1 /*
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
4
5 This software is provided 'as-is', without any express or implied
6 warranty. In no event will the authors be held liable for any damages
7 arising from the use of this software.
8
9 Permission is granted to anyone to use this software for any purpose,
10 including commercial applications, and to alter it and redistribute it
11 freely, subject to the following restrictions:
12
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software
15 in a product, an acknowledgment in the product documentation would be
16 appreciated but is not required.
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
20 */
21 #include "../SDL_internal.h"
22
23 /* Allow access to a raw mixing buffer */
24
25 #include "SDL.h"
26 #include "SDL_audio.h"
27 #include "SDL_audio_c.h"
28 #include "SDL_sysaudio.h"
29 #include "../thread/SDL_systhread.h"
30
31 #define _THIS SDL_AudioDevice *_this
32
33 static SDL_AudioDriver current_audio;
34 static SDL_AudioDevice *open_devices[16];
35
36 /*
37 * Not all of these will be compiled and linked in, but it's convenient
38 * to have a complete list here and saves yet-another block of #ifdefs...
39 * Please see bootstrap[], below, for the actual #ifdef mess.
40 */
41 extern AudioBootStrap PULSEAUDIO_bootstrap;
42 extern AudioBootStrap ALSA_bootstrap;
43 extern AudioBootStrap SNDIO_bootstrap;
44 extern AudioBootStrap BSD_AUDIO_bootstrap;
45 extern AudioBootStrap DSP_bootstrap;
46 extern AudioBootStrap QSAAUDIO_bootstrap;
47 extern AudioBootStrap SUNAUDIO_bootstrap;
48 extern AudioBootStrap ARTS_bootstrap;
49 extern AudioBootStrap ESD_bootstrap;
50 extern AudioBootStrap NACLAUDIO_bootstrap;
51 extern AudioBootStrap NAS_bootstrap;
52 extern AudioBootStrap XAUDIO2_bootstrap;
53 extern AudioBootStrap DSOUND_bootstrap;
54 extern AudioBootStrap WINMM_bootstrap;
55 extern AudioBootStrap PAUDIO_bootstrap;
56 extern AudioBootStrap HAIKUAUDIO_bootstrap;
57 extern AudioBootStrap COREAUDIO_bootstrap;
58 extern AudioBootStrap DISKAUDIO_bootstrap;
59 extern AudioBootStrap DUMMYAUDIO_bootstrap;
60 extern AudioBootStrap FUSIONSOUND_bootstrap;
61 extern AudioBootStrap ANDROIDAUDIO_bootstrap;
62 extern AudioBootStrap PSPAUDIO_bootstrap;
63 extern AudioBootStrap SNDIO_bootstrap;
64 extern AudioBootStrap EMSCRIPTENAUDIO_bootstrap;
65
66 /* Available audio drivers */
67 static const AudioBootStrap *const bootstrap[] = {
68 #if SDL_AUDIO_DRIVER_PULSEAUDIO
69 &PULSEAUDIO_bootstrap,
70 #endif
71 #if SDL_AUDIO_DRIVER_ALSA
72 &ALSA_bootstrap,
73 #endif
74 #if SDL_AUDIO_DRIVER_SNDIO
75 &SNDIO_bootstrap,
76 #endif
77 #if SDL_AUDIO_DRIVER_BSD
78 &BSD_AUDIO_bootstrap,
79 #endif
80 #if SDL_AUDIO_DRIVER_OSS
81 &DSP_bootstrap,
82 #endif
83 #if SDL_AUDIO_DRIVER_QSA
84 &QSAAUDIO_bootstrap,
85 #endif
86 #if SDL_AUDIO_DRIVER_SUNAUDIO
87 &SUNAUDIO_bootstrap,
88 #endif
89 #if SDL_AUDIO_DRIVER_ARTS
90 &ARTS_bootstrap,
91 #endif
92 #if SDL_AUDIO_DRIVER_ESD
93 &ESD_bootstrap,
94 #endif
95 #if SDL_AUDIO_DRIVER_NACL
96 &NACLAUDIO_bootstrap,
97 #endif
98 #if SDL_AUDIO_DRIVER_NAS
99 &NAS_bootstrap,
100 #endif
101 #if SDL_AUDIO_DRIVER_XAUDIO2
102 &XAUDIO2_bootstrap,
103 #endif
104 #if SDL_AUDIO_DRIVER_DSOUND
105 &DSOUND_bootstrap,
106 #endif
107 #if SDL_AUDIO_DRIVER_WINMM
108 &WINMM_bootstrap,
109 #endif
110 #if SDL_AUDIO_DRIVER_PAUDIO
111 &PAUDIO_bootstrap,
112 #endif
113 #if SDL_AUDIO_DRIVER_HAIKU
114 &HAIKUAUDIO_bootstrap,
115 #endif
116 #if SDL_AUDIO_DRIVER_COREAUDIO
117 &COREAUDIO_bootstrap,
118 #endif
119 #if SDL_AUDIO_DRIVER_DISK
120 &DISKAUDIO_bootstrap,
121 #endif
122 #if SDL_AUDIO_DRIVER_DUMMY
123 &DUMMYAUDIO_bootstrap,
124 #endif
125 #if SDL_AUDIO_DRIVER_FUSIONSOUND
126 &FUSIONSOUND_bootstrap,
127 #endif
128 #if SDL_AUDIO_DRIVER_ANDROID
129 &ANDROIDAUDIO_bootstrap,
130 #endif
131 #if SDL_AUDIO_DRIVER_PSP
132 &PSPAUDIO_bootstrap,
133 #endif
134 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
135 &EMSCRIPTENAUDIO_bootstrap,
136 #endif
137 NULL
138 };
139
140 static SDL_AudioDevice *
get_audio_device(SDL_AudioDeviceID id)141 get_audio_device(SDL_AudioDeviceID id)
142 {
143 id--;
144 if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
145 SDL_SetError("Invalid audio device ID");
146 return NULL;
147 }
148
149 return open_devices[id];
150 }
151
152
153 /* stubs for audio drivers that don't need a specific entry point... */
154 static void
SDL_AudioDetectDevices_Default(void)155 SDL_AudioDetectDevices_Default(void)
156 {
157 /* you have to write your own implementation if these assertions fail. */
158 SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
159 SDL_assert(current_audio.impl.OnlyHasDefaultCaptureDevice || !current_audio.impl.HasCaptureSupport);
160
161 SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
162 if (current_audio.impl.HasCaptureSupport) {
163 SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
164 }
165 }
166
167 static void
SDL_AudioThreadInit_Default(_THIS)168 SDL_AudioThreadInit_Default(_THIS)
169 { /* no-op. */
170 }
171
172 static void
SDL_AudioWaitDevice_Default(_THIS)173 SDL_AudioWaitDevice_Default(_THIS)
174 { /* no-op. */
175 }
176
177 static void
SDL_AudioPlayDevice_Default(_THIS)178 SDL_AudioPlayDevice_Default(_THIS)
179 { /* no-op. */
180 }
181
182 static int
SDL_AudioGetPendingBytes_Default(_THIS)183 SDL_AudioGetPendingBytes_Default(_THIS)
184 {
185 return 0;
186 }
187
188 static Uint8 *
SDL_AudioGetDeviceBuf_Default(_THIS)189 SDL_AudioGetDeviceBuf_Default(_THIS)
190 {
191 return NULL;
192 }
193
194 static int
SDL_AudioCaptureFromDevice_Default(_THIS,void * buffer,int buflen)195 SDL_AudioCaptureFromDevice_Default(_THIS, void *buffer, int buflen)
196 {
197 return -1; /* just fail immediately. */
198 }
199
200 static void
SDL_AudioFlushCapture_Default(_THIS)201 SDL_AudioFlushCapture_Default(_THIS)
202 { /* no-op. */
203 }
204
205 static void
SDL_AudioPrepareToClose_Default(_THIS)206 SDL_AudioPrepareToClose_Default(_THIS)
207 { /* no-op. */
208 }
209
210 static void
SDL_AudioCloseDevice_Default(_THIS)211 SDL_AudioCloseDevice_Default(_THIS)
212 { /* no-op. */
213 }
214
215 static void
SDL_AudioDeinitialize_Default(void)216 SDL_AudioDeinitialize_Default(void)
217 { /* no-op. */
218 }
219
220 static void
SDL_AudioFreeDeviceHandle_Default(void * handle)221 SDL_AudioFreeDeviceHandle_Default(void *handle)
222 { /* no-op. */
223 }
224
225
226 static int
SDL_AudioOpenDevice_Default(_THIS,void * handle,const char * devname,int iscapture)227 SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
228 {
229 return SDL_Unsupported();
230 }
231
232 static SDL_INLINE SDL_bool
is_in_audio_device_thread(SDL_AudioDevice * device)233 is_in_audio_device_thread(SDL_AudioDevice * device)
234 {
235 /* The device thread locks the same mutex, but not through the public API.
236 This check is in case the application, in the audio callback,
237 tries to lock the thread that we've already locked from the
238 device thread...just in case we only have non-recursive mutexes. */
239 if (device->thread && (SDL_ThreadID() == device->threadid)) {
240 return SDL_TRUE;
241 }
242
243 return SDL_FALSE;
244 }
245
246 static void
SDL_AudioLockDevice_Default(SDL_AudioDevice * device)247 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
248 {
249 if (!is_in_audio_device_thread(device)) {
250 SDL_LockMutex(device->mixer_lock);
251 }
252 }
253
254 static void
SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)255 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
256 {
257 if (!is_in_audio_device_thread(device)) {
258 SDL_UnlockMutex(device->mixer_lock);
259 }
260 }
261
262 static void
SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)263 SDL_AudioLockOrUnlockDeviceWithNoMixerLock(SDL_AudioDevice * device)
264 {
265 }
266
267 static void
finish_audio_entry_points_init(void)268 finish_audio_entry_points_init(void)
269 {
270 /*
271 * Fill in stub functions for unused driver entry points. This lets us
272 * blindly call them without having to check for validity first.
273 */
274
275 if (current_audio.impl.SkipMixerLock) {
276 if (current_audio.impl.LockDevice == NULL) {
277 current_audio.impl.LockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
278 }
279 if (current_audio.impl.UnlockDevice == NULL) {
280 current_audio.impl.UnlockDevice = SDL_AudioLockOrUnlockDeviceWithNoMixerLock;
281 }
282 }
283
284 #define FILL_STUB(x) \
285 if (current_audio.impl.x == NULL) { \
286 current_audio.impl.x = SDL_Audio##x##_Default; \
287 }
288 FILL_STUB(DetectDevices);
289 FILL_STUB(OpenDevice);
290 FILL_STUB(ThreadInit);
291 FILL_STUB(WaitDevice);
292 FILL_STUB(PlayDevice);
293 FILL_STUB(GetPendingBytes);
294 FILL_STUB(GetDeviceBuf);
295 FILL_STUB(CaptureFromDevice);
296 FILL_STUB(FlushCapture);
297 FILL_STUB(PrepareToClose);
298 FILL_STUB(CloseDevice);
299 FILL_STUB(LockDevice);
300 FILL_STUB(UnlockDevice);
301 FILL_STUB(FreeDeviceHandle);
302 FILL_STUB(Deinitialize);
303 #undef FILL_STUB
304 }
305
306
307 /* device hotplug support... */
308
309 static int
add_audio_device(const char * name,void * handle,SDL_AudioDeviceItem ** devices,int * devCount)310 add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
311 {
312 int retval = -1;
313 const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
314 SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
315 if (item == NULL) {
316 return -1;
317 }
318
319 SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
320
321 item->handle = handle;
322 SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
323
324 SDL_LockMutex(current_audio.detectionLock);
325 item->next = *devices;
326 *devices = item;
327 retval = (*devCount)++;
328 SDL_UnlockMutex(current_audio.detectionLock);
329
330 return retval;
331 }
332
333 static SDL_INLINE int
add_capture_device(const char * name,void * handle)334 add_capture_device(const char *name, void *handle)
335 {
336 SDL_assert(current_audio.impl.HasCaptureSupport);
337 return add_audio_device(name, handle, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
338 }
339
340 static SDL_INLINE int
add_output_device(const char * name,void * handle)341 add_output_device(const char *name, void *handle)
342 {
343 return add_audio_device(name, handle, ¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
344 }
345
346 static void
free_device_list(SDL_AudioDeviceItem ** devices,int * devCount)347 free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
348 {
349 SDL_AudioDeviceItem *item, *next;
350 for (item = *devices; item != NULL; item = next) {
351 next = item->next;
352 if (item->handle != NULL) {
353 current_audio.impl.FreeDeviceHandle(item->handle);
354 }
355 SDL_free(item);
356 }
357 *devices = NULL;
358 *devCount = 0;
359 }
360
361
362 /* The audio backends call this when a new device is plugged in. */
363 void
SDL_AddAudioDevice(const int iscapture,const char * name,void * handle)364 SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
365 {
366 const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
367 if (device_index != -1) {
368 /* Post the event, if desired */
369 if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
370 SDL_Event event;
371 SDL_zero(event);
372 event.adevice.type = SDL_AUDIODEVICEADDED;
373 event.adevice.which = device_index;
374 event.adevice.iscapture = iscapture;
375 SDL_PushEvent(&event);
376 }
377 }
378 }
379
380 /* The audio backends call this when a currently-opened device is lost. */
SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice * device)381 void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
382 {
383 SDL_assert(get_audio_device(device->id) == device);
384
385 if (!SDL_AtomicGet(&device->enabled)) {
386 return;
387 }
388
389 /* Ends the audio callback and mark the device as STOPPED, but the
390 app still needs to close the device to free resources. */
391 current_audio.impl.LockDevice(device);
392 SDL_AtomicSet(&device->enabled, 0);
393 current_audio.impl.UnlockDevice(device);
394
395 /* Post the event, if desired */
396 if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
397 SDL_Event event;
398 SDL_zero(event);
399 event.adevice.type = SDL_AUDIODEVICEREMOVED;
400 event.adevice.which = device->id;
401 event.adevice.iscapture = device->iscapture ? 1 : 0;
402 SDL_PushEvent(&event);
403 }
404 }
405
406 static void
mark_device_removed(void * handle,SDL_AudioDeviceItem * devices,SDL_bool * removedFlag)407 mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
408 {
409 SDL_AudioDeviceItem *item;
410 SDL_assert(handle != NULL);
411 for (item = devices; item != NULL; item = item->next) {
412 if (item->handle == handle) {
413 item->handle = NULL;
414 *removedFlag = SDL_TRUE;
415 return;
416 }
417 }
418 }
419
420 /* The audio backends call this when a device is removed from the system. */
421 void
SDL_RemoveAudioDevice(const int iscapture,void * handle)422 SDL_RemoveAudioDevice(const int iscapture, void *handle)
423 {
424 int device_index;
425 SDL_AudioDevice *device = NULL;
426
427 SDL_LockMutex(current_audio.detectionLock);
428 if (iscapture) {
429 mark_device_removed(handle, current_audio.inputDevices, ¤t_audio.captureDevicesRemoved);
430 } else {
431 mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved);
432 }
433 for (device_index = 0; device_index < SDL_arraysize(open_devices); device_index++)
434 {
435 device = open_devices[device_index];
436 if (device != NULL && device->handle == handle)
437 {
438 SDL_OpenedAudioDeviceDisconnected(device);
439 break;
440 }
441 }
442 SDL_UnlockMutex(current_audio.detectionLock);
443
444 current_audio.impl.FreeDeviceHandle(handle);
445 }
446
447
448
449 /* buffer queueing support... */
450
451 /* this expects that you managed thread safety elsewhere. */
452 static void
free_audio_queue(SDL_AudioBufferQueue * packet)453 free_audio_queue(SDL_AudioBufferQueue *packet)
454 {
455 while (packet) {
456 SDL_AudioBufferQueue *next = packet->next;
457 SDL_free(packet);
458 packet = next;
459 }
460 }
461
462 /* NOTE: This assumes you'll hold the mixer lock before calling! */
463 static int
queue_audio_to_device(SDL_AudioDevice * device,const Uint8 * data,Uint32 len)464 queue_audio_to_device(SDL_AudioDevice *device, const Uint8 *data, Uint32 len)
465 {
466 SDL_AudioBufferQueue *orighead;
467 SDL_AudioBufferQueue *origtail;
468 Uint32 origlen;
469 Uint32 datalen;
470
471 orighead = device->buffer_queue_head;
472 origtail = device->buffer_queue_tail;
473 origlen = origtail ? origtail->datalen : 0;
474
475 while (len > 0) {
476 SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
477 SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
478 if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
479 /* tail packet missing or completely full; we need a new packet. */
480 packet = device->buffer_queue_pool;
481 if (packet != NULL) {
482 /* we have one available in the pool. */
483 device->buffer_queue_pool = packet->next;
484 } else {
485 /* Have to allocate a new one! */
486 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
487 if (packet == NULL) {
488 /* uhoh, reset so we've queued nothing new, free what we can. */
489 if (!origtail) {
490 packet = device->buffer_queue_head; /* whole queue. */
491 } else {
492 packet = origtail->next; /* what we added to existing queue. */
493 origtail->next = NULL;
494 origtail->datalen = origlen;
495 }
496 device->buffer_queue_head = orighead;
497 device->buffer_queue_tail = origtail;
498 device->buffer_queue_pool = NULL;
499
500 free_audio_queue(packet); /* give back what we can. */
501
502 return SDL_OutOfMemory();
503 }
504 }
505 packet->datalen = 0;
506 packet->startpos = 0;
507 packet->next = NULL;
508
509 SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
510 if (device->buffer_queue_tail == NULL) {
511 device->buffer_queue_head = packet;
512 } else {
513 device->buffer_queue_tail->next = packet;
514 }
515 device->buffer_queue_tail = packet;
516 }
517
518 datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
519 SDL_memcpy(packet->data + packet->datalen, data, datalen);
520 data += datalen;
521 len -= datalen;
522 packet->datalen += datalen;
523 device->queued_bytes += datalen;
524 }
525
526 return 0;
527 }
528
529 /* NOTE: This assumes you'll hold the mixer lock before calling! */
530 static Uint32
dequeue_audio_from_device(SDL_AudioDevice * device,Uint8 * stream,Uint32 len)531 dequeue_audio_from_device(SDL_AudioDevice *device, Uint8 *stream, Uint32 len)
532 {
533 SDL_AudioBufferQueue *packet;
534 Uint8 *ptr = stream;
535
536 while ((len > 0) && ((packet = device->buffer_queue_head) != NULL)) {
537 const Uint32 avail = packet->datalen - packet->startpos;
538 const Uint32 cpy = SDL_min(len, avail);
539 SDL_assert(device->queued_bytes >= avail);
540
541 SDL_memcpy(ptr, packet->data + packet->startpos, cpy);
542 packet->startpos += cpy;
543 ptr += cpy;
544 device->queued_bytes -= cpy;
545 len -= cpy;
546
547 if (packet->startpos == packet->datalen) { /* packet is done, put it in the pool. */
548 device->buffer_queue_head = packet->next;
549 SDL_assert((packet->next != NULL) || (packet == device->buffer_queue_tail));
550 packet->next = device->buffer_queue_pool;
551 device->buffer_queue_pool = packet;
552 }
553 }
554
555 SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
556
557 if (device->buffer_queue_head == NULL) {
558 device->buffer_queue_tail = NULL; /* in case we drained the queue entirely. */
559 }
560
561 return (Uint32) (ptr - stream);
562 }
563
564 static void SDLCALL
SDL_BufferQueueDrainCallback(void * userdata,Uint8 * stream,int len)565 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int len)
566 {
567 /* this function always holds the mixer lock before being called. */
568 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
569 Uint32 written;
570
571 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
572 SDL_assert(!device->iscapture); /* this shouldn't ever happen, right?! */
573 SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
574
575 written = dequeue_audio_from_device(device, stream, (Uint32) len);
576 stream += written;
577 len -= (int) written;
578
579 if (len > 0) { /* fill any remaining space in the stream with silence. */
580 SDL_assert(device->buffer_queue_head == NULL);
581 SDL_memset(stream, device->spec.silence, len);
582 }
583 }
584
585 static void SDLCALL
SDL_BufferQueueFillCallback(void * userdata,Uint8 * stream,int len)586 SDL_BufferQueueFillCallback(void *userdata, Uint8 *stream, int len)
587 {
588 /* this function always holds the mixer lock before being called. */
589 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
590
591 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
592 SDL_assert(device->iscapture); /* this shouldn't ever happen, right?! */
593 SDL_assert(len >= 0); /* this shouldn't ever happen, right?! */
594
595 /* note that if this needs to allocate more space and run out of memory,
596 we have no choice but to quietly drop the data and hope it works out
597 later, but you probably have bigger problems in this case anyhow. */
598 queue_audio_to_device(device, stream, (Uint32) len);
599 }
600
601 int
SDL_QueueAudio(SDL_AudioDeviceID devid,const void * data,Uint32 len)602 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *data, Uint32 len)
603 {
604 SDL_AudioDevice *device = get_audio_device(devid);
605 int rc = 0;
606
607 if (!device) {
608 return -1; /* get_audio_device() will have set the error state */
609 } else if (device->iscapture) {
610 return SDL_SetError("This is a capture device, queueing not allowed");
611 } else if (device->spec.callback != SDL_BufferQueueDrainCallback) {
612 return SDL_SetError("Audio device has a callback, queueing not allowed");
613 }
614
615 if (len > 0) {
616 current_audio.impl.LockDevice(device);
617 rc = queue_audio_to_device(device, data, len);
618 current_audio.impl.UnlockDevice(device);
619 }
620
621 return rc;
622 }
623
624 Uint32
SDL_DequeueAudio(SDL_AudioDeviceID devid,void * data,Uint32 len)625 SDL_DequeueAudio(SDL_AudioDeviceID devid, void *data, Uint32 len)
626 {
627 SDL_AudioDevice *device = get_audio_device(devid);
628 Uint32 rc;
629
630 if ( (len == 0) || /* nothing to do? */
631 (!device) || /* called with bogus device id */
632 (!device->iscapture) || /* playback devices can't dequeue */
633 (device->spec.callback != SDL_BufferQueueFillCallback) ) { /* not set for queueing */
634 return 0; /* just report zero bytes dequeued. */
635 }
636
637 current_audio.impl.LockDevice(device);
638 rc = dequeue_audio_from_device(device, data, len);
639 current_audio.impl.UnlockDevice(device);
640 return rc;
641 }
642
643 Uint32
SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)644 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
645 {
646 Uint32 retval = 0;
647 SDL_AudioDevice *device = get_audio_device(devid);
648
649 if (!device) {
650 return 0;
651 }
652
653 /* Nothing to do unless we're set up for queueing. */
654 if (device->spec.callback == SDL_BufferQueueDrainCallback) {
655 current_audio.impl.LockDevice(device);
656 retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
657 current_audio.impl.UnlockDevice(device);
658 } else if (device->spec.callback == SDL_BufferQueueFillCallback) {
659 current_audio.impl.LockDevice(device);
660 retval = device->queued_bytes;
661 current_audio.impl.UnlockDevice(device);
662 }
663
664 return retval;
665 }
666
667 void
SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)668 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
669 {
670 SDL_AudioDevice *device = get_audio_device(devid);
671 SDL_AudioBufferQueue *packet;
672
673 if (!device) {
674 return; /* nothing to do. */
675 }
676
677 /* Blank out the device and release the mutex. Free it afterwards. */
678 current_audio.impl.LockDevice(device);
679
680 /* merge the available pool and the current queue into one list. */
681 packet = device->buffer_queue_head;
682 if (packet) {
683 device->buffer_queue_tail->next = device->buffer_queue_pool;
684 } else {
685 packet = device->buffer_queue_pool;
686 }
687
688 /* Remove the queued packets from the device. */
689 device->buffer_queue_tail = NULL;
690 device->buffer_queue_head = NULL;
691 device->queued_bytes = 0;
692 device->buffer_queue_pool = packet;
693
694 /* Keep up to two packets in the pool to reduce future malloc pressure. */
695 if (packet) {
696 if (!packet->next) {
697 packet = NULL; /* one packet (the only one) for the pool. */
698 } else {
699 SDL_AudioBufferQueue *next = packet->next->next;
700 packet->next->next = NULL; /* two packets for the pool. */
701 packet = next; /* rest will be freed. */
702 }
703 }
704
705 current_audio.impl.UnlockDevice(device);
706
707 /* free any extra packets we didn't keep in the pool. */
708 free_audio_queue(packet);
709 }
710
711
712 /* The general mixing thread function */
713 static int SDLCALL
SDL_RunAudio(void * devicep)714 SDL_RunAudio(void *devicep)
715 {
716 SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
717 const int silence = (int) device->spec.silence;
718 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
719 const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
720 Uint8 *stream;
721 void *udata = device->spec.userdata;
722 void (SDLCALL *callback) (void *, Uint8 *, int) = device->spec.callback;
723
724 SDL_assert(!device->iscapture);
725
726 /* The audio mixing is always a high priority thread */
727 SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
728
729 /* Perform any thread setup */
730 device->threadid = SDL_ThreadID();
731 current_audio.impl.ThreadInit(device);
732
733 /* Loop, filling the audio buffers */
734 while (!SDL_AtomicGet(&device->shutdown)) {
735 /* Fill the current buffer with sound */
736 if (device->convert.needed) {
737 stream = device->convert.buf;
738 } else if (SDL_AtomicGet(&device->enabled)) {
739 stream = current_audio.impl.GetDeviceBuf(device);
740 } else {
741 /* if the device isn't enabled, we still write to the
742 fake_stream, so the app's callback will fire with
743 a regular frequency, in case they depend on that
744 for timing or progress. They can use hotplug
745 now to know if the device failed. */
746 stream = NULL;
747 }
748
749 if (stream == NULL) {
750 stream = device->fake_stream;
751 }
752
753 /* !!! FIXME: this should be LockDevice. */
754 if ( SDL_AtomicGet(&device->enabled) ) {
755 SDL_LockMutex(device->mixer_lock);
756 if (SDL_AtomicGet(&device->paused)) {
757 SDL_memset(stream, silence, stream_len);
758 } else {
759 (*callback) (udata, stream, stream_len);
760 }
761 SDL_UnlockMutex(device->mixer_lock);
762 }
763
764 /* Convert the audio if necessary */
765 if (device->convert.needed && SDL_AtomicGet(&device->enabled)) {
766 SDL_ConvertAudio(&device->convert);
767 stream = current_audio.impl.GetDeviceBuf(device);
768 if (stream == NULL) {
769 stream = device->fake_stream;
770 } else {
771 SDL_memcpy(stream, device->convert.buf,
772 device->convert.len_cvt);
773 }
774 }
775
776 /* Ready current buffer for play and change current buffer */
777 if (stream == device->fake_stream) {
778 SDL_Delay(delay);
779 } else {
780 current_audio.impl.PlayDevice(device);
781 current_audio.impl.WaitDevice(device);
782 }
783 }
784
785 current_audio.impl.PrepareToClose(device);
786
787 /* Wait for the audio to drain. */
788 SDL_Delay(((device->spec.samples * 1000) / device->spec.freq) * 2);
789
790 return 0;
791 }
792
793 /* The general capture thread function */
794 static int SDLCALL
SDL_CaptureAudio(void * devicep)795 SDL_CaptureAudio(void *devicep)
796 {
797 SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
798 const int silence = (int) device->spec.silence;
799 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
800 const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
801 Uint8 *stream;
802 void *udata = device->spec.userdata;
803 void (SDLCALL *callback) (void *, Uint8 *, int) = device->spec.callback;
804
805 SDL_assert(device->iscapture);
806
807 /* The audio mixing is always a high priority thread */
808 SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
809
810 /* Perform any thread setup */
811 device->threadid = SDL_ThreadID();
812 current_audio.impl.ThreadInit(device);
813
814 /* Loop, filling the audio buffers */
815 while (!SDL_AtomicGet(&device->shutdown)) {
816 int still_need;
817 Uint8 *ptr;
818
819 if (!SDL_AtomicGet(&device->enabled) || SDL_AtomicGet(&device->paused)) {
820 SDL_Delay(delay); /* just so we don't cook the CPU. */
821 current_audio.impl.FlushCapture(device); /* dump anything pending. */
822 continue;
823 }
824
825 /* Fill the current buffer with sound */
826 still_need = stream_len;
827 if (device->convert.needed) {
828 ptr = stream = device->convert.buf;
829 } else {
830 /* just use the "fake" stream to hold data read from the device. */
831 ptr = stream = device->fake_stream;
832 }
833
834 /* We still read from the device when "paused" to keep the state sane,
835 and block when there isn't data so this thread isn't eating CPU.
836 But we don't process it further or call the app's callback. */
837
838 while (still_need > 0) {
839 const int rc = current_audio.impl.CaptureFromDevice(device, ptr, still_need);
840 SDL_assert(rc <= still_need); /* device should not overflow buffer. :) */
841 if (rc > 0) {
842 still_need -= rc;
843 ptr += rc;
844 } else { /* uhoh, device failed for some reason! */
845 SDL_OpenedAudioDeviceDisconnected(device);
846 break;
847 }
848 }
849
850 if (still_need > 0) {
851 /* Keep any data we already read, silence the rest. */
852 SDL_memset(ptr, silence, still_need);
853 }
854
855 if (device->convert.needed) {
856 SDL_ConvertAudio(&device->convert);
857 }
858
859 /* !!! FIXME: this should be LockDevice. */
860 SDL_LockMutex(device->mixer_lock);
861 if (SDL_AtomicGet(&device->paused)) {
862 current_audio.impl.FlushCapture(device); /* one snuck in! */
863 } else {
864 (*callback)(udata, stream, stream_len);
865 }
866 SDL_UnlockMutex(device->mixer_lock);
867 }
868
869 current_audio.impl.FlushCapture(device);
870
871 return 0;
872 }
873
874
875 static SDL_AudioFormat
SDL_ParseAudioFormat(const char * string)876 SDL_ParseAudioFormat(const char *string)
877 {
878 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
879 CHECK_FMT_STRING(U8);
880 CHECK_FMT_STRING(S8);
881 CHECK_FMT_STRING(U16LSB);
882 CHECK_FMT_STRING(S16LSB);
883 CHECK_FMT_STRING(U16MSB);
884 CHECK_FMT_STRING(S16MSB);
885 CHECK_FMT_STRING(U16SYS);
886 CHECK_FMT_STRING(S16SYS);
887 CHECK_FMT_STRING(U16);
888 CHECK_FMT_STRING(S16);
889 CHECK_FMT_STRING(S32LSB);
890 CHECK_FMT_STRING(S32MSB);
891 CHECK_FMT_STRING(S32SYS);
892 CHECK_FMT_STRING(S32);
893 CHECK_FMT_STRING(F32LSB);
894 CHECK_FMT_STRING(F32MSB);
895 CHECK_FMT_STRING(F32SYS);
896 CHECK_FMT_STRING(F32);
897 #undef CHECK_FMT_STRING
898 return 0;
899 }
900
901 int
SDL_GetNumAudioDrivers(void)902 SDL_GetNumAudioDrivers(void)
903 {
904 return SDL_arraysize(bootstrap) - 1;
905 }
906
907 const char *
SDL_GetAudioDriver(int index)908 SDL_GetAudioDriver(int index)
909 {
910 if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
911 return bootstrap[index]->name;
912 }
913 return NULL;
914 }
915
916 int
SDL_AudioInit(const char * driver_name)917 SDL_AudioInit(const char *driver_name)
918 {
919 int i = 0;
920 int initialized = 0;
921 int tried_to_init = 0;
922
923 if (SDL_WasInit(SDL_INIT_AUDIO)) {
924 SDL_AudioQuit(); /* shutdown driver if already running. */
925 }
926
927 SDL_zero(current_audio);
928 SDL_zero(open_devices);
929
930 /* Select the proper audio driver */
931 if (driver_name == NULL) {
932 driver_name = SDL_getenv("SDL_AUDIODRIVER");
933 }
934
935 for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
936 /* make sure we should even try this driver before doing so... */
937 const AudioBootStrap *backend = bootstrap[i];
938 if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
939 (!driver_name && backend->demand_only)) {
940 continue;
941 }
942
943 tried_to_init = 1;
944 SDL_zero(current_audio);
945 current_audio.name = backend->name;
946 current_audio.desc = backend->desc;
947 initialized = backend->init(¤t_audio.impl);
948 }
949
950 if (!initialized) {
951 /* specific drivers will set the error message if they fail... */
952 if (!tried_to_init) {
953 if (driver_name) {
954 SDL_SetError("Audio target '%s' not available", driver_name);
955 } else {
956 SDL_SetError("No available audio device");
957 }
958 }
959
960 SDL_zero(current_audio);
961 return -1; /* No driver was available, so fail. */
962 }
963
964 current_audio.detectionLock = SDL_CreateMutex();
965
966 finish_audio_entry_points_init();
967
968 /* Make sure we have a list of devices available at startup. */
969 current_audio.impl.DetectDevices();
970
971 return 0;
972 }
973
974 /*
975 * Get the current audio driver name
976 */
977 const char *
SDL_GetCurrentAudioDriver()978 SDL_GetCurrentAudioDriver()
979 {
980 return current_audio.name;
981 }
982
983 /* Clean out devices that we've removed but had to keep around for stability. */
984 static void
clean_out_device_list(SDL_AudioDeviceItem ** devices,int * devCount,SDL_bool * removedFlag)985 clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
986 {
987 SDL_AudioDeviceItem *item = *devices;
988 SDL_AudioDeviceItem *prev = NULL;
989 int total = 0;
990
991 while (item) {
992 SDL_AudioDeviceItem *next = item->next;
993 if (item->handle != NULL) {
994 total++;
995 prev = item;
996 } else {
997 if (prev) {
998 prev->next = next;
999 } else {
1000 *devices = next;
1001 }
1002 SDL_free(item);
1003 }
1004 item = next;
1005 }
1006
1007 *devCount = total;
1008 *removedFlag = SDL_FALSE;
1009 }
1010
1011
1012 int
SDL_GetNumAudioDevices(int iscapture)1013 SDL_GetNumAudioDevices(int iscapture)
1014 {
1015 int retval = 0;
1016
1017 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1018 return -1;
1019 }
1020
1021 SDL_LockMutex(current_audio.detectionLock);
1022 if (iscapture && current_audio.captureDevicesRemoved) {
1023 clean_out_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount, ¤t_audio.captureDevicesRemoved);
1024 }
1025
1026 if (!iscapture && current_audio.outputDevicesRemoved) {
1027 clean_out_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount, ¤t_audio.outputDevicesRemoved);
1028 current_audio.outputDevicesRemoved = SDL_FALSE;
1029 }
1030
1031 retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
1032 SDL_UnlockMutex(current_audio.detectionLock);
1033
1034 return retval;
1035 }
1036
1037
1038 const char *
SDL_GetAudioDeviceName(int index,int iscapture)1039 SDL_GetAudioDeviceName(int index, int iscapture)
1040 {
1041 const char *retval = NULL;
1042
1043 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1044 SDL_SetError("Audio subsystem is not initialized");
1045 return NULL;
1046 }
1047
1048 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1049 SDL_SetError("No capture support");
1050 return NULL;
1051 }
1052
1053 if (index >= 0) {
1054 SDL_AudioDeviceItem *item;
1055 int i;
1056
1057 SDL_LockMutex(current_audio.detectionLock);
1058 item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
1059 i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
1060 if (index < i) {
1061 for (i--; i > index; i--, item = item->next) {
1062 SDL_assert(item != NULL);
1063 }
1064 SDL_assert(item != NULL);
1065 retval = item->name;
1066 }
1067 SDL_UnlockMutex(current_audio.detectionLock);
1068 }
1069
1070 if (retval == NULL) {
1071 SDL_SetError("No such device");
1072 }
1073
1074 return retval;
1075 }
1076
1077
1078 static void
close_audio_device(SDL_AudioDevice * device)1079 close_audio_device(SDL_AudioDevice * device)
1080 {
1081 if (!device) {
1082 return;
1083 }
1084
1085 if (device->id > 0) {
1086 SDL_AudioDevice *opendev = open_devices[device->id - 1];
1087 SDL_assert((opendev == device) || (opendev == NULL));
1088 if (opendev == device) {
1089 open_devices[device->id - 1] = NULL;
1090 }
1091 }
1092
1093 SDL_AtomicSet(&device->shutdown, 1);
1094 SDL_AtomicSet(&device->enabled, 0);
1095 if (device->thread != NULL) {
1096 SDL_WaitThread(device->thread, NULL);
1097 }
1098 if (device->mixer_lock != NULL) {
1099 SDL_DestroyMutex(device->mixer_lock);
1100 }
1101 SDL_free(device->fake_stream);
1102 if (device->convert.needed) {
1103 SDL_free(device->convert.buf);
1104 }
1105 if (device->hidden != NULL) {
1106 current_audio.impl.CloseDevice(device);
1107 }
1108
1109 free_audio_queue(device->buffer_queue_head);
1110 free_audio_queue(device->buffer_queue_pool);
1111
1112 SDL_free(device);
1113 }
1114
1115
1116 /*
1117 * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
1118 * Fills in a sanitized copy in (prepared).
1119 * Returns non-zero if okay, zero on fatal parameters in (orig).
1120 */
1121 static int
prepare_audiospec(const SDL_AudioSpec * orig,SDL_AudioSpec * prepared)1122 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
1123 {
1124 SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
1125
1126 if (orig->freq == 0) {
1127 const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
1128 if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
1129 prepared->freq = 22050; /* a reasonable default */
1130 }
1131 }
1132
1133 if (orig->format == 0) {
1134 const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
1135 if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
1136 prepared->format = AUDIO_S16; /* a reasonable default */
1137 }
1138 }
1139
1140 switch (orig->channels) {
1141 case 0:{
1142 const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
1143 if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
1144 prepared->channels = 2; /* a reasonable default */
1145 }
1146 break;
1147 }
1148 case 1: /* Mono */
1149 case 2: /* Stereo */
1150 case 4: /* surround */
1151 case 6: /* surround with center and lfe */
1152 break;
1153 default:
1154 SDL_SetError("Unsupported number of audio channels.");
1155 return 0;
1156 }
1157
1158 if (orig->samples == 0) {
1159 const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
1160 if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
1161 /* Pick a default of ~46 ms at desired frequency */
1162 /* !!! FIXME: remove this when the non-Po2 resampling is in. */
1163 const int samples = (prepared->freq / 1000) * 46;
1164 int power2 = 1;
1165 while (power2 < samples) {
1166 power2 *= 2;
1167 }
1168 prepared->samples = power2;
1169 }
1170 }
1171
1172 /* Calculate the silence and size of the audio specification */
1173 SDL_CalculateAudioSpec(prepared);
1174
1175 return 1;
1176 }
1177
1178 static SDL_AudioDeviceID
open_audio_device(const char * devname,int iscapture,const SDL_AudioSpec * desired,SDL_AudioSpec * obtained,int allowed_changes,int min_id)1179 open_audio_device(const char *devname, int iscapture,
1180 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1181 int allowed_changes, int min_id)
1182 {
1183 const SDL_bool is_internal_thread = (desired->callback != NULL);
1184 SDL_AudioDeviceID id = 0;
1185 SDL_AudioSpec _obtained;
1186 SDL_AudioDevice *device;
1187 SDL_bool build_cvt;
1188 void *handle = NULL;
1189 int i = 0;
1190
1191 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1192 SDL_SetError("Audio subsystem is not initialized");
1193 return 0;
1194 }
1195
1196 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1197 SDL_SetError("No capture support");
1198 return 0;
1199 }
1200
1201 /* !!! FIXME: there is a race condition here if two devices open from two threads at once. */
1202 /* Find an available device ID... */
1203 for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
1204 if (open_devices[id] == NULL) {
1205 break;
1206 }
1207 }
1208
1209 if (id == SDL_arraysize(open_devices)) {
1210 SDL_SetError("Too many open audio devices");
1211 return 0;
1212 }
1213
1214 if (!obtained) {
1215 obtained = &_obtained;
1216 }
1217 if (!prepare_audiospec(desired, obtained)) {
1218 return 0;
1219 }
1220
1221 /* If app doesn't care about a specific device, let the user override. */
1222 if (devname == NULL) {
1223 devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
1224 }
1225
1226 /*
1227 * Catch device names at the high level for the simple case...
1228 * This lets us have a basic "device enumeration" for systems that
1229 * don't have multiple devices, but makes sure the device name is
1230 * always NULL when it hits the low level.
1231 *
1232 * Also make sure that the simple case prevents multiple simultaneous
1233 * opens of the default system device.
1234 */
1235
1236 if ((iscapture) && (current_audio.impl.OnlyHasDefaultCaptureDevice)) {
1237 if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
1238 SDL_SetError("No such device");
1239 return 0;
1240 }
1241 devname = NULL;
1242
1243 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1244 if ((open_devices[i]) && (open_devices[i]->iscapture)) {
1245 SDL_SetError("Audio device already open");
1246 return 0;
1247 }
1248 }
1249 } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
1250 if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
1251 SDL_SetError("No such device");
1252 return 0;
1253 }
1254 devname = NULL;
1255
1256 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1257 if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
1258 SDL_SetError("Audio device already open");
1259 return 0;
1260 }
1261 }
1262 } else if (devname != NULL) {
1263 /* if the app specifies an exact string, we can pass the backend
1264 an actual device handle thingey, which saves them the effort of
1265 figuring out what device this was (such as, reenumerating
1266 everything again to find the matching human-readable name).
1267 It might still need to open a device based on the string for,
1268 say, a network audio server, but this optimizes some cases. */
1269 SDL_AudioDeviceItem *item;
1270 SDL_LockMutex(current_audio.detectionLock);
1271 for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
1272 if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
1273 handle = item->handle;
1274 break;
1275 }
1276 }
1277 SDL_UnlockMutex(current_audio.detectionLock);
1278 }
1279
1280 if (!current_audio.impl.AllowsArbitraryDeviceNames) {
1281 /* has to be in our device list, or the default device. */
1282 if ((handle == NULL) && (devname != NULL)) {
1283 SDL_SetError("No such device.");
1284 return 0;
1285 }
1286 }
1287
1288 device = (SDL_AudioDevice *) SDL_calloc(1, sizeof (SDL_AudioDevice));
1289 if (device == NULL) {
1290 SDL_OutOfMemory();
1291 return 0;
1292 }
1293 device->id = id + 1;
1294 device->spec = *obtained;
1295 device->iscapture = iscapture ? SDL_TRUE : SDL_FALSE;
1296 device->handle = handle;
1297
1298 SDL_AtomicSet(&device->shutdown, 0); /* just in case. */
1299 SDL_AtomicSet(&device->paused, 1);
1300 SDL_AtomicSet(&device->enabled, 1);
1301
1302 /* Create a mutex for locking the sound buffers */
1303 if (!current_audio.impl.SkipMixerLock) {
1304 device->mixer_lock = SDL_CreateMutex();
1305 if (device->mixer_lock == NULL) {
1306 close_audio_device(device);
1307 SDL_SetError("Couldn't create mixer lock");
1308 return 0;
1309 }
1310 }
1311
1312 if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
1313 close_audio_device(device);
1314 return 0;
1315 }
1316
1317 /* if your target really doesn't need it, set it to 0x1 or something. */
1318 /* otherwise, close_audio_device() won't call impl.CloseDevice(). */
1319 SDL_assert(device->hidden != NULL);
1320
1321 /* See if we need to do any conversion */
1322 build_cvt = SDL_FALSE;
1323 if (obtained->freq != device->spec.freq) {
1324 if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
1325 obtained->freq = device->spec.freq;
1326 } else {
1327 build_cvt = SDL_TRUE;
1328 }
1329 }
1330 if (obtained->format != device->spec.format) {
1331 if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
1332 obtained->format = device->spec.format;
1333 } else {
1334 build_cvt = SDL_TRUE;
1335 }
1336 }
1337 if (obtained->channels != device->spec.channels) {
1338 if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
1339 obtained->channels = device->spec.channels;
1340 } else {
1341 build_cvt = SDL_TRUE;
1342 }
1343 }
1344
1345 /* If the audio driver changes the buffer size, accept it.
1346 This needs to be done after the format is modified above,
1347 otherwise it might not have the correct buffer size.
1348 */
1349 if (device->spec.samples != obtained->samples) {
1350 obtained->samples = device->spec.samples;
1351 SDL_CalculateAudioSpec(obtained);
1352 }
1353
1354 if (build_cvt) {
1355 /* Build an audio conversion block */
1356 if (SDL_BuildAudioCVT(&device->convert,
1357 obtained->format, obtained->channels,
1358 obtained->freq,
1359 device->spec.format, device->spec.channels,
1360 device->spec.freq) < 0) {
1361 close_audio_device(device);
1362 return 0;
1363 }
1364 if (device->convert.needed) {
1365 device->convert.len = (int) (((double) device->spec.size) /
1366 device->convert.len_ratio);
1367
1368 device->convert.buf =
1369 (Uint8 *) SDL_malloc(device->convert.len *
1370 device->convert.len_mult);
1371 if (device->convert.buf == NULL) {
1372 close_audio_device(device);
1373 SDL_OutOfMemory();
1374 return 0;
1375 }
1376 }
1377 }
1378
1379 if (device->spec.callback == NULL) { /* use buffer queueing? */
1380 /* pool a few packets to start. Enough for two callbacks. */
1381 const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
1382 const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
1383 const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
1384 for (i = 0; i < wantpackets; i++) {
1385 SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
1386 if (packet) { /* don't care if this fails, we'll deal later. */
1387 packet->datalen = 0;
1388 packet->startpos = 0;
1389 packet->next = device->buffer_queue_pool;
1390 device->buffer_queue_pool = packet;
1391 }
1392 }
1393
1394 device->spec.callback = iscapture ? SDL_BufferQueueFillCallback : SDL_BufferQueueDrainCallback;
1395 device->spec.userdata = device;
1396 }
1397
1398 /* add it to our list of open devices. */
1399 open_devices[id] = device;
1400
1401 /* Start the audio thread if necessary */
1402 if (!current_audio.impl.ProvidesOwnCallbackThread) {
1403 /* Start the audio thread */
1404 /* !!! FIXME: we don't force the audio thread stack size here if it calls into user code, but maybe we should? */
1405 /* buffer queueing callback only needs a few bytes, so make the stack tiny. */
1406 const size_t stacksize = is_internal_thread ? 64 * 1024 : 0;
1407 char threadname[64];
1408
1409 /* Allocate a fake audio buffer; only used by our internal threads. */
1410 Uint32 stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
1411 if (device->spec.size > stream_len) {
1412 stream_len = device->spec.size;
1413 }
1414 SDL_assert(stream_len > 0);
1415
1416 device->fake_stream = (Uint8 *) SDL_malloc(stream_len);
1417 if (device->fake_stream == NULL) {
1418 close_audio_device(device);
1419 SDL_OutOfMemory();
1420 return 0;
1421 }
1422
1423 SDL_snprintf(threadname, sizeof (threadname), "SDLAudioDev%d", (int) device->id);
1424 device->thread = SDL_CreateThreadInternal(iscapture ? SDL_CaptureAudio : SDL_RunAudio, threadname, stacksize, device);
1425
1426 if (device->thread == NULL) {
1427 close_audio_device(device);
1428 SDL_SetError("Couldn't create audio thread");
1429 return 0;
1430 }
1431 }
1432
1433 return device->id;
1434 }
1435
1436
1437 int
SDL_OpenAudio(SDL_AudioSpec * desired,SDL_AudioSpec * obtained)1438 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
1439 {
1440 SDL_AudioDeviceID id = 0;
1441
1442 /* Start up the audio driver, if necessary. This is legacy behaviour! */
1443 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1444 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
1445 return -1;
1446 }
1447 }
1448
1449 /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
1450 if (open_devices[0] != NULL) {
1451 SDL_SetError("Audio device is already opened");
1452 return -1;
1453 }
1454
1455 if (obtained) {
1456 id = open_audio_device(NULL, 0, desired, obtained,
1457 SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
1458 } else {
1459 id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
1460 }
1461
1462 SDL_assert((id == 0) || (id == 1));
1463 return (id == 0) ? -1 : 0;
1464 }
1465
1466 SDL_AudioDeviceID
SDL_OpenAudioDevice(const char * device,int iscapture,const SDL_AudioSpec * desired,SDL_AudioSpec * obtained,int allowed_changes)1467 SDL_OpenAudioDevice(const char *device, int iscapture,
1468 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1469 int allowed_changes)
1470 {
1471 return open_audio_device(device, iscapture, desired, obtained,
1472 allowed_changes, 2);
1473 }
1474
1475 SDL_AudioStatus
SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)1476 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
1477 {
1478 SDL_AudioDevice *device = get_audio_device(devid);
1479 SDL_AudioStatus status = SDL_AUDIO_STOPPED;
1480 if (device && SDL_AtomicGet(&device->enabled)) {
1481 if (SDL_AtomicGet(&device->paused)) {
1482 status = SDL_AUDIO_PAUSED;
1483 } else {
1484 status = SDL_AUDIO_PLAYING;
1485 }
1486 }
1487 return status;
1488 }
1489
1490
1491 SDL_AudioStatus
SDL_GetAudioStatus(void)1492 SDL_GetAudioStatus(void)
1493 {
1494 return SDL_GetAudioDeviceStatus(1);
1495 }
1496
1497 void
SDL_PauseAudioDevice(SDL_AudioDeviceID devid,int pause_on)1498 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
1499 {
1500 SDL_AudioDevice *device = get_audio_device(devid);
1501 if (device) {
1502 current_audio.impl.LockDevice(device);
1503 SDL_AtomicSet(&device->paused, pause_on ? 1 : 0);
1504 current_audio.impl.UnlockDevice(device);
1505 }
1506 }
1507
1508 void
SDL_PauseAudio(int pause_on)1509 SDL_PauseAudio(int pause_on)
1510 {
1511 SDL_PauseAudioDevice(1, pause_on);
1512 }
1513
1514
1515 void
SDL_LockAudioDevice(SDL_AudioDeviceID devid)1516 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
1517 {
1518 /* Obtain a lock on the mixing buffers */
1519 SDL_AudioDevice *device = get_audio_device(devid);
1520 if (device) {
1521 current_audio.impl.LockDevice(device);
1522 }
1523 }
1524
1525 void
SDL_LockAudio(void)1526 SDL_LockAudio(void)
1527 {
1528 SDL_LockAudioDevice(1);
1529 }
1530
1531 void
SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)1532 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
1533 {
1534 /* Obtain a lock on the mixing buffers */
1535 SDL_AudioDevice *device = get_audio_device(devid);
1536 if (device) {
1537 current_audio.impl.UnlockDevice(device);
1538 }
1539 }
1540
1541 void
SDL_UnlockAudio(void)1542 SDL_UnlockAudio(void)
1543 {
1544 SDL_UnlockAudioDevice(1);
1545 }
1546
1547 void
SDL_CloseAudioDevice(SDL_AudioDeviceID devid)1548 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
1549 {
1550 close_audio_device(get_audio_device(devid));
1551 }
1552
1553 void
SDL_CloseAudio(void)1554 SDL_CloseAudio(void)
1555 {
1556 SDL_CloseAudioDevice(1);
1557 }
1558
1559 void
SDL_AudioQuit(void)1560 SDL_AudioQuit(void)
1561 {
1562 SDL_AudioDeviceID i;
1563
1564 if (!current_audio.name) { /* not initialized?! */
1565 return;
1566 }
1567
1568 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1569 close_audio_device(open_devices[i]);
1570 }
1571
1572 free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
1573 free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
1574
1575 /* Free the driver data */
1576 current_audio.impl.Deinitialize();
1577
1578 SDL_DestroyMutex(current_audio.detectionLock);
1579
1580 SDL_zero(current_audio);
1581 SDL_zero(open_devices);
1582 }
1583
1584 #define NUM_FORMATS 10
1585 static int format_idx;
1586 static int format_idx_sub;
1587 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
1588 {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1589 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1590 {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1591 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1592 {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
1593 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1594 {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
1595 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1596 {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
1597 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1598 {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
1599 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1600 {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
1601 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1602 {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
1603 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1604 {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
1605 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1606 {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
1607 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1608 };
1609
1610 SDL_AudioFormat
SDL_FirstAudioFormat(SDL_AudioFormat format)1611 SDL_FirstAudioFormat(SDL_AudioFormat format)
1612 {
1613 for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
1614 if (format_list[format_idx][0] == format) {
1615 break;
1616 }
1617 }
1618 format_idx_sub = 0;
1619 return SDL_NextAudioFormat();
1620 }
1621
1622 SDL_AudioFormat
SDL_NextAudioFormat(void)1623 SDL_NextAudioFormat(void)
1624 {
1625 if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
1626 return 0;
1627 }
1628 return format_list[format_idx][format_idx_sub++];
1629 }
1630
1631 void
SDL_CalculateAudioSpec(SDL_AudioSpec * spec)1632 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
1633 {
1634 switch (spec->format) {
1635 case AUDIO_U8:
1636 spec->silence = 0x80;
1637 break;
1638 default:
1639 spec->silence = 0x00;
1640 break;
1641 }
1642 spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
1643 spec->size *= spec->channels;
1644 spec->size *= spec->samples;
1645 }
1646
1647
1648 /*
1649 * Moved here from SDL_mixer.c, since it relies on internals of an opened
1650 * audio device (and is deprecated, by the way!).
1651 */
1652 void
SDL_MixAudio(Uint8 * dst,const Uint8 * src,Uint32 len,int volume)1653 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
1654 {
1655 /* Mix the user-level audio format */
1656 SDL_AudioDevice *device = get_audio_device(1);
1657 if (device != NULL) {
1658 SDL_AudioFormat format;
1659 if (device->convert.needed) {
1660 format = device->convert.src_format;
1661 } else {
1662 format = device->spec.format;
1663 }
1664 SDL_MixAudioFormat(dst, src, format, len, volume);
1665 }
1666 }
1667
1668 /* vi: set ts=4 sw=4 expandtab: */
1669