2 Simple DirectMedia Layer
3 Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
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.
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:
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.
21 #include "../SDL_internal.h"
23 /* Allow access to a raw mixing buffer */
26 #include "SDL_audio.h"
27 #include "SDL_audio_c.h"
28 #include "SDL_audiomem.h"
29 #include "SDL_sysaudio.h"
31 #define _THIS SDL_AudioDevice *_this
33 static SDL_AudioDriver current_audio;
34 static SDL_AudioDevice *open_devices[16];
36 /* !!! FIXME: These are wordy and unlocalized... */
37 #define DEFAULT_OUTPUT_DEVNAME "System audio output device"
38 #define DEFAULT_INPUT_DEVNAME "System audio capture device"
42 * Not all of these will be compiled and linked in, but it's convenient
43 * to have a complete list here and saves yet-another block of #ifdefs...
44 * Please see bootstrap[], below, for the actual #ifdef mess.
46 extern AudioBootStrap BSD_AUDIO_bootstrap;
47 extern AudioBootStrap DSP_bootstrap;
48 extern AudioBootStrap ALSA_bootstrap;
49 extern AudioBootStrap PULSEAUDIO_bootstrap;
50 extern AudioBootStrap QSAAUDIO_bootstrap;
51 extern AudioBootStrap SUNAUDIO_bootstrap;
52 extern AudioBootStrap ARTS_bootstrap;
53 extern AudioBootStrap ESD_bootstrap;
54 extern AudioBootStrap NACLAUD_bootstrap;
55 extern AudioBootStrap NAS_bootstrap;
56 extern AudioBootStrap XAUDIO2_bootstrap;
57 extern AudioBootStrap DSOUND_bootstrap;
58 extern AudioBootStrap WINMM_bootstrap;
59 extern AudioBootStrap PAUDIO_bootstrap;
60 extern AudioBootStrap HAIKUAUDIO_bootstrap;
61 extern AudioBootStrap COREAUDIO_bootstrap;
62 extern AudioBootStrap SNDMGR_bootstrap;
63 extern AudioBootStrap DISKAUD_bootstrap;
64 extern AudioBootStrap DUMMYAUD_bootstrap;
65 extern AudioBootStrap DCAUD_bootstrap;
66 extern AudioBootStrap DART_bootstrap;
67 extern AudioBootStrap NDSAUD_bootstrap;
68 extern AudioBootStrap FUSIONSOUND_bootstrap;
69 extern AudioBootStrap ANDROIDAUD_bootstrap;
70 extern AudioBootStrap PSPAUD_bootstrap;
71 extern AudioBootStrap SNDIO_bootstrap;
72 extern AudioBootStrap EmscriptenAudio_bootstrap;
75 /* Available audio drivers */
76 static const AudioBootStrap *const bootstrap[] = {
77 #if SDL_AUDIO_DRIVER_PULSEAUDIO
78 &PULSEAUDIO_bootstrap,
80 #if SDL_AUDIO_DRIVER_ALSA
83 #if SDL_AUDIO_DRIVER_SNDIO
86 #if SDL_AUDIO_DRIVER_BSD
89 #if SDL_AUDIO_DRIVER_OSS
92 #if SDL_AUDIO_DRIVER_QSA
95 #if SDL_AUDIO_DRIVER_SUNAUDIO
98 #if SDL_AUDIO_DRIVER_ARTS
101 #if SDL_AUDIO_DRIVER_ESD
104 #if SDL_AUDIO_DRIVER_NACL
107 #if SDL_AUDIO_DRIVER_NAS
110 #if SDL_AUDIO_DRIVER_XAUDIO2
113 #if SDL_AUDIO_DRIVER_DSOUND
116 #if SDL_AUDIO_DRIVER_WINMM
119 #if SDL_AUDIO_DRIVER_PAUDIO
122 #if SDL_AUDIO_DRIVER_HAIKU
123 &HAIKUAUDIO_bootstrap,
125 #if SDL_AUDIO_DRIVER_COREAUDIO
126 &COREAUDIO_bootstrap,
128 #if SDL_AUDIO_DRIVER_DISK
131 #if SDL_AUDIO_DRIVER_DUMMY
134 #if SDL_AUDIO_DRIVER_FUSIONSOUND
135 &FUSIONSOUND_bootstrap,
137 #if SDL_AUDIO_DRIVER_ANDROID
138 &ANDROIDAUD_bootstrap,
140 #if SDL_AUDIO_DRIVER_PSP
143 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
144 &EmscriptenAudio_bootstrap,
149 static SDL_AudioDevice *
150 get_audio_device(SDL_AudioDeviceID id)
153 if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
154 SDL_SetError("Invalid audio device ID");
158 return open_devices[id];
162 /* stubs for audio drivers that don't need a specific entry point... */
164 SDL_AudioDetectDevices_Default(void)
166 /* you have to write your own implementation if these assertions fail. */
167 SDL_assert(current_audio.impl.OnlyHasDefaultOutputDevice);
168 SDL_assert(current_audio.impl.OnlyHasDefaultInputDevice || !current_audio.impl.HasCaptureSupport);
170 SDL_AddAudioDevice(SDL_FALSE, DEFAULT_OUTPUT_DEVNAME, (void *) ((size_t) 0x1));
171 if (current_audio.impl.HasCaptureSupport) {
172 SDL_AddAudioDevice(SDL_TRUE, DEFAULT_INPUT_DEVNAME, (void *) ((size_t) 0x2));
177 SDL_AudioThreadInit_Default(_THIS)
182 SDL_AudioWaitDevice_Default(_THIS)
187 SDL_AudioPlayDevice_Default(_THIS)
192 SDL_AudioGetPendingBytes_Default(_THIS)
198 SDL_AudioGetDeviceBuf_Default(_THIS)
204 SDL_AudioWaitDone_Default(_THIS)
209 SDL_AudioCloseDevice_Default(_THIS)
214 SDL_AudioDeinitialize_Default(void)
219 SDL_AudioFreeDeviceHandle_Default(void *handle)
225 SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
227 return SDL_Unsupported();
230 static SDL_INLINE SDL_bool
231 is_in_audio_device_thread(SDL_AudioDevice * device)
233 /* The device thread locks the same mutex, but not through the public API.
234 This check is in case the application, in the audio callback,
235 tries to lock the thread that we've already locked from the
236 device thread...just in case we only have non-recursive mutexes. */
237 if (device->thread && (SDL_ThreadID() == device->threadid)) {
245 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
247 if (!is_in_audio_device_thread(device)) {
248 SDL_LockMutex(device->mixer_lock);
253 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
255 if (!is_in_audio_device_thread(device)) {
256 SDL_UnlockMutex(device->mixer_lock);
262 finalize_audio_entry_points(void)
265 * Fill in stub functions for unused driver entry points. This lets us
266 * blindly call them without having to check for validity first.
269 #define FILL_STUB(x) \
270 if (current_audio.impl.x == NULL) { \
271 current_audio.impl.x = SDL_Audio##x##_Default; \
273 FILL_STUB(DetectDevices);
274 FILL_STUB(OpenDevice);
275 FILL_STUB(ThreadInit);
276 FILL_STUB(WaitDevice);
277 FILL_STUB(PlayDevice);
278 FILL_STUB(GetPendingBytes);
279 FILL_STUB(GetDeviceBuf);
281 FILL_STUB(CloseDevice);
282 FILL_STUB(LockDevice);
283 FILL_STUB(UnlockDevice);
284 FILL_STUB(FreeDeviceHandle);
285 FILL_STUB(Deinitialize);
290 /* device hotplug support... */
293 add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
296 const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
297 SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
302 SDL_assert(handle != NULL); /* we reserve NULL, audio backends can't use it. */
304 item->handle = handle;
305 SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
307 SDL_LockMutex(current_audio.detectionLock);
308 item->next = *devices;
310 retval = (*devCount)++;
311 SDL_UnlockMutex(current_audio.detectionLock);
316 static SDL_INLINE int
317 add_capture_device(const char *name, void *handle)
319 /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
320 return add_audio_device(name, handle, ¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
323 static SDL_INLINE int
324 add_output_device(const char *name, void *handle)
326 return add_audio_device(name, handle, ¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
330 free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
332 SDL_AudioDeviceItem *item, *next;
333 for (item = *devices; item != NULL; item = next) {
335 if (item->handle != NULL) {
336 current_audio.impl.FreeDeviceHandle(item->handle);
345 /* The audio backends call this when a new device is plugged in. */
347 SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
349 const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
350 if (device_index != -1) {
351 /* Post the event, if desired */
352 if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
355 event.adevice.type = SDL_AUDIODEVICEADDED;
356 event.adevice.which = device_index;
357 event.adevice.iscapture = iscapture;
358 SDL_PushEvent(&event);
363 /* The audio backends call this when a currently-opened device is lost. */
364 void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
366 SDL_assert(get_audio_device(device->id) == device);
368 if (!device->enabled) {
372 /* Ends the audio callback and mark the device as STOPPED, but the
373 app still needs to close the device to free resources. */
374 current_audio.impl.LockDevice(device);
376 current_audio.impl.UnlockDevice(device);
378 /* Post the event, if desired */
379 if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
382 event.adevice.type = SDL_AUDIODEVICEREMOVED;
383 event.adevice.which = device->id;
384 event.adevice.iscapture = device->iscapture ? 1 : 0;
385 SDL_PushEvent(&event);
390 mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
392 SDL_AudioDeviceItem *item;
393 SDL_assert(handle != NULL);
394 for (item = devices; item != NULL; item = item->next) {
395 if (item->handle == handle) {
397 *removedFlag = SDL_TRUE;
403 /* The audio backends call this when a device is removed from the system. */
405 SDL_RemoveAudioDevice(const int iscapture, void *handle)
407 SDL_LockMutex(current_audio.detectionLock);
409 mark_device_removed(handle, current_audio.inputDevices, ¤t_audio.captureDevicesRemoved);
411 mark_device_removed(handle, current_audio.outputDevices, ¤t_audio.outputDevicesRemoved);
413 SDL_UnlockMutex(current_audio.detectionLock);
414 current_audio.impl.FreeDeviceHandle(handle);
419 /* buffer queueing support... */
421 /* this expects that you managed thread safety elsewhere. */
423 free_audio_queue(SDL_AudioBufferQueue *buffer)
426 SDL_AudioBufferQueue *next = buffer->next;
433 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
435 /* this function always holds the mixer lock before being called. */
436 Uint32 len = (Uint32) _len;
437 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
438 SDL_AudioBufferQueue *buffer;
440 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
441 SDL_assert(_len >= 0); /* this shouldn't ever happen, right?! */
443 while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
444 const Uint32 avail = buffer->datalen - buffer->startpos;
445 const Uint32 cpy = SDL_min(len, avail);
446 SDL_assert(device->queued_bytes >= avail);
448 SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
449 buffer->startpos += cpy;
451 device->queued_bytes -= cpy;
454 if (buffer->startpos == buffer->datalen) { /* packet is done, put it in the pool. */
455 device->buffer_queue_head = buffer->next;
456 SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
457 buffer->next = device->buffer_queue_pool;
458 device->buffer_queue_pool = buffer;
462 SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
464 if (len > 0) { /* fill any remaining space in the stream with silence. */
465 SDL_assert(device->buffer_queue_head == NULL);
466 SDL_memset(stream, device->spec.silence, len);
469 if (device->buffer_queue_head == NULL) {
470 device->buffer_queue_tail = NULL; /* in case we drained the queue entirely. */
475 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
477 SDL_AudioDevice *device = get_audio_device(devid);
478 const Uint8 *data = (const Uint8 *) _data;
479 SDL_AudioBufferQueue *orighead;
480 SDL_AudioBufferQueue *origtail;
485 return -1; /* get_audio_device() will have set the error state */
488 if (device->spec.callback != SDL_BufferQueueDrainCallback) {
489 return SDL_SetError("Audio device has a callback, queueing not allowed");
492 current_audio.impl.LockDevice(device);
494 orighead = device->buffer_queue_head;
495 origtail = device->buffer_queue_tail;
496 origlen = origtail ? origtail->datalen : 0;
499 SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
500 SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
501 if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
502 /* tail packet missing or completely full; we need a new packet. */
503 packet = device->buffer_queue_pool;
504 if (packet != NULL) {
505 /* we have one available in the pool. */
506 device->buffer_queue_pool = packet->next;
508 /* Have to allocate a new one! */
509 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
510 if (packet == NULL) {
511 /* uhoh, reset so we've queued nothing new, free what we can. */
513 packet = device->buffer_queue_head; /* whole queue. */
515 packet = origtail->next; /* what we added to existing queue. */
516 origtail->next = NULL;
517 origtail->datalen = origlen;
519 device->buffer_queue_head = orighead;
520 device->buffer_queue_tail = origtail;
521 device->buffer_queue_pool = NULL;
523 current_audio.impl.UnlockDevice(device);
525 free_audio_queue(packet); /* give back what we can. */
527 return SDL_OutOfMemory();
531 packet->startpos = 0;
534 SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
535 if (device->buffer_queue_tail == NULL) {
536 device->buffer_queue_head = packet;
538 device->buffer_queue_tail->next = packet;
540 device->buffer_queue_tail = packet;
543 datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
544 SDL_memcpy(packet->data + packet->datalen, data, datalen);
547 packet->datalen += datalen;
548 device->queued_bytes += datalen;
551 current_audio.impl.UnlockDevice(device);
557 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
560 SDL_AudioDevice *device = get_audio_device(devid);
562 /* Nothing to do unless we're set up for queueing. */
563 if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
564 current_audio.impl.LockDevice(device);
565 retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
566 current_audio.impl.UnlockDevice(device);
573 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
575 SDL_AudioDevice *device = get_audio_device(devid);
576 SDL_AudioBufferQueue *buffer = NULL;
578 return; /* nothing to do. */
581 /* Blank out the device and release the mutex. Free it afterwards. */
582 current_audio.impl.LockDevice(device);
583 buffer = device->buffer_queue_head;
584 device->buffer_queue_tail = NULL;
585 device->buffer_queue_head = NULL;
586 device->queued_bytes = 0;
587 current_audio.impl.UnlockDevice(device);
589 free_audio_queue(buffer);
593 /* The general mixing thread function */
595 SDL_RunAudio(void *devicep)
597 SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
598 const int silence = (int) device->spec.silence;
599 const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
600 const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
602 void *udata = device->spec.userdata;
603 void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
605 /* The audio mixing is always a high priority thread */
606 SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
608 /* Perform any thread setup */
609 device->threadid = SDL_ThreadID();
610 current_audio.impl.ThreadInit(device);
612 /* Loop, filling the audio buffers */
613 while (!device->shutdown) {
614 /* Fill the current buffer with sound */
615 if (device->convert.needed) {
616 stream = device->convert.buf;
617 } else if (device->enabled) {
618 stream = current_audio.impl.GetDeviceBuf(device);
620 /* if the device isn't enabled, we still write to the
621 fake_stream, so the app's callback will fire with
622 a regular frequency, in case they depend on that
623 for timing or progress. They can use hotplug
624 now to know if the device failed. */
628 if (stream == NULL) {
629 stream = device->fake_stream;
632 /* !!! FIXME: this should be LockDevice. */
633 SDL_LockMutex(device->mixer_lock);
634 if (device->paused) {
635 SDL_memset(stream, silence, stream_len);
637 (*fill) (udata, stream, stream_len);
639 SDL_UnlockMutex(device->mixer_lock);
641 /* Convert the audio if necessary */
642 if (device->enabled && device->convert.needed) {
643 SDL_ConvertAudio(&device->convert);
644 stream = current_audio.impl.GetDeviceBuf(device);
645 if (stream == NULL) {
646 stream = device->fake_stream;
648 SDL_memcpy(stream, device->convert.buf,
649 device->convert.len_cvt);
653 /* Ready current buffer for play and change current buffer */
654 if (stream == device->fake_stream) {
657 current_audio.impl.PlayDevice(device);
658 current_audio.impl.WaitDevice(device);
662 /* Wait for the audio to drain. */
663 current_audio.impl.WaitDone(device);
669 static SDL_AudioFormat
670 SDL_ParseAudioFormat(const char *string)
672 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
673 CHECK_FMT_STRING(U8);
674 CHECK_FMT_STRING(S8);
675 CHECK_FMT_STRING(U16LSB);
676 CHECK_FMT_STRING(S16LSB);
677 CHECK_FMT_STRING(U16MSB);
678 CHECK_FMT_STRING(S16MSB);
679 CHECK_FMT_STRING(U16SYS);
680 CHECK_FMT_STRING(S16SYS);
681 CHECK_FMT_STRING(U16);
682 CHECK_FMT_STRING(S16);
683 CHECK_FMT_STRING(S32LSB);
684 CHECK_FMT_STRING(S32MSB);
685 CHECK_FMT_STRING(S32SYS);
686 CHECK_FMT_STRING(S32);
687 CHECK_FMT_STRING(F32LSB);
688 CHECK_FMT_STRING(F32MSB);
689 CHECK_FMT_STRING(F32SYS);
690 CHECK_FMT_STRING(F32);
691 #undef CHECK_FMT_STRING
696 SDL_GetNumAudioDrivers(void)
698 return SDL_arraysize(bootstrap) - 1;
702 SDL_GetAudioDriver(int index)
704 if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
705 return bootstrap[index]->name;
711 SDL_AudioInit(const char *driver_name)
715 int tried_to_init = 0;
717 if (SDL_WasInit(SDL_INIT_AUDIO)) {
718 SDL_AudioQuit(); /* shutdown driver if already running. */
721 SDL_zero(current_audio);
722 SDL_zero(open_devices);
724 /* Select the proper audio driver */
725 if (driver_name == NULL) {
726 driver_name = SDL_getenv("SDL_AUDIODRIVER");
729 for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
730 /* make sure we should even try this driver before doing so... */
731 const AudioBootStrap *backend = bootstrap[i];
732 if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
733 (!driver_name && backend->demand_only)) {
738 SDL_zero(current_audio);
739 current_audio.name = backend->name;
740 current_audio.desc = backend->desc;
741 initialized = backend->init(¤t_audio.impl);
745 /* specific drivers will set the error message if they fail... */
746 if (!tried_to_init) {
748 SDL_SetError("Audio target '%s' not available", driver_name);
750 SDL_SetError("No available audio device");
754 SDL_zero(current_audio);
755 return -1; /* No driver was available, so fail. */
758 current_audio.detectionLock = SDL_CreateMutex();
760 finalize_audio_entry_points();
762 /* Make sure we have a list of devices available at startup. */
763 current_audio.impl.DetectDevices();
769 * Get the current audio driver name
772 SDL_GetCurrentAudioDriver()
774 return current_audio.name;
777 /* Clean out devices that we've removed but had to keep around for stability. */
779 clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
781 SDL_AudioDeviceItem *item = *devices;
782 SDL_AudioDeviceItem *prev = NULL;
786 SDL_AudioDeviceItem *next = item->next;
787 if (item->handle != NULL) {
802 *removedFlag = SDL_FALSE;
807 SDL_GetNumAudioDevices(int iscapture)
811 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
815 SDL_LockMutex(current_audio.detectionLock);
816 if (iscapture && current_audio.captureDevicesRemoved) {
817 clean_out_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount, ¤t_audio.captureDevicesRemoved);
820 if (!iscapture && current_audio.outputDevicesRemoved) {
821 clean_out_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount, ¤t_audio.outputDevicesRemoved);
822 current_audio.outputDevicesRemoved = SDL_FALSE;
825 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
826 SDL_SetError("No capture support");
830 retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
831 SDL_UnlockMutex(current_audio.detectionLock);
838 SDL_GetAudioDeviceName(int index, int iscapture)
840 const char *retval = NULL;
842 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
843 SDL_SetError("Audio subsystem is not initialized");
847 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
848 SDL_SetError("No capture support");
853 SDL_AudioDeviceItem *item;
856 SDL_LockMutex(current_audio.detectionLock);
857 item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
858 i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
860 for (i--; i > index; i--, item = item->next) {
861 SDL_assert(item != NULL);
863 SDL_assert(item != NULL);
866 SDL_UnlockMutex(current_audio.detectionLock);
869 if (retval == NULL) {
870 SDL_SetError("No such device");
878 close_audio_device(SDL_AudioDevice * device)
881 device->shutdown = 1;
882 if (device->thread != NULL) {
883 SDL_WaitThread(device->thread, NULL);
885 if (device->mixer_lock != NULL) {
886 SDL_DestroyMutex(device->mixer_lock);
888 SDL_FreeAudioMem(device->fake_stream);
889 if (device->convert.needed) {
890 SDL_FreeAudioMem(device->convert.buf);
892 if (device->opened) {
893 current_audio.impl.CloseDevice(device);
897 free_audio_queue(device->buffer_queue_head);
898 free_audio_queue(device->buffer_queue_pool);
900 SDL_FreeAudioMem(device);
905 * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
906 * Fills in a sanitized copy in (prepared).
907 * Returns non-zero if okay, zero on fatal parameters in (orig).
910 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
912 SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
914 if (orig->freq == 0) {
915 const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
916 if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
917 prepared->freq = 22050; /* a reasonable default */
921 if (orig->format == 0) {
922 const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
923 if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
924 prepared->format = AUDIO_S16; /* a reasonable default */
928 switch (orig->channels) {
930 const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
931 if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
932 prepared->channels = 2; /* a reasonable default */
938 case 4: /* surround */
939 case 6: /* surround with center and lfe */
942 SDL_SetError("Unsupported number of audio channels.");
946 if (orig->samples == 0) {
947 const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
948 if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
949 /* Pick a default of ~46 ms at desired frequency */
950 /* !!! FIXME: remove this when the non-Po2 resampling is in. */
951 const int samples = (prepared->freq / 1000) * 46;
953 while (power2 < samples) {
956 prepared->samples = power2;
960 /* Calculate the silence and size of the audio specification */
961 SDL_CalculateAudioSpec(prepared);
966 static SDL_AudioDeviceID
967 open_audio_device(const char *devname, int iscapture,
968 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
969 int allowed_changes, int min_id)
971 SDL_AudioDeviceID id = 0;
972 SDL_AudioSpec _obtained;
973 SDL_AudioDevice *device;
979 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
980 SDL_SetError("Audio subsystem is not initialized");
984 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
985 SDL_SetError("No capture support");
989 /* Find an available device ID... */
990 for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
991 if (open_devices[id] == NULL) {
996 if (id == SDL_arraysize(open_devices)) {
997 SDL_SetError("Too many open audio devices");
1002 obtained = &_obtained;
1004 if (!prepare_audiospec(desired, obtained)) {
1008 /* If app doesn't care about a specific device, let the user override. */
1009 if (devname == NULL) {
1010 devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
1014 * Catch device names at the high level for the simple case...
1015 * This lets us have a basic "device enumeration" for systems that
1016 * don't have multiple devices, but makes sure the device name is
1017 * always NULL when it hits the low level.
1019 * Also make sure that the simple case prevents multiple simultaneous
1020 * opens of the default system device.
1023 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
1024 if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
1025 SDL_SetError("No such device");
1030 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1031 if ((open_devices[i]) && (open_devices[i]->iscapture)) {
1032 SDL_SetError("Audio device already open");
1036 } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
1037 if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
1038 SDL_SetError("No such device");
1043 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1044 if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
1045 SDL_SetError("Audio device already open");
1049 } else if (devname != NULL) {
1050 /* if the app specifies an exact string, we can pass the backend
1051 an actual device handle thingey, which saves them the effort of
1052 figuring out what device this was (such as, reenumerating
1053 everything again to find the matching human-readable name).
1054 It might still need to open a device based on the string for,
1055 say, a network audio server, but this optimizes some cases. */
1056 SDL_AudioDeviceItem *item;
1057 SDL_LockMutex(current_audio.detectionLock);
1058 for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
1059 if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
1060 handle = item->handle;
1064 SDL_UnlockMutex(current_audio.detectionLock);
1067 if (!current_audio.impl.AllowsArbitraryDeviceNames) {
1068 /* has to be in our device list, or the default device. */
1069 if ((handle == NULL) && (devname != NULL)) {
1070 SDL_SetError("No such device.");
1075 device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
1076 if (device == NULL) {
1081 device->id = id + 1;
1082 device->spec = *obtained;
1083 device->enabled = 1;
1085 device->iscapture = iscapture;
1087 /* Create a mutex for locking the sound buffers */
1088 if (!current_audio.impl.SkipMixerLock) {
1089 device->mixer_lock = SDL_CreateMutex();
1090 if (device->mixer_lock == NULL) {
1091 close_audio_device(device);
1092 SDL_SetError("Couldn't create mixer lock");
1097 if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
1098 close_audio_device(device);
1103 /* See if we need to do any conversion */
1104 build_cvt = SDL_FALSE;
1105 if (obtained->freq != device->spec.freq) {
1106 if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
1107 obtained->freq = device->spec.freq;
1109 build_cvt = SDL_TRUE;
1112 if (obtained->format != device->spec.format) {
1113 if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
1114 obtained->format = device->spec.format;
1116 build_cvt = SDL_TRUE;
1119 if (obtained->channels != device->spec.channels) {
1120 if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
1121 obtained->channels = device->spec.channels;
1123 build_cvt = SDL_TRUE;
1127 /* If the audio driver changes the buffer size, accept it.
1128 This needs to be done after the format is modified above,
1129 otherwise it might not have the correct buffer size.
1131 if (device->spec.samples != obtained->samples) {
1132 obtained->samples = device->spec.samples;
1133 SDL_CalculateAudioSpec(obtained);
1137 /* Build an audio conversion block */
1138 if (SDL_BuildAudioCVT(&device->convert,
1139 obtained->format, obtained->channels,
1141 device->spec.format, device->spec.channels,
1142 device->spec.freq) < 0) {
1143 close_audio_device(device);
1146 if (device->convert.needed) {
1147 device->convert.len = (int) (((double) device->spec.size) /
1148 device->convert.len_ratio);
1150 device->convert.buf =
1151 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
1152 device->convert.len_mult);
1153 if (device->convert.buf == NULL) {
1154 close_audio_device(device);
1161 /* Allocate a fake audio memory buffer */
1162 stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
1163 if (device->spec.size > stream_len) {
1164 stream_len = device->spec.size;
1166 SDL_assert(stream_len > 0);
1167 device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
1168 if (device->fake_stream == NULL) {
1169 close_audio_device(device);
1174 if (device->spec.callback == NULL) { /* use buffer queueing? */
1175 /* pool a few packets to start. Enough for two callbacks. */
1176 const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
1177 const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
1178 const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
1179 for (i = 0; i < wantpackets; i++) {
1180 SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
1181 if (packet) { /* don't care if this fails, we'll deal later. */
1182 packet->datalen = 0;
1183 packet->startpos = 0;
1184 packet->next = device->buffer_queue_pool;
1185 device->buffer_queue_pool = packet;
1189 device->spec.callback = SDL_BufferQueueDrainCallback;
1190 device->spec.userdata = device;
1193 /* add it to our list of open devices. */
1194 open_devices[id] = device;
1196 /* Start the audio thread if necessary */
1197 if (!current_audio.impl.ProvidesOwnCallbackThread) {
1198 /* Start the audio thread */
1200 SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
1201 /* !!! FIXME: this is nasty. */
1202 #if defined(__WIN32__) && !defined(HAVE_LIBC)
1203 #undef SDL_CreateThread
1205 device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
1207 device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
1210 device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
1212 if (device->thread == NULL) {
1213 SDL_CloseAudioDevice(device->id);
1214 SDL_SetError("Couldn't create audio thread");
1224 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
1226 SDL_AudioDeviceID id = 0;
1228 /* Start up the audio driver, if necessary. This is legacy behaviour! */
1229 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1230 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
1235 /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
1236 if (open_devices[0] != NULL) {
1237 SDL_SetError("Audio device is already opened");
1242 id = open_audio_device(NULL, 0, desired, obtained,
1243 SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
1245 id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
1248 SDL_assert((id == 0) || (id == 1));
1249 return (id == 0) ? -1 : 0;
1253 SDL_OpenAudioDevice(const char *device, int iscapture,
1254 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1255 int allowed_changes)
1257 return open_audio_device(device, iscapture, desired, obtained,
1258 allowed_changes, 2);
1262 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
1264 SDL_AudioDevice *device = get_audio_device(devid);
1265 SDL_AudioStatus status = SDL_AUDIO_STOPPED;
1266 if (device && device->enabled) {
1267 if (device->paused) {
1268 status = SDL_AUDIO_PAUSED;
1270 status = SDL_AUDIO_PLAYING;
1278 SDL_GetAudioStatus(void)
1280 return SDL_GetAudioDeviceStatus(1);
1284 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
1286 SDL_AudioDevice *device = get_audio_device(devid);
1288 current_audio.impl.LockDevice(device);
1289 device->paused = pause_on;
1290 current_audio.impl.UnlockDevice(device);
1295 SDL_PauseAudio(int pause_on)
1297 SDL_PauseAudioDevice(1, pause_on);
1302 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
1304 /* Obtain a lock on the mixing buffers */
1305 SDL_AudioDevice *device = get_audio_device(devid);
1307 current_audio.impl.LockDevice(device);
1314 SDL_LockAudioDevice(1);
1318 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
1320 /* Obtain a lock on the mixing buffers */
1321 SDL_AudioDevice *device = get_audio_device(devid);
1323 current_audio.impl.UnlockDevice(device);
1328 SDL_UnlockAudio(void)
1330 SDL_UnlockAudioDevice(1);
1334 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
1336 SDL_AudioDevice *device = get_audio_device(devid);
1338 close_audio_device(device);
1339 open_devices[devid - 1] = NULL;
1344 SDL_CloseAudio(void)
1346 SDL_CloseAudioDevice(1);
1352 SDL_AudioDeviceID i;
1354 if (!current_audio.name) { /* not initialized?! */
1358 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1359 if (open_devices[i] != NULL) {
1360 SDL_CloseAudioDevice(i+1);
1364 free_device_list(¤t_audio.outputDevices, ¤t_audio.outputDeviceCount);
1365 free_device_list(¤t_audio.inputDevices, ¤t_audio.inputDeviceCount);
1367 /* Free the driver data */
1368 if(current_audio.impl.Deinitialize)
1369 current_audio.impl.Deinitialize();
1371 SDL_DestroyMutex(current_audio.detectionLock);
1373 SDL_zero(current_audio);
1374 SDL_zero(open_devices);
1377 #define NUM_FORMATS 10
1378 static int format_idx;
1379 static int format_idx_sub;
1380 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
1381 {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1382 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1383 {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1384 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1385 {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
1386 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1387 {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
1388 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1389 {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
1390 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1391 {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
1392 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1393 {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
1394 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1395 {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
1396 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1397 {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
1398 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1399 {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
1400 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1404 SDL_FirstAudioFormat(SDL_AudioFormat format)
1406 for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
1407 if (format_list[format_idx][0] == format) {
1412 return SDL_NextAudioFormat();
1416 SDL_NextAudioFormat(void)
1418 if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
1421 return format_list[format_idx][format_idx_sub++];
1425 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
1427 switch (spec->format) {
1429 spec->silence = 0x80;
1432 spec->silence = 0x00;
1435 spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
1436 spec->size *= spec->channels;
1437 spec->size *= spec->samples;
1442 * Moved here from SDL_mixer.c, since it relies on internals of an opened
1443 * audio device (and is deprecated, by the way!).
1446 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
1448 /* Mix the user-level audio format */
1449 SDL_AudioDevice *device = get_audio_device(1);
1450 if (device != NULL) {
1451 SDL_AudioFormat format;
1452 if (device->convert.needed) {
1453 format = device->convert.src_format;
1455 format = device->spec.format;
1457 SDL_MixAudioFormat(dst, src, format, len, volume);
1461 /* vi: set ts=4 sw=4 expandtab: */