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, &current_audio.inputDevices, &current_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, &current_audio.outputDevices, &current_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, &current_audio.captureDevicesRemoved);
542     } else {
543         mark_device_removed(handle, current_audio.outputDevices, &current_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(&current_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(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
1059     }
1060 
1061     if (!iscapture && current_audio.outputDevicesRemoved) {
1062         clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_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(&current_audio.outputDevices, &current_audio.outputDeviceCount);
1606     free_device_list(&current_audio.inputDevices, &current_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