Emscripten: Fixed out of range joystick device index after joystick disconnect.
After disconnecting a joystick the remaining kept their original device index.
This was not correct because the device index must be a number between 0 and
SDL_NumJoysticks(). It was fixed with ideas from SDL's joystick implementation
for Android. Some range checks were removed as the caller already checks them.
2 Simple DirectMedia Layer
3 Copyright (C) 1997-2014 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 #if SDL_AUDIO_DRIVER_NACL
55 extern AudioBootStrap NACLAUD_bootstrap;
57 extern AudioBootStrap NAS_bootstrap;
58 extern AudioBootStrap XAUDIO2_bootstrap;
59 extern AudioBootStrap DSOUND_bootstrap;
60 extern AudioBootStrap WINMM_bootstrap;
61 extern AudioBootStrap PAUDIO_bootstrap;
62 extern AudioBootStrap HAIKUAUDIO_bootstrap;
63 extern AudioBootStrap COREAUDIO_bootstrap;
64 extern AudioBootStrap SNDMGR_bootstrap;
65 extern AudioBootStrap DISKAUD_bootstrap;
66 extern AudioBootStrap DUMMYAUD_bootstrap;
67 extern AudioBootStrap DCAUD_bootstrap;
68 extern AudioBootStrap DART_bootstrap;
69 extern AudioBootStrap NDSAUD_bootstrap;
70 extern AudioBootStrap FUSIONSOUND_bootstrap;
71 extern AudioBootStrap ANDROIDAUD_bootstrap;
72 extern AudioBootStrap PSPAUD_bootstrap;
73 extern AudioBootStrap SNDIO_bootstrap;
74 extern AudioBootStrap EmscriptenAudio_bootstrap;
77 /* Available audio drivers */
78 static const AudioBootStrap *const bootstrap[] = {
79 #if SDL_AUDIO_DRIVER_PULSEAUDIO
80 &PULSEAUDIO_bootstrap,
82 #if SDL_AUDIO_DRIVER_ALSA
85 #if SDL_AUDIO_DRIVER_SNDIO
88 #if SDL_AUDIO_DRIVER_BSD
91 #if SDL_AUDIO_DRIVER_OSS
94 #if SDL_AUDIO_DRIVER_QSA
97 #if SDL_AUDIO_DRIVER_SUNAUDIO
100 #if SDL_AUDIO_DRIVER_ARTS
103 #if SDL_AUDIO_DRIVER_ESD
106 #if SDL_AUDIO_DRIVER_NACL
109 #if SDL_AUDIO_DRIVER_NAS
112 #if SDL_AUDIO_DRIVER_XAUDIO2
115 #if SDL_AUDIO_DRIVER_DSOUND
118 #if SDL_AUDIO_DRIVER_WINMM
121 #if SDL_AUDIO_DRIVER_PAUDIO
124 #if SDL_AUDIO_DRIVER_HAIKU
125 &HAIKUAUDIO_bootstrap,
127 #if SDL_AUDIO_DRIVER_COREAUDIO
128 &COREAUDIO_bootstrap,
130 #if SDL_AUDIO_DRIVER_DISK
133 #if SDL_AUDIO_DRIVER_DUMMY
136 #if SDL_AUDIO_DRIVER_FUSIONSOUND
137 &FUSIONSOUND_bootstrap,
139 #if SDL_AUDIO_DRIVER_ANDROID
140 &ANDROIDAUD_bootstrap,
142 #if SDL_AUDIO_DRIVER_PSP
145 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
146 &EmscriptenAudio_bootstrap,
151 static SDL_AudioDevice *
152 get_audio_device(SDL_AudioDeviceID id)
155 if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
156 SDL_SetError("Invalid audio device ID");
160 return open_devices[id];
164 /* stubs for audio drivers that don't need a specific entry point... */
166 SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn)
171 SDL_AudioThreadInit_Default(_THIS)
176 SDL_AudioWaitDevice_Default(_THIS)
181 SDL_AudioPlayDevice_Default(_THIS)
186 SDL_AudioGetPendingBytes_Default(_THIS)
192 SDL_AudioGetDeviceBuf_Default(_THIS)
198 SDL_AudioWaitDone_Default(_THIS)
203 SDL_AudioCloseDevice_Default(_THIS)
208 SDL_AudioDeinitialize_Default(void)
213 SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
218 static SDL_INLINE SDL_bool
219 is_in_audio_device_thread(SDL_AudioDevice * device)
221 /* The device thread locks the same mutex, but not through the public API.
222 This check is in case the application, in the audio callback,
223 tries to lock the thread that we've already locked from the
224 device thread...just in case we only have non-recursive mutexes. */
225 if (device->thread && (SDL_ThreadID() == device->threadid)) {
233 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
235 if (!is_in_audio_device_thread(device)) {
236 SDL_LockMutex(device->mixer_lock);
241 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
243 if (!is_in_audio_device_thread(device)) {
244 SDL_UnlockMutex(device->mixer_lock);
250 finalize_audio_entry_points(void)
253 * Fill in stub functions for unused driver entry points. This lets us
254 * blindly call them without having to check for validity first.
257 #define FILL_STUB(x) \
258 if (current_audio.impl.x == NULL) { \
259 current_audio.impl.x = SDL_Audio##x##_Default; \
261 FILL_STUB(DetectDevices);
262 FILL_STUB(OpenDevice);
263 FILL_STUB(ThreadInit);
264 FILL_STUB(WaitDevice);
265 FILL_STUB(PlayDevice);
266 FILL_STUB(GetPendingBytes);
267 FILL_STUB(GetDeviceBuf);
269 FILL_STUB(CloseDevice);
270 FILL_STUB(LockDevice);
271 FILL_STUB(UnlockDevice);
272 FILL_STUB(Deinitialize);
276 #if 0 /* !!! FIXME: rewrite/remove this streamer code. */
277 /* Streaming functions (for when the input and output buffer sizes are different) */
278 /* Write [length] bytes from buf into the streamer */
280 SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length)
284 for (i = 0; i < length; ++i) {
285 stream->buffer[stream->write_pos] = buf[i];
290 /* Read [length] bytes out of the streamer into buf */
292 SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
296 for (i = 0; i < length; ++i) {
297 buf[i] = stream->buffer[stream->read_pos];
303 SDL_StreamLength(SDL_AudioStreamer * stream)
305 return (stream->write_pos - stream->read_pos) % stream->max_len;
308 /* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */
311 SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
313 /* First try to allocate the buffer */
314 stream->buffer = (Uint8 *) SDL_malloc(max_len);
315 if (stream->buffer == NULL) {
319 stream->max_len = max_len;
320 stream->read_pos = 0;
321 stream->write_pos = 0;
323 /* Zero out the buffer */
324 SDL_memset(stream->buffer, silence, max_len);
330 /* Deinitialize the stream simply by freeing the buffer */
332 SDL_StreamDeinit(SDL_AudioStreamer * stream)
334 SDL_free(stream->buffer);
339 /* buffer queueing support... */
341 /* this expects that you managed thread safety elsewhere. */
343 free_audio_queue(SDL_AudioBufferQueue *buffer)
346 SDL_AudioBufferQueue *next = buffer->next;
353 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
355 /* this function always holds the mixer lock before being called. */
356 Uint32 len = (Uint32) _len;
357 SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
358 SDL_AudioBufferQueue *buffer;
360 SDL_assert(device != NULL); /* this shouldn't ever happen, right?! */
361 SDL_assert(_len >= 0); /* this shouldn't ever happen, right?! */
363 while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
364 const Uint32 avail = buffer->datalen - buffer->startpos;
365 const Uint32 cpy = SDL_min(len, avail);
366 SDL_assert(device->queued_bytes >= avail);
368 SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
369 buffer->startpos += cpy;
371 device->queued_bytes -= cpy;
374 if (buffer->startpos == buffer->datalen) { /* packet is done, put it in the pool. */
375 device->buffer_queue_head = buffer->next;
376 SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
377 buffer->next = device->buffer_queue_pool;
378 device->buffer_queue_pool = buffer;
382 SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
384 if (len > 0) { /* fill any remaining space in the stream with silence. */
385 SDL_assert(device->buffer_queue_head == NULL);
386 SDL_memset(stream, device->spec.silence, len);
389 if (device->buffer_queue_head == NULL) {
390 device->buffer_queue_tail = NULL; /* in case we drained the queue entirely. */
395 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
397 SDL_AudioDevice *device = get_audio_device(devid);
398 const Uint8 *data = (const Uint8 *) _data;
399 SDL_AudioBufferQueue *orighead;
400 SDL_AudioBufferQueue *origtail;
405 return -1; /* get_audio_device() will have set the error state */
408 if (device->spec.callback != SDL_BufferQueueDrainCallback) {
409 return SDL_SetError("Audio device has a callback, queueing not allowed");
412 current_audio.impl.LockDevice(device);
414 orighead = device->buffer_queue_head;
415 origtail = device->buffer_queue_tail;
416 origlen = origtail ? origtail->datalen : 0;
419 SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
420 SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
421 if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
422 /* tail packet missing or completely full; we need a new packet. */
423 packet = device->buffer_queue_pool;
424 if (packet != NULL) {
425 /* we have one available in the pool. */
426 device->buffer_queue_pool = packet->next;
428 /* Have to allocate a new one! */
429 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
430 if (packet == NULL) {
431 /* uhoh, reset so we've queued nothing new, free what we can. */
433 packet = device->buffer_queue_head; /* whole queue. */
435 packet = origtail->next; /* what we added to existing queue. */
436 origtail->next = NULL;
437 origtail->datalen = origlen;
439 device->buffer_queue_head = orighead;
440 device->buffer_queue_tail = origtail;
441 device->buffer_queue_pool = NULL;
443 current_audio.impl.UnlockDevice(device);
445 free_audio_queue(packet); /* give back what we can. */
447 return SDL_OutOfMemory();
451 packet->startpos = 0;
454 SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
455 if (device->buffer_queue_tail == NULL) {
456 device->buffer_queue_head = packet;
458 device->buffer_queue_tail->next = packet;
460 device->buffer_queue_tail = packet;
463 datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
464 SDL_memcpy(packet->data + packet->datalen, data, datalen);
467 packet->datalen += datalen;
468 device->queued_bytes += datalen;
471 current_audio.impl.UnlockDevice(device);
477 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
480 SDL_AudioDevice *device = get_audio_device(devid);
482 /* Nothing to do unless we're set up for queueing. */
483 if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
484 current_audio.impl.LockDevice(device);
485 retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
486 current_audio.impl.UnlockDevice(device);
493 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
495 SDL_AudioDevice *device = get_audio_device(devid);
496 SDL_AudioBufferQueue *buffer = NULL;
498 return; /* nothing to do. */
501 /* Blank out the device and release the mutex. Free it afterwards. */
502 current_audio.impl.LockDevice(device);
503 buffer = device->buffer_queue_head;
504 device->buffer_queue_tail = NULL;
505 device->buffer_queue_head = NULL;
506 device->queued_bytes = 0;
507 current_audio.impl.UnlockDevice(device);
509 free_audio_queue(buffer);
513 #if defined(__ANDROID__)
514 #include <android/log.h>
517 /* The general mixing thread function */
519 SDL_RunAudio(void *devicep)
521 SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
525 void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
528 #if 0 /* !!! FIXME: rewrite/remove this streamer code. */
529 /* For streaming when the buffer sizes don't match up */
534 /* The audio mixing is always a high priority thread */
535 SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
537 /* Perform any thread setup */
538 device->threadid = SDL_ThreadID();
539 current_audio.impl.ThreadInit(device);
541 /* Set up the mixing function */
542 fill = device->spec.callback;
543 udata = device->spec.userdata;
545 /* By default do not stream */
546 device->use_streamer = 0;
548 if (device->convert.needed) {
549 #if 0 /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
550 /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
551 if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
552 /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
553 stream_max_len = 2 * device->spec.size;
554 if (device->convert.len_mult > device->convert.len_div) {
555 stream_max_len *= device->convert.len_mult;
556 stream_max_len /= device->convert.len_div;
558 if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
561 device->use_streamer = 1;
563 /* istream_len should be the length of what we grab from the callback and feed to conversion,
564 so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
567 device->spec.size * device->convert.len_div /
568 device->convert.len_mult;
571 stream_len = device->convert.len;
573 stream_len = device->spec.size;
576 /* Calculate the delay while paused */
577 delay = ((device->spec.samples * 1000) / device->spec.freq);
579 /* Determine if the streamer is necessary here */
580 #if 0 /* !!! FIXME: rewrite/remove this streamer code. */
581 if (device->use_streamer == 1) {
582 /* This code is almost the same as the old code. The difference is, instead of reading
583 directly from the callback into "stream", then converting and sending the audio off,
584 we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
585 However, reading and writing with streamer are done separately:
586 - We only call the callback and write to the streamer when the streamer does not
587 contain enough samples to output to the device.
588 - We only read from the streamer and tell the device to play when the streamer
589 does have enough samples to output.
590 This allows us to perform resampling in the conversion step, where the output of the
591 resampling process can be any number. We will have to see what a good size for the
592 stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
594 while (device->enabled) {
596 if (device->paused) {
601 /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
602 if (SDL_StreamLength(&device->streamer) < stream_len) {
604 if (device->convert.needed) {
605 if (device->convert.buf) {
606 istream = device->convert.buf;
611 /* FIXME: Ryan, this is probably wrong. I imagine we don't want to get
612 * a device buffer both here and below in the stream output.
614 istream = current_audio.impl.GetDeviceBuf(device);
615 if (istream == NULL) {
616 istream = device->fake_stream;
620 /* Read from the callback into the _input_ stream */
621 SDL_LockMutex(device->mixer_lock);
622 (*fill) (udata, istream, istream_len);
623 SDL_UnlockMutex(device->mixer_lock);
625 /* Convert the audio if necessary and write to the streamer */
626 if (device->convert.needed) {
627 SDL_ConvertAudio(&device->convert);
628 if (istream == NULL) {
629 istream = device->fake_stream;
631 /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
632 SDL_StreamWrite(&device->streamer, device->convert.buf,
633 device->convert.len_cvt);
635 SDL_StreamWrite(&device->streamer, istream, istream_len);
639 /* Only output audio if the streamer has enough to output */
640 if (SDL_StreamLength(&device->streamer) >= stream_len) {
641 /* Set up the output stream */
642 if (device->convert.needed) {
643 if (device->convert.buf) {
644 stream = device->convert.buf;
649 stream = current_audio.impl.GetDeviceBuf(device);
650 if (stream == NULL) {
651 stream = device->fake_stream;
655 /* Now read from the streamer */
656 SDL_StreamRead(&device->streamer, stream, stream_len);
658 /* Ready current buffer for play and change current buffer */
659 if (stream != device->fake_stream) {
660 current_audio.impl.PlayDevice(device);
661 /* Wait for an audio buffer to become available */
662 current_audio.impl.WaitDevice(device);
672 /* Otherwise, do not use the streamer. This is the old code. */
673 const int silence = (int) device->spec.silence;
675 /* Loop, filling the audio buffers */
676 while (device->enabled) {
678 /* Fill the current buffer with sound */
679 if (device->convert.needed) {
680 if (device->convert.buf) {
681 stream = device->convert.buf;
686 stream = current_audio.impl.GetDeviceBuf(device);
687 if (stream == NULL) {
688 stream = device->fake_stream;
692 SDL_LockMutex(device->mixer_lock);
693 if (device->paused) {
694 SDL_memset(stream, silence, stream_len);
696 (*fill) (udata, stream, stream_len);
698 SDL_UnlockMutex(device->mixer_lock);
700 /* Convert the audio if necessary */
701 if (device->convert.needed) {
702 SDL_ConvertAudio(&device->convert);
703 stream = current_audio.impl.GetDeviceBuf(device);
704 if (stream == NULL) {
705 stream = device->fake_stream;
707 SDL_memcpy(stream, device->convert.buf,
708 device->convert.len_cvt);
711 /* Ready current buffer for play and change current buffer */
712 if (stream != device->fake_stream) {
713 current_audio.impl.PlayDevice(device);
714 /* Wait for an audio buffer to become available */
715 current_audio.impl.WaitDevice(device);
722 /* Wait for the audio to drain.. */
723 current_audio.impl.WaitDone(device);
725 /* If necessary, deinit the streamer */
726 #if 0 /* !!! FIXME: rewrite/remove this streamer code. */
727 if (device->use_streamer == 1)
728 SDL_StreamDeinit(&device->streamer);
735 static SDL_AudioFormat
736 SDL_ParseAudioFormat(const char *string)
738 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
739 CHECK_FMT_STRING(U8);
740 CHECK_FMT_STRING(S8);
741 CHECK_FMT_STRING(U16LSB);
742 CHECK_FMT_STRING(S16LSB);
743 CHECK_FMT_STRING(U16MSB);
744 CHECK_FMT_STRING(S16MSB);
745 CHECK_FMT_STRING(U16SYS);
746 CHECK_FMT_STRING(S16SYS);
747 CHECK_FMT_STRING(U16);
748 CHECK_FMT_STRING(S16);
749 CHECK_FMT_STRING(S32LSB);
750 CHECK_FMT_STRING(S32MSB);
751 CHECK_FMT_STRING(S32SYS);
752 CHECK_FMT_STRING(S32);
753 CHECK_FMT_STRING(F32LSB);
754 CHECK_FMT_STRING(F32MSB);
755 CHECK_FMT_STRING(F32SYS);
756 CHECK_FMT_STRING(F32);
757 #undef CHECK_FMT_STRING
762 SDL_GetNumAudioDrivers(void)
764 return (SDL_arraysize(bootstrap) - 1);
768 SDL_GetAudioDriver(int index)
770 if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
771 return (bootstrap[index]->name);
777 SDL_AudioInit(const char *driver_name)
781 int tried_to_init = 0;
783 if (SDL_WasInit(SDL_INIT_AUDIO)) {
784 SDL_AudioQuit(); /* shutdown driver if already running. */
787 SDL_memset(¤t_audio, '\0', sizeof(current_audio));
788 SDL_memset(open_devices, '\0', sizeof(open_devices));
790 /* Select the proper audio driver */
791 if (driver_name == NULL) {
792 driver_name = SDL_getenv("SDL_AUDIODRIVER");
795 for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
796 /* make sure we should even try this driver before doing so... */
797 const AudioBootStrap *backend = bootstrap[i];
798 if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
799 (!driver_name && backend->demand_only)) {
804 SDL_memset(¤t_audio, 0, sizeof(current_audio));
805 current_audio.name = backend->name;
806 current_audio.desc = backend->desc;
807 initialized = backend->init(¤t_audio.impl);
811 /* specific drivers will set the error message if they fail... */
812 if (!tried_to_init) {
814 SDL_SetError("Audio target '%s' not available", driver_name);
816 SDL_SetError("No available audio device");
820 SDL_memset(¤t_audio, 0, sizeof(current_audio));
821 return (-1); /* No driver was available, so fail. */
824 finalize_audio_entry_points();
830 * Get the current audio driver name
833 SDL_GetCurrentAudioDriver()
835 return current_audio.name;
839 free_device_list(char ***devices, int *devCount)
842 if ((i > 0) && (*devices != NULL)) {
844 SDL_free((*devices)[i]);
855 void SDL_AddCaptureAudioDevice(const char *_name)
858 void *ptr = SDL_realloc(current_audio.inputDevices,
859 (current_audio.inputDeviceCount+1) * sizeof(char*));
861 return; /* oh well. */
864 current_audio.inputDevices = (char **) ptr;
865 name = SDL_strdup(_name); /* if this returns NULL, that's okay. */
866 current_audio.inputDevices[current_audio.inputDeviceCount++] = name;
870 void SDL_AddOutputAudioDevice(const char *_name)
873 void *ptr = SDL_realloc(current_audio.outputDevices,
874 (current_audio.outputDeviceCount+1) * sizeof(char*));
876 return; /* oh well. */
879 current_audio.outputDevices = (char **) ptr;
880 name = SDL_strdup(_name); /* if this returns NULL, that's okay. */
881 current_audio.outputDevices[current_audio.outputDeviceCount++] = name;
886 SDL_GetNumAudioDevices(int iscapture)
890 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
894 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
898 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
902 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
907 free_device_list(¤t_audio.inputDevices,
908 ¤t_audio.inputDeviceCount);
909 current_audio.impl.DetectDevices(iscapture, SDL_AddCaptureAudioDevice);
910 retval = current_audio.inputDeviceCount;
912 free_device_list(¤t_audio.outputDevices,
913 ¤t_audio.outputDeviceCount);
914 current_audio.impl.DetectDevices(iscapture, SDL_AddOutputAudioDevice);
915 retval = current_audio.outputDeviceCount;
923 SDL_GetAudioDeviceName(int index, int iscapture)
925 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
926 SDL_SetError("Audio subsystem is not initialized");
930 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
931 SDL_SetError("No capture support");
939 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
943 return DEFAULT_INPUT_DEVNAME;
946 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
950 return DEFAULT_OUTPUT_DEVNAME;
954 if (index >= current_audio.inputDeviceCount) {
957 return current_audio.inputDevices[index];
959 if (index >= current_audio.outputDeviceCount) {
962 return current_audio.outputDevices[index];
966 SDL_SetError("No such device");
972 close_audio_device(SDL_AudioDevice * device)
975 if (device->thread != NULL) {
976 SDL_WaitThread(device->thread, NULL);
978 if (device->mixer_lock != NULL) {
979 SDL_DestroyMutex(device->mixer_lock);
981 SDL_FreeAudioMem(device->fake_stream);
982 if (device->convert.needed) {
983 SDL_FreeAudioMem(device->convert.buf);
985 if (device->opened) {
986 current_audio.impl.CloseDevice(device);
990 free_audio_queue(device->buffer_queue_head);
991 free_audio_queue(device->buffer_queue_pool);
993 SDL_FreeAudioMem(device);
998 * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
999 * Fills in a sanitized copy in (prepared).
1000 * Returns non-zero if okay, zero on fatal parameters in (orig).
1003 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
1005 SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
1007 if (orig->freq == 0) {
1008 const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
1009 if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
1010 prepared->freq = 22050; /* a reasonable default */
1014 if (orig->format == 0) {
1015 const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
1016 if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
1017 prepared->format = AUDIO_S16; /* a reasonable default */
1021 switch (orig->channels) {
1023 const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
1024 if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
1025 prepared->channels = 2; /* a reasonable default */
1030 case 2: /* Stereo */
1031 case 4: /* surround */
1032 case 6: /* surround with center and lfe */
1035 SDL_SetError("Unsupported number of audio channels.");
1039 if (orig->samples == 0) {
1040 const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
1041 if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
1042 /* Pick a default of ~46 ms at desired frequency */
1043 /* !!! FIXME: remove this when the non-Po2 resampling is in. */
1044 const int samples = (prepared->freq / 1000) * 46;
1046 while (power2 < samples) {
1049 prepared->samples = power2;
1053 /* Calculate the silence and size of the audio specification */
1054 SDL_CalculateAudioSpec(prepared);
1059 static SDL_AudioDeviceID
1060 open_audio_device(const char *devname, int iscapture,
1061 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1062 int allowed_changes, int min_id)
1064 SDL_AudioDeviceID id = 0;
1065 SDL_AudioSpec _obtained;
1066 SDL_AudioDevice *device;
1070 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1071 SDL_SetError("Audio subsystem is not initialized");
1075 if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
1076 SDL_SetError("No capture support");
1081 obtained = &_obtained;
1083 if (!prepare_audiospec(desired, obtained)) {
1087 /* If app doesn't care about a specific device, let the user override. */
1088 if (devname == NULL) {
1089 devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
1093 * Catch device names at the high level for the simple case...
1094 * This lets us have a basic "device enumeration" for systems that
1095 * don't have multiple devices, but makes sure the device name is
1096 * always NULL when it hits the low level.
1098 * Also make sure that the simple case prevents multiple simultaneous
1099 * opens of the default system device.
1102 if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
1103 if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
1104 SDL_SetError("No such device");
1109 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1110 if ((open_devices[i]) && (open_devices[i]->iscapture)) {
1111 SDL_SetError("Audio device already open");
1117 if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
1118 if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
1119 SDL_SetError("No such device");
1124 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1125 if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
1126 SDL_SetError("Audio device already open");
1132 device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
1133 if (device == NULL) {
1138 device->spec = *obtained;
1139 device->enabled = 1;
1141 device->iscapture = iscapture;
1143 /* Create a semaphore for locking the sound buffers */
1144 if (!current_audio.impl.SkipMixerLock) {
1145 device->mixer_lock = SDL_CreateMutex();
1146 if (device->mixer_lock == NULL) {
1147 close_audio_device(device);
1148 SDL_SetError("Couldn't create mixer lock");
1153 /* force a device detection if we haven't done one yet. */
1154 if ( ((iscapture) && (current_audio.inputDevices == NULL)) ||
1155 ((!iscapture) && (current_audio.outputDevices == NULL)) ) {
1156 SDL_GetNumAudioDevices(iscapture);
1159 if (current_audio.impl.OpenDevice(device, devname, iscapture) < 0) {
1160 close_audio_device(device);
1165 /* Allocate a fake audio memory buffer */
1166 device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size);
1167 if (device->fake_stream == NULL) {
1168 close_audio_device(device);
1173 /* See if we need to do any conversion */
1174 build_cvt = SDL_FALSE;
1175 if (obtained->freq != device->spec.freq) {
1176 if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
1177 obtained->freq = device->spec.freq;
1179 build_cvt = SDL_TRUE;
1182 if (obtained->format != device->spec.format) {
1183 if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
1184 obtained->format = device->spec.format;
1186 build_cvt = SDL_TRUE;
1189 if (obtained->channels != device->spec.channels) {
1190 if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
1191 obtained->channels = device->spec.channels;
1193 build_cvt = SDL_TRUE;
1197 /* If the audio driver changes the buffer size, accept it.
1198 This needs to be done after the format is modified above,
1199 otherwise it might not have the correct buffer size.
1201 if (device->spec.samples != obtained->samples) {
1202 obtained->samples = device->spec.samples;
1203 SDL_CalculateAudioSpec(obtained);
1207 /* Build an audio conversion block */
1208 if (SDL_BuildAudioCVT(&device->convert,
1209 obtained->format, obtained->channels,
1211 device->spec.format, device->spec.channels,
1212 device->spec.freq) < 0) {
1213 close_audio_device(device);
1216 if (device->convert.needed) {
1217 device->convert.len = (int) (((double) device->spec.size) /
1218 device->convert.len_ratio);
1220 device->convert.buf =
1221 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
1222 device->convert.len_mult);
1223 if (device->convert.buf == NULL) {
1224 close_audio_device(device);
1231 if (device->spec.callback == NULL) { /* use buffer queueing? */
1232 /* pool a few packets to start. Enough for two callbacks. */
1233 const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
1234 const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
1235 const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
1236 for (i = 0; i < wantpackets; i++) {
1237 SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
1238 if (packet) { /* don't care if this fails, we'll deal later. */
1239 packet->datalen = 0;
1240 packet->startpos = 0;
1241 packet->next = device->buffer_queue_pool;
1242 device->buffer_queue_pool = packet;
1246 device->spec.callback = SDL_BufferQueueDrainCallback;
1247 device->spec.userdata = device;
1250 /* Find an available device ID and store the structure... */
1251 for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
1252 if (open_devices[id] == NULL) {
1253 open_devices[id] = device;
1258 if (id == SDL_arraysize(open_devices)) {
1259 SDL_SetError("Too many open audio devices");
1260 close_audio_device(device);
1264 /* Start the audio thread if necessary */
1265 if (!current_audio.impl.ProvidesOwnCallbackThread) {
1266 /* Start the audio thread */
1268 SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) (id + 1));
1269 /* !!! FIXME: this is nasty. */
1270 #if defined(__WIN32__) && !defined(HAVE_LIBC)
1271 #undef SDL_CreateThread
1273 device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
1275 device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
1278 device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
1280 if (device->thread == NULL) {
1281 SDL_CloseAudioDevice(id + 1);
1282 SDL_SetError("Couldn't create audio thread");
1292 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
1294 SDL_AudioDeviceID id = 0;
1296 /* Start up the audio driver, if necessary. This is legacy behaviour! */
1297 if (!SDL_WasInit(SDL_INIT_AUDIO)) {
1298 if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
1303 /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
1304 if (open_devices[0] != NULL) {
1305 SDL_SetError("Audio device is already opened");
1310 id = open_audio_device(NULL, 0, desired, obtained,
1311 SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
1313 id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
1316 SDL_assert((id == 0) || (id == 1));
1317 return ((id == 0) ? -1 : 0);
1321 SDL_OpenAudioDevice(const char *device, int iscapture,
1322 const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
1323 int allowed_changes)
1325 return open_audio_device(device, iscapture, desired, obtained,
1326 allowed_changes, 2);
1330 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
1332 SDL_AudioDevice *device = get_audio_device(devid);
1333 SDL_AudioStatus status = SDL_AUDIO_STOPPED;
1334 if (device && device->enabled) {
1335 if (device->paused) {
1336 status = SDL_AUDIO_PAUSED;
1338 status = SDL_AUDIO_PLAYING;
1346 SDL_GetAudioStatus(void)
1348 return SDL_GetAudioDeviceStatus(1);
1352 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
1354 SDL_AudioDevice *device = get_audio_device(devid);
1356 current_audio.impl.LockDevice(device);
1357 device->paused = pause_on;
1358 current_audio.impl.UnlockDevice(device);
1363 SDL_PauseAudio(int pause_on)
1365 SDL_PauseAudioDevice(1, pause_on);
1370 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
1372 /* Obtain a lock on the mixing buffers */
1373 SDL_AudioDevice *device = get_audio_device(devid);
1375 current_audio.impl.LockDevice(device);
1382 SDL_LockAudioDevice(1);
1386 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
1388 /* Obtain a lock on the mixing buffers */
1389 SDL_AudioDevice *device = get_audio_device(devid);
1391 current_audio.impl.UnlockDevice(device);
1396 SDL_UnlockAudio(void)
1398 SDL_UnlockAudioDevice(1);
1402 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
1404 SDL_AudioDevice *device = get_audio_device(devid);
1406 close_audio_device(device);
1407 open_devices[devid - 1] = NULL;
1412 SDL_CloseAudio(void)
1414 SDL_CloseAudioDevice(1);
1420 SDL_AudioDeviceID i;
1422 if (!current_audio.name) { /* not initialized?! */
1426 for (i = 0; i < SDL_arraysize(open_devices); i++) {
1427 if (open_devices[i] != NULL) {
1428 SDL_CloseAudioDevice(i+1);
1432 /* Free the driver data */
1433 current_audio.impl.Deinitialize();
1434 free_device_list(¤t_audio.outputDevices,
1435 ¤t_audio.outputDeviceCount);
1436 free_device_list(¤t_audio.inputDevices,
1437 ¤t_audio.inputDeviceCount);
1438 SDL_memset(¤t_audio, '\0', sizeof(current_audio));
1439 SDL_memset(open_devices, '\0', sizeof(open_devices));
1442 #define NUM_FORMATS 10
1443 static int format_idx;
1444 static int format_idx_sub;
1445 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
1446 {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1447 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1448 {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
1449 AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
1450 {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
1451 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1452 {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
1453 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1454 {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
1455 AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
1456 {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
1457 AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
1458 {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
1459 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1460 {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
1461 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1462 {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
1463 AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
1464 {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
1465 AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
1469 SDL_FirstAudioFormat(SDL_AudioFormat format)
1471 for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
1472 if (format_list[format_idx][0] == format) {
1477 return (SDL_NextAudioFormat());
1481 SDL_NextAudioFormat(void)
1483 if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
1486 return (format_list[format_idx][format_idx_sub++]);
1490 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
1492 switch (spec->format) {
1494 spec->silence = 0x80;
1497 spec->silence = 0x00;
1500 spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
1501 spec->size *= spec->channels;
1502 spec->size *= spec->samples;
1507 * Moved here from SDL_mixer.c, since it relies on internals of an opened
1508 * audio device (and is deprecated, by the way!).
1511 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
1513 /* Mix the user-level audio format */
1514 SDL_AudioDevice *device = get_audio_device(1);
1515 if (device != NULL) {
1516 SDL_AudioFormat format;
1517 if (device->convert.needed) {
1518 format = device->convert.src_format;
1520 format = device->spec.format;
1522 SDL_MixAudioFormat(dst, src, format, len, volume);
1526 /* vi: set ts=4 sw=4 expandtab: */