1
2 /*
3 * Diverse SLab audio routines.
4 * Copyright (c) by Nick Copeland <nickycopeland@hotmail.com> 1996,2012
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22
23 #if (BRISTOL_HAS_OSS == 1)
24 /*
25 * This may want to be /usr/lib/oss/include/sys/soundcard.h if someone has
26 * purchased the 4Front drivers?
27 */
28 #include <sys/soundcard.h>
29 #endif
30
31 #include <sys/ioctl.h>
32 #include <unistd.h>
33 #include <fcntl.h>
34 #include <stdlib.h>
35 #include <stdio.h>
36 #include <strings.h>
37
38 /*
39 * Audio device structure format definitions.
40 */
41 #include "slabrevisions.h"
42 #include "slabaudiodev.h"
43 #include "bristol.h"
44
45 int newInitAudioDevice2(duplexDev *, int, int);
46 static void checkAudioCaps2(duplexDev *, int, int);
47
48 int
ossAudioInit(audioDev,devID,fragSize)49 ossAudioInit(audioDev, devID, fragSize)
50 duplexDev *audioDev;
51 int devID;
52 {
53 #if (BRISTOL_HAS_OSS == 1)
54 int results, data = 0, mode;
55
56 //audioDev->cflags |= SLAB_AUDIODBG;
57
58 printf("ossAudioInit(%p, %i, %i)\n", audioDev, devID, fragSize);
59
60 /*
61 * This is what we are going to go for.
62 */
63 fragSize = 1024;
64
65 /*
66 * Clear out this buffer.
67 */
68 if (audioDev->fragBuf != (char *) NULL)
69 {
70 bristolfree(audioDev->fragBuf);
71 audioDev->fragBuf = (char *) NULL;
72 }
73
74 checkAudioCaps2(audioDev, devID, audioDev->fd);
75
76 if (fragSize != 0)
77 {
78 int data;
79
80 switch(fragSize) {
81 case 1024:
82 data = 0x0040000a;
83 break;
84 case 2048:
85 data = 0x0020000b;
86 break;
87 case 4096:
88 data = 0x0010000c;
89 break;
90 case 8192:
91 data = 0x0008000d;
92 break;
93 case 16384:
94 data = 0x0004000e;
95 break;
96 /*
97 * This is 8192 blockSampleSize, where internally we deal with
98 * ints or floats, but the IO buffer is in shorts.
99 */
100 case 32768:
101 default:
102 data = 0x0004000f;
103 break;
104 }
105 if ((results = ioctl(audioDev->fd, SNDCTL_DSP_SETFRAGMENT, &data)) == 0)
106 {
107 if (audioDev->cflags & SLAB_AUDIODBG)
108 printf("ioctl(%i, SNDCTL_DSP_SETFRAGMENT, %x)\n",
109 audioDev->fd, data);
110 } else
111 printf("ioctl(%i, SNDCTL_DSP_SETFRAGMENT, %x): failed\n",
112 audioDev->fd, data);
113 }
114
115 /*
116 * Check capabilities.
117 */
118 if (audioDev->cflags & SLAB_AUDIODBG)
119 printf("ioctl(%i, SNDCTL_DSP_GETCAPS, &0x%x)\n", audioDev->fd, data);
120
121 if ((results = ioctl(audioDev->fd, SNDCTL_DSP_GETCAPS, &data)) == 0)
122 {
123 audioDev->genCaps = data;
124
125 if (audioDev->cflags & SLAB_AUDIODBG)
126 {
127 if ((audioDev->genCaps & SNDCTL_DSP_SETTRIGGER) != 0)
128 printf("Device %s does support SNDCTL_SET_TRIGGER\n",
129 audioDev->devName);
130 else
131 printf("Device %s does NOT support SNDCTL_SET_TRIGGER\n",
132 audioDev->devName);
133 }
134
135 /*
136 * Take this out, we only need to check the options here.
137 */
138 if (data & DSP_CAP_DUPLEX)
139 {
140
141 if (audioDev->cflags & SLAB_AUDIODBG)
142 printf("ioctl(%i, SNDCTL_DSP_SETDUPLEX, &0x%x)\n",
143 audioDev->fd, data);
144
145 if (ioctl(audioDev->fd, SNDCTL_DSP_SETDUPLEX, &data) < 0)
146 printf("Failed to set Duplex\n");
147 else
148 printf("Set to Duplex\n");
149 }
150 }
151
152 if ((audioDev->cflags & SLAB_FDUP) == 0)
153 audioDev->fd2 = audioDev->fd;
154 else
155 audioDev->fd2 = fcntl(audioDev->fd, F_DUPFD, audioDev->fd);
156
157 /*
158 * Set to required resolution.
159 */
160 if (audioDev->cflags & (SLAB_8_BIT_OUT|SLAB_8_BIT_IN))
161 {
162 data = 8; /* THIS SHOULD USE THE soundcard.h DEFINITION */
163 } else
164 data = 16;
165
166 if (audioDev->cflags & SLAB_AUDIODBG)
167 printf("ioctl(%i, SNDCTL_DSP_SETFMT, &%i)\n", audioDev->fd, data);
168
169 if ((results = ioctl(audioDev->fd, SNDCTL_DSP_SETFMT, &data)) == 0)
170 {
171 if (audioDev->cflags & SLAB_AUDIODBG)
172 printf("Set audio format: %i\n", data);
173 } else
174 printf("Set resolution failed: %i\n", results);
175
176 /*
177 * Set to stereo
178 */
179 data = 1;
180 if (audioDev->cflags & SLAB_AUDIODBG)
181 printf("ioctl(%i, SNDCTL_DSP_STEREO, &%i)\n", audioDev->fd, data);
182 mode = SNDCTL_DSP_STEREO;
183 if ((results = ioctl(audioDev->fd, mode, &data)) == 0)
184 {
185 if (audioDev->cflags & SLAB_AUDIODBG)
186 printf("Set to stereo: %i\n", data);
187 } else
188 printf("Set stereo failed: %i\n", results);
189
190 /*
191 * Set to AUDIO_RATE Hz
192 */
193 data = audioDev->writeSampleRate;
194
195 if (audioDev->cflags & SLAB_AUDIODBG)
196 printf("ioctl(%i, SNDCTL_DSP_SPEED, &%i)\n", audioDev->fd, data);
197
198 if ((results = ioctl(audioDev->fd, SNDCTL_DSP_SPEED, &data)) == 0)
199 {
200 if (audioDev->cflags & SLAB_AUDIODBG)
201 printf("Set audio readwrite rate to %i\n", data);
202 } else
203 printf("Set line frequency failed: %i\n", results);
204
205 /*
206 * Save the actual physical line rate for conversions later
207 */
208 audioDev->writeSampleRate = data;
209
210 /*
211 * Save the actual physical line rate for conversions later
212 */
213 audioDev->readSampleRate = data;
214
215 /*
216 * Finally get the output fragment size. We can have an awkward problem if
217 * this fragment size is not the same as the primary device - with sync IO
218 * where we readBuffer/writeBuffer, having different sizes very soon puts
219 * the audio daemon in to a lock state. To overcome this, and to support
220 * eventual realtime mixing (where we will specify a small buffersize
221 * anyway) we should add a "desired buffer size" param, or have the adiod
222 * routines cater for differences.
223 */
224 data = 0;
225 if ((results = ioctl(audioDev->fd, SNDCTL_DSP_GETBLKSIZE, &data)) == 0)
226 {
227 audioDev->fragSize = data;
228
229 if (audioDev->cflags & SLAB_AUDIODBG)
230 printf("ioctl(%i, SNDCTL_DSP_GETBLKSIZE, &0): %i bytes\n",
231 audioDev->fd, audioDev->fragSize);
232 audioDev->fragBuf = (char *) bristolmalloc(audioDev->fragSize);
233 }
234 else
235 printf("Get frag size failed: %i\n", results);
236
237 #ifdef _BRISTOL_DRAIN
238 for (data = 0; data < audioDev->preLoad; data++)
239 results = write(audioDev->fd, audioDev->fragBuf,
240 audioDev->samplecount * 2 * audioDev->channels);
241 #endif
242
243 #endif /* BRISTOL_HAS_OSS */
244
245 return(0);
246 }
247
248 /*
249 * Needs to be ALSAfied - ie, binned if we have alsa - this is GUI stuff.
250 */
251 static void
checkAudioCaps2(audioDev,devID,fd)252 checkAudioCaps2(audioDev, devID, fd)
253 duplexDev *audioDev;
254 int devID, fd;
255 {
256 int i, stereodevs = 0;
257
258 #if (BRISTOL_HAS_OSS == 1)
259 printf("checkAudioCaps2(%i, %i)\n", devID, fd);
260
261 if (ioctl(fd, SOUND_MIXER_READ_STEREODEVS, &stereodevs) == -1)
262 {
263 if (audioDev->cflags & SLAB_AUDIODBG)
264 printf("Failed to get stereo capabilities: %08x\n", stereodevs);
265 } else {
266 if (audioDev->cflags & SLAB_AUDIODBG)
267 printf("Capabilities: %08x\n", stereodevs);
268 audioDev->stereoCaps = stereodevs;
269 }
270
271
272 for (i = 1; i < 131072; i = i << 1) {
273 if (i & stereodevs)
274 printf("Found stereo dev %08x\n", i);
275 }
276
277 stereodevs = 0;
278 if (ioctl(fd, SOUND_MIXER_READ_DEVMASK, &stereodevs) == -1)
279 {
280 if (audioDev->cflags & SLAB_AUDIODBG)
281 printf("Failed to get audio capabilities: %08x\n", stereodevs);
282 } else {
283 if (audioDev->cflags & SLAB_AUDIODBG)
284 printf("Mono Capabilities: %08x\n", stereodevs);
285 audioDev->monoCaps = stereodevs;
286 }
287
288
289 stereodevs = 0;
290 if (ioctl(fd, SOUND_MIXER_READ_RECMASK, &stereodevs) == -1)
291 {
292 if (audioDev->cflags & SLAB_AUDIODBG)
293 printf("Failed to get record capabilities: %08x\n", stereodevs);
294 } else {
295 if (audioDev->cflags & SLAB_AUDIODBG)
296 printf("Record Caps: %08x\n", stereodevs);
297 audioDev->recordCaps = stereodevs;
298 }
299
300 #endif /* BRISTOL_HAS_OSS */
301 }
302
303