MPD: player/Control.hxx Source File

MPD 0.20.15

Control.hxx
Go to the documentation of this file.
1 /*
2 * Copyright 2003-2017 The Music Player Daemon Project
3 * http://www.musicpd.org
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef MPD_PLAYER_CONTROL_HXX
21 #define MPD_PLAYER_CONTROL_HXX
22
23 #include "output/Client.hxx"
24 #include "AudioFormat.hxx"
25 #include "thread/Mutex.hxx"
26 #include "thread/Cond.hxx"
27 #include "thread/Thread.hxx"
28 #include "CrossFade.hxx"
29 #include "Chrono.hxx"
30 #include "ReplayGainConfig.hxx"
31 #include "ReplayGainMode.hxx"
32
33 #include <exception>
34
35 #include <stdint.h>
36
37 class PlayerListener;
38 class MultipleOutputs;
39 class DetachedSong;
40
41 enum class PlayerState : uint8_t {
42 STOP,
43 PAUSE,
44 PLAY
45 };
46
47 enum class PlayerCommand : uint8_t {
48 NONE,
49 EXIT,
50 STOP,
51 PAUSE,
52 SEEK,
53 CLOSE_AUDIO,
54
59 UPDATE_AUDIO,
60
62 QUEUE,
63
69 CANCEL,
70
75 REFRESH,
76 };
77
78 enum class PlayerError : uint8_t {
79 NONE,
80
84 DECODER,
85
89 OUTPUT,
90 };
91
92 struct player_status {
93 PlayerState state;
94 uint16_t bit_rate;
95 AudioFormat audio_format;
96 SignedSongTime total_time;
97 SongTime elapsed_time;
98 };
99
100 struct PlayerControl final : AudioOutputClient {
101 PlayerListener &listener;
102
103 MultipleOutputs &outputs;
104
105 const unsigned buffer_chunks;
106
107 const unsigned buffered_before_play;
108
112 const AudioFormat configured_audio_format;
113
117 Thread thread;
118
122 mutable Mutex mutex;
123
127 Cond cond;
128
134 Cond client_cond;
135
136 PlayerCommand command = PlayerCommand::NONE;
137 PlayerState state = PlayerState::STOP;
138
139 PlayerError error_type = PlayerError::NONE;
140
147 std::exception_ptr error;
148
159 DetachedSong *tagged_song = nullptr;
160
161 uint16_t bit_rate;
162 AudioFormat audio_format;
163 SignedSongTime total_time;
164 SongTime elapsed_time;
165
172 DetachedSong *next_song = nullptr;
173
174 SongTime seek_time;
175
176 CrossFadeSettings cross_fade;
177
178 const ReplayGainConfig replay_gain_config;
179 ReplayGainMode replay_gain_mode = ReplayGainMode::OFF;
180
181 double total_play_time = 0;
182
190 bool border_pause = false;
191
192 PlayerControl(PlayerListener &_listener,
193 MultipleOutputs &_outputs,
194 unsigned buffer_chunks,
195 unsigned buffered_before_play,
196 AudioFormat _configured_audio_format,
197 const ReplayGainConfig &_replay_gain_config);
198 ~PlayerControl();
199
203 void Lock() const {
204 mutex.lock();
205 }
206
210 void Unlock() const {
211 mutex.unlock();
212 }
213
218 void Signal() {
219 cond.signal();
220 }
221
226 void LockSignal() {
227 const std::lock_guard<Mutex> protect(mutex);
228 Signal();
229 }
230
236 void Wait() {
237 assert(thread.IsInside());
238
239 cond.wait(mutex);
240 }
241
247 void ClientSignal() {
248 assert(thread.IsInside());
249
250 client_cond.signal();
251 }
252
259 void ClientWait() {
260 assert(!thread.IsInside());
261
262 client_cond.wait(mutex);
263 }
264
272 void CommandFinished() {
273 assert(command != PlayerCommand::NONE);
274
275 command = PlayerCommand::NONE;
276 ClientSignal();
277 }
278
279 void LockCommandFinished() {
280 const std::lock_guard<Mutex> protect(mutex);
281 CommandFinished();
282 }
283
294 bool WaitOutputConsumed(unsigned threshold);
295
296 bool LockWaitOutputConsumed(unsigned threshold) {
297 const std::lock_guard<Mutex> protect(mutex);
298 return WaitOutputConsumed(threshold);
299 }
300
301 private:
308 void WaitCommandLocked() {
309 while (command != PlayerCommand::NONE)
310 ClientWait();
311 }
312
320 void SynchronousCommand(PlayerCommand cmd) noexcept {
321 assert(command == PlayerCommand::NONE);
322
323 command = cmd;
324 Signal();
325 WaitCommandLocked();
326 }
327
335 void LockSynchronousCommand(PlayerCommand cmd) noexcept {
336 const std::lock_guard<Mutex> protect(mutex);
337 SynchronousCommand(cmd);
338 }
339
340 public:
347 void Play(DetachedSong *song);
348
352 void LockCancel();
353
354 void LockSetPause(bool pause_flag);
355
356 private:
357 void PauseLocked();
358
359 void ClearError() {
360 error_type = PlayerError::NONE;
361 error = std::exception_ptr();
362 }
363
364 public:
365 void LockPause();
366
370 void LockSetBorderPause(bool border_pause);
371
372 bool ApplyBorderPause() {
373 if (border_pause)
374 state = PlayerState::PAUSE;
375 return border_pause;
376 }
377
378 bool LockApplyBorderPause() {
379 const std::lock_guard<Mutex> lock(mutex);
380 return ApplyBorderPause();
381 }
382
383 void Kill();
384
385 gcc_pure
386 player_status LockGetStatus() noexcept;
387
388 PlayerState GetState() const {
389 return state;
390 }
391
399 void SetError(PlayerError type, std::exception_ptr &&_error);
400
404 void SetOutputError(std::exception_ptr &&_error) {
405 SetError(PlayerError::OUTPUT, std::move(_error));
406
407 /* pause: the user may resume playback as soon as an
408 audio output becomes available */
409 state = PlayerState::PAUSE;
410 }
411
412 void LockSetOutputError(std::exception_ptr &&_error) {
413 const std::lock_guard<Mutex> lock(mutex);
414 SetOutputError(std::move(_error));
415 }
416
423 void CheckRethrowError() const {
424 if (error_type != PlayerError::NONE)
425 std::rethrow_exception(error);
426 }
427
431 void LockCheckRethrowError() const {
432 const std::lock_guard<Mutex> protect(mutex);
433 CheckRethrowError();
434 }
435
436 void LockClearError();
437
438 PlayerError GetErrorType() const {
439 return error_type;
440 }
441
446 void LockSetTaggedSong(const DetachedSong &song);
447
448 void ClearTaggedSong();
449
455 DetachedSong *ReadTaggedSong() {
456 DetachedSong *result = tagged_song;
457 tagged_song = nullptr;
458 return result;
459 }
460
464 DetachedSong *LockReadTaggedSong() {
465 const std::lock_guard<Mutex> protect(mutex);
466 return ReadTaggedSong();
467 }
468
469 void LockStop();
470
471 void LockUpdateAudio();
472
473 private:
474 void EnqueueSongLocked(DetachedSong *song) {
475 assert(song != nullptr);
476 assert(next_song == nullptr);
477
478 next_song = song;
479 seek_time = SongTime::zero();
480 SynchronousCommand(PlayerCommand::QUEUE);
481 }
482
486 void SeekLocked(DetachedSong *song, SongTime t);
487
488 public:
493 void LockEnqueueSong(DetachedSong *song);
494
503 void LockSeek(DetachedSong *song, SongTime t);
504
505 void SetCrossFade(float cross_fade_seconds);
506
507 float GetCrossFade() const {
508 return cross_fade.duration;
509 }
510
511 void SetMixRampDb(float mixramp_db);
512
513 float GetMixRampDb() const {
514 return cross_fade.mixramp_db;
515 }
516
517 void SetMixRampDelay(float mixramp_delay_seconds);
518
519 float GetMixRampDelay() const {
520 return cross_fade.mixramp_delay;
521 }
522
523 void LockSetReplayGainMode(ReplayGainMode _mode) {
524 const std::lock_guard<Mutex> protect(mutex);
525 replay_gain_mode = _mode;
526 }
527
528 double GetTotalPlayTime() const {
529 return total_play_time;
530 }
531
532 /* virtual methods from AudioOutputClient */
533 void ChunksConsumed() override {
534 LockSignal();
535 }
536
537 void ApplyEnabled() override {
538 LockUpdateAudio();
539 }
540 };
541
542 #endif
PlayerControl::ReadTaggedSong
DetachedSong * ReadTaggedSong()
Read and clear the tagged_song attribute.
Definition: Control.hxx:455
PlayerControl::SetOutputError
void SetOutputError(std::exception_ptr &&_error)
Set the error and set state to PlayerState::PAUSE.
Definition: Control.hxx:404
PlayerControl::tagged_song
DetachedSong * tagged_song
A copy of the current DetachedSong after its tags have been updated by the decoder (for example...
Definition: Control.hxx:159
Client.hxx
PlayerCommand::CANCEL
cancel pre-decoding PlayerControl.next_song; if the player has already started playing this song...
PlayerControl::GetMixRampDelay
float GetMixRampDelay() const
Definition: Control.hxx:519
player_status::bit_rate
uint16_t bit_rate
Definition: Control.hxx:94
ReplayGainMode
ReplayGainMode
Definition: ReplayGainMode.hxx:27
PlayerControl::GetErrorType
PlayerError GetErrorType() const
Definition: Control.hxx:438
PlayerControl::configured_audio_format
const AudioFormat configured_audio_format
The "audio_output_format" setting.
Definition: Control.hxx:112
AudioFormat
This structure describes the format of a raw PCM stream.
Definition: AudioFormat.hxx:37
ReplayGainMode.hxx
PlayerControl::LockSetBorderPause
void LockSetBorderPause(bool border_pause)
Set the player&#39;s border_pause flag.
PlayerControl::LockClearError
void LockClearError()
PlayerControl::ApplyEnabled
void ApplyEnabled() override
The AudioOutput has modified the "enabled" flag, and the client shall make the AudioOutput apply this...
Definition: Control.hxx:537
AudioOutputClient
An interface between the AudioOutput and the #Player.
Definition: Client.hxx:28
PlayerControl::LockPause
void LockPause()
PlayerError::OUTPUT
The audio output has failed.
PlayerControl::mutex
Mutex mutex
This lock protects command, state, error, tagged_song.
Definition: Control.hxx:122
Chrono.hxx
SongTime::zero
static constexpr SongTime zero()
Definition: Chrono.hxx:41
PlayerControl::next_song
DetachedSong * next_song
The next queued song.
Definition: Control.hxx:172
PlayerState::STOP
PlayerControl::GetCrossFade
float GetCrossFade() const
Definition: Control.hxx:507
AudioFormat.hxx
SongTime
A time stamp within a song.
Definition: Chrono.hxx:31
PlayerControl::CommandFinished
void CommandFinished()
A command has been finished.
Definition: Control.hxx:272
ReplayGainConfig
Definition: ReplayGainConfig.hxx:25
PlayerControl::LockReadTaggedSong
DetachedSong * LockReadTaggedSong()
Like ReadTaggedSong(), but locks and unlocks the object.
Definition: Control.hxx:464
PlayerControl::LockEnqueueSong
void LockEnqueueSong(DetachedSong *song)
PlayerCommand::CLOSE_AUDIO
PosixCond::wait
void wait(PosixMutex &mutex)
Definition: PosixCond.hxx:73
PlayerControl::SetError
void SetError(PlayerError type, std::exception_ptr &&_error)
Set the error.
player_status::elapsed_time
SongTime elapsed_time
Definition: Control.hxx:97
CrossFade.hxx
PlayerControl::seek_time
SongTime seek_time
Definition: Control.hxx:174
PlayerCommand
PlayerCommand
Definition: Control.hxx:47
PlayerControl::LockCommandFinished
void LockCommandFinished()
Definition: Control.hxx:279
PlayerControl::ClearTaggedSong
void ClearTaggedSong()
PlayerControl::LockSetReplayGainMode
void LockSetReplayGainMode(ReplayGainMode _mode)
Definition: Control.hxx:523
PlayerControl::outputs
MultipleOutputs & outputs
Definition: Control.hxx:103
Cond
Definition: Cond.hxx:41
Mutex
Definition: Mutex.hxx:43
PlayerControl::error
std::exception_ptr error
The error that occurred in the player thread.
Definition: Control.hxx:147
PlayerControl::Wait
void Wait()
Waits for a signal on the object.
Definition: Control.hxx:236
DecoderCommand::STOP
PlayerControl::PlayerControl
PlayerControl(PlayerListener &_listener, MultipleOutputs &_outputs, unsigned buffer_chunks, unsigned buffered_before_play, AudioFormat _configured_audio_format, const ReplayGainConfig &_replay_gain_config)
CrossFadeSettings
Definition: CrossFade.hxx:28
PlayerControl::LockSeek
void LockSeek(DetachedSong *song, SongTime t)
Makes the player thread seek the specified song to a position.
PlayerControl::Unlock
void Unlock() const
Unlocks the object.
Definition: Control.hxx:210
PlayerControl::~PlayerControl
~PlayerControl()
ConfigBlockOption::DECODER
PlayerControl::total_time
SignedSongTime total_time
Definition: Control.hxx:163
PlayerControl::Lock
void Lock() const
Locks the object.
Definition: Control.hxx:203
PlayerControl::LockSetOutputError
void LockSetOutputError(std::exception_ptr &&_error)
Definition: Control.hxx:412
PlayerControl::LockWaitOutputConsumed
bool LockWaitOutputConsumed(unsigned threshold)
Definition: Control.hxx:296
player_status::audio_format
AudioFormat audio_format
Definition: Control.hxx:95
PlayerControl::cond
Cond cond
Trigger this object after you have modified command.
Definition: Control.hxx:127
Cond.hxx
PlayerControl::LockSetTaggedSong
void LockSetTaggedSong(const DetachedSong &song)
Set the tagged_song attribute to a newly allocated copy of the given DetachedSong.
PlayerControl::ChunksConsumed
void ChunksConsumed() override
Notify the client that we have consumed a few chunks.
Definition: Control.hxx:533
Thread.hxx
PlayerControl::CheckRethrowError
void CheckRethrowError() const
Checks whether an error has occurred, and if so, rethrows it.
Definition: Control.hxx:423
PlayerControl::elapsed_time
SongTime elapsed_time
Definition: Control.hxx:164
PlayerControl::LockGetStatus
gcc_pure player_status LockGetStatus() noexcept
PlayerControl::ClientWait
void ClientWait()
The client calls this method to wait for command completion.
Definition: Control.hxx:259
PlayerControl::state
PlayerState state
Definition: Control.hxx:137
PlayerControl::total_play_time
double total_play_time
Definition: Control.hxx:181
PlayerError
PlayerError
Definition: Control.hxx:78
PlayerControl::WaitOutputConsumed
bool WaitOutputConsumed(unsigned threshold)
Checks if the size of the MusicPipe is below the #threshold.
CrossFadeSettings::mixramp_db
float mixramp_db
Definition: CrossFade.hxx:34
PlayerControl::GetState
PlayerState GetState() const
Definition: Control.hxx:388
PlayerControl::SetMixRampDb
void SetMixRampDb(float mixramp_db)
PlayerControl::border_pause
bool border_pause
If this flag is set, then the player will be auto-paused at the end of the song, before the next song...
Definition: Control.hxx:190
PlayerControl::error_type
PlayerError error_type
Definition: Control.hxx:139
PlayerControl::Signal
void Signal()
Signals the object.
Definition: Control.hxx:218
DecoderCommand::SEEK
PlayerCommand::NONE
PlayerControl::LockUpdateAudio
void LockUpdateAudio()
PlayerControl::LockCancel
void LockCancel()
see PlayerCommand::CANCEL
PlayerControl::buffered_before_play
const unsigned buffered_before_play
Definition: Control.hxx:107
PlayerCommand::UPDATE_AUDIO
At least one AudioOutput.enabled flag has been modified; commit those changes to the output threads...
PlayerControl::replay_gain_mode
ReplayGainMode replay_gain_mode
Definition: Control.hxx:179
PlayerState::PLAY
PlayerControl::LockSignal
void LockSignal()
Signals the object.
Definition: Control.hxx:226
PlayerControl::GetMixRampDb
float GetMixRampDb() const
Definition: Control.hxx:513
Mutex.hxx
ReplayGainConfig.hxx
PlayerListener
Definition: Listener.hxx:23
PlayerControl::ApplyBorderPause
bool ApplyBorderPause()
Definition: Control.hxx:372
PlayerControl::listener
PlayerListener & listener
Definition: Control.hxx:101
PlayerControl
Definition: Control.hxx:100
PlayerControl::replay_gain_config
const ReplayGainConfig replay_gain_config
Definition: Control.hxx:178
PlayerCommand::REFRESH
Refresh status information in the PlayerControl struct, e.g.
PlayerControl::SetCrossFade
void SetCrossFade(float cross_fade_seconds)
PosixMutex::unlock
void unlock()
Definition: PosixMutex.hxx:71
PosixCond::signal
void signal()
Definition: PosixCond.hxx:65
MultipleOutputs
Definition: MultipleOutputs.hxx:47
PlayerControl::LockApplyBorderPause
bool LockApplyBorderPause()
Definition: Control.hxx:378
SignedSongTime
A variant of SongTime that is based on a signed integer.
Definition: Chrono.hxx:115
PlayerState
PlayerState
Definition: Control.hxx:41
PlayerControl::thread
Thread thread
The handle of the player thread.
Definition: Control.hxx:117
PlayerCommand::EXIT
PlayerCommand::QUEUE
PlayerControl.next_song has been updated.
CrossFadeSettings::duration
float duration
The configured cross fade duration [s].
Definition: CrossFade.hxx:32
ReplayGainMode::OFF
PlayerControl::GetTotalPlayTime
double GetTotalPlayTime() const
Definition: Control.hxx:528
Thread
Definition: Thread.hxx:34
PlayerControl::SetMixRampDelay
void SetMixRampDelay(float mixramp_delay_seconds)
PlayerControl::LockSetPause
void LockSetPause(bool pause_flag)
PlayerControl::ClientSignal
void ClientSignal()
Wake up the client waiting for command completion.
Definition: Control.hxx:247
player_status
Definition: Control.hxx:92
PlayerControl::LockCheckRethrowError
void LockCheckRethrowError() const
Like CheckRethrowError(), but locks and unlocks the object.
Definition: Control.hxx:431
PlayerControl::Play
void Play(DetachedSong *song)
Throws std::runtime_error or #Error on error.
CrossFadeSettings::mixramp_delay
float mixramp_delay
The configured MixRapm delay [s].
Definition: CrossFade.hxx:40
Thread::IsInside
gcc_pure bool IsInside() const noexcept
Check if this thread is the current thread.
Definition: Thread.hxx:80
PlayerControl::bit_rate
uint16_t bit_rate
Definition: Control.hxx:161
PlayerControl::client_cond
Cond client_cond
This object gets signalled when the player thread has finished the command.
Definition: Control.hxx:134
gcc_pure
#define gcc_pure
Definition: Compiler.h:116
PlayerControl::LockStop
void LockStop()
PosixMutex::lock
void lock()
Definition: PosixMutex.hxx:63
DetachedSong
Definition: DetachedSong.hxx:37
player_status::total_time
SignedSongTime total_time
Definition: Control.hxx:96
PlayerControl::buffer_chunks
const unsigned buffer_chunks
Definition: Control.hxx:105
PlayerControl::Kill
void Kill()
PlayerError::NONE
PlayerControl::audio_format
AudioFormat audio_format
Definition: Control.hxx:162
PlayerState::PAUSE
PlayerControl::command
PlayerCommand command
Definition: Control.hxx:136
player_status::state
PlayerState state
Definition: Control.hxx:93
PlayerCommand::PAUSE
PlayerControl::cross_fade
CrossFadeSettings cross_fade
Definition: Control.hxx:176