[haiku-commits] r38594 - in haiku/trunk/src/apps/mediaplayer: . media_node_framework

  • From: superstippi@xxxxxx
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 9 Sep 2010 23:30:36 +0200 (CEST)

Author: stippi
Date: 2010-09-09 23:30:36 +0200 (Thu, 09 Sep 2010)
New Revision: 38594
Changeset: http://dev.haiku-os.org/changeset/38594
Ticket: http://dev.haiku-os.org/ticket/2495

Modified:
   haiku/trunk/src/apps/mediaplayer/Controller.cpp
   haiku/trunk/src/apps/mediaplayer/Controller.h
   haiku/trunk/src/apps/mediaplayer/ControllerObserver.cpp
   haiku/trunk/src/apps/mediaplayer/ControllerObserver.h
   haiku/trunk/src/apps/mediaplayer/MainWin.cpp
   haiku/trunk/src/apps/mediaplayer/MainWin.h
   haiku/trunk/src/apps/mediaplayer/media_node_framework/NodeManager.cpp
   haiku/trunk/src/apps/mediaplayer/media_node_framework/PlaybackManager.cpp
   haiku/trunk/src/apps/mediaplayer/media_node_framework/PlaybackManager.h
Log:
PlaybackManager:
 * Make sure that the messages which trigger a performance
   time update a) don't pever pile up and b) that we don't
   still receive an event after reinitialization (would
   not have been a problem, at one point I thought it was).
 * Don't compile in support for changing the playback speed
   for the moment.
 * Better support for notifying the reaching of a seek frame,
   In _UpdateStates(), the wrong state (most often out of bounds)
   was checked to be a seek request state. Check if a seek request
   was reached in all other cases where states are removed.

Controller:
 * Simple but important simplification of the problem that
   seeked frames are reached asynchronously and with a latency:
   In TimePosition() simply report the seeked frame, if there
   are still pending seek requests. This allows a consistent
   view from the outside, i.e. after calling SetTimePosition(),
   TimePosition() will not return something different.
 * Use a more robust way to track pending seek requests. A
   new request may have been issued while not having reached
   the previous one yet.
 * Implement a notification for reaching the seek frame, but
   I didn't need it after all, may come in handy later...

MainWin:
 * Change the cursor left/right keys to support winding.
   Cursor up/down change the volume, Cmd-up/down skips
   to the previous/next playlist item, left/right do the
   winding now, as requested in ticket #2495.


Modified: haiku/trunk/src/apps/mediaplayer/Controller.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/Controller.cpp     2010-09-09 19:55:09 UTC 
(rev 38593)
+++ haiku/trunk/src/apps/mediaplayer/Controller.cpp     2010-09-09 21:30:36 UTC 
(rev 38594)
@@ -77,6 +77,7 @@
 void Controller::Listener::AudioStatsChanged() {}
 void Controller::Listener::PlaybackStateChanged(uint32) {}
 void Controller::Listener::PositionChanged(float) {}
+void Controller::Listener::SeekHandled(int64 seekFrame) {}
 void Controller::Listener::VolumeChanged(float) {}
 void Controller::Listener::MutedChanged(bool) {}
 
@@ -108,11 +109,13 @@
        fAudioTrackList(4),
        fVideoTrackList(2),
 
-       fPosition(0),
+       fCurrentFrame(0),
        fDuration(0),
        fVideoFrameRate(25.0),
-       fSeekRequested(false),
 
+       fPendingSeekRequests(0),
+       fSeekFrame(-1),
+
        fGlobalSettingsListener(this),
 
        fListeners(4)
@@ -167,12 +170,7 @@
 int64
 Controller::Duration()
 {
-       // This should really be total frames (video frames at that)
-       // TODO: It is not so nice that the MediaPlayer still measures
-       // in video frames if only playing audio. Here for example, it will
-       // return a duration of 0 if the audio clip happens to be shorter than
-       // one video frame at 25 fps.
-       return (int64)((double)fDuration * fVideoFrameRate / 1000000.0);
+       return _FrameDuration();
 }
 
 
@@ -258,11 +256,12 @@
        fVideoTrackSupplier = NULL;
        fAudioTrackSupplier = NULL;
 
+       fCurrentFrame = 0;
        fDuration = 0;
        fVideoFrameRate = 25.0;
 
+       fPendingSeekRequests = 0;
        fSeekFrame = -1;
-       fSeekRequested = false;
 
        if (fItem.Get() == NULL)
                return B_BAD_VALUE;
@@ -641,7 +640,7 @@
 {
        BAutolock _(this);
 
-       return fPosition;
+       return _TimePosition();
 }
 
 
@@ -649,8 +648,7 @@
 Controller::SetVolume(float value)
 {
 //     printf("Controller::SetVolume %.4f\n", value);
-       if (!Lock())
-               return;
+       BAutolock _(this);
 
        value = max_c(0.0, min_c(2.0, value));
 
@@ -663,8 +661,6 @@
 
                _NotifyVolumeChanged(fVolume);
        }
-
-       Unlock();
 }
 
 void
@@ -684,8 +680,7 @@
 void
 Controller::ToggleMute()
 {
-       if (!Lock())
-               return;
+       BAutolock _(this);
 
        fMuted = !fMuted;
 
@@ -695,8 +690,6 @@
                fAudioSupplier->SetVolume(fVolume);
 
        _NotifyMutedChanged(fMuted);
-
-       Unlock();
 }
 
 
@@ -709,40 +702,50 @@
 }
 
 
-void
+int64
 Controller::SetPosition(float value)
 {
        BAutolock _(this);
 
-       SetFramePosition(Duration() * value);
+       return SetFramePosition(_FrameDuration() * value);
 }
 
 
-void
-Controller::SetFramePosition(int32 value)
+int64
+Controller::SetFramePosition(int64 value)
 {
        BAutolock _(this);
 
-       int64 seekFrame = max_c(0, min_c(Duration(), value));
-       int64 currentFrame = CurrentFrame();
+       fPendingSeekRequests++;
+       fSeekFrame = max_c(0, min_c(_FrameDuration(), value));
+
        // Snap to video keyframe, since that will be the fastest
        // to display and seeking will feel more snappy.
        if (Duration() > 240 && fVideoTrackSupplier != NULL)
-               fVideoTrackSupplier->FindKeyFrameForFrame(&seekFrame);
-       if (seekFrame != currentFrame) {
-               fSeekFrame = seekFrame;
-               fSeekRequested = true;
-               SetCurrentFrame(seekFrame);
-       }
+               fVideoTrackSupplier->FindKeyFrameForFrame(&fSeekFrame);
+
+       int64 currentFrame = CurrentFrame();
+//printf("SetFramePosition(%lld) -> %lld (current: %lld, duration: %lld) "
+//"(video: %p)\n", value, fSeekFrame, currentFrame, _FrameDuration(),
+//fVideoTrackSupplier);
+       if (fSeekFrame != currentFrame) {
+               int64 seekFrame = fSeekFrame;
+               SetCurrentFrame(fSeekFrame);
+                       // May trigger the notification and reset fSeekFrame,
+                       // if next current frame == seek frame.
+               return seekFrame;
+       } else
+               NotifySeekHandled(fSeekFrame);
+       return currentFrame;
 }
 
 
-void
+int64
 Controller::SetTimePosition(bigtime_t value)
 {
        BAutolock _(this);
 
-       SetPosition((float)value / TimeDuration());
+       return SetPosition((float)value / TimeDuration());
 }
 
 
@@ -924,6 +927,39 @@
 }
 
 
+bigtime_t
+Controller::_TimePosition() const
+{
+       if (fDuration == 0)
+               return 0;
+
+       // Check if we are still waiting to reach the seekframe,
+       // pass the last pending seek frame back to the caller, so
+       // that the view of the current frame/time from the outside
+       // does not depend on the internal latency to reach requested
+       // frames asynchronously.
+       int64 frame;
+       if (fPendingSeekRequests > 0)
+               frame = fSeekFrame;
+       else
+               frame = fCurrentFrame;
+
+       return frame * fDuration / _FrameDuration();
+}
+
+
+int64
+Controller::_FrameDuration() const
+{
+       // This should really be total frames (video frames at that)
+       // TODO: It is not so nice that the MediaPlayer still measures
+       // in video frames if only playing audio. Here for example, it will
+       // return a duration of 0 if the audio clip happens to be shorter than
+       // one video frame at 25 fps.
+       return (int64)((double)fDuration * fVideoFrameRate / 1000000.0);
+}
+
+
 // #pragma mark - Notifications
 
 
@@ -1024,6 +1060,18 @@
 
 
 void
+Controller::_NotifySeekHandled(int64 seekFrame) const
+{
+       BList listeners(fListeners);
+       int32 count = listeners.CountItems();
+       for (int32 i = 0; i < count; i++) {
+               Listener* listener = (Listener*)listeners.ItemAtFast(i);
+               listener->SeekHandled(seekFrame);
+       }
+}
+
+
+void
 Controller::_NotifyVolumeChanged(float volume) const
 {
        BList listeners(fListeners);
@@ -1084,20 +1132,8 @@
 void
 Controller::NotifyCurrentFrameChanged(int64 frame) const
 {
-       // check if we are still waiting to reach the seekframe,
-       // don't pass the event on to the listeners in that case
-       if (fSeekRequested && fSeekFrame != frame)
-               return;
-
-       fSeekFrame = -1;
-       fSeekRequested = false;
-
-       float position = 0.0;
-       double duration = (double)fDuration * fVideoFrameRate / 1000000.0;
-       if (duration > 0)
-               position = (float)frame / duration;
-       fPosition = (bigtime_t)(position * fDuration + 0.5);
-       _NotifyPositionChanged(position);
+       fCurrentFrame = frame;
+       _NotifyPositionChanged((float)_TimePosition() / fDuration);
 }
 
 
@@ -1124,9 +1160,15 @@
 
 
 void
-Controller::NotifySeekHandled() const
+Controller::NotifySeekHandled(int64 seekedFrame) const
 {
-       fSeekRequested = false;
-       fSeekFrame = -1;
+       if (fPendingSeekRequests == 0)
+               return;
+
+       fPendingSeekRequests--;
+       if (fPendingSeekRequests == 0)
+               fSeekFrame = -1;
+
+       _NotifySeekHandled(seekedFrame);
 }
 

Modified: haiku/trunk/src/apps/mediaplayer/Controller.h
===================================================================
--- haiku/trunk/src/apps/mediaplayer/Controller.h       2010-09-09 19:55:09 UTC 
(rev 38593)
+++ haiku/trunk/src/apps/mediaplayer/Controller.h       2010-09-09 21:30:36 UTC 
(rev 38594)
@@ -66,6 +66,7 @@
 
                virtual void                    PlaybackStateChanged(uint32 
state);
                virtual void                    PositionChanged(float position);
+               virtual void                    SeekHandled(int64 seekFrame);
                virtual void                    VolumeChanged(float volume);
                virtual void                    MutedChanged(bool muted);
        };
@@ -117,10 +118,11 @@
                        void                            VolumeUp();
                        void                            VolumeDown();
                        void                            ToggleMute();
-                       void                            SetPosition(float 
value);
-                       void                            SetFramePosition(int32 
frame);
-                       void                            
SetTimePosition(bigtime_t position);
 
+                       int64                           SetPosition(float 
value);
+                       int64                           SetFramePosition(int64 
frame);
+                       int64                           
SetTimePosition(bigtime_t position);
+
                        bool                            HasFile();
                        status_t                        GetFileFormatInfo(
                                                                        
media_file_format* fileFormat);
@@ -145,6 +147,8 @@
                        void                            _AdoptGlobalSettings();
 
                        uint32                          _PlaybackState(int32 
playingMode) const;
+                       int64                           _FrameDuration() const;
+                       bigtime_t                       _TimePosition() const;
 
                        void                            
_NotifyFileChanged(PlaylistItem* item,
                                                                        
status_t result) const;
@@ -157,6 +161,7 @@
 
                        void                            
_NotifyPlaybackStateChanged(uint32 state) const;
                        void                            
_NotifyPositionChanged(float position) const;
+                       void                            
_NotifySeekHandled(int64 seekFrame) const;
                        void                            
_NotifyVolumeChanged(float volume) const;
                        void                            
_NotifyMutedChanged(bool muted) const;
 
@@ -172,7 +177,7 @@
        virtual void                            NotifySpeedChanged(float speed) 
const;
        virtual void                            NotifyFrameDropped() const;
        virtual void                            NotifyStopFrameReached() const;
-       virtual void                            NotifySeekHandled() const;
+       virtual void                            NotifySeekHandled(int64 
seekedFrame) const;
 
 
                        VideoView*                      fVideoView;
@@ -191,12 +196,12 @@
                        BList                           fAudioTrackList;
                        BList                           fVideoTrackList;
 
-       mutable bigtime_t                       fPosition;
+       mutable int64                           fCurrentFrame;
                        bigtime_t                       fDuration;
                        float                           fVideoFrameRate;
 
-       mutable bool                            fSeekRequested;
-       mutable int32                           fSeekFrame;
+       mutable int32                           fPendingSeekRequests;
+       mutable int64                           fSeekFrame;
 
                        ListenerAdapter         fGlobalSettingsListener;
 

Modified: haiku/trunk/src/apps/mediaplayer/ControllerObserver.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/ControllerObserver.cpp     2010-09-09 
19:55:09 UTC (rev 38593)
+++ haiku/trunk/src/apps/mediaplayer/ControllerObserver.cpp     2010-09-09 
21:30:36 UTC (rev 38594)
@@ -134,6 +134,19 @@
 
 
 void
+ControllerObserver::SeekHandled(int64 seekFrame)
+{
+       if (!(fObserveFlags & OBSERVE_POSITION_CHANGES))
+               return;
+
+       BMessage message(MSG_CONTROLLER_SEEK_HANDLED);
+       message.AddInt64("seek frame", seekFrame);
+
+       DeliverMessage(message);
+}
+
+
+void
 ControllerObserver::VolumeChanged(float volume)
 {
        if (!(fObserveFlags & OBSERVE_VOLUME_CHANGES))

Modified: haiku/trunk/src/apps/mediaplayer/ControllerObserver.h
===================================================================
--- haiku/trunk/src/apps/mediaplayer/ControllerObserver.h       2010-09-09 
19:55:09 UTC (rev 38593)
+++ haiku/trunk/src/apps/mediaplayer/ControllerObserver.h       2010-09-09 
21:30:36 UTC (rev 38594)
@@ -25,6 +25,7 @@
 
        MSG_CONTROLLER_PLAYBACK_STATE_CHANGED   = 'cnps',
        MSG_CONTROLLER_POSITION_CHANGED                 = 'cnpc',
+       MSG_CONTROLLER_SEEK_HANDLED                             = 'cnsh',
        MSG_CONTROLLER_VOLUME_CHANGED                   = 'cnvc',
        MSG_CONTROLLER_MUTED_CHANGED                    = 'cnmc'
 };
@@ -60,6 +61,7 @@
 
        virtual void            PlaybackStateChanged(uint32 state);
        virtual void            PositionChanged(float position);
+       virtual void            SeekHandled(int64 seekFrame);
        virtual void            VolumeChanged(float volume);
        virtual void            MutedChanged(bool muted);
 

Modified: haiku/trunk/src/apps/mediaplayer/MainWin.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/MainWin.cpp        2010-09-09 19:55:09 UTC 
(rev 38593)
+++ haiku/trunk/src/apps/mediaplayer/MainWin.cpp        2010-09-09 21:30:36 UTC 
(rev 38594)
@@ -81,6 +81,7 @@
        M_VOLUME_DOWN,
        M_SKIP_NEXT,
        M_SKIP_PREV,
+       M_WIND,
 
        // The common display aspect ratios
        M_ASPECT_SAME_AS_SOURCE,
@@ -179,7 +180,8 @@
        fMouseMoveDist(0),
 
        fGlobalSettingsListener(this),
-       fInitialSeekPosition(0)
+       fInitialSeekPosition(0),
+       fAllowWinding(true)
 {
        // Handle window position and size depending on whether this is the
        // first window or not. Use the window size from the window that was
@@ -675,9 +677,13 @@
                        if (msg->FindFloat("position", &position) == B_OK) {
                                fControls->SetPosition(position, 
fController->TimePosition(),
                                        fController->TimeDuration());
+                               fAllowWinding = true;
                        }
                        break;
                }
+               case MSG_CONTROLLER_SEEK_HANDLED:
+                       break;
+
                case MSG_CONTROLLER_VOLUME_CHANGED:
                {
                        float volume;
@@ -782,6 +788,32 @@
                        fControls->SkipBackward();
                        break;
 
+               case M_WIND:
+               {
+                       if (!fAllowWinding)
+                               break;
+
+                       bigtime_t howMuch;
+                       if (msg->FindInt64("how much", &howMuch) != B_OK)
+                               break;
+
+                       if (fController->Lock()) {
+                               bigtime_t seekTime = 
fController->TimePosition() + howMuch;
+                               if (seekTime < 0) {
+                                       fInitialSeekPosition = seekTime;
+                                       PostMessage(M_SKIP_PREV);
+                               } else if (seekTime > 
fController->TimeDuration()) {
+                                       fInitialSeekPosition = 0;
+                                       PostMessage(M_SKIP_NEXT);
+                               } else
+                                       fController->SetTimePosition(seekTime);
+                               fController->Unlock();
+
+                               fAllowWinding = false;
+                       }
+                       break;
+               }
+
                case M_VOLUME_UP:
                        fController->VolumeUp();
                        break;
@@ -1248,6 +1280,10 @@
                fHasAudio = fController->AudioTrackCount() != 0;
                SetTitle(item->Name().String());
 
+               if (fInitialSeekPosition < 0) {
+                       fInitialSeekPosition
+                               = fController->TimeDuration() + 
fInitialSeekPosition;
+               }
                fController->SetTimePosition(fInitialSeekPosition);
                fInitialSeekPosition = 0;
        }
@@ -1401,7 +1437,7 @@
                new BMessage(M_TOGGLE_NO_INTERFACE), 'B');
        fSettingsMenu->AddItem(fNoInterfaceMenuItem);
        fSettingsMenu->AddItem(new BMenuItem("Always on top",
-               new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'T'));
+               new BMessage(M_TOGGLE_ALWAYS_ON_TOP), 'A'));
        fSettingsMenu->AddSeparatorItem();
        item = new BMenuItem("Settings"B_UTF8_ELLIPSIS,
                new BMessage(M_SETTINGS), 'S');
@@ -1872,8 +1908,8 @@
        uint32 rawChar = msg->FindInt32("raw_char");
        uint32 modifier = msg->FindInt32("modifiers");
 
-       printf("key 0x%lx, rawChar 0x%lx, modifiers 0x%lx\n", key, rawChar,
-               modifier);
+//     printf("key 0x%lx, rawChar 0x%lx, modifiers 0x%lx\n", key, rawChar,
+//             modifier);
 
        // ignore the system modifier namespace
        if ((modifier & (B_CONTROL_KEY | B_COMMAND_KEY))
@@ -1923,16 +1959,28 @@
 
                case B_RIGHT_ARROW:
                        if ((modifier & B_COMMAND_KEY) != 0)
-                               PostMessage(M_VOLUME_UP);
-                       else
                                PostMessage(M_SKIP_NEXT);
+                       else if (fAllowWinding) {
+                               BMessage windMessage(M_WIND);
+                               if ((modifier & B_SHIFT_KEY) != 0)
+                                       windMessage.AddInt64("how much", 
30000000LL);
+                               else
+                                       windMessage.AddInt64("how much", 
5000000LL);
+                               PostMessage(&windMessage);
+                       }
                        return true;
 
                case B_LEFT_ARROW:
                        if ((modifier & B_COMMAND_KEY) != 0)
-                               PostMessage(M_VOLUME_DOWN);
-                       else
                                PostMessage(M_SKIP_PREV);
+                       else if (fAllowWinding) {
+                               BMessage windMessage(M_WIND);
+                               if ((modifier & B_SHIFT_KEY) != 0)
+                                       windMessage.AddInt64("how much", 
-30000000LL);
+                               else
+                                       windMessage.AddInt64("how much", 
-5000000LL);
+                               PostMessage(&windMessage);
+                       }
                        return true;
 
                case B_PAGE_UP:
@@ -1942,6 +1990,19 @@
                case B_PAGE_DOWN:
                        PostMessage(M_SKIP_PREV);
                        return true;
+
+               case B_DELETE:
+               case 'd':                       // d for delete
+               case 't':                       // t for Trash
+                       if ((modifiers() & B_COMMAND_KEY) != 0) {
+                               BAutolock _(fPlaylist);
+                               BMessage 
removeMessage(M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH);
+                               removeMessage.AddInt32("playlist index",
+                                       fPlaylist->CurrentItemIndex());
+                               fPlaylistWindow->PostMessage(&removeMessage);
+                               return true;
+                       }
+                       break;
        }
 
        switch (key) {
@@ -1976,19 +2037,6 @@
                case 0x48:                      // numeric keypad left arrow
                        PostMessage(M_SKIP_PREV);
                        return true;
-
-               case 0x34:                      // delete button
-               case 0x3e:                      // d for delete
-               case 0x2b:                      // t for Trash
-                       if ((modifiers() & B_COMMAND_KEY) != 0) {
-                               BAutolock _(fPlaylist);
-                               BMessage 
removeMessage(M_PLAYLIST_REMOVE_AND_PUT_INTO_TRASH);
-                               removeMessage.AddInt32("playlist index",
-                                       fPlaylist->CurrentItemIndex());
-                               fPlaylistWindow->PostMessage(&removeMessage);
-                               return true;
-                       }
-                       break;
        }
 
        return false;

Modified: haiku/trunk/src/apps/mediaplayer/MainWin.h
===================================================================
--- haiku/trunk/src/apps/mediaplayer/MainWin.h  2010-09-09 19:55:09 UTC (rev 
38593)
+++ haiku/trunk/src/apps/mediaplayer/MainWin.h  2010-09-09 21:30:36 UTC (rev 
38594)
@@ -189,6 +189,7 @@
                        bool                            fLoopMovies;
                        bool                            fLoopSounds;
                        bigtime_t                       fInitialSeekPosition;
+                       bool                            fAllowWinding;
 
        static  int                                     sNoVideoWidth;
 };

Modified: haiku/trunk/src/apps/mediaplayer/media_node_framework/NodeManager.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/media_node_framework/NodeManager.cpp       
2010-09-09 19:55:09 UTC (rev 38593)
+++ haiku/trunk/src/apps/mediaplayer/media_node_framework/NodeManager.cpp       
2010-09-09 21:30:36 UTC (rev 38594)
@@ -83,7 +83,8 @@
        float speed, uint32 enabledNodes, bool useOverlays)
 {
        // init base class
-       PlaybackManager::Init(videoFrameRate, loopingMode, loopingEnabled, 
speed);
+       PlaybackManager::Init(videoFrameRate, true, loopingMode, loopingEnabled,
+               speed);
 
        // get some objects from a derived class
        if (fVideoTarget == NULL)
@@ -142,15 +143,18 @@
                // TODO: if enabledNodes would indicate that audio or video
                // is no longer needed, or, worse yet, suddenly needed when
                // it wasn't before, then we should not return here!
+               PlaybackManager::Init(videoFrameRate, false, LoopMode(),
+                       IsLoopingEnabled(), Speed(), 
MODE_PLAYING_PAUSED_FORWARD,
+                       CurrentFrame());
                return B_OK;
        }
 
-       PlaybackManager::Init(videoFrameRate, LoopMode(), IsLoopingEnabled(),
-               Speed(), MODE_PLAYING_PAUSED_FORWARD, CurrentFrame());
-
        _StopNodes();
        _TearDownNodes();
 
+       PlaybackManager::Init(videoFrameRate, true, LoopMode(), 
IsLoopingEnabled(),
+               Speed(), MODE_PLAYING_PAUSED_FORWARD, CurrentFrame());
+
        SetVideoBounds(videoBounds);
 
        status_t ret = _SetUpNodes(preferredVideoFormat, enabledNodes,

Modified: 
haiku/trunk/src/apps/mediaplayer/media_node_framework/PlaybackManager.cpp
===================================================================
--- haiku/trunk/src/apps/mediaplayer/media_node_framework/PlaybackManager.cpp   
2010-09-09 19:55:09 UTC (rev 38593)
+++ haiku/trunk/src/apps/mediaplayer/media_node_framework/PlaybackManager.cpp   
2010-09-09 21:30:36 UTC (rev 38594)
@@ -36,6 +36,9 @@
 }
 
 
+#define SUPPORT_SPEED_CHANGES 0
+
+
 struct PlaybackManager::PlayingState {
        int64           start_frame;
        int64           end_frame;
@@ -75,6 +78,7 @@
 };
 
 
+#if SUPPORT_SPEED_CHANGES
 struct PlaybackManager::SpeedInfo {
        int64           activation_frame;               // absolute video frame
        bigtime_t       activation_time;                // performance time
@@ -82,22 +86,25 @@
                                                                                
// is 1.0 if not playing
        float           set_speed;                              // speed set by 
the user
 };
+#endif
 
 
 // #pragma mark - PlaybackManager
 
 
 PlaybackManager::PlaybackManager()
-       : BLooper("playback manager"),
-         fStates(10),
-         fSpeeds(10),
-         fCurrentAudioTime(0),
-         fCurrentVideoTime(0),
-         fPerformanceTime(0),
-         fFrameRate(1.0),
-         fStopPlayingFrame(-1),
-         fListeners(),
-         fNoAudio(false)
+       :
+       BLooper("playback manager"),
+       fStates(10),
+       fSpeeds(10),
+       fCurrentAudioTime(0),
+       fCurrentVideoTime(0),
+       fPerformanceTime(0),
+       fPerformanceTimeEvent(NULL),
+       fFrameRate(1.0),
+       fStopPlayingFrame(-1),
+       fListeners(),
+       fNoAudio(false)
 {
        Run();
 }
@@ -110,19 +117,23 @@
 
 
 void
-PlaybackManager::Init(float frameRate, int32 loopingMode, bool loopingEnabled,
-       float playbackSpeed, int32 playMode, int32 currentFrame)
+PlaybackManager::Init(float frameRate, bool initPerformanceTimes,
+       int32 loopingMode, bool loopingEnabled, float playbackSpeed,
+       int32 playMode, int32 currentFrame)
 {
        // cleanup first
        Cleanup();
 
        // set the new frame rate
        fFrameRate = frameRate;
-       fCurrentAudioTime = 0;
-       fCurrentVideoTime = 0;
-       fPerformanceTime = 0;
+       if (initPerformanceTimes) {
+               fCurrentAudioTime = 0;
+               fCurrentVideoTime = 0;
+               fPerformanceTime = 0;
+       }
        fStopPlayingFrame = -1;
 
+#if SUPPORT_SPEED_CHANGES
        // set up the initial speed
        SpeedInfo* speed = new SpeedInfo;
        speed->activation_frame = 0;
@@ -130,6 +141,7 @@
        speed->speed = playbackSpeed;
        speed->set_speed = playbackSpeed;
        _PushSpeedInfo(speed);
+#endif
 
        // set up the initial state
        PlayingState* state = new PlayingState;
@@ -165,15 +177,20 @@
 void
 PlaybackManager::Cleanup()
 {
+       if (EventQueue::Default().RemoveEvent(fPerformanceTimeEvent))
+               delete fPerformanceTimeEvent;
+       fPerformanceTimeEvent = NULL;
        // delete states
        for (int32 i = 0; PlayingState* state = _StateAt(i); i++)
                delete state;
        fStates.MakeEmpty();
 
+#if SUPPORT_SPEED_CHANGES
        // delete speed infos
        for (int32 i = 0; SpeedInfo* speed = _SpeedInfoAt(i); i++)
                delete speed;
        fSpeeds.MakeEmpty();
+#endif
 }
 
 
@@ -182,9 +199,25 @@
 {
        switch (message->what) {
                case MSG_EVENT:
-                       SetPerformanceTime(TimeForRealTime(system_time()));
-//TRACE("MSG_EVENT: rt: %lld, pt: %lld\n", system_time(), fPerformanceTime);
+               {
+                       if (fPerformanceTimeEvent == NULL) {
+                               // Stale event message. There is a natural race
+                               // condition when removing the event from the 
queue,
+                               // it may have already fired, but we have not 
processed
+                               // the message yet. Simply ignore the event.
+                               break;
+                       }
+
+//                     bigtime_t eventTime;
+//                     message->FindInt64("time", &eventTime);
+                       bigtime_t now = system_time();
+                       fPerformanceTimeEvent = NULL;
+
+                       SetPerformanceTime(TimeForRealTime(now));
+//TRACE("MSG_EVENT: rt: %lld, pt: %lld\n", now, fPerformanceTime);
+//printf("MSG_EVENT: et: %lld, rt: %lld, pt: %lld\n", eventTime, now, 
fPerformanceTime);
                        break;
+               }
 
                case MSG_PLAYBACK_FORCE_UPDATE:
                {
@@ -333,9 +366,13 @@
 float
 PlaybackManager::Speed() const
 {
+#if SUPPORT_SPEED_CHANGES
        if (!_LastState())
                return 1.0;
        return _LastSpeedInfo()->set_speed;
+#else
+       return 1.0;
+#endif
 }
 
 
@@ -384,8 +421,8 @@
 void
 PlaybackManager::SetCurrentFrame(int64 frame)
 {
-       if (_LastState()->current_frame == frame) {
-               NotifySeekHandled();
+       if (CurrentFrame() == frame) {
+               NotifySeekHandled(frame);
                return;
        }
        PlayingState* newState = new PlayingState(*_LastState());
@@ -465,6 +502,7 @@
 void
 PlaybackManager::SetSpeed(float speed)
 {
+#if SUPPORT_SPEED_CHANGES
        SpeedInfo* lastSpeed = _LastSpeedInfo();
        if (speed != lastSpeed->set_speed) {
                SpeedInfo* info = new SpeedInfo(*lastSpeed);
@@ -476,6 +514,7 @@
                        info->speed = 1.0;
                _PushSpeedInfo(info);
        }
+#endif
 }
 
 
@@ -676,10 +715,12 @@
        int32 endIndex = _IndexForFrame(endFrame);
        if (startIndex < endIndex)
                endFrame = _StateAt(startIndex + 1)->activation_frame;
+#if SUPPORT_SPEED_CHANGES
        startIndex = _SpeedInfoIndexForFrame(startFrame);
        endIndex = _SpeedInfoIndexForFrame(endFrame);
        if (startIndex < endIndex)
                endFrame = _SpeedInfoAt(startIndex + 1)->activation_frame;
+#endif
        return endFrame;
 }
 
@@ -693,10 +734,12 @@
        int32 endIndex = _IndexForTime(endTime);
        if (startIndex < endIndex)
                endTime = TimeForFrame(_StateAt(startIndex + 
1)->activation_frame);
+#if SUPPORT_SPEED_CHANGES
        startIndex = _SpeedInfoIndexForTime(startTime);
        endIndex = _SpeedInfoIndexForTime(endTime);
        if (startIndex < endIndex)
                endTime = TimeForFrame(_SpeedInfoAt(startIndex + 
1)->activation_frame);
+#endif
        return endTime;
 }
 
@@ -751,7 +794,9 @@
        // be greater than necessary, but that doesn't harm.
        int64 startFrame = FrameForTime(startTime);
        int64 endFrame = FrameForTime(endTime) + 1;
-       SpeedInfo* info = _SpeedInfoForFrame(startFrame);
+#if SUPPORT_SPEED_CHANGES
+       SpeedInfo* info = _SpeedInfoForFrame(startFrame)->speed;
+#endif
        // Get the Playlist frame interval that belongs to the frame interval.
        int64 xStartFrame;
        int64 xEndFrame;
@@ -769,33 +814,37 @@
                // forward
                case 1:
                {
-//                     xStartTime = PlaylistTimeForFrame(xStartFrame)
-//                                              + startTime - 
TimeForFrame(startFrame);
-//                     xEndTime = xStartTime + intervalLength;
-
+#if SUPPORT_SPEED_CHANGES
 // TODO: The current method does not handle the times the same way.
 //       It may happen, that for the same performance time different
 //       Playlist times (within a frame) are returned when passing it
 //       one time as a start time and another time as an end time.
                        xStartTime = PlaylistTimeForFrame(xStartFrame)
                                + bigtime_t(double(startTime - 
TimeForFrame(startFrame))
-                                                       * info->speed);
+                                       * info->speed);
                        xEndTime = xStartTime
-                                          + bigtime_t((double)intervalLength * 
info->speed);
+                               + bigtime_t((double)intervalLength * 
info->speed);
+#else
+                       xStartTime = PlaylistTimeForFrame(xStartFrame)
+                               + startTime - TimeForFrame(startFrame);
+                       xEndTime = xStartTime + intervalLength;
+#endif
                        break;
                }
                // backward
                case -1:
                {
-//                     xEndTime = PlaylistTimeForFrame(xEndFrame)
-//                                        - startTime + 
TimeForFrame(startFrame);
-//                     xStartTime = xEndTime - intervalLength;
-
+#if SUPPORT_SPEED_CHANGES
                        xEndTime = PlaylistTimeForFrame(xEndFrame)
                                - bigtime_t(double(startTime - 
TimeForFrame(startFrame))
-                                                       * info->speed);
+                                       * info->speed);
                        xStartTime = xEndTime
-                                          - bigtime_t((double)intervalLength * 
info->speed);
+                               - bigtime_t((double)intervalLength * 
info->speed);
+#else
+                       xEndTime = PlaylistTimeForFrame(xEndFrame)
+                               - startTime + TimeForFrame(startFrame);
+                       xStartTime = xEndTime - intervalLength;
+#endif
                        break;
                }
                // not playing
@@ -805,7 +854,11 @@
                        xEndTime = xStartTime;
                        break;
        }
+#if SUPPORT_SPEED_CHANGES
        playingSpeed = (float)playingDirection * info->speed;
+#else
+       playingSpeed = (float)playingDirection;
+#endif
 }
 
 
@@ -815,11 +868,10 @@
 PlaybackManager::FrameForTime(bigtime_t time) const
 {
 //TRACE("PlaybackManager::FrameForTime(%lld)\n", time);
-//     return (int64)((double)time * (double)fFrameRate / 1000000.0);
        // In order to avoid problems caused by rounding errors, we check
        // if for the resulting frame holds
        // TimeForFrame(frame) <= time < TimeForFrame(frame + 1).
-//     int64 frame = (int64)((double)time * (double)fFrameRate / 1000000.0);
+#if SUPPORT_SPEED_CHANGES
        SpeedInfo* info = _SpeedInfoForTime(time);
 if (!info) {
        fprintf(stderr, "PlaybackManager::FrameForTime() - no SpeedInfo!\n");
@@ -828,6 +880,10 @@
        int64 frame = (int64)(((double)time - info->activation_time)
                * (double)fFrameRate * info->speed / 1000000.0)
                + info->activation_frame;
+
+#else
+       int64 frame = (int64)((double)time * (double)fFrameRate / 1000000.0);
+#endif
        if (TimeForFrame(frame) > time)
                frame--;
        else if (TimeForFrame(frame + 1) <= time)
@@ -843,19 +899,18 @@
 bigtime_t
 PlaybackManager::TimeForFrame(int64 frame) const
 {
-//     return (bigtime_t)((double)frame * 1000000.0 / (double)fFrameRate);
+#if SUPPORT_SPEED_CHANGES
        SpeedInfo* info = _SpeedInfoForFrame(frame);
 if (!info) {
        fprintf(stderr, "PlaybackManager::TimeForFrame() - no SpeedInfo!\n");
        return 0;
 }
-//     return (bigtime_t)((double)(frame - info->activation_frame) * 1000000.0
-//                                        / ((double)fFrameRate * info->speed))
-//                + info->activation_time;
-bigtime_t result = (bigtime_t)((double)(frame - info->activation_frame) * 
1000000.0
-/ ((double)fFrameRate * info->speed)) + info->activation_time;
-//fprintf(stderr, "PlaybackManager::TimeForFrame(%lld): %lld\n", frame, 
result);
-return result;
+       return (bigtime_t)((double)(frame - info->activation_frame) * 1000000.0
+                                          / ((double)fFrameRate * info->speed))
+                  + info->activation_time;
+#else
+       return (bigtime_t)((double)frame * 1000000.0 / (double)fFrameRate);
+#endif
 }
 
 
@@ -892,11 +947,13 @@
 TRACE("PlaybackManager::SetCurrentAudioTime(%lld)\n", time);
        bigtime_t lastFrameTime = _TimeForLastFrame();
        fCurrentAudioTime = time;
-//     _UpdateStates();
        bigtime_t newLastFrameTime = _TimeForLastFrame();
        if (lastFrameTime != newLastFrameTime) {
-               bigtime_t eventTime = RealTimeForTime(newLastFrameTime);
-               EventQueue::Default().AddEvent(new MessageEvent(eventTime, 
this));
+               if (fPerformanceTimeEvent == NULL) {
+                       bigtime_t eventTime = RealTimeForTime(newLastFrameTime);
+                       fPerformanceTimeEvent = new MessageEvent(eventTime, 
this);
+                       EventQueue::Default().AddEvent(fPerformanceTimeEvent);
+               }
                _CheckStopPlaying();
        }
 }
@@ -917,11 +974,13 @@
 TRACE("PlaybackManager::SetCurrentVideoTime(%lld)\n", time);
        bigtime_t lastFrameTime = _TimeForLastFrame();
        fCurrentVideoTime = time;
-//     _UpdateStates();
        bigtime_t newLastFrameTime = _TimeForLastFrame();
        if (lastFrameTime != newLastFrameTime) {
-               bigtime_t eventTime = RealTimeForTime(newLastFrameTime);
-               EventQueue::Default().AddEvent(new MessageEvent(eventTime, 
this));
+               if (fPerformanceTimeEvent == NULL) {
+                       bigtime_t eventTime = RealTimeForTime(newLastFrameTime);
+                       fPerformanceTimeEvent = new MessageEvent(eventTime, 
this);
+                       EventQueue::Default().AddEvent(fPerformanceTimeEvent);
+               }
                _CheckStopPlaying();
        }
 }
@@ -931,11 +990,11 @@
 void
 PlaybackManager::SetPerformanceFrame(int64 frame)
 {
-       SetPerformanceFrame(TimeForFrame(frame));
+       SetPerformanceTime(TimeForFrame(frame));
 }
 
 
-/*!    Similar to SetPerformanceTime() just with a time instead of a frame
+/*!    Similar to SetPerformanceFrame() just with a time instead of a frame
        argument. */
 void
 PlaybackManager::SetPerformanceTime(bigtime_t time)
@@ -1089,7 +1148,7 @@
 
 
 void
-PlaybackManager::NotifySeekHandled() const
+PlaybackManager::NotifySeekHandled(int64 frame) const
 {

[... truncated: 262 lines follow ...]

Other related posts:

  • » [haiku-commits] r38594 - in haiku/trunk/src/apps/mediaplayer: . media_node_framework - superstippi