mixer.c revision 29612
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
146448Sache#include <stdio.h>
156448Sache#include <fcntl.h>
166448Sache#include <string.h>
1729612Sjmg#include <stdlib.h>
1829612Sjmg#include <unistd.h>
196448Sache#ifdef __FreeBSD__
206448Sache#include <machine/soundcard.h>
216448Sache#else
226448Sache#include <sys/soundcard.h>
236448Sache#endif
246448Sache
256448Sachechar *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
3629612Sjmg	printf("usage:\tmixer [[dev [voll[:volr]] | recsrc | {^|+|-|=}rec recdev] ... ]\n");
3729612Sjmg	printf("   devices:\t");
3829612Sjmg	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
396448Sache		if ((1 << i) & devmask)  {
406448Sache			if (n)
4129612Sjmg				printf(", ");
426448Sache			printf(names[i]);
436448Sache			n = 1;
448857Srgrimes		}
4529612Sjmg	printf("\n   rec devices:\t");
4629612Sjmg	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
4729612Sjmg		if ((1 << i) & recmask)  {
4829612Sjmg			if (n)
4929612Sjmg				printf(", ");
5029612Sjmg			printf(names[i]);
5129612Sjmg			n = 1;
5229612Sjmg		}
5329612Sjmg	printf("\n");
546448Sache	exit(1);
556448Sache}
566448Sache
5729612Sjmgint
5829612Sjmgres_name(const char *name, int mask)
596448Sache{
6029612Sjmg	int foo;
6129612Sjmg
6229612Sjmg	for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
6329612Sjmg		if ((1 << foo) & mask && !strcmp(names[foo], name))
6429612Sjmg			break;
6529612Sjmg
6629612Sjmg	return foo == SOUND_MIXER_NRDEVICES ? -1 : foo;
6729612Sjmg}
6829612Sjmg
6929612Sjmgvoid
7029612Sjmgprint_recsrc(int recsrc)
7129612Sjmg{
726448Sache	int i, n = 0;
736448Sache	fprintf(stderr, "Recording source: ");
746448Sache
756448Sache	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
766448Sache		if ((1 << i) & recsrc) {
776448Sache			if (n)
786448Sache				fprintf(stderr, ", ");
796448Sache			fprintf(stderr, names[i]);
806448Sache			n = 1;
816448Sache		}
826448Sache	fprintf(stderr, "\n");
836448Sache}
846448Sache
858857Srgrimesint
866448Sachemain(int argc, char *argv[])
876448Sache{
886448Sache	int foo, bar, baz, dev;
8929612Sjmg	int devmask = 0, recmask = 0, recsrc = 0, orecsrc;
9029612Sjmg	int dusage = 0, drecsrc = 0;
9129612Sjmg	int l, r;
926448Sache
9329612Sjmg	char *name;
946448Sache
9529612Sjmg	name = strdup("/dev/mixer");
9629612Sjmg
976448Sache	if (!strcmp(argv[0], "mixer2"))
9829612Sjmg		name = strdup("/dev/mixer1");
9929612Sjmg	else if (!strcmp(argv[0], "mixer3"))
10029612Sjmg		name = strdup("/dev/mixer2");
1016448Sache
10229612Sjmg	if (argc > 1 && !strcmp(argv[1], "-f")) {
10329612Sjmg		name = strdup(argv[2]);
10429612Sjmg		argc -= 2; argv += 2;
10529612Sjmg	}
10629612Sjmg
1076448Sache	if ((baz = open(name, O_RDWR)) < 0) {
1086448Sache		perror(name);
1096448Sache		exit(1);
1106448Sache	}
11129612Sjmg	free(name);
1126448Sache	if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
1136448Sache		perror("SOUND_MIXER_READ_DEVMASK");
1146448Sache		exit(-1);
1156448Sache	}
1166448Sache	if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) {
1176448Sache		perror("SOUND_MIXER_READ_RECMASK");
1186448Sache		exit(-1);
1196448Sache	}
1206448Sache	if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) {
1216448Sache		perror("SOUND_MIXER_READ_RECSRC");
1226448Sache		exit(-1);
1236448Sache	}
12429612Sjmg	orecsrc = recsrc;
1256448Sache
12629612Sjmg	if (argc == 1) {
12713803Smpp		for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) {
12813803Smpp			if (!((1 << foo) & devmask))
12913803Smpp				continue;
13013803Smpp			if (ioctl(baz, MIXER_READ(foo),&bar)== -1) {
13113803Smpp			   	perror("MIXER_READ");
13213803Smpp				continue;
13313803Smpp			}
13413803Smpp			printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
13513803Smpp		}
13613803Smpp		return(0);
13713803Smpp	}
13813803Smpp
13929612Sjmg	argc--; argv++;
1406448Sache
14129612Sjmg	while (argc) {
14229612Sjmg		if (!strcmp("recsrc", *argv)) {
14329612Sjmg			drecsrc = 1;
14429612Sjmg			argc--; argv++;
14529612Sjmg			continue;
14629612Sjmg		} else if (argc > 1 && !strcmp("rec", *argv + 1)) {
14729612Sjmg			if (**argv != '+' && **argv != '-' &&
14829612Sjmg			    **argv != '=' && **argv != '^') {
14929612Sjmg				dusage = 1;
15029612Sjmg				argc -= 1; argv += 1;
15129612Sjmg				continue;
15213435Smpp			}
15329612Sjmg			if ((dev = res_name(argv[1], recmask)) == -1) {
15429612Sjmg				dusage = 1;
15529612Sjmg				argc -= 1; argv += 1;
15629612Sjmg				continue;
1576448Sache			}
15829612Sjmg			switch(**argv) {
15929612Sjmg			case '+':
1606448Sache				recsrc |= (1 << dev);
16129612Sjmg				break;
16229612Sjmg			case '-':
1636448Sache				recsrc &= ~(1 << dev);
16429612Sjmg				break;
16529612Sjmg			case '=':
16629612Sjmg				recsrc = (1 << dev);
16729612Sjmg				break;
16829612Sjmg			case '^':
16929612Sjmg				recsrc ^= (1 << dev);
17029612Sjmg				break;
17129612Sjmg			}
17229612Sjmg			drecsrc = 1;
17329612Sjmg			argc -= 2; argv += 2;
17429612Sjmg			continue;
17529612Sjmg		}
1766448Sache
17729612Sjmg		if ((dev = res_name(*argv, devmask)) == -1) {
17829612Sjmg			dusage = 1;
17929612Sjmg			argc--; argv++;
18029612Sjmg			continue;
18129612Sjmg		}
18229612Sjmg
18329612Sjmg		switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) {
18429612Sjmg		case 0:
18529612Sjmg			if (ioctl(baz, MIXER_READ(dev),&bar)== -1) {
18629612Sjmg				perror("MIXER_READ");
18729612Sjmg				argc--; argv++;
18829612Sjmg				continue;
1896448Sache			}
19029612Sjmg			printf("Mixer %-8s is currently set to %3d:%d\n",
19129612Sjmg			    names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
1926448Sache
19329612Sjmg			argc--; argv++;
19429612Sjmg			break;
19529612Sjmg		case 1:
19629612Sjmg			r = l;
19729612Sjmg		case 2:
19829612Sjmg			if (l < 0)
19929612Sjmg				l = 0;
20029612Sjmg			else if (l > 100)
20129612Sjmg				l = 100;
20229612Sjmg			if (r < 0)
20329612Sjmg				r = 0;
20429612Sjmg			else if (r > 100)
20529612Sjmg				r = 100;
2068857Srgrimes
20729612Sjmg			printf("Setting the mixer %s to %d:%d.\n", names[dev],
20829612Sjmg			    l, r);
2096448Sache
21029612Sjmg			l |= r << 8;
21129612Sjmg			if (ioctl(baz, MIXER_WRITE(dev), &l) == -1)
21229612Sjmg				perror("WRITE_MIXER");
2136448Sache
21429612Sjmg			argc -= 2; argv += 2;
21529612Sjmg 			break;
2166448Sache		}
2176448Sache	}
2186448Sache
21929612Sjmg	if (orecsrc != recsrc)
22029612Sjmg		if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) {
22129612Sjmg			perror("SOUND_MIXER_WRITE_RECSRC");
22229612Sjmg			exit(-1);
22329612Sjmg		}
22429612Sjmg
22529612Sjmg	if (drecsrc) {
22629612Sjmg		if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) {
22729612Sjmg			perror("SOUND_MIXER_READ_RECSRC");
22829612Sjmg			exit(-1);
22929612Sjmg		}
23029612Sjmg		print_recsrc(recsrc);
23129612Sjmg	}
23229612Sjmg
2336448Sache	close(baz);
23429612Sjmg
23529612Sjmg	if (dusage)
23629612Sjmg		usage(devmask, recmask);
23729612Sjmg
23829612Sjmg	exit(0);
2396448Sache}
240