Commit 7e219c36 authored by Max Kellermann's avatar Max Kellermann

Merge branch 'v0.16.x'

Conflicts: src/player_thread.c
parents 203f48d1 525a7919
...@@ -34,6 +34,7 @@ ver 0.16.5 (2010/??/??) ...@@ -34,6 +34,7 @@ ver 0.16.5 (2010/??/??)
* decoder: * decoder:
- ffmpeg: higher precision timestamps - ffmpeg: higher precision timestamps
- ffmpeg: don't require key frame for seeking - ffmpeg: don't require key frame for seeking
- fix CUE track seeking
* WIN32: close sockets properly * WIN32: close sockets properly
......
...@@ -219,7 +219,7 @@ AC_ARG_ENABLE(raop-output, ...@@ -219,7 +219,7 @@ AC_ARG_ENABLE(raop-output,
AC_ARG_ENABLE(id3, AC_ARG_ENABLE(id3,
AS_HELP_STRING([--enable-id3], AS_HELP_STRING([--enable-id3],
[disable id3 support]),, [enable id3 support]),,
enable_id3=auto) enable_id3=auto)
AC_ARG_ENABLE(inotify, AC_ARG_ENABLE(inotify,
......
...@@ -76,15 +76,40 @@ decoder_initialized(struct decoder *decoder, ...@@ -76,15 +76,40 @@ decoder_initialized(struct decoder *decoder,
&af_string)); &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; const struct decoder_control *dc = decoder->dc;
assert(dc->pipe != NULL); 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; return dc->command;
} }
enum decoder_command
decoder_get_command(struct decoder *decoder)
{
return decoder_get_virtual_command(decoder);
}
void void
decoder_command_finished(struct decoder *decoder) decoder_command_finished(struct decoder *decoder)
{ {
...@@ -92,11 +117,24 @@ decoder_command_finished(struct decoder *decoder) ...@@ -92,11 +117,24 @@ decoder_command_finished(struct decoder *decoder)
decoder_lock(dc); 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 || assert(dc->command != DECODE_COMMAND_SEEK ||
decoder->initial_seek_running ||
dc->seek_error || decoder->seeking); dc->seek_error || decoder->seeking);
assert(dc->pipe != NULL); 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) { if (decoder->seeking) {
decoder->seeking = false; decoder->seeking = false;
...@@ -121,9 +159,13 @@ double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder) ...@@ -121,9 +159,13 @@ double decoder_seek_where(G_GNUC_UNUSED struct decoder * decoder)
{ {
const struct decoder_control *dc = decoder->dc; const struct decoder_control *dc = decoder->dc;
assert(dc->command == DECODE_COMMAND_SEEK);
assert(dc->pipe != NULL); assert(dc->pipe != NULL);
if (decoder->initial_seek_running)
return dc->song->start_ms / 1000.;
assert(dc->command == DECODE_COMMAND_SEEK);
decoder->seeking = true; decoder->seeking = true;
return dc->seek_where; return dc->seek_where;
...@@ -133,9 +175,15 @@ void decoder_seek_error(struct decoder * decoder) ...@@ -133,9 +175,15 @@ void decoder_seek_error(struct decoder * decoder)
{ {
struct decoder_control *dc = decoder->dc; struct decoder_control *dc = decoder->dc;
assert(dc->command == DECODE_COMMAND_SEEK);
assert(dc->pipe != NULL); 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; dc->seek_error = true;
decoder->seeking = false; decoder->seeking = false;
...@@ -289,7 +337,7 @@ decoder_data(struct decoder *decoder, ...@@ -289,7 +337,7 @@ decoder_data(struct decoder *decoder,
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); decoder_lock(dc);
cmd = dc->command; cmd = decoder_get_virtual_command(decoder);
decoder_unlock(dc); decoder_unlock(dc);
if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK || if (cmd == DECODE_COMMAND_STOP || cmd == DECODE_COMMAND_SEEK ||
...@@ -420,6 +468,9 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is, ...@@ -420,6 +468,9 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is,
/* send only the decoder tag */ /* send only the decoder tag */
cmd = do_send_tag(decoder, tag); cmd = do_send_tag(decoder, tag);
if (cmd == DECODE_COMMAND_NONE)
cmd = decoder_get_virtual_command(decoder);
return cmd; return cmd;
} }
......
...@@ -36,6 +36,25 @@ struct decoder { ...@@ -36,6 +36,25 @@ struct decoder {
*/ */
double timestamp; double timestamp;
/**
* Is the initial seek (to the start position of the sub-song)
* pending, or has it been performed already?
*/
bool initial_seek_pending;
/**
* Is the initial seek currently running? During this time,
* the decoder command is SEEK. This flag is set by
* decoder_get_virtual_command(), when the virtual SEEK
* command is generated for the first time.
*/
bool initial_seek_running;
/**
* This flag is set by decoder_seek_where(), and checked by
* decoder_command_finished(). It is used to clean up after
* seeking.
*/
bool seeking; bool seeking;
/** /**
......
...@@ -380,6 +380,8 @@ decoder_run_song(struct decoder_control *dc, ...@@ -380,6 +380,8 @@ decoder_run_song(struct decoder_control *dc,
{ {
struct decoder decoder = { struct decoder decoder = {
.dc = dc, .dc = dc,
.initial_seek_pending = song->start_ms > 0,
.initial_seek_running = false,
}; };
int ret; int ret;
......
...@@ -894,16 +894,6 @@ static void do_play(struct player_control *pc, struct decoder_control *dc) ...@@ -894,16 +894,6 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
if (!player_check_decoder_startup(&player)) if (!player_check_decoder_startup(&player))
break; break;
/* seek to the beginning of the range */
const struct song *song = decoder_current_song(dc);
if (song != NULL && song->start_ms > 0 &&
/* we must not send a seek command until
the decoder is initialized
completely */
!player.decoder_starting &&
!dc_seek(dc, song->start_ms / 1000.0))
player_dc_stop(&player);
player_lock(pc); player_lock(pc);
continue; continue;
} }
......
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
#include <stdbool.h> #include <stdbool.h>
/** /**
* Checks whether the specified URI has a schema in the form * Checks whether the specified URI has a scheme in the form
* "scheme://". * "scheme://".
*/ */
G_GNUC_PURE G_GNUC_PURE
......
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