MPD  0.20.23
DecoderControl.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_DECODER_CONTROL_HXX
21 #define MPD_DECODER_CONTROL_HXX
22 
23 #include "DecoderCommand.hxx"
24 #include "AudioFormat.hxx"
25 #include "MixRampInfo.hxx"
26 #include "thread/Mutex.hxx"
27 #include "thread/Cond.hxx"
28 #include "thread/Thread.hxx"
29 #include "Chrono.hxx"
30 #include "ReplayGainConfig.hxx"
31 #include "ReplayGainMode.hxx"
32 
33 #include <exception>
34 
35 #include <utility>
36 
37 #include <assert.h>
38 #include <stdint.h>
39 
40 /* damn you, windows.h! */
41 #ifdef ERROR
42 #undef ERROR
43 #endif
44 
45 class DetachedSong;
46 class MusicBuffer;
47 class MusicPipe;
48 
49 enum class DecoderState : uint8_t {
50  STOP = 0,
51  START,
52  DECODE,
53 
60  ERROR,
61 };
62 
68 
78 
85 
93 
96 
103  std::exception_ptr error;
104 
105  bool quit;
106 
112  bool client_is_waiting = false;
113 
115  bool seekable;
117 
122 
125 
128 
137  DetachedSong *song = nullptr;
138 
146 
154 
156 
159 
165 
168 
169  float replay_gain_db = 0;
171 
173 
178  DecoderControl(Mutex &_mutex, Cond &_client_cond,
179  const AudioFormat _configured_audio_format,
180  const ReplayGainConfig &_replay_gain_config);
181  ~DecoderControl();
182 
186  void Lock() const {
187  mutex.lock();
188  }
189 
193  void Unlock() const {
194  mutex.unlock();
195  }
196 
202  void Signal() {
203  cond.signal();
204  }
205 
211  void Wait() {
212  cond.wait(mutex);
213  }
214 
222  void WaitForDecoder();
223 
224  bool IsIdle() const {
225  return state == DecoderState::STOP ||
227  }
228 
229  gcc_pure
230  bool LockIsIdle() const noexcept {
231  const std::lock_guard<Mutex> protect(mutex);
232  return IsIdle();
233  }
234 
235  bool IsStarting() const noexcept {
236  return state == DecoderState::START;
237  }
238 
239  gcc_pure
240  bool LockIsStarting() const noexcept {
241  const std::lock_guard<Mutex> protect(mutex);
242  return IsStarting();
243  }
244 
245  bool HasFailed() const noexcept {
246  assert(command == DecoderCommand::NONE);
247 
248  return state == DecoderState::ERROR;
249  }
250 
251  gcc_pure
252  bool LockHasFailed() const noexcept {
253  const std::lock_guard<Mutex> protect(mutex);
254  return HasFailed();
255  }
256 
263  void SetReady(const AudioFormat audio_format,
264  bool _seekable, SignedSongTime _duration);
265 
272  void CheckRethrowError() const {
273  assert(command == DecoderCommand::NONE);
274  assert(state != DecoderState::ERROR || error);
275 
276  if (state == DecoderState::ERROR)
277  std::rethrow_exception(error);
278  }
279 
283  void LockCheckRethrowError() const {
284  const std::lock_guard<Mutex> protect(mutex);
286  }
287 
293  void ClearError() {
294  if (state == DecoderState::ERROR) {
295  error = std::exception_ptr();
297  }
298  }
299 
307  gcc_pure
308  bool IsCurrentSong(const DetachedSong &_song) const noexcept;
309 
310  gcc_pure
311  bool IsSeekableCurrentSong(const DetachedSong &_song) const noexcept {
312  return seekable && IsCurrentSong(_song);
313  }
314 
315  gcc_pure
316  bool LockIsSeeakbleCurrentSong(const DetachedSong &_song) const noexcept {
317  const std::lock_guard<Mutex> protect(mutex);
318  return IsSeekableCurrentSong(_song);
319  }
320 
321 private:
328  void WaitCommandLocked() {
329  while (command != DecoderCommand::NONE)
330  WaitForDecoder();
331  }
332 
340  void SynchronousCommandLocked(DecoderCommand cmd) {
341  command = cmd;
342  Signal();
343  WaitCommandLocked();
344  }
345 
353  void LockSynchronousCommand(DecoderCommand cmd) {
354  const std::lock_guard<Mutex> protect(mutex);
355  ClearError();
356  SynchronousCommandLocked(cmd);
357  }
358 
359  void LockAsynchronousCommand(DecoderCommand cmd) {
360  const std::lock_guard<Mutex> protect(mutex);
361  command = cmd;
362  Signal();
363  }
364 
365 public:
374  assert(command != DecoderCommand::NONE);
375 
378  }
379 
392 
393  void Stop();
394 
398  void Seek(SongTime t);
399 
400  void Quit();
401 
402  const char *GetMixRampStart() const {
403  return mix_ramp.GetStart();
404  }
405 
406  const char *GetMixRampEnd() const {
407  return mix_ramp.GetEnd();
408  }
409 
410  const char *GetMixRampPreviousEnd() const {
411  return previous_mix_ramp.GetEnd();
412  }
413 
414  void SetMixRamp(MixRampInfo &&new_value) {
415  mix_ramp = std::move(new_value);
416  }
417 
422  void CycleMixRamp();
423 
424 private:
425  void RunThread();
426 };
427 
428 #endif
void Wait()
Waits for a signal on the DecoderControl object.
void ClearError()
Clear the error condition and free the #Error object (if any).
ReplayGainMode
gcc_pure const char * GetEnd() const noexcept
Definition: MixRampInfo.hxx:50
This structure describes the format of a raw PCM stream.
Definition: AudioFormat.hxx:36
gcc_pure bool LockHasFailed() const noexcept
SignedSongTime total_time
std::exception_ptr error
The error that occurred in the decoder thread.
gcc_pure bool IsCurrentSong(const DetachedSong &_song) const noexcept
Check if the specified song is currently being decoded.
A queue of MusicChunk objects.
Definition: MusicPipe.hxx:39
void CycleMixRamp()
Move mixramp_end to mixramp_prev_end and clear mixramp_start/mixramp_end.
const char * GetMixRampPreviousEnd() const
A time stamp within a song.
Definition: Chrono.hxx:31
DetachedSong * song
The song currently being decoded.
void wait(PosixMutex &mutex)
Definition: PosixCond.hxx:73
void Signal()
Signals the object.
AudioFormat in_audio_format
the format of the song file
Cond cond
Trigger this object after you have modified command.
Definition: Cond.hxx:41
Definition: Mutex.hxx:43
MixRampInfo previous_mix_ramp
Thread thread
The handle of the decoder thread.
gcc_pure bool LockIsIdle() const noexcept
SongTime end_time
The decoder will stop when it reaches this position.
void Seek(SongTime t)
Throws #std::runtime_error on error.
An allocator for MusicChunk objects.
Definition: MusicBuffer.hxx:31
gcc_pure bool LockIsSeeakbleCurrentSong(const DetachedSong &_song) const noexcept
void SetReady(const AudioFormat audio_format, bool _seekable, SignedSongTime _duration)
Transition this obejct from DecoderState::START to DecoderState::DECODE.
gcc_pure bool IsSeekableCurrentSong(const DetachedSong &_song) const noexcept
MusicBuffer * buffer
the MusicChunk allocator
gcc_pure bool LockIsStarting() const noexcept
void Unlock() const
Unlocks the object.
ReplayGainMode replay_gain_mode
gcc_pure const char * GetStart() const noexcept
Definition: MixRampInfo.hxx:45
void CommandFinishedLocked()
Marks the current command as "finished" and notifies the client (= player thread).
MusicPipe * pipe
The destination pipe for decoded chunks.
void SetMixRamp(MixRampInfo &&new_value)
MixRampInfo mix_ramp
DecoderControl(Mutex &_mutex, Cond &_client_cond, const AudioFormat _configured_audio_format, const ReplayGainConfig &_replay_gain_config)
void Lock() const
Locks the object.
The last "START" command failed, because there was an I/O error or because no decoder was able to dec...
void LockCheckRethrowError() const
Like CheckRethrowError(), but locks and unlocks the object.
Mutex & mutex
This lock protects state and command.
bool client_is_waiting
Is the client currently waiting for the DecoderThread? If false, the DecoderThread may omit invoking ...
bool IsStarting() const noexcept
DecoderState state
void unlock()
Definition: PosixMutex.hxx:71
void signal()
Definition: PosixCond.hxx:65
bool HasFailed() const noexcept
const char * GetMixRampEnd() const
DecoderCommand
A variant of SongTime that is based on a signed integer.
Definition: Chrono.hxx:115
const char * GetMixRampStart() const
bool IsIdle() const
#define gcc_pure
Definition: Compiler.h:116
void Start(DetachedSong *song, SongTime start_time, SongTime end_time, MusicBuffer &buffer, MusicPipe &pipe)
Start the decoder.
void lock()
Definition: PosixMutex.hxx:63
DecoderCommand command
Cond & client_cond
The trigger of this object's client.
const AudioFormat configured_audio_format
The "audio_output_format" setting.
AudioFormat out_audio_format
the format being sent to the music pipe
const ReplayGainConfig replay_gain_config
void CheckRethrowError() const
Checks whether an error has occurred, and if so, rethrows it.
DecoderState
SongTime start_time
The initial seek position, e.g.
void WaitForDecoder()
Waits for a signal from the decoder thread.