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

View File

@ -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)
{

View File

@ -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.
*/

View File

@ -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);

View File

@ -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);

View File

@ -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
};

View File

@ -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)