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:
|
* 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,
|
|||||||
|
|
||||||
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,
|
|||||||
&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)
|
|||||||
|
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
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,
|
|||||||
/* 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 {
|
|||||||
*/
|
*/
|
||||||
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,
|
|||||||
{
|
{
|
||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user