diff options
Diffstat (limited to 'src/decoder_internal.c')
-rw-r--r-- | src/decoder_internal.c | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/src/decoder_internal.c b/src/decoder_internal.c index 4a56fa5f3..d40ef89d7 100644 --- a/src/decoder_internal.c +++ b/src/decoder_internal.c @@ -28,21 +28,39 @@ #include <assert.h> /** + * This is a wrapper for input_stream_buffer(). It assumes that the + * decoder is currently locked, and temporarily unlocks it while + * calling input_stream_buffer(). We shouldn't hold the lock during a + * potentially blocking operation. + */ +static int +decoder_input_buffer(struct decoder_control *dc, struct input_stream *is) +{ + int ret; + + decoder_unlock(dc); + ret = input_stream_buffer(is) > 0; + decoder_lock(dc); + + return ret; +} + +/** * All chunks are full of decoded data; wait for the player to free * 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 || input_stream_buffer(is) <= 0) && do_wait) { - notify_wait(&dc.notify); - notify_signal(&pc.notify); + 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; @@ -51,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); @@ -59,11 +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; - cmd = need_chunks(is, true); + decoder_lock(dc); + cmd = need_chunks(dc, is, true); + decoder_unlock(dc); } while (cmd == DECODE_COMMAND_NONE); return NULL; @@ -72,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; } |