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