mixer.c revision 29963
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[] =
1629963Scharnier	"$Id$";
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#ifdef __FreeBSD__
266448Sache#include <machine/soundcard.h>
276448Sache#else
286448Sache#include <sys/soundcard.h>
296448Sache#endif
306448Sache
316448Sachechar *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
326448Sache
3329612Sjmgvoid usage(int devmask, int recmask);
3429612Sjmgint res_name(const char *name, int mask);
3529612Sjmgvoid print_recsrc(int recsrc);
366448Sache
3729612Sjmgvoid
3829612Sjmgusage(int devmask, int recmask)
396448Sache{
4029612Sjmg	int i, n;
416448Sache
4229963Scharnier	printf("usage: mixer [[dev [voll[:volr]] | recsrc | {^|+|-|=}rec recdev] ... ]\n");
4329753Sache	printf(" devices: ");
4429612Sjmg	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
456448Sache		if ((1 << i) & devmask)  {
466448Sache			if (n)
4729612Sjmg				printf(", ");
486448Sache			printf(names[i]);
496448Sache			n = 1;
508857Srgrimes		}
5129753Sache	printf("\n rec devices: ");
5229612Sjmg	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
5329612Sjmg		if ((1 << i) & recmask)  {
5429612Sjmg			if (n)
5529612Sjmg				printf(", ");
5629612Sjmg			printf(names[i]);
5729612Sjmg			n = 1;
5829612Sjmg		}
5929612Sjmg	printf("\n");
606448Sache	exit(1);
616448Sache}
626448Sache
6329612Sjmgint
6429612Sjmgres_name(const char *name, int mask)
656448Sache{
6629612Sjmg	int foo;
6729612Sjmg
6829612Sjmg	for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
6929612Sjmg		if ((1 << foo) & mask && !strcmp(names[foo], name))
7029612Sjmg			break;
7129612Sjmg
7229612Sjmg	return foo == SOUND_MIXER_NRDEVICES ? -1 : foo;
7329612Sjmg}
7429612Sjmg
7529612Sjmgvoid
7629612Sjmgprint_recsrc(int recsrc)
7729612Sjmg{
786448Sache	int i, n = 0;
796448Sache	fprintf(stderr, "Recording source: ");
806448Sache
816448Sache	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
826448Sache		if ((1 << i) & recsrc) {
836448Sache			if (n)
846448Sache				fprintf(stderr, ", ");
856448Sache			fprintf(stderr, names[i]);
866448Sache			n = 1;
876448Sache		}
886448Sache	fprintf(stderr, "\n");
896448Sache}
906448Sache
918857Srgrimesint
926448Sachemain(int argc, char *argv[])
936448Sache{
946448Sache	int foo, bar, baz, dev;
9529612Sjmg	int devmask = 0, recmask = 0, recsrc = 0, orecsrc;
9629612Sjmg	int dusage = 0, drecsrc = 0;
9729612Sjmg	int l, r;
986448Sache
9929612Sjmg	char *name;
1006448Sache
10129612Sjmg	name = strdup("/dev/mixer");
10229612Sjmg
1036448Sache	if (!strcmp(argv[0], "mixer2"))
10429612Sjmg		name = strdup("/dev/mixer1");
10529612Sjmg	else if (!strcmp(argv[0], "mixer3"))
10629612Sjmg		name = strdup("/dev/mixer2");
1076448Sache
10829612Sjmg	if (argc > 1 && !strcmp(argv[1], "-f")) {
10929612Sjmg		name = strdup(argv[2]);
11029612Sjmg		argc -= 2; argv += 2;
11129612Sjmg	}
11229612Sjmg
11329963Scharnier	if ((baz = open(name, O_RDWR)) < 0)
11429963Scharnier		err(1, "%s", name);
11529612Sjmg	free(name);
11629963Scharnier	if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
11729963Scharnier		err(-1, "SOUND_MIXER_READ_DEVMASK");
11829963Scharnier	if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
11929963Scharnier		err(-1, "SOUND_MIXER_READ_RECMASK");
12029963Scharnier	if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
12129963Scharnier		err(-1, "SOUND_MIXER_READ_RECSRC");
12229612Sjmg	orecsrc = recsrc;
1236448Sache
12429612Sjmg	if (argc == 1) {
12513803Smpp		for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) {
12613803Smpp			if (!((1 << foo) & devmask))
12713803Smpp				continue;
12813803Smpp			if (ioctl(baz, MIXER_READ(foo),&bar)== -1) {
12929963Scharnier			   	warn("MIXER_READ");
13013803Smpp				continue;
13113803Smpp			}
13213803Smpp			printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
13313803Smpp		}
13413803Smpp		return(0);
13513803Smpp	}
13613803Smpp
13729612Sjmg	argc--; argv++;
1386448Sache
13929612Sjmg	while (argc) {
14029612Sjmg		if (!strcmp("recsrc", *argv)) {
14129612Sjmg			drecsrc = 1;
14229612Sjmg			argc--; argv++;
14329612Sjmg			continue;
14429612Sjmg		} else if (argc > 1 && !strcmp("rec", *argv + 1)) {
14529612Sjmg			if (**argv != '+' && **argv != '-' &&
14629612Sjmg			    **argv != '=' && **argv != '^') {
14729612Sjmg				dusage = 1;
14829612Sjmg				argc -= 1; argv += 1;
14929612Sjmg				continue;
15013435Smpp			}
15129612Sjmg			if ((dev = res_name(argv[1], recmask)) == -1) {
15229612Sjmg				dusage = 1;
15329612Sjmg				argc -= 1; argv += 1;
15429612Sjmg				continue;
1556448Sache			}
15629612Sjmg			switch(**argv) {
15729612Sjmg			case '+':
1586448Sache				recsrc |= (1 << dev);
15929612Sjmg				break;
16029612Sjmg			case '-':
1616448Sache				recsrc &= ~(1 << dev);
16229612Sjmg				break;
16329612Sjmg			case '=':
16429612Sjmg				recsrc = (1 << dev);
16529612Sjmg				break;
16629612Sjmg			case '^':
16729612Sjmg				recsrc ^= (1 << dev);
16829612Sjmg				break;
16929612Sjmg			}
17029612Sjmg			drecsrc = 1;
17129612Sjmg			argc -= 2; argv += 2;
17229612Sjmg			continue;
17329612Sjmg		}
1746448Sache
17529612Sjmg		if ((dev = res_name(*argv, devmask)) == -1) {
17629612Sjmg			dusage = 1;
17729612Sjmg			argc--; argv++;
17829612Sjmg			continue;
17929612Sjmg		}
18029612Sjmg
18129612Sjmg		switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) {
18229612Sjmg		case 0:
18329612Sjmg			if (ioctl(baz, MIXER_READ(dev),&bar)== -1) {
18429963Scharnier				warn("MIXER_READ");
18529612Sjmg				argc--; argv++;
18629612Sjmg				continue;
1876448Sache			}
18829612Sjmg			printf("Mixer %-8s is currently set to %3d:%d\n",
18929612Sjmg			    names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
1906448Sache
19129612Sjmg			argc--; argv++;
19229612Sjmg			break;
19329612Sjmg		case 1:
19429612Sjmg			r = l;
19529612Sjmg		case 2:
19629612Sjmg			if (l < 0)
19729612Sjmg				l = 0;
19829612Sjmg			else if (l > 100)
19929612Sjmg				l = 100;
20029612Sjmg			if (r < 0)
20129612Sjmg				r = 0;
20229612Sjmg			else if (r > 100)
20329612Sjmg				r = 100;
2048857Srgrimes
20529612Sjmg			printf("Setting the mixer %s to %d:%d.\n", names[dev],
20629612Sjmg			    l, r);
2076448Sache
20829612Sjmg			l |= r << 8;
20929612Sjmg			if (ioctl(baz, MIXER_WRITE(dev), &l) == -1)
21029963Scharnier				warn("WRITE_MIXER");
2116448Sache
21229612Sjmg			argc -= 2; argv += 2;
21329612Sjmg 			break;
2146448Sache		}
2156448Sache	}
2166448Sache
21729612Sjmg	if (orecsrc != recsrc)
21829963Scharnier		if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
21929963Scharnier			err(-1, "SOUND_MIXER_WRITE_RECSRC");
22029612Sjmg
22129612Sjmg	if (drecsrc) {
22229963Scharnier		if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
22329963Scharnier			err(-1, "SOUND_MIXER_READ_RECSRC");
22429612Sjmg		print_recsrc(recsrc);
22529612Sjmg	}
22629612Sjmg
2276448Sache	close(baz);
22829612Sjmg
22929612Sjmg	if (dusage)
23029612Sjmg		usage(devmask, recmask);
23129612Sjmg
23229612Sjmg	exit(0);
2336448Sache}
234