mixer.c revision 116388
199127Sobrien/* 299127Sobrien * This is an example of a mixer program for Linux 399127Sobrien * 499127Sobrien * updated 1/1/93 to add stereo, level query, broken 599127Sobrien * devmask kludge - cmetz@thor.tjhsst.edu 699127Sobrien * 799127Sobrien * (C) Craig Metz and Hannu Savolainen 1993. 899127Sobrien * 999127Sobrien * You may do anything you wish with this program. 1099127Sobrien * 1199127Sobrien * ditto for my modifications (John-Mark Gurney, 1997) 1299127Sobrien */ 1399127Sobrien 1499127Sobrien#include <sys/cdefs.h> 1599127Sobrien__FBSDID("$FreeBSD: head/usr.sbin/mixer/mixer.c 116388 2003-06-15 08:46:04Z grog $"); 1699127Sobrien 1799127Sobrien#include <err.h> 1899127Sobrien#include <fcntl.h> 1999127Sobrien#include <stdio.h> 2099127Sobrien#include <string.h> 2199127Sobrien#include <stdlib.h> 2299127Sobrien#include <unistd.h> 2399127Sobrien#include <sys/soundcard.h> 2499127Sobrien 2599127Sobrienconst char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES; 2699127Sobrien 2799127Sobrienvoid usage(int devmask, int recmask); 2899127Sobrienint res_name(const char *name, int mask); 2999127Sobrienvoid print_recsrc(int recsrc); 3099127Sobrien 3199127Sobrienvoid 3299127Sobrienusage(int devmask, int recmask) 3399127Sobrien{ 3499127Sobrien int i, n; 3599127Sobrien 3699127Sobrien printf("usage: mixer [-f device] [-s] [dev [+|-][voll[:[+|-]volr]] ...\n" 3799127Sobrien " mixer [-f device] [-s] recsrc ...\n" 3899127Sobrien " mixer [-f device] [-s] {^|+|-|=}rec rdev ... \n"); 3999127Sobrien printf(" devices: "); 4099127Sobrien for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 4199127Sobrien if ((1 << i) & devmask) { 4299127Sobrien if (n) 4399127Sobrien printf(", "); 4499127Sobrien printf("%s", names[i]); 4599127Sobrien n = 1; 4699127Sobrien } 4799127Sobrien printf("\n rec devices: "); 4899127Sobrien for (i = 0, n = 0; i < SOUND_MIXER_NRDEVICES; i++) 4999127Sobrien if ((1 << i) & recmask) { 5099127Sobrien 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, 142 (bar >> 8) & 0x7f); 143 else 144 printf("Mixer %-8s is currently set to %3d:%d\n", 145 names[foo], bar & 0x7f, (bar >> 8) & 0x7f); 146 } 147 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 148 err(1, "SOUND_MIXER_READ_RECSRC"); 149 print_recsrc(recsrc); 150 return(0); 151 } 152 153 argc--; argv++; 154 155 while ((argc > 0) && (dusage == 0)) { 156 if (!strcmp("recsrc", *argv)) { 157 drecsrc = 1; 158 argc--; argv++; 159 continue; 160 } else if (argc > 1 && !strcmp("rec", *argv + 1)) { 161 if (**argv != '+' && **argv != '-' && 162 **argv != '=' && **argv != '^') { 163 warnx("unknown modifier: %c", **argv); 164 dusage = 1; 165 break; 166 } 167 if ((dev = res_name(argv[1], recmask)) == -1) { 168 warnx("unknown recording device: %s", argv[1]); 169 dusage = 1; 170 break; 171 } 172 switch(**argv) { 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 case '^': 183 recsrc ^= (1 << dev); 184 break; 185 } 186 drecsrc = 1; 187 argc -= 2; argv += 2; 188 continue; 189 } 190 191 if ((t = sscanf(*argv, "%d:%d", &l, &r)) > 0) { 192 dev = 0; 193 } 194 else if((dev = res_name(*argv, devmask)) == -1) { 195 warnx("unknown device: %s", *argv); 196 dusage = 1; 197 break; 198 } 199 200#define issign(c) (((c) == '+') || ((c) == '-')) 201 202 if (argc > 1) { 203 n = sscanf(argv[1], "%7[^:]:%7s", lstr, rstr); 204 if (n > 0) { 205 if (issign(lstr[0])) 206 lrel = rrel = 1; 207 l = atoi(lstr); 208 } 209 if (n > 1) { 210 rrel = 0; 211 if (issign(rstr[0])) 212 rrel = 1; 213 r = atoi(rstr); 214 } 215 } 216 217 switch(argc > 1 ? n : t) { 218 case 0: 219 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 220 warn("MIXER_READ"); 221 argc--; argv++; 222 continue; 223 } 224 if (shortflag) 225 printf("%s %d:%d ", names[dev], bar & 0x7f, 226 (bar >> 8) & 0x7f); 227 else 228 printf("Mixer %-8s is currently set to %3d:%d\n", 229 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 230 231 argc--; argv++; 232 break; 233 case 1: 234 r = l; 235 case 2: 236 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 237 warn("MIXER_READ"); 238 argc--; argv++; 239 continue; 240 } 241 242 if (lrel) 243 l = (bar & 0x7f) + l; 244 if (rrel) 245 r = ((bar >> 8) & 0x7f) + r; 246 247 if (l < 0) 248 l = 0; 249 else if (l > 100) 250 l = 100; 251 if (r < 0) 252 r = 0; 253 else if (r > 100) 254 r = 100; 255 256 printf("Setting the mixer %s from %d:%d to %d:%d.\n", 257 names[dev], bar & 0x7f, (bar >> 8) & 0x7f, l, r); 258 259 l |= r << 8; 260 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 261 warn("WRITE_MIXER"); 262 263 argc -= 2; argv += 2; 264 break; 265 } 266 } 267 268 if (dusage) { 269 close(baz); 270 usage(devmask, recmask); 271 /* Not reached */ 272 } 273 274 if (orecsrc != recsrc) 275 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 276 err(1, "SOUND_MIXER_WRITE_RECSRC"); 277 278 if (drecsrc) { 279 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 280 err(1, "SOUND_MIXER_READ_RECSRC"); 281 print_recsrc(recsrc); 282 } 283 284 close(baz); 285 286 exit(0); 287} 288