mixer.c revision 113299
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 113299 2003-04-09 15:25:52Z mdodd $"; 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]] ...\n" 39 " mixer [-f device] [-s] recsrc ...\n" 40 " mixer [-f device] [-s] {^|+|-|=}rec rdev ... \n"); 41 printf(" devices: "); 42 for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 43 if ((1 << i) & devmask) { 44 if (n) 45 printf(", "); 46 printf("%s", names[i]); 47 n = 1; 48 } 49 printf("\n rec devices: "); 50 for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 51 if ((1 << i) & recmask) { 52 if (n) 53 printf(", "); 54 printf("%s", names[i]); 55 n = 1; 56 } 57 printf("\n"); 58 exit(1); 59} 60 61int 62res_name(const char *name, int mask) 63{ 64 int foo; 65 66 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) 67 if ((1 << foo) & mask && !strcmp(names[foo], name)) 68 break; 69 70 return foo == SOUND_MIXER_NRDEVICES ? -1 : foo; 71} 72 73void 74print_recsrc(int recsrc) 75{ 76 int i, n = 0; 77 fprintf(stderr, "Recording source: "); 78 79 for (i = 0; i < SOUND_MIXER_NRDEVICES; i++) 80 if ((1 << i) & recsrc) { 81 if (n) 82 fprintf(stderr, ", "); 83 fprintf(stderr, "%s", names[i]); 84 n = 1; 85 } 86 fprintf(stderr, "\n"); 87} 88 89int 90main(int argc, char *argv[]) 91{ 92 int foo, bar, baz, dev; 93 int devmask = 0, recmask = 0, recsrc = 0, orecsrc; 94 int dusage = 0, drecsrc = 0, shortflag = 0; 95 int l = 0, r = 0, t = 0; 96 char lstr[5], rstr[5]; 97 int n = 0, lrel = 0, rrel = 0; 98 char ch; 99 100 char *name; 101 102 name = strdup("/dev/mixer"); 103 104 if (!strcmp(argv[0], "mixer2")) 105 name = strdup("/dev/mixer1"); 106 else if (!strcmp(argv[0], "mixer3")) 107 name = strdup("/dev/mixer2"); 108 109 while ((ch = getopt(argc, argv, "f:s")) != -1) 110 switch (ch) { 111 case 'f': 112 name = strdup(optarg); 113 break; 114 case 's': 115 shortflag = 1; 116 break; 117 default: 118 dusage = 1; 119 } 120 argc -= (optind - 1); 121 argv += (optind - 1); 122 123 if ((baz = open(name, O_RDWR)) < 0) 124 err(1, "%s", name); 125 free(name); 126 if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) 127 err(1, "SOUND_MIXER_READ_DEVMASK"); 128 if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) 129 err(1, "SOUND_MIXER_READ_RECMASK"); 130 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 131 err(1, "SOUND_MIXER_READ_RECSRC"); 132 orecsrc = recsrc; 133 134 if ((argc == 1) && (dusage == 0)) { 135 for (foo = 0; foo < SOUND_MIXER_NRDEVICES; foo++) { 136 if (!((1 << foo) & devmask)) 137 continue; 138 if (ioctl(baz, MIXER_READ(foo),&bar)== -1) { 139 warn("MIXER_READ"); 140 continue; 141 } 142 if (shortflag) 143 printf("%s %d:%d ", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 144 else 145 printf("Mixer %-8s is currently set to %3d:%d\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 146 } 147 return(0); 148 } 149 150 argc--; argv++; 151 152 while ((argc > 0) && (dusage == 0)) { 153 if (!strcmp("recsrc", *argv)) { 154 drecsrc = 1; 155 argc--; argv++; 156 continue; 157 } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 158 if (**argv != '+' && **argv != '-' && 159 **argv != '=' && **argv != '^') { 160 warnx("unknown modifier: %c", **argv); 161 dusage = 1; 162 break; 163 } 164 if ((dev = res_name(argv[1], recmask)) == -1) { 165 warnx("unknown recording device: %s", argv[1]); 166 dusage = 1; 167 break; 168 } 169 switch(**argv) { 170 case '+': 171 recsrc |= (1 << dev); 172 break; 173 case '-': 174 recsrc &= ~(1 << dev); 175 break; 176 case '=': 177 recsrc = (1 << dev); 178 break; 179 case '^': 180 recsrc ^= (1 << dev); 181 break; 182 } 183 drecsrc = 1; 184 argc -= 2; argv += 2; 185 continue; 186 } 187 188 if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) { 189 dev = 0; 190 } 191 else if((dev = res_name(*argv, devmask)) == -1) { 192 warnx("unknown device: %s", *argv); 193 dusage = 1; 194 break; 195 } 196 197#define issign(c) (((c) == '+') || ((c) == '-')) 198 199 if (argc > 1) { 200 n = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr); 201 if (n > 0) { 202 if (issign(lstr[0])) 203 lrel = rrel = 1; 204 l = atoi(lstr); 205 } 206 if (n > 1) { 207 rrel = 0; 208 if (issign(rstr[0])) 209 rrel = 1; 210 r = atoi(rstr); 211 } 212 } 213 214 switch(argc > 1 ? n : t) { 215 case 0: 216 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 217 warn("MIXER_READ"); 218 argc--; argv++; 219 continue; 220 } 221 if (shortflag) 222 printf("%s %d:%d ", names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 223 else 224 printf("Mixer %-8s is currently set to %3d:%d\n", 225 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 226 227 argc--; argv++; 228 break; 229 case 1: 230 r = l; 231 case 2: 232 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 233 warn("MIXER_READ"); 234 argc--; argv++; 235 continue; 236 } 237 238 if (lrel) 239 l = (bar & 0x7f) + l; 240 if (rrel) 241 r = ((bar >> 8) & 0x7f) + r; 242 243 if (l < 0) 244 l = 0; 245 else if (l > 100) 246 l = 100; 247 if (r < 0) 248 r = 0; 249 else if (r > 100) 250 r = 100; 251 252 printf("Setting the mixer %s from %d:%d to %d:%d.\n", 253 names[dev], bar & 0x7f, (bar >> 8) & 0x7f, l, r); 254 255 l |= r << 8; 256 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 257 warn("WRITE_MIXER"); 258 259 argc -= 2; argv += 2; 260 break; 261 } 262 } 263 264 if (dusage) { 265 close(baz); 266 usage(devmask, recmask); 267 /* Not reached */ 268 } 269 270 if (orecsrc != recsrc) 271 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 272 err(1, "SOUND_MIXER_WRITE_RECSRC"); 273 274 if (drecsrc) { 275 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 276 err(1, "SOUND_MIXER_READ_RECSRC"); 277 print_recsrc(recsrc); 278 } 279 280 close(baz); 281 282 exit(0); 283} 284