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:
parent
47b5e73a15
commit
448aefaace
@ -52,6 +52,11 @@ static struct music_buffer *g_music_buffer;
|
||||
*/
|
||||
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)
|
||||
{
|
||||
return num_audio_outputs;
|
||||
@ -385,6 +390,8 @@ audio_output_all_check(void)
|
||||
this chunk */
|
||||
return music_pipe_size(g_mp);
|
||||
|
||||
audio_output_all_elapsed_time = chunk->times;
|
||||
|
||||
is_tail = chunk->next == NULL;
|
||||
if (is_tail)
|
||||
/* 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_free(g_mp);
|
||||
g_mp = NULL;
|
||||
audio_output_all_elapsed_time = 0.0;
|
||||
}
|
||||
|
||||
g_music_buffer = NULL;
|
||||
|
||||
audio_format_clear(&input_audio_format);
|
||||
}
|
||||
|
||||
float
|
||||
audio_output_all_get_elapsed_time(void)
|
||||
{
|
||||
return audio_output_all_elapsed_time;
|
||||
}
|
||||
|
@ -128,4 +128,11 @@ audio_output_all_pause(void);
|
||||
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
|
||||
|
@ -142,6 +142,8 @@ pc_set_pause(bool pause_flag)
|
||||
void
|
||||
pc_get_status(struct player_status *status)
|
||||
{
|
||||
player_command(PLAYER_COMMAND_REFRESH);
|
||||
|
||||
status->state = pc.state;
|
||||
|
||||
if (pc.state != PLAYER_STATE_STOP) {
|
||||
|
@ -48,6 +48,12 @@ enum player_command {
|
||||
* stop
|
||||
*/
|
||||
PLAYER_COMMAND_CANCEL,
|
||||
|
||||
/**
|
||||
* Refresh status information in the #player_control struct,
|
||||
* e.g. elapsed_time.
|
||||
*/
|
||||
PLAYER_COMMAND_REFRESH,
|
||||
};
|
||||
|
||||
enum player_error {
|
||||
|
@ -151,7 +151,6 @@ player_wait_for_decoder(struct player *player)
|
||||
|
||||
player->song = pc.next_song;
|
||||
pc.next_song = NULL;
|
||||
pc.elapsed_time = 0;
|
||||
player->queued = false;
|
||||
|
||||
/* set the "starting" flag, which will be cleared by
|
||||
@ -330,7 +329,6 @@ static bool player_seek_decoder(struct player *player)
|
||||
return false;
|
||||
}
|
||||
|
||||
pc.elapsed_time = where;
|
||||
player_command_finished();
|
||||
|
||||
player->xfade = XFADE_UNKNOWN;
|
||||
@ -409,6 +407,14 @@ static void player_process_command(struct player *player)
|
||||
player->queued = false;
|
||||
player_command_finished();
|
||||
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;
|
||||
}
|
||||
|
||||
pc.elapsed_time = chunk->times;
|
||||
pc.bit_rate = chunk->bit_rate;
|
||||
|
||||
/* send the chunk to the audio outputs */
|
||||
@ -630,7 +635,6 @@ static void do_play(void)
|
||||
return;
|
||||
}
|
||||
|
||||
pc.elapsed_time = 0;
|
||||
pc.state = PLAYER_STATE_PLAY;
|
||||
player_command_finished();
|
||||
|
||||
@ -813,6 +817,11 @@ static gpointer player_task(G_GNUC_UNUSED gpointer arg)
|
||||
player_command_finished();
|
||||
break;
|
||||
|
||||
case PLAYER_COMMAND_REFRESH:
|
||||
/* no-op when not playing */
|
||||
player_command_finished();
|
||||
break;
|
||||
|
||||
case PLAYER_COMMAND_NONE:
|
||||
notify_wait(&pc.notify);
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user