xref: /haiku/src/apps/mediaplayer/media_node_framework/PlaybackManager.h (revision 0beac2ff048390fecd8a08a99e7dd2cd8a9724b4)
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