163 lines
3.9 KiB
C
163 lines
3.9 KiB
C
/* Copyright 2005 Red Hat, Inc.
|
|
*
|
|
* Portions extraced from various ALSA code:
|
|
* Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
|
|
* Jaroslav Kysela <perex@suse.cz>
|
|
*
|
|
* 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include <alsa/asoundlib.h>
|
|
|
|
#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") ||
|
|
!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;
|
|
}
|
|
|
|
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);
|
|
}
|