]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/mixer/mixer.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / usr.sbin / mixer / mixer.c
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 #include <sys/cdefs.h>
15 __FBSDID("$FreeBSD$");
16
17 #include <err.h>
18 #include <fcntl.h>
19 #include <libgen.h>
20 #include <limits.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <sys/soundcard.h>
26
27 const char      *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
28
29 static void     usage(int devmask, int recmask);
30 static int      res_name(const char *name, int mask);
31 static void     print_recsrc(int recsrc, int recmask, int sflag);
32
33 static void
34 usage(int devmask, int recmask)
35 {
36         int     i, n;
37
38         printf("usage: mixer [-f device] [-s | -S] [dev [+|-][voll[:[+|-]volr]] ...\n"
39             "       mixer [-f device] [-s | -S] recsrc ...\n"
40             "       mixer [-f device] [-s | -S] {^|+|-|=}rec rdev ...\n");
41         if (devmask != 0) {
42                 printf(" devices: ");
43                 for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
44                         if ((1 << i) & devmask)  {
45                                 if (n)
46                                         printf(", ");
47                                 printf("%s", names[i]);
48                                 n++;
49                         }
50         }
51         if (recmask != 0) {
52                 printf("\n rec devices: ");
53                 for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
54                         if ((1 << i) & recmask)  {
55                                 if (n)
56                                         printf(", ");
57                                 printf("%s", names[i]);
58                                 n++;
59                         }
60         }
61         printf("\n");
62         exit(1);
63 }
64
65 static int
66 res_name(const char *name, int mask)
67 {
68         int     foo;
69
70         for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++)
71                 if ((1 << foo) & mask && strcmp(names[foo], name) == 0)
72                         break;
73
74         return (foo == SOUND_MIXER_NRDEVICES ? -1 : foo);
75 }
76
77 static void
78 print_recsrc(int recsrc, int recmask, int sflag)
79 {
80         int     i, n;
81
82         if (recmask == 0)
83                 return;
84
85         if (!sflag)
86                 printf("Recording source: ");
87
88         for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++)
89                 if ((1 << i) & recsrc) {
90                         if (sflag)
91                                 printf("%srec ", n ? " +" : "=");
92                         else if (n)
93                                 printf(", ");
94                         printf("%s", names[i]);
95                         n++;
96                 }
97         if (!sflag)
98                 printf("\n");
99 }
100
101 int
102 main(int argc, char *argv[])
103 {
104         char    mixer[PATH_MAX] = "/dev/mixer";
105         char    lstr[5], rstr[5];
106         char    *name, *eptr;
107         int     devmask = 0, recmask = 0, recsrc = 0, orecsrc;
108         int     dusage = 0, drecsrc = 0, sflag = 0, Sflag = 0;
109         int     l, r, lrel, rrel;
110         int     ch, foo, bar, baz, dev, m, n, t;
111
112         if ((name = strdup(basename(argv[0]))) == NULL)
113                 err(1, "strdup()");
114         if (strncmp(name, "mixer", 5) == 0 && name[5] != '\0') {
115                 n = strtol(name + 5, &eptr, 10) - 1;
116                 if (n > 0 && *eptr == '\0')
117                         snprintf(mixer, PATH_MAX - 1, "/dev/mixer%d", n);
118         }
119         free(name);
120         name = mixer;
121
122         n = 1;
123         for (;;) {
124                 if (n >= argc || *argv[n] != '-')
125                         break;
126                 if (strlen(argv[n]) != 2) {
127                         if (strcmp(argv[n] + 1, "rec") != 0)
128                                 dusage = 1;
129                         break;
130                 }
131                 ch = *(argv[n] + 1);
132                 if (ch == 'f' && n < argc - 1) {
133                         name = argv[n + 1];
134                         n += 2;
135                 } else if (ch == 's') {
136                         sflag = 1;
137                         n++;
138                 } else if (ch == 'S') {
139                         Sflag = 1;
140                         n++;
141                 } else {
142                         dusage = 1;
143                         break;
144                 }
145         }
146         if (sflag && Sflag)
147                 dusage = 1;
148
149         argc -= n - 1;
150         argv += n - 1;
151
152         if ((baz = open(name, O_RDWR)) < 0)
153                 err(1, "%s", name);
154         if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1)
155                 err(1, "SOUND_MIXER_READ_DEVMASK");
156         if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1)
157                 err(1, "SOUND_MIXER_READ_RECMASK");
158         if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
159                 err(1, "SOUND_MIXER_READ_RECSRC");
160         orecsrc = recsrc;
161
162         if (argc == 1 && dusage == 0) {
163                 for (foo = 0, n = 0; foo < SOUND_MIXER_NRDEVICES; foo++) {
164                         if (!((1 << foo) & devmask))
165                                 continue;
166                         if (ioctl(baz, MIXER_READ(foo),&bar) == -1) {
167                                 warn("MIXER_READ");
168                                 continue;
169                         }
170                         if (Sflag || sflag) {
171                                 printf("%s%s%c%d:%d", n ? " " : "",
172                                     names[foo], Sflag ? ':' : ' ',
173                                     bar & 0x7f, (bar >> 8) & 0x7f);
174                                 n++;
175                         } else
176                                 printf("Mixer %-8s is currently set to "
177                                     "%3d:%d\n", names[foo], bar & 0x7f,
178                                     (bar >> 8) & 0x7f);
179                 }
180                 if (n && recmask)
181                         printf(" ");
182                 print_recsrc(recsrc, recmask, Sflag || sflag);
183                 return (0);
184         }
185
186         argc--;
187         argv++;
188
189         n = 0;
190         while (argc > 0 && dusage == 0) {
191                 if (strcmp("recsrc", *argv) == 0) {
192                         drecsrc = 1;
193                         argc--;
194                         argv++;
195                         continue;
196                 } else if (strcmp("rec", *argv + 1) == 0) {
197                         if (**argv != '+' && **argv != '-' &&
198                             **argv != '=' && **argv != '^') {
199                                 warnx("unknown modifier: %c", **argv);
200                                 dusage = 1;
201                                 break;
202                         }
203                         if (argc <= 1) {
204                                 warnx("no recording device specified");
205                                 dusage = 1;
206                                 break;
207                         }
208                         if ((dev = res_name(argv[1], recmask)) == -1) {
209                                 warnx("unknown recording device: %s", argv[1]);
210                                 dusage = 1;
211                                 break;
212                         }
213                         switch (**argv) {
214                         case '+':
215                                 recsrc |= (1 << dev);
216                                 break;
217                         case '-':
218                                 recsrc &= ~(1 << dev);
219                                 break;
220                         case '=':
221                                 recsrc = (1 << dev);
222                                 break;
223                         case '^':
224                                 recsrc ^= (1 << dev);
225                                 break;
226                         }
227                         drecsrc = 1;
228                         argc -= 2;
229                         argv += 2;
230                         continue;
231                 }
232
233                 if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0)
234                         dev = 0;
235                 else if ((dev = res_name(*argv, devmask)) == -1) {
236                         warnx("unknown device: %s", *argv);
237                         dusage = 1;
238                         break;
239                 }
240
241                 lrel = rrel = 0;
242                 if (argc > 1) {
243                         m = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr);
244                         if (m > 0) {
245                                 if (*lstr == '+' || *lstr == '-')
246                                         lrel = rrel = 1;
247                                 l = strtol(lstr, NULL, 10);
248                         }
249                         if (m > 1) {
250                                 if (*rstr == '+' || *rstr == '-')
251                                         rrel = 1;
252                                 r = strtol(rstr, NULL, 10);
253                         }
254                 }
255
256                 switch (argc > 1 ? m : t) {
257                 case 0:
258                         if (ioctl(baz, MIXER_READ(dev), &bar) == -1) {
259                                 warn("MIXER_READ");
260                                 argc--;
261                                 argv++;
262                                 continue;
263                         }
264                         if (Sflag || sflag) {
265                                 printf("%s%s%c%d:%d", n ? " " : "",
266                                     names[dev], Sflag ? ':' : ' ',
267                                     bar & 0x7f, (bar >> 8) & 0x7f);
268                                 n++;
269                         } else
270                                 printf("Mixer %-8s is currently set to "
271                                     "%3d:%d\n", names[dev], bar & 0x7f,
272                                     (bar >> 8) & 0x7f);
273
274                         argc--;
275                         argv++;
276                         break;
277                 case 1:
278                         r = l;
279                         /* FALLTHROUGH */
280                 case 2:
281                         if (ioctl(baz, MIXER_READ(dev), &bar) == -1) {
282                                 warn("MIXER_READ");
283                                 argc--;
284                                 argv++;
285                                 continue;
286                         }
287
288                         if (lrel)
289                                 l = (bar & 0x7f) + l;
290                         if (rrel)
291                                 r = ((bar >> 8) & 0x7f) + r;
292
293                         if (l < 0)
294                                 l = 0;
295                         else if (l > 100)
296                                 l = 100;
297                         if (r < 0)
298                                 r = 0;
299                         else if (r > 100)
300                                 r = 100;
301
302                         if (!Sflag)
303                                 printf("Setting the mixer %s from %d:%d to "
304                                     "%d:%d.\n", names[dev], bar & 0x7f,
305                                     (bar >> 8) & 0x7f, l, r);
306
307                         l |= r << 8;
308                         if (ioctl(baz, MIXER_WRITE(dev), &l) == -1)
309                                 warn("WRITE_MIXER");
310
311                         argc -= 2;
312                         argv += 2;
313                         break;
314                 }
315         }
316
317         if (dusage) {
318                 close(baz);
319                 usage(devmask, recmask);
320                 /* NOTREACHED */
321         }
322
323         if (orecsrc != recsrc) {
324                 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
325                         err(1, "SOUND_MIXER_WRITE_RECSRC");
326                 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
327                         err(1, "SOUND_MIXER_READ_RECSRC");
328         }
329
330         if (drecsrc)
331                 print_recsrc(recsrc, recmask, Sflag || sflag);
332
333         close(baz);
334
335         return (0);
336 }