From ad2ab5893e2153a12bc566cb06aab94246136945 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 28 Sep 2015 17:29:47 +0200 Subject: ao_alsa: improve handling of device disconnection This can happen with USB audio. There was already code for this, but something in mpv and ALSA changed - and now the old code is not necessarily triggered anymore. It probably depends on the exact situation. --- audio/out/ao_alsa.c | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) (limited to 'audio/out') diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c index b9e6cfc7ee..a9d642566a 100644 --- a/audio/out/ao_alsa.c +++ b/audio/out/ao_alsa.c @@ -50,6 +50,7 @@ struct priv { snd_pcm_t *alsa; + bool device_lost; snd_pcm_format_t alsa_fmt; int can_pause; snd_pcm_sframes_t prepause_frames; @@ -83,6 +84,21 @@ struct priv { MP_WARN(ao, "%s: %s\n", (message), snd_strerror(err)); \ } while (0) +// Common code for handling ENODEV, which happens if a device gets "lost", and +// can't be used anymore. Returns true if alsa_err is not ENODEV. +static bool check_device_present(struct ao *ao, int alsa_err) +{ + struct priv *p = ao->priv; + if (alsa_err != -ENODEV) + return true; + if (!p->device_lost) { + MP_WARN(ao, "Device lost, trying to recover...\n"); + ao_request_reload(ao); + p->device_lost = true; + } + return false; +} + static int control(struct ao *ao, enum aocontrol cmd, void *arg) { struct priv *p = ao->priv; @@ -730,6 +746,8 @@ static int get_space(struct ao *ao) snd_pcm_status_alloca(&status); err = snd_pcm_status(p->alsa, status); + if (!check_device_present(ao, err)) + goto alsa_error; CHECK_ALSA_ERROR("cannot get pcm status"); unsigned space = snd_pcm_status_get_avail(status); @@ -856,9 +874,8 @@ static int play(struct ao *ao, void **data, int samples, int flags) if (res == -EINTR || res == -EAGAIN) { /* retry */ res = 0; - } else if (res == -ENODEV) { - MP_WARN(ao, "Device lost, trying to recover...\n"); - ao_request_reload(ao); + } else if (!check_device_present(ao, res)) { + goto alsa_error; } else if (res < 0) { if (res == -ESTRPIPE) { /* suspend */ resume_device(ao); -- cgit v1.2.3