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 [[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; 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 > 2 && strcmp(argv[1], "-f") == 0) { 105 name = strdup(argv[2]); 106 argc -= 2; argv += 2; 107 } 108 109 if ((baz = open(name, O_RDWR)) < 0) 110 err(1, "%s", name); 111 free(name); 112 if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 113 err(1, "SOUND_MIXER_READ_DEVMASK"); 114 if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 115 err(1, "SOUND_MIXER_READ_RECMASK"); 116 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 117 err(1, "SOUND_MIXER_READ_RECSRC"); 118 orecsrc = recsrc; 119 120 if (argc == 1) { 121 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { 122 if (!((1 << foo) & devmask)) 123 continue; 124 if (ioctl(baz, MIXER_READ(foo),&bar)== -1) { 125 warn("MIXER_READ"); 126 continue; 127 } 128 printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 129 } 130 return(0); 131 } 132 133 argc--; argv++; 134 135 while (argc) { 136 if (!strcmp("recsrc", *argv)) { 137 drecsrc = 1; 138 argc--; argv++; 139 continue; 140 } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 141 if (**argv != '+' && **argv != '-' && 142 **argv != '=' && **argv != '^') { 143 dusage = 1; 144 argc -= 1; argv += 1; 145 continue; 146 } 147 if ((dev = res_name(argv[1], recmask)) == -1) { 148 dusage = 1; 149 argc -= 1; argv += 1; 150 continue; 151 } 152 switch(**argv) { 153 case '+': 154 recsrc |= (1 << dev); 155 break; 156 case '-': 157 recsrc &= ~(1 << dev); 158 break; 159 case '=': 160 recsrc = (1 << dev); 161 break; 162 case '^': 163 recsrc ^= (1 << dev); 164 break; 165 } 166 drecsrc = 1; 167 argc -= 2; argv += 2; 168 continue; 169 } 170 171 if ((dev = res_name(*argv, devmask)) == -1) { 172 dusage = 1; 173 argc--; argv++; 174 continue; 175 } 176 177 switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) { 178 case 0: 179 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 180 warn("MIXER_READ"); 181 argc--; argv++; 182 continue; 183 } 184 printf("Mixer %-8s is currently set to %3d:%d\n", 185 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 186 187 argc--; argv++; 188 break; 189 case 1: 190 r = l; 191 case 2: 192 if (l < 0) 193 l = 0; 194 else if (l > 100) 195 l = 100; 196 if (r < 0) 197 r = 0; 198 else if (r > 100) 199 r = 100; 200 201 printf("Setting the mixer %s to %d:%d.\n", names[dev], 202 l, r); 203 204 l |= r << 8; 205 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 206 warn("WRITE_MIXER"); 207 208 argc -= 2; argv += 2; 209 break; 210 } 211 } 212 213 if (orecsrc != recsrc) 214 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 215 err(1, "SOUND_MIXER_WRITE_RECSRC"); 216 217 if (drecsrc) { 218 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 219 err(1, "SOUND_MIXER_READ_RECSRC"); 220 print_recsrc(recsrc); 221 } 222 223 close(baz); 224 225 if (dusage) 226 usage(devmask, recmask); 227 228 exit(0); 229 } 230