mixer.c revision 60741
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  "$FreeBSD: head/usr.sbin/mixer/mixer.c 60741 2000-05-20 23:25:08Z jkh $";
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#include <sys/soundcard.h>
26
27char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
28
29void usage(int devmask, int recmask);
30int res_name(const char *name, int mask);
31void print_recsrc(int recsrc);
32
33void
34usage(int devmask, int recmask)
35{
36	int i, n;
37
38	printf("usage: mixer [-s] [[dev [voll[:volr]] | recsrc | {^|+|-|=}rec recdev] ... ]\n");
39	printf(" devices: ");
40	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
41		if ((1 << i) & devmask)  {
42			if (n)
43				printf(", ");
44			printf(names[i]);
45			n = 1;
46		}
47	printf("\n rec devices: ");
48	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
49		if ((1 << i) & recmask)  {
50			if (n)
51				printf(", ");
52			printf(names[i]);
53			n = 1;
54		}
55	printf("\n");
56	exit(1);
57}
58
59int
60res_name(const char *name, int mask)
61{
62	int foo;
63
64	for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
65		if ((1 << foo) & mask && !strcmp(names[foo], name))
66			break;
67
68	return foo == SOUND_MIXER_NRDEVICES ? -1 : foo;
69}
70
71void
72print_recsrc(int recsrc)
73{
74	int i, n = 0;
75	fprintf(stderr, "Recording source: ");
76
77	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
78		if ((1 << i) & recsrc) {
79			if (n)
80				fprintf(stderr, ", ");
81			fprintf(stderr, names[i]);
82			n = 1;
83		}
84	fprintf(stderr, "\n");
85}
86
87int
88main(int argc, char *argv[])
89{
90	int foo, bar, baz, dev;
91	int devmask = 0, recmask = 0, recsrc = 0, orecsrc;
92	int dusage = 0, drecsrc = 0, shortflag = 0;
93	int l, r;
94
95	char *name;
96
97	name = strdup("/dev/mixer");
98
99	if (!strcmp(argv[0], "mixer2"))
100		name = strdup("/dev/mixer1");
101	else if (!strcmp(argv[0], "mixer3"))
102		name = strdup("/dev/mixer2");
103
104	if (argc > 1 && strcmp(argv[1], "-s") == 0) {
105		shortflag = 1;
106		argc -= 1; argv += 1;
107	}
108	if (argc > 2 && strcmp(argv[1], "-f") == 0) {
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			if (shortflag)
133				printf("%s %d:%d ", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
134			else
135				printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
136		}
137		return(0);
138	}
139
140	argc--; argv++;
141
142	while (argc) {
143		if (!strcmp("recsrc", *argv)) {
144			drecsrc = 1;
145			argc--; argv++;
146			continue;
147		} else if (argc > 1 && !strcmp("rec", *argv + 1)) {
148			if (**argv != '+' && **argv != '-' &&
149			    **argv != '=' && **argv != '^') {
150				dusage = 1;
151				argc -= 1; argv += 1;
152				continue;
153			}
154			if ((dev = res_name(argv[1], recmask)) == -1) {
155				dusage = 1;
156				argc -= 1; argv += 1;
157				continue;
158			}
159			switch(**argv) {
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			case '^':
170				recsrc ^= (1 << dev);
171				break;
172			}
173			drecsrc = 1;
174			argc -= 2; argv += 2;
175			continue;
176		}
177
178		if ((dev = res_name(*argv, devmask)) == -1) {
179			dusage = 1;
180			argc--; argv++;
181			continue;
182		}
183
184		switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) {
185		case 0:
186			if (ioctl(baz, MIXER_READ(dev),&bar)== -1) {
187				warn("MIXER_READ");
188				argc--; argv++;
189				continue;
190			}
191			if (shortflag)
192				printf("%s %d:%d ", names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
193			else
194				printf("Mixer %-8s is currently set to %3d:%d\n",
195				  names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
196
197			argc--; argv++;
198			break;
199		case 1:
200			r = l;
201		case 2:
202			if (l < 0)
203				l = 0;
204			else if (l > 100)
205				l = 100;
206			if (r < 0)
207				r = 0;
208			else if (r > 100)
209				r = 100;
210
211			printf("Setting the mixer %s to %d:%d.\n", names[dev],
212			    l, r);
213
214			l |= r << 8;
215			if (ioctl(baz, MIXER_WRITE(dev), &l) == -1)
216				warn("WRITE_MIXER");
217
218			argc -= 2; argv += 2;
219 			break;
220		}
221	}
222
223	if (orecsrc != recsrc)
224		if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
225			err(1, "SOUND_MIXER_WRITE_RECSRC");
226
227	if (drecsrc) {
228		if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
229			err(1, "SOUND_MIXER_READ_RECSRC");
230		print_recsrc(recsrc);
231	}
232
233	close(baz);
234
235	if (dusage)
236		usage(devmask, recmask);
237
238	exit(0);
239}
240