mixer.c revision 153953
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: head/usr.sbin/mixer/mixer.c 153953 2006-01-01 20:19:49Z ariff $"); 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 25const char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 26 27void usage(int devmask, int recmask); 28int res_name(const char *name, int mask); 29void print_recsrc(int recsrc, int shortflag); 30 31void 32usage(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 59int 60res_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 71void 72print_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 95int 96main(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