xref: /dragonfly/usr.sbin/mixer/mixer.c (revision 1de703da)
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  * $FreeBSD: src/usr.sbin/mixer/mixer.c,v 1.11.2.6 2001/07/30 10:22:58 dd Exp $
14  * $DragonFly: src/usr.sbin/mixer/mixer.c,v 1.2 2003/06/17 04:29:57 dillon Exp $
15  */
16 
17 #include <err.h>
18 #include <fcntl.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <sys/soundcard.h>
24 
25 const char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
26 
27 void usage(int devmask, int recmask);
28 int res_name(const char *name, int mask);
29 void print_recsrc(int recsrc);
30 
31 void
32 usage(int devmask, int recmask)
33 {
34 	int i, n;
35 
36 	printf("usage: mixer [-f device] [-s] [[dev [voll[:volr]] | recsrc | {^|+|-|=}rec recdev] ... ]\n");
37 	printf(" devices: ");
38 	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
39 		if ((1 << i) & devmask)  {
40 			if (n)
41 				printf(", ");
42 			printf("%s", names[i]);
43 			n = 1;
44 		}
45 	printf("\n rec devices: ");
46 	for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
47 		if ((1 << i) & recmask)  {
48 			if (n)
49 				printf(", ");
50 			printf("%s", names[i]);
51 			n = 1;
52 		}
53 	printf("\n");
54 	exit(1);
55 }
56 
57 int
58 res_name(const char *name, int mask)
59 {
60 	int foo;
61 
62 	for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
63 		if ((1 << foo) & mask && !strcmp(names[foo], name))
64 			break;
65 
66 	return foo == SOUND_MIXER_NRDEVICES ? -1 : foo;
67 }
68 
69 void
70 print_recsrc(int recsrc)
71 {
72 	int i, n = 0;
73 	fprintf(stderr, "Recording source: ");
74 
75 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
76 		if ((1 << i) & recsrc) {
77 			if (n)
78 				fprintf(stderr, ", ");
79 			fprintf(stderr, "%s", names[i]);
80 			n = 1;
81 		}
82 	fprintf(stderr, "\n");
83 }
84 
85 int
86 main(int argc, char *argv[])
87 {
88 	int foo, bar, baz, dev;
89 	int devmask = 0, recmask = 0, recsrc = 0, orecsrc;
90 	int dusage = 0, drecsrc = 0, shortflag = 0;
91 	int l = 0, r = 0, t = 0;
92 	char ch;
93 
94 	char *name;
95 
96 	name = strdup("/dev/mixer");
97 
98 	if (!strcmp(argv[0], "mixer2"))
99 		name = strdup("/dev/mixer1");
100 	else if (!strcmp(argv[0], "mixer3"))
101 		name = strdup("/dev/mixer2");
102 
103 	while ((ch = getopt(argc, argv, "f:s")) != -1)
104 		switch (ch) {
105 			case 'f':
106 				name = strdup(optarg);
107 				break;
108 			case 's':
109 				shortflag = 1;
110 				break;
111 			default:
112 				dusage = 1;
113 		}
114 	argc -= (optind - 1);
115 	argv += (optind - 1);
116 
117 	if ((baz = open(name, O_RDWR)) < 0)
118 		err(1, "%s", name);
119 	free(name);
120 	if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
121 		err(1, "SOUND_MIXER_READ_DEVMASK");
122 	if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
123 		err(1, "SOUND_MIXER_READ_RECMASK");
124 	if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
125 		err(1, "SOUND_MIXER_READ_RECSRC");
126 	orecsrc = recsrc;
127 
128 	if ((argc == 1) && (dusage == 0)) {
129 		for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) {
130 			if (!((1 << foo) & devmask))
131 				continue;
132 			if (ioctl(baz, MIXER_READ(foo),&bar)== -1) {
133 			   	warn("MIXER_READ");
134 				continue;
135 			}
136 			if (shortflag)
137 				printf("%s %d:%d ", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
138 			else
139 				printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
140 		}
141 		return(0);
142 	}
143 
144 	argc--; argv++;
145 
146 	while ((argc > 0) && (dusage == 0)) {
147 		if (!strcmp("recsrc", *argv)) {
148 			drecsrc = 1;
149 			argc--; argv++;
150 			continue;
151 		} else if (argc > 1 && !strcmp("rec", *argv + 1)) {
152 			if (**argv != '+' && **argv != '-' &&
153 			    **argv != '=' && **argv != '^') {
154 				warnx("unknown modifier: %c", **argv);
155 				dusage = 1;
156 				break;
157 			}
158 			if ((dev = res_name(argv[1], recmask)) == -1) {
159 				warnx("unknown recording device: %s", argv[1]);
160 				dusage = 1;
161 				break;
162 			}
163 			switch(**argv) {
164 			case '+':
165 				recsrc |= (1 << dev);
166 				break;
167 			case '-':
168 				recsrc &= ~(1 << dev);
169 				break;
170 			case '=':
171 				recsrc = (1 << dev);
172 				break;
173 			case '^':
174 				recsrc ^= (1 << dev);
175 				break;
176 			}
177 			drecsrc = 1;
178 			argc -= 2; argv += 2;
179 			continue;
180 		}
181 
182 		if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) {
183 			dev = 0;
184 		}
185 		else if((dev = res_name(*argv, devmask)) == -1) {
186 			warnx("unknown device: %s", *argv);
187 			dusage = 1;
188 			break;
189 		}
190 
191 		switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : t) {
192 		case 0:
193 			if (ioctl(baz, MIXER_READ(dev),&bar)== -1) {
194 				warn("MIXER_READ");
195 				argc--; argv++;
196 				continue;
197 			}
198 			if (shortflag)
199 				printf("%s %d:%d ", names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
200 			else
201 				printf("Mixer %-8s is currently set to %3d:%d\n",
202 				  names[dev], bar & 0x7f, (bar >> 8) & 0x7f);
203 
204 			argc--; argv++;
205 			break;
206 		case 1:
207 			r = l;
208 		case 2:
209 			if (l < 0)
210 				l = 0;
211 			else if (l > 100)
212 				l = 100;
213 			if (r < 0)
214 				r = 0;
215 			else if (r > 100)
216 				r = 100;
217 
218 			printf("Setting the mixer %s to %d:%d.\n", names[dev],
219 			    l, r);
220 
221 			l |= r << 8;
222 			if (ioctl(baz, MIXER_WRITE(dev), &l) == -1)
223 				warn("WRITE_MIXER");
224 
225 			argc -= 2; argv += 2;
226  			break;
227 		}
228 	}
229 
230 	if (dusage) {
231 		close(baz);
232 		usage(devmask, recmask);
233 		/* Not reached */
234 	}
235 
236 	if (orecsrc != recsrc)
237 		if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
238 			err(1, "SOUND_MIXER_WRITE_RECSRC");
239 
240 	if (drecsrc) {
241 		if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
242 			err(1, "SOUND_MIXER_READ_RECSRC");
243 		print_recsrc(recsrc);
244 	}
245 
246 	close(baz);
247 
248 	exit(0);
249 }
250