xref: /plan9/sys/src/cmd/unix/drawterm/kern/devaudio-unix.c (revision 499069debb03e99ea217d35fd87fb49e96918a92)
1*499069deSDavid du Colombier /*
2*499069deSDavid du Colombier  * Linux and BSD
3*499069deSDavid du Colombier  */
4*499069deSDavid du Colombier #include <sys/ioctl.h>
5*499069deSDavid du Colombier #ifdef __linux__
6*499069deSDavid du Colombier #include <linux/soundcard.h>
7*499069deSDavid du Colombier #else
8*499069deSDavid du Colombier #include <sys/soundcard.h>
9*499069deSDavid du Colombier #endif
10*499069deSDavid du Colombier #include	"u.h"
11*499069deSDavid du Colombier #include	"lib.h"
12*499069deSDavid du Colombier #include	"dat.h"
13*499069deSDavid du Colombier #include	"fns.h"
14*499069deSDavid du Colombier #include	"error.h"
15*499069deSDavid du Colombier #include	"devaudio.h"
16*499069deSDavid du Colombier 
17*499069deSDavid du Colombier enum
18*499069deSDavid du Colombier {
19*499069deSDavid du Colombier 	Channels = 2,
20*499069deSDavid du Colombier 	Rate = 44100,
21*499069deSDavid du Colombier 	Bits = 16,
22*499069deSDavid du Colombier 	Bigendian = 1,
23*499069deSDavid du Colombier };
24*499069deSDavid du Colombier 
25*499069deSDavid du Colombier static int afd = -1;
26*499069deSDavid du Colombier static int cfd= -1;
27*499069deSDavid du Colombier static int speed;
28*499069deSDavid du Colombier 
29*499069deSDavid du Colombier /* maybe this should return -1 instead of sysfatal */
30*499069deSDavid du Colombier void
31*499069deSDavid du Colombier audiodevopen(void)
32*499069deSDavid du Colombier {
33*499069deSDavid du Colombier 	int t;
34*499069deSDavid du Colombier 	ulong ul;
35*499069deSDavid du Colombier 
36*499069deSDavid du Colombier 	afd = -1;
37*499069deSDavid du Colombier 	cfd = -1;
38*499069deSDavid du Colombier 	if((afd = open("/dev/dsp", OWRITE)) < 0)
39*499069deSDavid du Colombier 		goto err;
40*499069deSDavid du Colombier 	if((cfd = open("/dev/mixer", ORDWR)) < 0)
41*499069deSDavid du Colombier 		goto err;
42*499069deSDavid du Colombier 
43*499069deSDavid du Colombier 	t = Bits;
44*499069deSDavid du Colombier 	if(ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &t) < 0)
45*499069deSDavid du Colombier 		goto err;
46*499069deSDavid du Colombier 
47*499069deSDavid du Colombier 	t = Channels-1;
48*499069deSDavid du Colombier 	if(ioctl(afd, SNDCTL_DSP_STEREO, &t) < 0)
49*499069deSDavid du Colombier 		goto err;
50*499069deSDavid du Colombier 
51*499069deSDavid du Colombier 	speed = Rate;
52*499069deSDavid du Colombier 	ul = Rate;
53*499069deSDavid du Colombier 	if(ioctl(afd, SNDCTL_DSP_SPEED, &ul) < 0)
54*499069deSDavid du Colombier 		goto err;
55*499069deSDavid du Colombier 
56*499069deSDavid du Colombier 	return;
57*499069deSDavid du Colombier 
58*499069deSDavid du Colombier err:
59*499069deSDavid du Colombier 	if(afd >= 0)
60*499069deSDavid du Colombier 		close(afd);
61*499069deSDavid du Colombier 	afd = -1;
62*499069deSDavid du Colombier 	oserror();
63*499069deSDavid du Colombier }
64*499069deSDavid du Colombier 
65*499069deSDavid du Colombier void
66*499069deSDavid du Colombier audiodevclose(void)
67*499069deSDavid du Colombier {
68*499069deSDavid du Colombier 	close(afd);
69*499069deSDavid du Colombier 	close(cfd);
70*499069deSDavid du Colombier 	afd = -1;
71*499069deSDavid du Colombier 	cfd = -1;
72*499069deSDavid du Colombier }
73*499069deSDavid du Colombier 
74*499069deSDavid du Colombier static struct {
75*499069deSDavid du Colombier 	int id9;
76*499069deSDavid du Colombier 	int id;
77*499069deSDavid du Colombier } names[] = {
78*499069deSDavid du Colombier 	Vaudio,	SOUND_MIXER_VOLUME,
79*499069deSDavid du Colombier 	Vbass, 		SOUND_MIXER_BASS,
80*499069deSDavid du Colombier 	Vtreb, 		SOUND_MIXER_TREBLE,
81*499069deSDavid du Colombier 	Vline, 		SOUND_MIXER_LINE,
82*499069deSDavid du Colombier 	Vpcm, 		SOUND_MIXER_PCM,
83*499069deSDavid du Colombier 	Vsynth, 		SOUND_MIXER_SYNTH,
84*499069deSDavid du Colombier 	Vcd, 		SOUND_MIXER_CD,
85*499069deSDavid du Colombier 	Vmic, 		SOUND_MIXER_MIC,
86*499069deSDavid du Colombier //	"record", 		SOUND_MIXER_RECLEV,
87*499069deSDavid du Colombier //	"mix",		SOUND_MIXER_IMIX,
88*499069deSDavid du Colombier //	"pcm2",		SOUND_MIXER_ALTPCM,
89*499069deSDavid du Colombier 	Vspeaker,	SOUND_MIXER_SPEAKER
90*499069deSDavid du Colombier //	"line1",		SOUND_MIXER_LINE1,
91*499069deSDavid du Colombier //	"line2",		SOUND_MIXER_LINE2,
92*499069deSDavid du Colombier //	"line3",		SOUND_MIXER_LINE3,
93*499069deSDavid du Colombier //	"digital1",	SOUND_MIXER_DIGITAL1,
94*499069deSDavid du Colombier //	"digital2",	SOUND_MIXER_DIGITAL2,
95*499069deSDavid du Colombier //	"digital3",	SOUND_MIXER_DIGITAL3,
96*499069deSDavid du Colombier //	"phonein",		SOUND_MIXER_PHONEIN,
97*499069deSDavid du Colombier //	"phoneout",		SOUND_MIXER_PHONEOUT,
98*499069deSDavid du Colombier //	"radio",		SOUND_MIXER_RADIO,
99*499069deSDavid du Colombier //	"video",		SOUND_MIXER_VIDEO,
100*499069deSDavid du Colombier //	"monitor",	SOUND_MIXER_MONITOR,
101*499069deSDavid du Colombier //	"igain",		SOUND_MIXER_IGAIN,
102*499069deSDavid du Colombier //	"ogain",		SOUND_MIXER_OGAIN,
103*499069deSDavid du Colombier };
104*499069deSDavid du Colombier 
105*499069deSDavid du Colombier static int
106*499069deSDavid du Colombier lookname(int id9)
107*499069deSDavid du Colombier {
108*499069deSDavid du Colombier 	int i;
109*499069deSDavid du Colombier 
110*499069deSDavid du Colombier 	for(i=0; i<nelem(names); i++)
111*499069deSDavid du Colombier 		if(names[i].id9 == id9)
112*499069deSDavid du Colombier 			return names[i].id;
113*499069deSDavid du Colombier 	return -1;
114*499069deSDavid du Colombier }
115*499069deSDavid du Colombier 
116*499069deSDavid du Colombier void
117*499069deSDavid du Colombier audiodevsetvol(int what, int left, int right)
118*499069deSDavid du Colombier {
119*499069deSDavid du Colombier 	int id;
120*499069deSDavid du Colombier 	ulong x;
121*499069deSDavid du Colombier 	int can, v;
122*499069deSDavid du Colombier 
123*499069deSDavid du Colombier 	if(cfd < 0)
124*499069deSDavid du Colombier 		error("audio device not open");
125*499069deSDavid du Colombier 	if(what == Vspeed){
126*499069deSDavid du Colombier 		x = left;
127*499069deSDavid du Colombier 		if(ioctl(afd, SNDCTL_DSP_SPEED, &x) < 0)
128*499069deSDavid du Colombier 			oserror();
129*499069deSDavid du Colombier 		speed = x;
130*499069deSDavid du Colombier 		return;
131*499069deSDavid du Colombier 	}
132*499069deSDavid du Colombier 	if((id = lookname(what)) < 0)
133*499069deSDavid du Colombier 		return;
134*499069deSDavid du Colombier 	if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0)
135*499069deSDavid du Colombier 		can = ~0;
136*499069deSDavid du Colombier 	if(!(can & (1<<id)))
137*499069deSDavid du Colombier 		return;
138*499069deSDavid du Colombier 	v = left | (right<<8);
139*499069deSDavid du Colombier 	if(ioctl(cfd, MIXER_WRITE(id), &v) < 0)
140*499069deSDavid du Colombier 		oserror();
141*499069deSDavid du Colombier }
142*499069deSDavid du Colombier 
143*499069deSDavid du Colombier void
144*499069deSDavid du Colombier audiodevgetvol(int what, int *left, int *right)
145*499069deSDavid du Colombier {
146*499069deSDavid du Colombier 	int id;
147*499069deSDavid du Colombier 	int can, v;
148*499069deSDavid du Colombier 
149*499069deSDavid du Colombier 	if(cfd < 0)
150*499069deSDavid du Colombier 		error("audio device not open");
151*499069deSDavid du Colombier 	if(what == Vspeed){
152*499069deSDavid du Colombier 		*left = *right = speed;
153*499069deSDavid du Colombier 		return;
154*499069deSDavid du Colombier 	}
155*499069deSDavid du Colombier 	if((id = lookname(what)) < 0)
156*499069deSDavid du Colombier 		return;
157*499069deSDavid du Colombier 	if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0)
158*499069deSDavid du Colombier 		can = ~0;
159*499069deSDavid du Colombier 	if(!(can & (1<<id)))
160*499069deSDavid du Colombier 		return;
161*499069deSDavid du Colombier 	if(ioctl(cfd, MIXER_READ(id), &v) < 0)
162*499069deSDavid du Colombier 		oserror();
163*499069deSDavid du Colombier 	*left = v&0xFF;
164*499069deSDavid du Colombier 	*right = (v>>8)&0xFF;
165*499069deSDavid du Colombier }
166*499069deSDavid du Colombier 
167*499069deSDavid du Colombier int
168*499069deSDavid du Colombier audiodevwrite(void *v, int n)
169*499069deSDavid du Colombier {
170*499069deSDavid du Colombier 	int m, tot;
171*499069deSDavid du Colombier 
172*499069deSDavid du Colombier 	for(tot=0; tot<n; tot+=m)
173*499069deSDavid du Colombier 		if((m = write(afd, (uchar*)v+tot, n-tot)) <= 0)
174*499069deSDavid du Colombier 			oserror();
175*499069deSDavid du Colombier 	return tot;
176*499069deSDavid du Colombier }
177*499069deSDavid du Colombier 
178*499069deSDavid du Colombier int
179*499069deSDavid du Colombier audiodevread(void *v, int n)
180*499069deSDavid du Colombier {
181*499069deSDavid du Colombier 	error("no reading");
182*499069deSDavid du Colombier }
183