Commit 3359f878 authored by Max Kellermann's avatar Max Kellermann

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.
parent 96b974bc
...@@ -496,6 +496,15 @@ audio_output_all_pause(void) ...@@ -496,6 +496,15 @@ audio_output_all_pause(void)
} }
void 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) audio_output_all_cancel(void)
{ {
unsigned int i; unsigned int i;
......
...@@ -130,6 +130,12 @@ void ...@@ -130,6 +130,12 @@ void
audio_output_all_pause(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. * Try to cancel data which may still be in the device's buffers.
*/ */
void void
......
...@@ -229,6 +229,15 @@ void audio_output_pause(struct audio_output *ao) ...@@ -229,6 +229,15 @@ void audio_output_pause(struct audio_output *ao)
g_mutex_unlock(ao->mutex); 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) void audio_output_cancel(struct audio_output *ao)
{ {
g_mutex_lock(ao->mutex); g_mutex_lock(ao->mutex);
......
...@@ -67,6 +67,9 @@ audio_output_play(struct audio_output *ao); ...@@ -67,6 +67,9 @@ audio_output_play(struct audio_output *ao);
void audio_output_pause(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_cancel(struct audio_output *ao);
void audio_output_close(struct audio_output *ao); void audio_output_close(struct audio_output *ao);
void audio_output_finish(struct audio_output *ao); void audio_output_finish(struct audio_output *ao);
......
...@@ -40,6 +40,13 @@ enum audio_output_command { ...@@ -40,6 +40,13 @@ enum audio_output_command {
AO_COMMAND_CLOSE, AO_COMMAND_CLOSE,
AO_COMMAND_PAUSE, 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_CANCEL,
AO_COMMAND_KILL AO_COMMAND_KILL
}; };
......
...@@ -450,6 +450,19 @@ static gpointer audio_output_task(gpointer arg) ...@@ -450,6 +450,19 @@ static gpointer audio_output_task(gpointer arg)
the new command first */ the new command first */
continue; 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: case AO_COMMAND_CANCEL:
ao->chunk = NULL; ao->chunk = NULL;
if (ao->open) if (ao->open)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment