Commit 32799fef authored by Max Kellermann's avatar Max Kellermann

DecoderControl: move functions into the class

parent e1b03b4a
...@@ -64,10 +64,10 @@ decoder_initialized(struct decoder *decoder, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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);
} }
...@@ -27,46 +27,30 @@ ...@@ -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 ...@@ -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, ...@@ -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);
song = _song;
start_ms = _start_ms;
end_ms = _end_ms;
buffer = _buffer;
pipe = _pipe;
dc->song = song; dc_command(this, DECODE_COMMAND_START);
dc->start_ms = start_ms;
dc->end_ms = end_ms;
dc->buffer = buffer;
dc->pipe = pipe;
dc_command(dc, 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 false;
return true; return !seek_error;
} }
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;
} }
...@@ -130,6 +130,41 @@ struct decoder_control { ...@@ -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 { ...@@ -138,211 +173,123 @@ struct decoder_control {
void WaitForDecoder() { void WaitForDecoder() {
g_cond_wait(client_cond, mutex); g_cond_wait(client_cond, mutex);
} }
};
G_GNUC_MALLOC
struct decoder_control *
dc_new();
void bool IsIdle() const {
dc_free(struct decoder_control *dc); return state == DECODE_STATE_STOP ||
state == DECODE_STATE_ERROR;
/**
* 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 gcc_pure
decoder_lock_is_idle(struct decoder_control *dc) bool LockIsIdle() const {
{ Lock();
bool ret; bool result = IsIdle();
Unlock();
return result;
}
decoder_lock(dc); bool IsStarting() const {
ret = decoder_is_idle(dc); return state == DECODE_STATE_START;
decoder_unlock(dc); }
return ret; gcc_pure
} bool LockIsStarting() const {
Lock();
bool result = IsStarting();
Unlock();
return result;
}
static inline bool bool HasFailed() const {
decoder_lock_is_starting(struct decoder_control *dc) assert(command == DECODE_COMMAND_NONE);
{
bool ret;
decoder_lock(dc); return state == DECODE_STATE_ERROR;
ret = decoder_is_starting(dc); }
decoder_unlock(dc);
return ret; gcc_pure
} bool LockHasFailed() const {
Lock();
bool result = HasFailed();
Unlock();
return result;
}
static inline bool /**
decoder_lock_has_failed(struct decoder_control *dc) * Checks whether an error has occurred, and if so, returns a newly
{ * allocated copy of the #GError object.
bool ret; *
* Caller must lock the object.
*/
GError *GetError() const {
assert(command == DECODE_COMMAND_NONE);
assert(state != DECODE_STATE_ERROR || error != nullptr);
decoder_lock(dc); return state == DECODE_STATE_ERROR
ret = decoder_has_failed(dc); ? g_error_copy(error)
decoder_unlock(dc); : nullptr;
}
return ret; /**
} * Like dc_get_error(), but locks and unlocks the object.
*/
GError *LockGetError() const {
Lock();
GError *result = GetError();
Unlock();
return result;
}
/** /**
* Check if the specified song is currently being decoded. If the * Clear the error condition and free the #GError object (if any).
* decoder is not running currently (or being started), then this *
* function returns false in any case. * Caller must lock the object.
* */
* Caller must lock the object. void ClearError() {
*/ if (state == DECODE_STATE_ERROR) {
gcc_pure g_error_free(error);
bool state = DECODE_STATE_STOP;
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); * 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;
}
bool /**
dc_seek(struct decoder_control *dc, double where); * 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 void Stop();
dc_quit(struct decoder_control *dc);
void bool Seek(double where);
dc_mixramp_start(struct decoder_control *dc, char *mixramp_start);
void void Quit();
dc_mixramp_end(struct decoder_control *dc, char *mixramp_end);
void void MixRampStart(char *_mixramp_start);
dc_mixramp_prev_end(struct decoder_control *dc, char *mixramp_prev_end); void MixRampEnd(char *_mixramp_end);
void MixRampPrevEnd(char *_mixramp_prev_end);
};
#endif #endif
...@@ -57,7 +57,7 @@ need_chunks(struct decoder_control *dc, bool do_wait) ...@@ -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) ...@@ -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;
......
...@@ -91,18 +91,18 @@ decoder_input_stream_open(struct decoder_control *dc, const char *uri) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
...@@ -176,9 +176,9 @@ player_dc_start(struct player *player, struct music_pipe *pipe) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment