Merge branch 'v0.16.x'
Conflicts: src/player_thread.c
This commit is contained in:
commit
7e219c362c
1
NEWS
1
NEWS
@ -34,6 +34,7 @@ ver 0.16.5 (2010/??/??)
|
||||
* decoder:
|
||||
- ffmpeg: higher precision timestamps
|
||||
- ffmpeg: don't require key frame for seeking
|
||||
- fix CUE track seeking
|
||||
* WIN32: close sockets properly
|
||||
|
||||
|
||||
|
@ -219,7 +219,7 @@ AC_ARG_ENABLE(raop-output,
|
||||
|
||||
AC_ARG_ENABLE(id3,
|
||||
AS_HELP_STRING([--enable-id3],
|
||||
[disable id3 support]),,
|
||||
[enable id3 support]),,
|
||||
enable_id3=auto)
|
||||
|
||||
AC_ARG_ENABLE(inotify,
|
||||
|
@ -76,15 +76,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)
|
||||
{
|
||||
@ -92,11 +117,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;
|
||||
|
||||
@ -121,9 +159,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;
|
||||
@ -133,9 +175,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;
|
||||
|
||||
@ -289,7 +337,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 ||
|
||||
@ -420,6 +468,9 @@ decoder_tag(G_GNUC_UNUSED struct decoder *decoder, struct input_stream *is,
|
||||
/* send only the decoder tag */
|
||||
cmd = do_send_tag(decoder, tag);
|
||||
|
||||
if (cmd == DECODE_COMMAND_NONE)
|
||||
cmd = decoder_get_virtual_command(decoder);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
|
@ -36,6 +36,25 @@ struct decoder {
|
||||
*/
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -380,6 +380,8 @@ decoder_run_song(struct decoder_control *dc,
|
||||
{
|
||||
struct decoder decoder = {
|
||||
.dc = dc,
|
||||
.initial_seek_pending = song->start_ms > 0,
|
||||
.initial_seek_running = false,
|
||||
};
|
||||
int ret;
|
||||
|
||||
|
@ -894,16 +894,6 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
|
||||
if (!player_check_decoder_startup(&player))
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user