src/audio/SDL_audio.c
author Ryan C. Gordon
Wed, 18 Mar 2015 02:01:17 -0400
changeset 9394 bb28e5281770
parent 9393 ed79a66e57e5
child 9396 69c501ed36f3
permissions -rw-r--r--
Bunch of reworking to how we manage audio devices.

Device enumeration now happens at startup and then is managed exclusively
through hotplugging instead of full redetection. The device name list now has
a unique "handle" associated with each item and SDL will pass this to the
backend so they don't have to figure out how a human readable name maps to
real hardware for a second time.

Other cleanups, fixes, improvements, plus all the audio backends updated to
the new interface...largely untested at this point, though.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 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_audiomem.h"
    29 #include "SDL_sysaudio.h"
    30 
    31 #define _THIS SDL_AudioDevice *_this
    32 
    33 static SDL_AudioDriver current_audio;
    34 static SDL_AudioDevice *open_devices[16];
    35 
    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"
    39 
    40 
    41 /*
    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.
    45  */
    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;
    73 
    74 
    75 /* Available audio drivers */
    76 static const AudioBootStrap *const bootstrap[] = {
    77 #if SDL_AUDIO_DRIVER_PULSEAUDIO
    78     &PULSEAUDIO_bootstrap,
    79 #endif
    80 #if SDL_AUDIO_DRIVER_ALSA
    81     &ALSA_bootstrap,
    82 #endif
    83 #if SDL_AUDIO_DRIVER_SNDIO
    84     &SNDIO_bootstrap,
    85 #endif
    86 #if SDL_AUDIO_DRIVER_BSD
    87     &BSD_AUDIO_bootstrap,
    88 #endif
    89 #if SDL_AUDIO_DRIVER_OSS
    90     &DSP_bootstrap,
    91 #endif
    92 #if SDL_AUDIO_DRIVER_QSA
    93     &QSAAUDIO_bootstrap,
    94 #endif
    95 #if SDL_AUDIO_DRIVER_SUNAUDIO
    96     &SUNAUDIO_bootstrap,
    97 #endif
    98 #if SDL_AUDIO_DRIVER_ARTS
    99     &ARTS_bootstrap,
   100 #endif
   101 #if SDL_AUDIO_DRIVER_ESD
   102     &ESD_bootstrap,
   103 #endif
   104 #if SDL_AUDIO_DRIVER_NACL
   105    &NACLAUD_bootstrap,
   106 #endif
   107 #if SDL_AUDIO_DRIVER_NAS
   108     &NAS_bootstrap,
   109 #endif
   110 #if SDL_AUDIO_DRIVER_XAUDIO2
   111     &XAUDIO2_bootstrap,
   112 #endif
   113 #if SDL_AUDIO_DRIVER_DSOUND
   114     &DSOUND_bootstrap,
   115 #endif
   116 #if SDL_AUDIO_DRIVER_WINMM
   117     &WINMM_bootstrap,
   118 #endif
   119 #if SDL_AUDIO_DRIVER_PAUDIO
   120     &PAUDIO_bootstrap,
   121 #endif
   122 #if SDL_AUDIO_DRIVER_HAIKU
   123     &HAIKUAUDIO_bootstrap,
   124 #endif
   125 #if SDL_AUDIO_DRIVER_COREAUDIO
   126     &COREAUDIO_bootstrap,
   127 #endif
   128 #if SDL_AUDIO_DRIVER_DISK
   129     &DISKAUD_bootstrap,
   130 #endif
   131 #if SDL_AUDIO_DRIVER_DUMMY
   132     &DUMMYAUD_bootstrap,
   133 #endif
   134 #if SDL_AUDIO_DRIVER_FUSIONSOUND
   135     &FUSIONSOUND_bootstrap,
   136 #endif
   137 #if SDL_AUDIO_DRIVER_ANDROID
   138     &ANDROIDAUD_bootstrap,
   139 #endif
   140 #if SDL_AUDIO_DRIVER_PSP
   141     &PSPAUD_bootstrap,
   142 #endif
   143 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
   144     &EmscriptenAudio_bootstrap,
   145 #endif
   146     NULL
   147 };
   148 
   149 static SDL_AudioDevice *
   150 get_audio_device(SDL_AudioDeviceID id)
   151 {
   152     id--;
   153     if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
   154         SDL_SetError("Invalid audio device ID");
   155         return NULL;
   156     }
   157 
   158     return open_devices[id];
   159 }
   160 
   161 
   162 /* stubs for audio drivers that don't need a specific entry point... */
   163 static void
   164 SDL_AudioDetectDevices_Default(void)
   165 {
   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);
   169 
   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));
   173     }
   174 }
   175 
   176 static void
   177 SDL_AudioThreadInit_Default(_THIS)
   178 {                               /* no-op. */
   179 }
   180 
   181 static void
   182 SDL_AudioWaitDevice_Default(_THIS)
   183 {                               /* no-op. */
   184 }
   185 
   186 static void
   187 SDL_AudioPlayDevice_Default(_THIS)
   188 {                               /* no-op. */
   189 }
   190 
   191 static int
   192 SDL_AudioGetPendingBytes_Default(_THIS)
   193 {
   194     return 0;
   195 }
   196 
   197 static Uint8 *
   198 SDL_AudioGetDeviceBuf_Default(_THIS)
   199 {
   200     return NULL;
   201 }
   202 
   203 static void
   204 SDL_AudioWaitDone_Default(_THIS)
   205 {                               /* no-op. */
   206 }
   207 
   208 static void
   209 SDL_AudioCloseDevice_Default(_THIS)
   210 {                               /* no-op. */
   211 }
   212 
   213 static void
   214 SDL_AudioDeinitialize_Default(void)
   215 {                               /* no-op. */
   216 }
   217 
   218 static void
   219 SDL_AudioFreeDeviceHandle_Default(void *handle)
   220 {                               /* no-op. */
   221 }
   222 
   223 
   224 static int
   225 SDL_AudioOpenDevice_Default(_THIS, void *handle, const char *devname, int iscapture)
   226 {
   227     return SDL_Unsupported();
   228 }
   229 
   230 static SDL_INLINE SDL_bool
   231 is_in_audio_device_thread(SDL_AudioDevice * device)
   232 {
   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)) {
   238         return SDL_TRUE;
   239     }
   240 
   241     return SDL_FALSE;
   242 }
   243 
   244 static void
   245 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
   246 {
   247     if (!is_in_audio_device_thread(device)) {
   248         SDL_LockMutex(device->mixer_lock);
   249     }
   250 }
   251 
   252 static void
   253 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
   254 {
   255     if (!is_in_audio_device_thread(device)) {
   256         SDL_UnlockMutex(device->mixer_lock);
   257     }
   258 }
   259 
   260 
   261 static void
   262 finalize_audio_entry_points(void)
   263 {
   264     /*
   265      * Fill in stub functions for unused driver entry points. This lets us
   266      *  blindly call them without having to check for validity first.
   267      */
   268 
   269 #define FILL_STUB(x) \
   270         if (current_audio.impl.x == NULL) { \
   271             current_audio.impl.x = SDL_Audio##x##_Default; \
   272         }
   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);
   280     FILL_STUB(WaitDone);
   281     FILL_STUB(CloseDevice);
   282     FILL_STUB(LockDevice);
   283     FILL_STUB(UnlockDevice);
   284     FILL_STUB(FreeDeviceHandle);
   285     FILL_STUB(Deinitialize);
   286 #undef FILL_STUB
   287 }
   288 
   289 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   290 /* Streaming functions (for when the input and output buffer sizes are different) */
   291 /* Write [length] bytes from buf into the streamer */
   292 static void
   293 SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length)
   294 {
   295     int i;
   296 
   297     for (i = 0; i < length; ++i) {
   298         stream->buffer[stream->write_pos] = buf[i];
   299         ++stream->write_pos;
   300     }
   301 }
   302 
   303 /* Read [length] bytes out of the streamer into buf */
   304 static void
   305 SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
   306 {
   307     int i;
   308 
   309     for (i = 0; i < length; ++i) {
   310         buf[i] = stream->buffer[stream->read_pos];
   311         ++stream->read_pos;
   312     }
   313 }
   314 
   315 static int
   316 SDL_StreamLength(SDL_AudioStreamer * stream)
   317 {
   318     return (stream->write_pos - stream->read_pos) % stream->max_len;
   319 }
   320 
   321 /* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */
   322 #if 0
   323 static int
   324 SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
   325 {
   326     /* First try to allocate the buffer */
   327     stream->buffer = (Uint8 *) SDL_malloc(max_len);
   328     if (stream->buffer == NULL) {
   329         return -1;
   330     }
   331 
   332     stream->max_len = max_len;
   333     stream->read_pos = 0;
   334     stream->write_pos = 0;
   335 
   336     /* Zero out the buffer */
   337     SDL_memset(stream->buffer, silence, max_len);
   338 
   339     return 0;
   340 }
   341 #endif
   342 
   343 /* Deinitialize the stream simply by freeing the buffer */
   344 static void
   345 SDL_StreamDeinit(SDL_AudioStreamer * stream)
   346 {
   347     SDL_free(stream->buffer);
   348 }
   349 #endif
   350 
   351 /* device hotplug support... */
   352 
   353 static int
   354 add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
   355 {
   356     int retval = -1;
   357     const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
   358     SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
   359     if (item == NULL) {
   360         return -1;
   361     }
   362 
   363     SDL_assert(handle != NULL);
   364 
   365     item->handle = handle;
   366     SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
   367 
   368     SDL_LockMutex(current_audio.detectionLock);
   369     item->next = *devices;
   370     *devices = item;
   371     retval = (*devCount)++;
   372     SDL_UnlockMutex(current_audio.detectionLock);
   373 
   374     return retval;
   375 }
   376 
   377 static SDL_INLINE int
   378 add_capture_device(const char *name, void *handle)
   379 {
   380     /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
   381     return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
   382 }
   383 
   384 static SDL_INLINE int
   385 add_output_device(const char *name, void *handle)
   386 {
   387     return add_audio_device(name, handle, &current_audio.outputDevices, &current_audio.outputDeviceCount);
   388 }
   389 
   390 static void
   391 free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
   392 {
   393     SDL_AudioDeviceItem *item, *next;
   394     for (item = *devices; item != NULL; item = next) {
   395         next = item->next;
   396         if (item->handle != NULL) {
   397             current_audio.impl.FreeDeviceHandle(item->handle);
   398         }
   399         SDL_free(item);
   400     }
   401     *devices = NULL;
   402     *devCount = 0;
   403 }
   404 
   405 
   406 /* The audio backends call this when a new device is plugged in. */
   407 void
   408 SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
   409 {
   410     const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
   411     if (device_index != -1) {
   412         /* Post the event, if desired */
   413         if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
   414             SDL_Event event;
   415             event.adevice.type = SDL_AUDIODEVICEADDED;
   416             event.adevice.which = device_index;
   417             event.adevice.iscapture = iscapture;
   418             SDL_PushEvent(&event);
   419         }
   420     }
   421 }
   422 
   423 /* The audio backends call this when a currently-opened device is lost. */
   424 void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
   425 {
   426     SDL_assert(get_audio_device(device->id) == device);
   427     SDL_assert(device->enabled);  /* called more than once?! */
   428 
   429     /* Ends the audio callback and mark the device as STOPPED, but the
   430        app still needs to close the device to free resources. */
   431     current_audio.impl.LockDevice(device);
   432     device->enabled = 0;
   433     current_audio.impl.UnlockDevice(device);
   434 
   435     /* Post the event, if desired */
   436     if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
   437         SDL_Event event;
   438         event.adevice.type = SDL_AUDIODEVICEREMOVED;
   439         event.adevice.which = device->id;
   440         event.adevice.iscapture = device->iscapture ? 1 : 0;
   441         SDL_PushEvent(&event);
   442     }
   443 }
   444 
   445 static void
   446 mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
   447 {
   448     SDL_AudioDeviceItem *item;
   449     SDL_assert(handle != NULL);
   450     for (item = devices; item != NULL; item = item->next) {
   451         if (item->handle == handle) {
   452             item->handle = NULL;
   453             *removedFlag = SDL_TRUE;
   454             return;
   455         }
   456     }
   457 }
   458 
   459 /* The audio backends call this when a device is removed from the system. */
   460 void
   461 SDL_RemoveAudioDevice(void *handle)
   462 {
   463     SDL_LockMutex(current_audio.detectionLock);
   464     mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
   465     mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
   466     SDL_UnlockMutex(current_audio.detectionLock);
   467     current_audio.impl.FreeDeviceHandle(handle);
   468 }
   469 
   470 
   471 
   472 /* buffer queueing support... */
   473 
   474 /* this expects that you managed thread safety elsewhere. */
   475 static void
   476 free_audio_queue(SDL_AudioBufferQueue *buffer)
   477 {
   478     while (buffer) {
   479         SDL_AudioBufferQueue *next = buffer->next;
   480         SDL_free(buffer);
   481         buffer = next;
   482     }
   483 }
   484 
   485 static void SDLCALL
   486 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
   487 {
   488     /* this function always holds the mixer lock before being called. */
   489     Uint32 len = (Uint32) _len;
   490     SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
   491     SDL_AudioBufferQueue *buffer;
   492 
   493     SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
   494     SDL_assert(_len >= 0);  /* this shouldn't ever happen, right?! */
   495 
   496     while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
   497         const Uint32 avail = buffer->datalen - buffer->startpos;
   498         const Uint32 cpy = SDL_min(len, avail);
   499         SDL_assert(device->queued_bytes >= avail);
   500 
   501         SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
   502         buffer->startpos += cpy;
   503         stream += cpy;
   504         device->queued_bytes -= cpy;
   505         len -= cpy;
   506 
   507         if (buffer->startpos == buffer->datalen) {  /* packet is done, put it in the pool. */
   508             device->buffer_queue_head = buffer->next;
   509             SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
   510             buffer->next = device->buffer_queue_pool;
   511             device->buffer_queue_pool = buffer;
   512         }
   513     }
   514 
   515     SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
   516 
   517     if (len > 0) {  /* fill any remaining space in the stream with silence. */
   518         SDL_assert(device->buffer_queue_head == NULL);
   519         SDL_memset(stream, device->spec.silence, len);
   520     }
   521 
   522     if (device->buffer_queue_head == NULL) {
   523         device->buffer_queue_tail = NULL;  /* in case we drained the queue entirely. */
   524     }
   525 }
   526 
   527 int
   528 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
   529 {
   530     SDL_AudioDevice *device = get_audio_device(devid);
   531     const Uint8 *data = (const Uint8 *) _data;
   532     SDL_AudioBufferQueue *orighead;
   533     SDL_AudioBufferQueue *origtail;
   534     Uint32 origlen;
   535     Uint32 datalen;
   536 
   537     if (!device) {
   538         return -1;  /* get_audio_device() will have set the error state */
   539     }
   540 
   541     if (device->spec.callback != SDL_BufferQueueDrainCallback) {
   542         return SDL_SetError("Audio device has a callback, queueing not allowed");
   543     }
   544 
   545     current_audio.impl.LockDevice(device);
   546 
   547     orighead = device->buffer_queue_head;
   548     origtail = device->buffer_queue_tail;
   549     origlen = origtail ? origtail->datalen : 0;
   550 
   551     while (len > 0) {
   552         SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
   553         SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
   554         if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
   555             /* tail packet missing or completely full; we need a new packet. */
   556             packet = device->buffer_queue_pool;
   557             if (packet != NULL) {
   558                 /* we have one available in the pool. */
   559                 device->buffer_queue_pool = packet->next;
   560             } else {
   561                 /* Have to allocate a new one! */
   562                 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
   563                 if (packet == NULL) {
   564                     /* uhoh, reset so we've queued nothing new, free what we can. */
   565                     if (!origtail) {
   566                         packet = device->buffer_queue_head;  /* whole queue. */
   567                     } else {
   568                         packet = origtail->next;  /* what we added to existing queue. */
   569                         origtail->next = NULL;
   570                         origtail->datalen = origlen;
   571                     }
   572                     device->buffer_queue_head = orighead;
   573                     device->buffer_queue_tail = origtail;
   574                     device->buffer_queue_pool = NULL;
   575 
   576                     current_audio.impl.UnlockDevice(device);
   577 
   578                     free_audio_queue(packet);  /* give back what we can. */
   579 
   580                     return SDL_OutOfMemory();
   581                 }
   582             }
   583             packet->datalen = 0;
   584             packet->startpos = 0;
   585             packet->next = NULL;
   586 
   587             SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
   588             if (device->buffer_queue_tail == NULL) {
   589                 device->buffer_queue_head = packet;
   590             } else {
   591                 device->buffer_queue_tail->next = packet;
   592             }
   593             device->buffer_queue_tail = packet;
   594         }
   595 
   596         datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
   597         SDL_memcpy(packet->data + packet->datalen, data, datalen);
   598         data += datalen;
   599         len -= datalen;
   600         packet->datalen += datalen;
   601         device->queued_bytes += datalen;
   602     }
   603 
   604     current_audio.impl.UnlockDevice(device);
   605 
   606     return 0;
   607 }
   608 
   609 Uint32
   610 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
   611 {
   612     Uint32 retval = 0;
   613     SDL_AudioDevice *device = get_audio_device(devid);
   614 
   615     /* Nothing to do unless we're set up for queueing. */
   616     if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
   617         current_audio.impl.LockDevice(device);
   618         retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
   619         current_audio.impl.UnlockDevice(device);
   620     }
   621 
   622     return retval;
   623 }
   624 
   625 void
   626 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
   627 {
   628     SDL_AudioDevice *device = get_audio_device(devid);
   629     SDL_AudioBufferQueue *buffer = NULL;
   630     if (!device) {
   631         return;  /* nothing to do. */
   632     }
   633 
   634     /* Blank out the device and release the mutex. Free it afterwards. */
   635     current_audio.impl.LockDevice(device);
   636     buffer = device->buffer_queue_head;
   637     device->buffer_queue_tail = NULL;
   638     device->buffer_queue_head = NULL;
   639     device->queued_bytes = 0;
   640     current_audio.impl.UnlockDevice(device);
   641 
   642     free_audio_queue(buffer);
   643 }
   644 
   645 
   646 #if defined(__ANDROID__)
   647 #include <android/log.h>
   648 #endif
   649 
   650 /* The general mixing thread function */
   651 int SDLCALL
   652 SDL_RunAudio(void *devicep)
   653 {
   654     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
   655     Uint8 *stream;
   656     int stream_len;
   657     void *udata;
   658     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   659     Uint32 delay;
   660 
   661 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   662     /* For streaming when the buffer sizes don't match up */
   663     Uint8 *istream;
   664     int istream_len = 0;
   665 #endif
   666 
   667     /* The audio mixing is always a high priority thread */
   668     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
   669 
   670     /* Perform any thread setup */
   671     device->threadid = SDL_ThreadID();
   672     current_audio.impl.ThreadInit(device);
   673 
   674     /* Set up the mixing function */
   675     fill = device->spec.callback;
   676     udata = device->spec.userdata;
   677 
   678     /* By default do not stream */
   679     device->use_streamer = 0;
   680 
   681     if (device->convert.needed) {
   682 #if 0                           /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
   683         /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
   684         if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
   685             /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
   686             stream_max_len = 2 * device->spec.size;
   687             if (device->convert.len_mult > device->convert.len_div) {
   688                 stream_max_len *= device->convert.len_mult;
   689                 stream_max_len /= device->convert.len_div;
   690             }
   691             if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
   692                 0)
   693                 return -1;
   694             device->use_streamer = 1;
   695 
   696             /* istream_len should be the length of what we grab from the callback and feed to conversion,
   697                so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
   698              */
   699             istream_len =
   700                 device->spec.size * device->convert.len_div /
   701                 device->convert.len_mult;
   702         }
   703 #endif
   704         stream_len = device->convert.len;
   705     } else {
   706         stream_len = device->spec.size;
   707     }
   708 
   709     /* Calculate the delay while paused */
   710     delay = ((device->spec.samples * 1000) / device->spec.freq);
   711 
   712     /* Determine if the streamer is necessary here */
   713 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   714     if (device->use_streamer == 1) {
   715         /* This code is almost the same as the old code. The difference is, instead of reading
   716            directly from the callback into "stream", then converting and sending the audio off,
   717            we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
   718            However, reading and writing with streamer are done separately:
   719            - We only call the callback and write to the streamer when the streamer does not
   720            contain enough samples to output to the device.
   721            - We only read from the streamer and tell the device to play when the streamer
   722            does have enough samples to output.
   723            This allows us to perform resampling in the conversion step, where the output of the
   724            resampling process can be any number. We will have to see what a good size for the
   725            stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
   726          */
   727         while (device->enabled) {
   728 
   729             if (device->paused) {
   730                 SDL_Delay(delay);
   731                 continue;
   732             }
   733 
   734             /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
   735             if (SDL_StreamLength(&device->streamer) < stream_len) {
   736                 /* Set up istream */
   737                 if (device->convert.needed) {
   738                     if (device->convert.buf) {
   739                         istream = device->convert.buf;
   740                     } else {
   741                         continue;
   742                     }
   743                 } else {
   744 /* FIXME: Ryan, this is probably wrong.  I imagine we don't want to get
   745  * a device buffer both here and below in the stream output.
   746  */
   747                     istream = current_audio.impl.GetDeviceBuf(device);
   748                     if (istream == NULL) {
   749                         istream = device->fake_stream;
   750                     }
   751                 }
   752 
   753                 /* Read from the callback into the _input_ stream */
   754                 // !!! FIXME: this should be LockDevice.
   755                 SDL_LockMutex(device->mixer_lock);
   756                 (*fill) (udata, istream, istream_len);
   757                 SDL_UnlockMutex(device->mixer_lock);
   758 
   759                 /* Convert the audio if necessary and write to the streamer */
   760                 if (device->convert.needed) {
   761                     SDL_ConvertAudio(&device->convert);
   762                     if (istream == NULL) {
   763                         istream = device->fake_stream;
   764                     }
   765                     /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
   766                     SDL_StreamWrite(&device->streamer, device->convert.buf,
   767                                     device->convert.len_cvt);
   768                 } else {
   769                     SDL_StreamWrite(&device->streamer, istream, istream_len);
   770                 }
   771             }
   772 
   773             /* Only output audio if the streamer has enough to output */
   774             if (SDL_StreamLength(&device->streamer) >= stream_len) {
   775                 /* Set up the output stream */
   776                 if (device->convert.needed) {
   777                     if (device->convert.buf) {
   778                         stream = device->convert.buf;
   779                     } else {
   780                         continue;
   781                     }
   782                 } else {
   783                     stream = current_audio.impl.GetDeviceBuf(device);
   784                     if (stream == NULL) {
   785                         stream = device->fake_stream;
   786                     }
   787                 }
   788 
   789                 /* Now read from the streamer */
   790                 SDL_StreamRead(&device->streamer, stream, stream_len);
   791 
   792                 /* Ready current buffer for play and change current buffer */
   793                 if (stream != device->fake_stream) {
   794                     current_audio.impl.PlayDevice(device);
   795                     /* Wait for an audio buffer to become available */
   796                     current_audio.impl.WaitDevice(device);
   797                 } else {
   798                     SDL_Delay(delay);
   799                 }
   800             }
   801 
   802         }
   803     } else
   804 #endif
   805     {
   806         /* Otherwise, do not use the streamer. This is the old code. */
   807         const int silence = (int) device->spec.silence;
   808 
   809         /* Loop, filling the audio buffers */
   810         while (device->enabled) {
   811 
   812             /* Fill the current buffer with sound */
   813             if (device->convert.needed) {
   814                 if (device->convert.buf) {
   815                     stream = device->convert.buf;
   816                 } else {
   817                     continue;
   818                 }
   819             } else {
   820                 stream = current_audio.impl.GetDeviceBuf(device);
   821                 if (stream == NULL) {
   822                     stream = device->fake_stream;
   823                 }
   824             }
   825 
   826             /* !!! FIXME: this should be LockDevice. */
   827             SDL_LockMutex(device->mixer_lock);
   828 
   829             /* Check again, in case device was removed while a lock was held. */
   830             if (!device->enabled) {
   831                 SDL_UnlockMutex(device->mixer_lock);
   832                 break;
   833             }
   834 
   835             if (device->paused) {
   836                 SDL_memset(stream, silence, stream_len);
   837             } else {
   838                 (*fill) (udata, stream, stream_len);
   839             }
   840             SDL_UnlockMutex(device->mixer_lock);
   841 
   842             /* Convert the audio if necessary */
   843             if (device->convert.needed) {
   844                 SDL_ConvertAudio(&device->convert);
   845                 stream = current_audio.impl.GetDeviceBuf(device);
   846                 if (stream == NULL) {
   847                     stream = device->fake_stream;
   848                 }
   849                 SDL_memcpy(stream, device->convert.buf,
   850                            device->convert.len_cvt);
   851             }
   852 
   853             /* Ready current buffer for play and change current buffer */
   854             if (stream != device->fake_stream) {
   855                 current_audio.impl.PlayDevice(device);
   856                 /* Wait for an audio buffer to become available */
   857                 current_audio.impl.WaitDevice(device);
   858             } else {
   859                 SDL_Delay(delay);
   860             }
   861         }
   862     }
   863 
   864     /* Wait for the audio to drain.. */
   865     current_audio.impl.WaitDone(device);
   866 
   867     /* If necessary, deinit the streamer */
   868 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   869     if (device->use_streamer == 1)
   870         SDL_StreamDeinit(&device->streamer);
   871 #endif
   872 
   873     return 0;
   874 }
   875 
   876 
   877 static SDL_AudioFormat
   878 SDL_ParseAudioFormat(const char *string)
   879 {
   880 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
   881     CHECK_FMT_STRING(U8);
   882     CHECK_FMT_STRING(S8);
   883     CHECK_FMT_STRING(U16LSB);
   884     CHECK_FMT_STRING(S16LSB);
   885     CHECK_FMT_STRING(U16MSB);
   886     CHECK_FMT_STRING(S16MSB);
   887     CHECK_FMT_STRING(U16SYS);
   888     CHECK_FMT_STRING(S16SYS);
   889     CHECK_FMT_STRING(U16);
   890     CHECK_FMT_STRING(S16);
   891     CHECK_FMT_STRING(S32LSB);
   892     CHECK_FMT_STRING(S32MSB);
   893     CHECK_FMT_STRING(S32SYS);
   894     CHECK_FMT_STRING(S32);
   895     CHECK_FMT_STRING(F32LSB);
   896     CHECK_FMT_STRING(F32MSB);
   897     CHECK_FMT_STRING(F32SYS);
   898     CHECK_FMT_STRING(F32);
   899 #undef CHECK_FMT_STRING
   900     return 0;
   901 }
   902 
   903 int
   904 SDL_GetNumAudioDrivers(void)
   905 {
   906     return SDL_arraysize(bootstrap) - 1;
   907 }
   908 
   909 const char *
   910 SDL_GetAudioDriver(int index)
   911 {
   912     if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
   913         return bootstrap[index]->name;
   914     }
   915     return NULL;
   916 }
   917 
   918 int
   919 SDL_AudioInit(const char *driver_name)
   920 {
   921     int i = 0;
   922     int initialized = 0;
   923     int tried_to_init = 0;
   924 
   925     if (SDL_WasInit(SDL_INIT_AUDIO)) {
   926         SDL_AudioQuit();        /* shutdown driver if already running. */
   927     }
   928 
   929     SDL_zero(current_audio);
   930     SDL_zero(open_devices);
   931 
   932     /* Select the proper audio driver */
   933     if (driver_name == NULL) {
   934         driver_name = SDL_getenv("SDL_AUDIODRIVER");
   935     }
   936 
   937     for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
   938         /* make sure we should even try this driver before doing so... */
   939         const AudioBootStrap *backend = bootstrap[i];
   940         if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
   941             (!driver_name && backend->demand_only)) {
   942             continue;
   943         }
   944 
   945         tried_to_init = 1;
   946         SDL_zero(current_audio);
   947         current_audio.name = backend->name;
   948         current_audio.desc = backend->desc;
   949         initialized = backend->init(&current_audio.impl);
   950     }
   951 
   952     if (!initialized) {
   953         /* specific drivers will set the error message if they fail... */
   954         if (!tried_to_init) {
   955             if (driver_name) {
   956                 SDL_SetError("Audio target '%s' not available", driver_name);
   957             } else {
   958                 SDL_SetError("No available audio device");
   959             }
   960         }
   961 
   962         SDL_zero(current_audio);
   963         return -1;            /* No driver was available, so fail. */
   964     }
   965 
   966     current_audio.detectionLock = SDL_CreateMutex();
   967 
   968     finalize_audio_entry_points();
   969 
   970     /* Make sure we have a list of devices available at startup. */
   971     current_audio.impl.DetectDevices();
   972 
   973     return 0;
   974 }
   975 
   976 /*
   977  * Get the current audio driver name
   978  */
   979 const char *
   980 SDL_GetCurrentAudioDriver()
   981 {
   982     return current_audio.name;
   983 }
   984 
   985 /* Clean out devices that we've removed but had to keep around for stability. */
   986 static void
   987 clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
   988 {
   989     SDL_AudioDeviceItem *item = *devices;
   990     SDL_AudioDeviceItem *prev = NULL;
   991     int total = 0;
   992 
   993     while (item) {
   994         SDL_AudioDeviceItem *next = item->next;
   995         if (item->handle != NULL) {
   996             total++;
   997             prev = item;
   998         } else {
   999             if (prev) {
  1000                 prev->next = next;
  1001             } else {
  1002                 *devices = next;
  1003             }
  1004             SDL_free(item);
  1005         }
  1006         item = next;
  1007     }
  1008 
  1009     *devCount = total;
  1010     *removedFlag = SDL_FALSE;
  1011 }
  1012 
  1013 
  1014 int
  1015 SDL_GetNumAudioDevices(int iscapture)
  1016 {
  1017     int retval = 0;
  1018 
  1019     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1020         return -1;
  1021     }
  1022 
  1023     SDL_LockMutex(current_audio.detectionLock);
  1024     if (iscapture && current_audio.captureDevicesRemoved) {
  1025         clean_out_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
  1026     }
  1027 
  1028     if (!iscapture && current_audio.outputDevicesRemoved) {
  1029         clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
  1030         current_audio.outputDevicesRemoved = SDL_FALSE;
  1031     }
  1032 
  1033     retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
  1034     SDL_UnlockMutex(current_audio.detectionLock);
  1035 
  1036     return retval;
  1037 }
  1038 
  1039 
  1040 const char *
  1041 SDL_GetAudioDeviceName(int index, int iscapture)
  1042 {
  1043     const char *retval = NULL;
  1044 
  1045     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1046         SDL_SetError("Audio subsystem is not initialized");
  1047         return NULL;
  1048     }
  1049 
  1050     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
  1051         SDL_SetError("No capture support");
  1052         return NULL;
  1053     }
  1054 
  1055     if (index >= 0) {
  1056         SDL_AudioDeviceItem *item;
  1057         int i;
  1058 
  1059         SDL_LockMutex(current_audio.detectionLock);
  1060         item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
  1061         i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
  1062         if (index < i) {
  1063             for (i--; i > index; i--, item = item->next) {
  1064                 SDL_assert(item != NULL);
  1065             }
  1066             SDL_assert(item != NULL);
  1067             retval = item->name;
  1068         }
  1069         SDL_UnlockMutex(current_audio.detectionLock);
  1070     }
  1071 
  1072     if (retval == NULL) {
  1073         SDL_SetError("No such device");
  1074     }
  1075 
  1076     return retval;
  1077 }
  1078 
  1079 
  1080 static void
  1081 close_audio_device(SDL_AudioDevice * device)
  1082 {
  1083     device->enabled = 0;
  1084     if (device->thread != NULL) {
  1085         SDL_WaitThread(device->thread, NULL);
  1086     }
  1087     if (device->mixer_lock != NULL) {
  1088         SDL_DestroyMutex(device->mixer_lock);
  1089     }
  1090     SDL_FreeAudioMem(device->fake_stream);
  1091     if (device->convert.needed) {
  1092         SDL_FreeAudioMem(device->convert.buf);
  1093     }
  1094     if (device->opened) {
  1095         current_audio.impl.CloseDevice(device);
  1096         device->opened = 0;
  1097     }
  1098 
  1099     free_audio_queue(device->buffer_queue_head);
  1100     free_audio_queue(device->buffer_queue_pool);
  1101 
  1102     SDL_FreeAudioMem(device);
  1103 }
  1104 
  1105 
  1106 /*
  1107  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
  1108  *  Fills in a sanitized copy in (prepared).
  1109  *  Returns non-zero if okay, zero on fatal parameters in (orig).
  1110  */
  1111 static int
  1112 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
  1113 {
  1114     SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
  1115 
  1116     if (orig->freq == 0) {
  1117         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
  1118         if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
  1119             prepared->freq = 22050;     /* a reasonable default */
  1120         }
  1121     }
  1122 
  1123     if (orig->format == 0) {
  1124         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
  1125         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
  1126             prepared->format = AUDIO_S16;       /* a reasonable default */
  1127         }
  1128     }
  1129 
  1130     switch (orig->channels) {
  1131     case 0:{
  1132             const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
  1133             if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
  1134                 prepared->channels = 2; /* a reasonable default */
  1135             }
  1136             break;
  1137         }
  1138     case 1:                    /* Mono */
  1139     case 2:                    /* Stereo */
  1140     case 4:                    /* surround */
  1141     case 6:                    /* surround with center and lfe */
  1142         break;
  1143     default:
  1144         SDL_SetError("Unsupported number of audio channels.");
  1145         return 0;
  1146     }
  1147 
  1148     if (orig->samples == 0) {
  1149         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
  1150         if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
  1151             /* Pick a default of ~46 ms at desired frequency */
  1152             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
  1153             const int samples = (prepared->freq / 1000) * 46;
  1154             int power2 = 1;
  1155             while (power2 < samples) {
  1156                 power2 *= 2;
  1157             }
  1158             prepared->samples = power2;
  1159         }
  1160     }
  1161 
  1162     /* Calculate the silence and size of the audio specification */
  1163     SDL_CalculateAudioSpec(prepared);
  1164 
  1165     return 1;
  1166 }
  1167 
  1168 static SDL_AudioDeviceID
  1169 open_audio_device(const char *devname, int iscapture,
  1170                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1171                   int allowed_changes, int min_id)
  1172 {
  1173     SDL_AudioDeviceID id = 0;
  1174     SDL_AudioSpec _obtained;
  1175     SDL_AudioDevice *device;
  1176     SDL_bool build_cvt;
  1177     void *handle = NULL;
  1178     int i = 0;
  1179 
  1180     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1181         SDL_SetError("Audio subsystem is not initialized");
  1182         return 0;
  1183     }
  1184 
  1185     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
  1186         SDL_SetError("No capture support");
  1187         return 0;
  1188     }
  1189 
  1190     /* Find an available device ID... */
  1191     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
  1192         if (open_devices[id] == NULL) {
  1193             break;
  1194         }
  1195     }
  1196 
  1197     if (id == SDL_arraysize(open_devices)) {
  1198         SDL_SetError("Too many open audio devices");
  1199         return 0;
  1200     }
  1201 
  1202     if (!obtained) {
  1203         obtained = &_obtained;
  1204     }
  1205     if (!prepare_audiospec(desired, obtained)) {
  1206         return 0;
  1207     }
  1208 
  1209     /* If app doesn't care about a specific device, let the user override. */
  1210     if (devname == NULL) {
  1211         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
  1212     }
  1213 
  1214     /*
  1215      * Catch device names at the high level for the simple case...
  1216      * This lets us have a basic "device enumeration" for systems that
  1217      *  don't have multiple devices, but makes sure the device name is
  1218      *  always NULL when it hits the low level.
  1219      *
  1220      * Also make sure that the simple case prevents multiple simultaneous
  1221      *  opens of the default system device.
  1222      */
  1223 
  1224     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
  1225         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
  1226             SDL_SetError("No such device");
  1227             return 0;
  1228         }
  1229         devname = NULL;
  1230 
  1231         for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1232             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
  1233                 SDL_SetError("Audio device already open");
  1234                 return 0;
  1235             }
  1236         }
  1237     } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
  1238         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
  1239             SDL_SetError("No such device");
  1240             return 0;
  1241         }
  1242         devname = NULL;
  1243 
  1244         for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1245             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
  1246                 SDL_SetError("Audio device already open");
  1247                 return 0;
  1248             }
  1249         }
  1250     } else if (devname != NULL) {
  1251         /* if the app specifies an exact string, we can pass the backend
  1252            an actual device handle thingey, which saves them the effort of
  1253            figuring out what device this was (such as, reenumerating
  1254            everything again to find the matching human-readable name).
  1255            It might still need to open a device based on the string for,
  1256            say, a network audio server, but this optimizes some cases. */
  1257         SDL_AudioDeviceItem *item;
  1258         SDL_LockMutex(current_audio.detectionLock);
  1259         for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
  1260             if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
  1261                 handle = item->handle;
  1262                 break;
  1263             }
  1264         }
  1265         SDL_UnlockMutex(current_audio.detectionLock);
  1266     }
  1267 
  1268     if (!current_audio.impl.AllowsArbitraryDeviceNames) {
  1269         /* has to be in our device list, or the default device. */
  1270         if ((handle == NULL) && (devname != NULL)) {
  1271             SDL_SetError("No such device.");
  1272             return 0;
  1273         }
  1274     }
  1275 
  1276     device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
  1277     if (device == NULL) {
  1278         SDL_OutOfMemory();
  1279         return 0;
  1280     }
  1281     SDL_zerop(device);
  1282     device->id = id + 1;
  1283     device->spec = *obtained;
  1284     device->enabled = 1;
  1285     device->paused = 1;
  1286     device->iscapture = iscapture;
  1287 
  1288     /* Create a mutex for locking the sound buffers */
  1289     if (!current_audio.impl.SkipMixerLock) {
  1290         device->mixer_lock = SDL_CreateMutex();
  1291         if (device->mixer_lock == NULL) {
  1292             close_audio_device(device);
  1293             SDL_SetError("Couldn't create mixer lock");
  1294             return 0;
  1295         }
  1296     }
  1297 
  1298     if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
  1299         close_audio_device(device);
  1300         return 0;
  1301     }
  1302     device->opened = 1;
  1303 
  1304     /* Allocate a fake audio memory buffer */
  1305     device->fake_stream = (Uint8 *)SDL_AllocAudioMem(device->spec.size);
  1306     if (device->fake_stream == NULL) {
  1307         close_audio_device(device);
  1308         SDL_OutOfMemory();
  1309         return 0;
  1310     }
  1311 
  1312     /* See if we need to do any conversion */
  1313     build_cvt = SDL_FALSE;
  1314     if (obtained->freq != device->spec.freq) {
  1315         if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
  1316             obtained->freq = device->spec.freq;
  1317         } else {
  1318             build_cvt = SDL_TRUE;
  1319         }
  1320     }
  1321     if (obtained->format != device->spec.format) {
  1322         if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
  1323             obtained->format = device->spec.format;
  1324         } else {
  1325             build_cvt = SDL_TRUE;
  1326         }
  1327     }
  1328     if (obtained->channels != device->spec.channels) {
  1329         if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
  1330             obtained->channels = device->spec.channels;
  1331         } else {
  1332             build_cvt = SDL_TRUE;
  1333         }
  1334     }
  1335 
  1336     /* If the audio driver changes the buffer size, accept it.
  1337        This needs to be done after the format is modified above,
  1338        otherwise it might not have the correct buffer size.
  1339      */
  1340     if (device->spec.samples != obtained->samples) {
  1341         obtained->samples = device->spec.samples;
  1342         SDL_CalculateAudioSpec(obtained);
  1343     }
  1344 
  1345     if (build_cvt) {
  1346         /* Build an audio conversion block */
  1347         if (SDL_BuildAudioCVT(&device->convert,
  1348                               obtained->format, obtained->channels,
  1349                               obtained->freq,
  1350                               device->spec.format, device->spec.channels,
  1351                               device->spec.freq) < 0) {
  1352             close_audio_device(device);
  1353             return 0;
  1354         }
  1355         if (device->convert.needed) {
  1356             device->convert.len = (int) (((double) device->spec.size) /
  1357                                          device->convert.len_ratio);
  1358 
  1359             device->convert.buf =
  1360                 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
  1361                                             device->convert.len_mult);
  1362             if (device->convert.buf == NULL) {
  1363                 close_audio_device(device);
  1364                 SDL_OutOfMemory();
  1365                 return 0;
  1366             }
  1367         }
  1368     }
  1369 
  1370     if (device->spec.callback == NULL) {  /* use buffer queueing? */
  1371         /* pool a few packets to start. Enough for two callbacks. */
  1372         const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
  1373         const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
  1374         const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
  1375         for (i = 0; i < wantpackets; i++) {
  1376             SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
  1377             if (packet) { /* don't care if this fails, we'll deal later. */
  1378                 packet->datalen = 0;
  1379                 packet->startpos = 0;
  1380                 packet->next = device->buffer_queue_pool;
  1381                 device->buffer_queue_pool = packet;
  1382             }
  1383         }
  1384 
  1385         device->spec.callback = SDL_BufferQueueDrainCallback;
  1386         device->spec.userdata = device;
  1387     }
  1388 
  1389     /* add it to our list of open devices. */
  1390     open_devices[id] = device;
  1391 
  1392     /* Start the audio thread if necessary */
  1393     if (!current_audio.impl.ProvidesOwnCallbackThread) {
  1394         /* Start the audio thread */
  1395         char name[64];
  1396         SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
  1397 /* !!! FIXME: this is nasty. */
  1398 #if defined(__WIN32__) && !defined(HAVE_LIBC)
  1399 #undef SDL_CreateThread
  1400 #if SDL_DYNAMIC_API
  1401         device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
  1402 #else
  1403         device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
  1404 #endif
  1405 #else
  1406         device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
  1407 #endif
  1408         if (device->thread == NULL) {
  1409             SDL_CloseAudioDevice(device->id);
  1410             SDL_SetError("Couldn't create audio thread");
  1411             return 0;
  1412         }
  1413     }
  1414 
  1415     return device->id;
  1416 }
  1417 
  1418 
  1419 int
  1420 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
  1421 {
  1422     SDL_AudioDeviceID id = 0;
  1423 
  1424     /* Start up the audio driver, if necessary. This is legacy behaviour! */
  1425     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1426         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  1427             return -1;
  1428         }
  1429     }
  1430 
  1431     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  1432     if (open_devices[0] != NULL) {
  1433         SDL_SetError("Audio device is already opened");
  1434         return -1;
  1435     }
  1436 
  1437     if (obtained) {
  1438         id = open_audio_device(NULL, 0, desired, obtained,
  1439                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
  1440     } else {
  1441         id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
  1442     }
  1443 
  1444     SDL_assert((id == 0) || (id == 1));
  1445     return (id == 0) ? -1 : 0;
  1446 }
  1447 
  1448 SDL_AudioDeviceID
  1449 SDL_OpenAudioDevice(const char *device, int iscapture,
  1450                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1451                     int allowed_changes)
  1452 {
  1453     return open_audio_device(device, iscapture, desired, obtained,
  1454                              allowed_changes, 2);
  1455 }
  1456 
  1457 SDL_AudioStatus
  1458 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
  1459 {
  1460     SDL_AudioDevice *device = get_audio_device(devid);
  1461     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
  1462     if (device && device->enabled) {
  1463         if (device->paused) {
  1464             status = SDL_AUDIO_PAUSED;
  1465         } else {
  1466             status = SDL_AUDIO_PLAYING;
  1467         }
  1468     }
  1469     return status;
  1470 }
  1471 
  1472 
  1473 SDL_AudioStatus
  1474 SDL_GetAudioStatus(void)
  1475 {
  1476     return SDL_GetAudioDeviceStatus(1);
  1477 }
  1478 
  1479 void
  1480 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
  1481 {
  1482     SDL_AudioDevice *device = get_audio_device(devid);
  1483     if (device) {
  1484         current_audio.impl.LockDevice(device);
  1485         device->paused = pause_on;
  1486         current_audio.impl.UnlockDevice(device);
  1487     }
  1488 }
  1489 
  1490 void
  1491 SDL_PauseAudio(int pause_on)
  1492 {
  1493     SDL_PauseAudioDevice(1, pause_on);
  1494 }
  1495 
  1496 
  1497 void
  1498 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
  1499 {
  1500     /* Obtain a lock on the mixing buffers */
  1501     SDL_AudioDevice *device = get_audio_device(devid);
  1502     if (device) {
  1503         current_audio.impl.LockDevice(device);
  1504     }
  1505 }
  1506 
  1507 void
  1508 SDL_LockAudio(void)
  1509 {
  1510     SDL_LockAudioDevice(1);
  1511 }
  1512 
  1513 void
  1514 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
  1515 {
  1516     /* Obtain a lock on the mixing buffers */
  1517     SDL_AudioDevice *device = get_audio_device(devid);
  1518     if (device) {
  1519         current_audio.impl.UnlockDevice(device);
  1520     }
  1521 }
  1522 
  1523 void
  1524 SDL_UnlockAudio(void)
  1525 {
  1526     SDL_UnlockAudioDevice(1);
  1527 }
  1528 
  1529 void
  1530 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
  1531 {
  1532     SDL_AudioDevice *device = get_audio_device(devid);
  1533     if (device) {
  1534         close_audio_device(device);
  1535         open_devices[devid - 1] = NULL;
  1536     }
  1537 }
  1538 
  1539 void
  1540 SDL_CloseAudio(void)
  1541 {
  1542     SDL_CloseAudioDevice(1);
  1543 }
  1544 
  1545 void
  1546 SDL_AudioQuit(void)
  1547 {
  1548     SDL_AudioDeviceID i;
  1549 
  1550     if (!current_audio.name) {  /* not initialized?! */
  1551         return;
  1552     }
  1553 
  1554     for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1555         if (open_devices[i] != NULL) {
  1556             SDL_CloseAudioDevice(i+1);
  1557         }
  1558     }
  1559 
  1560     free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
  1561     free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
  1562 
  1563     /* Free the driver data */
  1564     current_audio.impl.Deinitialize();
  1565 
  1566     SDL_DestroyMutex(current_audio.detectionLock);
  1567 
  1568     SDL_zero(current_audio);
  1569     SDL_zero(open_devices);
  1570 }
  1571 
  1572 #define NUM_FORMATS 10
  1573 static int format_idx;
  1574 static int format_idx_sub;
  1575 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
  1576     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1577      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1578     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1579      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1580     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
  1581      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1582     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
  1583      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1584     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
  1585      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1586     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
  1587      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1588     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
  1589      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1590     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
  1591      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1592     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
  1593      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1594     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
  1595      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1596 };
  1597 
  1598 SDL_AudioFormat
  1599 SDL_FirstAudioFormat(SDL_AudioFormat format)
  1600 {
  1601     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
  1602         if (format_list[format_idx][0] == format) {
  1603             break;
  1604         }
  1605     }
  1606     format_idx_sub = 0;
  1607     return SDL_NextAudioFormat();
  1608 }
  1609 
  1610 SDL_AudioFormat
  1611 SDL_NextAudioFormat(void)
  1612 {
  1613     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
  1614         return 0;
  1615     }
  1616     return format_list[format_idx][format_idx_sub++];
  1617 }
  1618 
  1619 void
  1620 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
  1621 {
  1622     switch (spec->format) {
  1623     case AUDIO_U8:
  1624         spec->silence = 0x80;
  1625         break;
  1626     default:
  1627         spec->silence = 0x00;
  1628         break;
  1629     }
  1630     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  1631     spec->size *= spec->channels;
  1632     spec->size *= spec->samples;
  1633 }
  1634 
  1635 
  1636 /*
  1637  * Moved here from SDL_mixer.c, since it relies on internals of an opened
  1638  *  audio device (and is deprecated, by the way!).
  1639  */
  1640 void
  1641 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
  1642 {
  1643     /* Mix the user-level audio format */
  1644     SDL_AudioDevice *device = get_audio_device(1);
  1645     if (device != NULL) {
  1646         SDL_AudioFormat format;
  1647         if (device->convert.needed) {
  1648             format = device->convert.src_format;
  1649         } else {
  1650             format = device->spec.format;
  1651         }
  1652         SDL_MixAudioFormat(dst, src, format, len, volume);
  1653     }
  1654 }
  1655 
  1656 /* vi: set ts=4 sw=4 expandtab: */