mixer.c revision 114601
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#include <sys/cdefs.h> 15__FBSDID("$FreeBSD: head/usr.sbin/mixer/mixer.c 114601 2003-05-03 21:06:42Z obrien $"); 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 25const char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 26 27void usage(int devmask, int recmask); 28int res_name(const char *name, int mask); 29void print_recsrc(int recsrc); 30 31void 32usage(int devmask, int recmask) 33{ 34 int i, n; 35 36 printf("usage: mixer [-f device] [-s] [dev [+|-][voll[:[+|-]volr]] ...\n" 37 " mixer [-f device] [-s] recsrc ...\n" 38 " mixer [-f device] [-s] {^|+|-|=}rec rdev ... \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 lstr[5], rstr[5]; 95 int n = 0, lrel = 0, rrel = 0; 96 char ch; 97 98 char *name; 99 100 name = strdup("/dev/mixer"); 101 102 if (!strcmp(argv[0], "mixer2")) 103 name = strdup("/dev/mixer1"); 104 else if (!strcmp(argv[0], "mixer3")) 105 name = strdup("/dev/mixer2"); 106 107 while ((ch = getopt(argc, argv, "f:s")) != -1) 108 switch (ch) { 109 case 'f': 110 name = strdup(optarg); 111 break; 112 case 's': 113 shortflag = 1; 114 break; 115 default: 116 dusage = 1; 117 } 118 argc -= (optind - 1); 119 argv += (optind - 1); 120 121 if ((baz = open(name, O_RDWR)) < 0) 122 err(1, "%s", name); 123 free(name); 124 if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 125 err(1, "SOUND_MIXER_READ_DEVMASK"); 126 if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 127 err(1, "SOUND_MIXER_READ_RECMASK"); 128 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 129 err(1, "SOUND_MIXER_READ_RECSRC"); 130 orecsrc = recsrc; 131 132 if ((argc == 1) && (dusage == 0)) { 133 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { 134 if (!((1 << foo) & devmask)) 135 continue; 136 if (ioctl(baz, MIXER_READ(foo),&bar)== -1) { 137 warn("MIXER_READ"); 138 continue; 139 } 140 if (shortflag) 141 printf("%s %d:%d ", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 142 else 143 printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 144 } 145 return(0); 146 } 147 148 argc--; argv++; 149 150 while ((argc > 0) && (dusage == 0)) { 151 if (!strcmp("recsrc", *argv)) { 152 drecsrc = 1; 153 argc--; argv++; 154 continue; 155 } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 156 if (**argv != '+' && **argv != '-' && 157 **argv != '=' && **argv != '^') { 158 warnx("unknown modifier: %c", **argv); 159 dusage = 1; 160 break; 161 } 162 if ((dev = res_name(argv[1], recmask)) == -1) { 163 warnx("unknown recording device: %s", argv[1]); 164 dusage = 1; 165 break; 166 } 167 switch(**argv) { 168 case '+': 169 recsrc |= (1 << dev); 170 break; 171 case '-': 172 recsrc &= ~(1 << dev); 173 break; 174 case '=': 175 recsrc = (1 << dev); 176 break; 177 case '^': 178 recsrc ^= (1 << dev); 179 break; 180 } 181 drecsrc = 1; 182 argc -= 2; argv += 2; 183 continue; 184 } 185 186 if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) { 187 dev = 0; 188 } 189 else if((dev = res_name(*argv, devmask)) == -1) { 190 warnx("unknown device: %s", *argv); 191 dusage = 1; 192 break; 193 } 194 195#define issign(c) (((c) == '+') || ((c) == '-')) 196 197 if (argc > 1) { 198 n = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr); 199 if (n > 0) { 200 if (issign(lstr[0])) 201 lrel = rrel = 1; 202 l = atoi(lstr); 203 } 204 if (n > 1) { 205 rrel = 0; 206 if (issign(rstr[0])) 207 rrel = 1; 208 r = atoi(rstr); 209 } 210 } 211 212 switch(argc > 1 ? n : t) { 213 case 0: 214 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 215 warn("MIXER_READ"); 216 argc--; argv++; 217 continue; 218 } 219 if (shortflag) 220 printf("%s %d:%d ", names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 221 else 222 printf("Mixer %-8s is currently set to %3d:%d\n", 223 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 224 225 argc--; argv++; 226 break; 227 case 1: 228 r = l; 229 case 2: 230 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 231 warn("MIXER_READ"); 232 argc--; argv++; 233 continue; 234 } 235 236 if (lrel) 237 l = (bar & 0x7f) + l; 238 if (rrel) 239 r = ((bar >> 8) & 0x7f) + r; 240 241 if (l < 0) 242 l = 0; 243 else if (l > 100) 244 l = 100; 245 if (r < 0) 246 r = 0; 247 else if (r > 100) 248 r = 100; 249 250 printf("Setting the mixer %s from %d:%d to %d:%d.\n", 251 names[dev], bar & 0x7f, (bar >> 8) & 0x7f, l, r); 252 253 l |= r << 8; 254 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 255 warn("WRITE_MIXER"); 256 257 argc -= 2; argv += 2; 258 break; 259 } 260 } 261 262 if (dusage) { 263 close(baz); 264 usage(devmask, recmask); 265 /* Not reached */ 266 } 267 268 if (orecsrc != recsrc) 269 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 270 err(1, "SOUND_MIXER_WRITE_RECSRC"); 271 272 if (drecsrc) { 273 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 274 err(1, "SOUND_MIXER_READ_RECSRC"); 275 print_recsrc(recsrc); 276 } 277 278 close(baz); 279 280 exit(0); 281} 282