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: }