File:  [DragonFly] / src / usr.sbin / mixer / mixer.c
Revision 1.3: download - view: text, annotated - select for diffs
Tue Jan 6 08:35:42 2004 UTC (10 years, 11 months ago) by asmodai
Branches: MAIN
CVS tags: HEAD
Synch up with FreeBSD 5 with clean up changes.
-h option added (for help)
Relative volume values are now also supported.

Submitted by:	Craig Dooley <craig@xlnx-x.net>

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