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