1 /***************************************************************************
2        PlaybackController.h  -  Interface for generic playback control
3 			     -------------------
4     begin                : Nov 15 2000
5     copyright            : (C) 2000 by Thomas Eschenbacher
6     email                : Thomas Eschenbacher <Thomas.Eschenbacher@gmx.de>
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef PLAYBACK_CONTROLLER_H
19 #define PLAYBACK_CONTROLLER_H
20 
21 #include "config.h"
22 
23 #include <QtGlobal>
24 #include <QList>
25 #include <QMutex>
26 #include <QObject>
27 
28 #include "libkwave/PlayBackParam.h"
29 #include "libkwave/Runnable.h"
30 #include "libkwave/Sample.h"
31 #include "libkwave/WorkerThread.h"
32 
33 namespace Kwave
34 {
35 
36     class PlayBackDevice;
37     class PlaybackDeviceFactory;
38     class SignalManager;
39 
40     /**
41      * Provides a generic interface for classes that can contol playback
42      * with start, stop, pause and continue. This class is intended to be used
43      * or derived in a class that is able to control a playback device by
44      * simply startig or stopping playback and can be easily used by some
45      * other part of the program that has nothing to do directly with
46      * playback. The playback control functions all start with "playback"
47      * and are slots that are intended to be connected to some simple
48      * gui elements like toolbar buttons or menu entries.
49      *
50      * This class internally manages the logic and handling of the
51      * playback position.
52      */
53     class Q_DECL_EXPORT PlaybackController: public QObject,
54                                             public Kwave::Runnable
55     {
56     Q_OBJECT
57 
58     public:
59 
60 	/** Default constructor */
61 	explicit PlaybackController(Kwave::SignalManager &signal_manager);
62 
63 	/** Destructor */
64         virtual ~PlaybackController() Q_DECL_OVERRIDE;
65 
66     public:
67 
68 	/** resets start, current position, loop, pause and running flag */
69 	void reset();
70 
71 	/** returns the loop mode flag */
72 	bool loop() const;
73 
74 	/** returns true if the playback is running */
75 	bool running() const;
76 
77 	/** returns true if the playback is paused */
78 	bool paused() const;
79 
80 	/** sets a new start position */
81 	void setStartPos(sample_index_t pos);
82 
83 	/** sets a new end position */
84 	void setEndPos(sample_index_t pos);
85 
86 	/** returns the position where the playback starts */
87 	sample_index_t startPos() const;
88 
89 	/** returns the position where the playback ends */
90 	sample_index_t endPos() const;
91 
92 	/** returns the current position of the playback pointer */
93 	sample_index_t currentPos() const;
94 
95 	/**
96 	 * Registers a PlaybackDeviceFactory
97 	 */
98 	void registerPlaybackDeviceFactory(
99 	    Kwave::PlaybackDeviceFactory *factory);
100 
101 	/**
102 	 * Unregisters a PlaybackDeviceFactory
103 	 */
104 	void unregisterPlaybackDeviceFactory(
105 	    Kwave::PlaybackDeviceFactory *factory);
106 
107 	/**
108 	 * Create a playback device matching the given playback method.
109 	 *
110 	 * @param method a playback_method_t (e.g. Pulse, ALSA, OSS...)
111 	 * @return a new PlayBackDevice or 0 if failed
112 	 */
113 	virtual Kwave::PlayBackDevice *createDevice(
114 	    Kwave::playback_method_t method);
115 
116 	/**
117 	 * Creates, opens and initializes a playback device.
118 	 *
119 	 * @param tracks number of tracks,
120 	 *               if negative use the setting of playback_params
121 	 * @param playback_params points to a structure with playback
122 	 *                        parameters. If null, the default parameters
123 	 *                        of the current signal will be used
124 	 * @return a pointer to an opened PlayBackDevice or null if failed
125 	 * @see PlayBackDevice
126 	 */
127 	Kwave::PlayBackDevice *openDevice(int tracks,
128 	    const Kwave::PlayBackParam *playback_params);
129 
130 	/**
131 	 * Sets default playback parameters, for use next time playback
132 	 * is started
133 	 * @param params new playback parameters
134 	 */
135 	void setDefaultParams(const Kwave::PlayBackParam &params);
136 
137 	/**
138 	 * Checks whether a playback method is supported and returns the
139 	 * next best match if not.
140 	 * @param method reference to a playback method, can be modified
141 	 */
142 	void checkMethod(Kwave::playback_method_t &method);
143 
144     public slots:
145 
146 	/**
147 	 * (Re-)starts the playback. If playback has successfully been
148 	 * started, the signal sigPlaybackStarted() will be emitted.
149 	 */
150 	void playbackStart();
151 
152 	/**
153 	 * (Re-)starts the playback in loop mode (like with playbackStart().
154 	 * Also emitts sigPlaybackStarted() if playback has successfully
155 	 * been started.
156 	 */
157 	void playbackLoop();
158 
159 	/**
160 	 * Pauses the playback. Causes sigPlaybackDone() to be emitted if
161 	 * the current buffer has played out. The current playback pointer
162 	 * will stay at it's current position.
163 	 */
164 	void playbackPause();
165 
166 	/**
167 	 * Continues the playback at the position where it has been stopped
168 	 * by the playbackPause() command. If the last playback pointer
169 	 * has become invalid or is not available (less 0), this function
170 	 * will do the same as playbackStart(). This also emits the
171 	 * signal sigPlaybackStarted().
172 	 */
173 	void playbackContinue();
174 
175 	/**
176 	 * Stopps playback / loop. Like playbackPause(), but resets the
177 	 * playback pointer back to the start.
178 	 */
179 	void playbackStop();
180 
181 	/**
182 	 * If playback is currently running, it will be paused and
183 	 * then restarted with current track and time selection.
184 	 */
185 	void reload();
186 
187 	/** Seeks to a new position */
188 	void seekTo(sample_index_t pos);
189 
190 	/** Called when the seek has finished */
191 	void seekDone(sample_index_t pos);
192 
193 	/** Updates the current playback position */
194 	void updatePlaybackPos(sample_index_t pos);
195 
196 	/** Updates the status if playback is done */
197 	void playbackDone();
198 
199     signals:
200 
201 	/**
202 	 * Signals that playback has started.
203 	 */
204 	void sigPlaybackStarted();
205 
206 	/**
207 	 * Signals that playback has been paused.
208 	 */
209 	void sigPlaybackPaused();
210 
211 	/**
212 	 * Signals that playback has stopped.
213 	 */
214 	void sigPlaybackStopped();
215 
216 	/**
217 	 * Emits the current position of the playback pointer
218 	 */
219 	void sigPlaybackPos(sample_index_t pos);
220 
221 	/**
222 	 * Emits the current position after a seek operation
223 	 */
224 	void sigSeekDone(sample_index_t pos);
225 
226 	/**
227 	 * Signals that playback has stopped (sent from worker thread).
228 	 */
229 	void sigDevicePlaybackDone();
230 
231 	/** Emits the current playback position (from worker thread) */
232 	void sigDevicePlaybackPos(sample_index_t pos);
233 
234 	/** Emitted after a successful seek operation (from worker thread)*/
235 	void sigDeviceSeekDone(sample_index_t pos);
236 
237     private slots:
238 
239 	/**
240 	 * Closes the playback device, deletes the instance of the
241 	 * PlayBackDevice and sets m_device to 0.
242 	 * @see m_device
243 	 * @see PlayBackDevice
244 	 */
245 	void closeDevice();
246 
247 	/** updates the mixer matrix if the track selection has changed */
248 	void trackSelectionChanged();
249 
250     protected:
251 
252 	/** wrapper for our run() function, called from worker thread */
253         virtual void run_wrapper(const QVariant &params) Q_DECL_OVERRIDE;
254 
255     private:
256 
257 	/** Starts playback device (and worker thread) */
258 	void startDevicePlayBack();
259 
260 	/** Stops the playback device (and worker thread) */
261 	void stopDevicePlayBack();
262 
263     private:
264 
265 	/** Reference to our signal manager */
266 	Kwave::SignalManager &m_signal_manager;
267 
268 	/**
269 	 * Thread that executes the run() member function.
270 	 */
271 	Kwave::WorkerThread m_thread;
272 
273 	/** The playback device used for playback */
274 	Kwave::PlayBackDevice *m_device;
275 
276 	/** Mutex for locking access to the playback device */
277 	QMutex m_lock_device;
278 
279 	/** the parameters used for playback */
280 	Kwave::PlayBackParam m_playback_params;
281 
282 	/**
283 	 * Mutex for locking access to members that control the playback
284 	 * loop, like m_should_seek, m_seek_pos and m_mixer
285 	 */
286 	QMutex m_lock_playback;
287 
288 	/** if true, m_seek_pos is valid and a seek has been requested */
289 	bool m_should_seek;
290 
291 	/** position to seek to */
292 	sample_index_t m_seek_pos;
293 
294 	/** notification flag, true if the track selection has changed */
295 	bool m_track_selection_changed;
296 
297 	/**
298 	 * If true, we are in "reload" mode. In this mode the playback is
299 	 * paused and continued without emitting a sigPlaybackDone. This
300 	 * is useful if playback parameters or signal selection has changed
301 	 * during playback.
302 	 */
303 	bool m_reload_mode;
304 
305 	/** if set to true, the playback will be done in loop mode */
306 	bool m_loop_mode;
307 
308 	/** if true, playback is only paused and can be continued */
309 	bool m_paused;
310 
311 	/** is set to true if the playback has been started */
312 	bool m_playing;
313 
314 	/** the current play position */
315 	sample_index_t m_playback_position;
316 
317 	/** the start position for playback */
318 	sample_index_t m_playback_start;
319 
320 	/** the end position for playback */
321 	sample_index_t m_playback_end;
322 
323 	/** Start of the selection when playback started */
324 	sample_index_t m_old_first;
325 
326 	/** End of the selection when playback started */
327 	sample_index_t m_old_last;
328 
329 	/** list of playback device factories */
330 	QList<Kwave::PlaybackDeviceFactory *> m_playback_factories;
331 
332     };
333 }
334 
335 #endif /* PLAYBACK_CONTROLLER_H */
336 
337 //***************************************************************************
338 //***************************************************************************
339