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