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.
This commit is contained in:
wm4 2013-05-25 15:07:05 +02:00
parent 8db90e18d3
commit 3546188a41
1 changed files with 9 additions and 8 deletions

View File

@ -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)