summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-05-25 15:07:05 +0200
committerwm4 <wm4@nowhere>2013-05-26 16:44:18 +0200
commit3546188a41aa8c231e563ac89af68edd2798323b (patch)
tree76729cb525bedfd28d7401c8e1b2e3715452079f
parent8db90e18d3e5bb524a1a611f6dd03ba78f315552 (diff)
downloadmpv-3546188a41aa8c231e563ac89af68edd2798323b.tar.bz2
mpv-3546188a41aa8c231e563ac89af68edd2798323b.tar.xz
ao_alsa: always unset ALSA error handler, cleanup on init error
The ALSA device was not closed when initialization failed. The ALSA error handler (set with snd_lib_error_set_handler()) was not unset when closing ao_alsa. If this is not done, the handler will still be called when other libraries using ALSA cause errors, even though ao_alsa was long closed. Since these messages were prefixed with "[AO_ALSA]", they were misleading and implying ao_alsa was still used. For some reason, our error handler is still called even after doing snd_lib_error_set_handler(NULL), which should be impossible. Checking with the debuggers, inserting printf(), as well as the alsa-lib source code all suggest our error handler should not be called, but it still happens. It's a complete mystery.
-rw-r--r--audio/out/ao_alsa.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/audio/out/ao_alsa.c b/audio/out/ao_alsa.c
index d2e8180608..a8952e4547 100644
--- a/audio/out/ao_alsa.c
+++ b/audio/out/ao_alsa.c
@@ -75,6 +75,7 @@ struct priv {
static float get_delay(struct ao *ao);
static int play(struct ao *ao, void *data, int len, int flags);
+static void uninit(struct ao *ao, bool immed);
static void alsa_error_handler(const char *file, int line, const char *function,
int err, const char *format, ...)
@@ -436,14 +437,11 @@ static int init(struct ao *ao, char *params)
mp_msg(MSGT_AO, MSGL_V,
"alsa-init: requested format: %d Hz, %d channels, %x\n",
ao->samplerate, ao->channels.num, ao->format);
- p->alsa = NULL;
- mp_msg(MSGT_AO, MSGL_V, "alsa-init: using ALSA %s\n", snd_asoundlib_version());
+
p->prepause_frames = 0;
p->delay_before_pause = 0;
- snd_lib_error_set_handler(alsa_error_handler);
-
//subdevice parsing
// set defaults
block = 1;
@@ -478,6 +476,9 @@ static int init(struct ao *ao, char *params)
p->can_pause = 1;
+ mp_msg(MSGT_AO, MSGL_V, "alsa-init: using ALSA %s\n", snd_asoundlib_version());
+ snd_lib_error_set_handler(alsa_error_handler);
+
int open_mode = block ? 0 : SND_PCM_NONBLOCK;
int isac3 = AF_FORMAT_IS_IEC61937(ao->format);
//modes = 0, SND_PCM_NONBLOCK, SND_PCM_ASYNC
@@ -626,6 +627,7 @@ static int init(struct ao *ao, char *params)
return 0;
alsa_error:
+ uninit(ao, true);
return -1;
} // end init
@@ -644,13 +646,12 @@ static void uninit(struct ao *ao, bool immed)
err = snd_pcm_close(p->alsa);
CHECK_ALSA_ERROR("pcm close error");
- p->alsa = NULL;
mp_msg(MSGT_AO, MSGL_V, "alsa-uninit: pcm closed\n");
- } else {
- mp_tmsg(MSGT_AO, MSGL_ERR, "[AO_ALSA] No handler defined!\n");
}
-alsa_error: ;
+alsa_error:
+ p->alsa = NULL;
+ snd_lib_error_set_handler(NULL);
}
static void audio_pause(struct ao *ao)