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