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;
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
Loading…
Reference in New Issue