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