xref: /plan9/sys/src/cmd/unix/drawterm/kern/devaudio-unix.c (revision ec59a3ddbfceee0efe34584c2c9981a5e5ff1ec4)
1499069deSDavid du Colombier /*
2499069deSDavid du Colombier  * Linux and BSD
3499069deSDavid du Colombier  */
4499069deSDavid du Colombier #include <sys/ioctl.h>
5499069deSDavid du Colombier #ifdef __linux__
6499069deSDavid du Colombier #include <linux/soundcard.h>
7499069deSDavid du Colombier #else
8499069deSDavid du Colombier #include <sys/soundcard.h>
9499069deSDavid du Colombier #endif
10499069deSDavid du Colombier #include	"u.h"
11499069deSDavid du Colombier #include	"lib.h"
12499069deSDavid du Colombier #include	"dat.h"
13499069deSDavid du Colombier #include	"fns.h"
14499069deSDavid du Colombier #include	"error.h"
15499069deSDavid du Colombier #include	"devaudio.h"
16499069deSDavid du Colombier 
17499069deSDavid du Colombier enum
18499069deSDavid du Colombier {
19499069deSDavid du Colombier 	Channels = 2,
20499069deSDavid du Colombier 	Rate = 44100,
21499069deSDavid du Colombier 	Bits = 16,
22499069deSDavid du Colombier 	Bigendian = 1,
23499069deSDavid du Colombier };
24499069deSDavid du Colombier 
25499069deSDavid du Colombier static int afd = -1;
26499069deSDavid du Colombier static int cfd= -1;
27499069deSDavid du Colombier static int speed;
28499069deSDavid du Colombier 
29499069deSDavid du Colombier /* maybe this should return -1 instead of sysfatal */
30499069deSDavid du Colombier void
audiodevopen(void)31499069deSDavid du Colombier audiodevopen(void)
32499069deSDavid du Colombier {
33499069deSDavid du Colombier 	int t;
34499069deSDavid du Colombier 	ulong ul;
35499069deSDavid du Colombier 
36499069deSDavid du Colombier 	afd = -1;
37499069deSDavid du Colombier 	cfd = -1;
38499069deSDavid du Colombier 	if((afd = open("/dev/dsp", OWRITE)) < 0)
39499069deSDavid du Colombier 		goto err;
40499069deSDavid du Colombier 	if((cfd = open("/dev/mixer", ORDWR)) < 0)
41499069deSDavid du Colombier 		goto err;
42499069deSDavid du Colombier 
43499069deSDavid du Colombier 	t = Bits;
44499069deSDavid du Colombier 	if(ioctl(afd, SNDCTL_DSP_SAMPLESIZE, &t) < 0)
45499069deSDavid du Colombier 		goto err;
46499069deSDavid du Colombier 
47499069deSDavid du Colombier 	t = Channels-1;
48499069deSDavid du Colombier 	if(ioctl(afd, SNDCTL_DSP_STEREO, &t) < 0)
49499069deSDavid du Colombier 		goto err;
50499069deSDavid du Colombier 
51499069deSDavid du Colombier 	speed = Rate;
52499069deSDavid du Colombier 	ul = Rate;
53499069deSDavid du Colombier 	if(ioctl(afd, SNDCTL_DSP_SPEED, &ul) < 0)
54499069deSDavid du Colombier 		goto err;
55499069deSDavid du Colombier 
56499069deSDavid du Colombier 	return;
57499069deSDavid du Colombier 
58499069deSDavid du Colombier err:
59499069deSDavid du Colombier 	if(afd >= 0)
60499069deSDavid du Colombier 		close(afd);
61499069deSDavid du Colombier 	afd = -1;
62499069deSDavid du Colombier 	oserror();
63499069deSDavid du Colombier }
64499069deSDavid du Colombier 
65499069deSDavid du Colombier void
audiodevclose(void)66499069deSDavid du Colombier audiodevclose(void)
67499069deSDavid du Colombier {
68499069deSDavid du Colombier 	close(afd);
69499069deSDavid du Colombier 	close(cfd);
70499069deSDavid du Colombier 	afd = -1;
71499069deSDavid du Colombier 	cfd = -1;
72499069deSDavid du Colombier }
73499069deSDavid du Colombier 
74499069deSDavid du Colombier static struct {
75499069deSDavid du Colombier 	int id9;
76499069deSDavid du Colombier 	int id;
77499069deSDavid du Colombier } names[] = {
78499069deSDavid du Colombier 	Vaudio,	SOUND_MIXER_VOLUME,
79499069deSDavid du Colombier 	Vbass, 		SOUND_MIXER_BASS,
80499069deSDavid du Colombier 	Vtreb, 		SOUND_MIXER_TREBLE,
81499069deSDavid du Colombier 	Vline, 		SOUND_MIXER_LINE,
82499069deSDavid du Colombier 	Vpcm, 		SOUND_MIXER_PCM,
83499069deSDavid du Colombier 	Vsynth, 		SOUND_MIXER_SYNTH,
84499069deSDavid du Colombier 	Vcd, 		SOUND_MIXER_CD,
85499069deSDavid du Colombier 	Vmic, 		SOUND_MIXER_MIC,
86499069deSDavid du Colombier //	"record", 		SOUND_MIXER_RECLEV,
87499069deSDavid du Colombier //	"mix",		SOUND_MIXER_IMIX,
88499069deSDavid du Colombier //	"pcm2",		SOUND_MIXER_ALTPCM,
89499069deSDavid du Colombier 	Vspeaker,	SOUND_MIXER_SPEAKER
90499069deSDavid du Colombier //	"line1",		SOUND_MIXER_LINE1,
91499069deSDavid du Colombier //	"line2",		SOUND_MIXER_LINE2,
92499069deSDavid du Colombier //	"line3",		SOUND_MIXER_LINE3,
93499069deSDavid du Colombier //	"digital1",	SOUND_MIXER_DIGITAL1,
94499069deSDavid du Colombier //	"digital2",	SOUND_MIXER_DIGITAL2,
95499069deSDavid du Colombier //	"digital3",	SOUND_MIXER_DIGITAL3,
96499069deSDavid du Colombier //	"phonein",		SOUND_MIXER_PHONEIN,
97499069deSDavid du Colombier //	"phoneout",		SOUND_MIXER_PHONEOUT,
98499069deSDavid du Colombier //	"radio",		SOUND_MIXER_RADIO,
99499069deSDavid du Colombier //	"video",		SOUND_MIXER_VIDEO,
100499069deSDavid du Colombier //	"monitor",	SOUND_MIXER_MONITOR,
101499069deSDavid du Colombier //	"igain",		SOUND_MIXER_IGAIN,
102499069deSDavid du Colombier //	"ogain",		SOUND_MIXER_OGAIN,
103499069deSDavid du Colombier };
104499069deSDavid du Colombier 
105499069deSDavid du Colombier static int
lookname(int id9)106499069deSDavid du Colombier lookname(int id9)
107499069deSDavid du Colombier {
108499069deSDavid du Colombier 	int i;
109499069deSDavid du Colombier 
110499069deSDavid du Colombier 	for(i=0; i<nelem(names); i++)
111499069deSDavid du Colombier 		if(names[i].id9 == id9)
112499069deSDavid du Colombier 			return names[i].id;
113499069deSDavid du Colombier 	return -1;
114499069deSDavid du Colombier }
115499069deSDavid du Colombier 
116499069deSDavid du Colombier void
audiodevsetvol(int what,int left,int right)117499069deSDavid du Colombier audiodevsetvol(int what, int left, int right)
118499069deSDavid du Colombier {
119499069deSDavid du Colombier 	int id;
120499069deSDavid du Colombier 	ulong x;
121499069deSDavid du Colombier 	int can, v;
122499069deSDavid du Colombier 
123499069deSDavid du Colombier 	if(cfd < 0)
124499069deSDavid du Colombier 		error("audio device not open");
125499069deSDavid du Colombier 	if(what == Vspeed){
126499069deSDavid du Colombier 		x = left;
127499069deSDavid du Colombier 		if(ioctl(afd, SNDCTL_DSP_SPEED, &x) < 0)
128499069deSDavid du Colombier 			oserror();
129499069deSDavid du Colombier 		speed = x;
130499069deSDavid du Colombier 		return;
131499069deSDavid du Colombier 	}
132499069deSDavid du Colombier 	if((id = lookname(what)) < 0)
133499069deSDavid du Colombier 		return;
134499069deSDavid du Colombier 	if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0)
135499069deSDavid du Colombier 		can = ~0;
136499069deSDavid du Colombier 	if(!(can & (1<<id)))
137499069deSDavid du Colombier 		return;
138499069deSDavid du Colombier 	v = left | (right<<8);
139499069deSDavid du Colombier 	if(ioctl(cfd, MIXER_WRITE(id), &v) < 0)
140499069deSDavid du Colombier 		oserror();
141499069deSDavid du Colombier }
142499069deSDavid du Colombier 
143499069deSDavid du Colombier void
audiodevgetvol(int what,int * left,int * right)144499069deSDavid du Colombier audiodevgetvol(int what, int *left, int *right)
145499069deSDavid du Colombier {
146499069deSDavid du Colombier 	int id;
147499069deSDavid du Colombier 	int can, v;
148499069deSDavid du Colombier 
149499069deSDavid du Colombier 	if(cfd < 0)
150499069deSDavid du Colombier 		error("audio device not open");
151499069deSDavid du Colombier 	if(what == Vspeed){
152499069deSDavid du Colombier 		*left = *right = speed;
153499069deSDavid du Colombier 		return;
154499069deSDavid du Colombier 	}
155499069deSDavid du Colombier 	if((id = lookname(what)) < 0)
156499069deSDavid du Colombier 		return;
157499069deSDavid du Colombier 	if(ioctl(cfd, SOUND_MIXER_READ_DEVMASK, &can) < 0)
158499069deSDavid du Colombier 		can = ~0;
159499069deSDavid du Colombier 	if(!(can & (1<<id)))
160499069deSDavid du Colombier 		return;
161499069deSDavid du Colombier 	if(ioctl(cfd, MIXER_READ(id), &v) < 0)
162499069deSDavid du Colombier 		oserror();
163499069deSDavid du Colombier 	*left = v&0xFF;
164499069deSDavid du Colombier 	*right = (v>>8)&0xFF;
165499069deSDavid du Colombier }
166499069deSDavid du Colombier 
167499069deSDavid du Colombier int
audiodevwrite(void * v,int n)168499069deSDavid du Colombier audiodevwrite(void *v, int n)
169499069deSDavid du Colombier {
170499069deSDavid du Colombier 	int m, tot;
171499069deSDavid du Colombier 
172499069deSDavid du Colombier 	for(tot=0; tot<n; tot+=m)
173499069deSDavid du Colombier 		if((m = write(afd, (uchar*)v+tot, n-tot)) <= 0)
174499069deSDavid du Colombier 			oserror();
175499069deSDavid du Colombier 	return tot;
176499069deSDavid du Colombier }
177499069deSDavid du Colombier 
178499069deSDavid du Colombier int
audiodevread(void * v,int n)179499069deSDavid du Colombier audiodevread(void *v, int n)
180499069deSDavid du Colombier {
181499069deSDavid du Colombier 	error("no reading");
182*ec59a3ddSDavid du Colombier 	return -1;
183499069deSDavid du Colombier }
184