output_plugin: added method "drain"
drain() is the opposite of cancel(): it waits until all data in the buffer has finished playing. Instead of implicitly draining in the close() method like the ALSA plugin has been doing it forever, let the output thread decide whether to drain or to cancel.
This commit is contained in:
parent
f74ee1a352
commit
1403172ef3
|
@ -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,
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue