mixer.c revision 64657
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 64657 2000-08-15 05:42:39Z sobomax $"; 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 27char *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(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(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, 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, r; 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) && (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 ((dev = res_name(*argv, devmask)) == -1) { 185 warnx("unknown device: %s", *argv); 186 dusage = 1; 187 break; 188 } 189 190 switch(argc > 1 ? sscanf(argv[1], "%d:%d", &l, &r) : 0) { 191 case 0: 192 if (ioctl(baz, MIXER_READ(dev),&bar)== -1) { 193 warn("MIXER_READ"); 194 argc--; argv++; 195 continue; 196 } 197 if (shortflag) 198 printf("%s %d:%d ", names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 199 else 200 printf("Mixer %-8s is currently set to %3d:%d\n", 201 names[dev], bar & 0x7f, (bar >> 8) & 0x7f); 202 203 argc--; argv++; 204 break; 205 case 1: 206 r = l; 207 case 2: 208 if (l < 0) 209 l = 0; 210 else if (l > 100) 211 l = 100; 212 if (r < 0) 213 r = 0; 214 else if (r > 100) 215 r = 100; 216 217 printf("Setting the mixer %s to %d:%d.\n", names[dev], 218 l, r); 219 220 l |= r << 8; 221 if (ioctl(baz, MIXER_WRITE(dev), &l) == -1) 222 warn("WRITE_MIXER"); 223 224 argc -= 2; argv += 2; 225 break; 226 } 227 } 228 229 if (dusage) { 230 close(baz); 231 usage(devmask, recmask); 232 /* Not reached */ 233 } 234 235 if (orecsrc != recsrc) 236 if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) 237 err(1, "SOUND_MIXER_WRITE_RECSRC"); 238 239 if (drecsrc) { 240 if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) 241 err(1, "SOUND_MIXER_READ_RECSRC"); 242 print_recsrc(recsrc); 243 } 244 245 close(baz); 246 247 exit(0); 248} 249