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