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