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 #ifndef lint 15 static const char rcsid[] = 16 "$FreeBSD$"; 17 #endif /* not lint */ 18 19 #include <err.h> 20 #include <fcntl.h> 21 #include <stdio.h> 22 #include <string.h> 23 #include <stdlib.h> 24 #include <unistd.h> 25 #include <sys/soundcard.h> 26 27 char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 28 29 void usage(int devmask, int recmask); 30 int res_name(const char *name, int mask); 31 void print_recsrc(int recsrc); 32 33 void 34 usage(int devmask, int recmask) 35 { 36 int i, n; 37 38 printf("usage: mixer [-s] [[dev [voll[:volr]] | recsrc | {^|+|-|=}rec recdev] ... ]\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(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(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, 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; 93 int l, r; 94 95 char *name; 96 97 name = strdup("/dev/mixer"); 98 99 if (!strcmp(argv[0], "mixer2")) 100 name = strdup("/dev/mixer1"); 101 else if (!strcmp(argv[0], "mixer3")) 102 name = strdup("/dev/mixer2"); 103 104 if (argc > 1 && strcmp(argv[1], "-s") == 0) { 105 shortflag = 1; 106 argc -= 1; argv += 1; 107 } 108 if (argc > 2 && strcmp(argv[1], "-f") == 0) { 109 name = strdup(argv[2]); 110 argc -= 2; argv += 2; 111 } 112 113 if ((baz = open(name, O_RDWR)) < 0) 114 err(1, "%s", name); 115 free(name); 116 if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 117 err(1, "SOUND_MIXER_READ_DEVMASK"); 118 if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 119 err(1, "SOUND_MIXER_READ_RECMASK"); 120 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 121 err(1, "SOUND_MIXER_READ_RECSRC"); 122 orecsrc = recsrc; 123 124 if (argc == 1) { 125 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { 126 if (!((1 << foo) & devmask)) 127 continue; 128 if (ioctl(baz, MIXER_READ(foo),&bar)== -1) { 129 warn("MIXER_READ"); 130 continue; 131 } 132 if (shortflag) 133 printf("%s %d:%d ", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 134 else 135 printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 136 } 137 return(0); 138 } 139 140 argc--; argv++; 141 142 while (argc) { 143 if (!strcmp("recsrc", *argv)) { 144 drecsrc = 1; 145 argc--; argv++; 146 continue; 147 } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 148 if (**argv != '+' && **argv != '-' && 149 **argv != '=' && **argv != '^') { 150 dusage = 1; 151 argc -= 1; argv += 1; 152 continue; 153 } 154 if ((dev = res_name(argv[1], recmask)) == -1) { 155 dusage = 1; 156 argc -= 1; argv += 1; 157 continue; 158 } 159 switch(**argv) { 160 case '+': 161 recsrc |= (1 << dev); 162 break; 163 case '-': 164 recsrc &= ~(1 << dev); 165 break; 166 case '=': 167 recsrc = (1 << dev); 168 break; 169 case '^': 170 recsrc ^= (1 << dev); 171 break; 172 } 173 drecsrc = 1; 174 argc -= 2; argv += 2; 175 continue; 176 } 177 178 if ((dev = res_name(*argv, devmask)) == -1) { 179 dusage = 1; 180 argc--; argv++; 181 continue; 182 } 183 184 switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) { 185 case 0: 186 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 187 warn("MIXER_READ"); 188 argc--; argv++; 189 continue; 190 } 191 if (shortflag) 192 printf("%s %d:%d ", names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 193 else 194 printf("Mixer %-8s is currently set to %3d:%d\n", 195 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 196 197 argc--; argv++; 198 break; 199 case 1: 200 r = l; 201 case 2: 202 if (l < 0) 203 l = 0; 204 else if (l > 100) 205 l = 100; 206 if (r < 0) 207 r = 0; 208 else if (r > 100) 209 r = 100; 210 211 printf("Setting the mixer %s to %d:%d.\n", names[dev], 212 l, r); 213 214 l |= r << 8; 215 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 216 warn("WRITE_MIXER"); 217 218 argc -= 2; argv += 2; 219 break; 220 } 221 } 222 223 if (orecsrc != recsrc) 224 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 225 err(1, "SOUND_MIXER_WRITE_RECSRC"); 226 227 if (drecsrc) { 228 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 229 err(1, "SOUND_MIXER_READ_RECSRC"); 230 print_recsrc(recsrc); 231 } 232 233 close(baz); 234 235 if (dusage) 236 usage(devmask, recmask); 237 238 exit(0); 239 } 240