mixer.c revision 30028
1/*
2 *	This is an example of a mixer program for Linux
3 *
4 *	updated 1/1/93 to add stereo, level query, broken
5 *      	devmask kludge - cmetz@thor.tjhsst.edu
6 *
7 * (C) Craig Metz and Hannu Savolainen 1993.
8 *
9 * You may do anything you wish with this program.
10 *
11 * ditto for my modifications (John-Mark Gurney, 1997)
12 */
13
14#ifndef lint
15static const char rcsid[] =
16	"$Id: mixer.c,v 1.7 1997/09/29 06:38:49 charnier Exp $";
17#endif /* not lint */
18
19#include <err.h>
20#include <fcntl.h>
21#include <stdio.h>
22#include <string.h>
23#include <stdlib.h>
24#include <unistd.h>
25#ifdef __FreeBSD__
26#include <machine/soundcard.h>
27#else
28#include <sys/soundcard.h>
29#endif
30
31char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
32
33void usage(int devmask, int recmask);
34int res_name(const char *name, int mask);
35void print_recsrc(int recsrc);
36
37void
38usage(int devmask, int recmask)
39{
40	int i, n;
41
42	printf("usage: mixer [[dev [voll[:volr]] | recsrc | {^|+|-|=}rec recdev] ... ]\n");
43	printf(" devices: ");
44	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
45		if ((1 << i) & devmask)  {
46			if (n)
47				printf(", ");
48			printf(names[i]);
49			n = 1;
50		}
51	printf("\n rec devices: ");
52	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
53		if ((1 << i) & recmask)  {
54			if (n)
55				printf(", ");
56			printf(names[i]);
57			n = 1;
58		}
59	printf("\n");
60	exit(1);
61}
62
63int
64res_name(const char *name, int mask)
65{
66	int foo;
67
68	for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
69		if ((1 << foo) & mask && !strcmp(names[foo], name))
70			break;
71
72	return foo == SOUND_MIXER_NRDEVICES ? -1 : foo;
73}
74
75void
76print_recsrc(int recsrc)
77{
78	int i, n = 0;
79	fprintf(stderr, "Recording source: ");
80
81	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
82		if ((1 << i) & recsrc) {
83			if (n)
84				fprintf(stderr, ", ");
85			fprintf(stderr, names[i]);
86			n = 1;
87		}
88	fprintf(stderr, "\n");
89}
90
91int
92main(int argc, char *argv[])
93{
94	int foo, bar, baz, dev;
95	int devmask = 0, recmask = 0, recsrc = 0, orecsrc;
96	int dusage = 0, drecsrc = 0;
97	int l, r;
98
99	char *name;
100
101	name = strdup("/dev/mixer");
102
103	if (!strcmp(argv[0], "mixer2"))
104		name = strdup("/dev/mixer1");
105	else if (!strcmp(argv[0], "mixer3"))
106		name = strdup("/dev/mixer2");
107
108	if (argc > 1 && !strcmp(argv[1], "-f")) {
109		name = strdup(argv[2]);
110		argc -= 2; argv += 2;
111	}
112
113	if ((baz = open(name, O_RDWR)) < 0)
114		err(1, "%s", name);
115	free(name);
116	if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
117		err(1, "SOUND_MIXER_READ_DEVMASK");
118	if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
119		err(1, "SOUND_MIXER_READ_RECMASK");
120	if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
121		err(1, "SOUND_MIXER_READ_RECSRC");
122	orecsrc = recsrc;
123
124	if (argc == 1) {
125		for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) {
126			if (!((1 << foo) & devmask))
127				continue;
128			if (ioctl(baz, MIXER_READ(foo),&bar)== -1) {
129			   	warn("MIXER_READ");
130				continue;
131			}
132			printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
133		}
134		return(0);
135	}
136
137	argc--; argv++;
138
139	while (argc) {
140		if (!strcmp("recsrc", *argv)) {
141			drecsrc = 1;
142			argc--; argv++;
143			continue;
144		} else if (argc > 1 && !strcmp("rec", *argv + 1)) {
145			if (**argv != '+' && **argv != '-' &&
146			    **argv != '=' && **argv != '^') {
147				dusage = 1;
148				argc -= 1; argv += 1;
149				continue;
150			}
151			if ((dev = res_name(argv[1], recmask)) == -1) {
152				dusage = 1;
153				argc -= 1; argv += 1;
154				continue;
155			}
156			switch(**argv) {
157			case '+':
158				recsrc |= (1 << dev);
159				break;
160			case '-':
161				recsrc &= ~(1 << dev);
162				break;
163			case '=':
164				recsrc = (1 << dev);
165				break;
166			case '^':
167				recsrc ^= (1 << dev);
168				break;
169			}
170			drecsrc = 1;
171			argc -= 2; argv += 2;
172			continue;
173		}
174
175		if ((dev = res_name(*argv, devmask)) == -1) {
176			dusage = 1;
177			argc--; argv++;
178			continue;
179		}
180
181		switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) {
182		case 0:
183			if (ioctl(baz, MIXER_READ(dev),&bar)== -1) {
184				warn("MIXER_READ");
185				argc--; argv++;
186				continue;
187			}
188			printf("Mixer %-8s is currently set to %3d:%d\n",
189			    names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
190
191			argc--; argv++;
192			break;
193		case 1:
194			r = l;
195		case 2:
196			if (l < 0)
197				l = 0;
198			else if (l > 100)
199				l = 100;
200			if (r < 0)
201				r = 0;
202			else if (r > 100)
203				r = 100;
204
205			printf("Setting the mixer %s to %d:%d.\n", names[dev],
206			    l, r);
207
208			l |= r << 8;
209			if (ioctl(baz, MIXER_WRITE(dev), &l) == -1)
210				warn("WRITE_MIXER");
211
212			argc -= 2; argv += 2;
213 			break;
214		}
215	}
216
217	if (orecsrc != recsrc)
218		if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
219			err(1, "SOUND_MIXER_WRITE_RECSRC");
220
221	if (drecsrc) {
222		if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
223			err(1, "SOUND_MIXER_READ_RECSRC");
224		print_recsrc(recsrc);
225	}
226
227	close(baz);
228
229	if (dusage)
230		usage(devmask, recmask);
231
232	exit(0);
233}
234