xref: /freebsd/usr.sbin/mixer/mixer.c (revision 17ee9d00bc1ae1e598c38f25826f861e4bc6c3ce)
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 
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <string.h>
15 #ifdef __FreeBSD__
16 #include <machine/soundcard.h>
17 #else
18 #include <sys/soundcard.h>
19 #endif
20 
21 char *names[SOUND_MIXER_NRDEVICES] = SOUND_DEVICE_NAMES;
22 
23 int devmask = 0, recmask = 0, recsrc = 0;
24 
25 void usage(void)
26 {
27 	int i, n = 0;
28 	printf("Usage: mixer { ");
29 
30 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
31 		if ((1 << i) & devmask)  {
32 			if (n)
33 				putchar('|');
34 			printf(names[i]);
35 			n = 1;
36 		}
37 	printf(" } <value>\n  or   mixer { +rec|-rec } <devicename>\n");
38 	exit(1);
39 }
40 
41 void print_recsrc(void)
42 {
43 	int i, n = 0;
44 	fprintf(stderr, "Recording source: ");
45 
46 	for (i = 0; i < SOUND_MIXER_NRDEVICES; i++)
47 		if ((1 << i) & recsrc) {
48 			if (n)
49 				fprintf(stderr, ", ");
50 			fprintf(stderr, names[i]);
51 			n = 1;
52 		}
53 	fprintf(stderr, "\n");
54 }
55 
56 int
57 main(int argc, char *argv[])
58 {
59 	int foo, bar, baz, dev;
60 
61 	char name[30] = "/dev/mixer";
62 
63 	if (!strcmp(argv[0], "mixer2"))
64 	   strcpy(name, "/dev/mixer1");
65 	else
66 	  if (!strcmp(argv[0], "mixer3"))
67 	     strcpy(name, "/dev/mixer2");
68 
69 	if ((baz = open(name, O_RDWR)) < 0) {
70 		perror(name);
71 		exit(1);
72 	}
73 	if (ioctl(baz, SOUND_MIXER_READ_DEVMASK, &devmask) == -1) {
74 		perror("SOUND_MIXER_READ_DEVMASK");
75 		exit(-1);
76 	}
77 	if (ioctl(baz, SOUND_MIXER_READ_RECMASK, &recmask) == -1) {
78 		perror("SOUND_MIXER_READ_RECMASK");
79 		exit(-1);
80 	}
81 	if (ioctl(baz, SOUND_MIXER_READ_RECSRC, &recsrc) == -1) {
82 		perror("SOUND_MIXER_READ_RECSRC");
83 		exit(-1);
84 	}
85 
86 	switch (argc) {
87 		case 3:
88 			bar = 1;
89 			break;
90 		case 2:
91 			bar = 0;
92 			break;
93 		default:
94 			usage();
95 	}
96 
97 	for (foo = 0; foo < SOUND_MIXER_NRDEVICES && strcmp(names[foo], argv[1]); foo++);
98 
99 	if (foo >= SOUND_MIXER_NRDEVICES) {
100 
101 		if (!strcmp("+rec", argv[1]) || !strcmp("-rec", argv[1])) {
102 			for (dev = 0; dev < SOUND_MIXER_NRDEVICES && strcmp(names[dev], argv[2]); dev++);
103 			if (dev >= SOUND_MIXER_NRDEVICES)
104 				usage();
105 
106 			if (!((1 << dev) & recmask)) {
107 				fprintf(stderr, "Invalid recording source %s\n", argv[2]);
108 				exit(-1);
109 			}
110 			if (argv[1][0] == '+')
111 				recsrc |= (1 << dev);
112 			else
113 				recsrc &= ~(1 << dev);
114 
115 			if (ioctl(baz, SOUND_MIXER_WRITE_RECSRC, &recsrc) == -1) {
116 				perror("SOUND_MIXER_WRITE_RECSRC");
117 				exit(-1);
118 			}
119 			print_recsrc();
120 
121 		} else
122 			usage();
123 	} else {
124 		if (bar) {
125 			if (strchr(argv[2], ':') == NULL) {
126 				sscanf(argv[2], "%d", &bar);
127 				dev = bar;
128 			} else
129 				sscanf(argv[2], "%d:%d", &bar, &dev);
130 
131 			if (bar < 0)
132 				bar = 0;
133 			if (dev < 0)
134 				dev = 0;
135 			if (bar > 100)
136 				bar = 100;
137 			if (dev > 100)
138 				dev = 100;
139 
140 			printf("Setting the mixer %s to %d:%d.\n", names[foo], bar, dev);
141 
142                         bar |= dev << 8;
143 			if (ioctl(baz, MIXER_WRITE(foo), &bar) == -1)
144 				perror("WRITE_MIXER");
145 	return (0);
146 		} else {
147 			if (ioctl(baz, MIXER_READ(foo),&bar)== -1)
148 			   perror("MIXER_READ");
149 			printf("The mixer %s is currently set to %d:%d.\n", names[foo], bar & 0x7f, (bar >> 8) & 0x7f);
150 		}
151 	}
152 
153 	close(baz);
154 }
155