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 "$Id: mixer.c,v 1.8 1997/10/01 06:34:09 charnier Exp $"; 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 #ifdef __FreeBSD__ 26 #include <machine/soundcard.h> 27 #else 28 #include <sys/soundcard.h> 29 #endif 30 31 char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 32 33 void usage(int devmask, int recmask); 34 int res_name(const char *name, int mask); 35 void print_recsrc(int recsrc); 36 37 void 38 usage(int devmask, int recmask) 39 { 40 int i, n; 41 42 printf("usage: mixer [[dev [voll[:volr]] | recsrc | {^|+|-|=}rec recdev] ... ]\n"); 43 printf(" devices: "); 44 for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 45 if ((1 << i) & devmask) { 46 if (n) 47 printf(", "); 48 printf(names[i]); 49 n = 1; 50 } 51 printf("\n rec devices: "); 52 for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 53 if ((1 << i) & recmask) { 54 if (n) 55 printf(", "); 56 printf(names[i]); 57 n = 1; 58 } 59 printf("\n"); 60 exit(1); 61 } 62 63 int 64 res_name(const char *name, int mask) 65 { 66 int foo; 67 68 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) 69 if ((1 << foo) & mask && !strcmp(names[foo], name)) 70 break; 71 72 return foo == SOUND_MIXER_NRDEVICES ? -1 : foo; 73 } 74 75 void 76 print_recsrc(int recsrc) 77 { 78 int i, n = 0; 79 fprintf(stderr, "Recording source: "); 80 81 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 82 if ((1 << i) & recsrc) { 83 if (n) 84 fprintf(stderr, ", "); 85 fprintf(stderr, names[i]); 86 n = 1; 87 } 88 fprintf(stderr, "\n"); 89 } 90 91 int 92 main(int argc, char *argv[]) 93 { 94 int foo, bar, baz, dev; 95 int devmask = 0, recmask = 0, recsrc = 0, orecsrc; 96 int dusage = 0, drecsrc = 0; 97 int l, r; 98 99 char *name; 100 101 name = strdup("/dev/mixer"); 102 103 if (!strcmp(argv[0], "mixer2")) 104 name = strdup("/dev/mixer1"); 105 else if (!strcmp(argv[0], "mixer3")) 106 name = strdup("/dev/mixer2"); 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 printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 133 } 134 return(0); 135 } 136 137 argc--; argv++; 138 139 while (argc) { 140 if (!strcmp("recsrc", *argv)) { 141 drecsrc = 1; 142 argc--; argv++; 143 continue; 144 } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 145 if (**argv != '+' && **argv != '-' && 146 **argv != '=' && **argv != '^') { 147 dusage = 1; 148 argc -= 1; argv += 1; 149 continue; 150 } 151 if ((dev = res_name(argv[1], recmask)) == -1) { 152 dusage = 1; 153 argc -= 1; argv += 1; 154 continue; 155 } 156 switch(**argv) { 157 case '+': 158 recsrc |= (1 << dev); 159 break; 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 } 170 drecsrc = 1; 171 argc -= 2; argv += 2; 172 continue; 173 } 174 175 if ((dev = res_name(*argv, devmask)) == -1) { 176 dusage = 1; 177 argc--; argv++; 178 continue; 179 } 180 181 switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) { 182 case 0: 183 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 184 warn("MIXER_READ"); 185 argc--; argv++; 186 continue; 187 } 188 printf("Mixer %-8s is currently set to %3d:%d\n", 189 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 190 191 argc--; argv++; 192 break; 193 case 1: 194 r = l; 195 case 2: 196 if (l < 0) 197 l = 0; 198 else if (l > 100) 199 l = 100; 200 if (r < 0) 201 r = 0; 202 else if (r > 100) 203 r = 100; 204 205 printf("Setting the mixer %s to %d:%d.\n", names[dev], 206 l, r); 207 208 l |= r << 8; 209 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 210 warn("WRITE_MIXER"); 211 212 argc -= 2; argv += 2; 213 break; 214 } 215 } 216 217 if (orecsrc != recsrc) 218 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 219 err(1, "SOUND_MIXER_WRITE_RECSRC"); 220 221 if (drecsrc) { 222 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 223 err(1, "SOUND_MIXER_READ_RECSRC"); 224 print_recsrc(recsrc); 225 } 226 227 close(baz); 228 229 if (dusage) 230 usage(devmask, recmask); 231 232 exit(0); 233 } 234