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