10fc56ed5SStephan Aßmus /* 20fc56ed5SStephan Aßmus * Copyright (c) 2000-2008, Ingo Weinhold <ingo_weinhold@gmx.de>, 30fc56ed5SStephan Aßmus * Copyright (c) 2000-2008, Stephan Aßmus <superstippi@gmx.de>, 40fc56ed5SStephan Aßmus * All Rights Reserved. Distributed under the terms of the MIT license. 50fc56ed5SStephan Aßmus */ 60fc56ed5SStephan Aßmus 70fc56ed5SStephan Aßmus /*! This class controls our playback 80fc56ed5SStephan Aßmus Note: Add/RemoveListener() are the only methods that lock the object 90fc56ed5SStephan Aßmus themselves. All other methods need it to be locked before. 100fc56ed5SStephan Aßmus */ 110fc56ed5SStephan Aßmus #ifndef PLAYBACK_MANAGER_H 120fc56ed5SStephan Aßmus #define PLAYBACK_MANAGER_H 130fc56ed5SStephan Aßmus 140fc56ed5SStephan Aßmus 150fc56ed5SStephan Aßmus #include <List.h> 160fc56ed5SStephan Aßmus #include <Looper.h> 170fc56ed5SStephan Aßmus #include <Rect.h> 180fc56ed5SStephan Aßmus 190fc56ed5SStephan Aßmus 20*0beac2ffSStephan Aßmus class MessageEvent; 210fc56ed5SStephan Aßmus class PlaybackListener; 220fc56ed5SStephan Aßmus 230fc56ed5SStephan Aßmus 240fc56ed5SStephan Aßmus enum { 250fc56ed5SStephan Aßmus MODE_PLAYING_FORWARD = 1, 260fc56ed5SStephan Aßmus MODE_PLAYING_BACKWARD = 2, 270fc56ed5SStephan Aßmus MODE_PLAYING_PAUSED_FORWARD = -1, 280fc56ed5SStephan Aßmus MODE_PLAYING_PAUSED_BACKWARD = -2, 290fc56ed5SStephan Aßmus }; 300fc56ed5SStephan Aßmus 310fc56ed5SStephan Aßmus enum { 320fc56ed5SStephan Aßmus LOOPING_ALL = 0, 330fc56ed5SStephan Aßmus LOOPING_RANGE = 1, 340fc56ed5SStephan Aßmus LOOPING_SELECTION = 2, 350fc56ed5SStephan Aßmus LOOPING_VISIBLE = 3, 360fc56ed5SStephan Aßmus }; 370fc56ed5SStephan Aßmus 380fc56ed5SStephan Aßmus enum { 390fc56ed5SStephan Aßmus MSG_PLAYBACK_FORCE_UPDATE = 'pbfu', 400fc56ed5SStephan Aßmus MSG_PLAYBACK_SET_RANGE = 'pbsr', 410fc56ed5SStephan Aßmus MSG_PLAYBACK_SET_VISIBLE = 'pbsv', 420fc56ed5SStephan Aßmus MSG_PLAYBACK_SET_LOOP_MODE = 'pbsl', 430fc56ed5SStephan Aßmus }; 440fc56ed5SStephan Aßmus 450fc56ed5SStephan Aßmus 460fc56ed5SStephan Aßmus class PlaybackManager : public BLooper { 470fc56ed5SStephan Aßmus private: 480fc56ed5SStephan Aßmus struct PlayingState; 490fc56ed5SStephan Aßmus struct SpeedInfo; 500fc56ed5SStephan Aßmus 510fc56ed5SStephan Aßmus public: 520fc56ed5SStephan Aßmus PlaybackManager(); 530fc56ed5SStephan Aßmus virtual ~PlaybackManager(); 540fc56ed5SStephan Aßmus 550fc56ed5SStephan Aßmus void Init(float frameRate, 56*0beac2ffSStephan Aßmus bool initPerformanceTimes, 570fc56ed5SStephan Aßmus int32 loopingMode = LOOPING_ALL, 580fc56ed5SStephan Aßmus bool loopingEnabled = true, 590fc56ed5SStephan Aßmus float speed = 1.0, 60*0beac2ffSStephan Aßmus int32 playMode 61*0beac2ffSStephan Aßmus = MODE_PLAYING_PAUSED_FORWARD, 620fc56ed5SStephan Aßmus int32 currentFrame = 0); 630fc56ed5SStephan Aßmus void Cleanup(); 640fc56ed5SStephan Aßmus 650fc56ed5SStephan Aßmus // BHandler interface 660fc56ed5SStephan Aßmus virtual void MessageReceived(BMessage* message); 670fc56ed5SStephan Aßmus 680fc56ed5SStephan Aßmus void StartPlaying(bool atBeginning = false); 690fc56ed5SStephan Aßmus void StopPlaying(); 700fc56ed5SStephan Aßmus void TogglePlaying(bool atBeginning = false); 710fc56ed5SStephan Aßmus void PausePlaying(); 720fc56ed5SStephan Aßmus bool IsPlaying() const; 730fc56ed5SStephan Aßmus 740fc56ed5SStephan Aßmus int32 PlayMode() const; 750fc56ed5SStephan Aßmus int32 LoopMode() const; 760fc56ed5SStephan Aßmus bool IsLoopingEnabled() const; 77818577b2SStephan Aßmus int64 CurrentFrame() const; 780fc56ed5SStephan Aßmus float Speed() const; 790fc56ed5SStephan Aßmus 800fc56ed5SStephan Aßmus virtual void SetFramesPerSecond(float framesPerSecond); 810fc56ed5SStephan Aßmus float FramesPerSecond() const; 820fc56ed5SStephan Aßmus 830fc56ed5SStephan Aßmus virtual BRect VideoBounds() const = 0; 840fc56ed5SStephan Aßmus 850fc56ed5SStephan Aßmus virtual void FrameDropped() const; 860fc56ed5SStephan Aßmus 870fc56ed5SStephan Aßmus void DurationChanged(); 880fc56ed5SStephan Aßmus virtual int64 Duration() = 0; 890fc56ed5SStephan Aßmus 900fc56ed5SStephan Aßmus virtual void SetVolume(float percent) = 0; 910fc56ed5SStephan Aßmus 920fc56ed5SStephan Aßmus // playing state manipulation 930fc56ed5SStephan Aßmus void SetCurrentFrame(int64 frame); 940fc56ed5SStephan Aßmus virtual void SetPlayMode(int32 mode, 950fc56ed5SStephan Aßmus bool continuePlaying = true); 960fc56ed5SStephan Aßmus void SetLoopMode(int32 mode, 970fc56ed5SStephan Aßmus bool continuePlaying = true); 980fc56ed5SStephan Aßmus void SetLoopingEnabled(bool enabled, 990fc56ed5SStephan Aßmus bool continuePlaying = true); 1000fc56ed5SStephan Aßmus void SetSpeed(float speed); 1010fc56ed5SStephan Aßmus 1020fc56ed5SStephan Aßmus // playing state change info 1030fc56ed5SStephan Aßmus int64 NextFrame() const; 1040fc56ed5SStephan Aßmus int64 NextPlaylistFrame() const; 1050fc56ed5SStephan Aßmus 1060fc56ed5SStephan Aßmus int64 FirstPlaybackRangeFrame(); 1070fc56ed5SStephan Aßmus int64 LastPlaybackRangeFrame(); 1080fc56ed5SStephan Aßmus 1090fc56ed5SStephan Aßmus // playing state access 1100fc56ed5SStephan Aßmus int64 StartFrameAtFrame(int64 frame); 1110fc56ed5SStephan Aßmus int64 StartFrameAtTime(bigtime_t time); 1120fc56ed5SStephan Aßmus int64 EndFrameAtFrame(int64 frame); 1130fc56ed5SStephan Aßmus int64 EndFrameAtTime(bigtime_t time); 1140fc56ed5SStephan Aßmus int64 FrameCountAtFrame(int64 frame); 1150fc56ed5SStephan Aßmus int64 FrameCountAtTime(bigtime_t time); 1160fc56ed5SStephan Aßmus int32 PlayModeAtFrame(int64 frame); 1170fc56ed5SStephan Aßmus int32 PlayModeAtTime(bigtime_t time); 1180fc56ed5SStephan Aßmus int32 LoopModeAtFrame(int64 frame); 1190fc56ed5SStephan Aßmus int32 LoopModeAtTime(bigtime_t time); 1200fc56ed5SStephan Aßmus // ... 1210fc56ed5SStephan Aßmus 1220fc56ed5SStephan Aßmus // playing frame/time/interval info 1230fc56ed5SStephan Aßmus int64 PlaylistFrameAtFrame(int64 frame, 1240fc56ed5SStephan Aßmus int32& playingDirection, 1250fc56ed5SStephan Aßmus bool& newState) const; 1260fc56ed5SStephan Aßmus int64 PlaylistFrameAtFrame(int64 frame, 1270fc56ed5SStephan Aßmus int32& playingDirection) const; 1280fc56ed5SStephan Aßmus int64 PlaylistFrameAtFrame(int64 frame) const; 1290fc56ed5SStephan Aßmus int64 NextChangeFrame(int64 startFrame, 1300fc56ed5SStephan Aßmus int64 endFrame) const; 1310fc56ed5SStephan Aßmus bigtime_t NextChangeTime(bigtime_t startTime, 1320fc56ed5SStephan Aßmus bigtime_t endTime) const; 1330fc56ed5SStephan Aßmus void GetPlaylistFrameInterval( 1340fc56ed5SStephan Aßmus int64 startFrame, int64& endFrame, 1350fc56ed5SStephan Aßmus int64& xStartFrame, int64& xEndFrame, 1360fc56ed5SStephan Aßmus int32& playingDirection) const; 1370fc56ed5SStephan Aßmus 1380fc56ed5SStephan Aßmus virtual void GetPlaylistTimeInterval( 1390fc56ed5SStephan Aßmus bigtime_t startTime, bigtime_t& endTime, 1400fc56ed5SStephan Aßmus bigtime_t& xStartTime, bigtime_t& xEndTime, 1410fc56ed5SStephan Aßmus float& playingSpeed) const; 1420fc56ed5SStephan Aßmus 1430fc56ed5SStephan Aßmus // conversion: video frame <-> (performance) time 1440fc56ed5SStephan Aßmus int64 FrameForTime(bigtime_t time) const; 1450fc56ed5SStephan Aßmus bigtime_t TimeForFrame(int64 frame) const; 1460fc56ed5SStephan Aßmus // conversion: (performance) time <-> real time 1470fc56ed5SStephan Aßmus virtual bigtime_t RealTimeForTime(bigtime_t time) const = 0; 1480fc56ed5SStephan Aßmus virtual bigtime_t TimeForRealTime(bigtime_t time) const = 0; 1490fc56ed5SStephan Aßmus // conversion: Playist frame <-> Playlist time 1500fc56ed5SStephan Aßmus int64 PlaylistFrameForTime(bigtime_t time) const; 1510fc56ed5SStephan Aßmus bigtime_t PlaylistTimeForFrame(int64 frame) const; 1520fc56ed5SStephan Aßmus 1530fc56ed5SStephan Aßmus // to be called by audio/video producers 1540fc56ed5SStephan Aßmus virtual void SetCurrentAudioTime(bigtime_t time); 1550fc56ed5SStephan Aßmus void SetCurrentVideoFrame(int64 frame); 1560fc56ed5SStephan Aßmus void SetCurrentVideoTime(bigtime_t time); 1570fc56ed5SStephan Aßmus void SetPerformanceFrame(int64 frame); 1580fc56ed5SStephan Aßmus void SetPerformanceTime(bigtime_t time); 1590fc56ed5SStephan Aßmus 1600fc56ed5SStephan Aßmus // listener support 1610fc56ed5SStephan Aßmus void AddListener(PlaybackListener* listener); 1620fc56ed5SStephan Aßmus void RemoveListener(PlaybackListener* listener); 1630fc56ed5SStephan Aßmus 1640fc56ed5SStephan Aßmus virtual void NotifyPlayModeChanged(int32 mode) const; 1650fc56ed5SStephan Aßmus virtual void NotifyLoopModeChanged(int32 mode) const; 1660fc56ed5SStephan Aßmus virtual void NotifyLoopingEnabledChanged( 1670fc56ed5SStephan Aßmus bool enabled) const; 1680fc56ed5SStephan Aßmus virtual void NotifyVideoBoundsChanged(BRect bounds) const; 1690fc56ed5SStephan Aßmus virtual void NotifyFPSChanged(float fps) const; 170818577b2SStephan Aßmus virtual void NotifyCurrentFrameChanged(int64 frame) const; 1710fc56ed5SStephan Aßmus virtual void NotifySpeedChanged(float speed) const; 1720fc56ed5SStephan Aßmus virtual void NotifyFrameDropped() const; 1730fc56ed5SStephan Aßmus virtual void NotifyStopFrameReached() const; 174*0beac2ffSStephan Aßmus virtual void NotifySeekHandled(int64 seekedFrame) const; 1750fc56ed5SStephan Aßmus 1760fc56ed5SStephan Aßmus // debugging 1770fc56ed5SStephan Aßmus void PrintState(PlayingState* state); 1780fc56ed5SStephan Aßmus void PrintStateAtFrame(int64 frame); 1790fc56ed5SStephan Aßmus 1800fc56ed5SStephan Aßmus private: 1810fc56ed5SStephan Aßmus // state management 1820fc56ed5SStephan Aßmus void _PushState(PlayingState* state, 1830fc56ed5SStephan Aßmus bool adjustCurrentFrame); 1840fc56ed5SStephan Aßmus void _UpdateStates(); 1850fc56ed5SStephan Aßmus int32 _IndexForFrame(int64 frame) const; 1860fc56ed5SStephan Aßmus int32 _IndexForTime(bigtime_t time) const; 1870fc56ed5SStephan Aßmus PlayingState* _LastState() const; 1880fc56ed5SStephan Aßmus PlayingState* _StateAt(int32 index) const; 1890fc56ed5SStephan Aßmus PlayingState* _StateAtTime(bigtime_t time) const; 1900fc56ed5SStephan Aßmus PlayingState* _StateAtFrame(int64 frame) const; 1910fc56ed5SStephan Aßmus 1920fc56ed5SStephan Aßmus static int32 _PlayingDirectionFor(int32 playingMode); 1930fc56ed5SStephan Aßmus static int32 _PlayingDirectionFor(PlayingState* state); 1940fc56ed5SStephan Aßmus static void _GetPlayingBoundsFor(PlayingState* state, 1950fc56ed5SStephan Aßmus int64& startFrame, 1960fc56ed5SStephan Aßmus int64& endFrame, 1970fc56ed5SStephan Aßmus int64& frameCount); 1980fc56ed5SStephan Aßmus static int64 _PlayingStartFrameFor(PlayingState* state); 1990fc56ed5SStephan Aßmus static int64 _PlayingEndFrameFor(PlayingState* state); 2000fc56ed5SStephan Aßmus static int64 _RangeFrameForFrame(PlayingState* state, 2010fc56ed5SStephan Aßmus int64 frame); 2020fc56ed5SStephan Aßmus static int64 _FrameForRangeFrame(PlayingState* state, 2030fc56ed5SStephan Aßmus int64 index); 2040fc56ed5SStephan Aßmus static int64 _NextFrameInRange(PlayingState* state, 2050fc56ed5SStephan Aßmus int64 frame); 2060fc56ed5SStephan Aßmus 2070fc56ed5SStephan Aßmus // speed management 2080fc56ed5SStephan Aßmus void _PushSpeedInfo(SpeedInfo* info); 2090fc56ed5SStephan Aßmus SpeedInfo* _LastSpeedInfo() const; 2100fc56ed5SStephan Aßmus SpeedInfo* _SpeedInfoAt(int32 index) const; 2110fc56ed5SStephan Aßmus int32 _SpeedInfoIndexForFrame(int64 frame) const; 2120fc56ed5SStephan Aßmus int32 _SpeedInfoIndexForTime(bigtime_t time) const; 2130fc56ed5SStephan Aßmus SpeedInfo* _SpeedInfoForFrame(int64 frame) const; 2140fc56ed5SStephan Aßmus SpeedInfo* _SpeedInfoForTime(bigtime_t time) const; 2150fc56ed5SStephan Aßmus void _UpdateSpeedInfos(); 2160fc56ed5SStephan Aßmus 2170fc56ed5SStephan Aßmus bigtime_t _TimeForLastFrame() const; 2180fc56ed5SStephan Aßmus bigtime_t _TimeForNextFrame() const; 2190fc56ed5SStephan Aßmus 220*0beac2ffSStephan Aßmus void _NotifySeekHandledIfNecessary( 221*0beac2ffSStephan Aßmus PlayingState* state); 2220fc56ed5SStephan Aßmus void _CheckStopPlaying(); 2230fc56ed5SStephan Aßmus 2240fc56ed5SStephan Aßmus private: 2250fc56ed5SStephan Aßmus BList fStates; 2260fc56ed5SStephan Aßmus BList fSpeeds; 2270fc56ed5SStephan Aßmus volatile bigtime_t fCurrentAudioTime; 2280fc56ed5SStephan Aßmus volatile bigtime_t fCurrentVideoTime; 2290fc56ed5SStephan Aßmus volatile bigtime_t fPerformanceTime; 230*0beac2ffSStephan Aßmus 231*0beac2ffSStephan Aßmus MessageEvent* fPerformanceTimeEvent; 232*0beac2ffSStephan Aßmus 2330fc56ed5SStephan Aßmus volatile float fFrameRate; // video frame rate 2340fc56ed5SStephan Aßmus volatile bigtime_t fStopPlayingFrame; // frame at which playing 2350fc56ed5SStephan Aßmus // shall be stopped, 2360fc56ed5SStephan Aßmus // disabled: -1 2370fc56ed5SStephan Aßmus 2380fc56ed5SStephan Aßmus BList fListeners; 239eb91d005SStephan Aßmus protected: 240eb91d005SStephan Aßmus bool fNoAudio; 2410fc56ed5SStephan Aßmus }; 2420fc56ed5SStephan Aßmus 2430fc56ed5SStephan Aßmus 2440fc56ed5SStephan Aßmus #endif // PLAYBACK_MANAGER_H 245