xref: /haiku/src/apps/mediaplayer/media_node_framework/PlaybackManager.h (revision 0fc56ed57bdd5d2d44f33edd17d94210704613bd)
1*0fc56ed5SStephan Aßmus /*
2*0fc56ed5SStephan Aßmus  * Copyright (c) 2000-2008, Ingo Weinhold <ingo_weinhold@gmx.de>,
3*0fc56ed5SStephan Aßmus  * Copyright (c) 2000-2008, Stephan Aßmus <superstippi@gmx.de>,
4*0fc56ed5SStephan Aßmus  * All Rights Reserved. Distributed under the terms of the MIT license.
5*0fc56ed5SStephan Aßmus  */
6*0fc56ed5SStephan Aßmus 
7*0fc56ed5SStephan Aßmus /*!	This class controls our playback
8*0fc56ed5SStephan Aßmus 	Note: Add/RemoveListener() are the only methods that lock the object
9*0fc56ed5SStephan Aßmus 	themselves. All other methods need it to be locked before.
10*0fc56ed5SStephan Aßmus */
11*0fc56ed5SStephan Aßmus #ifndef PLAYBACK_MANAGER_H
12*0fc56ed5SStephan Aßmus #define PLAYBACK_MANAGER_H
13*0fc56ed5SStephan Aßmus 
14*0fc56ed5SStephan Aßmus 
15*0fc56ed5SStephan Aßmus #include <List.h>
16*0fc56ed5SStephan Aßmus #include <Looper.h>
17*0fc56ed5SStephan Aßmus #include <Rect.h>
18*0fc56ed5SStephan Aßmus 
19*0fc56ed5SStephan Aßmus 
20*0fc56ed5SStephan Aßmus class PlaybackListener;
21*0fc56ed5SStephan Aßmus 
22*0fc56ed5SStephan Aßmus 
23*0fc56ed5SStephan Aßmus enum {
24*0fc56ed5SStephan Aßmus 	MODE_PLAYING_FORWARD			= 1,
25*0fc56ed5SStephan Aßmus 	MODE_PLAYING_BACKWARD			= 2,
26*0fc56ed5SStephan Aßmus 	MODE_PLAYING_PAUSED_FORWARD		= -1,
27*0fc56ed5SStephan Aßmus 	MODE_PLAYING_PAUSED_BACKWARD	= -2,
28*0fc56ed5SStephan Aßmus };
29*0fc56ed5SStephan Aßmus 
30*0fc56ed5SStephan Aßmus enum {
31*0fc56ed5SStephan Aßmus 	LOOPING_ALL						= 0,
32*0fc56ed5SStephan Aßmus 	LOOPING_RANGE					= 1,
33*0fc56ed5SStephan Aßmus 	LOOPING_SELECTION				= 2,
34*0fc56ed5SStephan Aßmus 	LOOPING_VISIBLE					= 3,
35*0fc56ed5SStephan Aßmus };
36*0fc56ed5SStephan Aßmus 
37*0fc56ed5SStephan Aßmus enum {
38*0fc56ed5SStephan Aßmus 	MSG_PLAYBACK_FORCE_UPDATE		= 'pbfu',
39*0fc56ed5SStephan Aßmus 	MSG_PLAYBACK_SET_RANGE			= 'pbsr',
40*0fc56ed5SStephan Aßmus 	MSG_PLAYBACK_SET_VISIBLE		= 'pbsv',
41*0fc56ed5SStephan Aßmus 	MSG_PLAYBACK_SET_LOOP_MODE		= 'pbsl',
42*0fc56ed5SStephan Aßmus };
43*0fc56ed5SStephan Aßmus 
44*0fc56ed5SStephan Aßmus 
45*0fc56ed5SStephan Aßmus class PlaybackManager : public BLooper {
46*0fc56ed5SStephan Aßmus private:
47*0fc56ed5SStephan Aßmus 			struct PlayingState;
48*0fc56ed5SStephan Aßmus 			struct SpeedInfo;
49*0fc56ed5SStephan Aßmus 
50*0fc56ed5SStephan Aßmus public:
51*0fc56ed5SStephan Aßmus 								PlaybackManager();
52*0fc56ed5SStephan Aßmus 	virtual						~PlaybackManager();
53*0fc56ed5SStephan Aßmus 
54*0fc56ed5SStephan Aßmus 			void				Init(float frameRate,
55*0fc56ed5SStephan Aßmus 									 int32 loopingMode = LOOPING_ALL,
56*0fc56ed5SStephan Aßmus 									 bool loopingEnabled = true,
57*0fc56ed5SStephan Aßmus 									 float speed = 1.0,
58*0fc56ed5SStephan Aßmus 									 int32 playMode = MODE_PLAYING_PAUSED_FORWARD,
59*0fc56ed5SStephan Aßmus 									 int32 currentFrame = 0);
60*0fc56ed5SStephan Aßmus 			void				Cleanup();
61*0fc56ed5SStephan Aßmus 
62*0fc56ed5SStephan Aßmus 	// BHandler interface
63*0fc56ed5SStephan Aßmus 	virtual	void				MessageReceived(BMessage* message);
64*0fc56ed5SStephan Aßmus 
65*0fc56ed5SStephan Aßmus 			void				StartPlaying(bool atBeginning = false);
66*0fc56ed5SStephan Aßmus 			void				StopPlaying();
67*0fc56ed5SStephan Aßmus 			void				TogglePlaying(bool atBeginning = false);
68*0fc56ed5SStephan Aßmus 			void				PausePlaying();
69*0fc56ed5SStephan Aßmus 			bool				IsPlaying() const;
70*0fc56ed5SStephan Aßmus 
71*0fc56ed5SStephan Aßmus 			int32				PlayMode() const;
72*0fc56ed5SStephan Aßmus 			int32				LoopMode() const;
73*0fc56ed5SStephan Aßmus 			bool				IsLoopingEnabled() const;
74*0fc56ed5SStephan Aßmus 			int32				CurrentFrame() const;
75*0fc56ed5SStephan Aßmus 			float				Speed() const;
76*0fc56ed5SStephan Aßmus 
77*0fc56ed5SStephan Aßmus 	virtual	void				SetFramesPerSecond(float framesPerSecond);
78*0fc56ed5SStephan Aßmus 			float				FramesPerSecond() const;
79*0fc56ed5SStephan Aßmus 
80*0fc56ed5SStephan Aßmus 	virtual	BRect				VideoBounds() const = 0;
81*0fc56ed5SStephan Aßmus 
82*0fc56ed5SStephan Aßmus 	virtual	void				FrameDropped() const;
83*0fc56ed5SStephan Aßmus 
84*0fc56ed5SStephan Aßmus 			void				DurationChanged();
85*0fc56ed5SStephan Aßmus 	virtual	int64				Duration() = 0;
86*0fc56ed5SStephan Aßmus 
87*0fc56ed5SStephan Aßmus 	virtual	void				SetVolume(float percent) = 0;
88*0fc56ed5SStephan Aßmus 
89*0fc56ed5SStephan Aßmus 			// playing state manipulation
90*0fc56ed5SStephan Aßmus 			void				SetCurrentFrame(int64 frame);
91*0fc56ed5SStephan Aßmus 	virtual	void				SetPlayMode(int32 mode,
92*0fc56ed5SStephan Aßmus 									bool continuePlaying = true);
93*0fc56ed5SStephan Aßmus 			void				SetLoopMode(int32 mode,
94*0fc56ed5SStephan Aßmus 									bool continuePlaying = true);
95*0fc56ed5SStephan Aßmus 			void				SetLoopingEnabled(bool enabled,
96*0fc56ed5SStephan Aßmus 									bool continuePlaying = true);
97*0fc56ed5SStephan Aßmus 			void				SetSpeed(float speed);
98*0fc56ed5SStephan Aßmus 
99*0fc56ed5SStephan Aßmus 			// playing state change info
100*0fc56ed5SStephan Aßmus 			int64				NextFrame() const;
101*0fc56ed5SStephan Aßmus 			int64				NextPlaylistFrame() const;
102*0fc56ed5SStephan Aßmus 
103*0fc56ed5SStephan Aßmus 			int64				FirstPlaybackRangeFrame();
104*0fc56ed5SStephan Aßmus 			int64				LastPlaybackRangeFrame();
105*0fc56ed5SStephan Aßmus 
106*0fc56ed5SStephan Aßmus 			// playing state access
107*0fc56ed5SStephan Aßmus 			int64				StartFrameAtFrame(int64 frame);
108*0fc56ed5SStephan Aßmus 			int64				StartFrameAtTime(bigtime_t time);
109*0fc56ed5SStephan Aßmus 			int64				EndFrameAtFrame(int64 frame);
110*0fc56ed5SStephan Aßmus 			int64				EndFrameAtTime(bigtime_t time);
111*0fc56ed5SStephan Aßmus 			int64				FrameCountAtFrame(int64 frame);
112*0fc56ed5SStephan Aßmus 			int64				FrameCountAtTime(bigtime_t time);
113*0fc56ed5SStephan Aßmus 			int32				PlayModeAtFrame(int64 frame);
114*0fc56ed5SStephan Aßmus 			int32				PlayModeAtTime(bigtime_t time);
115*0fc56ed5SStephan Aßmus 			int32				LoopModeAtFrame(int64 frame);
116*0fc56ed5SStephan Aßmus 			int32				LoopModeAtTime(bigtime_t time);
117*0fc56ed5SStephan Aßmus 			// ...
118*0fc56ed5SStephan Aßmus 
119*0fc56ed5SStephan Aßmus 			// playing frame/time/interval info
120*0fc56ed5SStephan Aßmus 			int64				PlaylistFrameAtFrame(int64 frame,
121*0fc56ed5SStephan Aßmus 									int32& playingDirection,
122*0fc56ed5SStephan Aßmus 									bool& newState) const;
123*0fc56ed5SStephan Aßmus 			int64				PlaylistFrameAtFrame(int64 frame,
124*0fc56ed5SStephan Aßmus 									int32& playingDirection) const;
125*0fc56ed5SStephan Aßmus 			int64				PlaylistFrameAtFrame(int64 frame) const;
126*0fc56ed5SStephan Aßmus 			int64				NextChangeFrame(int64 startFrame,
127*0fc56ed5SStephan Aßmus 												int64 endFrame) const;
128*0fc56ed5SStephan Aßmus 			bigtime_t			NextChangeTime(bigtime_t startTime,
129*0fc56ed5SStephan Aßmus 											   bigtime_t endTime) const;
130*0fc56ed5SStephan Aßmus 			void				GetPlaylistFrameInterval(
131*0fc56ed5SStephan Aßmus 									int64 startFrame, int64& endFrame,
132*0fc56ed5SStephan Aßmus 									int64& xStartFrame, int64& xEndFrame,
133*0fc56ed5SStephan Aßmus 									int32& playingDirection) const;
134*0fc56ed5SStephan Aßmus 
135*0fc56ed5SStephan Aßmus 	// PlaybackManagerInterface
136*0fc56ed5SStephan Aßmus 	virtual	void				GetPlaylistTimeInterval(
137*0fc56ed5SStephan Aßmus 									bigtime_t startTime, bigtime_t& endTime,
138*0fc56ed5SStephan Aßmus 									bigtime_t& xStartTime, bigtime_t& xEndTime,
139*0fc56ed5SStephan Aßmus 									float& playingSpeed) const;
140*0fc56ed5SStephan Aßmus 
141*0fc56ed5SStephan Aßmus 			// conversion: video frame <-> (performance) time
142*0fc56ed5SStephan Aßmus 			int64				FrameForTime(bigtime_t time) const;
143*0fc56ed5SStephan Aßmus 			bigtime_t			TimeForFrame(int64 frame) const;
144*0fc56ed5SStephan Aßmus 			// conversion: (performance) time <-> real time
145*0fc56ed5SStephan Aßmus 	virtual	bigtime_t			RealTimeForTime(bigtime_t time) const = 0;
146*0fc56ed5SStephan Aßmus 	virtual	bigtime_t			TimeForRealTime(bigtime_t time) const = 0;
147*0fc56ed5SStephan Aßmus 			// conversion: Playist frame <-> Playlist time
148*0fc56ed5SStephan Aßmus 			int64				PlaylistFrameForTime(bigtime_t time) const;
149*0fc56ed5SStephan Aßmus 			bigtime_t			PlaylistTimeForFrame(int64 frame) const;
150*0fc56ed5SStephan Aßmus 
151*0fc56ed5SStephan Aßmus 			// to be called by audio/video producers
152*0fc56ed5SStephan Aßmus 	virtual	void				SetCurrentAudioTime(bigtime_t time);
153*0fc56ed5SStephan Aßmus 			void				SetCurrentVideoFrame(int64 frame);
154*0fc56ed5SStephan Aßmus 			void				SetCurrentVideoTime(bigtime_t time);
155*0fc56ed5SStephan Aßmus 			void				SetPerformanceFrame(int64 frame);
156*0fc56ed5SStephan Aßmus 			void				SetPerformanceTime(bigtime_t time);
157*0fc56ed5SStephan Aßmus 
158*0fc56ed5SStephan Aßmus 			// listener support
159*0fc56ed5SStephan Aßmus 			void				AddListener(PlaybackListener* listener);
160*0fc56ed5SStephan Aßmus 			void				RemoveListener(PlaybackListener* listener);
161*0fc56ed5SStephan Aßmus 
162*0fc56ed5SStephan Aßmus 	virtual	void				NotifyPlayModeChanged(int32 mode) const;
163*0fc56ed5SStephan Aßmus 	virtual	void				NotifyLoopModeChanged(int32 mode) const;
164*0fc56ed5SStephan Aßmus 	virtual	void				NotifyLoopingEnabledChanged(
165*0fc56ed5SStephan Aßmus 									bool enabled) const;
166*0fc56ed5SStephan Aßmus 	virtual	void				NotifyVideoBoundsChanged(BRect bounds) const;
167*0fc56ed5SStephan Aßmus 	virtual	void				NotifyFPSChanged(float fps) const;
168*0fc56ed5SStephan Aßmus 	virtual	void				NotifyCurrentFrameChanged(int32 frame) const;
169*0fc56ed5SStephan Aßmus 	virtual	void				NotifySpeedChanged(float speed) const;
170*0fc56ed5SStephan Aßmus 	virtual	void				NotifyFrameDropped() const;
171*0fc56ed5SStephan Aßmus 	virtual	void				NotifyStopFrameReached() const;
172*0fc56ed5SStephan Aßmus 
173*0fc56ed5SStephan Aßmus 			// debugging
174*0fc56ed5SStephan Aßmus 			void				PrintState(PlayingState* state);
175*0fc56ed5SStephan Aßmus 			void				PrintStateAtFrame(int64 frame);
176*0fc56ed5SStephan Aßmus 
177*0fc56ed5SStephan Aßmus  private:
178*0fc56ed5SStephan Aßmus 			// state management
179*0fc56ed5SStephan Aßmus 			void				_PushState(PlayingState* state,
180*0fc56ed5SStephan Aßmus 										   bool adjustCurrentFrame);
181*0fc56ed5SStephan Aßmus 			void				_UpdateStates();
182*0fc56ed5SStephan Aßmus 			int32				_IndexForFrame(int64 frame) const;
183*0fc56ed5SStephan Aßmus 			int32				_IndexForTime(bigtime_t time) const;
184*0fc56ed5SStephan Aßmus 			PlayingState*		_LastState() const;
185*0fc56ed5SStephan Aßmus 			PlayingState*		_StateAt(int32 index) const;
186*0fc56ed5SStephan Aßmus 			PlayingState*		_StateAtTime(bigtime_t time) const;
187*0fc56ed5SStephan Aßmus 			PlayingState*		_StateAtFrame(int64 frame) const;
188*0fc56ed5SStephan Aßmus 
189*0fc56ed5SStephan Aßmus 	static	int32				_PlayingDirectionFor(int32 playingMode);
190*0fc56ed5SStephan Aßmus 	static	int32				_PlayingDirectionFor(PlayingState* state);
191*0fc56ed5SStephan Aßmus 	static	void				_GetPlayingBoundsFor(PlayingState* state,
192*0fc56ed5SStephan Aßmus 													 int64& startFrame,
193*0fc56ed5SStephan Aßmus 													 int64& endFrame,
194*0fc56ed5SStephan Aßmus 													 int64& frameCount);
195*0fc56ed5SStephan Aßmus 	static	int64				_PlayingStartFrameFor(PlayingState* state);
196*0fc56ed5SStephan Aßmus 	static	int64				_PlayingEndFrameFor(PlayingState* state);
197*0fc56ed5SStephan Aßmus 	static	int64				_RangeFrameForFrame(PlayingState* state,
198*0fc56ed5SStephan Aßmus 													int64 frame);
199*0fc56ed5SStephan Aßmus 	static	int64				_FrameForRangeFrame(PlayingState* state,
200*0fc56ed5SStephan Aßmus 													int64 index);
201*0fc56ed5SStephan Aßmus 	static	int64				_NextFrameInRange(PlayingState* state,
202*0fc56ed5SStephan Aßmus 												  int64 frame);
203*0fc56ed5SStephan Aßmus 
204*0fc56ed5SStephan Aßmus 			// speed management
205*0fc56ed5SStephan Aßmus 			void				_PushSpeedInfo(SpeedInfo* info);
206*0fc56ed5SStephan Aßmus 			SpeedInfo*			_LastSpeedInfo() const;
207*0fc56ed5SStephan Aßmus 			SpeedInfo*			_SpeedInfoAt(int32 index) const;
208*0fc56ed5SStephan Aßmus 			int32				_SpeedInfoIndexForFrame(int64 frame) const;
209*0fc56ed5SStephan Aßmus 			int32				_SpeedInfoIndexForTime(bigtime_t time) const;
210*0fc56ed5SStephan Aßmus 			SpeedInfo*			_SpeedInfoForFrame(int64 frame) const;
211*0fc56ed5SStephan Aßmus 			SpeedInfo*			_SpeedInfoForTime(bigtime_t time) const;
212*0fc56ed5SStephan Aßmus 			void				_UpdateSpeedInfos();
213*0fc56ed5SStephan Aßmus 
214*0fc56ed5SStephan Aßmus 			bigtime_t			_TimeForLastFrame() const;
215*0fc56ed5SStephan Aßmus 			bigtime_t			_TimeForNextFrame() const;
216*0fc56ed5SStephan Aßmus 
217*0fc56ed5SStephan Aßmus 			void				_CheckStopPlaying();
218*0fc56ed5SStephan Aßmus 
219*0fc56ed5SStephan Aßmus  private:
220*0fc56ed5SStephan Aßmus 			BList				fStates;
221*0fc56ed5SStephan Aßmus 			BList				fSpeeds;
222*0fc56ed5SStephan Aßmus 	volatile bigtime_t			fCurrentAudioTime;
223*0fc56ed5SStephan Aßmus 	volatile bigtime_t			fCurrentVideoTime;
224*0fc56ed5SStephan Aßmus 	volatile bigtime_t			fPerformanceTime;
225*0fc56ed5SStephan Aßmus 	volatile float				fFrameRate;			// video frame rate
226*0fc56ed5SStephan Aßmus 	volatile bigtime_t			fStopPlayingFrame;	// frame at which playing
227*0fc56ed5SStephan Aßmus 													// shall be stopped,
228*0fc56ed5SStephan Aßmus 													// disabled: -1
229*0fc56ed5SStephan Aßmus 
230*0fc56ed5SStephan Aßmus 			BList				fListeners;
231*0fc56ed5SStephan Aßmus };
232*0fc56ed5SStephan Aßmus 
233*0fc56ed5SStephan Aßmus 
234*0fc56ed5SStephan Aßmus #endif	// PLAYBACK_MANAGER_H
235