From ea6dc826a1c40047058ab7d86c848b32be3de25e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 16 Jul 2006 16:52:49 +0000 Subject: volume: gracefully handle disconnected ALSA mixers This should help with the previous set of patches against the ALSA audio output. We should have fully disconnectable/reconnectable ALSA devices now. git-svn-id: https://svn.musicpd.org/mpd/trunk@4365 09075e82-0dd4-0310-85a5-a0d7c8717e4f --- src/volume.c | 60 ++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/volume.c b/src/volume.c index 512b7f157..6fd68d778 100644 --- a/src/volume.c +++ b/src/volume.c @@ -185,6 +185,11 @@ static int changeOssVolumeLevel(FILE * fp, int change, int rel) { #endif #ifdef HAVE_ALSA +static void closeAlsaMixer(void) { + snd_mixer_close(volume_alsaMixerHandle); + volume_alsaMixerHandle = NULL; +} + static int prepAlsaMixer(char * card) { int err; snd_mixer_elem_t * elem; @@ -197,21 +202,21 @@ static int prepAlsaMixer(char * card) { } if((err = snd_mixer_attach(volume_alsaMixerHandle,card))<0) { - snd_mixer_close(volume_alsaMixerHandle); + closeAlsaMixer(); WARNING("problems problems attaching alsa mixer: %s\n", snd_strerror(err)); return -1; } if((err = snd_mixer_selem_register(volume_alsaMixerHandle,NULL,NULL))<0) { - snd_mixer_close(volume_alsaMixerHandle); + closeAlsaMixer(); WARNING("problems snd_mixer_selem_register'ing: %s\n", snd_strerror(err)); return -1; } - + if((err = snd_mixer_load(volume_alsaMixerHandle))<0) { - snd_mixer_close(volume_alsaMixerHandle); + closeAlsaMixer(); WARNING("problems snd_mixer_selem_register'ing: %s\n", snd_strerror(err)); return -1; @@ -246,12 +251,33 @@ static int prepAlsaMixer(char * card) { WARNING("can't find alsa mixer_control \"%s\"\n",controlName); - snd_mixer_close(volume_alsaMixerHandle); + closeAlsaMixer(); return -1; } -static void closeAlsaMixer() { - snd_mixer_close(volume_alsaMixerHandle); +static int prep_alsa_get_level(long *level) +{ + const char *cmd; + int err; + + if (!volume_alsaMixerHandle && prepAlsaMixer(volume_mixerDevice)<0) + return -1; + + if ((err = snd_mixer_handle_events(volume_alsaMixerHandle)) < 0) { + cmd = "handle_events"; + goto error; + } + if((err = snd_mixer_selem_get_playback_volume(volume_alsaElem, + SND_MIXER_SCHN_FRONT_LEFT, level)) < 0) { + cmd = "selem_get_playback_volume"; + goto error; + } + return 0; +error: + WARNING("problems getting alsa volume: %s (snd_mixer_%s)\n", + snd_strerror(err), cmd); + closeAlsaMixer(); + return -1; } static int getAlsaVolumeLevel() { @@ -259,18 +285,10 @@ static int getAlsaVolumeLevel() { long level; long max = volume_alsaMax; long min = volume_alsaMin; - int err; - - snd_mixer_handle_events(volume_alsaMixerHandle); - if((err = snd_mixer_selem_get_playback_volume(volume_alsaElem, - SND_MIXER_SCHN_FRONT_LEFT,&level))<0) { - WARNING("problems getting alsa volume: %s\n",snd_strerror(err)); + if (prep_alsa_get_level(&level) < 0) return -1; - } - snd_mixer_selem_get_playback_volume(volume_alsaElem, - SND_MIXER_SCHN_FRONT_LEFT,&level); ret = ((volume_alsaSet/100.0)*(max-min)+min)+0.5; if(volume_alsaSet>0 && ret==level) { ret = volume_alsaSet; @@ -288,15 +306,8 @@ static int changeAlsaVolumeLevel(FILE * fp, int change, int rel) { long min = volume_alsaMin; int err; - snd_mixer_handle_events(volume_alsaMixerHandle); - - if((err = snd_mixer_selem_get_playback_volume(volume_alsaElem, - SND_MIXER_SCHN_FRONT_LEFT,&level))<0) { - commandError(fp, ACK_ERROR_SYSTEM, "problems getting volume", - NULL); - WARNING("problems getting alsa volume: %s\n",snd_strerror(err)); + if (prep_alsa_get_level(&level) < 0) return -1; - } if (rel) { test = ((volume_alsaSet/100.0)*(max-min)+min)+0.5; @@ -322,6 +333,7 @@ static int changeAlsaVolumeLevel(FILE * fp, int change, int rel) { commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume", NULL); WARNING("problems setting alsa volume: %s\n",snd_strerror(err)); + closeAlsaMixer(); return -1; } -- cgit v1.2.3