Mercurial > sdl-ios-xcode
comparison src/audio/bsd/SDL_bsdaudio.c @ 3820:1f156fd874fa SDL-ryan-multiple-audio-device
Moved more audio drivers to 1.3 API (all 5 MiNT backends, BSD, IRIX...), and
some other tweaks in already-converted drivers.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 07 Oct 2006 05:36:36 +0000 |
parents | 9d070c1a45fa |
children | 66fb40445587 |
comparison
equal
deleted
inserted
replaced
3819:b225d9820ee3 | 3820:1f156fd874fa |
---|---|
59 | 59 |
60 /* #define DEBUG_AUDIO */ | 60 /* #define DEBUG_AUDIO */ |
61 /* #define DEBUG_AUDIO_STREAM */ | 61 /* #define DEBUG_AUDIO_STREAM */ |
62 | 62 |
63 #ifdef USE_BLOCKING_WRITES | 63 #ifdef USE_BLOCKING_WRITES |
64 #define OPEN_FLAGS O_WRONLY | 64 #define OPEN_FLAGS_OUTPUT O_WRONLY |
65 #define OPEN_FLAGS_INPUT O_RDONLY | |
65 #else | 66 #else |
66 #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) | 67 #define OPEN_FLAGS_OUTPUT (O_WRONLY|O_NONBLOCK) |
67 #endif | 68 #define OPEN_FLAGS_INPUT (O_RDONLY|O_NONBLOCK) |
68 | 69 #endif |
69 /* Audio driver functions */ | 70 |
70 static void OBSD_WaitAudio(_THIS); | 71 /* !!! FIXME: so much cut and paste with dsp/dma drivers... */ |
71 static int OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec); | 72 static char **outputDevices = NULL; |
72 static void OBSD_PlayAudio(_THIS); | 73 static int outputDeviceCount = 0; |
73 static Uint8 *OBSD_GetAudioBuf(_THIS); | 74 static char **inputDevices = NULL; |
74 static void OBSD_CloseAudio(_THIS); | 75 static int inputDeviceCount = 0; |
75 | 76 |
77 static inline void | |
78 free_device_list(char ***devs, int *count) | |
79 { | |
80 SDL_FreeUnixAudioDevices(devs, count); | |
81 } | |
82 | |
83 static inline void | |
84 build_device_list(int iscapture, char ***devs, int *count) | |
85 { | |
86 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); | |
87 free_device_list(devs, count); | |
88 SDL_EnumUnixAudioDevices(flags, 0, NULL, devs, count); | |
89 } | |
90 | |
91 static inline void | |
92 build_device_lists(void) | |
93 { | |
94 build_device_list(0, &outputDevices, &outputDeviceCount); | |
95 build_device_list(1, &inputDevices, &inputDeviceCount); | |
96 } | |
97 | |
98 | |
99 static inline void | |
100 free_device_lists(void) | |
101 { | |
102 free_device_list(&outputDevices, &outputDeviceCount); | |
103 free_device_list(&inputDevices, &inputDeviceCount); | |
104 } | |
105 | |
106 | |
107 static int | |
108 BSDAUDIO_Available(void) | |
109 { | |
110 int available = 0; | |
111 build_device_lists(); | |
112 available = ((outputDeviceCount > 0) || (inputDeviceCount > 0)); | |
113 free_device_lists(); | |
114 return available; | |
115 } | |
116 | |
117 | |
118 static void | |
119 BSDAUDIO_Deinitialize(void) | |
120 { | |
121 free_device_lists(); | |
122 } | |
123 | |
124 | |
125 static int | |
126 BSDAUDIO_DetectDevices(int iscapture) | |
127 { | |
128 if (iscapture) { | |
129 build_device_list(1, &inputDevices, &inputDeviceCount); | |
130 return inputDeviceCount; | |
131 } else { | |
132 build_device_list(0, &outputDevices, &outputDeviceCount); | |
133 return outputDeviceCount; | |
134 } | |
135 | |
136 return 0; /* shouldn't ever hit this. */ | |
137 } | |
138 | |
139 static const char * | |
140 BSDAUDIO_GetDeviceName(int index, int iscapture) | |
141 { | |
142 if ((iscapture) && (index < inputDeviceCount)) { | |
143 return inputDevices[index]; | |
144 } else if ((!iscapture) && (index < outputDeviceCount)) { | |
145 return outputDevices[index]; | |
146 } | |
147 | |
148 SDL_SetError("No such device"); | |
149 return NULL; | |
150 } | |
151 | |
152 | |
153 static void | |
154 BSDAUDIO_Status(_THIS) | |
155 { | |
76 #ifdef DEBUG_AUDIO | 156 #ifdef DEBUG_AUDIO |
77 static void OBSD_Status(_THIS); | |
78 #endif | |
79 | |
80 /* Audio driver bootstrap functions */ | |
81 | |
82 static int | |
83 Audio_Available(void) | |
84 { | |
85 int fd; | |
86 int available; | |
87 | |
88 available = 0; | |
89 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); | |
90 if (fd >= 0) { | |
91 available = 1; | |
92 close(fd); | |
93 } | |
94 return (available); | |
95 } | |
96 | |
97 static void | |
98 Audio_DeleteDevice(SDL_AudioDevice * device) | |
99 { | |
100 SDL_free(device->hidden); | |
101 SDL_free(device); | |
102 } | |
103 | |
104 static SDL_AudioDevice * | |
105 Audio_CreateDevice(int devindex) | |
106 { | |
107 SDL_AudioDevice *this; | |
108 | |
109 /* Initialize all variables that we clean on shutdown */ | |
110 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); | |
111 if (this) { | |
112 SDL_memset(this, 0, (sizeof *this)); | |
113 this->hidden = (struct SDL_PrivateAudioData *) | |
114 SDL_malloc((sizeof *this->hidden)); | |
115 } | |
116 if ((this == NULL) || (this->hidden == NULL)) { | |
117 SDL_OutOfMemory(); | |
118 if (this) | |
119 SDL_free(this); | |
120 return (0); | |
121 } | |
122 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
123 audio_fd = -1; | |
124 | |
125 /* Set the function pointers */ | |
126 this->OpenAudio = OBSD_OpenAudio; | |
127 this->WaitAudio = OBSD_WaitAudio; | |
128 this->PlayAudio = OBSD_PlayAudio; | |
129 this->GetAudioBuf = OBSD_GetAudioBuf; | |
130 this->CloseAudio = OBSD_CloseAudio; | |
131 | |
132 this->free = Audio_DeleteDevice; | |
133 | |
134 return this; | |
135 } | |
136 | |
137 AudioBootStrap BSD_AUDIO_bootstrap = { | |
138 BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, | |
139 Audio_Available, Audio_CreateDevice, 0 | |
140 }; | |
141 | |
142 /* This function waits until it is possible to write a full sound buffer */ | |
143 static void | |
144 OBSD_WaitAudio(_THIS) | |
145 { | |
146 #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ | |
147 /* See if we need to use timed audio synchronization */ | |
148 if (frame_ticks) { | |
149 /* Use timer for general audio synchronization */ | |
150 Sint32 ticks; | |
151 | |
152 ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; | |
153 if (ticks > 0) { | |
154 SDL_Delay(ticks); | |
155 } | |
156 } else { | |
157 /* Use select() for audio synchronization */ | |
158 fd_set fdset; | |
159 struct timeval timeout; | |
160 | |
161 FD_ZERO(&fdset); | |
162 FD_SET(audio_fd, &fdset); | |
163 timeout.tv_sec = 10; | |
164 timeout.tv_usec = 0; | |
165 #ifdef DEBUG_AUDIO | |
166 fprintf(stderr, "Waiting for audio to get ready\n"); | |
167 #endif | |
168 if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) { | |
169 const char *message = | |
170 "Audio timeout - buggy audio driver? (disabled)"; | |
171 /* In general we should never print to the screen, | |
172 but in this case we have no other way of letting | |
173 the user know what happened. | |
174 */ | |
175 fprintf(stderr, "SDL: %s\n", message); | |
176 this->enabled = 0; | |
177 /* Don't try to close - may hang */ | |
178 audio_fd = -1; | |
179 #ifdef DEBUG_AUDIO | |
180 fprintf(stderr, "Done disabling audio\n"); | |
181 #endif | |
182 } | |
183 #ifdef DEBUG_AUDIO | |
184 fprintf(stderr, "Ready!\n"); | |
185 #endif | |
186 } | |
187 #endif /* !USE_BLOCKING_WRITES */ | |
188 } | |
189 | |
190 static void | |
191 OBSD_PlayAudio(_THIS) | |
192 { | |
193 int written, p = 0; | |
194 | |
195 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | |
196 do { | |
197 written = write(audio_fd, &mixbuf[p], mixlen - p); | |
198 if (written > 0) | |
199 p += written; | |
200 if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) { | |
201 /* Non recoverable error has occurred. It should be reported!!! */ | |
202 perror("audio"); | |
203 break; | |
204 } | |
205 | |
206 if (p < written | |
207 || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) { | |
208 SDL_Delay(1); /* Let a little CPU time go by */ | |
209 } | |
210 } | |
211 while (p < written); | |
212 | |
213 /* If timer synchronization is enabled, set the next write frame */ | |
214 if (frame_ticks) { | |
215 next_frame += frame_ticks; | |
216 } | |
217 | |
218 /* If we couldn't write, assume fatal error for now */ | |
219 if (written < 0) { | |
220 this->enabled = 0; | |
221 } | |
222 #ifdef DEBUG_AUDIO | |
223 fprintf(stderr, "Wrote %d bytes of audio data\n", written); | |
224 #endif | |
225 } | |
226 | |
227 static Uint8 * | |
228 OBSD_GetAudioBuf(_THIS) | |
229 { | |
230 return (mixbuf); | |
231 } | |
232 | |
233 static void | |
234 OBSD_CloseAudio(_THIS) | |
235 { | |
236 if (mixbuf != NULL) { | |
237 SDL_FreeAudioMem(mixbuf); | |
238 mixbuf = NULL; | |
239 } | |
240 if (audio_fd >= 0) { | |
241 close(audio_fd); | |
242 audio_fd = -1; | |
243 } | |
244 } | |
245 | |
246 #ifdef DEBUG_AUDIO | |
247 void | |
248 OBSD_Status(_THIS) | |
249 { | |
250 audio_info_t info; | 157 audio_info_t info; |
251 | 158 |
252 if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) { | 159 if (ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info) < 0) { |
253 fprintf(stderr, "AUDIO_GETINFO failed.\n"); | 160 fprintf(stderr, "AUDIO_GETINFO failed.\n"); |
254 return; | 161 return; |
255 } | 162 } |
256 | 163 |
257 fprintf(stderr, "\n" | 164 fprintf(stderr, "\n" |
294 info.blocksize, | 201 info.blocksize, |
295 info.hiwat, info.lowat, | 202 info.hiwat, info.lowat, |
296 (info.mode == AUMODE_PLAY) ? "PLAY" | 203 (info.mode == AUMODE_PLAY) ? "PLAY" |
297 : (info.mode = AUMODE_RECORD) ? "RECORD" | 204 : (info.mode = AUMODE_RECORD) ? "RECORD" |
298 : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?")); | 205 : (info.mode == AUMODE_PLAY_ALL ? "PLAY_ALL" : "?")); |
299 } | |
300 #endif /* DEBUG_AUDIO */ | 206 #endif /* DEBUG_AUDIO */ |
207 } | |
208 | |
209 | |
210 /* This function waits until it is possible to write a full sound buffer */ | |
211 static void | |
212 BSDAUDIO_WaitDevice(_THIS) | |
213 { | |
214 #ifndef USE_BLOCKING_WRITES /* Not necessary when using blocking writes */ | |
215 /* See if we need to use timed audio synchronization */ | |
216 if (this->hidden->frame_ticks) { | |
217 /* Use timer for general audio synchronization */ | |
218 Sint32 ticks; | |
219 | |
220 ticks = ((Sint32)(this->hidden->next_frame-SDL_GetTicks()))-FUDGE_TICKS; | |
221 if (ticks > 0) { | |
222 SDL_Delay(ticks); | |
223 } | |
224 } else { | |
225 /* Use select() for audio synchronization */ | |
226 fd_set fdset; | |
227 struct timeval timeout; | |
228 | |
229 FD_ZERO(&fdset); | |
230 FD_SET(this->hidden->audio_fd, &fdset); | |
231 timeout.tv_sec = 10; | |
232 timeout.tv_usec = 0; | |
233 #ifdef DEBUG_AUDIO | |
234 fprintf(stderr, "Waiting for audio to get ready\n"); | |
235 #endif | |
236 if (select(this->hidden->audio_fd+1,NULL,&fdset,NULL,&timeout) <= 0) { | |
237 const char *message = | |
238 "Audio timeout - buggy audio driver? (disabled)"; | |
239 /* In general we should never print to the screen, | |
240 but in this case we have no other way of letting | |
241 the user know what happened. | |
242 */ | |
243 fprintf(stderr, "SDL: %s\n", message); | |
244 this->enabled = 0; | |
245 /* Don't try to close - may hang */ | |
246 this->hidden->audio_fd = -1; | |
247 #ifdef DEBUG_AUDIO | |
248 fprintf(stderr, "Done disabling audio\n"); | |
249 #endif | |
250 } | |
251 #ifdef DEBUG_AUDIO | |
252 fprintf(stderr, "Ready!\n"); | |
253 #endif | |
254 } | |
255 #endif /* !USE_BLOCKING_WRITES */ | |
256 } | |
257 | |
258 static void | |
259 BSDAUDIO_PlayDevice(_THIS) | |
260 { | |
261 int written, p = 0; | |
262 | |
263 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | |
264 do { | |
265 written = write(this->hidden->audio_fd, | |
266 &this->hidden->mixbuf[p], | |
267 this->hidden->mixlen - p); | |
268 | |
269 if (written > 0) | |
270 p += written; | |
271 if (written == -1 && errno != 0 && errno != EAGAIN && errno != EINTR) { | |
272 /* Non recoverable error has occurred. It should be reported!!! */ | |
273 perror("audio"); | |
274 break; | |
275 } | |
276 | |
277 if (p < written | |
278 || ((written < 0) && ((errno == 0) || (errno == EAGAIN)))) { | |
279 SDL_Delay(1); /* Let a little CPU time go by */ | |
280 } | |
281 } | |
282 while (p < written); | |
283 | |
284 /* If timer synchronization is enabled, set the next write frame */ | |
285 if (this->hidden->frame_ticks) { | |
286 this->hidden->next_frame += this->hidden->frame_ticks; | |
287 } | |
288 | |
289 /* If we couldn't write, assume fatal error for now */ | |
290 if (written < 0) { | |
291 this->enabled = 0; | |
292 } | |
293 #ifdef DEBUG_AUDIO | |
294 fprintf(stderr, "Wrote %d bytes of audio data\n", written); | |
295 #endif | |
296 } | |
297 | |
298 static Uint8 * | |
299 BSDAUDIO_GetDeviceBuf(_THIS) | |
300 { | |
301 return (this->hidden->mixbuf); | |
302 } | |
303 | |
304 static void | |
305 BSDAUDIO_CloseDevice(_THIS) | |
306 { | |
307 if (this->hidden != NULL) { | |
308 if (this->hidden->mixbuf != NULL) { | |
309 SDL_FreeAudioMem(this->hidden->mixbuf); | |
310 this->hidden->mixbuf = NULL; | |
311 } | |
312 if (this->hidden->audio_fd >= 0) { | |
313 close(this->hidden->audio_fd); | |
314 this->hidden->audio_fd = -1; | |
315 } | |
316 SDL_free(this->hidden); | |
317 this->hidden = NULL; | |
318 } | |
319 } | |
301 | 320 |
302 static int | 321 static int |
303 OBSD_OpenAudio(_THIS, SDL_AudioSpec * spec) | 322 BSDAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) |
304 { | 323 { |
305 char audiodev[64]; | 324 const int flags = ((iscapture) ? OPEN_FLAGS_INPUT : OPEN_FLAGS_OUTPUT); |
306 SDL_AudioFormat format; | 325 SDL_AudioFormat format = 0; |
307 audio_info_t info; | 326 audio_info_t info; |
308 | 327 |
328 /* We don't care what the devname is...we'll try to open anything. */ | |
329 /* ...but default to first name in the list... */ | |
330 if (devname == NULL) { | |
331 if ( ((iscapture) && (inputDeviceCount == 0)) || | |
332 ((!iscapture) && (outputDeviceCount == 0)) ) { | |
333 SDL_SetError("No such audio device"); | |
334 return 0; | |
335 } | |
336 devname = ((iscapture) ? inputDevices[0] : outputDevices[0]); | |
337 } | |
338 | |
339 /* Initialize all variables that we clean on shutdown */ | |
340 this->hidden = (struct SDL_PrivateAudioData *) | |
341 SDL_malloc((sizeof *this->hidden)); | |
342 if (this->hidden == NULL) { | |
343 SDL_OutOfMemory(); | |
344 return 0; | |
345 } | |
346 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
347 | |
348 /* Open the audio device */ | |
349 this->hidden->audio_fd = open(devname, flags, 0); | |
350 if (this->hidden->audio_fd < 0) { | |
351 SDL_SetError("Couldn't open %s: %s", devname, strerror(errno)); | |
352 return 0; | |
353 } | |
354 | |
309 AUDIO_INITINFO(&info); | 355 AUDIO_INITINFO(&info); |
310 | 356 |
311 /* Calculate the final parameters for this audio specification */ | 357 /* Calculate the final parameters for this audio specification */ |
312 SDL_CalculateAudioSpec(spec); | 358 SDL_CalculateAudioSpec(&this->spec); |
313 | |
314 #ifdef USE_TIMER_SYNC | |
315 frame_ticks = 0.0; | |
316 #endif | |
317 | |
318 /* Open the audio device */ | |
319 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); | |
320 if (audio_fd < 0) { | |
321 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | |
322 return (-1); | |
323 } | |
324 | 359 |
325 /* Set to play mode */ | 360 /* Set to play mode */ |
326 info.mode = AUMODE_PLAY; | 361 info.mode = AUMODE_PLAY; |
327 if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) { | 362 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) < 0) { |
363 BSDAUDIO_CloseDevice(this); | |
328 SDL_SetError("Couldn't put device into play mode"); | 364 SDL_SetError("Couldn't put device into play mode"); |
329 return (-1); | 365 return 0; |
330 } | 366 } |
331 | 367 |
332 mixbuf = NULL; | |
333 AUDIO_INITINFO(&info); | 368 AUDIO_INITINFO(&info); |
334 for (format = SDL_FirstAudioFormat(spec->format); | 369 for (format = SDL_FirstAudioFormat(this->spec.format); |
335 format; format = SDL_NextAudioFormat()) { | 370 format; format = SDL_NextAudioFormat()) { |
336 switch (format) { | 371 switch (format) { |
337 case AUDIO_U8: | 372 case AUDIO_U8: |
338 info.play.encoding = AUDIO_ENCODING_ULINEAR; | 373 info.play.encoding = AUDIO_ENCODING_ULINEAR; |
339 info.play.precision = 8; | 374 info.play.precision = 8; |
359 info.play.precision = 16; | 394 info.play.precision = 16; |
360 break; | 395 break; |
361 default: | 396 default: |
362 continue; | 397 continue; |
363 } | 398 } |
364 if (ioctl(audio_fd, AUDIO_SETINFO, &info) == 0) | 399 |
365 break; | 400 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == 0) { |
401 break; | |
402 } | |
366 } | 403 } |
367 | 404 |
368 if (!format) { | 405 if (!format) { |
369 SDL_SetError("No supported encoding for 0x%x", spec->format); | 406 BSDAUDIO_CloseDevice(this); |
370 return (-1); | 407 SDL_SetError("No supported encoding for 0x%x", this->spec.format); |
371 } | 408 return 0; |
372 | 409 } |
373 spec->format = format; | 410 |
411 this->spec.format = format; | |
374 | 412 |
375 AUDIO_INITINFO(&info); | 413 AUDIO_INITINFO(&info); |
376 info.play.channels = spec->channels; | 414 info.play.channels = this->spec.channels; |
377 if (ioctl(audio_fd, AUDIO_SETINFO, &info) == -1) | 415 if (ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info) == -1) { |
378 spec->channels = 1; | 416 this->spec.channels = 1; |
417 } | |
379 AUDIO_INITINFO(&info); | 418 AUDIO_INITINFO(&info); |
380 info.play.sample_rate = spec->freq; | 419 info.play.sample_rate = this->spec.freq; |
381 info.blocksize = spec->size; | 420 info.blocksize = this->spec.size; |
382 info.hiwat = 5; | 421 info.hiwat = 5; |
383 info.lowat = 3; | 422 info.lowat = 3; |
384 (void) ioctl(audio_fd, AUDIO_SETINFO, &info); | 423 (void) ioctl(this->hidden->audio_fd, AUDIO_SETINFO, &info); |
385 (void) ioctl(audio_fd, AUDIO_GETINFO, &info); | 424 (void) ioctl(this->hidden->audio_fd, AUDIO_GETINFO, &info); |
386 spec->freq = info.play.sample_rate; | 425 this->spec.freq = info.play.sample_rate; |
387 /* Allocate mixing buffer */ | 426 /* Allocate mixing buffer */ |
388 mixlen = spec->size; | 427 this->hidden->mixlen = this->spec.size; |
389 mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); | 428 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); |
390 if (mixbuf == NULL) { | 429 if (this->hidden->mixbuf == NULL) { |
391 return (-1); | 430 BSDAUDIO_CloseDevice(this); |
392 } | 431 SDL_OutOfMemory(); |
393 SDL_memset(mixbuf, spec->silence, spec->size); | 432 return 0; |
394 | 433 } |
395 /* Get the parent process id (we're the parent of the audio thread) */ | 434 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); |
396 parent = getpid(); | 435 |
397 | 436 BSDAUDIO_Status(this); |
398 #ifdef DEBUG_AUDIO | |
399 OBSD_Status(this); | |
400 #endif | |
401 | 437 |
402 /* We're ready to rock and roll. :-) */ | 438 /* We're ready to rock and roll. :-) */ |
403 return (0); | 439 return (0); |
404 } | 440 } |
405 | 441 |
442 static int | |
443 BSDAUDIO_Init(SDL_AudioDriverImpl *impl) | |
444 { | |
445 /* Set the function pointers */ | |
446 impl->DetectDevices = DSP_DetectDevices; | |
447 impl->GetDeviceName = DSP_GetDeviceName; | |
448 impl->OpenDevice = DSP_OpenDevice; | |
449 impl->PlayDevice = DSP_PlayDevice; | |
450 impl->WaitDevice = DSP_WaitDevice; | |
451 impl->GetDeviceBuf = DSP_GetDeviceBuf; | |
452 impl->CloseDevice = DSP_CloseDevice; | |
453 impl->Deinitialize = DSP_Deinitialize; | |
454 | |
455 build_device_lists(); | |
456 return 1; | |
457 } | |
458 | |
459 | |
460 AudioBootStrap BSD_AUDIO_bootstrap = { | |
461 BSD_AUDIO_DRIVER_NAME, BSD_AUDIO_DRIVER_DESC, | |
462 BSDAUDIO_Available, BSDAUDIO_Init, 0 | |
463 }; | |
464 | |
406 /* vi: set ts=4 sw=4 expandtab: */ | 465 /* vi: set ts=4 sw=4 expandtab: */ |