diff options
Diffstat (limited to 'usr.sbin/mixer/mixer.c')
-rw-r--r-- | usr.sbin/mixer/mixer.c | 336 |
1 files changed, 336 insertions, 0 deletions
diff --git a/usr.sbin/mixer/mixer.c b/usr.sbin/mixer/mixer.c new file mode 100644 index 0000000..49b57d8 --- /dev/null +++ b/usr.sbin/mixer/mixer.c @@ -0,0 +1,336 @@ +/* + * This is an example of a mixer program for Linux + * + * updated 1/1/93 to add stereo, level query, broken + * devmask kludge - cmetz@thor.tjhsst.edu + * + * (C) Craig Metz and Hannu Savolainen 1993. + * + * You may do anything you wish with this program. + * + * ditto for my modifications (John-Mark Gurney, 1997) + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <err.h> +#include <fcntl.h> +#include <libgen.h> +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/soundcard.h> + +static const char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; + +static void usage(int devmask, int recmask); +static int res_name(const char *name, int mask); +static void print_recsrc(int recsrc, int recmask, int sflag); + +static void +usage(int devmask, int recmask) +{ + int i, n; + + printf("usage: mixer [-f device] [-s | -S] [dev [+|-][voll[:[+|-]volr]] ...\n" + " mixer [-f device] [-s | -S] recsrc ...\n" + " mixer [-f device] [-s | -S] {^|+|-|=}rec rdev ...\n"); + if (devmask != 0) { + printf(" devices: "); + for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) + if ((1 << i) & devmask) { + if (n) + printf(", "); + printf("%s", names[i]); + n++; + } + } + if (recmask != 0) { + printf("\n rec devices: "); + for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) + if ((1 << i) & recmask) { + if (n) + printf(", "); + printf("%s", names[i]); + n++; + } + } + printf("\n"); + exit(1); +} + +static int +res_name(const char *name, int mask) +{ + int foo; + + for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) + if ((1 << foo) & mask && strcmp(names[foo], name) == 0) + break; + + return (foo == SOUND_MIXER_NRDEVICES ? -1 : foo); +} + +static void +print_recsrc(int recsrc, int recmask, int sflag) +{ + int i, n; + + if (recmask == 0) + return; + + if (!sflag) + printf("Recording source: "); + + for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) + if ((1 << i) & recsrc) { + if (sflag) + printf("%srec ", n ? " +" : "="); + else if (n) + printf(", "); + printf("%s", names[i]); + n++; + } + if (!sflag) + printf("\n"); +} + +int +main(int argc, char *argv[]) +{ + char mixer[PATH_MAX] = "/dev/mixer"; + char lstr[5], rstr[5]; + char *name, *eptr; + int devmask = 0, recmask = 0, recsrc = 0, orecsrc; + int dusage = 0, drecsrc = 0, sflag = 0, Sflag = 0; + int l, r, lrel, rrel; + int ch, foo, bar, baz, dev, m, n, t; + + if ((name = strdup(basename(argv[0]))) == NULL) + err(1, "strdup()"); + if (strncmp(name, "mixer", 5) == 0 && name[5] != '\0') { + n = strtol(name + 5, &eptr, 10) - 1; + if (n > 0 && *eptr == '\0') + snprintf(mixer, PATH_MAX - 1, "/dev/mixer%d", n); + } + free(name); + name = mixer; + + n = 1; + for (;;) { + if (n >= argc || *argv[n] != '-') + break; + if (strlen(argv[n]) != 2) { + if (strcmp(argv[n] + 1, "rec") != 0) + dusage = 1; + break; + } + ch = *(argv[n] + 1); + if (ch == 'f' && n < argc - 1) { + name = argv[n + 1]; + n += 2; + } else if (ch == 's') { + sflag = 1; + n++; + } else if (ch == 'S') { + Sflag = 1; + n++; + } else { + dusage = 1; + break; + } + } + if (sflag && Sflag) + dusage = 1; + + argc -= n - 1; + argv += n - 1; + + if ((baz = open(name, O_RDWR)) < 0) + err(1, "%s", name); + if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) + err(1, "SOUND_MIXER_READ_DEVMASK"); + if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) + err(1, "SOUND_MIXER_READ_RECMASK"); + if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) + err(1, "SOUND_MIXER_READ_RECSRC"); + orecsrc = recsrc; + + if (argc == 1 && dusage == 0) { + for (foo = 0, n = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { + if (!((1 << foo) & devmask)) + continue; + if (ioctl(baz, MIXER_READ(foo),&bar) == -1) { + warn("MIXER_READ"); + continue; + } + if (Sflag || sflag) { + printf("%s%s%c%d:%d", n ? " " : "", + names[foo], Sflag ? ':' : ' ', + bar & 0x7f, (bar >> 8) & 0x7f); + n++; + } else + printf("Mixer %-8s is currently set to " + "%3d:%d\n", names[foo], bar & 0x7f, + (bar >> 8) & 0x7f); + } + if (n && recmask) + printf(" "); + print_recsrc(recsrc, recmask, Sflag || sflag); + return (0); + } + + argc--; + argv++; + + n = 0; + while (argc > 0 && dusage == 0) { + if (strcmp("recsrc", *argv) == 0) { + drecsrc = 1; + argc--; + argv++; + continue; + } else if (strcmp("rec", *argv + 1) == 0) { + if (**argv != '+' && **argv != '-' && + **argv != '=' && **argv != '^') { + warnx("unknown modifier: %c", **argv); + dusage = 1; + break; + } + if (argc <= 1) { + warnx("no recording device specified"); + dusage = 1; + break; + } + if ((dev = res_name(argv[1], recmask)) == -1) { + warnx("unknown recording device: %s", argv[1]); + dusage = 1; + break; + } + switch (**argv) { + case '+': + recsrc |= (1 << dev); + break; + case '-': + recsrc &= ~(1 << dev); + break; + case '=': + recsrc = (1 << dev); + break; + case '^': + recsrc ^= (1 << dev); + break; + } + drecsrc = 1; + argc -= 2; + argv += 2; + continue; + } + + if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) + dev = 0; + else if ((dev = res_name(*argv, devmask)) == -1) { + warnx("unknown device: %s", *argv); + dusage = 1; + break; + } + + lrel = rrel = 0; + if (argc > 1) { + m = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr); + if (m > 0) { + if (*lstr == '+' || *lstr == '-') + lrel = rrel = 1; + l = strtol(lstr, NULL, 10); + } + if (m > 1) { + if (*rstr == '+' || *rstr == '-') + rrel = 1; + r = strtol(rstr, NULL, 10); + } + } + + switch (argc > 1 ? m : t) { + case 0: + if (ioctl(baz, MIXER_READ(dev), &bar) == -1) { + warn("MIXER_READ"); + argc--; + argv++; + continue; + } + if (Sflag || sflag) { + printf("%s%s%c%d:%d", n ? " " : "", + names[dev], Sflag ? ':' : ' ', + bar & 0x7f, (bar >> 8) & 0x7f); + n++; + } else + printf("Mixer %-8s is currently set to " + "%3d:%d\n", names[dev], bar & 0x7f, + (bar >> 8) & 0x7f); + + argc--; + argv++; + break; + case 1: + r = l; + /* FALLTHROUGH */ + case 2: + if (ioctl(baz, MIXER_READ(dev), &bar) == -1) { + warn("MIXER_READ"); + argc--; + argv++; + continue; + } + + if (lrel) + l = (bar & 0x7f) + l; + if (rrel) + r = ((bar >> 8) & 0x7f) + r; + + if (l < 0) + l = 0; + else if (l > 100) + l = 100; + if (r < 0) + r = 0; + else if (r > 100) + r = 100; + + if (!Sflag) + printf("Setting the mixer %s from %d:%d to " + "%d:%d.\n", names[dev], bar & 0x7f, + (bar >> 8) & 0x7f, l, r); + + l |= r << 8; + if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) + warn("WRITE_MIXER"); + + argc -= 2; + argv += 2; + break; + } + } + + if (dusage) { + close(baz); + usage(devmask, recmask); + /* NOTREACHED */ + } + + if (orecsrc != recsrc) { + if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) + err(1, "SOUND_MIXER_WRITE_RECSRC"); + if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) + err(1, "SOUND_MIXER_READ_RECSRC"); + } + + if (drecsrc) + print_recsrc(recsrc, recmask, Sflag || sflag); + + close(baz); + + return (0); +} |