DecoderControl: move functions into the class

This commit is contained in:
Max Kellermann 2013-01-21 10:13:29 +01:00
parent e1b03b4a71
commit 32799fef5c
6 changed files with 298 additions and 377 deletions

View File

@ -64,10 +64,10 @@ decoder_initialized(struct decoder *decoder,
dc->seekable = seekable; dc->seekable = seekable;
dc->total_time = total_time; dc->total_time = total_time;
decoder_lock(dc); dc->Lock();
dc->state = DECODE_STATE_DECODE; dc->state = DECODE_STATE_DECODE;
g_cond_signal(dc->client_cond); g_cond_signal(dc->client_cond);
decoder_unlock(dc); dc->Unlock();
g_debug("audio_format=%s, seekable=%s", g_debug("audio_format=%s, seekable=%s",
audio_format_to_string(&dc->in_audio_format, &af_string), audio_format_to_string(&dc->in_audio_format, &af_string),
@ -155,7 +155,7 @@ decoder_command_finished(struct decoder *decoder)
{ {
struct decoder_control *dc = decoder->dc; struct decoder_control *dc = decoder->dc;
decoder_lock(dc); dc->Lock();
assert(dc->command != DECODE_COMMAND_NONE || assert(dc->command != DECODE_COMMAND_NONE ||
decoder->initial_seek_running); decoder->initial_seek_running);
@ -171,7 +171,7 @@ decoder_command_finished(struct decoder *decoder)
decoder->initial_seek_running = false; decoder->initial_seek_running = false;
decoder->timestamp = dc->start_ms / 1000.; decoder->timestamp = dc->start_ms / 1000.;
decoder_unlock(dc); dc->Unlock();
return; return;
} }
@ -192,7 +192,7 @@ decoder_command_finished(struct decoder *decoder)
dc->command = DECODE_COMMAND_NONE; dc->command = DECODE_COMMAND_NONE;
g_cond_signal(dc->client_cond); g_cond_signal(dc->client_cond);
decoder_unlock(dc); dc->Unlock();
} }
double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder) double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder)
@ -377,9 +377,9 @@ decoder_data(struct decoder *decoder,
assert(dc->pipe != NULL); assert(dc->pipe != NULL);
assert(length % audio_format_frame_size(&dc->in_audio_format) == 0); assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);
decoder_lock(dc); dc->Lock();
cmd = decoder_get_virtual_command(decoder); cmd = decoder_get_virtual_command(decoder);
decoder_unlock(dc); dc->Unlock();
if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK || if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
length == 0) length == 0)
@ -564,6 +564,6 @@ decoder_mixramp(struct decoder *decoder,
struct decoder_control *dc = decoder->dc; struct decoder_control *dc = decoder->dc;
assert(dc != NULL); assert(dc != NULL);
dc_mixramp_start(dc, mixramp_start); dc->MixRampStart(mixramp_start);
dc_mixramp_end(dc, mixramp_end); dc->MixRampEnd(mixramp_end);
} }

View File

@ -27,46 +27,30 @@
#undef G_LOG_DOMAIN #undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "decoder_control" #define G_LOG_DOMAIN "decoder_control"
struct decoder_control * decoder_control::decoder_control()
dc_new() :thread(nullptr),
mutex(g_mutex_new()), cond(g_cond_new()),
client_cond(g_cond_new()),
state(DECODE_STATE_STOP),
command(DECODE_COMMAND_NONE),
song(nullptr),
replay_gain_db(0), replay_gain_prev_db(0),
mixramp_start(nullptr), mixramp_end(nullptr),
mixramp_prev_end(nullptr) {}
decoder_control::~decoder_control()
{ {
struct decoder_control *dc = g_new(struct decoder_control, 1); ClearError();
dc->thread = NULL; if (song != NULL)
song_free(song);
dc->mutex = g_mutex_new(); g_cond_free(client_cond);
dc->cond = g_cond_new(); g_cond_free(cond);
dc->client_cond = g_cond_new(); g_mutex_free(mutex);
g_free(mixramp_start);
dc->state = DECODE_STATE_STOP; g_free(mixramp_end);
dc->command = DECODE_COMMAND_NONE; g_free(mixramp_prev_end);
dc->song = NULL;
dc->replay_gain_db = 0;
dc->replay_gain_prev_db = 0;
dc->mixramp_start = NULL;
dc->mixramp_end = NULL;
dc->mixramp_prev_end = NULL;
return dc;
}
void
dc_free(struct decoder_control *dc)
{
dc_clear_error(dc);
if (dc->song != NULL)
song_free(dc->song);
g_cond_free(dc->client_cond);
g_cond_free(dc->cond);
g_mutex_free(dc->mutex);
g_free(dc->mixramp_start);
g_free(dc->mixramp_end);
g_free(dc->mixramp_prev_end);
g_free(dc);
} }
static void static void
@ -80,45 +64,43 @@ static void
dc_command_locked(struct decoder_control *dc, enum decoder_command cmd) dc_command_locked(struct decoder_control *dc, enum decoder_command cmd)
{ {
dc->command = cmd; dc->command = cmd;
decoder_signal(dc); dc->Signal();
dc_command_wait_locked(dc); dc_command_wait_locked(dc);
} }
static void static void
dc_command(struct decoder_control *dc, enum decoder_command cmd) dc_command(struct decoder_control *dc, enum decoder_command cmd)
{ {
decoder_lock(dc); dc->Lock();
dc_clear_error(dc); dc->ClearError();
dc_command_locked(dc, cmd); dc_command_locked(dc, cmd);
decoder_unlock(dc); dc->Unlock();
} }
static void static void
dc_command_async(struct decoder_control *dc, enum decoder_command cmd) dc_command_async(struct decoder_control *dc, enum decoder_command cmd)
{ {
decoder_lock(dc); dc->Lock();
dc->command = cmd; dc->command = cmd;
decoder_signal(dc); dc->Signal();
decoder_unlock(dc); dc->Unlock();
} }
bool bool
decoder_is_current_song(const struct decoder_control *dc, decoder_control::IsCurrentSong(const struct song *_song) const
const struct song *song)
{ {
assert(dc != NULL); assert(_song != NULL);
assert(song != NULL);
switch (dc->state) { switch (state) {
case DECODE_STATE_STOP: case DECODE_STATE_STOP:
case DECODE_STATE_ERROR: case DECODE_STATE_ERROR:
return false; return false;
case DECODE_STATE_START: case DECODE_STATE_START:
case DECODE_STATE_DECODE: case DECODE_STATE_DECODE:
return song_equals(dc->song, song); return song_equals(song, _song);
} }
assert(false); assert(false);
@ -126,99 +108,91 @@ decoder_is_current_song(const struct decoder_control *dc,
} }
void void
dc_start(struct decoder_control *dc, struct song *song, decoder_control::Start(struct song *_song,
unsigned start_ms, unsigned end_ms, unsigned _start_ms, unsigned _end_ms,
struct music_buffer *buffer, struct music_pipe *pipe) music_buffer *_buffer, music_pipe *_pipe)
{ {
assert(song != NULL); assert(_song != NULL);
assert(buffer != NULL); assert(buffer != NULL);
assert(pipe != NULL); assert(pipe != NULL);
assert(music_pipe_empty(pipe)); assert(music_pipe_empty(pipe));
if (dc->song != NULL) if (song != nullptr)
song_free(dc->song); song_free(song);
dc->song = song; song = _song;
dc->start_ms = start_ms; start_ms = _start_ms;
dc->end_ms = end_ms; end_ms = _end_ms;
dc->buffer = buffer; buffer = _buffer;
dc->pipe = pipe; pipe = _pipe;
dc_command(dc, DECODE_COMMAND_START);
dc_command(this, DECODE_COMMAND_START);
} }
void void
dc_stop(struct decoder_control *dc) decoder_control::Stop()
{ {
decoder_lock(dc); Lock();
if (dc->command != DECODE_COMMAND_NONE) if (command != DECODE_COMMAND_NONE)
/* Attempt to cancel the current command. If it's too /* Attempt to cancel the current command. If it's too
late and the decoder thread is already executing late and the decoder thread is already executing
the old command, we'll call STOP again in this the old command, we'll call STOP again in this
function (see below). */ function (see below). */
dc_command_locked(dc, DECODE_COMMAND_STOP); dc_command_locked(this, DECODE_COMMAND_STOP);
if (dc->state != DECODE_STATE_STOP && dc->state != DECODE_STATE_ERROR) if (state != DECODE_STATE_STOP && state != DECODE_STATE_ERROR)
dc_command_locked(dc, DECODE_COMMAND_STOP); dc_command_locked(this, DECODE_COMMAND_STOP);
decoder_unlock(dc); Unlock();
} }
bool bool
dc_seek(struct decoder_control *dc, double where) decoder_control::Seek(double where)
{ {
assert(dc->state != DECODE_STATE_START); assert(state != DECODE_STATE_START);
assert(where >= 0.0); assert(where >= 0.0);
if (dc->state == DECODE_STATE_STOP || if (state == DECODE_STATE_STOP ||
dc->state == DECODE_STATE_ERROR || !dc->seekable) state == DECODE_STATE_ERROR || !seekable)
return false; return false;
dc->seek_where = where; seek_where = where;
dc->seek_error = false; seek_error = false;
dc_command(dc, DECODE_COMMAND_SEEK); dc_command(this, DECODE_COMMAND_SEEK);
if (dc->seek_error) return !seek_error;
return false;
return true;
} }
void void
dc_quit(struct decoder_control *dc) decoder_control::Quit()
{ {
assert(dc->thread != NULL); assert(thread != nullptr);
dc->quit = true; quit = true;
dc_command_async(dc, DECODE_COMMAND_STOP); dc_command_async(this, DECODE_COMMAND_STOP);
g_thread_join(dc->thread); g_thread_join(thread);
dc->thread = NULL; thread = nullptr;
} }
void void
dc_mixramp_start(struct decoder_control *dc, char *mixramp_start) decoder_control::MixRampStart(char *_mixramp_start)
{ {
assert(dc != NULL); g_free(mixramp_start);
mixramp_start = _mixramp_start;
g_free(dc->mixramp_start);
dc->mixramp_start = mixramp_start;
} }
void void
dc_mixramp_end(struct decoder_control *dc, char *mixramp_end) decoder_control::MixRampEnd(char *_mixramp_end)
{ {
assert(dc != NULL); g_free(mixramp_end);
mixramp_end = _mixramp_end;
g_free(dc->mixramp_end);
dc->mixramp_end = mixramp_end;
} }
void void
dc_mixramp_prev_end(struct decoder_control *dc, char *mixramp_prev_end) decoder_control::MixRampPrevEnd(char *_mixramp_prev_end)
{ {
assert(dc != NULL); g_free(mixramp_prev_end);
mixramp_prev_end = _mixramp_prev_end;
g_free(dc->mixramp_prev_end);
dc->mixramp_prev_end = mixramp_prev_end;
} }

View File

@ -130,6 +130,41 @@ struct decoder_control {
char *mixramp_end; char *mixramp_end;
char *mixramp_prev_end; char *mixramp_prev_end;
decoder_control();
~decoder_control();
/**
* Locks the object.
*/
void Lock() const {
g_mutex_lock(mutex);
}
/**
* Unlocks the object.
*/
void Unlock() const {
g_mutex_unlock(mutex);
}
/**
* Signals the object. This function is only valid in the
* player thread. The object should be locked prior to
* calling this function.
*/
void Signal() {
g_cond_signal(cond);
}
/**
* Waits for a signal on the #decoder_control object. This function
* is only valid in the decoder thread. The object must be locked
* prior to calling this function.
*/
void Wait() {
g_cond_wait(cond, mutex);
}
/** /**
* Waits for a signal from the decoder thread. This object * Waits for a signal from the decoder thread. This object
* must be locked prior to calling this function. This method * must be locked prior to calling this function. This method
@ -138,211 +173,123 @@ struct decoder_control {
void WaitForDecoder() { void WaitForDecoder() {
g_cond_wait(client_cond, mutex); g_cond_wait(client_cond, mutex);
} }
bool IsIdle() const {
return state == DECODE_STATE_STOP ||
state == DECODE_STATE_ERROR;
}
gcc_pure
bool LockIsIdle() const {
Lock();
bool result = IsIdle();
Unlock();
return result;
}
bool IsStarting() const {
return state == DECODE_STATE_START;
}
gcc_pure
bool LockIsStarting() const {
Lock();
bool result = IsStarting();
Unlock();
return result;
}
bool HasFailed() const {
assert(command == DECODE_COMMAND_NONE);
return state == DECODE_STATE_ERROR;
}
gcc_pure
bool LockHasFailed() const {
Lock();
bool result = HasFailed();
Unlock();
return result;
}
/**
* Checks whether an error has occurred, and if so, returns a newly
* allocated copy of the #GError object.
*
* Caller must lock the object.
*/
GError *GetError() const {
assert(command == DECODE_COMMAND_NONE);
assert(state != DECODE_STATE_ERROR || error != nullptr);
return state == DECODE_STATE_ERROR
? g_error_copy(error)
: nullptr;
}
/**
* Like dc_get_error(), but locks and unlocks the object.
*/
GError *LockGetError() const {
Lock();
GError *result = GetError();
Unlock();
return result;
}
/**
* Clear the error condition and free the #GError object (if any).
*
* Caller must lock the object.
*/
void ClearError() {
if (state == DECODE_STATE_ERROR) {
g_error_free(error);
state = DECODE_STATE_STOP;
}
}
/**
* Check if the specified song is currently being decoded. If the
* decoder is not running currently (or being started), then this
* function returns false in any case.
*
* Caller must lock the object.
*/
gcc_pure
bool IsCurrentSong(const struct song *_song) const;
gcc_pure
bool LockIsCurrentSong(const struct song *_song) const {
Lock();
const bool result = IsCurrentSong(_song);
Unlock();
return result;
}
/**
* Start the decoder.
*
* @param song the song to be decoded; the given instance will be
* owned and freed by the decoder
* @param start_ms see #decoder_control
* @param end_ms see #decoder_control
* @param pipe the pipe which receives the decoded chunks (owned by
* the caller)
*/
void Start(struct song *song, unsigned start_ms, unsigned end_ms,
music_buffer *buffer, music_pipe *pipe);
void Stop();
bool Seek(double where);
void Quit();
void MixRampStart(char *_mixramp_start);
void MixRampEnd(char *_mixramp_end);
void MixRampPrevEnd(char *_mixramp_prev_end);
}; };
G_GNUC_MALLOC
struct decoder_control *
dc_new();
void
dc_free(struct decoder_control *dc);
/**
* Locks the #decoder_control object.
*/
static inline void
decoder_lock(struct decoder_control *dc)
{
g_mutex_lock(dc->mutex);
}
/**
* Unlocks the #decoder_control object.
*/
static inline void
decoder_unlock(struct decoder_control *dc)
{
g_mutex_unlock(dc->mutex);
}
/**
* Waits for a signal on the #decoder_control object. This function
* is only valid in the decoder thread. The object must be locked
* prior to calling this function.
*/
static inline void
decoder_wait(struct decoder_control *dc)
{
g_cond_wait(dc->cond, dc->mutex);
}
/**
* Signals the #decoder_control object. This function is only valid
* in the player thread. The object should be locked prior to calling
* this function.
*/
static inline void
decoder_signal(struct decoder_control *dc)
{
g_cond_signal(dc->cond);
}
static inline bool
decoder_is_idle(const struct decoder_control *dc)
{
return dc->state == DECODE_STATE_STOP ||
dc->state == DECODE_STATE_ERROR;
}
static inline bool
decoder_is_starting(const struct decoder_control *dc)
{
return dc->state == DECODE_STATE_START;
}
static inline bool
decoder_has_failed(const struct decoder_control *dc)
{
assert(dc->command == DECODE_COMMAND_NONE);
return dc->state == DECODE_STATE_ERROR;
}
/**
* Checks whether an error has occurred, and if so, returns a newly
* allocated copy of the #GError object.
*
* Caller must lock the object.
*/
static inline GError *
dc_get_error(const struct decoder_control *dc)
{
assert(dc != NULL);
assert(dc->command == DECODE_COMMAND_NONE);
assert(dc->state != DECODE_STATE_ERROR || dc->error != NULL);
return dc->state == DECODE_STATE_ERROR
? g_error_copy(dc->error)
: NULL;
}
/**
* Like dc_get_error(), but locks and unlocks the object.
*/
static inline GError *
dc_lock_get_error(struct decoder_control *dc)
{
decoder_lock(dc);
GError *error = dc_get_error(dc);
decoder_unlock(dc);
return error;
}
/**
* Clear the error condition and free the #GError object (if any).
*
* Caller must lock the object.
*/
static inline void
dc_clear_error(struct decoder_control *dc)
{
if (dc->state == DECODE_STATE_ERROR) {
g_error_free(dc->error);
dc->state = DECODE_STATE_STOP;
}
}
static inline bool
decoder_lock_is_idle(struct decoder_control *dc)
{
bool ret;
decoder_lock(dc);
ret = decoder_is_idle(dc);
decoder_unlock(dc);
return ret;
}
static inline bool
decoder_lock_is_starting(struct decoder_control *dc)
{
bool ret;
decoder_lock(dc);
ret = decoder_is_starting(dc);
decoder_unlock(dc);
return ret;
}
static inline bool
decoder_lock_has_failed(struct decoder_control *dc)
{
bool ret;
decoder_lock(dc);
ret = decoder_has_failed(dc);
decoder_unlock(dc);
return ret;
}
/**
* Check if the specified song is currently being decoded. If the
* decoder is not running currently (or being started), then this
* function returns false in any case.
*
* Caller must lock the object.
*/
gcc_pure
bool
decoder_is_current_song(const struct decoder_control *dc,
const struct song *song);
gcc_pure
static inline bool
decoder_lock_is_current_song(struct decoder_control *dc,
const struct song *song)
{
decoder_lock(dc);
const bool result = decoder_is_current_song(dc, song);
decoder_unlock(dc);
return result;
}
/**
* Start the decoder.
*
* @param the decoder
* @param song the song to be decoded; the given instance will be
* owned and freed by the decoder
* @param start_ms see #decoder_control
* @param end_ms see #decoder_control
* @param pipe the pipe which receives the decoded chunks (owned by
* the caller)
*/
void
dc_start(struct decoder_control *dc, struct song *song,
unsigned start_ms, unsigned end_ms,
struct music_buffer *buffer, struct music_pipe *pipe);
void
dc_stop(struct decoder_control *dc);
bool
dc_seek(struct decoder_control *dc, double where);
void
dc_quit(struct decoder_control *dc);
void
dc_mixramp_start(struct decoder_control *dc, char *mixramp_start);
void
dc_mixramp_end(struct decoder_control *dc, char *mixramp_end);
void
dc_mixramp_prev_end(struct decoder_control *dc, char *mixramp_prev_end);
#endif #endif

View File

@ -57,7 +57,7 @@ need_chunks(struct decoder_control *dc, bool do_wait)
return dc->command; return dc->command;
if (do_wait) { if (do_wait) {
decoder_wait(dc); dc->Wait();
g_cond_signal(dc->client_cond); g_cond_signal(dc->client_cond);
return dc->command; return dc->command;
@ -89,9 +89,9 @@ decoder_get_chunk(struct decoder *decoder)
return decoder->chunk; return decoder->chunk;
} }
decoder_lock(dc); dc->Lock();
cmd = need_chunks(dc, true); cmd = need_chunks(dc, true);
decoder_unlock(dc); dc->Unlock();
} while (cmd == DECODE_COMMAND_NONE); } while (cmd == DECODE_COMMAND_NONE);
return NULL; return NULL;

View File

@ -91,18 +91,18 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri)
/* wait for the input stream to become ready; its metadata /* wait for the input stream to become ready; its metadata
will be available then */ will be available then */
decoder_lock(dc); dc->Lock();
input_stream_update(is); input_stream_update(is);
while (!is->ready && while (!is->ready &&
dc->command != DECODE_COMMAND_STOP) { dc->command != DECODE_COMMAND_STOP) {
decoder_wait(dc); dc->Wait();
input_stream_update(is); input_stream_update(is);
} }
if (!input_stream_check(is, &error)) { if (!input_stream_check(is, &error)) {
decoder_unlock(dc); dc->Unlock();
g_warning("%s", error->message); g_warning("%s", error->message);
g_error_free(error); g_error_free(error);
@ -110,7 +110,7 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri)
return NULL; return NULL;
} }
decoder_unlock(dc); dc->Unlock();
return is; return is;
} }
@ -137,11 +137,11 @@ decoder_stream_decode(const struct decoder_plugin *plugin,
/* rewind the stream, so each plugin gets a fresh start */ /* rewind the stream, so each plugin gets a fresh start */
input_stream_seek(input_stream, 0, SEEK_SET, NULL); input_stream_seek(input_stream, 0, SEEK_SET, NULL);
decoder_unlock(decoder->dc); decoder->dc->Unlock();
decoder_plugin_stream_decode(plugin, decoder, input_stream); decoder_plugin_stream_decode(plugin, decoder, input_stream);
decoder_lock(decoder->dc); decoder->dc->Lock();
assert(decoder->dc->state == DECODE_STATE_START || assert(decoder->dc->state == DECODE_STATE_START ||
decoder->dc->state == DECODE_STATE_DECODE); decoder->dc->state == DECODE_STATE_DECODE);
@ -167,11 +167,11 @@ decoder_file_decode(const struct decoder_plugin *plugin,
if (decoder->dc->command == DECODE_COMMAND_STOP) if (decoder->dc->command == DECODE_COMMAND_STOP)
return true; return true;
decoder_unlock(decoder->dc); decoder->dc->Unlock();
decoder_plugin_file_decode(plugin, decoder, path); decoder_plugin_file_decode(plugin, decoder, path);
decoder_lock(decoder->dc); decoder->dc->Lock();
assert(decoder->dc->state == DECODE_STATE_START || assert(decoder->dc->state == DECODE_STATE_START ||
decoder->dc->state == DECODE_STATE_DECODE); decoder->dc->state == DECODE_STATE_DECODE);
@ -280,15 +280,15 @@ decoder_run_stream(struct decoder *decoder, const char *uri)
struct input_stream *input_stream; struct input_stream *input_stream;
bool success; bool success;
decoder_unlock(dc); dc->Unlock();
input_stream = decoder_input_stream_open(dc, uri); input_stream = decoder_input_stream_open(dc, uri);
if (input_stream == NULL) { if (input_stream == NULL) {
decoder_lock(dc); dc->Lock();
return false; return false;
} }
decoder_lock(dc); dc->Lock();
GSList *tried = NULL; GSList *tried = NULL;
@ -305,9 +305,9 @@ decoder_run_stream(struct decoder *decoder, const char *uri)
g_slist_free(tried); g_slist_free(tried);
decoder_unlock(dc); dc->Unlock();
input_stream_close(input_stream); input_stream_close(input_stream);
decoder_lock(dc); dc->Lock();
return success; return success;
} }
@ -337,18 +337,18 @@ decoder_run_file(struct decoder *decoder, const char *path_fs)
if (suffix == NULL) if (suffix == NULL)
return false; return false;
decoder_unlock(dc); dc->Unlock();
decoder_load_replay_gain(decoder, path_fs); decoder_load_replay_gain(decoder, path_fs);
while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != NULL) { while ((plugin = decoder_plugin_from_suffix(suffix, plugin)) != NULL) {
if (plugin->file_decode != NULL) { if (plugin->file_decode != NULL) {
decoder_lock(dc); dc->Lock();
if (decoder_file_decode(plugin, decoder, path_fs)) if (decoder_file_decode(plugin, decoder, path_fs))
return true; return true;
decoder_unlock(dc); dc->Unlock();
} else if (plugin->stream_decode != NULL) { } else if (plugin->stream_decode != NULL) {
struct input_stream *input_stream; struct input_stream *input_stream;
bool success; bool success;
@ -357,23 +357,23 @@ decoder_run_file(struct decoder *decoder, const char *path_fs)
if (input_stream == NULL) if (input_stream == NULL)
continue; continue;
decoder_lock(dc); dc->Lock();
success = decoder_stream_decode(plugin, decoder, success = decoder_stream_decode(plugin, decoder,
input_stream); input_stream);
decoder_unlock(dc); dc->Unlock();
input_stream_close(input_stream); input_stream_close(input_stream);
if (success) { if (success) {
decoder_lock(dc); dc->Lock();
return true; return true;
} }
} }
} }
decoder_lock(dc); dc->Lock();
return false; return false;
} }
@ -394,14 +394,14 @@ decoder_run_song(struct decoder_control *dc,
? decoder_run_file(&decoder, uri) ? decoder_run_file(&decoder, uri)
: decoder_run_stream(&decoder, uri); : decoder_run_stream(&decoder, uri);
decoder_unlock(dc); dc->Unlock();
/* flush the last chunk */ /* flush the last chunk */
if (decoder.chunk != NULL) if (decoder.chunk != NULL)
decoder_flush_chunk(&decoder); decoder_flush_chunk(&decoder);
decoder_lock(dc); dc->Lock();
if (ret) if (ret)
dc->state = DECODE_STATE_STOP; dc->state = DECODE_STATE_STOP;
@ -424,7 +424,7 @@ decoder_run_song(struct decoder_control *dc,
static void static void
decoder_run(struct decoder_control *dc) decoder_run(struct decoder_control *dc)
{ {
dc_clear_error(dc); dc->ClearError();
const struct song *song = dc->song; const struct song *song = dc->song;
char *uri; char *uri;
@ -455,7 +455,7 @@ decoder_task(gpointer arg)
{ {
struct decoder_control *dc = (struct decoder_control *)arg; struct decoder_control *dc = (struct decoder_control *)arg;
decoder_lock(dc); dc->Lock();
do { do {
assert(dc->state == DECODE_STATE_STOP || assert(dc->state == DECODE_STATE_STOP ||
@ -463,8 +463,8 @@ decoder_task(gpointer arg)
switch (dc->command) { switch (dc->command) {
case DECODE_COMMAND_START: case DECODE_COMMAND_START:
dc_mixramp_start(dc, NULL); dc->MixRampStart(nullptr);
dc_mixramp_prev_end(dc, dc->mixramp_end); dc->MixRampPrevEnd(dc->mixramp_end);
dc->mixramp_end = NULL; /* Don't free, it's copied above. */ dc->mixramp_end = NULL; /* Don't free, it's copied above. */
dc->replay_gain_prev_db = dc->replay_gain_db; dc->replay_gain_prev_db = dc->replay_gain_db;
dc->replay_gain_db = 0; dc->replay_gain_db = 0;
@ -480,12 +480,12 @@ decoder_task(gpointer arg)
break; break;
case DECODE_COMMAND_NONE: case DECODE_COMMAND_NONE:
decoder_wait(dc); dc->Wait();
break; break;
} }
} while (dc->command != DECODE_COMMAND_NONE || !dc->quit); } while (dc->command != DECODE_COMMAND_NONE || !dc->quit);
decoder_unlock(dc); dc->Unlock();
return NULL; return NULL;
} }

View File

@ -176,9 +176,9 @@ player_dc_start(struct player *player, struct music_pipe *pipe)
if (pc->command == PLAYER_COMMAND_SEEK) if (pc->command == PLAYER_COMMAND_SEEK)
start_ms += (unsigned)(pc->seek_where * 1000); start_ms += (unsigned)(pc->seek_where * 1000);
dc_start(dc, song_dup_detached(pc->next_song), dc->Start(song_dup_detached(pc->next_song),
start_ms, pc->next_song->end_ms, start_ms, pc->next_song->end_ms,
player_buffer, pipe); player_buffer, pipe);
} }
/** /**
@ -217,7 +217,7 @@ player_dc_stop(struct player *player)
{ {
struct decoder_control *dc = player->dc; struct decoder_control *dc = player->dc;
dc_stop(dc); dc->Stop();
if (dc->pipe != NULL) { if (dc->pipe != NULL) {
/* clear and free the decoder pipe */ /* clear and free the decoder pipe */
@ -249,7 +249,7 @@ player_wait_for_decoder(struct player *player)
player->queued = false; player->queued = false;
GError *error = dc_lock_get_error(dc); GError *error = dc->LockGetError();
if (error != NULL) { if (error != NULL) {
pc->Lock(); pc->Lock();
pc->SetError(PLAYER_ERROR_DECODER, error); pc->SetError(PLAYER_ERROR_DECODER, error);
@ -369,22 +369,22 @@ player_check_decoder_startup(struct player *player)
assert(player->decoder_starting); assert(player->decoder_starting);
decoder_lock(dc); dc->Lock();
GError *error = dc_get_error(dc); GError *error = dc->GetError();
if (error != NULL) { if (error != NULL) {
/* the decoder failed */ /* the decoder failed */
decoder_unlock(dc); dc->Unlock();
pc->Lock(); pc->Lock();
pc->SetError(PLAYER_ERROR_DECODER, error); pc->SetError(PLAYER_ERROR_DECODER, error);
pc->Unlock(); pc->Unlock();
return false; return false;
} else if (!decoder_is_starting(dc)) { } else if (!dc->IsStarting()) {
/* the decoder is ready and ok */ /* the decoder is ready and ok */
decoder_unlock(dc); dc->Unlock();
if (player->output_open && if (player->output_open &&
!audio_output_all_wait(pc, 1)) !audio_output_all_wait(pc, 1))
@ -414,7 +414,7 @@ player_check_decoder_startup(struct player *player)
/* the decoder is not yet ready; wait /* the decoder is not yet ready; wait
some more */ some more */
dc->WaitForDecoder(); dc->WaitForDecoder();
decoder_unlock(dc); dc->Unlock();
return true; return true;
} }
@ -480,7 +480,7 @@ static bool player_seek_decoder(struct player *player)
const unsigned start_ms = song->start_ms; const unsigned start_ms = song->start_ms;
if (!decoder_lock_is_current_song(dc, song)) { if (!dc->LockIsCurrentSong(song)) {
/* the decoder is already decoding the "next" song - /* the decoder is already decoding the "next" song -
stop it and start the previous song again */ stop it and start the previous song again */
@ -529,7 +529,7 @@ static bool player_seek_decoder(struct player *player)
if (where < 0.0) if (where < 0.0)
where = 0.0; where = 0.0;
if (!dc_seek(dc, where + start_ms / 1000.0)) { if (!dc->Seek(where + start_ms / 1000.0)) {
/* decoder failure */ /* decoder failure */
player_command_finished(pc); player_command_finished(pc);
return false; return false;
@ -782,19 +782,19 @@ play_next_chunk(struct player *player)
} else { } else {
/* there are not enough decoded chunks yet */ /* there are not enough decoded chunks yet */
decoder_lock(dc); dc->Lock();
if (decoder_is_idle(dc)) { if (dc->IsIdle()) {
/* the decoder isn't running, abort /* the decoder isn't running, abort
cross fading */ cross fading */
decoder_unlock(dc); dc->Unlock();
player->xfade = XFADE_DISABLED; player->xfade = XFADE_DISABLED;
} else { } else {
/* wait for the decoder */ /* wait for the decoder */
decoder_signal(dc); dc->Signal();
dc->WaitForDecoder(); dc->WaitForDecoder();
decoder_unlock(dc); dc->Unlock();
return true; return true;
} }
@ -840,12 +840,12 @@ play_next_chunk(struct player *player)
/* this formula should prevent that the decoder gets woken up /* this formula should prevent that the decoder gets woken up
with each chunk; it is more efficient to make it decode a with each chunk; it is more efficient to make it decode a
larger block at a time */ larger block at a time */
decoder_lock(dc); dc->Lock();
if (!decoder_is_idle(dc) && if (!dc->IsIdle() &&
music_pipe_size(dc->pipe) <= (pc->buffered_before_play + music_pipe_size(dc->pipe) <= (pc->buffered_before_play +
music_buffer_size(player_buffer) * 3) / 4) music_buffer_size(player_buffer) * 3) / 4)
decoder_signal(dc); dc->Signal();
decoder_unlock(dc); dc->Unlock();
return true; return true;
} }
@ -940,7 +940,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
prevent stuttering on slow machines */ prevent stuttering on slow machines */
if (music_pipe_size(player.pipe) < pc->buffered_before_play && if (music_pipe_size(player.pipe) < pc->buffered_before_play &&
!decoder_lock_is_idle(dc)) { !dc->LockIsIdle()) {
/* not enough decoded buffer space yet */ /* not enough decoded buffer space yet */
if (!player.paused && if (!player.paused &&
@ -949,10 +949,10 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
!player_send_silence(&player)) !player_send_silence(&player))
break; break;
decoder_lock(dc); dc->Lock();
/* XXX race condition: check decoder again */ /* XXX race condition: check decoder again */
dc->WaitForDecoder(); dc->WaitForDecoder();
decoder_unlock(dc); dc->Unlock();
pc->Lock(); pc->Lock();
continue; continue;
} else { } else {
@ -979,7 +979,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
*/ */
#endif #endif
if (decoder_lock_is_idle(dc) && player.queued && if (dc->LockIsIdle() && player.queued &&
dc->pipe == player.pipe) { dc->pipe == player.pipe) {
/* the decoder has finished the current song; /* the decoder has finished the current song;
make it decode the next song */ make it decode the next song */
@ -994,7 +994,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
!pc->border_pause && !pc->border_pause &&
player_dc_at_next_song(&player) && player_dc_at_next_song(&player) &&
player.xfade == XFADE_UNKNOWN && player.xfade == XFADE_UNKNOWN &&
!decoder_lock_is_starting(dc)) { !dc->LockIsStarting()) {
/* enable cross fading in this song? if yes, /* enable cross fading in this song? if yes,
calculate how many chunks will be required calculate how many chunks will be required
for it */ for it */
@ -1042,7 +1042,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
if (!player_song_border(&player)) if (!player_song_border(&player))
break; break;
} else if (decoder_lock_is_idle(dc)) { } else if (dc->LockIsIdle()) {
/* check the size of the pipe again, because /* check the size of the pipe again, because
the decoder thread may have added something the decoder thread may have added something
since we last checked */ since we last checked */
@ -1096,7 +1096,7 @@ player_task(gpointer arg)
{ {
struct player_control *pc = (struct player_control *)arg; struct player_control *pc = (struct player_control *)arg;
struct decoder_control *dc = dc_new(); struct decoder_control *dc = new decoder_control();
decoder_thread_start(dc); decoder_thread_start(dc);
player_buffer = music_buffer_new(pc->buffer_chunks); player_buffer = music_buffer_new(pc->buffer_chunks);
@ -1156,8 +1156,8 @@ player_task(gpointer arg)
case PLAYER_COMMAND_EXIT: case PLAYER_COMMAND_EXIT:
pc->Unlock(); pc->Unlock();
dc_quit(dc); dc->Quit();
dc_free(dc); delete dc;
audio_output_all_close(); audio_output_all_close();
music_buffer_free(player_buffer); music_buffer_free(player_buffer);