Merge branch 'vendor/GCC47'
[dragonfly.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  * $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 $
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 #define LEFT(vol) (vol & 0x7f)
26 #define RIGHT(vol) ((vol >> 8) & 0x7f)
27
28 static const char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
29 static const char *defaultdev = "/dev/mixer";
30
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);
35
36 void
37 usage(int devmask, int recmask)
38 {
39         int i, n;
40
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;
52                 }
53         }
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;
61                 }
62         }
63         printf("\n");
64         exit(1);
65 }
66
67 int
68 res_name(const char *name, int mask)
69 {
70         int i;
71
72         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
73                 if ((1 << i) & mask && !strcmp(names[i], name))
74                         break;
75
76         if (i == SOUND_MIXER_NRDEVICES)
77                 return(-1);
78
79         return(i);
80 }
81
82 void
83 print_recsrc(int recsrc)
84 {
85         int i, n = 0;
86         printf("Recording source: ");
87
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;
94                 }
95         }
96         printf("\n");
97 }
98
99 void
100 print_recsrc_short(int recsrc)
101 {
102         int i, first;
103
104         first = 1;
105
106         for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) {
107                 if ((1 << i) & recsrc) {
108                         if (first) {
109                                 printf("=rec ");
110                                 first = 0;
111                         }
112                         printf("%s ", names[i]);
113                 }
114         }
115 }
116
117 int
118 main(int argc, char **argv)
119 {
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;
127
128         const char *name = defaultdev;
129
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;
141                 }
142         argc -= optind;
143         argv += optind;
144
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;
154
155         if (dusage) {
156                 close(fd);
157                 usage(devmask, recmask); /* Does not return */
158         }
159
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;
167                         }
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));
174                 }
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);
184         }
185
186
187
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;
199                         }
200                         if ((dev = res_name(argv[1], recmask)) == -1) {
201                                 warnx("unknown recording device: %s", argv[1]);
202                                 dusage = 1;
203                                 break;
204                         }
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;
218                         }
219                         drecsrc = 1;
220                         argc -= 2; argv += 2;
221                         continue;
222                 }
223
224                 if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) {
225                         dev = 0;
226                 }
227                 else if((dev = res_name(*argv, devmask)) == -1) {
228                         warnx("unknown device: %s", *argv);
229                         dusage = 1;
230                         break;
231                 }
232
233 #define issign(c)       (((c) == '+') || ((c) == '-'))
234
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);
241                         }
242                         if (n > 1) {
243                                 rrel = 0;
244                                 if (issign(rstr[0]))
245                                         rrel = 1;
246                                 r = atoi(rstr);
247                         }
248                 }
249
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;
256                         }
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));
263
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;
273                         }
274
275                         if (lrel)
276                                 l += LEFT(mset);
277                         if (rrel)
278                                 r += RIGHT(mset);
279
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;
288
289                         printf("Setting the mixer %s to %d:%d.\n", names[dev],
290                                l, r);
291
292                         l |= r << 8;
293                         if (ioctl(fd, MIXER_WRITE(dev), &l) == -1)
294                                 warn("WRITE_MIXER");
295
296                         argc -= 2; argv += 2;
297                         break;
298                 }
299         }
300
301         if (orecsrc != recsrc)
302                 if (ioctl(fd, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1)
303                         err(1, "SOUND_MIXER_WRITE_RECSRC");
304  
305         if (drecsrc) {
306                 if (ioctl(fd, SOUND_MIXER_READ_RECSRC, &recsrc) == -1)
307                         err(1, "SOUND_MIXER_READ_RECSRC");
308                 print_recsrc(recsrc);
309         }
310
311         close(fd);
312
313         exit(0);
314 }