MPD  0.20.6
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,
54 
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 {
94  uint16_t bit_rate;
98 };
99 
102 
104 
105  const unsigned buffer_chunks;
106 
107  const unsigned buffered_before_play;
108 
113 
118 
122  mutable Mutex mutex;
123 
128 
135 
138 
140 
147  std::exception_ptr error;
148 
160 
161  uint16_t bit_rate;
165 
173 
175 
177 
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 
273  assert(command != PlayerCommand::NONE);
274 
275  command = PlayerCommand::NONE;
276  ClientSignal();
277  }
278 
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) {
321  assert(command == PlayerCommand::NONE);
322 
323  command = cmd;
324  Signal();
325  WaitCommandLocked();
326  }
327 
335  void LockSynchronousCommand(PlayerCommand cmd) {
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 
373  if (border_pause)
374  state = PlayerState::PAUSE;
375  return border_pause;
376  }
377 
379  const std::lock_guard<Mutex> lock(mutex);
380  return ApplyBorderPause();
381  }
382 
383  void Kill();
384 
385  gcc_pure
387 
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);
434  }
435 
436  void LockClearError();
437 
439  return error_type;
440  }
441 
446  void LockSetTaggedSong(const DetachedSong &song);
447 
448  void ClearTaggedSong();
449 
456  DetachedSong *result = tagged_song;
457  tagged_song = nullptr;
458  return result;
459  }
460 
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 
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
DetachedSong * ReadTaggedSong()
Read and clear the tagged_song attribute.
Definition: Control.hxx:455
void SetOutputError(std::exception_ptr &&_error)
Set the error and set state to PlayerState::PAUSE.
Definition: Control.hxx:404
DetachedSong * tagged_song
A copy of the current DetachedSong after its tags have been updated by the decoder (for example...
Definition: Control.hxx:159
cancel pre-decoding PlayerControl.next_song; if the player has already started playing this song...
uint16_t bit_rate
Definition: Control.hxx:94
ReplayGainMode
const AudioFormat configured_audio_format
The "audio_output_format" setting.
Definition: Control.hxx:112
This structure describes the format of a raw PCM stream.
Definition: AudioFormat.hxx:37
void LockSetBorderPause(bool border_pause)
Set the player's border_pause flag.
void LockClearError()
void ApplyEnabled() override
The AudioOutput has modified the "enabled" flag, and the client shall make the AudioOutput apply this...
Definition: Control.hxx:537
An interface between the AudioOutput and the #Player.
Definition: Client.hxx:28
void LockPause()
The audio output has failed.
Mutex mutex
This lock protects command, state, error, tagged_song.
Definition: Control.hxx:122
static constexpr SongTime zero()
Definition: Chrono.hxx:41
DetachedSong * next_song
The next queued song.
Definition: Control.hxx:172
A time stamp within a song.
Definition: Chrono.hxx:31
void CommandFinished()
A command has been finished.
Definition: Control.hxx:272
DetachedSong * LockReadTaggedSong()
Like ReadTaggedSong(), but locks and unlocks the object.
Definition: Control.hxx:464
void LockEnqueueSong(DetachedSong *song)
PlayerError GetErrorType() const
Definition: Control.hxx:438
void wait(PosixMutex &mutex)
Definition: PosixCond.hxx:73
void SetError(PlayerError type, std::exception_ptr &&_error)
Set the error.
SongTime elapsed_time
Definition: Control.hxx:97
SongTime seek_time
Definition: Control.hxx:174
PlayerCommand
Definition: Control.hxx:47
void LockCommandFinished()
Definition: Control.hxx:279
void ClearTaggedSong()
void LockSetReplayGainMode(ReplayGainMode _mode)
Definition: Control.hxx:523
MultipleOutputs & outputs
Definition: Control.hxx:103
Definition: Cond.hxx:41
Definition: Mutex.hxx:43
std::exception_ptr error
The error that occurred in the player thread.
Definition: Control.hxx:147
void Wait()
Waits for a signal on the object.
Definition: Control.hxx:236
PlayerControl(PlayerListener &_listener, MultipleOutputs &_outputs, unsigned buffer_chunks, unsigned buffered_before_play, AudioFormat _configured_audio_format, const ReplayGainConfig &_replay_gain_config)
float GetMixRampDelay() const
Definition: Control.hxx:519
void LockSeek(DetachedSong *song, SongTime t)
Makes the player thread seek the specified song to a position.
SignedSongTime total_time
Definition: Control.hxx:163
void LockSetOutputError(std::exception_ptr &&_error)
Definition: Control.hxx:412
bool LockWaitOutputConsumed(unsigned threshold)
Definition: Control.hxx:296
AudioFormat audio_format
Definition: Control.hxx:95
Cond cond
Trigger this object after you have modified command.
Definition: Control.hxx:127
double GetTotalPlayTime() const
Definition: Control.hxx:528
void LockSetTaggedSong(const DetachedSong &song)
Set the tagged_song attribute to a newly allocated copy of the given DetachedSong.
void ChunksConsumed() override
Notify the client that we have consumed a few chunks.
Definition: Control.hxx:533
SongTime elapsed_time
Definition: Control.hxx:164
void ClientWait()
The client calls this method to wait for command completion.
Definition: Control.hxx:259
PlayerState state
Definition: Control.hxx:137
double total_play_time
Definition: Control.hxx:181
PlayerError
Definition: Control.hxx:78
bool WaitOutputConsumed(unsigned threshold)
Checks if the size of the MusicPipe is below the #threshold.
void SetMixRampDb(float mixramp_db)
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
PlayerError error_type
Definition: Control.hxx:139
void Signal()
Signals the object.
Definition: Control.hxx:218
void LockCheckRethrowError() const
Like CheckRethrowError(), but locks and unlocks the object.
Definition: Control.hxx:431
float GetCrossFade() const
Definition: Control.hxx:507
void LockUpdateAudio()
void LockCancel()
see PlayerCommand::CANCEL
const unsigned buffered_before_play
Definition: Control.hxx:107
At least one AudioOutput.enabled flag has been modified; commit those changes to the output threads...
ReplayGainMode replay_gain_mode
Definition: Control.hxx:179
void LockSignal()
Signals the object.
Definition: Control.hxx:226
bool ApplyBorderPause()
Definition: Control.hxx:372
PlayerListener & listener
Definition: Control.hxx:101
const ReplayGainConfig replay_gain_config
Definition: Control.hxx:178
Refresh status information in the PlayerControl struct, e.g.
void SetCrossFade(float cross_fade_seconds)
void unlock()
Definition: PosixMutex.hxx:71
void signal()
Definition: PosixCond.hxx:65
bool LockApplyBorderPause()
Definition: Control.hxx:378
float GetMixRampDb() const
Definition: Control.hxx:513
A variant of SongTime that is based on a signed integer.
Definition: Chrono.hxx:115
PlayerState
Definition: Control.hxx:41
Thread thread
The handle of the player thread.
Definition: Control.hxx:117
PlayerControl.next_song has been updated.
float duration
The configured cross fade duration [s].
Definition: CrossFade.hxx:32
void SetMixRampDelay(float mixramp_delay_seconds)
void LockSetPause(bool pause_flag)
gcc_pure bool IsInside() const
Check if this thread is the current thread.
Definition: Thread.hxx:80
void ClientSignal()
Wake up the client waiting for command completion.
Definition: Control.hxx:247
void CheckRethrowError() const
Checks whether an error has occurred, and if so, rethrows it.
Definition: Control.hxx:423
void Play(DetachedSong *song)
Throws std::runtime_error or #Error on error.
float mixramp_delay
The configured MixRapm delay [s].
Definition: CrossFade.hxx:40
void Lock() const
Locks the object.
Definition: Control.hxx:203
uint16_t bit_rate
Definition: Control.hxx:161
Cond client_cond
This object gets signalled when the player thread has finished the command.
Definition: Control.hxx:134
#define gcc_pure
Definition: Compiler.h:116
void lock()
Definition: PosixMutex.hxx:63
SignedSongTime total_time
Definition: Control.hxx:96
const unsigned buffer_chunks
Definition: Control.hxx:105
AudioFormat audio_format
Definition: Control.hxx:162
void Unlock() const
Unlocks the object.
Definition: Control.hxx:210
PlayerCommand command
Definition: Control.hxx:136
PlayerState state
Definition: Control.hxx:93
CrossFadeSettings cross_fade
Definition: Control.hxx:176
gcc_pure player_status LockGetStatus()
PlayerState GetState() const
Definition: Control.hxx:388