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
This commit is contained in:
60
src/volume.c
60
src/volume.c
@@ -185,6 +185,11 @@ static int changeOssVolumeLevel(FILE * fp, int change, int rel) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ALSA
|
#ifdef HAVE_ALSA
|
||||||
|
static void closeAlsaMixer(void) {
|
||||||
|
snd_mixer_close(volume_alsaMixerHandle);
|
||||||
|
volume_alsaMixerHandle = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static int prepAlsaMixer(char * card) {
|
static int prepAlsaMixer(char * card) {
|
||||||
int err;
|
int err;
|
||||||
snd_mixer_elem_t * elem;
|
snd_mixer_elem_t * elem;
|
||||||
@@ -197,21 +202,21 @@ static int prepAlsaMixer(char * card) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if((err = snd_mixer_attach(volume_alsaMixerHandle,card))<0) {
|
if((err = snd_mixer_attach(volume_alsaMixerHandle,card))<0) {
|
||||||
snd_mixer_close(volume_alsaMixerHandle);
|
closeAlsaMixer();
|
||||||
WARNING("problems problems attaching alsa mixer: %s\n",
|
WARNING("problems problems attaching alsa mixer: %s\n",
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((err = snd_mixer_selem_register(volume_alsaMixerHandle,NULL,NULL))<0) {
|
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",
|
WARNING("problems snd_mixer_selem_register'ing: %s\n",
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if((err = snd_mixer_load(volume_alsaMixerHandle))<0) {
|
if((err = snd_mixer_load(volume_alsaMixerHandle))<0) {
|
||||||
snd_mixer_close(volume_alsaMixerHandle);
|
closeAlsaMixer();
|
||||||
WARNING("problems snd_mixer_selem_register'ing: %s\n",
|
WARNING("problems snd_mixer_selem_register'ing: %s\n",
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
return -1;
|
return -1;
|
||||||
@@ -246,12 +251,33 @@ static int prepAlsaMixer(char * card) {
|
|||||||
|
|
||||||
WARNING("can't find alsa mixer_control \"%s\"\n",controlName);
|
WARNING("can't find alsa mixer_control \"%s\"\n",controlName);
|
||||||
|
|
||||||
snd_mixer_close(volume_alsaMixerHandle);
|
closeAlsaMixer();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void closeAlsaMixer() {
|
static int prep_alsa_get_level(long *level)
|
||||||
snd_mixer_close(volume_alsaMixerHandle);
|
{
|
||||||
|
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() {
|
static int getAlsaVolumeLevel() {
|
||||||
@@ -259,18 +285,10 @@ static int getAlsaVolumeLevel() {
|
|||||||
long level;
|
long level;
|
||||||
long max = volume_alsaMax;
|
long max = volume_alsaMax;
|
||||||
long min = volume_alsaMin;
|
long min = volume_alsaMin;
|
||||||
int err;
|
|
||||||
|
|
||||||
snd_mixer_handle_events(volume_alsaMixerHandle);
|
if (prep_alsa_get_level(&level) < 0)
|
||||||
|
|
||||||
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));
|
|
||||||
return -1;
|
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;
|
ret = ((volume_alsaSet/100.0)*(max-min)+min)+0.5;
|
||||||
if(volume_alsaSet>0 && ret==level) {
|
if(volume_alsaSet>0 && ret==level) {
|
||||||
ret = volume_alsaSet;
|
ret = volume_alsaSet;
|
||||||
@@ -288,15 +306,8 @@ static int changeAlsaVolumeLevel(FILE * fp, int change, int rel) {
|
|||||||
long min = volume_alsaMin;
|
long min = volume_alsaMin;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
snd_mixer_handle_events(volume_alsaMixerHandle);
|
if (prep_alsa_get_level(&level) < 0)
|
||||||
|
|
||||||
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));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if (rel) {
|
if (rel) {
|
||||||
test = ((volume_alsaSet/100.0)*(max-min)+min)+0.5;
|
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",
|
commandError(fp, ACK_ERROR_SYSTEM, "problems setting volume",
|
||||||
NULL);
|
NULL);
|
||||||
WARNING("problems setting alsa volume: %s\n",snd_strerror(err));
|
WARNING("problems setting alsa volume: %s\n",snd_strerror(err));
|
||||||
|
closeAlsaMixer();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user