PlayerControl.hxx 6.6 KB
Newer Older
1
/*
Max Kellermann's avatar
Max Kellermann committed
2
 * Copyright (C) 2003-2011 The Music Player Daemon Project
3
 * http://www.musicpd.org
Warren Dukes's avatar
Warren Dukes committed
4 5 6 7 8 9 10 11 12 13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
14 15 16 17
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Warren Dukes's avatar
Warren Dukes committed
18 19
 */

20 21
#ifndef MPD_PLAYER_H
#define MPD_PLAYER_H
Warren Dukes's avatar
Warren Dukes committed
22

23
#include "audio_format.h"
24 25
#include "thread/Mutex.hxx"
#include "thread/Cond.hxx"
26

Max Kellermann's avatar
Max Kellermann committed
27 28
#include <glib.h>

29
#include <stdint.h>
Warren Dukes's avatar
Warren Dukes committed
30

31 32
struct decoder_control;

33 34 35 36 37
enum player_state {
	PLAYER_STATE_STOP = 0,
	PLAYER_STATE_PAUSE,
	PLAYER_STATE_PLAY
};
Warren Dukes's avatar
Warren Dukes committed
38

39 40
enum player_command {
	PLAYER_COMMAND_NONE = 0,
Max Kellermann's avatar
Max Kellermann committed
41
	PLAYER_COMMAND_EXIT,
42 43 44 45
	PLAYER_COMMAND_STOP,
	PLAYER_COMMAND_PAUSE,
	PLAYER_COMMAND_SEEK,
	PLAYER_COMMAND_CLOSE_AUDIO,
46

47 48 49 50 51 52
	/**
	 * At least one audio_output.enabled flag has been modified;
	 * commit those changes to the output threads.
	 */
	PLAYER_COMMAND_UPDATE_AUDIO,

53 54 55 56 57 58 59 60 61
	/** player_control.next_song has been updated */
	PLAYER_COMMAND_QUEUE,

	/**
	 * cancel pre-decoding player_control.next_song; if the player
	 * has already started playing this song, it will completely
	 * stop
	 */
	PLAYER_COMMAND_CANCEL,
62 63 64 65 66 67

	/**
	 * Refresh status information in the #player_control struct,
	 * e.g. elapsed_time.
	 */
	PLAYER_COMMAND_REFRESH,
68 69
};

70
enum player_error {
71 72 73 74 75 76 77 78 79 80 81
	PLAYER_ERROR_NONE = 0,

	/**
	 * The decoder has failed to decode the song.
	 */
	PLAYER_ERROR_DECODER,

	/**
	 * The audio output has failed.
	 */
	PLAYER_ERROR_OUTPUT,
82
};
Warren Dukes's avatar
Warren Dukes committed
83

84 85 86 87 88 89 90 91
struct player_status {
	enum player_state state;
	uint16_t bit_rate;
	struct audio_format audio_format;
	float total_time;
	float elapsed_time;
};

92
struct player_control {
93 94
	unsigned buffer_chunks;

95 96
	unsigned int buffered_before_play;

97 98 99 100
	/** the handle of the player thread, or NULL if the player
	    thread isn't running */
	GThread *thread;

101 102 103
	/**
	 * This lock protects #command, #state, #error.
	 */
104
	mutable Mutex mutex;
105 106 107 108

	/**
	 * Trigger this object after you have modified #command.
	 */
109
	Cond cond;
110

111 112 113 114 115 116 117
	/**
	 * This object gets signalled when the player thread has
	 * finished the #command.  It wakes up the client that waits
	 * (i.e. the main thread).
	 */
	Cond client_cond;

118 119
	enum player_command command;
	enum player_state state;
120 121 122

	enum player_error error_type;

123 124 125 126 127 128 129 130
	/**
	 * The error that occurred in the player thread.  This
	 * attribute is only valid if #error is not
	 * #PLAYER_ERROR_NONE.  The object must be freed when this
	 * object transitions back to #PLAYER_ERROR_NONE.
	 */
	GError *error;

131
	uint16_t bit_rate;
132
	struct audio_format audio_format;
133 134
	float total_time;
	float elapsed_time;
135 136 137 138 139 140 141

	/**
	 * The next queued song.
	 *
	 * This is a duplicate, and must be freed when this attribute
	 * is cleared.
	 */
142
	struct song *next_song;
143

144
	double seek_where;
145
	float cross_fade_seconds;
146 147
	float mixramp_db;
	float mixramp_delay_seconds;
148
	double total_play_time;
149 150 151 152 153 154 155 156 157

	/**
	 * If this flag is set, then the player will be auto-paused at
	 * the end of the song, before the next song starts to play.
	 *
	 * This is a copy of the queue's "single" flag most of the
	 * time.
	 */
	bool border_pause;
Warren Dukes's avatar
Warren Dukes committed
158

159 160 161
	player_control(unsigned buffer_chunks,
		       unsigned buffered_before_play);
	~player_control();
162

163 164 165 166 167 168
	/**
	 * Locks the object.
	 */
	void Lock() const {
		mutex.lock();
	}
169

170 171 172 173 174 175
	/**
	 * Unlocks the object.
	 */
	void Unlock() const {
		mutex.unlock();
	}
Warren Dukes's avatar
Warren Dukes committed
176

177 178 179 180 181 182 183
	/**
	 * Signals the object.  The object should be locked prior to
	 * calling this function.
	 */
	void Signal() {
		cond.signal();
	}
184

185 186 187 188 189 190 191 192 193
	/**
	 * Signals the object.  The object is temporarily locked by
	 * this function.
	 */
	void LockSignal() {
		Lock();
		Signal();
		Unlock();
	}
194

195 196 197 198 199 200
	/**
	 * Waits for a signal on the object.  This function is only
	 * valid in the player thread.  The object must be locked
	 * prior to calling this function.
	 */
	void Wait() {
201 202
		assert(thread == g_thread_self());

203 204
		cond.wait(mutex);
	}
Warren Dukes's avatar
Warren Dukes committed
205

206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
	/**
	 * Wake up the client waiting for command completion.
	 *
	 * Caller must lock the object.
	 */
	void ClientSignal() {
		assert(thread == g_thread_self());

		client_cond.signal();
	}

	/**
	 * The client calls this method to wait for command
	 * completion.
	 *
	 * Caller must lock the object.
	 */
	void ClientWait() {
		assert(thread != g_thread_self());

		client_cond.wait(mutex);
	}

229 230 231 232 233
	/**
	 * @param song the song to be queued; the given instance will
	 * be owned and freed by the player
	 */
	void Play(struct song *song);
234

235 236 237 238
	/**
	 * see PLAYER_COMMAND_CANCEL
	 */
	void Cancel();
Warren Dukes's avatar
Warren Dukes committed
239

240
	void SetPause(bool pause_flag);
Warren Dukes's avatar
Warren Dukes committed
241

242
	void Pause();
Warren Dukes's avatar
Warren Dukes committed
243

244 245 246 247
	/**
	 * Set the player's #border_pause flag.
	 */
	void SetBorderPause(bool border_pause);
248

249
	void Kill();
Warren Dukes's avatar
Warren Dukes committed
250

251 252
	gcc_pure
	player_status GetStatus();
Warren Dukes's avatar
Warren Dukes committed
253

254 255 256
	player_state GetState() const {
		return state;
	}
Warren Dukes's avatar
Warren Dukes committed
257

258 259 260 261 262 263 264 265 266 267
	/**
	 * Set the error.  Discards any previous error condition.
	 *
	 * Caller must lock the object.
	 *
	 * @param type the error type; must not be #PLAYER_ERROR_NONE
	 * @param error detailed error information; must not be NULL; the
	 * #player_control takes over ownership of this #GError instance
	 */
	void SetError(player_error type, GError *error);
268

269
	void ClearError();
270

271 272 273 274 275 276
	/**
	 * Returns the human-readable message describing the last
	 * error during playback, NULL if no error occurred.  The
	 * caller has to free the returned string.
	 */
	char *GetErrorMessage() const;
Warren Dukes's avatar
Warren Dukes committed
277

278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323
	player_error GetErrorType() const {
		return error_type;
	}

	void Stop();

	void UpdateAudio();

	/**
	 * @param song the song to be queued; the given instance will be owned
	 * and freed by the player
	 */
	void EnqueueSong(struct song *song);

	/**
	 * Makes the player thread seek the specified song to a position.
	 *
	 * @param song the song to be queued; the given instance will be owned
	 * and freed by the player
	 * @return true on success, false on failure (e.g. if MPD isn't
	 * playing currently)
	 */
	bool Seek(struct song *song, float seek_time);

	void SetCrossFade(float cross_fade_seconds);

	float GetCrossFade() const {
		return cross_fade_seconds;
	}

	void SetMixRampDb(float mixramp_db);

	float GetMixRampDb() const {
		return mixramp_db;
	}

	void SetMixRampDelay(float mixramp_delay_seconds);

	float GetMixRampDelay() const {
		return mixramp_delay_seconds;
	}

	double GetTotalPlayTime() const {
		return total_play_time;
	}
};
324

Warren Dukes's avatar
Warren Dukes committed
325
#endif