aboutsummaryrefslogtreecommitdiffstats
path: root/src/decoder
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/decoder_api.c142
-rw-r--r--src/decoder_control.c121
-rw-r--r--src/decoder_control.h94
-rw-r--r--src/decoder_internal.c35
-rw-r--r--src/decoder_internal.h2
-rw-r--r--src/decoder_thread.c125
-rw-r--r--src/decoder_thread.h5
7 files changed, 284 insertions, 240 deletions
diff --git a/src/decoder_api.c b/src/decoder_api.c
index 070151a67..f1ce0f5f7 100644
--- a/src/decoder_api.c
+++ b/src/decoder_api.c
@@ -37,12 +37,15 @@
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "decoder"
-void decoder_initialized(G_GNUC_UNUSED struct decoder * decoder,
- const struct audio_format *audio_format,
- bool seekable, float total_time)
+void
+decoder_initialized(struct decoder *decoder,
+ const struct audio_format *audio_format,
+ bool seekable, float total_time)
{
- assert(dc.state == DECODE_STATE_START);
- assert(dc.pipe != NULL);
+ struct decoder_control *dc = decoder->dc;
+
+ assert(dc->state == DECODE_STATE_START);
+ assert(dc->pipe != NULL);
assert(decoder != NULL);
assert(decoder->stream_tag == NULL);
assert(decoder->decoder_tag == NULL);
@@ -51,86 +54,98 @@ void decoder_initialized(G_GNUC_UNUSED struct decoder * decoder,
assert(audio_format_defined(audio_format));
assert(audio_format_valid(audio_format));
- dc.in_audio_format = *audio_format;
- getOutputAudioFormat(audio_format, &dc.out_audio_format);
+ dc->in_audio_format = *audio_format;
+ getOutputAudioFormat(audio_format, &dc->out_audio_format);
- dc.seekable = seekable;
- dc.total_time = total_time;
+ dc->seekable = seekable;
+ dc->total_time = total_time;
- decoder_lock();
- dc.state = DECODE_STATE_DECODE;
- decoder_unlock();
+ decoder_lock(dc);
+ dc->state = DECODE_STATE_DECODE;
+ decoder_unlock(dc);
player_lock_signal();
g_debug("audio_format=%u:%u:%u, seekable=%s",
- dc.in_audio_format.sample_rate, dc.in_audio_format.bits,
- dc.in_audio_format.channels,
+ dc->in_audio_format.sample_rate,
+ dc->in_audio_format.bits,
+ dc->in_audio_format.channels,
seekable ? "true" : "false");
- if (!audio_format_equals(&dc.in_audio_format, &dc.out_audio_format))
+ if (!audio_format_equals(&dc->in_audio_format,
+ &dc->out_audio_format))
g_debug("converting to %u:%u:%u",
- dc.out_audio_format.sample_rate,
- dc.out_audio_format.bits,
- dc.out_audio_format.channels);
+ dc->out_audio_format.sample_rate,
+ dc->out_audio_format.bits,
+ dc->out_audio_format.channels);
}
char *decoder_get_uri(G_GNUC_UNUSED struct decoder *decoder)
{
- assert(dc.pipe != NULL);
+ const struct decoder_control *dc = decoder->dc;
+
+ assert(dc->pipe != NULL);
- return song_get_uri(dc.current_song);
+ return song_get_uri(dc->current_song);
}
enum decoder_command decoder_get_command(G_GNUC_UNUSED struct decoder * decoder)
{
- assert(dc.pipe != NULL);
+ const struct decoder_control *dc = decoder->dc;
+
+ assert(dc->pipe != NULL);
- return dc.command;
+ return dc->command;
}
void decoder_command_finished(G_GNUC_UNUSED struct decoder * decoder)
{
- decoder_lock();
+ struct decoder_control *dc = decoder->dc;
- assert(dc.command != DECODE_COMMAND_NONE);
- assert(dc.command != DECODE_COMMAND_SEEK ||
- dc.seek_error || decoder->seeking);
- assert(dc.pipe != NULL);
+ decoder_lock(dc);
- if (dc.command == DECODE_COMMAND_SEEK) {
+ assert(dc->command != DECODE_COMMAND_NONE);
+ assert(dc->command != DECODE_COMMAND_SEEK ||
+ dc->seek_error || decoder->seeking);
+ assert(dc->pipe != NULL);
+
+ if (dc->command == DECODE_COMMAND_SEEK) {
/* delete frames from the old song position */
if (decoder->chunk != NULL) {
- music_buffer_return(dc.buffer, decoder->chunk);
+ music_buffer_return(dc->buffer, decoder->chunk);
decoder->chunk = NULL;
}
- music_pipe_clear(dc.pipe, dc.buffer);
+ music_pipe_clear(dc->pipe, dc->buffer);
}
- dc.command = DECODE_COMMAND_NONE;
- decoder_unlock();
+ dc->command = DECODE_COMMAND_NONE;
+ decoder_unlock(dc);
player_lock_signal();
}
double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder)
{
- assert(dc.command == DECODE_COMMAND_SEEK);
- assert(dc.pipe != NULL);
+ const struct decoder_control *dc = decoder->dc;
+
+ assert(dc->command == DECODE_COMMAND_SEEK);
+ assert(dc->pipe != NULL);
decoder->seeking = true;
- return dc.seek_where;
+ return dc->seek_where;
}
void decoder_seek_error(struct decoder * decoder)
{
- assert(dc.command == DECODE_COMMAND_SEEK);
- assert(dc.pipe != NULL);
+ struct decoder_control *dc = decoder->dc;
+
+ assert(dc->command == DECODE_COMMAND_SEEK);
+ assert(dc->pipe != NULL);
- dc.seek_error = true;
+ dc->seek_error = true;
decoder_command_finished(decoder);
}
@@ -138,11 +153,12 @@ size_t decoder_read(struct decoder *decoder,
struct input_stream *is,
void *buffer, size_t length)
{
+ const struct decoder_control *dc = decoder->dc;
size_t nbytes;
assert(decoder == NULL ||
- dc.state == DECODE_STATE_START ||
- dc.state == DECODE_STATE_DECODE);
+ dc->state == DECODE_STATE_START ||
+ dc->state == DECODE_STATE_DECODE);
assert(is != NULL);
assert(buffer != NULL);
@@ -155,9 +171,9 @@ size_t decoder_read(struct decoder *decoder,
/* ignore the SEEK command during initialization,
the plugin should handle that after it has
initialized successfully */
- (dc.command != DECODE_COMMAND_SEEK ||
- (dc.state != DECODE_STATE_START && !decoder->seeking)) &&
- dc.command != DECODE_COMMAND_NONE)
+ (dc->command != DECODE_COMMAND_SEEK ||
+ (dc->state != DECODE_STATE_START && !decoder->seeking)) &&
+ dc->command != DECODE_COMMAND_NONE)
return 0;
nbytes = input_stream_read(is, buffer, length);
@@ -191,8 +207,8 @@ do_send_tag(struct decoder *decoder, struct input_stream *is,
chunk = decoder_get_chunk(decoder, is);
if (chunk == NULL) {
- assert(dc.command != DECODE_COMMAND_NONE);
- return dc.command;
+ assert(decoder->dc->command != DECODE_COMMAND_NONE);
+ return decoder->dc->command;
}
chunk->tag = tag_dup(tag);
@@ -231,17 +247,18 @@ decoder_data(struct decoder *decoder,
float data_time, uint16_t bitRate,
struct replay_gain_info *replay_gain_info)
{
+ struct decoder_control *dc = decoder->dc;
const char *data = _data;
GError *error = NULL;
enum decoder_command cmd;
- assert(dc.state == DECODE_STATE_DECODE);
- assert(dc.pipe != NULL);
- assert(length % audio_format_frame_size(&dc.in_audio_format) == 0);
+ assert(dc->state == DECODE_STATE_DECODE);
+ assert(dc->pipe != NULL);
+ assert(length % audio_format_frame_size(&dc->in_audio_format) == 0);
- decoder_lock();
- cmd = dc.command;
- decoder_unlock();
+ decoder_lock(dc);
+ cmd = dc->command;
+ decoder_unlock(dc);
if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
length == 0)
@@ -266,10 +283,10 @@ decoder_data(struct decoder *decoder,
return cmd;
}
- if (!audio_format_equals(&dc.in_audio_format, &dc.out_audio_format)) {
+ if (!audio_format_equals(&dc->in_audio_format, &dc->out_audio_format)) {
data = pcm_convert(&decoder->conv_state,
- &dc.in_audio_format, data, length,
- &dc.out_audio_format, &length,
+ &dc->in_audio_format, data, length,
+ &dc->out_audio_format, &length,
&error);
if (data == NULL) {
/* the PCM conversion has failed - stop
@@ -288,11 +305,11 @@ decoder_data(struct decoder *decoder,
chunk = decoder_get_chunk(decoder, is);
if (chunk == NULL) {
- assert(dc.command != DECODE_COMMAND_NONE);
- return dc.command;
+ assert(dc->command != DECODE_COMMAND_NONE);
+ return dc->command;
}
- dest = music_chunk_write(chunk, &dc.out_audio_format,
+ dest = music_chunk_write(chunk, &dc->out_audio_format,
data_time, bitRate, &nbytes);
if (dest == NULL) {
/* the chunk is full, flush it */
@@ -314,13 +331,13 @@ decoder_data(struct decoder *decoder,
if (replay_gain_mode != REPLAY_GAIN_OFF)
replay_gain_apply(replay_gain_info, dest, nbytes,
- &dc.out_audio_format);
+ &dc->out_audio_format);
else if (normalizationEnabled)
- normalizeData(dest, nbytes, &dc.out_audio_format);
+ normalizeData(dest, nbytes, &dc->out_audio_format);
/* expand the music pipe chunk */
- full = music_chunk_expand(chunk, &dc.out_audio_format, nbytes);
+ full = music_chunk_expand(chunk, &dc->out_audio_format, nbytes);
if (full) {
/* the chunk is full, flush it */
decoder_flush_chunk(decoder);
@@ -338,10 +355,11 @@ enum decoder_command
decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is,
const struct tag *tag)
{
+ const struct decoder_control *dc = decoder->dc;
enum decoder_command cmd;
- assert(dc.state == DECODE_STATE_DECODE);
- assert(dc.pipe != NULL);
+ assert(dc->state == DECODE_STATE_DECODE);
+ assert(dc->pipe != NULL);
assert(tag != NULL);
/* save the tag */
diff --git a/src/decoder_control.c b/src/decoder_control.c
index d7f5808fc..10f576c5c 100644
--- a/src/decoder_control.c
+++ b/src/decoder_control.c
@@ -22,131 +22,134 @@
#include <assert.h>
-struct decoder_control dc;
-
-void dc_init(void)
+void
+dc_init(struct decoder_control *dc)
{
- dc.mutex = g_mutex_new();
- dc.cond = g_cond_new();
+ dc->thread = NULL;
+
+ dc->mutex = g_mutex_new();
+ dc->cond = g_cond_new();
- dc.state = DECODE_STATE_STOP;
- dc.command = DECODE_COMMAND_NONE;
+ dc->state = DECODE_STATE_STOP;
+ dc->command = DECODE_COMMAND_NONE;
}
-void dc_deinit(void)
+void
+dc_deinit(struct decoder_control *dc)
{
- g_cond_free(dc.cond);
- g_mutex_free(dc.mutex);
+ g_cond_free(dc->cond);
+ g_mutex_free(dc->mutex);
}
static void
-dc_command_wait_locked(void)
+dc_command_wait_locked(struct decoder_control *dc)
{
- while (dc.command != DECODE_COMMAND_NONE) {
- decoder_signal();
- player_wait_decoder();
+ while (dc->command != DECODE_COMMAND_NONE) {
+ decoder_signal(dc);
+ player_wait_decoder(dc);
}
}
void
-dc_command_wait(void)
+dc_command_wait(struct decoder_control *dc)
{
- decoder_lock();
- dc_command_wait_locked();
- decoder_unlock();
+ decoder_lock(dc);
+ dc_command_wait_locked(dc);
+ decoder_unlock(dc);
}
static void
-dc_command_locked(enum decoder_command cmd)
+dc_command_locked(struct decoder_control *dc, enum decoder_command cmd)
{
- dc.command = cmd;
- dc_command_wait_locked();
+ dc->command = cmd;
+ dc_command_wait_locked(dc);
}
static void
-dc_command(enum decoder_command cmd)
+dc_command(struct decoder_control *dc, enum decoder_command cmd)
{
- decoder_lock();
- dc_command_locked(cmd);
- decoder_unlock();
+ decoder_lock(dc);
+ dc_command_locked(dc, cmd);
+ decoder_unlock(dc);
}
-static void dc_command_async(enum decoder_command cmd)
+static void
+dc_command_async(struct decoder_control *dc, enum decoder_command cmd)
{
- decoder_lock();
+ decoder_lock(dc);
- dc.command = cmd;
- decoder_signal();
+ dc->command = cmd;
+ decoder_signal(dc);
- decoder_unlock();
+ decoder_unlock(dc);
}
void
-dc_start(struct song *song)
+dc_start(struct decoder_control *dc, struct song *song)
{
- assert(dc.pipe != NULL);
+ assert(dc->pipe != NULL);
assert(song != NULL);
- dc.next_song = song;
- dc_command(DECODE_COMMAND_START);
+ dc->next_song = song;
+ dc_command(dc, DECODE_COMMAND_START);
}
void
-dc_start_async(struct song *song)
+dc_start_async(struct decoder_control *dc, struct song *song)
{
- assert(dc.pipe != NULL);
+ assert(dc->pipe != NULL);
assert(song != NULL);
- dc.next_song = song;
- dc_command_async(DECODE_COMMAND_START);
+ dc->next_song = song;
+ dc_command_async(dc, DECODE_COMMAND_START);
}
void
-dc_stop(void)
+dc_stop(struct decoder_control *dc)
{
- decoder_lock();
+ decoder_lock(dc);
- if (dc.command != DECODE_COMMAND_NONE)
+ if (dc->command != DECODE_COMMAND_NONE)
/* Attempt to cancel the current command. If it's too
late and the decoder thread is already executing
the old command, we'll call STOP again in this
function (see below). */
- dc_command_locked(DECODE_COMMAND_STOP);
+ dc_command_locked(dc, DECODE_COMMAND_STOP);
- if (dc.state != DECODE_STATE_STOP && dc.state != DECODE_STATE_ERROR)
- dc_command_locked(DECODE_COMMAND_STOP);
+ if (dc->state != DECODE_STATE_STOP && dc->state != DECODE_STATE_ERROR)
+ dc_command_locked(dc, DECODE_COMMAND_STOP);
- decoder_unlock();
+ decoder_unlock(dc);
}
bool
-dc_seek(double where)
+dc_seek(struct decoder_control *dc, double where)
{
- assert(dc.state != DECODE_STATE_START);
+ assert(dc->state != DECODE_STATE_START);
assert(where >= 0.0);
- if (dc.state == DECODE_STATE_STOP ||
- dc.state == DECODE_STATE_ERROR || !dc.seekable)
+ if (dc->state == DECODE_STATE_STOP ||
+ dc->state == DECODE_STATE_ERROR || !dc->seekable)
return false;
- dc.seek_where = where;
- dc.seek_error = false;
- dc_command(DECODE_COMMAND_SEEK);
+ dc->seek_where = where;
+ dc->seek_error = false;
+ dc_command(dc, DECODE_COMMAND_SEEK);
- if (dc.seek_error)
+ if (dc->seek_error)
return false;
return true;
}
void
-dc_quit(void)
+dc_quit(struct decoder_control *dc)
{
- assert(dc.thread != NULL);
+ assert(dc->thread != NULL);
- dc.quit = true;
- dc_command_async(DECODE_COMMAND_STOP);
+ dc->quit = true;
+ dc_command_async(dc, DECODE_COMMAND_STOP);
- g_thread_join(dc.thread);
- dc.thread = NULL;
+ g_thread_join(dc->thread);
+ dc->thread = NULL;
}
diff --git a/src/decoder_control.h b/src/decoder_control.h
index cab6c69c7..d03c7a805 100644
--- a/src/decoder_control.h
+++ b/src/decoder_control.h
@@ -83,28 +83,28 @@ struct decoder_control {
struct music_pipe *pipe;
};
-extern struct decoder_control dc;
-
-void dc_init(void);
+void
+dc_init(struct decoder_control *dc);
-void dc_deinit(void);
+void
+dc_deinit(struct decoder_control *dc);
/**
* Locks the #decoder_control object.
*/
static inline void
-decoder_lock(void)
+decoder_lock(struct decoder_control *dc)
{
- g_mutex_lock(dc.mutex);
+ g_mutex_lock(dc->mutex);
}
/**
* Unlocks the #decoder_control object.
*/
static inline void
-decoder_unlock(void)
+decoder_unlock(struct decoder_control *dc)
{
- g_mutex_unlock(dc.mutex);
+ g_mutex_unlock(dc->mutex);
}
/**
@@ -113,9 +113,9 @@ decoder_unlock(void)
* prior to calling this function.
*/
static inline void
-decoder_wait(void)
+decoder_wait(struct decoder_control *dc)
{
- g_cond_wait(dc.cond, dc.mutex);
+ g_cond_wait(dc->cond, dc->mutex);
}
/**
@@ -124,75 +124,81 @@ decoder_wait(void)
* this function.
*/
static inline void
-decoder_signal(void)
+decoder_signal(struct decoder_control *dc)
{
- g_cond_signal(dc.cond);
+ g_cond_signal(dc->cond);
}
-static inline bool decoder_is_idle(void)
+static inline bool
+decoder_is_idle(const struct decoder_control *dc)
{
- return (dc.state == DECODE_STATE_STOP ||
- dc.state == DECODE_STATE_ERROR) &&
- dc.command != DECODE_COMMAND_START;
+ return (dc->state == DECODE_STATE_STOP ||
+ dc->state == DECODE_STATE_ERROR) &&
+ dc->command != DECODE_COMMAND_START;
}
-static inline bool decoder_is_starting(void)
+static inline bool
+decoder_is_starting(const struct decoder_control *dc)
{
- return dc.command == DECODE_COMMAND_START ||
- dc.state == DECODE_STATE_START;
+ return dc->command == DECODE_COMMAND_START ||
+ dc->state == DECODE_STATE_START;
}
-static inline bool decoder_has_failed(void)
+static inline bool
+decoder_has_failed(const struct decoder_control *dc)
{
- assert(dc.command == DECODE_COMMAND_NONE);
+ assert(dc->command == DECODE_COMMAND_NONE);
- return dc.state == DECODE_STATE_ERROR;
+ return dc->state == DECODE_STATE_ERROR;
}
-static inline bool decoder_lock_is_idle(void)
+static inline bool
+decoder_lock_is_idle(struct decoder_control *dc)
{
bool ret;
- decoder_lock();
- ret = decoder_is_idle();
- decoder_unlock();
+ decoder_lock(dc);
+ ret = decoder_is_idle(dc);
+ decoder_unlock(dc);
return ret;
}
-static inline bool decoder_lock_is_starting(void)
+static inline bool
+decoder_lock_is_starting(struct decoder_control *dc)
{
bool ret;
- decoder_lock();
- ret = decoder_is_starting();
- decoder_unlock();
+ decoder_lock(dc);
+ ret = decoder_is_starting(dc);
+ decoder_unlock(dc);
return ret;
}
-static inline bool decoder_lock_has_failed(void)
+static inline bool
+decoder_lock_has_failed(struct decoder_control *dc)
{
bool ret;
- decoder_lock();
- ret = decoder_has_failed();
- decoder_unlock();
+ decoder_lock(dc);
+ ret = decoder_has_failed(dc);
+ decoder_unlock(dc);
return ret;
}
-static inline struct song *
-decoder_current_song(void)
+static inline const struct song *
+decoder_current_song(const struct decoder_control *dc)
{
- switch (dc.state) {
+ switch (dc->state) {
case DECODE_STATE_STOP:
case DECODE_STATE_ERROR:
return NULL;
case DECODE_STATE_START:
case DECODE_STATE_DECODE:
- return dc.current_song;
+ return dc->current_song;
}
assert(false);
@@ -200,21 +206,21 @@ decoder_current_song(void)
}
void
-dc_command_wait(void);
+dc_command_wait(struct decoder_control *dc);
void
-dc_start(struct song *song);
+dc_start(struct decoder_control *dc, struct song *song);
void
-dc_start_async(struct song *song);
+dc_start_async(struct decoder_control *dc, struct song *song);
void
-dc_stop(void);
+dc_stop(struct decoder_control *dc);
bool
-dc_seek(double where);
+dc_seek(struct decoder_control *dc, double where);
void
-dc_quit(void);
+dc_quit(struct decoder_control *dc);
#endif
diff --git a/src/decoder_internal.c b/src/decoder_internal.c
index db90333b4..d40ef89d7 100644
--- a/src/decoder_internal.c
+++ b/src/decoder_internal.c
@@ -34,13 +34,13 @@
* potentially blocking operation.
*/
static int
-decoder_input_buffer(struct input_stream *is)
+decoder_input_buffer(struct decoder_control *dc, struct input_stream *is)
{
int ret;
- decoder_unlock();
+ decoder_unlock(dc);
ret = input_stream_buffer(is) > 0;
- decoder_lock();
+ decoder_lock(dc);
return ret;
}
@@ -50,17 +50,17 @@ decoder_input_buffer(struct input_stream *is)
* one.
*/
static enum decoder_command
-need_chunks(struct input_stream *is, bool do_wait)
+need_chunks(struct decoder_control *dc, struct input_stream *is, bool do_wait)
{
- if (dc.command == DECODE_COMMAND_STOP ||
- dc.command == DECODE_COMMAND_SEEK)
- return dc.command;
+ if (dc->command == DECODE_COMMAND_STOP ||
+ dc->command == DECODE_COMMAND_SEEK)
+ return dc->command;
- if ((is == NULL || decoder_input_buffer(is) <= 0) && do_wait) {
- decoder_wait();
+ if ((is == NULL || decoder_input_buffer(dc, is) <= 0) && do_wait) {
+ decoder_wait(dc);
player_signal();
- return dc.command;
+ return dc->command;
}
return DECODE_COMMAND_NONE;
@@ -69,6 +69,7 @@ need_chunks(struct input_stream *is, bool do_wait)
struct music_chunk *
decoder_get_chunk(struct decoder *decoder, struct input_stream *is)
{
+ struct decoder_control *dc = decoder->dc;
enum decoder_command cmd;
assert(decoder != NULL);
@@ -77,13 +78,13 @@ decoder_get_chunk(struct decoder *decoder, struct input_stream *is)
return decoder->chunk;
do {
- decoder->chunk = music_buffer_allocate(dc.buffer);
+ decoder->chunk = music_buffer_allocate(dc->buffer);
if (decoder->chunk != NULL)
return decoder->chunk;
- decoder_lock();
- cmd = need_chunks(is, true);
- decoder_unlock();
+ decoder_lock(dc);
+ cmd = need_chunks(dc, is, true);
+ decoder_unlock(dc);
} while (cmd == DECODE_COMMAND_NONE);
return NULL;
@@ -92,13 +93,15 @@ decoder_get_chunk(struct decoder *decoder, struct input_stream *is)
void
decoder_flush_chunk(struct decoder *decoder)
{
+ struct decoder_control *dc = decoder->dc;
+
assert(decoder != NULL);
assert(decoder->chunk != NULL);
if (music_chunk_is_empty(decoder->chunk))
- music_buffer_return(dc.buffer, decoder->chunk);
+ music_buffer_return(dc->buffer, decoder->chunk);
else
- music_pipe_push(dc.pipe, decoder->chunk);
+ music_pipe_push(dc->pipe, decoder->chunk);
decoder->chunk = NULL;
}
diff --git a/src/decoder_internal.h b/src/decoder_internal.h
index cf54dbf6d..9d422d253 100644
--- a/src/decoder_internal.h
+++ b/src/decoder_internal.h
@@ -26,6 +26,8 @@
struct input_stream;
struct decoder {
+ struct decoder_control *dc;
+
struct pcm_convert_state conv_state;
bool seeking;
diff --git a/src/decoder_thread.c b/src/decoder_thread.c
index 712e4d20c..7308795c3 100644
--- a/src/decoder_thread.c
+++ b/src/decoder_thread.c
@@ -47,21 +47,21 @@ decoder_stream_decode(const struct decoder_plugin *plugin,
assert(decoder->decoder_tag == NULL);
assert(input_stream != NULL);
assert(input_stream->ready);
- assert(dc.state == DECODE_STATE_START);
+ assert(decoder->dc->state == DECODE_STATE_START);
- decoder_unlock();
+ decoder_unlock(decoder->dc);
/* rewind the stream, so each plugin gets a fresh start */
input_stream_seek(input_stream, 0, SEEK_SET);
decoder_plugin_stream_decode(plugin, decoder, input_stream);
- decoder_lock();
+ decoder_lock(decoder->dc);
- assert(dc.state == DECODE_STATE_START ||
- dc.state == DECODE_STATE_DECODE);
+ assert(decoder->dc->state == DECODE_STATE_START ||
+ decoder->dc->state == DECODE_STATE_DECODE);
- return dc.state != DECODE_STATE_START;
+ return decoder->dc->state != DECODE_STATE_START;
}
static bool
@@ -75,30 +75,34 @@ decoder_file_decode(const struct decoder_plugin *plugin,
assert(decoder->decoder_tag == NULL);
assert(path != NULL);
assert(g_path_is_absolute(path));
- assert(dc.state == DECODE_STATE_START);
+ assert(decoder->dc->state == DECODE_STATE_START);
- decoder_unlock();
+ decoder_unlock(decoder->dc);
decoder_plugin_file_decode(plugin, decoder, path);
- decoder_lock();
+ decoder_lock(decoder->dc);
- assert(dc.state == DECODE_STATE_START ||
- dc.state == DECODE_STATE_DECODE);
+ assert(decoder->dc->state == DECODE_STATE_START ||
+ decoder->dc->state == DECODE_STATE_DECODE);
- return dc.state != DECODE_STATE_START;
+ return decoder->dc->state != DECODE_STATE_START;
}
-static void decoder_run_song(const struct song *song, const char *uri)
+static void
+decoder_run_song(struct decoder_control *dc,
+ const struct song *song, const char *uri)
{
- struct decoder decoder;
+ struct decoder decoder = {
+ .dc = dc,
+ };
int ret;
bool close_instream = true;
struct input_stream input_stream;
const struct decoder_plugin *plugin;
if (!input_stream_open(&input_stream, uri)) {
- dc.state = DECODE_STATE_ERROR;
+ dc->state = DECODE_STATE_ERROR;
return;
}
@@ -109,8 +113,8 @@ static void decoder_run_song(const struct song *song, const char *uri)
decoder.decoder_tag = NULL;
decoder.chunk = NULL;
- dc.state = DECODE_STATE_START;
- dc.command = DECODE_COMMAND_NONE;
+ dc->state = DECODE_STATE_START;
+ dc->command = DECODE_COMMAND_NONE;
player_signal();
@@ -118,32 +122,32 @@ static void decoder_run_song(const struct song *song, const char *uri)
will be available then */
while (!input_stream.ready) {
- if (dc.command == DECODE_COMMAND_STOP) {
- decoder_unlock();
+ if (dc->command == DECODE_COMMAND_STOP) {
+ decoder_unlock(dc);
input_stream_close(&input_stream);
- decoder_lock();
- dc.state = DECODE_STATE_STOP;
+ decoder_lock(dc);
+ dc->state = DECODE_STATE_STOP;
return;
}
- decoder_unlock();
+ decoder_unlock(dc);
ret = input_stream_buffer(&input_stream);
if (ret < 0) {
input_stream_close(&input_stream);
- decoder_lock();
- dc.state = DECODE_STATE_ERROR;
+ decoder_lock(dc);
+ dc->state = DECODE_STATE_ERROR;
return;
}
- decoder_lock();
+ decoder_lock(dc);
}
- if (dc.command == DECODE_COMMAND_STOP) {
- decoder_unlock();
+ if (dc->command == DECODE_COMMAND_STOP) {
+ decoder_unlock(dc);
input_stream_close(&input_stream);
- decoder_lock();
+ decoder_lock(dc);
- dc.state = DECODE_STATE_STOP;
+ dc->state = DECODE_STATE_STOP;
return;
}
@@ -162,7 +166,7 @@ static void decoder_run_song(const struct song *song, const char *uri)
if (ret)
break;
- assert(dc.state == DECODE_STATE_START);
+ assert(dc->state == DECODE_STATE_START);
}
/* if that fails, try suffix matching the URL: */
@@ -177,7 +181,7 @@ static void decoder_run_song(const struct song *song, const char *uri)
if (ret)
break;
- assert(dc.state == DECODE_STATE_START);
+ assert(dc->state == DECODE_STATE_START);
}
}
/* fallback to mp3: */
@@ -196,9 +200,9 @@ static void decoder_run_song(const struct song *song, const char *uri)
const char *s = uri_get_suffix(uri);
while ((plugin = decoder_plugin_from_suffix(s, next++))) {
if (plugin->file_decode != NULL) {
- decoder_unlock();
+ decoder_unlock(dc);
input_stream_close(&input_stream);
- decoder_lock();
+ decoder_lock(dc);
close_instream = false;
ret = decoder_file_decode(plugin,
@@ -213,9 +217,9 @@ static void decoder_run_song(const struct song *song, const char *uri)
reopen it */
bool success;
- decoder_unlock();
+ decoder_unlock(dc);
success = input_stream_open(&input_stream, uri);
- decoder_lock();
+ decoder_lock(dc);
if (success)
close_instream = true;
@@ -231,7 +235,7 @@ static void decoder_run_song(const struct song *song, const char *uri)
}
}
- decoder_unlock();
+ decoder_unlock(dc);
pcm_convert_deinit(&decoder.conv_state);
@@ -251,14 +255,15 @@ static void decoder_run_song(const struct song *song, const char *uri)
if (decoder.decoder_tag != NULL)
tag_free(decoder.decoder_tag);
- decoder_lock();
+ decoder_lock(dc);
- dc.state = ret ? DECODE_STATE_STOP : DECODE_STATE_ERROR;
+ dc->state = ret ? DECODE_STATE_STOP : DECODE_STATE_ERROR;
}
-static void decoder_run(void)
+static void
+decoder_run(struct decoder_control *dc)
{
- struct song *song = dc.next_song;
+ struct song *song = dc->next_song;
char *uri;
if (song_is_file(song))
@@ -267,58 +272,62 @@ static void decoder_run(void)
uri = song_get_uri(song);
if (uri == NULL) {
- dc.state = DECODE_STATE_ERROR;
+ dc->state = DECODE_STATE_ERROR;
return;
}
- dc.current_song = dc.next_song; /* NEED LOCK */
- decoder_run_song(song, uri);
+ dc->current_song = dc->next_song; /* NEED LOCK */
+ decoder_run_song(dc, song, uri);
g_free(uri);
}
-static gpointer decoder_task(G_GNUC_UNUSED gpointer arg)
+static gpointer
+decoder_task(gpointer arg)
{
- decoder_lock();
+ struct decoder_control *dc = arg;
+
+ decoder_lock(dc);
do {
- assert(dc.state == DECODE_STATE_STOP ||
- dc.state == DECODE_STATE_ERROR);
+ assert(dc->state == DECODE_STATE_STOP ||
+ dc->state == DECODE_STATE_ERROR);
- switch (dc.command) {
+ switch (dc->command) {
case DECODE_COMMAND_START:
case DECODE_COMMAND_SEEK:
- decoder_run();
+ decoder_run(dc);
- dc.command = DECODE_COMMAND_NONE;
+ dc->command = DECODE_COMMAND_NONE;
player_signal();
break;
case DECODE_COMMAND_STOP:
- dc.command = DECODE_COMMAND_NONE;
+ dc->command = DECODE_COMMAND_NONE;
player_signal();
break;
case DECODE_COMMAND_NONE:
- decoder_wait();
+ decoder_wait(dc);
break;
}
- } while (dc.command != DECODE_COMMAND_NONE || !dc.quit);
+ } while (dc->command != DECODE_COMMAND_NONE || !dc->quit);
- decoder_unlock();
+ decoder_unlock(dc);
return NULL;
}
-void decoder_thread_start(void)
+void
+decoder_thread_start(struct decoder_control *dc)
{
GError *e = NULL;
- assert(dc.thread == NULL);
+ assert(dc->thread == NULL);
- dc.thread = g_thread_create(decoder_task, NULL, true, &e);
- if (dc.thread == NULL)
+ dc->thread = g_thread_create(decoder_task, dc, true, &e);
+ if (dc->thread == NULL)
g_error("Failed to spawn decoder task: %s", e->message);
}
diff --git a/src/decoder_thread.h b/src/decoder_thread.h
index 50ed7116e..a25564b87 100644
--- a/src/decoder_thread.h
+++ b/src/decoder_thread.h
@@ -20,6 +20,9 @@
#ifndef MPD_DECODER_THREAD_H
#define MPD_DECODER_THREAD_H
-void decoder_thread_start(void);
+struct decoder_control;
+
+void
+decoder_thread_start(struct decoder_control *dc);
#endif