player_thread: get "elapsed" from audio outputs

Tracking the "elapsed" time from the chunks which we have sent to the
output pipe is very imprecise: since we have implemented the music
pipe, we're sending large number of chunks at once, giving the
"elapsed" time stamp a resolution of usually more than a second.

This patch changes the source of this information to the outputs.  If
a chunk has been played by all outputs, the "elapsed" time stamp is
updated.

The new command PLAYER_COMMAND_REFRESH makes the player thread update
its status information: it tells the outputs to update the chunk time
stamp.  After that, player_control.elapsed_time is current.
This commit is contained in:
Max Kellermann 2009-10-08 22:09:25 +02:00
parent 47b5e73a15
commit 448aefaace
5 changed files with 42 additions and 4 deletions

View File

@ -52,6 +52,11 @@ static struct music_buffer *g_music_buffer;
*/ */
static struct music_pipe *g_mp; static struct music_pipe *g_mp;
/**
* The "elapsed_time" stamp of the most recently finished chunk.
*/
static float audio_output_all_elapsed_time;
unsigned int audio_output_count(void) unsigned int audio_output_count(void)
{ {
return num_audio_outputs; return num_audio_outputs;
@ -385,6 +390,8 @@ audio_output_all_check(void)
this chunk */ this chunk */
return music_pipe_size(g_mp); return music_pipe_size(g_mp);
audio_output_all_elapsed_time = chunk->times;
is_tail = chunk->next == NULL; is_tail = chunk->next == NULL;
if (is_tail) if (is_tail)
/* this is the tail of the pipe - clear the /* this is the tail of the pipe - clear the
@ -468,9 +475,16 @@ audio_output_all_close(void)
music_pipe_clear(g_mp, g_music_buffer); music_pipe_clear(g_mp, g_music_buffer);
music_pipe_free(g_mp); music_pipe_free(g_mp);
g_mp = NULL; g_mp = NULL;
audio_output_all_elapsed_time = 0.0;
} }
g_music_buffer = NULL; g_music_buffer = NULL;
audio_format_clear(&input_audio_format); audio_format_clear(&input_audio_format);
} }
float
audio_output_all_get_elapsed_time(void)
{
return audio_output_all_elapsed_time;
}

View File

@ -128,4 +128,11 @@ audio_output_all_pause(void);
void void
audio_output_all_cancel(void); audio_output_all_cancel(void);
/**
* Returns the "elapsed_time" stamp of the most recently finished
* chunk.
*/
float
audio_output_all_get_elapsed_time(void);
#endif #endif

View File

@ -142,6 +142,8 @@ pc_set_pause(bool pause_flag)
void void
pc_get_status(struct player_status *status) pc_get_status(struct player_status *status)
{ {
player_command(PLAYER_COMMAND_REFRESH);
status->state = pc.state; status->state = pc.state;
if (pc.state != PLAYER_STATE_STOP) { if (pc.state != PLAYER_STATE_STOP) {

View File

@ -48,6 +48,12 @@ enum player_command {
* stop * stop
*/ */
PLAYER_COMMAND_CANCEL, PLAYER_COMMAND_CANCEL,
/**
* Refresh status information in the #player_control struct,
* e.g. elapsed_time.
*/
PLAYER_COMMAND_REFRESH,
}; };
enum player_error { enum player_error {

View File

@ -151,7 +151,6 @@ player_wait_for_decoder(struct player *player)
player->song = pc.next_song; player->song = pc.next_song;
pc.next_song = NULL; pc.next_song = NULL;
pc.elapsed_time = 0;
player->queued = false; player->queued = false;
/* set the "starting" flag, which will be cleared by /* set the "starting" flag, which will be cleared by
@ -330,7 +329,6 @@ static bool player_seek_decoder(struct player *player)
return false; return false;
} }
pc.elapsed_time = where;
player_command_finished(); player_command_finished();
player->xfade = XFADE_UNKNOWN; player->xfade = XFADE_UNKNOWN;
@ -409,6 +407,14 @@ static void player_process_command(struct player *player)
player->queued = false; player->queued = false;
player_command_finished(); player_command_finished();
break; break;
case PLAYER_COMMAND_REFRESH:
if (audio_format_defined(&player->play_audio_format))
audio_output_all_check();
pc.elapsed_time = audio_output_all_get_elapsed_time();
player_command_finished();
break;
} }
} }
@ -456,7 +462,6 @@ play_chunk(struct song *song, struct music_chunk *chunk,
return true; return true;
} }
pc.elapsed_time = chunk->times;
pc.bit_rate = chunk->bit_rate; pc.bit_rate = chunk->bit_rate;
/* send the chunk to the audio outputs */ /* send the chunk to the audio outputs */
@ -630,7 +635,6 @@ static void do_play(void)
return; return;
} }
pc.elapsed_time = 0;
pc.state = PLAYER_STATE_PLAY; pc.state = PLAYER_STATE_PLAY;
player_command_finished(); player_command_finished();
@ -813,6 +817,11 @@ static gpointer player_task(G_GNUC_UNUSED gpointer arg)
player_command_finished(); player_command_finished();
break; break;
case PLAYER_COMMAND_REFRESH:
/* no-op when not playing */
player_command_finished();
break;
case PLAYER_COMMAND_NONE: case PLAYER_COMMAND_NONE:
notify_wait(&pc.notify); notify_wait(&pc.notify);
break; break;