Martin Stransky 5e20f4
/* Copyright 2007 Red Hat, Inc.
Bill Nottingham 0e0d15
 *
Bill Nottingham 0e0d15
 * Portions extraced from various ALSA code:
Bill Nottingham 0e0d15
 *  Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
Bill Nottingham 0e0d15
 *                   Jaroslav Kysela <perex@suse.cz>
Bill Nottingham 0e0d15
 *
Bill Nottingham 0e0d15
 * This software may be freely redistributed under the terms of the GNU
Bill Nottingham 0e0d15
 * public license.
Bill Nottingham 0e0d15
 *
Bill Nottingham 0e0d15
 * You should have received a copy of the GNU General Public License
Bill Nottingham 0e0d15
 * along with this program; if not, write to the Free Software
Bill Nottingham 0e0d15
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Bill Nottingham 0e0d15
 *
Bill Nottingham 0e0d15
 */
Bill Nottingham 6c53f8
Bill Nottingham 6c53f8
#include <stdio.h>
Bill Nottingham 6c53f8
#include <stdlib.h>
Bill Nottingham 6c53f8
#include <string.h>
Martin Stransky 5e20f4
#include <time.h>
Bill Nottingham 6c53f8
Bill Nottingham 6c53f8
#include <alsa/asoundlib.h>
Bill Nottingham 6c53f8
Martin Stransky 5e20f4
#define ALSA_CONFIG_PATH	"/etc/alsa/asound.state"
Martin Stransky 5e20f4
#define ALL_CARDS         	(-1)
Martin Stransky 5e20f4
Bill Nottingham 6c53f8
Bill Nottingham 6c53f8
int get_card_number()
Bill Nottingham 6c53f8
{
Martin Stransky 2351ac
  char *devname, *action;
Martin Stransky 2351ac
Martin Stransky 2351ac
  action = getenv("ACTION");
Martin Stransky 2351ac
  if (!action || strcmp(action, "add"))
Martin Stransky 2351ac
    return -1;
Martin Stransky 2351ac
  devname = getenv("DEVNAME");
Martin Stransky 2351ac
  if (!devname)
Martin Stransky 2351ac
    return -1;
Martin Stransky 2351ac
  if (!strncmp(devname, "/dev/snd/controlC", 17))
Martin Stransky 2351ac
    return atoi(devname + 17);
Martin Stransky 2351ac
  if (!strncmp(devname, "/dev/snd/pcmC", 13))
Martin Stransky 2351ac
    return atoi(devname + 13);
Martin Stransky 2351ac
  return -1;
Bill Nottingham 6c53f8
}
Bill Nottingham 6c53f8
Bill Nottingham 6c53f8
int has_config(int index)
Bill Nottingham 6c53f8
{
Martin Stransky 2351ac
  int rc = 0;
Martin Stransky 2351ac
  snd_config_t *config, *control;
Martin Stransky 2351ac
  snd_input_t *in;
Martin Stransky 2351ac
  snd_ctl_t *handle;
Martin Stransky 2351ac
  snd_ctl_card_info_t *info;
Martin Stransky 2351ac
  const char *id;
Martin Stransky 5e20f4
  char path[32];  
Martin Stransky 5e20f4
  
Martin Stransky 2351ac
  rc = snd_config_top(&config);
Martin Stransky 2351ac
  if (rc < 0)
Martin Stransky 2351ac
    goto out;
Martin Stransky 2351ac
  rc = snd_input_stdio_open(&in, ALSA_CONFIG_PATH, "r");
Martin Stransky 2351ac
  if (rc >= 0) {
Martin Stransky 2351ac
    rc = snd_config_load(config, in);
Martin Stransky 2351ac
    snd_input_close(in);
Martin Stransky 2351ac
    if (rc < 0)
Martin Stransky 2351ac
      goto out;
Martin Stransky 2351ac
  }
Martin Stransky 2351ac
  sprintf(path, "hw:%d", index);
Martin Stransky 2351ac
  rc = snd_ctl_open(&handle, path, 0);
Martin Stransky 2351ac
  if (rc < 0)
Martin Stransky 2351ac
    goto out;
Martin Stransky 2351ac
  snd_ctl_card_info_alloca(&info;;
Martin Stransky 2351ac
  rc = snd_ctl_card_info(handle, info);
Martin Stransky 2351ac
  if (rc < 0)
Martin Stransky 2351ac
    goto out_close;
Martin Stransky 2351ac
  id = snd_ctl_card_info_get_id(info);
Martin Stransky 2351ac
  rc = snd_config_searchv(config, &control, "state", id, "control", 0);
Bill Nottingham 6c53f8
out_close:
Martin Stransky 2351ac
  snd_ctl_close(handle);
Bill Nottingham 6c53f8
out:
Martin Stransky 2351ac
  return !rc;
Martin Stransky 2351ac
Bill Nottingham 6c53f8
}
Bill Nottingham 6c53f8
Martin Stransky 5e20f4
void load_volume_settings(int index)
Bill Nottingham 6c53f8
{
Martin Stransky 5e20f4
  char *args[] = { "/sbin/alsactl", "-f", ALSA_CONFIG_PATH, "restore", NULL, NULL };
Martin Stransky 5e20f4
  char  num[10];
Martin Stransky 5e20f4
Martin Stransky 5e20f4
  if(index != ALL_CARDS) {
Martin Stransky 5e20f4
    snprintf(num, 10, "%d", index);
Martin Stransky 5e20f4
    args[4] = num;
Martin Stransky 5e20f4
  }
Martin Stransky 5e20f4
  
Martin Stransky 5e20f4
  execv(args[0], args);  
Martin Stransky 5e20f4
}
Martin Stransky 2351ac
Martin Stransky 5e20f4
void save_volume_settings(int index)
Martin Stransky 5e20f4
{
Martin Stransky 5e20f4
  char *args[] = { "/sbin/alsactl", "-f", ALSA_CONFIG_PATH, "store", NULL, NULL };
Martin Stransky 5e20f4
  char  num[10];
Martin Stransky 5e20f4
  
Martin Stransky 5e20f4
  if(index != ALL_CARDS) {
Martin Stransky 5e20f4
    snprintf(num, 10, "%d", index);
Martin Stransky 5e20f4
    args[4] = num;    
Martin Stransky 5e20f4
  }
Martin Stransky 5e20f4
  
Martin Stransky 2351ac
  execv(args[0], args);
Bill Nottingham 6c53f8
}
Bill Nottingham 6c53f8
Martin Stransky 2351ac
void frob_mixer(int index)
Bill Nottingham 6c53f8
{
Martin Stransky 2351ac
  char tmp[100];  
Martin Stransky 2351ac
  snprintf(tmp, 100, "%d", index);
Martin Stransky 2351ac
  tmp[99] = '\0';
Bill Nottingham 6a536a
  execl("/bin/alsaunmute","/bin/alsaunmute", tmp, "-v", NULL);
Bill Nottingham 6c53f8
}
Bill Nottingham 6c53f8
Martin Stransky 5e20f4
void banner(void)
Martin Stransky 5e20f4
{
Martin Stransky 5e20f4
  printf("ALSA volume settings handler, Copyright 2007 Red Hat, Inc.\n");
Martin Stransky 5e20f4
  printf("This software may be freely redistributed under\nthe terms of the GNU public license.\n\n");
Martin Stransky 5e20f4
  
Martin Stransky 5e20f4
  printf("Usage: salsa [options] [card number]\n\n");
Martin Stransky 5e20f4
  printf(" Options:\n");
Martin Stransky 5e20f4
  printf("    -l      - Load volume settings\n");
Martin Stransky 5e20f4
  printf("    -s      - Save volume settings\n\n");
Martin Stransky 5e20f4
  printf(" Card number:\n");
Martin Stransky 5e20f4
  printf("    ##      - An affected card. If it isn't specified,\n");
Martin Stransky 5e20f4
  printf("              configure all installed sound cards.\n\n");
Martin Stransky 5e20f4
  
Martin Stransky 5e20f4
  exit(0);   
Martin Stransky 5e20f4
}
Martin Stransky 5e20f4
Bill Nottingham 6c53f8
int main(int argc, char **argv)
Bill Nottingham 6c53f8
{
Martin Stransky 2351ac
  int i;
Martin Stransky 5e20f4
  
Martin Stransky 5e20f4
  if(argc == 1) {
Martin Stransky 5e20f4
    i = get_card_number();
Martin Stransky 5e20f4
    if (i < 0) {
Martin Stransky 5e20f4
      return 0;
Martin Stransky 5e20f4
    }
Martin Stransky 5e20f4
    if (has_config(i)) {
Martin Stransky 5e20f4
      load_volume_settings(i);
Martin Stransky 5e20f4
    }
Martin Stransky 5e20f4
    else {
Martin Stransky 5e20f4
      frob_mixer(i);
Martin Stransky 5e20f4
    }
Martin Stransky 5e20f4
  }
Martin Stransky 5e20f4
  else if(argc >= 2) {
Martin Stransky 5e20f4
    
Martin Stransky 5e20f4
    int card_number = ALL_CARDS;
Martin Stransky 5e20f4
    if(argc == 3) {
Martin Stransky 5e20f4
      card_number = atoi(argv[2]);
Martin Stransky 5e20f4
    }
Martin Stransky 5e20f4
    
Martin Stransky 5e20f4
    if(argv[1][1] == 'l') {
Martin Stransky 5e20f4
      load_volume_settings(card_number);
Martin Stransky 5e20f4
    }
Martin Stransky 5e20f4
    else if(argv[1][1] == 's') {
Martin Stransky 5e20f4
      save_volume_settings(card_number);
Martin Stransky 5e20f4
    }
Martin Stransky 5e20f4
    else {
Martin Stransky 5e20f4
      banner();
Martin Stransky 5e20f4
    }
Martin Stransky 5e20f4
  }
Martin Stransky 2351ac
  
Martin Stransky 2351ac
  return(0);
Bill Nottingham 6c53f8
}