Index: src/volume.c =================================================================== --- src/volume.c (revision 2798) +++ src/volume.c (working copy) @@ -1,5 +1,6 @@ /* the Music Player Daemon (MPD) * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) + * Daniel Brown (danb@cs.utexas.edu) * This project's homepage is: http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -63,6 +64,9 @@ int volume_softwareSet = 100; +int volume_fakeMuteStatus = 0; +int volume_fakeLastUnmutedLevel = -1; + #ifdef HAVE_OSS int volume_ossFd; int volume_ossControl = SOUND_MIXER_VOLUME; @@ -79,14 +83,14 @@ #ifdef HAVE_OSS int prepOssMixer(char * device) { int devmask = 0; - ConfigParam * param; + ConfigParam * param; if((volume_ossFd = open(device,O_RDONLY))<0) { WARNING("unable to open oss mixer \"%s\"\n",device); return -1; } - param = getConfigParam(CONF_MIXER_CONTROL); + param = getConfigParam(CONF_MIXER_CONTROL); if(param) { char * labels[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_LABELS; @@ -113,13 +117,13 @@ if(i>=SOUND_MIXER_NRDEVICES) { WARNING("mixer control \"%s\" not found at line %i\n", - param->value, param->line); + param->value, param->line); close(volume_ossFd); return -1; } else if(!( ( 1 << i ) & devmask )) { WARNING("mixer control \"%s\" not usable at line %i\n", - param->value, param->line); + param->value, param->line); close(volume_ossFd); return -1; } @@ -161,7 +165,7 @@ if (rel) { if((current = getOssVolumeLevel()) < 0) { commandError(fp, ACK_ERROR_SYSTEM, - "problem getting current volume", NULL); + "problem getting current volume", NULL); return -1; } @@ -189,7 +193,7 @@ int err; snd_mixer_elem_t * elem; char * controlName = VOLUME_MIXER_ALSA_CONTROL_DEFAULT; - ConfigParam * param; + ConfigParam * param; if((err = snd_mixer_open(&volume_alsaMixerHandle,0))<0) { WARNING("problems opening alsa mixer: %s\n",snd_strerror(err)); @@ -219,7 +223,7 @@ elem = snd_mixer_first_elem(volume_alsaMixerHandle); - param = getConfigParam(CONF_MIXER_CONTROL); + param = getConfigParam(CONF_MIXER_CONTROL); if(param) { controlName = param->value; @@ -275,7 +279,7 @@ if(volume_alsaSet>0 && ret==level) { ret = volume_alsaSet; } - else ret = (int)(100*(((float)(level-min))/(max-min))+0.5); + else ret = (int)(100*(((float)(level-min))/(max-min))+0.5); return ret; } @@ -303,7 +307,7 @@ if(volume_alsaSet >= 0 && level==test) { vol = volume_alsaSet; } - else vol = 100.0*(((float)(level-min))/(max-min)); + else vol = 100.0*(((float)(level-min))/(max-min)); vol+=change; } else @@ -360,10 +364,10 @@ } void initVolume() { - ConfigParam * param = getConfigParam(CONF_MIXER_TYPE); + ConfigParam * param = getConfigParam(CONF_MIXER_TYPE); - if(param) { - if(0); + if(param) { + if(0); #ifdef HAVE_ALSA else if(strcmp(param->value, VOLUME_MIXER_ALSA)==0) { volume_mixerType = VOLUME_MIXER_TYPE_ALSA; @@ -443,6 +447,9 @@ } int changeVolumeLevel(FILE * fp, int change, int rel) { + if(getVolumeMuteStatus()) + setVolumeMuteStatus(fp,0); + switch(volume_mixerType) { #ifdef HAVE_ALSA case VOLUME_MIXER_TYPE_ALSA: @@ -455,7 +462,115 @@ case VOLUME_MIXER_TYPE_SOFTWARE: return changeSoftwareVolume(fp,change,rel); default: - return 0; - break; + return 0; + break; } } + +int getAlsaVolumeMuteStatus() { + int err; + int status; + + if((err = snd_mixer_selem_get_playback_switch(volume_alsaElem, + SND_MIXER_SCHN_FRONT_LEFT,&status))<0) { + WARNING("problems getting alsa mute status: %s\n", + snd_strerror(err)); + return -1; + } + + return !status; +} + +int setAlsaVolumeMuteStatus(FILE * fp, int status) { + int err; + + if(status == getVolumeMuteStatus()) + return 0; + + if((err = snd_mixer_selem_set_playback_switch_all(volume_alsaElem, + !status))<0) { + commandError(fp, ACK_ERROR_SYSTEM, "problems muting volume", + NULL); + WARNING("problems muting alsa volume: %s\n", snd_strerror(err)); + return -1; + } + + return 0; +} + +int getFakeVolumeMuteStatus() { + return volume_fakeMuteStatus; +} + +// Fake mute: just drop volume to 0 +int setFakeVolumeMuteStatus(FILE * fp, int status) { + // Don't call changeVolumeLevel while volume_fakeMuteStatus is set! + if(status && !getVolumeMuteStatus()) { + // Mute + int ret; + volume_fakeLastUnmutedLevel = getVolumeLevel(); + ret = changeVolumeLevel(fp,0,0); + volume_fakeMuteStatus = 1; + return ret; + } + else if(!status && getVolumeMuteStatus()){ + // Unmute + volume_fakeMuteStatus = 0; + return changeVolumeLevel(fp,volume_fakeLastUnmutedLevel,0); + } + else { + return 0; + } +} + +int getOssVolumeMuteStatus() { + return getFakeVolumeMuteStatus(); +} + +int setOssVolumeMuteStatus(FILE * fp, int status) { + return setFakeVolumeMuteStatus(fp,status); +} + +int getSoftwareVolumeMuteStatus() { + return getFakeVolumeMuteStatus(); +} + +int setSoftwareVolumeMuteStatus(FILE * fp, int status) { + return setFakeVolumeMuteStatus(fp,status); +} + +int getVolumeMuteStatus() { + switch(volume_mixerType) { +#ifdef HAVE_ALSA + case VOLUME_MIXER_TYPE_ALSA: + return getAlsaVolumeMuteStatus(); +#endif +#ifdef HAVE_OSS + case VOLUME_MIXER_TYPE_OSS: + return getOssVolumeMuteStatus(); +#endif + case VOLUME_MIXER_TYPE_SOFTWARE: + return getSoftwareVolumeMuteStatus(); + default: + return 0; + break; + } +} + +int setVolumeMuteStatus(FILE * fp, int status) { + switch(volume_mixerType) { +#ifdef HAVE_ALSA + case VOLUME_MIXER_TYPE_ALSA: + return setAlsaVolumeMuteStatus(fp,status); +#endif +#ifdef HAVE_OSS + case VOLUME_MIXER_TYPE_OSS: + return setOssVolumeMuteStatus(fp,status); +#endif + case VOLUME_MIXER_TYPE_SOFTWARE: + return setSoftwareVolumeMuteStatus(fp,status); + default: + return 0; + break; + } +} Index: src/volume.h =================================================================== --- src/volume.h (revision 2798) +++ src/volume.h (working copy) @@ -1,5 +1,6 @@ /* the Music Player Daemon (MPD) * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) + * Daniel Brown (danb@cs.utexas.edu) * This project's homepage is: http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -37,4 +38,8 @@ int changeVolumeLevel(FILE * fp, int change, int rel); +int getVolumeMuteStatus(); + +int setVolumeMuteStatus(FILE * fp, int status); + #endif Index: src/command.c =================================================================== --- src/command.c (revision 2798) +++ src/command.c (working copy) @@ -1,5 +1,6 @@ /* the Music Player Daemon (MPD) * (c)2003-2004 by Warren Dukes (shank@mercury.chem.pitt.edu) + * Daniel Brown (danb@cs.utexas.edu) * This project's homepage is: http://www.musicpd.org * * This program is free software; you can redistribute it and/or modify @@ -64,6 +65,7 @@ #define COMMAND_PREVIOUS "previous" #define COMMAND_LISTALL "listall" #define COMMAND_VOLUME "volume" +#define COMMAND_MUTE "mute" #define COMMAND_REPEAT "repeat" #define COMMAND_RANDOM "random" #define COMMAND_STATS "stats" @@ -90,6 +92,7 @@ #define COMMAND_NOTCOMMANDS "notcommands" #define COMMAND_STATUS_VOLUME "volume" +#define COMMAND_STATUS_MUTE "mute" #define COMMAND_STATUS_STATE "state" #define COMMAND_STATUS_REPEAT "repeat" #define COMMAND_STATUS_RANDOM "random" @@ -248,6 +251,7 @@ } myfprintf(fp,"%s: %i\n",COMMAND_STATUS_VOLUME,getVolumeLevel()); + myfprintf(fp,"%s: %i\n",COMMAND_STATUS_MUTE,getVolumeMuteStatus()); myfprintf(fp,"%s: %i\n",COMMAND_STATUS_REPEAT,getPlaylistRepeatStatus()); myfprintf(fp,"%s: %i\n",COMMAND_STATUS_RANDOM,getPlaylistRandomStatus()); myfprintf(fp,"%s: %li\n",COMMAND_STATUS_PLAYLIST,getPlaylistVersion()); @@ -572,6 +576,20 @@ return changeVolumeLevel(fp,level,0); } +int handleMute(FILE * fp, unsigned int * permission, int argArrayLength, + char ** argArray) +{ + int status; + char * test; + + status = strtol(argArray[1],&test,10); + if(*test!='\0') { + commandError(fp, ACK_ERROR_ARG, "need an integer", NULL); + return -1; + } + return setVolumeMuteStatus(fp,status); +} + int handleRepeat(FILE * fp, unsigned int * permission, int argArrayLength, char ** argArray) { @@ -942,6 +960,7 @@ addCommand(COMMAND_PREVIOUS ,PERMISSION_CONTROL, 0, 0,handlePrevious,NULL); addCommand(COMMAND_LISTALL ,PERMISSION_READ, 0, 1,handleListAll,NULL); addCommand(COMMAND_VOLUME ,PERMISSION_CONTROL, 1, 1,handleVolume,NULL); + addCommand(COMMAND_MUTE ,PERMISSION_CONTROL, 1, 1,handleMute,NULL); addCommand(COMMAND_REPEAT ,PERMISSION_CONTROL, 1, 1,handleRepeat,NULL); addCommand(COMMAND_RANDOM ,PERMISSION_CONTROL, 1, 1,handleRandom,NULL); addCommand(COMMAND_STATS ,PERMISSION_READ, 0, 0,handleStats,NULL);