diff options
author | wm4 <wm4@nowhere> | 2015-09-28 17:29:47 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2015-09-28 22:03:14 +0200 |
commit | ad2ab5893e2153a12bc566cb06aab94246136945 (patch) | |
tree | 6d05578c619d5672ed4a026edb57bad80f1d950f /audio | |
parent | 144571da9b5b595d7bb49822e78887771554b68b (diff) |
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.
Diffstat (limited to 'audio')
-rw-r--r-- | audio/out/ao_alsa.c | 23 |
1 files changed, 20 insertions, 3 deletions
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); |