summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_alsa.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-09-28 17:29:47 +0200
committerwm4 <wm4@nowhere>2015-09-28 22:03:14 +0200
commitad2ab5893e2153a12bc566cb06aab94246136945 (patch)
tree6d05578c619d5672ed4a026edb57bad80f1d950f /audio/out/ao_alsa.c
parent144571da9b5b595d7bb49822e78887771554b68b (diff)
downloadmpv-ad2ab5893e2153a12bc566cb06aab94246136945.tar.bz2
mpv-ad2ab5893e2153a12bc566cb06aab94246136945.tar.xz
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/out/ao_alsa.c')
-rw-r--r--audio/out/ao_alsa.c23
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);