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 <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, int shortflag); 30 31 void 32 usage(int devmask, int recmask) 33 { 34 int i, n; 35 36 printf("usage: mixer [-f device] [-s | -S] [dev [+|-][voll[:[+|-]volr]] ...\n" 37 " mixer [-f device] [-s | -S] recsrc ...\n" 38 " mixer [-f device] [-s | -S] {^|+|-|=}rec rdev ... \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, int shortflag) 73 { 74 int i, n = 0; 75 76 if (!shortflag) 77 printf("Recording source: "); 78 79 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 80 if ((1 << i) & recsrc) { 81 if (shortflag) { 82 if (n) 83 printf(" +rec "); 84 else 85 printf("=rec "); 86 } else if (n) 87 printf(", "); 88 printf("%s", names[i]); 89 n = 1; 90 } 91 if (!shortflag) 92 printf("\n"); 93 } 94 95 int 96 main(int argc, char *argv[]) 97 { 98 int foo, bar, baz, dev; 99 int devmask = 0, recmask = 0, recsrc = 0, orecsrc; 100 int dusage = 0, drecsrc = 0, shortflag = 0, Shortflag = 0; 101 int l = 0, r = 0, t = 0; 102 char lstr[5], rstr[5]; 103 int n = 0, lrel = 0, rrel = 0; 104 int ch; 105 106 char *name; 107 108 name = "/dev/mixer"; 109 110 if (!strcmp(argv[0], "mixer2")) 111 name = "/dev/mixer1"; 112 else if (!strcmp(argv[0], "mixer3")) 113 name = "/dev/mixer2"; 114 115 while ((ch = getopt(argc, argv, "f:sS")) != -1) 116 switch (ch) { 117 case 'f': 118 name = optarg; 119 break; 120 case 's': 121 shortflag = 1; 122 break; 123 case 'S': 124 Shortflag = 1; 125 break; 126 default: 127 dusage = 1; 128 } 129 argc -= (optind - 1); 130 argv += (optind - 1); 131 132 if ((baz = open(name, O_RDWR)) < 0) 133 err(1, "%s", name); 134 if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 135 err(1, "SOUND_MIXER_READ_DEVMASK"); 136 if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 137 err(1, "SOUND_MIXER_READ_RECMASK"); 138 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 139 err(1, "SOUND_MIXER_READ_RECSRC"); 140 orecsrc = recsrc; 141 142 if ((argc == 1) && (dusage == 0)) { 143 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { 144 if (!((1 << foo) & devmask)) 145 continue; 146 if (ioctl(baz, MIXER_READ(foo),&bar)== -1) { 147 warn("MIXER_READ"); 148 continue; 149 } 150 if (Shortflag) 151 printf("%s:%d:%d ", names[foo], bar & 0x7f, 152 (bar >> 8) & 0x7f); 153 else if (shortflag) 154 printf("%s %d:%d ", names[foo], bar & 0x7f, 155 (bar >> 8) & 0x7f); 156 else 157 printf("Mixer %-8s is currently set to %3d:%d\n", 158 names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 159 } 160 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 161 err(1, "SOUND_MIXER_READ_RECSRC"); 162 print_recsrc(recsrc, shortflag || Shortflag); 163 return(0); 164 } 165 166 argc--; argv++; 167 168 while ((argc > 0) && (dusage == 0)) { 169 if (!strcmp("recsrc", *argv)) { 170 drecsrc = 1; 171 argc--; argv++; 172 continue; 173 } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 174 if (**argv != '+' && **argv != '-' && 175 **argv != '=' && **argv != '^') { 176 warnx("unknown modifier: %c", **argv); 177 dusage = 1; 178 break; 179 } 180 if ((dev = res_name(argv[1], recmask)) == -1) { 181 warnx("unknown recording device: %s", argv[1]); 182 dusage = 1; 183 break; 184 } 185 switch(**argv) { 186 case '+': 187 recsrc |= (1 << dev); 188 break; 189 case '-': 190 recsrc &= ~(1 << dev); 191 break; 192 case '=': 193 recsrc = (1 << dev); 194 break; 195 case '^': 196 recsrc ^= (1 << dev); 197 break; 198 } 199 drecsrc = 1; 200 argc -= 2; argv += 2; 201 continue; 202 } 203 204 if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) { 205 dev = 0; 206 } 207 else if((dev = res_name(*argv, devmask)) == -1) { 208 warnx("unknown device: %s", *argv); 209 dusage = 1; 210 break; 211 } 212 213 #define issign(c) (((c) == '+') || ((c) == '-')) 214 215 if (argc > 1) { 216 n = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr); 217 if (n > 0) { 218 if (issign(lstr[0])) 219 lrel = rrel = 1; 220 l = atoi(lstr); 221 } 222 if (n > 1) { 223 rrel = 0; 224 if (issign(rstr[0])) 225 rrel = 1; 226 r = atoi(rstr); 227 } 228 } 229 230 switch(argc > 1 ? n : t) { 231 case 0: 232 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 233 warn("MIXER_READ"); 234 argc--; argv++; 235 continue; 236 } 237 if (Shortflag) 238 printf("%s:%d:%d ", names[dev], bar & 0x7f, 239 (bar >> 8) & 0x7f); 240 else if (shortflag) 241 printf("%s %d:%d ", names[dev], bar & 0x7f, 242 (bar >> 8) & 0x7f); 243 else 244 printf("Mixer %-8s is currently set to %3d:%d\n", 245 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 246 247 argc--; argv++; 248 break; 249 case 1: 250 r = l; 251 case 2: 252 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 253 warn("MIXER_READ"); 254 argc--; argv++; 255 continue; 256 } 257 258 if (lrel) 259 l = (bar & 0x7f) + l; 260 if (rrel) 261 r = ((bar >> 8) & 0x7f) + r; 262 263 if (l < 0) 264 l = 0; 265 else if (l > 100) 266 l = 100; 267 if (r < 0) 268 r = 0; 269 else if (r > 100) 270 r = 100; 271 272 if (!Shortflag) 273 printf("Setting the mixer %s from %d:%d to %d:%d.\n", 274 names[dev], bar & 0x7f, (bar >> 8) & 0x7f, l, r); 275 276 l |= r << 8; 277 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 278 warn("WRITE_MIXER"); 279 280 argc -= 2; argv += 2; 281 break; 282 } 283 } 284 285 if (dusage) { 286 close(baz); 287 usage(devmask, recmask); 288 /* Not reached */ 289 } 290 291 if (orecsrc != recsrc) 292 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 293 err(1, "SOUND_MIXER_WRITE_RECSRC"); 294 295 if (drecsrc) { 296 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 297 err(1, "SOUND_MIXER_READ_RECSRC"); 298 print_recsrc(recsrc, shortflag || Shortflag); 299 } 300 301 close(baz); 302 303 exit(0); 304 } 305