/* Copyright 2005 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 #define ALSA_CONFIG_PATH "/etc/asound.state" 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; } 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; } int 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")) { 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; } 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); }