src/audio/SDL_audio.c
author Ryan C. Gordon
Thu, 19 Mar 2015 13:27:10 -0400
changeset 9397 d72d2aa46341
parent 9396 69c501ed36f3
child 9398 c41dd34e4996
permissions -rw-r--r--
Disconnected/broken/lost audio devices now continue to fire their callback.

The data produced by the callback is just thrown away and the audio thread
delays as if it's waiting for the hardware to drain.

This lets apps that rely on their audio callback firing regularly continue
to make progress to function as properly as possible in the face of disaster.
Apps that want to know that the device is really gone and deal with that
scenario can use the new hotplug functionality.
     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 
   428     if (!device->enabled) {
   429         return;
   430     }
   431 
   432     /* Ends the audio callback and mark the device as STOPPED, but the
   433        app still needs to close the device to free resources. */
   434     current_audio.impl.LockDevice(device);
   435     device->enabled = 0;
   436     current_audio.impl.UnlockDevice(device);
   437 
   438     /* Post the event, if desired */
   439     if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
   440         SDL_Event event;
   441         event.adevice.type = SDL_AUDIODEVICEREMOVED;
   442         event.adevice.which = device->id;
   443         event.adevice.iscapture = device->iscapture ? 1 : 0;
   444         SDL_PushEvent(&event);
   445     }
   446 }
   447 
   448 static void
   449 mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
   450 {
   451     SDL_AudioDeviceItem *item;
   452     SDL_assert(handle != NULL);
   453     for (item = devices; item != NULL; item = item->next) {
   454         if (item->handle == handle) {
   455             item->handle = NULL;
   456             *removedFlag = SDL_TRUE;
   457             return;
   458         }
   459     }
   460 }
   461 
   462 /* The audio backends call this when a device is removed from the system. */
   463 void
   464 SDL_RemoveAudioDevice(void *handle)
   465 {
   466     SDL_LockMutex(current_audio.detectionLock);
   467     mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
   468     mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
   469     SDL_UnlockMutex(current_audio.detectionLock);
   470     current_audio.impl.FreeDeviceHandle(handle);
   471 }
   472 
   473 
   474 
   475 /* buffer queueing support... */
   476 
   477 /* this expects that you managed thread safety elsewhere. */
   478 static void
   479 free_audio_queue(SDL_AudioBufferQueue *buffer)
   480 {
   481     while (buffer) {
   482         SDL_AudioBufferQueue *next = buffer->next;
   483         SDL_free(buffer);
   484         buffer = next;
   485     }
   486 }
   487 
   488 static void SDLCALL
   489 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
   490 {
   491     /* this function always holds the mixer lock before being called. */
   492     Uint32 len = (Uint32) _len;
   493     SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
   494     SDL_AudioBufferQueue *buffer;
   495 
   496     SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
   497     SDL_assert(_len >= 0);  /* this shouldn't ever happen, right?! */
   498 
   499     while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
   500         const Uint32 avail = buffer->datalen - buffer->startpos;
   501         const Uint32 cpy = SDL_min(len, avail);
   502         SDL_assert(device->queued_bytes >= avail);
   503 
   504         SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
   505         buffer->startpos += cpy;
   506         stream += cpy;
   507         device->queued_bytes -= cpy;
   508         len -= cpy;
   509 
   510         if (buffer->startpos == buffer->datalen) {  /* packet is done, put it in the pool. */
   511             device->buffer_queue_head = buffer->next;
   512             SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
   513             buffer->next = device->buffer_queue_pool;
   514             device->buffer_queue_pool = buffer;
   515         }
   516     }
   517 
   518     SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
   519 
   520     if (len > 0) {  /* fill any remaining space in the stream with silence. */
   521         SDL_assert(device->buffer_queue_head == NULL);
   522         SDL_memset(stream, device->spec.silence, len);
   523     }
   524 
   525     if (device->buffer_queue_head == NULL) {
   526         device->buffer_queue_tail = NULL;  /* in case we drained the queue entirely. */
   527     }
   528 }
   529 
   530 int
   531 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
   532 {
   533     SDL_AudioDevice *device = get_audio_device(devid);
   534     const Uint8 *data = (const Uint8 *) _data;
   535     SDL_AudioBufferQueue *orighead;
   536     SDL_AudioBufferQueue *origtail;
   537     Uint32 origlen;
   538     Uint32 datalen;
   539 
   540     if (!device) {
   541         return -1;  /* get_audio_device() will have set the error state */
   542     }
   543 
   544     if (device->spec.callback != SDL_BufferQueueDrainCallback) {
   545         return SDL_SetError("Audio device has a callback, queueing not allowed");
   546     }
   547 
   548     current_audio.impl.LockDevice(device);
   549 
   550     orighead = device->buffer_queue_head;
   551     origtail = device->buffer_queue_tail;
   552     origlen = origtail ? origtail->datalen : 0;
   553 
   554     while (len > 0) {
   555         SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
   556         SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
   557         if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
   558             /* tail packet missing or completely full; we need a new packet. */
   559             packet = device->buffer_queue_pool;
   560             if (packet != NULL) {
   561                 /* we have one available in the pool. */
   562                 device->buffer_queue_pool = packet->next;
   563             } else {
   564                 /* Have to allocate a new one! */
   565                 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
   566                 if (packet == NULL) {
   567                     /* uhoh, reset so we've queued nothing new, free what we can. */
   568                     if (!origtail) {
   569                         packet = device->buffer_queue_head;  /* whole queue. */
   570                     } else {
   571                         packet = origtail->next;  /* what we added to existing queue. */
   572                         origtail->next = NULL;
   573                         origtail->datalen = origlen;
   574                     }
   575                     device->buffer_queue_head = orighead;
   576                     device->buffer_queue_tail = origtail;
   577                     device->buffer_queue_pool = NULL;
   578 
   579                     current_audio.impl.UnlockDevice(device);
   580 
   581                     free_audio_queue(packet);  /* give back what we can. */
   582 
   583                     return SDL_OutOfMemory();
   584                 }
   585             }
   586             packet->datalen = 0;
   587             packet->startpos = 0;
   588             packet->next = NULL;
   589 
   590             SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
   591             if (device->buffer_queue_tail == NULL) {
   592                 device->buffer_queue_head = packet;
   593             } else {
   594                 device->buffer_queue_tail->next = packet;
   595             }
   596             device->buffer_queue_tail = packet;
   597         }
   598 
   599         datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
   600         SDL_memcpy(packet->data + packet->datalen, data, datalen);
   601         data += datalen;
   602         len -= datalen;
   603         packet->datalen += datalen;
   604         device->queued_bytes += datalen;
   605     }
   606 
   607     current_audio.impl.UnlockDevice(device);
   608 
   609     return 0;
   610 }
   611 
   612 Uint32
   613 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
   614 {
   615     Uint32 retval = 0;
   616     SDL_AudioDevice *device = get_audio_device(devid);
   617 
   618     /* Nothing to do unless we're set up for queueing. */
   619     if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
   620         current_audio.impl.LockDevice(device);
   621         retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
   622         current_audio.impl.UnlockDevice(device);
   623     }
   624 
   625     return retval;
   626 }
   627 
   628 void
   629 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
   630 {
   631     SDL_AudioDevice *device = get_audio_device(devid);
   632     SDL_AudioBufferQueue *buffer = NULL;
   633     if (!device) {
   634         return;  /* nothing to do. */
   635     }
   636 
   637     /* Blank out the device and release the mutex. Free it afterwards. */
   638     current_audio.impl.LockDevice(device);
   639     buffer = device->buffer_queue_head;
   640     device->buffer_queue_tail = NULL;
   641     device->buffer_queue_head = NULL;
   642     device->queued_bytes = 0;
   643     current_audio.impl.UnlockDevice(device);
   644 
   645     free_audio_queue(buffer);
   646 }
   647 
   648 
   649 #if defined(__ANDROID__)
   650 #include <android/log.h>
   651 #endif
   652 
   653 /* The general mixing thread function */
   654 int SDLCALL
   655 SDL_RunAudio(void *devicep)
   656 {
   657     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
   658     Uint8 *stream;
   659     int stream_len;
   660     void *udata;
   661     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   662     Uint32 delay;
   663 
   664 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   665     /* For streaming when the buffer sizes don't match up */
   666     Uint8 *istream;
   667     int istream_len = 0;
   668 #endif
   669 
   670     /* The audio mixing is always a high priority thread */
   671     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
   672 
   673     /* Perform any thread setup */
   674     device->threadid = SDL_ThreadID();
   675     current_audio.impl.ThreadInit(device);
   676 
   677     /* Set up the mixing function */
   678     fill = device->spec.callback;
   679     udata = device->spec.userdata;
   680 
   681     /* By default do not stream */
   682     device->use_streamer = 0;
   683 
   684     if (device->convert.needed) {
   685 #if 0                           /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
   686         /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
   687         if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
   688             /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
   689             stream_max_len = 2 * device->spec.size;
   690             if (device->convert.len_mult > device->convert.len_div) {
   691                 stream_max_len *= device->convert.len_mult;
   692                 stream_max_len /= device->convert.len_div;
   693             }
   694             if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
   695                 0)
   696                 return -1;
   697             device->use_streamer = 1;
   698 
   699             /* istream_len should be the length of what we grab from the callback and feed to conversion,
   700                so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
   701              */
   702             istream_len =
   703                 device->spec.size * device->convert.len_div /
   704                 device->convert.len_mult;
   705         }
   706 #endif
   707         stream_len = device->convert.len;
   708     } else {
   709         stream_len = device->spec.size;
   710     }
   711 
   712     /* Calculate the delay while paused */
   713     delay = ((device->spec.samples * 1000) / device->spec.freq);
   714 
   715     /* Determine if the streamer is necessary here */
   716 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   717     if (device->use_streamer == 1) {
   718         /* This code is almost the same as the old code. The difference is, instead of reading
   719            directly from the callback into "stream", then converting and sending the audio off,
   720            we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
   721            However, reading and writing with streamer are done separately:
   722            - We only call the callback and write to the streamer when the streamer does not
   723            contain enough samples to output to the device.
   724            - We only read from the streamer and tell the device to play when the streamer
   725            does have enough samples to output.
   726            This allows us to perform resampling in the conversion step, where the output of the
   727            resampling process can be any number. We will have to see what a good size for the
   728            stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
   729          */
   730         while (!device->shutdown) {
   731 
   732             if (device->paused) {
   733                 SDL_Delay(delay);
   734                 continue;
   735             }
   736 
   737             /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
   738             if (SDL_StreamLength(&device->streamer) < stream_len) {
   739                 /* Set up istream */
   740                 if (device->convert.needed) {
   741                     if (device->convert.buf) {
   742                         istream = device->convert.buf;
   743                     } else {
   744                         continue;
   745                     }
   746                 } else {
   747 /* FIXME: Ryan, this is probably wrong.  I imagine we don't want to get
   748  * a device buffer both here and below in the stream output.
   749  */
   750                     istream = current_audio.impl.GetDeviceBuf(device);
   751                     if (istream == NULL) {
   752                         istream = device->fake_stream;
   753                     }
   754                 }
   755 
   756                 /* Read from the callback into the _input_ stream */
   757                 // !!! FIXME: this should be LockDevice.
   758                 SDL_LockMutex(device->mixer_lock);
   759                 (*fill) (udata, istream, istream_len);
   760                 SDL_UnlockMutex(device->mixer_lock);
   761 
   762                 /* Convert the audio if necessary and write to the streamer */
   763                 if (device->convert.needed) {
   764                     SDL_ConvertAudio(&device->convert);
   765                     if (istream == NULL) {
   766                         istream = device->fake_stream;
   767                     }
   768                     /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
   769                     SDL_StreamWrite(&device->streamer, device->convert.buf,
   770                                     device->convert.len_cvt);
   771                 } else {
   772                     SDL_StreamWrite(&device->streamer, istream, istream_len);
   773                 }
   774             }
   775 
   776             /* Only output audio if the streamer has enough to output */
   777             if (SDL_StreamLength(&device->streamer) >= stream_len) {
   778                 /* Set up the output stream */
   779                 if (device->convert.needed) {
   780                     if (device->convert.buf) {
   781                         stream = device->convert.buf;
   782                     } else {
   783                         continue;
   784                     }
   785                 } else {
   786                     stream = current_audio.impl.GetDeviceBuf(device);
   787                     if (stream == NULL) {
   788                         stream = device->fake_stream;
   789                     }
   790                 }
   791 
   792                 /* Now read from the streamer */
   793                 SDL_StreamRead(&device->streamer, stream, stream_len);
   794 
   795                 /* Ready current buffer for play and change current buffer */
   796                 if (stream != device->fake_stream) {
   797                     current_audio.impl.PlayDevice(device);
   798                     /* Wait for an audio buffer to become available */
   799                     current_audio.impl.WaitDevice(device);
   800                 } else {
   801                     SDL_Delay(delay);
   802                 }
   803             }
   804 
   805         }
   806     } else
   807 #endif
   808     {
   809         /* Otherwise, do not use the streamer. This is the old code. */
   810         const int silence = (int) device->spec.silence;
   811 
   812         /* Loop, filling the audio buffers */
   813         while (!device->shutdown) {
   814             /* Fill the current buffer with sound */
   815             if (device->convert.needed) {
   816                 stream = device->convert.buf;
   817             } else if (device->enabled) {
   818                 stream = current_audio.impl.GetDeviceBuf(device);
   819             } else {
   820                 /* if the device isn't enabled, we still write to the
   821                     fake_stream, so the app's callback will fire with
   822                     a regular frequency, in case they depend on that
   823                     for timing or progress. They can use hotplug
   824                     now to know if the device failed. */
   825                 stream = NULL;
   826             }
   827 
   828             if (stream == NULL) {
   829                 stream = device->fake_stream;
   830             }
   831 
   832             /* !!! FIXME: this should be LockDevice. */
   833             SDL_LockMutex(device->mixer_lock);
   834             if (device->paused) {
   835                 SDL_memset(stream, silence, stream_len);
   836             } else {
   837                 (*fill) (udata, stream, stream_len);
   838             }
   839             SDL_UnlockMutex(device->mixer_lock);
   840 
   841             /* Convert the audio if necessary */
   842             if (device->enabled && device->convert.needed) {
   843                 SDL_ConvertAudio(&device->convert);
   844                 stream = current_audio.impl.GetDeviceBuf(device);
   845                 if (stream == NULL) {
   846                     stream = device->fake_stream;
   847                 } else {
   848                     SDL_memcpy(stream, device->convert.buf,
   849                                device->convert.len_cvt);
   850                 }
   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     device->shutdown = 1;
  1085     if (device->thread != NULL) {
  1086         SDL_WaitThread(device->thread, NULL);
  1087     }
  1088     if (device->mixer_lock != NULL) {
  1089         SDL_DestroyMutex(device->mixer_lock);
  1090     }
  1091     SDL_FreeAudioMem(device->fake_stream);
  1092     if (device->convert.needed) {
  1093         SDL_FreeAudioMem(device->convert.buf);
  1094     }
  1095     if (device->opened) {
  1096         current_audio.impl.CloseDevice(device);
  1097         device->opened = 0;
  1098     }
  1099 
  1100     free_audio_queue(device->buffer_queue_head);
  1101     free_audio_queue(device->buffer_queue_pool);
  1102 
  1103     SDL_FreeAudioMem(device);
  1104 }
  1105 
  1106 
  1107 /*
  1108  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
  1109  *  Fills in a sanitized copy in (prepared).
  1110  *  Returns non-zero if okay, zero on fatal parameters in (orig).
  1111  */
  1112 static int
  1113 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
  1114 {
  1115     SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
  1116 
  1117     if (orig->freq == 0) {
  1118         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
  1119         if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
  1120             prepared->freq = 22050;     /* a reasonable default */
  1121         }
  1122     }
  1123 
  1124     if (orig->format == 0) {
  1125         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
  1126         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
  1127             prepared->format = AUDIO_S16;       /* a reasonable default */
  1128         }
  1129     }
  1130 
  1131     switch (orig->channels) {
  1132     case 0:{
  1133             const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
  1134             if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
  1135                 prepared->channels = 2; /* a reasonable default */
  1136             }
  1137             break;
  1138         }
  1139     case 1:                    /* Mono */
  1140     case 2:                    /* Stereo */
  1141     case 4:                    /* surround */
  1142     case 6:                    /* surround with center and lfe */
  1143         break;
  1144     default:
  1145         SDL_SetError("Unsupported number of audio channels.");
  1146         return 0;
  1147     }
  1148 
  1149     if (orig->samples == 0) {
  1150         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
  1151         if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
  1152             /* Pick a default of ~46 ms at desired frequency */
  1153             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
  1154             const int samples = (prepared->freq / 1000) * 46;
  1155             int power2 = 1;
  1156             while (power2 < samples) {
  1157                 power2 *= 2;
  1158             }
  1159             prepared->samples = power2;
  1160         }
  1161     }
  1162 
  1163     /* Calculate the silence and size of the audio specification */
  1164     SDL_CalculateAudioSpec(prepared);
  1165 
  1166     return 1;
  1167 }
  1168 
  1169 static SDL_AudioDeviceID
  1170 open_audio_device(const char *devname, int iscapture,
  1171                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1172                   int allowed_changes, int min_id)
  1173 {
  1174     SDL_AudioDeviceID id = 0;
  1175     SDL_AudioSpec _obtained;
  1176     SDL_AudioDevice *device;
  1177     SDL_bool build_cvt;
  1178     void *handle = NULL;
  1179     int stream_len;
  1180     int i = 0;
  1181 
  1182     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1183         SDL_SetError("Audio subsystem is not initialized");
  1184         return 0;
  1185     }
  1186 
  1187     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
  1188         SDL_SetError("No capture support");
  1189         return 0;
  1190     }
  1191 
  1192     /* Find an available device ID... */
  1193     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
  1194         if (open_devices[id] == NULL) {
  1195             break;
  1196         }
  1197     }
  1198 
  1199     if (id == SDL_arraysize(open_devices)) {
  1200         SDL_SetError("Too many open audio devices");
  1201         return 0;
  1202     }
  1203 
  1204     if (!obtained) {
  1205         obtained = &_obtained;
  1206     }
  1207     if (!prepare_audiospec(desired, obtained)) {
  1208         return 0;
  1209     }
  1210 
  1211     /* If app doesn't care about a specific device, let the user override. */
  1212     if (devname == NULL) {
  1213         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
  1214     }
  1215 
  1216     /*
  1217      * Catch device names at the high level for the simple case...
  1218      * This lets us have a basic "device enumeration" for systems that
  1219      *  don't have multiple devices, but makes sure the device name is
  1220      *  always NULL when it hits the low level.
  1221      *
  1222      * Also make sure that the simple case prevents multiple simultaneous
  1223      *  opens of the default system device.
  1224      */
  1225 
  1226     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
  1227         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
  1228             SDL_SetError("No such device");
  1229             return 0;
  1230         }
  1231         devname = NULL;
  1232 
  1233         for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1234             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
  1235                 SDL_SetError("Audio device already open");
  1236                 return 0;
  1237             }
  1238         }
  1239     } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
  1240         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
  1241             SDL_SetError("No such device");
  1242             return 0;
  1243         }
  1244         devname = NULL;
  1245 
  1246         for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1247             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
  1248                 SDL_SetError("Audio device already open");
  1249                 return 0;
  1250             }
  1251         }
  1252     } else if (devname != NULL) {
  1253         /* if the app specifies an exact string, we can pass the backend
  1254            an actual device handle thingey, which saves them the effort of
  1255            figuring out what device this was (such as, reenumerating
  1256            everything again to find the matching human-readable name).
  1257            It might still need to open a device based on the string for,
  1258            say, a network audio server, but this optimizes some cases. */
  1259         SDL_AudioDeviceItem *item;
  1260         SDL_LockMutex(current_audio.detectionLock);
  1261         for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
  1262             if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
  1263                 handle = item->handle;
  1264                 break;
  1265             }
  1266         }
  1267         SDL_UnlockMutex(current_audio.detectionLock);
  1268     }
  1269 
  1270     if (!current_audio.impl.AllowsArbitraryDeviceNames) {
  1271         /* has to be in our device list, or the default device. */
  1272         if ((handle == NULL) && (devname != NULL)) {
  1273             SDL_SetError("No such device.");
  1274             return 0;
  1275         }
  1276     }
  1277 
  1278     device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
  1279     if (device == NULL) {
  1280         SDL_OutOfMemory();
  1281         return 0;
  1282     }
  1283     SDL_zerop(device);
  1284     device->id = id + 1;
  1285     device->spec = *obtained;
  1286     device->enabled = 1;
  1287     device->paused = 1;
  1288     device->iscapture = iscapture;
  1289 
  1290     /* Create a mutex for locking the sound buffers */
  1291     if (!current_audio.impl.SkipMixerLock) {
  1292         device->mixer_lock = SDL_CreateMutex();
  1293         if (device->mixer_lock == NULL) {
  1294             close_audio_device(device);
  1295             SDL_SetError("Couldn't create mixer lock");
  1296             return 0;
  1297         }
  1298     }
  1299 
  1300     if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
  1301         close_audio_device(device);
  1302         return 0;
  1303     }
  1304     device->opened = 1;
  1305 
  1306     /* See if we need to do any conversion */
  1307     build_cvt = SDL_FALSE;
  1308     if (obtained->freq != device->spec.freq) {
  1309         if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
  1310             obtained->freq = device->spec.freq;
  1311         } else {
  1312             build_cvt = SDL_TRUE;
  1313         }
  1314     }
  1315     if (obtained->format != device->spec.format) {
  1316         if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
  1317             obtained->format = device->spec.format;
  1318         } else {
  1319             build_cvt = SDL_TRUE;
  1320         }
  1321     }
  1322     if (obtained->channels != device->spec.channels) {
  1323         if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
  1324             obtained->channels = device->spec.channels;
  1325         } else {
  1326             build_cvt = SDL_TRUE;
  1327         }
  1328     }
  1329 
  1330     /* If the audio driver changes the buffer size, accept it.
  1331        This needs to be done after the format is modified above,
  1332        otherwise it might not have the correct buffer size.
  1333      */
  1334     if (device->spec.samples != obtained->samples) {
  1335         obtained->samples = device->spec.samples;
  1336         SDL_CalculateAudioSpec(obtained);
  1337     }
  1338 
  1339     if (build_cvt) {
  1340         /* Build an audio conversion block */
  1341         if (SDL_BuildAudioCVT(&device->convert,
  1342                               obtained->format, obtained->channels,
  1343                               obtained->freq,
  1344                               device->spec.format, device->spec.channels,
  1345                               device->spec.freq) < 0) {
  1346             close_audio_device(device);
  1347             return 0;
  1348         }
  1349         if (device->convert.needed) {
  1350             device->convert.len = (int) (((double) device->spec.size) /
  1351                                          device->convert.len_ratio);
  1352 
  1353             device->convert.buf =
  1354                 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
  1355                                             device->convert.len_mult);
  1356             if (device->convert.buf == NULL) {
  1357                 close_audio_device(device);
  1358                 SDL_OutOfMemory();
  1359                 return 0;
  1360             }
  1361         }
  1362     }
  1363 
  1364     /* Allocate a fake audio memory buffer */
  1365     stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
  1366     if (device->spec.size > stream_len) {
  1367         stream_len = device->spec.size;
  1368     }
  1369     device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
  1370     if (device->fake_stream == NULL) {
  1371         close_audio_device(device);
  1372         SDL_OutOfMemory();
  1373         return 0;
  1374     }
  1375 
  1376     if (device->spec.callback == NULL) {  /* use buffer queueing? */
  1377         /* pool a few packets to start. Enough for two callbacks. */
  1378         const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
  1379         const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
  1380         const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
  1381         for (i = 0; i < wantpackets; i++) {
  1382             SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
  1383             if (packet) { /* don't care if this fails, we'll deal later. */
  1384                 packet->datalen = 0;
  1385                 packet->startpos = 0;
  1386                 packet->next = device->buffer_queue_pool;
  1387                 device->buffer_queue_pool = packet;
  1388             }
  1389         }
  1390 
  1391         device->spec.callback = SDL_BufferQueueDrainCallback;
  1392         device->spec.userdata = device;
  1393     }
  1394 
  1395     /* add it to our list of open devices. */
  1396     open_devices[id] = device;
  1397 
  1398     /* Start the audio thread if necessary */
  1399     if (!current_audio.impl.ProvidesOwnCallbackThread) {
  1400         /* Start the audio thread */
  1401         char name[64];
  1402         SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
  1403 /* !!! FIXME: this is nasty. */
  1404 #if defined(__WIN32__) && !defined(HAVE_LIBC)
  1405 #undef SDL_CreateThread
  1406 #if SDL_DYNAMIC_API
  1407         device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
  1408 #else
  1409         device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
  1410 #endif
  1411 #else
  1412         device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
  1413 #endif
  1414         if (device->thread == NULL) {
  1415             SDL_CloseAudioDevice(device->id);
  1416             SDL_SetError("Couldn't create audio thread");
  1417             return 0;
  1418         }
  1419     }
  1420 
  1421     return device->id;
  1422 }
  1423 
  1424 
  1425 int
  1426 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
  1427 {
  1428     SDL_AudioDeviceID id = 0;
  1429 
  1430     /* Start up the audio driver, if necessary. This is legacy behaviour! */
  1431     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1432         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  1433             return -1;
  1434         }
  1435     }
  1436 
  1437     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  1438     if (open_devices[0] != NULL) {
  1439         SDL_SetError("Audio device is already opened");
  1440         return -1;
  1441     }
  1442 
  1443     if (obtained) {
  1444         id = open_audio_device(NULL, 0, desired, obtained,
  1445                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
  1446     } else {
  1447         id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
  1448     }
  1449 
  1450     SDL_assert((id == 0) || (id == 1));
  1451     return (id == 0) ? -1 : 0;
  1452 }
  1453 
  1454 SDL_AudioDeviceID
  1455 SDL_OpenAudioDevice(const char *device, int iscapture,
  1456                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1457                     int allowed_changes)
  1458 {
  1459     return open_audio_device(device, iscapture, desired, obtained,
  1460                              allowed_changes, 2);
  1461 }
  1462 
  1463 SDL_AudioStatus
  1464 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
  1465 {
  1466     SDL_AudioDevice *device = get_audio_device(devid);
  1467     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
  1468     if (device && device->enabled) {
  1469         if (device->paused) {
  1470             status = SDL_AUDIO_PAUSED;
  1471         } else {
  1472             status = SDL_AUDIO_PLAYING;
  1473         }
  1474     }
  1475     return status;
  1476 }
  1477 
  1478 
  1479 SDL_AudioStatus
  1480 SDL_GetAudioStatus(void)
  1481 {
  1482     return SDL_GetAudioDeviceStatus(1);
  1483 }
  1484 
  1485 void
  1486 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
  1487 {
  1488     SDL_AudioDevice *device = get_audio_device(devid);
  1489     if (device) {
  1490         current_audio.impl.LockDevice(device);
  1491         device->paused = pause_on;
  1492         current_audio.impl.UnlockDevice(device);
  1493     }
  1494 }
  1495 
  1496 void
  1497 SDL_PauseAudio(int pause_on)
  1498 {
  1499     SDL_PauseAudioDevice(1, pause_on);
  1500 }
  1501 
  1502 
  1503 void
  1504 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
  1505 {
  1506     /* Obtain a lock on the mixing buffers */
  1507     SDL_AudioDevice *device = get_audio_device(devid);
  1508     if (device) {
  1509         current_audio.impl.LockDevice(device);
  1510     }
  1511 }
  1512 
  1513 void
  1514 SDL_LockAudio(void)
  1515 {
  1516     SDL_LockAudioDevice(1);
  1517 }
  1518 
  1519 void
  1520 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
  1521 {
  1522     /* Obtain a lock on the mixing buffers */
  1523     SDL_AudioDevice *device = get_audio_device(devid);
  1524     if (device) {
  1525         current_audio.impl.UnlockDevice(device);
  1526     }
  1527 }
  1528 
  1529 void
  1530 SDL_UnlockAudio(void)
  1531 {
  1532     SDL_UnlockAudioDevice(1);
  1533 }
  1534 
  1535 void
  1536 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
  1537 {
  1538     SDL_AudioDevice *device = get_audio_device(devid);
  1539     if (device) {
  1540         close_audio_device(device);
  1541         open_devices[devid - 1] = NULL;
  1542     }
  1543 }
  1544 
  1545 void
  1546 SDL_CloseAudio(void)
  1547 {
  1548     SDL_CloseAudioDevice(1);
  1549 }
  1550 
  1551 void
  1552 SDL_AudioQuit(void)
  1553 {
  1554     SDL_AudioDeviceID i;
  1555 
  1556     if (!current_audio.name) {  /* not initialized?! */
  1557         return;
  1558     }
  1559 
  1560     for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1561         if (open_devices[i] != NULL) {
  1562             SDL_CloseAudioDevice(i+1);
  1563         }
  1564     }
  1565 
  1566     free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
  1567     free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
  1568 
  1569     /* Free the driver data */
  1570     current_audio.impl.Deinitialize();
  1571 
  1572     SDL_DestroyMutex(current_audio.detectionLock);
  1573 
  1574     SDL_zero(current_audio);
  1575     SDL_zero(open_devices);
  1576 }
  1577 
  1578 #define NUM_FORMATS 10
  1579 static int format_idx;
  1580 static int format_idx_sub;
  1581 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
  1582     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1583      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1584     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1585      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1586     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
  1587      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1588     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
  1589      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1590     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
  1591      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1592     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
  1593      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1594     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
  1595      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1596     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
  1597      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1598     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
  1599      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1600     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
  1601      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1602 };
  1603 
  1604 SDL_AudioFormat
  1605 SDL_FirstAudioFormat(SDL_AudioFormat format)
  1606 {
  1607     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
  1608         if (format_list[format_idx][0] == format) {
  1609             break;
  1610         }
  1611     }
  1612     format_idx_sub = 0;
  1613     return SDL_NextAudioFormat();
  1614 }
  1615 
  1616 SDL_AudioFormat
  1617 SDL_NextAudioFormat(void)
  1618 {
  1619     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
  1620         return 0;
  1621     }
  1622     return format_list[format_idx][format_idx_sub++];
  1623 }
  1624 
  1625 void
  1626 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
  1627 {
  1628     switch (spec->format) {
  1629     case AUDIO_U8:
  1630         spec->silence = 0x80;
  1631         break;
  1632     default:
  1633         spec->silence = 0x00;
  1634         break;
  1635     }
  1636     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  1637     spec->size *= spec->channels;
  1638     spec->size *= spec->samples;
  1639 }
  1640 
  1641 
  1642 /*
  1643  * Moved here from SDL_mixer.c, since it relies on internals of an opened
  1644  *  audio device (and is deprecated, by the way!).
  1645  */
  1646 void
  1647 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
  1648 {
  1649     /* Mix the user-level audio format */
  1650     SDL_AudioDevice *device = get_audio_device(1);
  1651     if (device != NULL) {
  1652         SDL_AudioFormat format;
  1653         if (device->convert.needed) {
  1654             format = device->convert.src_format;
  1655         } else {
  1656             format = device->spec.format;
  1657         }
  1658         SDL_MixAudioFormat(dst, src, format, len, volume);
  1659     }
  1660 }
  1661 
  1662 /* vi: set ts=4 sw=4 expandtab: */