Fix str[c]spn off by one error.
[dragonfly.git] / usr.sbin / mixer / mixer.c
blob29aa408a9038cfbc20216f530ee83b7d3a5f743e
1 /*
2 * This is an example of a mixer program for Linux
4 * updated 1/1/93 to add stereo, level query, broken
5 * devmask kludge - cmetz@thor.tjhsst.edu
7 * (C) Craig Metz and Hannu Savolainen 1993.
9 * You may do anything you wish with this program.
11 * ditto for my modifications (John-Mark Gurney, 1997)
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.6 2004/04/15 12:58:12 joerg Exp $
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>
25 #define LEFT(vol) (vol & 0x7f)
26 #define RIGHT(vol) ((vol >> 8) & 0x7f)
28 static const char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
29 static const char *defaultdev = "/dev/mixer";
31 static void usage(int devmask, int recmask);
32 static int res_name(const char *name, int mask);
33 static void print_recsrc(int recsrc);
34 static void print_recsrc_short(int recsrc);
36 void
37 usage(int devmask, int recmask)
39 int i, n;
41 printf("usage: mixer [-f device] [-s] [dev [+|-][voll[:[+|-]volr]] ...\n"
42 " mixer [-f device] [-s] recsrc ...\n"
43 " mixer [-f device] [-s] {^|+|-|=}rec recdev ...\n"
44 " mixer -h\n");
45 printf(" devices: ");
46 for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) {
47 if ((1 << i) & devmask) {
48 if (n)
49 printf(", ");
50 printf("%s", names[i]);
51 n = 1;
54 printf("\n rec devices: ");
55 for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) {
56 if ((1 << i) & recmask) {
57 if (n)
58 printf(", ");
59 printf("%s", names[i]);
60 n = 1;
63 printf("\n");
64 exit(1);
67 int
68 res_name(const char *name, int mask)
70 int i;
72 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
73 if ((1 << i) & mask && !strcmp(names[i], name))
74 break;
76 if (i == SOUND_MIXER_NRDEVICES)
77 return(-1);
79 return(i);
82 void
83 print_recsrc(int recsrc)
85 int i, n = 0;
86 printf("Recording source: ");
88 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
89 if ((1 << i) & recsrc) {
90 if (n)
91 printf(", ");
92 printf("%s", names[i]);
93 n = 1;
96 printf("\n");
99 void
100 print_recsrc_short(int recsrc)
102 int i, first;
104 first = 1;
106 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
107 if ((1 << i) & recsrc) {
108 if (first) {
109 printf("=rec ");
110 first = 0;
112 printf("%s ", names[i]);
118 main(int argc, char **argv)
120 int i, mset, fd, dev;
121 int devmask = 0, recmask = 0, recsrc = 0, orecsrc;
122 int dusage = 0, drecsrc = 0, shortflag = 0;
123 int l = 0, r = 0, t = 0;
124 int n = 0, lrel = 0, rrel = 0;
125 char lstr[8], rstr[8];
126 char ch;
128 const char *name = defaultdev;
130 while ((ch = getopt(argc, argv, "f:sh")) != -1)
131 switch (ch) {
132 case 'f':
133 name = optarg;
134 break;
135 case 's':
136 shortflag = 1;
137 break;
138 case 'h': /* Fall through */
139 default:
140 dusage = 1;
142 argc -= optind;
143 argv += optind;
145 if ((fd = open(name, O_RDWR)) < 0)
146 err(1, "%s", name);
147 if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
148 err(1, "SOUND_MIXER_READ_DEVMASK");
149 if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
150 err(1, "SOUND_MIXER_READ_RECMASK");
151 if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
152 err(1, "SOUND_MIXER_READ_RECSRC");
153 orecsrc = recsrc;
155 if (dusage) {
156 close(fd);
157 usage(devmask, recmask); /* Does not return */
160 if (argc == 0) {
161 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
162 if (!((1 << i) & devmask))
163 continue;
164 if (ioctl(fd, MIXER_READ(i),&mset)== -1) {
165 warn("MIXER_READ");
166 continue;
168 if (shortflag)
169 printf("%s %d:%d ", names[i], LEFT(mset),
170 RIGHT(mset));
171 else
172 printf("Mixer %-8s is currently set to %3d:%d\n",
173 names[i], LEFT(mset), RIGHT(mset));
175 if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
176 err(1, "SOUND_MIXER_READ_RECSRC");
177 if (shortflag) {
178 print_recsrc_short(recsrc);
179 if (isatty(STDOUT_FILENO))
180 printf("\n");
181 } else
182 print_recsrc(recsrc);
183 exit(0);
188 while (argc > 0) {
189 if (!strcmp("recsrc", *argv)) {
190 drecsrc = 1;
191 argc--; argv++;
192 continue;
193 } else if (argc > 1 && !strcmp("rec", *argv + 1)) {
194 if (**argv != '+' && **argv != '-' &&
195 **argv != '=' && **argv != '^') {
196 warnx("unknown modifier: %c", **argv);
197 dusage = 1;
198 break;
200 if ((dev = res_name(argv[1], recmask)) == -1) {
201 warnx("unknown recording device: %s", argv[1]);
202 dusage = 1;
203 break;
205 switch(**argv) {
206 case '+':
207 recsrc |= (1 << dev);
208 break;
209 case '-':
210 recsrc &= ~(1 << dev);
211 break;
212 case '=':
213 recsrc = (1 << dev);
214 break;
215 case '^':
216 recsrc ^= (1 << dev);
217 break;
219 drecsrc = 1;
220 argc -= 2; argv += 2;
221 continue;
224 if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) {
225 dev = 0;
227 else if((dev = res_name(*argv, devmask)) == -1) {
228 warnx("unknown device: %s", *argv);
229 dusage = 1;
230 break;
233 #define issign(c) (((c) == '+') || ((c) == '-'))
235 if (argc > 1) {
236 n = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr);
237 if (n > 0) {
238 if (issign(lstr[0]))
239 lrel = rrel = 1;
240 l = atoi(lstr);
242 if (n > 1) {
243 rrel = 0;
244 if (issign(rstr[0]))
245 rrel = 1;
246 r = atoi(rstr);
250 switch(argc > 1 ? n : t) {
251 case 0:
252 if (ioctl(fd, MIXER_READ(dev),&mset)== -1) {
253 warn("MIXER_READ");
254 argc--; argv++;
255 continue;
257 if (shortflag)
258 printf("%s %d:%d ", names[dev], LEFT(mset),
259 RIGHT(mset));
260 else
261 printf("Mixer %-8s is currently set to %3d:%d\n",
262 names[dev], LEFT(mset), RIGHT(mset));
264 argc--; argv++;
265 break;
266 case 1:
267 r = l;
268 case 2:
269 if (ioctl(fd, MIXER_READ(dev),&mset)== -1) {
270 warn("MIXER_READ");
271 argc--; argv++;
272 continue;
275 if (lrel)
276 l += LEFT(mset);
277 if (rrel)
278 r += RIGHT(mset);
280 if (l < 0)
281 l = 0;
282 else if (l > 100)
283 l = 100;
284 if (r < 0)
285 r = 0;
286 else if (r > 100)
287 r = 100;
289 printf("Setting the mixer %s to %d:%d.\n", names[dev],
290 l, r);
292 l |= r << 8;
293 if (ioctl(fd, MIXER_WRITE(dev), &l) == -1)
294 warn("WRITE_MIXER");
296 argc -= 2; argv += 2;
297 break;
301 if (orecsrc != recsrc)
302 if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
303 err(1, "SOUND_MIXER_WRITE_RECSRC");
305 if (drecsrc) {
306 if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
307 err(1, "SOUND_MIXER_READ_RECSRC");
308 print_recsrc(recsrc);
311 close(fd);
313 exit(0);