mixer.c revision 64657
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
1429963Scharnier#ifndef lint
1529963Scharnierstatic const char rcsid[] =
1650479Speter  "$FreeBSD: head/usr.sbin/mixer/mixer.c 64657 2000-08-15 05:42:39Z sobomax $";
1729963Scharnier#endif /* not lint */
1829963Scharnier
1929963Scharnier#include <err.h>
2029963Scharnier#include <fcntl.h>
216448Sache#include <stdio.h>
226448Sache#include <string.h>
2329612Sjmg#include <stdlib.h>
2429612Sjmg#include <unistd.h>
256448Sache#include <sys/soundcard.h>
266448Sache
276448Sachechar *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
286448Sache
2929612Sjmgvoid usage(int devmask, int recmask);
3029612Sjmgint res_name(const char *name, int mask);
3129612Sjmgvoid print_recsrc(int recsrc);
326448Sache
3329612Sjmgvoid
3429612Sjmgusage(int devmask, int recmask)
356448Sache{
3629612Sjmg	int i, n;
376448Sache
3864657Ssobomax	printf("usage: mixer [-f device] [-s] [[dev [voll[:volr]] | recsrc | {^|+|-|=}rec recdev] ... ]\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(", ");
446448Sache			printf(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(", ");
5229612Sjmg			printf(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, ", ");
816448Sache			fprintf(stderr, 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;
9260741Sjkh	int dusage = 0, drecsrc = 0, shortflag = 0;
9329612Sjmg	int l, r;
9464657Ssobomax	char ch;
956448Sache
9629612Sjmg	char *name;
976448Sache
9829612Sjmg	name = strdup("/dev/mixer");
9929612Sjmg
1006448Sache	if (!strcmp(argv[0], "mixer2"))
10129612Sjmg		name = strdup("/dev/mixer1");
10229612Sjmg	else if (!strcmp(argv[0], "mixer3"))
10329612Sjmg		name = strdup("/dev/mixer2");
1046448Sache
10564657Ssobomax	while ((ch = getopt(argc, argv, "f:s")) != -1)
10664657Ssobomax		switch (ch) {
10764657Ssobomax			case 'f':
10864657Ssobomax				name = strdup(optarg);
10964657Ssobomax				break;
11064657Ssobomax			case 's':
11164657Ssobomax				shortflag = 1;
11264657Ssobomax				break;
11364657Ssobomax			default:
11464657Ssobomax				dusage = 1;
11564657Ssobomax		}
11664657Ssobomax	argc -= (optind - 1);
11764657Ssobomax	argv += (optind - 1);
11829612Sjmg
11929963Scharnier	if ((baz = open(name, O_RDWR)) < 0)
12029963Scharnier		err(1, "%s", name);
12129612Sjmg	free(name);
12229963Scharnier	if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
12330028Scharnier		err(1, "SOUND_MIXER_READ_DEVMASK");
12429963Scharnier	if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
12530028Scharnier		err(1, "SOUND_MIXER_READ_RECMASK");
12629963Scharnier	if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
12730028Scharnier		err(1, "SOUND_MIXER_READ_RECSRC");
12829612Sjmg	orecsrc = recsrc;
1296448Sache
13064657Ssobomax	if ((argc == 1) && (dusage == 0)) {
13113803Smpp		for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) {
13213803Smpp			if (!((1 << foo) & devmask))
13313803Smpp				continue;
13413803Smpp			if (ioctl(baz, MIXER_READ(foo),&bar)== -1) {
13529963Scharnier			   	warn("MIXER_READ");
13613803Smpp				continue;
13713803Smpp			}
13860741Sjkh			if (shortflag)
13960741Sjkh				printf("%s %d:%d ", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
14060741Sjkh			else
14160741Sjkh				printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
14213803Smpp		}
14313803Smpp		return(0);
14413803Smpp	}
14513803Smpp
14629612Sjmg	argc--; argv++;
1476448Sache
14864657Ssobomax	while ((argc) && (dusage == 0)) {
14929612Sjmg		if (!strcmp("recsrc", *argv)) {
15029612Sjmg			drecsrc = 1;
15129612Sjmg			argc--; argv++;
15229612Sjmg			continue;
15329612Sjmg		} else if (argc > 1 && !strcmp("rec", *argv + 1)) {
15429612Sjmg			if (**argv != '+' && **argv != '-' &&
15529612Sjmg			    **argv != '=' && **argv != '^') {
15664657Ssobomax				warnx("unknown modifier: %c", **argv);
15729612Sjmg				dusage = 1;
15864657Ssobomax				break;
15913435Smpp			}
16029612Sjmg			if ((dev = res_name(argv[1], recmask)) == -1) {
16164657Ssobomax				warnx("unknown recording device: %s", argv[1]);
16229612Sjmg				dusage = 1;
16364657Ssobomax				break;
1646448Sache			}
16529612Sjmg			switch(**argv) {
16629612Sjmg			case '+':
1676448Sache				recsrc |= (1 << dev);
16829612Sjmg				break;
16929612Sjmg			case '-':
1706448Sache				recsrc &= ~(1 << dev);
17129612Sjmg				break;
17229612Sjmg			case '=':
17329612Sjmg				recsrc = (1 << dev);
17429612Sjmg				break;
17529612Sjmg			case '^':
17629612Sjmg				recsrc ^= (1 << dev);
17729612Sjmg				break;
17829612Sjmg			}
17929612Sjmg			drecsrc = 1;
18029612Sjmg			argc -= 2; argv += 2;
18129612Sjmg			continue;
18229612Sjmg		}
1836448Sache
18429612Sjmg		if ((dev = res_name(*argv, devmask)) == -1) {
18564657Ssobomax			warnx("unknown device: %s", *argv);
18629612Sjmg			dusage = 1;
18764657Ssobomax			break;
18829612Sjmg		}
18929612Sjmg
19029612Sjmg		switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) {
19129612Sjmg		case 0:
19229612Sjmg			if (ioctl(baz, MIXER_READ(dev),&bar)== -1) {
19329963Scharnier				warn("MIXER_READ");
19429612Sjmg				argc--; argv++;
19529612Sjmg				continue;
1966448Sache			}
19760741Sjkh			if (shortflag)
19860741Sjkh				printf("%s %d:%d ", names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
19960741Sjkh			else
20060741Sjkh				printf("Mixer %-8s is currently set to %3d:%d\n",
20160741Sjkh				  names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
2026448Sache
20329612Sjmg			argc--; argv++;
20429612Sjmg			break;
20529612Sjmg		case 1:
20629612Sjmg			r = l;
20729612Sjmg		case 2:
20829612Sjmg			if (l < 0)
20929612Sjmg				l = 0;
21029612Sjmg			else if (l > 100)
21129612Sjmg				l = 100;
21229612Sjmg			if (r < 0)
21329612Sjmg				r = 0;
21429612Sjmg			else if (r > 100)
21529612Sjmg				r = 100;
2168857Srgrimes
21729612Sjmg			printf("Setting the mixer %s to %d:%d.\n", names[dev],
21829612Sjmg			    l, r);
2196448Sache
22029612Sjmg			l |= r << 8;
22129612Sjmg			if (ioctl(baz, MIXER_WRITE(dev), &l) == -1)
22229963Scharnier				warn("WRITE_MIXER");
2236448Sache
22429612Sjmg			argc -= 2; argv += 2;
22529612Sjmg 			break;
2266448Sache		}
2276448Sache	}
2286448Sache
22964657Ssobomax	if (dusage) {
23064657Ssobomax		close(baz);
23164657Ssobomax		usage(devmask, recmask);
23264657Ssobomax		/* Not reached */
23364657Ssobomax	}
23464657Ssobomax
23529612Sjmg	if (orecsrc != recsrc)
23629963Scharnier		if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
23730028Scharnier			err(1, "SOUND_MIXER_WRITE_RECSRC");
23829612Sjmg
23929612Sjmg	if (drecsrc) {
24029963Scharnier		if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
24130028Scharnier			err(1, "SOUND_MIXER_READ_RECSRC");
24229612Sjmg		print_recsrc(recsrc);
24329612Sjmg	}
24429612Sjmg
2456448Sache	close(baz);
24629612Sjmg
24729612Sjmg	exit(0);
2486448Sache}
249