mixer.c revision 108421
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 15static const char rcsid[] = 16 "$FreeBSD: head/usr.sbin/mixer/mixer.c 108421 2002-12-30 04:23:08Z jmallett $"; 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 27const char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 28 29void usage(int devmask, int recmask); 30int res_name(const char *name, int mask); 31void print_recsrc(int recsrc); 32 33void 34usage(int devmask, int recmask) 35{ 36 int i, n; 37 38 printf("usage: mixer [-f device] [-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("%s", 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("%s", names[i]); 53 n = 1; 54 } 55 printf("\n"); 56 exit(1); 57} 58 59int 60res_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 71void 72print_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, "%s", names[i]); 82 n = 1; 83 } 84 fprintf(stderr, "\n"); 85} 86 87int 88main(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 = 0, r = 0, t = 0; 94 char ch; 95 96 char *name; 97 98 name = strdup("/dev/mixer"); 99 100 if (!strcmp(argv[0], "mixer2")) 101 name = strdup("/dev/mixer1"); 102 else if (!strcmp(argv[0], "mixer3")) 103 name = strdup("/dev/mixer2"); 104 105 while ((ch = getopt(argc, argv, "f:s")) != -1) 106 switch (ch) { 107 case 'f': 108 name = strdup(optarg); 109 break; 110 case 's': 111 shortflag = 1; 112 break; 113 default: 114 dusage = 1; 115 } 116 argc -= (optind - 1); 117 argv += (optind - 1); 118 119 if ((baz = open(name, O_RDWR)) < 0) 120 err(1, "%s", name); 121 free(name); 122 if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 123 err(1, "SOUND_MIXER_READ_DEVMASK"); 124 if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 125 err(1, "SOUND_MIXER_READ_RECMASK"); 126 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 127 err(1, "SOUND_MIXER_READ_RECSRC"); 128 orecsrc = recsrc; 129 130 if ((argc == 1) && (dusage == 0)) { 131 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { 132 if (!((1 << foo) & devmask)) 133 continue; 134 if (ioctl(baz, MIXER_READ(foo),&bar)== -1) { 135 warn("MIXER_READ"); 136 continue; 137 } 138 if (shortflag) 139 printf("%s %d:%d ", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 140 else 141 printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 142 } 143 return(0); 144 } 145 146 argc--; argv++; 147 148 while ((argc > 0) && (dusage == 0)) { 149 if (!strcmp("recsrc", *argv)) { 150 drecsrc = 1; 151 argc--; argv++; 152 continue; 153 } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 154 if (**argv != '+' && **argv != '-' && 155 **argv != '=' && **argv != '^') { 156 warnx("unknown modifier: %c", **argv); 157 dusage = 1; 158 break; 159 } 160 if ((dev = res_name(argv[1], recmask)) == -1) { 161 warnx("unknown recording device: %s", argv[1]); 162 dusage = 1; 163 break; 164 } 165 switch(**argv) { 166 case '+': 167 recsrc |= (1 << dev); 168 break; 169 case '-': 170 recsrc &= ~(1 << dev); 171 break; 172 case '=': 173 recsrc = (1 << dev); 174 break; 175 case '^': 176 recsrc ^= (1 << dev); 177 break; 178 } 179 drecsrc = 1; 180 argc -= 2; argv += 2; 181 continue; 182 } 183 184 if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) { 185 dev = 0; 186 } 187 else if((dev = res_name(*argv, devmask)) == -1) { 188 warnx("unknown device: %s", *argv); 189 dusage = 1; 190 break; 191 } 192 193 switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : t) { 194 case 0: 195 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 196 warn("MIXER_READ"); 197 argc--; argv++; 198 continue; 199 } 200 if (shortflag) 201 printf("%s %d:%d ", names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 202 else 203 printf("Mixer %-8s is currently set to %3d:%d\n", 204 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 205 206 argc--; argv++; 207 break; 208 case 1: 209 r = l; 210 case 2: 211 if (l < 0) 212 l = 0; 213 else if (l > 100) 214 l = 100; 215 if (r < 0) 216 r = 0; 217 else if (r > 100) 218 r = 100; 219 220 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 221 warn("MIXER_READ"); 222 argc--; argv++; 223 continue; 224 } 225 226 printf("Setting the mixer %s from %d:%d to %d:%d.\n", 227 names[dev], bar & 0x7f, (bar >> 8) & 0x7f, l, r); 228 229 l |= r << 8; 230 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 231 warn("WRITE_MIXER"); 232 233 argc -= 2; argv += 2; 234 break; 235 } 236 } 237 238 if (dusage) { 239 close(baz); 240 usage(devmask, recmask); 241 /* Not reached */ 242 } 243 244 if (orecsrc != recsrc) 245 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 246 err(1, "SOUND_MIXER_WRITE_RECSRC"); 247 248 if (drecsrc) { 249 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 250 err(1, "SOUND_MIXER_READ_RECSRC"); 251 print_recsrc(recsrc); 252 } 253 254 close(baz); 255 256 exit(0); 257} 258