output_thread: added command DRAIN

This command manually drains the hardware buffer.  This is useful when
the player thread want to make sure that everything has been played.
This commit is contained in:
Max Kellermann
2009-11-09 22:16:26 +01:00
parent 96b974bc45
commit 3359f8785e
6 changed files with 47 additions and 0 deletions

@ -495,6 +495,15 @@ audio_output_all_pause(void)
audio_output_wait_all();
}
void
audio_output_all_drain(void)
{
for (unsigned i = 0; i < num_audio_outputs; ++i)
audio_output_drain_async(&audio_outputs[i]);
audio_output_wait_all();
}
void
audio_output_all_cancel(void)
{

@ -129,6 +129,12 @@ audio_output_all_wait(unsigned threshold);
void
audio_output_all_pause(void);
/**
* Drain all audio outputs.
*/
void
audio_output_all_drain(void);
/**
* Try to cancel data which may still be in the device's buffers.
*/

@ -229,6 +229,15 @@ void audio_output_pause(struct audio_output *ao)
g_mutex_unlock(ao->mutex);
}
void
audio_output_drain_async(struct audio_output *ao)
{
g_mutex_lock(ao->mutex);
if (audio_output_is_open(ao))
ao_command_async(ao, AO_COMMAND_DRAIN);
g_mutex_unlock(ao->mutex);
}
void audio_output_cancel(struct audio_output *ao)
{
g_mutex_lock(ao->mutex);

@ -67,6 +67,9 @@ audio_output_play(struct audio_output *ao);
void audio_output_pause(struct audio_output *ao);
void
audio_output_drain_async(struct audio_output *ao);
void audio_output_cancel(struct audio_output *ao);
void audio_output_close(struct audio_output *ao);
void audio_output_finish(struct audio_output *ao);

@ -40,6 +40,13 @@ enum audio_output_command {
AO_COMMAND_CLOSE,
AO_COMMAND_PAUSE,
/**
* Drains the internal (hardware) buffers of the device. This
* operation may take a while to complete.
*/
AO_COMMAND_DRAIN,
AO_COMMAND_CANCEL,
AO_COMMAND_KILL
};

@ -450,6 +450,19 @@ static gpointer audio_output_task(gpointer arg)
the new command first */
continue;
case AO_COMMAND_DRAIN:
if (ao->open) {
assert(ao->chunk == NULL);
assert(music_pipe_peek(ao->pipe) == NULL);
g_mutex_unlock(ao->mutex);
ao_plugin_drain(ao->plugin, ao->data);
g_mutex_lock(ao->mutex);
}
ao_command_finished(ao);
continue;
case AO_COMMAND_CANCEL:
ao->chunk = NULL;
if (ao->open)