mixer.c revision 177195
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 177195 2008-03-15 01:09:47Z jkim $"); 1629963Scharnier 1729963Scharnier#include <err.h> 1829963Scharnier#include <fcntl.h> 19177195Sjkim#include <libgen.h> 20177195Sjkim#include <limits.h> 216448Sache#include <stdio.h> 226448Sache#include <string.h> 2329612Sjmg#include <stdlib.h> 2429612Sjmg#include <unistd.h> 256448Sache#include <sys/soundcard.h> 266448Sache 2778778Sddconst char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 286448Sache 2929612Sjmgvoid usage(int devmask, int recmask); 3029612Sjmgint res_name(const char *name, int mask); 31177195Sjkimvoid print_recsrc(int recsrc, int recmask, int shortflag); 326448Sache 3329612Sjmgvoid 3429612Sjmgusage(int devmask, int recmask) 356448Sache{ 3629612Sjmg int i, n; 376448Sache 38144999Smdodd printf("usage: mixer [-f device] [-s | -S] [dev [+|-][voll[:[+|-]volr]] ...\n" 39144999Smdodd " mixer [-f device] [-s | -S] recsrc ...\n" 40144999Smdodd " mixer [-f device] [-s | -S] {^|+|-|=}rec rdev ... \n"); 41177195Sjkim if (devmask != 0) { 42177195Sjkim printf(" devices: "); 43177195Sjkim for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 44177195Sjkim if ((1 << i) & devmask) { 45177195Sjkim if (n) 46177195Sjkim printf(", "); 47177195Sjkim printf("%s", names[i]); 48177195Sjkim n = 1; 49177195Sjkim } 50177195Sjkim } 51177195Sjkim if (recmask != 0) { 52177195Sjkim printf("\n rec devices: "); 53177195Sjkim for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 54177195Sjkim if ((1 << i) & recmask) { 55177195Sjkim if (n) 56177195Sjkim printf(", "); 57177195Sjkim printf("%s", names[i]); 58177195Sjkim n = 1; 59177195Sjkim } 60177195Sjkim } 6129612Sjmg printf("\n"); 626448Sache exit(1); 636448Sache} 646448Sache 6529612Sjmgint 6629612Sjmgres_name(const char *name, int mask) 676448Sache{ 6829612Sjmg int foo; 6929612Sjmg 7029612Sjmg for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) 7129612Sjmg if ((1 << foo) & mask && !strcmp(names[foo], name)) 7229612Sjmg break; 7329612Sjmg 7429612Sjmg return foo == SOUND_MIXER_NRDEVICES ? -1 : foo; 7529612Sjmg} 7629612Sjmg 7729612Sjmgvoid 78177195Sjkimprint_recsrc(int recsrc, int recmask, int shortflag) 7929612Sjmg{ 806448Sache int i, n = 0; 816448Sache 82177195Sjkim if (recmask == 0) 83177195Sjkim return; 84177195Sjkim 85153953Sariff if (!shortflag) 86153953Sariff printf("Recording source: "); 87153953Sariff 886448Sache for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 896448Sache if ((1 << i) & recsrc) { 90153953Sariff if (shortflag) { 91153953Sariff if (n) 92153953Sariff printf(" +rec "); 93153953Sariff else 94153953Sariff printf("=rec "); 95153953Sariff } else if (n) 96153953Sariff printf(", "); 97153953Sariff printf("%s", names[i]); 986448Sache n = 1; 996448Sache } 100153953Sariff if (!shortflag) 101153953Sariff printf("\n"); 1026448Sache} 1036448Sache 1048857Srgrimesint 1056448Sachemain(int argc, char *argv[]) 1066448Sache{ 107177195Sjkim char mixer[PATH_MAX] = "/dev/mixer"; 108177195Sjkim char *name, *eptr; 1096448Sache int foo, bar, baz, dev; 11029612Sjmg int devmask = 0, recmask = 0, recsrc = 0, orecsrc; 111144999Smdodd int dusage = 0, drecsrc = 0, shortflag = 0, Shortflag = 0; 11275334Sgreid int l = 0, r = 0, t = 0; 113113299Smdodd char lstr[5], rstr[5]; 114177195Sjkim int n, lrel = 0, rrel = 0; 115177195Sjkim char ch; 1166448Sache 117177195Sjkim if ((name = strdup(basename(argv[0]))) == NULL) 118177195Sjkim err(1, "strdup()"); 119177195Sjkim if (strncmp(name, "mixer", 5) == 0 && name[5] != '\0') { 120177195Sjkim n = strtol(name + 5, &eptr, 10) - 1; 121177195Sjkim if (n > 0 && *eptr == '\0') 122177195Sjkim snprintf(mixer, PATH_MAX - 1, "/dev/mixer%d", n); 123177195Sjkim } 124177195Sjkim free(name); 125177195Sjkim name = mixer; 1266448Sache 127177195Sjkim n = 1; 128177195Sjkim for (;;) { 129177195Sjkim if (n >= argc || *argv[n] != '-') 130177195Sjkim break; 131177195Sjkim if (strlen(argv[n]) != 2) { 132177195Sjkim if (strcmp(argv[n] + 1, "rec") != 0) 13364657Ssobomax dusage = 1; 134177195Sjkim break; 13564657Ssobomax } 136177195Sjkim ch = *(argv[n] + 1); 137177195Sjkim if (ch == 'f' && n < argc - 1) { 138177195Sjkim name = argv[n + 1]; 139177195Sjkim n += 2; 140177195Sjkim } else if (ch == 's') { 141177195Sjkim shortflag = 1; 142177195Sjkim n++; 143177195Sjkim } else if (ch == 'S') { 144177195Sjkim Shortflag = 1; 145177195Sjkim n++; 146177195Sjkim } else { 147177195Sjkim dusage = 1; 148177195Sjkim break; 149177195Sjkim } 150177195Sjkim } 151177195Sjkim if (shortflag && Shortflag) 152177195Sjkim dusage = 1; 15329612Sjmg 154177195Sjkim argc -= n - 1; 155177195Sjkim argv += n - 1; 156177195Sjkim 15729963Scharnier if ((baz = open(name, O_RDWR)) < 0) 15829963Scharnier err(1, "%s", name); 15929963Scharnier if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 16030028Scharnier err(1, "SOUND_MIXER_READ_DEVMASK"); 16129963Scharnier if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 16230028Scharnier err(1, "SOUND_MIXER_READ_RECMASK"); 16329963Scharnier if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 16430028Scharnier err(1, "SOUND_MIXER_READ_RECSRC"); 16529612Sjmg orecsrc = recsrc; 1666448Sache 16764657Ssobomax if ((argc == 1) && (dusage == 0)) { 16813803Smpp for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { 16913803Smpp if (!((1 << foo) & devmask)) 17013803Smpp continue; 17113803Smpp if (ioctl(baz, MIXER_READ(foo),&bar)== -1) { 17229963Scharnier warn("MIXER_READ"); 17313803Smpp continue; 17413803Smpp } 175144999Smdodd if (Shortflag) 176144999Smdodd printf("%s:%d:%d ", names[foo], bar & 0x7f, 177144999Smdodd (bar >> 8) & 0x7f); 178144999Smdodd else if (shortflag) 179116388Sgrog printf("%s %d:%d ", names[foo], bar & 0x7f, 180116388Sgrog (bar >> 8) & 0x7f); 18160741Sjkh else 182116388Sgrog printf("Mixer %-8s is currently set to %3d:%d\n", 183116388Sgrog names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 18413803Smpp } 185116388Sgrog if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 186116388Sgrog err(1, "SOUND_MIXER_READ_RECSRC"); 187177195Sjkim print_recsrc(recsrc, recmask, shortflag || Shortflag); 18813803Smpp return(0); 18913803Smpp } 19013803Smpp 19129612Sjmg argc--; argv++; 1926448Sache 19375334Sgreid while ((argc > 0) && (dusage == 0)) { 19429612Sjmg if (!strcmp("recsrc", *argv)) { 19529612Sjmg drecsrc = 1; 19629612Sjmg argc--; argv++; 19729612Sjmg continue; 19829612Sjmg } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 19929612Sjmg if (**argv != '+' && **argv != '-' && 20029612Sjmg **argv != '=' && **argv != '^') { 20164657Ssobomax warnx("unknown modifier: %c", **argv); 20229612Sjmg dusage = 1; 20364657Ssobomax break; 20413435Smpp } 20529612Sjmg if ((dev = res_name(argv[1], recmask)) == -1) { 20664657Ssobomax warnx("unknown recording device: %s", argv[1]); 20729612Sjmg dusage = 1; 20864657Ssobomax break; 2096448Sache } 21029612Sjmg switch(**argv) { 21129612Sjmg case '+': 2126448Sache recsrc |= (1 << dev); 21329612Sjmg break; 21429612Sjmg case '-': 2156448Sache recsrc &= ~(1 << dev); 21629612Sjmg break; 21729612Sjmg case '=': 21829612Sjmg recsrc = (1 << dev); 21929612Sjmg break; 22029612Sjmg case '^': 22129612Sjmg recsrc ^= (1 << dev); 22229612Sjmg break; 22329612Sjmg } 22429612Sjmg drecsrc = 1; 22529612Sjmg argc -= 2; argv += 2; 22629612Sjmg continue; 22729612Sjmg } 2286448Sache 22975334Sgreid if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) { 23075334Sgreid dev = 0; 23175334Sgreid } 23275334Sgreid else if((dev = res_name(*argv, devmask)) == -1) { 23364657Ssobomax warnx("unknown device: %s", *argv); 23429612Sjmg dusage = 1; 23564657Ssobomax break; 23629612Sjmg } 23729612Sjmg 238113299Smdodd#define issign(c) (((c) == '+') || ((c) == '-')) 239113299Smdodd 240113299Smdodd if (argc > 1) { 241113299Smdodd n = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr); 242113299Smdodd if (n > 0) { 243113299Smdodd if (issign(lstr[0])) 244113299Smdodd lrel = rrel = 1; 245113299Smdodd l = atoi(lstr); 246113299Smdodd } 247113299Smdodd if (n > 1) { 248113299Smdodd rrel = 0; 249113299Smdodd if (issign(rstr[0])) 250113299Smdodd rrel = 1; 251113299Smdodd r = atoi(rstr); 252113299Smdodd } 253113299Smdodd } 254113299Smdodd 255113299Smdodd switch(argc > 1 ? n : t) { 25629612Sjmg case 0: 25729612Sjmg if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 25829963Scharnier warn("MIXER_READ"); 25929612Sjmg argc--; argv++; 26029612Sjmg continue; 2616448Sache } 262144999Smdodd if (Shortflag) 263144999Smdodd printf("%s:%d:%d ", names[dev], bar & 0x7f, 264144999Smdodd (bar >> 8) & 0x7f); 265144999Smdodd else if (shortflag) 266116388Sgrog printf("%s %d:%d ", names[dev], bar & 0x7f, 267116388Sgrog (bar >> 8) & 0x7f); 26860741Sjkh else 26960741Sjkh printf("Mixer %-8s is currently set to %3d:%d\n", 27060741Sjkh names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 2716448Sache 27229612Sjmg argc--; argv++; 27329612Sjmg break; 27429612Sjmg case 1: 27529612Sjmg r = l; 27629612Sjmg case 2: 277113299Smdodd if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 278113299Smdodd warn("MIXER_READ"); 279113299Smdodd argc--; argv++; 280113299Smdodd continue; 281113299Smdodd } 282113299Smdodd 283113299Smdodd if (lrel) 284113299Smdodd l = (bar & 0x7f) + l; 285113299Smdodd if (rrel) 286113299Smdodd r = ((bar >> 8) & 0x7f) + r; 287113299Smdodd 28829612Sjmg if (l < 0) 28929612Sjmg l = 0; 29029612Sjmg else if (l > 100) 29129612Sjmg l = 100; 29229612Sjmg if (r < 0) 29329612Sjmg r = 0; 29429612Sjmg else if (r > 100) 29529612Sjmg r = 100; 2968857Srgrimes 297144999Smdodd if (!Shortflag) 298144999Smdodd printf("Setting the mixer %s from %d:%d to %d:%d.\n", 299144999Smdodd names[dev], bar & 0x7f, (bar >> 8) & 0x7f, l, r); 300108421Sjmallett 30129612Sjmg l |= r << 8; 30229612Sjmg if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 30329963Scharnier warn("WRITE_MIXER"); 3046448Sache 30529612Sjmg argc -= 2; argv += 2; 30629612Sjmg break; 3076448Sache } 3086448Sache } 3096448Sache 31064657Ssobomax if (dusage) { 31164657Ssobomax close(baz); 31264657Ssobomax usage(devmask, recmask); 31364657Ssobomax /* Not reached */ 31464657Ssobomax } 31564657Ssobomax 316177195Sjkim if (orecsrc != recsrc) { 31729963Scharnier if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 31830028Scharnier err(1, "SOUND_MIXER_WRITE_RECSRC"); 31929963Scharnier if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 32030028Scharnier err(1, "SOUND_MIXER_READ_RECSRC"); 32129612Sjmg } 322177195Sjkim 323177195Sjkim if (drecsrc) 324177195Sjkim print_recsrc(recsrc, recmask, shortflag || Shortflag); 32529612Sjmg 3266448Sache close(baz); 32729612Sjmg 32829612Sjmg exit(0); 3296448Sache} 330