diff options
author | Max Kellermann <max@duempel.org> | 2009-08-13 23:33:46 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2009-08-13 23:33:46 +0200 |
commit | e28a0e97b5d2e54684c6452d6d45f64ff1e542d9 (patch) | |
tree | 38f0c66be040d13c8356293e64cedf8280174fbc /src/decoder_thread.c | |
parent | 499ed62dd790949c571517b54ef0e96fad26b16b (diff) | |
download | mpd-e28a0e97b5d2e54684c6452d6d45f64ff1e542d9.tar.gz mpd-e28a0e97b5d2e54684c6452d6d45f64ff1e542d9.tar.xz mpd-e28a0e97b5d2e54684c6452d6d45f64ff1e542d9.zip |
decoder_control: protect command, state with a mutex
Replace decoder_control.notify with decoder_control.mutex and
decoder_control.cond. Lock the mutex on all accesses to
decoder_control.command and decoder_control.state.
Diffstat (limited to '')
-rw-r--r-- | src/decoder_thread.c | 47 |
1 files changed, 45 insertions, 2 deletions
diff --git a/src/decoder_thread.c b/src/decoder_thread.c index 2b1a6299a..be37896c1 100644 --- a/src/decoder_thread.c +++ b/src/decoder_thread.c @@ -49,11 +49,15 @@ decoder_stream_decode(const struct decoder_plugin *plugin, assert(input_stream->ready); assert(dc.state == DECODE_STATE_START); + decoder_unlock(); + /* 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(); + assert(dc.state == DECODE_STATE_START || dc.state == DECODE_STATE_DECODE); @@ -73,8 +77,12 @@ decoder_file_decode(const struct decoder_plugin *plugin, assert(path[0] == '/'); assert(dc.state == DECODE_STATE_START); + decoder_unlock(); + decoder_plugin_file_decode(plugin, decoder, path); + decoder_lock(); + assert(dc.state == DECODE_STATE_START || dc.state == DECODE_STATE_DECODE); @@ -103,28 +111,40 @@ static void decoder_run_song(const struct song *song, const char *uri) dc.state = DECODE_STATE_START; dc.command = DECODE_COMMAND_NONE; + + decoder_unlock(); notify_signal(&pc.notify); + decoder_lock(); /* wait for the input stream to become ready; its metadata will be available then */ while (!input_stream.ready) { if (dc.command == DECODE_COMMAND_STOP) { + decoder_unlock(); input_stream_close(&input_stream); + decoder_lock(); dc.state = DECODE_STATE_STOP; return; } + decoder_unlock(); ret = input_stream_buffer(&input_stream); if (ret < 0) { input_stream_close(&input_stream); + decoder_lock(); dc.state = DECODE_STATE_ERROR; return; } + + decoder_lock(); } if (dc.command == DECODE_COMMAND_STOP) { + decoder_unlock(); input_stream_close(&input_stream); + decoder_lock(); + dc.state = DECODE_STATE_STOP; return; } @@ -179,7 +199,10 @@ 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(); input_stream_close(&input_stream); + decoder_lock(); + close_instream = false; ret = decoder_file_decode(plugin, &decoder, uri); @@ -191,7 +214,13 @@ static void decoder_run_song(const struct song *song, const char *uri) been closed before decoder_file_decode() - reopen it */ - if (input_stream_open(&input_stream, uri)) + bool success; + + decoder_unlock(); + success = input_stream_open(&input_stream, uri); + decoder_lock(); + + if (success) close_instream = true; else continue; @@ -205,6 +234,8 @@ static void decoder_run_song(const struct song *song, const char *uri) } } + decoder_unlock(); + pcm_convert_deinit(&decoder.conv_state); /* flush the last chunk */ @@ -223,6 +254,8 @@ static void decoder_run_song(const struct song *song, const char *uri) if (decoder.decoder_tag != NULL) tag_free(decoder.decoder_tag); + decoder_lock(); + dc.state = ret ? DECODE_STATE_STOP : DECODE_STATE_ERROR; } @@ -249,6 +282,8 @@ static void decoder_run(void) static gpointer decoder_task(G_GNUC_UNUSED gpointer arg) { + decoder_lock(); + do { assert(dc.state == DECODE_STATE_STOP || dc.state == DECODE_STATE_ERROR); @@ -259,20 +294,28 @@ static gpointer decoder_task(G_GNUC_UNUSED gpointer arg) decoder_run(); dc.command = DECODE_COMMAND_NONE; + + decoder_unlock(); notify_signal(&pc.notify); + decoder_lock(); break; case DECODE_COMMAND_STOP: dc.command = DECODE_COMMAND_NONE; + + decoder_unlock(); notify_signal(&pc.notify); + decoder_lock(); break; case DECODE_COMMAND_NONE: - notify_wait(&dc.notify); + decoder_wait(); break; } } while (dc.command != DECODE_COMMAND_NONE || !dc.quit); + decoder_unlock(); + return NULL; } |