mixer.c revision 144999
16448Sache/* 26448Sache * This is an example of a mixer program for Linux 36448Sache * 46448Sache * updated 1/1/93 to add stereo, level query, broken 58857Srgrimes * devmask kludge - cmetz@thor.tjhsst.edu 66448Sache * 76448Sache * (C) Craig Metz and Hannu Savolainen 1993. 86448Sache * 96448Sache * You may do anything you wish with this program. 1029612Sjmg * 1129612Sjmg * ditto for my modifications (John-Mark Gurney, 1997) 126448Sache */ 136448Sache 14114601Sobrien#include <sys/cdefs.h> 15114601Sobrien__FBSDID("$FreeBSD: head/usr.sbin/mixer/mixer.c 144999 2005-04-13 07:11:54Z mdodd $"); 1629963Scharnier 1729963Scharnier#include <err.h> 1829963Scharnier#include <fcntl.h> 196448Sache#include <stdio.h> 206448Sache#include <string.h> 2129612Sjmg#include <stdlib.h> 2229612Sjmg#include <unistd.h> 236448Sache#include <sys/soundcard.h> 246448Sache 2578778Sddconst char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 266448Sache 2729612Sjmgvoid usage(int devmask, int recmask); 2829612Sjmgint res_name(const char *name, int mask); 2929612Sjmgvoid print_recsrc(int recsrc); 306448Sache 3129612Sjmgvoid 3229612Sjmgusage(int devmask, int recmask) 336448Sache{ 3429612Sjmg int i, n; 356448Sache 36144999Smdodd printf("usage: mixer [-f device] [-s | -S] [dev [+|-][voll[:[+|-]volr]] ...\n" 37144999Smdodd " mixer [-f device] [-s | -S] recsrc ...\n" 38144999Smdodd " mixer [-f device] [-s | -S] {^|+|-|=}rec rdev ... \n"); 3929753Sache printf(" devices: "); 4029612Sjmg for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 416448Sache if ((1 << i) & devmask) { 426448Sache if (n) 4329612Sjmg printf(", "); 4469258Skris printf("%s", names[i]); 456448Sache n = 1; 468857Srgrimes } 4729753Sache printf("\n rec devices: "); 4829612Sjmg for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 4929612Sjmg if ((1 << i) & recmask) { 5029612Sjmg if (n) 5129612Sjmg printf(", "); 5269258Skris printf("%s", names[i]); 5329612Sjmg n = 1; 5429612Sjmg } 5529612Sjmg printf("\n"); 566448Sache exit(1); 576448Sache} 586448Sache 5929612Sjmgint 6029612Sjmgres_name(const char *name, int mask) 616448Sache{ 6229612Sjmg int foo; 6329612Sjmg 6429612Sjmg for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) 6529612Sjmg if ((1 << foo) & mask && !strcmp(names[foo], name)) 6629612Sjmg break; 6729612Sjmg 6829612Sjmg return foo == SOUND_MIXER_NRDEVICES ? -1 : foo; 6929612Sjmg} 7029612Sjmg 7129612Sjmgvoid 7229612Sjmgprint_recsrc(int recsrc) 7329612Sjmg{ 746448Sache int i, n = 0; 756448Sache fprintf(stderr, "Recording source: "); 766448Sache 776448Sache for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 786448Sache if ((1 << i) & recsrc) { 796448Sache if (n) 806448Sache fprintf(stderr, ", "); 8169258Skris fprintf(stderr, "%s", names[i]); 826448Sache n = 1; 836448Sache } 846448Sache fprintf(stderr, "\n"); 856448Sache} 866448Sache 878857Srgrimesint 886448Sachemain(int argc, char *argv[]) 896448Sache{ 906448Sache int foo, bar, baz, dev; 9129612Sjmg int devmask = 0, recmask = 0, recsrc = 0, orecsrc; 92144999Smdodd int dusage = 0, drecsrc = 0, shortflag = 0, Shortflag = 0; 9375334Sgreid int l = 0, r = 0, t = 0; 94113299Smdodd char lstr[5], rstr[5]; 95113299Smdodd int n = 0, lrel = 0, rrel = 0; 96124830Sgrehan int ch; 976448Sache 9829612Sjmg char *name; 996448Sache 10029612Sjmg name = strdup("/dev/mixer"); 10129612Sjmg 1026448Sache if (!strcmp(argv[0], "mixer2")) 10329612Sjmg name = strdup("/dev/mixer1"); 10429612Sjmg else if (!strcmp(argv[0], "mixer3")) 10529612Sjmg name = strdup("/dev/mixer2"); 1066448Sache 107144999Smdodd while ((ch = getopt(argc, argv, "f:sS")) != -1) 10864657Ssobomax switch (ch) { 10964657Ssobomax case 'f': 11064657Ssobomax name = strdup(optarg); 11164657Ssobomax break; 11264657Ssobomax case 's': 11364657Ssobomax shortflag = 1; 11464657Ssobomax break; 115144999Smdodd case 'S': 116144999Smdodd Shortflag = 1; 117144999Smdodd break; 11864657Ssobomax default: 11964657Ssobomax dusage = 1; 12064657Ssobomax } 12164657Ssobomax argc -= (optind - 1); 12264657Ssobomax argv += (optind - 1); 12329612Sjmg 12429963Scharnier if ((baz = open(name, O_RDWR)) < 0) 12529963Scharnier err(1, "%s", name); 12629612Sjmg free(name); 12729963Scharnier if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 12830028Scharnier err(1, "SOUND_MIXER_READ_DEVMASK"); 12929963Scharnier if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 13030028Scharnier err(1, "SOUND_MIXER_READ_RECMASK"); 13129963Scharnier if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 13230028Scharnier err(1, "SOUND_MIXER_READ_RECSRC"); 13329612Sjmg orecsrc = recsrc; 1346448Sache 13564657Ssobomax if ((argc == 1) && (dusage == 0)) { 13613803Smpp for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { 13713803Smpp if (!((1 << foo) & devmask)) 13813803Smpp continue; 13913803Smpp if (ioctl(baz, MIXER_READ(foo),&bar)== -1) { 14029963Scharnier warn("MIXER_READ"); 14113803Smpp continue; 14213803Smpp } 143144999Smdodd if (Shortflag) 144144999Smdodd printf("%s:%d:%d ", names[foo], bar & 0x7f, 145144999Smdodd (bar >> 8) & 0x7f); 146144999Smdodd else if (shortflag) 147116388Sgrog printf("%s %d:%d ", names[foo], bar & 0x7f, 148116388Sgrog (bar >> 8) & 0x7f); 14960741Sjkh else 150116388Sgrog printf("Mixer %-8s is currently set to %3d:%d\n", 151116388Sgrog names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 15213803Smpp } 153116388Sgrog if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 154116388Sgrog err(1, "SOUND_MIXER_READ_RECSRC"); 155116388Sgrog print_recsrc(recsrc); 15613803Smpp return(0); 15713803Smpp } 15813803Smpp 15929612Sjmg argc--; argv++; 1606448Sache 16175334Sgreid while ((argc > 0) && (dusage == 0)) { 16229612Sjmg if (!strcmp("recsrc", *argv)) { 16329612Sjmg drecsrc = 1; 16429612Sjmg argc--; argv++; 16529612Sjmg continue; 16629612Sjmg } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 16729612Sjmg if (**argv != '+' && **argv != '-' && 16829612Sjmg **argv != '=' && **argv != '^') { 16964657Ssobomax warnx("unknown modifier: %c", **argv); 17029612Sjmg dusage = 1; 17164657Ssobomax break; 17213435Smpp } 17329612Sjmg if ((dev = res_name(argv[1], recmask)) == -1) { 17464657Ssobomax warnx("unknown recording device: %s", argv[1]); 17529612Sjmg dusage = 1; 17664657Ssobomax break; 1776448Sache } 17829612Sjmg switch(**argv) { 17929612Sjmg case '+': 1806448Sache recsrc |= (1 << dev); 18129612Sjmg break; 18229612Sjmg case '-': 1836448Sache recsrc &= ~(1 << dev); 18429612Sjmg break; 18529612Sjmg case '=': 18629612Sjmg recsrc = (1 << dev); 18729612Sjmg break; 18829612Sjmg case '^': 18929612Sjmg recsrc ^= (1 << dev); 19029612Sjmg break; 19129612Sjmg } 19229612Sjmg drecsrc = 1; 19329612Sjmg argc -= 2; argv += 2; 19429612Sjmg continue; 19529612Sjmg } 1966448Sache 19775334Sgreid if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) { 19875334Sgreid dev = 0; 19975334Sgreid } 20075334Sgreid else if((dev = res_name(*argv, devmask)) == -1) { 20164657Ssobomax warnx("unknown device: %s", *argv); 20229612Sjmg dusage = 1; 20364657Ssobomax break; 20429612Sjmg } 20529612Sjmg 206113299Smdodd#define issign(c) (((c) == '+') || ((c) == '-')) 207113299Smdodd 208113299Smdodd if (argc > 1) { 209113299Smdodd n = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr); 210113299Smdodd if (n > 0) { 211113299Smdodd if (issign(lstr[0])) 212113299Smdodd lrel = rrel = 1; 213113299Smdodd l = atoi(lstr); 214113299Smdodd } 215113299Smdodd if (n > 1) { 216113299Smdodd rrel = 0; 217113299Smdodd if (issign(rstr[0])) 218113299Smdodd rrel = 1; 219113299Smdodd r = atoi(rstr); 220113299Smdodd } 221113299Smdodd } 222113299Smdodd 223113299Smdodd switch(argc > 1 ? n : t) { 22429612Sjmg case 0: 22529612Sjmg if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 22629963Scharnier warn("MIXER_READ"); 22729612Sjmg argc--; argv++; 22829612Sjmg continue; 2296448Sache } 230144999Smdodd if (Shortflag) 231144999Smdodd printf("%s:%d:%d ", names[dev], bar & 0x7f, 232144999Smdodd (bar >> 8) & 0x7f); 233144999Smdodd else if (shortflag) 234116388Sgrog printf("%s %d:%d ", names[dev], bar & 0x7f, 235116388Sgrog (bar >> 8) & 0x7f); 23660741Sjkh else 23760741Sjkh printf("Mixer %-8s is currently set to %3d:%d\n", 23860741Sjkh names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 2396448Sache 24029612Sjmg argc--; argv++; 24129612Sjmg break; 24229612Sjmg case 1: 24329612Sjmg r = l; 24429612Sjmg case 2: 245113299Smdodd if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 246113299Smdodd warn("MIXER_READ"); 247113299Smdodd argc--; argv++; 248113299Smdodd continue; 249113299Smdodd } 250113299Smdodd 251113299Smdodd if (lrel) 252113299Smdodd l = (bar & 0x7f) + l; 253113299Smdodd if (rrel) 254113299Smdodd r = ((bar >> 8) & 0x7f) + r; 255113299Smdodd 25629612Sjmg if (l < 0) 25729612Sjmg l = 0; 25829612Sjmg else if (l > 100) 25929612Sjmg l = 100; 26029612Sjmg if (r < 0) 26129612Sjmg r = 0; 26229612Sjmg else if (r > 100) 26329612Sjmg r = 100; 2648857Srgrimes 265144999Smdodd if (!Shortflag) 266144999Smdodd printf("Setting the mixer %s from %d:%d to %d:%d.\n", 267144999Smdodd names[dev], bar & 0x7f, (bar >> 8) & 0x7f, l, r); 268108421Sjmallett 26929612Sjmg l |= r << 8; 27029612Sjmg if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 27129963Scharnier warn("WRITE_MIXER"); 2726448Sache 27329612Sjmg argc -= 2; argv += 2; 27429612Sjmg break; 2756448Sache } 2766448Sache } 2776448Sache 27864657Ssobomax if (dusage) { 27964657Ssobomax close(baz); 28064657Ssobomax usage(devmask, recmask); 28164657Ssobomax /* Not reached */ 28264657Ssobomax } 28364657Ssobomax 28429612Sjmg if (orecsrc != recsrc) 28529963Scharnier if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 28630028Scharnier err(1, "SOUND_MIXER_WRITE_RECSRC"); 28729612Sjmg 28829612Sjmg if (drecsrc) { 28929963Scharnier if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 29030028Scharnier err(1, "SOUND_MIXER_READ_RECSRC"); 29129612Sjmg print_recsrc(recsrc); 29229612Sjmg } 29329612Sjmg 2946448Sache close(baz); 29529612Sjmg 29629612Sjmg exit(0); 2976448Sache} 298