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