diff options
author | Max Kellermann <max@duempel.org> | 2011-09-21 23:17:34 +0200 |
---|---|---|
committer | Max Kellermann <max@duempel.org> | 2011-09-22 00:04:48 +0200 |
commit | 525a791987c66ed2f8b1ca9e5357836f536fdb8b (patch) | |
tree | 5244d5bab9f7ab1a2f2ea0ee92ab24e6076f7d3b /src/decoder_api.c | |
parent | fb19210cfd3ec20d69f53ea258c36ef72e002edd (diff) | |
download | mpd-525a791987c66ed2f8b1ca9e5357836f536fdb8b.tar.gz mpd-525a791987c66ed2f8b1ca9e5357836f536fdb8b.tar.xz mpd-525a791987c66ed2f8b1ca9e5357836f536fdb8b.zip |
decoder_api: emulate SEEK command for initial seek to CUE track
When playing a CUE track, the player thread waited for the decoder to
become ready, and then sent a SEEK command to the beginning of the CUE
track. If that is near the start of the song file, and the track is
short enough, the decoder could have finished decoding already at that
point, and seeking fails.
This commit makes this initial seek more robust: instead of letting
the player thread deal with the difficult timings, let the decoder API
emulate a SEEK command, and return it to the decoder plugin, as soon
as the plugin finishes its initialization.
Diffstat (limited to '')
-rw-r--r-- | src/decoder_api.c | 63 |
1 files changed, 57 insertions, 6 deletions
diff --git a/src/decoder_api.c b/src/decoder_api.c index fe34ea34a..99c02db87 100644 --- a/src/decoder_api.c +++ b/src/decoder_api.c @@ -78,15 +78,40 @@ decoder_initialized(struct decoder *decoder, &af_string)); } -enum decoder_command decoder_get_command(G_GNUC_UNUSED struct decoder * decoder) +/** + * Returns the current decoder command. May return a "virtual" + * synthesized command, e.g. to seek to the beginning of the CUE + * track. + */ +G_GNUC_PURE +static enum decoder_command +decoder_get_virtual_command(struct decoder *decoder) { const struct decoder_control *dc = decoder->dc; - assert(dc->pipe != NULL); + if (decoder->initial_seek_running) + return DECODE_COMMAND_SEEK; + + if (decoder->initial_seek_pending) { + if (dc->command == DECODE_COMMAND_NONE) { + decoder->initial_seek_pending = false; + decoder->initial_seek_running = true; + return DECODE_COMMAND_SEEK; + } + + decoder->initial_seek_pending = false; + } + return dc->command; } +enum decoder_command +decoder_get_command(struct decoder *decoder) +{ + return decoder_get_virtual_command(decoder); +} + void decoder_command_finished(struct decoder *decoder) { @@ -94,11 +119,24 @@ decoder_command_finished(struct decoder *decoder) decoder_lock(dc); - assert(dc->command != DECODE_COMMAND_NONE); + assert(dc->command != DECODE_COMMAND_NONE || + decoder->initial_seek_running); assert(dc->command != DECODE_COMMAND_SEEK || + decoder->initial_seek_running || dc->seek_error || decoder->seeking); assert(dc->pipe != NULL); + if (decoder->initial_seek_running) { + assert(!decoder->seeking); + assert(decoder->chunk == NULL); + assert(music_pipe_empty(dc->pipe)); + + decoder->initial_seek_running = false; + decoder->timestamp = dc->song->start_ms / 1000.; + decoder_unlock(dc); + return; + } + if (decoder->seeking) { decoder->seeking = false; @@ -124,9 +162,13 @@ double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder) { const struct decoder_control *dc = decoder->dc; - assert(dc->command == DECODE_COMMAND_SEEK); assert(dc->pipe != NULL); + if (decoder->initial_seek_running) + return dc->song->start_ms / 1000.; + + assert(dc->command == DECODE_COMMAND_SEEK); + decoder->seeking = true; return dc->seek_where; @@ -136,9 +178,15 @@ void decoder_seek_error(struct decoder * decoder) { struct decoder_control *dc = decoder->dc; - assert(dc->command == DECODE_COMMAND_SEEK); assert(dc->pipe != NULL); + if (decoder->initial_seek_running) + /* d'oh, we can't seek to the sub-song start position, + what now? - no idea, ignoring the problem for now. */ + return; + + assert(dc->command == DECODE_COMMAND_SEEK); + dc->seek_error = true; decoder->seeking = false; @@ -270,7 +318,7 @@ decoder_data(struct decoder *decoder, assert(length % audio_format_frame_size(&dc->in_audio_format) == 0); decoder_lock(dc); - cmd = dc->command; + cmd = decoder_get_virtual_command(decoder); decoder_unlock(dc); if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK || @@ -401,6 +449,9 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is, /* send only the decoder tag */ cmd = do_send_tag(decoder, is, tag); + if (cmd == DECODE_COMMAND_NONE) + cmd = decoder_get_virtual_command(decoder); + return cmd; } |