diff --git a/src/output/alsa_plugin.c b/src/output/alsa_plugin.c
index 89ed6058e..870115998 100644
--- a/src/output/alsa_plugin.c
+++ b/src/output/alsa_plugin.c
@@ -495,6 +495,14 @@ alsa_recover(struct alsa_data *ad, int err)
 	return err;
 }
 
+static void
+alsa_drain(void *data)
+{
+	struct alsa_data *ad = data;
+
+	snd_pcm_drain(ad->pcm);
+}
+
 static void
 alsa_cancel(void *data)
 {
@@ -508,9 +516,6 @@ alsa_close(void *data)
 {
 	struct alsa_data *ad = data;
 
-	if (snd_pcm_state(ad->pcm) == SND_PCM_STATE_RUNNING)
-		snd_pcm_drain(ad->pcm);
-
 	snd_pcm_close(ad->pcm);
 }
 
@@ -542,6 +547,7 @@ const struct audio_output_plugin alsaPlugin = {
 	.finish = alsa_finish,
 	.open = alsa_open,
 	.play = alsa_play,
+	.drain = alsa_drain,
 	.cancel = alsa_cancel,
 	.close = alsa_close,
 
diff --git a/src/output_plugin.h b/src/output_plugin.h
index 3a9748d46..ee7f7c73d 100644
--- a/src/output_plugin.h
+++ b/src/output_plugin.h
@@ -116,6 +116,11 @@ struct audio_output_plugin {
 	size_t (*play)(void *data, const void *chunk, size_t size,
 		       GError **error);
 
+	/**
+	 * Wait until the device has finished playing.
+	 */
+	void (*drain)(void *data);
+
 	/**
 	 * Try to cancel data which may still be in the device's
 	 * buffers.
@@ -213,6 +218,13 @@ ao_plugin_play(const struct audio_output_plugin *plugin,
 	return plugin->play(data, chunk, size, error);
 }
 
+static inline void
+ao_plugin_drain(const struct audio_output_plugin *plugin, void *data)
+{
+	if (plugin->drain != NULL)
+		plugin->drain(data);
+}
+
 static inline void
 ao_plugin_cancel(const struct audio_output_plugin *plugin, void *data)
 {
diff --git a/src/output_thread.c b/src/output_thread.c
index f1af81a37..9d25d4758 100644
--- a/src/output_thread.c
+++ b/src/output_thread.c
@@ -62,13 +62,13 @@ ao_enable(struct audio_output *ao)
 }
 
 static void
-ao_close(struct audio_output *ao);
+ao_close(struct audio_output *ao, bool drain);
 
 static void
 ao_disable(struct audio_output *ao)
 {
 	if (ao->open)
-		ao_close(ao);
+		ao_close(ao, false);
 
 	if (ao->really_enabled) {
 		ao->really_enabled = false;
@@ -151,7 +151,7 @@ ao_open(struct audio_output *ao)
 }
 
 static void
-ao_close(struct audio_output *ao)
+ao_close(struct audio_output *ao, bool drain)
 {
 	assert(ao->open);
 
@@ -162,6 +162,11 @@ ao_close(struct audio_output *ao)
 	ao->open = false;
 	g_mutex_unlock(ao->mutex);
 
+	if (drain)
+		ao_plugin_drain(ao->plugin, ao->data);
+	else
+		ao_plugin_cancel(ao->plugin, ao->data);
+
 	ao_plugin_close(ao->plugin, ao->data);
 	filter_close(ao->filter);
 
@@ -208,7 +213,7 @@ ao_reopen(struct audio_output *ao)
 	if (!audio_format_fully_defined(&ao->config_audio_format)) {
 		if (ao->open) {
 			const struct music_pipe *mp = ao->pipe;
-			ao_close(ao);
+			ao_close(ao, true);
 			ao->pipe = mp;
 		}
 
@@ -253,8 +258,7 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
 			  ao->name, ao->plugin->name, error->message);
 		g_error_free(error);
 
-		ao_plugin_cancel(ao->plugin, ao->data);
-		ao_close(ao);
+		ao_close(ao, false);
 
 		/* don't automatically reopen this device for 10
 		   seconds */
@@ -273,8 +277,7 @@ ao_play_chunk(struct audio_output *ao, const struct music_chunk *chunk)
 				  ao->name, ao->plugin->name, error->message);
 			g_error_free(error);
 
-			ao_plugin_cancel(ao->plugin, ao->data);
-			ao_close(ao);
+			ao_close(ao, false);
 
 			/* don't automatically reopen this device for
 			   10 seconds */
@@ -344,7 +347,7 @@ static void ao_pause(struct audio_output *ao)
 	do {
 		ret = ao_plugin_pause(ao->plugin, ao->data);
 		if (!ret) {
-			ao_close(ao);
+			ao_close(ao, false);
 			break;
 		}
 	} while (ao->command == AO_COMMAND_NONE);
@@ -385,8 +388,7 @@ static gpointer audio_output_task(gpointer arg)
 			assert(ao->open);
 			assert(ao->pipe != NULL);
 
-			ao_plugin_cancel(ao->plugin, ao->data);
-			ao_close(ao);
+			ao_close(ao, false);
 			ao_command_finished(ao);
 			break;