/* Copyright 2007 Red Hat, Inc. * * Portions extraced from various ALSA code: * Copyright (c) by Abramo Bagnara * Jaroslav Kysela * * 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 ALSA_CONFIG_PATH "/etc/alsa/asound.state" #define ALL_CARDS (-1) 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; } 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); out_close: snd_ctl_close(handle); out: return !rc; } void load_volume_settings(int index) { char *args[] = { "/sbin/alsactl", "-f", ALSA_CONFIG_PATH, "restore", NULL, NULL }; char num[10]; if(index != ALL_CARDS) { snprintf(num, 10, "%d", index); args[4] = num; } execv(args[0], args); } void save_volume_settings(int index) { char *args[] = { "/sbin/alsactl", "-f", ALSA_CONFIG_PATH, "store", NULL, NULL }; char num[10]; if(index != ALL_CARDS) { snprintf(num, 10, "%d", index); args[4] = num; } execv(args[0], args); } void frob_mixer(int index) { char tmp[100]; snprintf(tmp, 100, "%d", index); tmp[99] = '\0'; execl("/bin/alsaunmute","/bin/alsaunmute", tmp, "-v", NULL); } void banner(void) { printf("ALSA volume settings handler, Copyright 2007 Red Hat, Inc.\n"); printf("This software may be freely redistributed under\nthe terms of the GNU public license.\n\n"); printf("Usage: salsa [options] [card number]\n\n"); printf(" Options:\n"); printf(" -l - Load volume settings\n"); printf(" -s - Save volume settings\n\n"); printf(" Card number:\n"); printf(" ## - An affected card. If it isn't specified,\n"); printf(" configure all installed sound cards.\n\n"); exit(0); } int main(int argc, char **argv) { int i; if(argc == 1) { i = get_card_number(); if (i < 0) { return 0; } if (has_config(i)) { load_volume_settings(i); } else { frob_mixer(i); } } else if(argc >= 2) { int card_number = ALL_CARDS; if(argc == 3) { card_number = atoi(argv[2]); } if(argv[1][1] == 'l') { load_volume_settings(card_number); } else if(argv[1][1] == 's') { save_volume_settings(card_number); } else { banner(); } } return(0); }