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