aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMax Kellermann <max@duempel.org>2009-11-09 22:16:26 +0100
committerMax Kellermann <max@duempel.org>2009-11-09 22:16:26 +0100
commit3359f8785ef9b595b3ad943fdd2227f98ce56990 (patch)
tree248b51245d424b4700fffffb2eb8efd89f1ed6a0
parent96b974bc452e6b33ada281c5ccb4df7b9492e1da (diff)
downloadmpd-3359f8785ef9b595b3ad943fdd2227f98ce56990.tar.gz
mpd-3359f8785ef9b595b3ad943fdd2227f98ce56990.tar.xz
mpd-3359f8785ef9b595b3ad943fdd2227f98ce56990.zip
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.
-rw-r--r--src/output_all.c9
-rw-r--r--src/output_all.h6
-rw-r--r--src/output_control.c9
-rw-r--r--src/output_control.h3
-rw-r--r--src/output_internal.h7
-rw-r--r--src/output_thread.c13
6 files changed, 47 insertions, 0 deletions
diff --git a/src/output_all.c b/src/output_all.c
index 5b7cc4908..29590abf0 100644
--- a/src/output_all.c
+++ b/src/output_all.c
@@ -496,6 +496,15 @@ audio_output_all_pause(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)
{
unsigned int i;
diff --git a/src/output_all.h b/src/output_all.h
index 91b6f3f5d..6ff45fb79 100644
--- a/src/output_all.h
+++ b/src/output_all.h
@@ -130,6 +130,12 @@ 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.
*/
void
diff --git a/src/output_control.c b/src/output_control.c
index 842b89030..795d04a8c 100644
--- a/src/output_control.c
+++ b/src/output_control.c
@@ -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);
diff --git a/src/output_control.h b/src/output_control.h
index b2e48fa8d..692c11676 100644
--- a/src/output_control.h
+++ b/src/output_control.h
@@ -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);
diff --git a/src/output_internal.h b/src/output_internal.h
index 6b81bbc78..de1b15c29 100644
--- a/src/output_internal.h
+++ b/src/output_internal.h
@@ -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
};
diff --git a/src/output_thread.c b/src/output_thread.c
index 40906d82f..fb1701591 100644
--- a/src/output_thread.c
+++ b/src/output_thread.c
@@ -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)