xref: /freebsd/usr.sbin/mixer/mixer.c (revision a8445737e740901f5f2c8d24c12ef7fc8b00134e)
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
15 static const char rcsid[] =
16 	"$Id: mixer.c,v 1.8 1997/10/01 06:34:09 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 
31 char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
32 
33 void usage(int devmask, int recmask);
34 int res_name(const char *name, int mask);
35 void print_recsrc(int recsrc);
36 
37 void
38 usage(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 
63 int
64 res_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 
75 void
76 print_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 
91 int
92 main(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 > 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 			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