From 2351acf9f2e84a2f376820411017ad83bc64eee7 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Jul 11 2005 13:11:40 +0000 Subject: New alsaunmute utility --- diff --git a/alsa-utils.spec b/alsa-utils.spec index 1b6bd0a..ff5511d 100644 --- a/alsa-utils.spec +++ b/alsa-utils.spec @@ -4,17 +4,19 @@ Summary: Advanced Linux Sound Architecture (ALSA) utilities Name: alsa-utils Version: %{version_pack} -Release: 2 +Release: 3 License: GPL Group: Applications/Multimedia URL: http://www.alsa-project.org/ Source: ftp://ftp.alsa-project.org/pub/utils/alsa-utils-%{version_tar}%{?prever}.tar.bz2 Source2: salsa.c Source3: alsacard.c +Source4: alsaunmute.c BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: alsa-lib-devel >= %{version} BuildRequires: ncurses-devel BuildRequires: gettext-devel +BuildRequires: autoconf %description @@ -30,6 +32,7 @@ autoreconf -f -i %{__make} %{?_smp_mflags} %{__cc} $RPM_OPT_FLAGS -o salsa %{SOURCE2} -lasound %{__cc} $RPM_OPT_FLAGS -o alsacard %{SOURCE3} -lasound +%{__cc} $RPM_OPT_FLAGS -o alsaunmute %{SOURCE4} -lasound %install %{__rm} -rf ${RPM_BUILD_ROOT} @@ -44,6 +47,7 @@ ln -s ../../sbin/alsactl $RPM_BUILD_ROOT/%{_sbindir}/alsactl mkdir -p -m755 $RPM_BUILD_ROOT/etc/dev.d/sound install -m 755 salsa $RPM_BUILD_ROOT/etc/dev.d/sound/alsa.dev install -m 755 alsacard %{buildroot}%{_bindir} +install -m 755 alsaunmute %{buildroot}%{_bindir} %clean %{__rm} -rf $RPM_BUILD_ROOT @@ -60,10 +64,12 @@ install -m 755 alsacard %{buildroot}%{_bindir} %{_mandir}/fr/man?/* /usr/share/sounds/alsa/* /usr/share/alsa/speaker-test/* -%{_bindir}/alsacard - %changelog +* Thu Jul 11 2005 Martin Stransky 1.0.9-3 +- New alsaunmute utility +- Add autoconf to BuildRequires (#162483) + * Thu Jun 16 2005 Martin Stransky 1.0.9-2 - New upstream version diff --git a/alsaunmute.c b/alsaunmute.c new file mode 100644 index 0000000..e287872 --- /dev/null +++ b/alsaunmute.c @@ -0,0 +1,320 @@ +/* Copyright 2005 Red Hat, Inc. + * + * Portions extraced from various ALSA code: + * Copyright (c) by Abramo Bagnara + * Jaroslav Kysela + * Takashi Iwai + * Bernd Kaindl + * Jan ONDREJ (SAL) + * + * This software may be freely redistributed under the terms of the GNU + * public license. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include + +#include + +#define TRUE (1==1) +#define FALSE (1!=1) + +int verbose = 0; + +typedef struct _CHANNEL { + + char name[100]; + int play_volume; + int play_switch; + int rec_volume; + int rec_switch; + char driver[100]; + +} CHANNEL; + +CHANNEL channels[] = { + +// channel pl vol pl swt rec vol rec swt driver + + {"Master", 75, 1, 0, 0, ""}, + {"Front", 75, 1, 0, 0, ""}, + {"PCM", 75, 1, 0, 0, ""}, + {"PCM-2", 75, 1, 0, 0, ""}, + {"Synth", 75, 1, 0, 0, ""}, + {"CD", 75, 1, 90, 1, ""}, + + // mute mic + {"Mic", 0, 0, 0, 0, ""}, + + // Trident/YMFPCI/emu10k1 + {"Wave", 100, 1, 0, 0, ""}, + {"Music", 100, 1, 0, 0, ""}, + {"AC97", 100, 1, 0, 0, ""}, + + // CS4237B chipset + {"Master Digital", 75, 1, 0, 0, ""}, + + // Envy24 chips with analog outs + {"DAC", 75, 1, 0, 0, ""}, + + // Powermacs + {"DRC Range", 75, 1, 0, 0, ""}, + + // some notebooks use headphone instead of master + {"Headphone", 75, 1, 0, 0, ""}, + {"Playback", 100, 1, 0, 0, ""}, + + // turn off digital switches + {"SB Live Analog/Digital Output Jack", 0, 0, 0, 0, ""}, + {"Audigy Analog/Digital Output Jack", 0, 0, 0, 0, ""}, + + // Specific config for ca0106 + {"Analog Front", 75, 1, 0, 0, "snd-ca0106"}, + {"Analog Rear", 75, 1, 0, 0, "snd-ca0106"}, + {"SPDIF Out", 0, 0, 0, 0, "snd-ca0106"}, + + // Specific config for snd-emu10k1 + {"Audigy Analog/Digital Output Jack", 0,1,0, 0, "snd-emu10k1"}, + {"IEC958 Optical Raw", 0, 0, 0, 0, "snd-emu10k1"}, + {"Tone", 0, 0, 0, 0, "snd-emu10k1"}, + + // Specific config for snd-intel8x0 + {"External Amplifier", 0, 1, 0, 0, "snd-intel8x0"}, + + // Specific config for snd-intel8x0 (xw8000) + {"Master Mono", 75, 1, 0, 0, "snd-intel8x0"}, + + // Specific config for snd_ens1371 + {"IEC958", 0, 0, 0, 0, "snd-ens1371"} +}; + +char * strlwr(char *a) +{ + char *ret = a; + + while (*a != '\0') { + if (isupper (*a)) + *a = tolower (*a); + a++; + } + return ret; +} + +CHANNEL * channel_find(const char *p_name, const char *p_driver) { + int i; + + for (i = 0; i < sizeof(channels) / sizeof(channels[0]); i++) + if (!strcmp(channels[i].driver, p_driver) && !strcmp(channels[i].name, p_name)) + return (channels + i); + + return (NULL); +} + +int calc_volume(long min, long max, int percent) +{ + return ((int)(min + ((max - min) / 100.0f) * percent)); +} + +int unmute_card(int index, const char *p_driver) +{ + CHANNEL *p_chan; + long pmin, pmax; + long rmin, rmax; + int rc = 0; + char card[32]; + char channel_name[500]; + int c,vol; + + snd_mixer_t *handle; + snd_mixer_selem_id_t *sid; + snd_mixer_elem_t *elem; + snd_mixer_selem_id_alloca(&sid); + + if(verbose) { + fprintf(stderr,"Unmuting %s...\n",p_driver ? p_driver : ""); + } + + sprintf(card, "hw:%d", index); + if ((rc = snd_mixer_open(&handle, 0)) < 0) { + if(verbose) { + fprintf(stderr,"%s: error file %s, line %d...\n",__FUNCTION__,__FILE__,__LINE__); + } + return rc; + } + if ((rc = snd_mixer_attach(handle, card)) < 0) { + if(verbose) { + fprintf(stderr,"%s: error file %s, line %d...\n",__FUNCTION__,__FILE__,__LINE__); + } + goto out; + } + if ((rc = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { + if(verbose) { + fprintf(stderr,"%s: error file %s, line %d...\n",__FUNCTION__,__FILE__,__LINE__); + } + goto out; + } + rc = snd_mixer_load(handle); + if (rc < 0) { + if(verbose) { + fprintf(stderr,"%s: error file %s, line %d...\n",__FUNCTION__,__FILE__,__LINE__); + } + goto out; + } + + for (elem = snd_mixer_first_elem(handle); elem; + elem = snd_mixer_elem_next(elem)) { + + snd_mixer_selem_get_id(elem, sid); + strncpy(channel_name,snd_mixer_selem_id_get_name(sid),500); + channel_name[499] = '\0'; + p_chan = channel_find(strlwr(channel_name),p_driver); + if (!p_chan) + continue; + + for (c = 0; c < SND_MIXER_SCHN_LAST; c++) { + + if (snd_mixer_selem_has_capture_channel(elem, c)) { + if (snd_mixer_selem_has_capture_switch(elem)) { + snd_mixer_selem_set_capture_switch(elem, c, p_chan->rec_switch); + if(verbose) { + fprintf(stderr,"Cap. Switch %s(%d) to %d\n",p_chan->name,c,p_chan->rec_switch); + } + } + if (snd_mixer_selem_has_capture_volume(elem)) { + snd_mixer_selem_get_capture_volume_range(elem, &rmin, &rmax); + vol = calc_volume(rmin, rmax,p_chan->rec_volume); + snd_mixer_selem_set_capture_volume(elem, c, vol); + if(verbose) { + fprintf(stderr,"Cap. Volume %s(%d) to %d\n",p_chan->name,c,vol); + } + } + } + + if (snd_mixer_selem_has_playback_channel(elem, c)) { + if (snd_mixer_selem_has_playback_switch(elem)) { + snd_mixer_selem_set_playback_switch(elem, c, p_chan->play_switch); + if(verbose) { + fprintf(stderr,"Play. Switch %s(%d) to %d\n",p_chan->name,c,p_chan->play_switch); + } + } + if (snd_mixer_selem_has_playback_volume(elem)) { + snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); + vol = calc_volume(pmin, pmax,p_chan->play_volume); + snd_mixer_selem_set_playback_volume(elem, c, vol); + if(verbose) { + fprintf(stderr,"Play. Volume %s(%d) to %d\n",p_chan->name,c,vol); + } + } + } + } + } + return(TRUE); + +out: + snd_mixer_close(handle); + return rc; +} + +char * check_driver_name(char *p_name) +{ + char *p_tmp = strchr(p_name,'-'); + if(p_tmp) { + *p_tmp = '_'; + } + return(p_name); +} + +#define PROC_MODULES "/proc/asound/modules" + +static char driver_name[100]; + +const char * get_card_driver(int index) +{ + FILE *f = fopen(PROC_MODULES,"r"); + char tmp[100]; + char *p_tmp; + int id; + + if(!f) + return(NULL); + + while(fgets(tmp,100,f)) { + sscanf(tmp," %d %s",&id,driver_name); + if(id == index) { + return(check_driver_name(driver_name)); + } + } + + return(NULL); +} + +void check_data(void) +{ + char *p_tmp; + int i; + + for (i = 0; i < sizeof(channels) / sizeof(channels[0]); i++) { + strlwr(channels[i].name); + check_driver_name(channels[i].driver); + } +} + +void usage(char *p_name) +{ + printf("Alsa Unmute utility, Copyright 2005 Red Hat, Inc.\n"); + printf("This software may be freely redistributed under the terms of the GNU\n"); + printf("public license.\n\n"); + + printf("usage: %s card_number [-v]\n\n", p_name); + printf(" card_number - number of unmuted card\n"); + printf(" [-v] - verbose mode\n\n"); + exit(0); +} + +/* + Unmute specified card + alsaunmute 0 +*/ +int main(int argc, char **argv) +{ + const char *p_driver; + int index; + + if (argc < 2) { + usage(argv[0]); + exit(0); + } + + index = atoi(argv[1]); + p_driver = get_card_driver(index); + + if (argc == 3 && (!strcmp(argv[2],"-v") || !strcmp(argv[2],"-V"))) { + verbose = TRUE; + } + + if(!p_driver) { + fprintf(stderr,"Wrong card index %d...\n",index); + return(1); + } + + if(verbose) { + fprintf(stderr,"Card %d Driver %s...\n",index,p_driver); + } + + check_data(); + + // default settings for all cards + unmute_card(index,""); + + // specific setting for selected card_number + unmute_card(index,p_driver); + + return (0); +} diff --git a/salsa.c b/salsa.c index f632cd2..ee41774 100644 --- a/salsa.c +++ b/salsa.c @@ -23,140 +23,88 @@ int get_card_number() { - char *devname, *action; - - action = getenv("ACTION"); - if (!action || strcmp(action,"add")) - return -1; - devname = getenv("DEVNAME"); - if (!devname) - return -1; - if (!strncmp(devname,"/dev/snd/controlC",17)) - return atoi(devname+17); - if (!strncmp(devname,"/dev/snd/pcmC",13)) - return atoi(devname+13); - return -1; + char *devname, *action; + + action = getenv("ACTION"); + if (!action || strcmp(action, "add")) + return -1; + devname = getenv("DEVNAME"); + if (!devname) + return -1; + if (!strncmp(devname, "/dev/snd/controlC", 17)) + return atoi(devname + 17); + if (!strncmp(devname, "/dev/snd/pcmC", 13)) + return atoi(devname + 13); + return -1; } int has_config(int index) { - int rc = 0; - snd_config_t *config, *control; - snd_input_t *in; - snd_ctl_t *handle; - snd_ctl_card_info_t *info; - const char *id; - char path[32]; - - rc = snd_config_top(&config); - if (rc < 0) - goto out; - rc = snd_input_stdio_open(&in, ALSA_CONFIG_PATH, "r"); - if (rc >= 0) { - rc = snd_config_load(config, in); - snd_input_close(in); - if (rc < 0) - goto out; - } - sprintf(path, "hw:%d", index); - rc = snd_ctl_open(&handle, path, 0); - if (rc < 0) - goto out; - snd_ctl_card_info_alloca(&info); - rc = snd_ctl_card_info(handle, info); - if (rc < 0) - goto out_close; - id = snd_ctl_card_info_get_id(info); - rc = snd_config_searchv(config, &control, "state", id, "control", 0); + int rc = 0; + snd_config_t *config, *control; + snd_input_t *in; + snd_ctl_t *handle; + snd_ctl_card_info_t *info; + const char *id; + char path[32]; + + rc = snd_config_top(&config); + if (rc < 0) + goto out; + rc = snd_input_stdio_open(&in, ALSA_CONFIG_PATH, "r"); + if (rc >= 0) { + rc = snd_config_load(config, in); + snd_input_close(in); + if (rc < 0) + goto out; + } + sprintf(path, "hw:%d", index); + rc = snd_ctl_open(&handle, path, 0); + if (rc < 0) + goto out; + snd_ctl_card_info_alloca(&info); + rc = snd_ctl_card_info(handle, info); + if (rc < 0) + goto out_close; + id = snd_ctl_card_info_get_id(info); + rc = snd_config_searchv(config, &control, "state", id, "control", 0); out_close: - snd_ctl_close(handle); + snd_ctl_close(handle); out: - return !rc; - + return !rc; + } int run_alsactl(int index) { - char *args[] = { "/sbin/alsactl", "restore", NULL, NULL }; - char num[10]; - - sprintf(num,"%d",index); - args[2] = num; - execv(args[0],args); - return 1; + char *args[] = { "/sbin/alsactl", "restore", NULL, NULL }; + char num[10]; + + sprintf(num, "%d", index); + args[2] = num; + execv(args[0], args); + return 1; } -int frob_mixer(int index) +void frob_mixer(int index) { - int rc = 0; - char card[32]; - snd_mixer_t *handle; - snd_mixer_selem_id_t *sid; - snd_mixer_elem_t *elem; - snd_mixer_selem_id_alloca(&sid); - - sprintf(card,"hw:%d",index); - if ((rc = snd_mixer_open(&handle, 0)) < 0) { - return rc; - } - if ((rc = snd_mixer_attach(handle, card)) < 0) { - goto out; - } - if ((rc = snd_mixer_selem_register(handle, NULL, NULL)) < 0) { - goto out; - } - rc = snd_mixer_load(handle); - if (rc < 0) { - goto out; - } - for (elem = snd_mixer_first_elem(handle); elem; elem = snd_mixer_elem_next(elem)) { - long pmin, pmax; - int c; - - snd_mixer_selem_get_id(elem, sid); - snd_mixer_selem_get_playback_volume_range(elem, &pmin, &pmax); - for (c = 0; c < SND_MIXER_SCHN_LAST; c++) { - if (snd_mixer_selem_has_capture_channel(elem, c)) { - if (snd_mixer_selem_has_capture_volume(elem)) - snd_mixer_selem_set_capture_volume(elem, c, 0); - if (!strcmp(snd_mixer_selem_id_get_name(sid),"CD")) { - if (snd_mixer_selem_has_capture_switch(elem)) - snd_mixer_selem_set_capture_switch(elem, c, 1); - } else { - if (snd_mixer_selem_has_capture_switch(elem)) - snd_mixer_selem_set_capture_switch(elem, c, 0); - if (snd_mixer_selem_has_playback_switch(elem)) - snd_mixer_selem_set_playback_switch(elem, c, 0); - if (snd_mixer_selem_has_playback_volume(elem)) - snd_mixer_selem_set_playback_volume(elem, c, 0); - } - } - if (snd_mixer_selem_has_playback_channel(elem, c)) { - if (!snd_mixer_selem_has_capture_channel(elem, c) || - !strcmp(snd_mixer_selem_id_get_name(sid),"CD") || - !strcmp(snd_mixer_selem_id_get_name(sid),"Wave")) { - if (snd_mixer_selem_has_playback_switch(elem)) - snd_mixer_selem_set_playback_switch(elem, c, 1); - if (snd_mixer_selem_has_playback_volume(elem)) - snd_mixer_selem_set_playback_volume(elem, c, pmin + (pmax - pmin) * 0.75); - } - } - } - } -out: - snd_mixer_close(handle); - return rc; + char tmp[100]; + snprintf(tmp, 100, "%d", index); + tmp[99] = '\0'; + execl("//usr//bin//alsaunmute","//usr//bin//alsaunmute", tmp, "-v", NULL); } int main(int argc, char **argv) { - int i; - - i = get_card_number(); - if (i < 0) - return 0; - if (has_config(i)) - return run_alsactl(i); - else - return frob_mixer(i); + int i; + + i = get_card_number(); + if (i < 0) + return 0; + if (has_config(i)) + return run_alsactl(i); + else + frob_mixer(i); + + return(0); }