src/audio/SDL_audio.c
author Ryan C. Gordon
Thu, 19 Mar 2015 13:34:17 -0400
changeset 9398 c41dd34e4996
parent 9397 d72d2aa46341
child 9399 a684dbd185c7
permissions -rw-r--r--
Removed the broken audio streaming code, other small cleanups.
     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 
   290 /* device hotplug support... */
   291 
   292 static int
   293 add_audio_device(const char *name, void *handle, SDL_AudioDeviceItem **devices, int *devCount)
   294 {
   295     int retval = -1;
   296     const size_t size = sizeof (SDL_AudioDeviceItem) + SDL_strlen(name) + 1;
   297     SDL_AudioDeviceItem *item = (SDL_AudioDeviceItem *) SDL_malloc(size);
   298     if (item == NULL) {
   299         return -1;
   300     }
   301 
   302     SDL_assert(handle != NULL);
   303 
   304     item->handle = handle;
   305     SDL_strlcpy(item->name, name, size - sizeof (SDL_AudioDeviceItem));
   306 
   307     SDL_LockMutex(current_audio.detectionLock);
   308     item->next = *devices;
   309     *devices = item;
   310     retval = (*devCount)++;
   311     SDL_UnlockMutex(current_audio.detectionLock);
   312 
   313     return retval;
   314 }
   315 
   316 static SDL_INLINE int
   317 add_capture_device(const char *name, void *handle)
   318 {
   319     /* !!! FIXME: add this later. SDL_assert(current_audio.impl.HasCaptureSupport);*/
   320     return add_audio_device(name, handle, &current_audio.inputDevices, &current_audio.inputDeviceCount);
   321 }
   322 
   323 static SDL_INLINE int
   324 add_output_device(const char *name, void *handle)
   325 {
   326     return add_audio_device(name, handle, &current_audio.outputDevices, &current_audio.outputDeviceCount);
   327 }
   328 
   329 static void
   330 free_device_list(SDL_AudioDeviceItem **devices, int *devCount)
   331 {
   332     SDL_AudioDeviceItem *item, *next;
   333     for (item = *devices; item != NULL; item = next) {
   334         next = item->next;
   335         if (item->handle != NULL) {
   336             current_audio.impl.FreeDeviceHandle(item->handle);
   337         }
   338         SDL_free(item);
   339     }
   340     *devices = NULL;
   341     *devCount = 0;
   342 }
   343 
   344 
   345 /* The audio backends call this when a new device is plugged in. */
   346 void
   347 SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)
   348 {
   349     const int device_index = iscapture ? add_capture_device(name, handle) : add_output_device(name, handle);
   350     if (device_index != -1) {
   351         /* Post the event, if desired */
   352         if (SDL_GetEventState(SDL_AUDIODEVICEADDED) == SDL_ENABLE) {
   353             SDL_Event event;
   354             event.adevice.type = SDL_AUDIODEVICEADDED;
   355             event.adevice.which = device_index;
   356             event.adevice.iscapture = iscapture;
   357             SDL_PushEvent(&event);
   358         }
   359     }
   360 }
   361 
   362 /* The audio backends call this when a currently-opened device is lost. */
   363 void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
   364 {
   365     SDL_assert(get_audio_device(device->id) == device);
   366 
   367     if (!device->enabled) {
   368         return;
   369     }
   370 
   371     /* Ends the audio callback and mark the device as STOPPED, but the
   372        app still needs to close the device to free resources. */
   373     current_audio.impl.LockDevice(device);
   374     device->enabled = 0;
   375     current_audio.impl.UnlockDevice(device);
   376 
   377     /* Post the event, if desired */
   378     if (SDL_GetEventState(SDL_AUDIODEVICEREMOVED) == SDL_ENABLE) {
   379         SDL_Event event;
   380         event.adevice.type = SDL_AUDIODEVICEREMOVED;
   381         event.adevice.which = device->id;
   382         event.adevice.iscapture = device->iscapture ? 1 : 0;
   383         SDL_PushEvent(&event);
   384     }
   385 }
   386 
   387 static void
   388 mark_device_removed(void *handle, SDL_AudioDeviceItem *devices, SDL_bool *removedFlag)
   389 {
   390     SDL_AudioDeviceItem *item;
   391     SDL_assert(handle != NULL);
   392     for (item = devices; item != NULL; item = item->next) {
   393         if (item->handle == handle) {
   394             item->handle = NULL;
   395             *removedFlag = SDL_TRUE;
   396             return;
   397         }
   398     }
   399 }
   400 
   401 /* The audio backends call this when a device is removed from the system. */
   402 void
   403 SDL_RemoveAudioDevice(void *handle)
   404 {
   405     SDL_LockMutex(current_audio.detectionLock);
   406     mark_device_removed(handle, current_audio.inputDevices, &current_audio.captureDevicesRemoved);
   407     mark_device_removed(handle, current_audio.outputDevices, &current_audio.outputDevicesRemoved);
   408     SDL_UnlockMutex(current_audio.detectionLock);
   409     current_audio.impl.FreeDeviceHandle(handle);
   410 }
   411 
   412 
   413 
   414 /* buffer queueing support... */
   415 
   416 /* this expects that you managed thread safety elsewhere. */
   417 static void
   418 free_audio_queue(SDL_AudioBufferQueue *buffer)
   419 {
   420     while (buffer) {
   421         SDL_AudioBufferQueue *next = buffer->next;
   422         SDL_free(buffer);
   423         buffer = next;
   424     }
   425 }
   426 
   427 static void SDLCALL
   428 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
   429 {
   430     /* this function always holds the mixer lock before being called. */
   431     Uint32 len = (Uint32) _len;
   432     SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
   433     SDL_AudioBufferQueue *buffer;
   434 
   435     SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
   436     SDL_assert(_len >= 0);  /* this shouldn't ever happen, right?! */
   437 
   438     while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
   439         const Uint32 avail = buffer->datalen - buffer->startpos;
   440         const Uint32 cpy = SDL_min(len, avail);
   441         SDL_assert(device->queued_bytes >= avail);
   442 
   443         SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
   444         buffer->startpos += cpy;
   445         stream += cpy;
   446         device->queued_bytes -= cpy;
   447         len -= cpy;
   448 
   449         if (buffer->startpos == buffer->datalen) {  /* packet is done, put it in the pool. */
   450             device->buffer_queue_head = buffer->next;
   451             SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
   452             buffer->next = device->buffer_queue_pool;
   453             device->buffer_queue_pool = buffer;
   454         }
   455     }
   456 
   457     SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
   458 
   459     if (len > 0) {  /* fill any remaining space in the stream with silence. */
   460         SDL_assert(device->buffer_queue_head == NULL);
   461         SDL_memset(stream, device->spec.silence, len);
   462     }
   463 
   464     if (device->buffer_queue_head == NULL) {
   465         device->buffer_queue_tail = NULL;  /* in case we drained the queue entirely. */
   466     }
   467 }
   468 
   469 int
   470 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
   471 {
   472     SDL_AudioDevice *device = get_audio_device(devid);
   473     const Uint8 *data = (const Uint8 *) _data;
   474     SDL_AudioBufferQueue *orighead;
   475     SDL_AudioBufferQueue *origtail;
   476     Uint32 origlen;
   477     Uint32 datalen;
   478 
   479     if (!device) {
   480         return -1;  /* get_audio_device() will have set the error state */
   481     }
   482 
   483     if (device->spec.callback != SDL_BufferQueueDrainCallback) {
   484         return SDL_SetError("Audio device has a callback, queueing not allowed");
   485     }
   486 
   487     current_audio.impl.LockDevice(device);
   488 
   489     orighead = device->buffer_queue_head;
   490     origtail = device->buffer_queue_tail;
   491     origlen = origtail ? origtail->datalen : 0;
   492 
   493     while (len > 0) {
   494         SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
   495         SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
   496         if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
   497             /* tail packet missing or completely full; we need a new packet. */
   498             packet = device->buffer_queue_pool;
   499             if (packet != NULL) {
   500                 /* we have one available in the pool. */
   501                 device->buffer_queue_pool = packet->next;
   502             } else {
   503                 /* Have to allocate a new one! */
   504                 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
   505                 if (packet == NULL) {
   506                     /* uhoh, reset so we've queued nothing new, free what we can. */
   507                     if (!origtail) {
   508                         packet = device->buffer_queue_head;  /* whole queue. */
   509                     } else {
   510                         packet = origtail->next;  /* what we added to existing queue. */
   511                         origtail->next = NULL;
   512                         origtail->datalen = origlen;
   513                     }
   514                     device->buffer_queue_head = orighead;
   515                     device->buffer_queue_tail = origtail;
   516                     device->buffer_queue_pool = NULL;
   517 
   518                     current_audio.impl.UnlockDevice(device);
   519 
   520                     free_audio_queue(packet);  /* give back what we can. */
   521 
   522                     return SDL_OutOfMemory();
   523                 }
   524             }
   525             packet->datalen = 0;
   526             packet->startpos = 0;
   527             packet->next = NULL;
   528 
   529             SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
   530             if (device->buffer_queue_tail == NULL) {
   531                 device->buffer_queue_head = packet;
   532             } else {
   533                 device->buffer_queue_tail->next = packet;
   534             }
   535             device->buffer_queue_tail = packet;
   536         }
   537 
   538         datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
   539         SDL_memcpy(packet->data + packet->datalen, data, datalen);
   540         data += datalen;
   541         len -= datalen;
   542         packet->datalen += datalen;
   543         device->queued_bytes += datalen;
   544     }
   545 
   546     current_audio.impl.UnlockDevice(device);
   547 
   548     return 0;
   549 }
   550 
   551 Uint32
   552 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
   553 {
   554     Uint32 retval = 0;
   555     SDL_AudioDevice *device = get_audio_device(devid);
   556 
   557     /* Nothing to do unless we're set up for queueing. */
   558     if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
   559         current_audio.impl.LockDevice(device);
   560         retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
   561         current_audio.impl.UnlockDevice(device);
   562     }
   563 
   564     return retval;
   565 }
   566 
   567 void
   568 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
   569 {
   570     SDL_AudioDevice *device = get_audio_device(devid);
   571     SDL_AudioBufferQueue *buffer = NULL;
   572     if (!device) {
   573         return;  /* nothing to do. */
   574     }
   575 
   576     /* Blank out the device and release the mutex. Free it afterwards. */
   577     current_audio.impl.LockDevice(device);
   578     buffer = device->buffer_queue_head;
   579     device->buffer_queue_tail = NULL;
   580     device->buffer_queue_head = NULL;
   581     device->queued_bytes = 0;
   582     current_audio.impl.UnlockDevice(device);
   583 
   584     free_audio_queue(buffer);
   585 }
   586 
   587 
   588 #if defined(__ANDROID__)
   589 #include <android/log.h>
   590 #endif
   591 
   592 /* The general mixing thread function */
   593 int SDLCALL
   594 SDL_RunAudio(void *devicep)
   595 {
   596     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
   597     const int silence = (int) device->spec.silence;
   598     const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
   599     const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
   600     Uint8 *stream;
   601     void *udata = device->spec.userdata;
   602     void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
   603 
   604     /* The audio mixing is always a high priority thread */
   605     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
   606 
   607     /* Perform any thread setup */
   608     device->threadid = SDL_ThreadID();
   609     current_audio.impl.ThreadInit(device);
   610 
   611     /* Loop, filling the audio buffers */
   612     while (!device->shutdown) {
   613         /* Fill the current buffer with sound */
   614         if (device->convert.needed) {
   615             stream = device->convert.buf;
   616         } else if (device->enabled) {
   617             stream = current_audio.impl.GetDeviceBuf(device);
   618         } else {
   619             /* if the device isn't enabled, we still write to the
   620                fake_stream, so the app's callback will fire with
   621                a regular frequency, in case they depend on that
   622                for timing or progress. They can use hotplug
   623                now to know if the device failed. */
   624             stream = NULL;
   625         }
   626 
   627         if (stream == NULL) {
   628             stream = device->fake_stream;
   629         }
   630 
   631         /* !!! FIXME: this should be LockDevice. */
   632         SDL_LockMutex(device->mixer_lock);
   633         if (device->paused) {
   634             SDL_memset(stream, silence, stream_len);
   635         } else {
   636             (*fill) (udata, stream, stream_len);
   637         }
   638         SDL_UnlockMutex(device->mixer_lock);
   639 
   640         /* Convert the audio if necessary */
   641         if (device->enabled && device->convert.needed) {
   642             SDL_ConvertAudio(&device->convert);
   643             stream = current_audio.impl.GetDeviceBuf(device);
   644             if (stream == NULL) {
   645                 stream = device->fake_stream;
   646             } else {
   647                 SDL_memcpy(stream, device->convert.buf,
   648                            device->convert.len_cvt);
   649             }
   650         }
   651 
   652         /* Ready current buffer for play and change current buffer */
   653         if (stream == device->fake_stream) {
   654             SDL_Delay(delay);
   655         } else {
   656             current_audio.impl.PlayDevice(device);
   657             current_audio.impl.WaitDevice(device);
   658         }
   659     }
   660 
   661     /* Wait for the audio to drain. */
   662     current_audio.impl.WaitDone(device);
   663 
   664     return 0;
   665 }
   666 
   667 
   668 static SDL_AudioFormat
   669 SDL_ParseAudioFormat(const char *string)
   670 {
   671 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
   672     CHECK_FMT_STRING(U8);
   673     CHECK_FMT_STRING(S8);
   674     CHECK_FMT_STRING(U16LSB);
   675     CHECK_FMT_STRING(S16LSB);
   676     CHECK_FMT_STRING(U16MSB);
   677     CHECK_FMT_STRING(S16MSB);
   678     CHECK_FMT_STRING(U16SYS);
   679     CHECK_FMT_STRING(S16SYS);
   680     CHECK_FMT_STRING(U16);
   681     CHECK_FMT_STRING(S16);
   682     CHECK_FMT_STRING(S32LSB);
   683     CHECK_FMT_STRING(S32MSB);
   684     CHECK_FMT_STRING(S32SYS);
   685     CHECK_FMT_STRING(S32);
   686     CHECK_FMT_STRING(F32LSB);
   687     CHECK_FMT_STRING(F32MSB);
   688     CHECK_FMT_STRING(F32SYS);
   689     CHECK_FMT_STRING(F32);
   690 #undef CHECK_FMT_STRING
   691     return 0;
   692 }
   693 
   694 int
   695 SDL_GetNumAudioDrivers(void)
   696 {
   697     return SDL_arraysize(bootstrap) - 1;
   698 }
   699 
   700 const char *
   701 SDL_GetAudioDriver(int index)
   702 {
   703     if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
   704         return bootstrap[index]->name;
   705     }
   706     return NULL;
   707 }
   708 
   709 int
   710 SDL_AudioInit(const char *driver_name)
   711 {
   712     int i = 0;
   713     int initialized = 0;
   714     int tried_to_init = 0;
   715 
   716     if (SDL_WasInit(SDL_INIT_AUDIO)) {
   717         SDL_AudioQuit();        /* shutdown driver if already running. */
   718     }
   719 
   720     SDL_zero(current_audio);
   721     SDL_zero(open_devices);
   722 
   723     /* Select the proper audio driver */
   724     if (driver_name == NULL) {
   725         driver_name = SDL_getenv("SDL_AUDIODRIVER");
   726     }
   727 
   728     for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
   729         /* make sure we should even try this driver before doing so... */
   730         const AudioBootStrap *backend = bootstrap[i];
   731         if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
   732             (!driver_name && backend->demand_only)) {
   733             continue;
   734         }
   735 
   736         tried_to_init = 1;
   737         SDL_zero(current_audio);
   738         current_audio.name = backend->name;
   739         current_audio.desc = backend->desc;
   740         initialized = backend->init(&current_audio.impl);
   741     }
   742 
   743     if (!initialized) {
   744         /* specific drivers will set the error message if they fail... */
   745         if (!tried_to_init) {
   746             if (driver_name) {
   747                 SDL_SetError("Audio target '%s' not available", driver_name);
   748             } else {
   749                 SDL_SetError("No available audio device");
   750             }
   751         }
   752 
   753         SDL_zero(current_audio);
   754         return -1;            /* No driver was available, so fail. */
   755     }
   756 
   757     current_audio.detectionLock = SDL_CreateMutex();
   758 
   759     finalize_audio_entry_points();
   760 
   761     /* Make sure we have a list of devices available at startup. */
   762     current_audio.impl.DetectDevices();
   763 
   764     return 0;
   765 }
   766 
   767 /*
   768  * Get the current audio driver name
   769  */
   770 const char *
   771 SDL_GetCurrentAudioDriver()
   772 {
   773     return current_audio.name;
   774 }
   775 
   776 /* Clean out devices that we've removed but had to keep around for stability. */
   777 static void
   778 clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
   779 {
   780     SDL_AudioDeviceItem *item = *devices;
   781     SDL_AudioDeviceItem *prev = NULL;
   782     int total = 0;
   783 
   784     while (item) {
   785         SDL_AudioDeviceItem *next = item->next;
   786         if (item->handle != NULL) {
   787             total++;
   788             prev = item;
   789         } else {
   790             if (prev) {
   791                 prev->next = next;
   792             } else {
   793                 *devices = next;
   794             }
   795             SDL_free(item);
   796         }
   797         item = next;
   798     }
   799 
   800     *devCount = total;
   801     *removedFlag = SDL_FALSE;
   802 }
   803 
   804 
   805 int
   806 SDL_GetNumAudioDevices(int iscapture)
   807 {
   808     int retval = 0;
   809 
   810     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   811         return -1;
   812     }
   813 
   814     SDL_LockMutex(current_audio.detectionLock);
   815     if (iscapture && current_audio.captureDevicesRemoved) {
   816         clean_out_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
   817     }
   818 
   819     if (!iscapture && current_audio.outputDevicesRemoved) {
   820         clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
   821         current_audio.outputDevicesRemoved = SDL_FALSE;
   822     }
   823 
   824     retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
   825     SDL_UnlockMutex(current_audio.detectionLock);
   826 
   827     return retval;
   828 }
   829 
   830 
   831 const char *
   832 SDL_GetAudioDeviceName(int index, int iscapture)
   833 {
   834     const char *retval = NULL;
   835 
   836     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   837         SDL_SetError("Audio subsystem is not initialized");
   838         return NULL;
   839     }
   840 
   841     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   842         SDL_SetError("No capture support");
   843         return NULL;
   844     }
   845 
   846     if (index >= 0) {
   847         SDL_AudioDeviceItem *item;
   848         int i;
   849 
   850         SDL_LockMutex(current_audio.detectionLock);
   851         item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
   852         i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
   853         if (index < i) {
   854             for (i--; i > index; i--, item = item->next) {
   855                 SDL_assert(item != NULL);
   856             }
   857             SDL_assert(item != NULL);
   858             retval = item->name;
   859         }
   860         SDL_UnlockMutex(current_audio.detectionLock);
   861     }
   862 
   863     if (retval == NULL) {
   864         SDL_SetError("No such device");
   865     }
   866 
   867     return retval;
   868 }
   869 
   870 
   871 static void
   872 close_audio_device(SDL_AudioDevice * device)
   873 {
   874     device->enabled = 0;
   875     device->shutdown = 1;
   876     if (device->thread != NULL) {
   877         SDL_WaitThread(device->thread, NULL);
   878     }
   879     if (device->mixer_lock != NULL) {
   880         SDL_DestroyMutex(device->mixer_lock);
   881     }
   882     SDL_FreeAudioMem(device->fake_stream);
   883     if (device->convert.needed) {
   884         SDL_FreeAudioMem(device->convert.buf);
   885     }
   886     if (device->opened) {
   887         current_audio.impl.CloseDevice(device);
   888         device->opened = 0;
   889     }
   890 
   891     free_audio_queue(device->buffer_queue_head);
   892     free_audio_queue(device->buffer_queue_pool);
   893 
   894     SDL_FreeAudioMem(device);
   895 }
   896 
   897 
   898 /*
   899  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
   900  *  Fills in a sanitized copy in (prepared).
   901  *  Returns non-zero if okay, zero on fatal parameters in (orig).
   902  */
   903 static int
   904 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
   905 {
   906     SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
   907 
   908     if (orig->freq == 0) {
   909         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   910         if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
   911             prepared->freq = 22050;     /* a reasonable default */
   912         }
   913     }
   914 
   915     if (orig->format == 0) {
   916         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
   917         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
   918             prepared->format = AUDIO_S16;       /* a reasonable default */
   919         }
   920     }
   921 
   922     switch (orig->channels) {
   923     case 0:{
   924             const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
   925             if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
   926                 prepared->channels = 2; /* a reasonable default */
   927             }
   928             break;
   929         }
   930     case 1:                    /* Mono */
   931     case 2:                    /* Stereo */
   932     case 4:                    /* surround */
   933     case 6:                    /* surround with center and lfe */
   934         break;
   935     default:
   936         SDL_SetError("Unsupported number of audio channels.");
   937         return 0;
   938     }
   939 
   940     if (orig->samples == 0) {
   941         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
   942         if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
   943             /* Pick a default of ~46 ms at desired frequency */
   944             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
   945             const int samples = (prepared->freq / 1000) * 46;
   946             int power2 = 1;
   947             while (power2 < samples) {
   948                 power2 *= 2;
   949             }
   950             prepared->samples = power2;
   951         }
   952     }
   953 
   954     /* Calculate the silence and size of the audio specification */
   955     SDL_CalculateAudioSpec(prepared);
   956 
   957     return 1;
   958 }
   959 
   960 static SDL_AudioDeviceID
   961 open_audio_device(const char *devname, int iscapture,
   962                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
   963                   int allowed_changes, int min_id)
   964 {
   965     SDL_AudioDeviceID id = 0;
   966     SDL_AudioSpec _obtained;
   967     SDL_AudioDevice *device;
   968     SDL_bool build_cvt;
   969     void *handle = NULL;
   970     int stream_len;
   971     int i = 0;
   972 
   973     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   974         SDL_SetError("Audio subsystem is not initialized");
   975         return 0;
   976     }
   977 
   978     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   979         SDL_SetError("No capture support");
   980         return 0;
   981     }
   982 
   983     /* Find an available device ID... */
   984     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
   985         if (open_devices[id] == NULL) {
   986             break;
   987         }
   988     }
   989 
   990     if (id == SDL_arraysize(open_devices)) {
   991         SDL_SetError("Too many open audio devices");
   992         return 0;
   993     }
   994 
   995     if (!obtained) {
   996         obtained = &_obtained;
   997     }
   998     if (!prepare_audiospec(desired, obtained)) {
   999         return 0;
  1000     }
  1001 
  1002     /* If app doesn't care about a specific device, let the user override. */
  1003     if (devname == NULL) {
  1004         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
  1005     }
  1006 
  1007     /*
  1008      * Catch device names at the high level for the simple case...
  1009      * This lets us have a basic "device enumeration" for systems that
  1010      *  don't have multiple devices, but makes sure the device name is
  1011      *  always NULL when it hits the low level.
  1012      *
  1013      * Also make sure that the simple case prevents multiple simultaneous
  1014      *  opens of the default system device.
  1015      */
  1016 
  1017     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
  1018         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
  1019             SDL_SetError("No such device");
  1020             return 0;
  1021         }
  1022         devname = NULL;
  1023 
  1024         for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1025             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
  1026                 SDL_SetError("Audio device already open");
  1027                 return 0;
  1028             }
  1029         }
  1030     } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
  1031         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
  1032             SDL_SetError("No such device");
  1033             return 0;
  1034         }
  1035         devname = NULL;
  1036 
  1037         for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1038             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
  1039                 SDL_SetError("Audio device already open");
  1040                 return 0;
  1041             }
  1042         }
  1043     } else if (devname != NULL) {
  1044         /* if the app specifies an exact string, we can pass the backend
  1045            an actual device handle thingey, which saves them the effort of
  1046            figuring out what device this was (such as, reenumerating
  1047            everything again to find the matching human-readable name).
  1048            It might still need to open a device based on the string for,
  1049            say, a network audio server, but this optimizes some cases. */
  1050         SDL_AudioDeviceItem *item;
  1051         SDL_LockMutex(current_audio.detectionLock);
  1052         for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
  1053             if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
  1054                 handle = item->handle;
  1055                 break;
  1056             }
  1057         }
  1058         SDL_UnlockMutex(current_audio.detectionLock);
  1059     }
  1060 
  1061     if (!current_audio.impl.AllowsArbitraryDeviceNames) {
  1062         /* has to be in our device list, or the default device. */
  1063         if ((handle == NULL) && (devname != NULL)) {
  1064             SDL_SetError("No such device.");
  1065             return 0;
  1066         }
  1067     }
  1068 
  1069     device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
  1070     if (device == NULL) {
  1071         SDL_OutOfMemory();
  1072         return 0;
  1073     }
  1074     SDL_zerop(device);
  1075     device->id = id + 1;
  1076     device->spec = *obtained;
  1077     device->enabled = 1;
  1078     device->paused = 1;
  1079     device->iscapture = iscapture;
  1080 
  1081     /* Create a mutex for locking the sound buffers */
  1082     if (!current_audio.impl.SkipMixerLock) {
  1083         device->mixer_lock = SDL_CreateMutex();
  1084         if (device->mixer_lock == NULL) {
  1085             close_audio_device(device);
  1086             SDL_SetError("Couldn't create mixer lock");
  1087             return 0;
  1088         }
  1089     }
  1090 
  1091     if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
  1092         close_audio_device(device);
  1093         return 0;
  1094     }
  1095     device->opened = 1;
  1096 
  1097     /* See if we need to do any conversion */
  1098     build_cvt = SDL_FALSE;
  1099     if (obtained->freq != device->spec.freq) {
  1100         if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
  1101             obtained->freq = device->spec.freq;
  1102         } else {
  1103             build_cvt = SDL_TRUE;
  1104         }
  1105     }
  1106     if (obtained->format != device->spec.format) {
  1107         if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
  1108             obtained->format = device->spec.format;
  1109         } else {
  1110             build_cvt = SDL_TRUE;
  1111         }
  1112     }
  1113     if (obtained->channels != device->spec.channels) {
  1114         if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
  1115             obtained->channels = device->spec.channels;
  1116         } else {
  1117             build_cvt = SDL_TRUE;
  1118         }
  1119     }
  1120 
  1121     /* If the audio driver changes the buffer size, accept it.
  1122        This needs to be done after the format is modified above,
  1123        otherwise it might not have the correct buffer size.
  1124      */
  1125     if (device->spec.samples != obtained->samples) {
  1126         obtained->samples = device->spec.samples;
  1127         SDL_CalculateAudioSpec(obtained);
  1128     }
  1129 
  1130     if (build_cvt) {
  1131         /* Build an audio conversion block */
  1132         if (SDL_BuildAudioCVT(&device->convert,
  1133                               obtained->format, obtained->channels,
  1134                               obtained->freq,
  1135                               device->spec.format, device->spec.channels,
  1136                               device->spec.freq) < 0) {
  1137             close_audio_device(device);
  1138             return 0;
  1139         }
  1140         if (device->convert.needed) {
  1141             device->convert.len = (int) (((double) device->spec.size) /
  1142                                          device->convert.len_ratio);
  1143 
  1144             device->convert.buf =
  1145                 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
  1146                                             device->convert.len_mult);
  1147             if (device->convert.buf == NULL) {
  1148                 close_audio_device(device);
  1149                 SDL_OutOfMemory();
  1150                 return 0;
  1151             }
  1152         }
  1153     }
  1154 
  1155     /* Allocate a fake audio memory buffer */
  1156     stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
  1157     if (device->spec.size > stream_len) {
  1158         stream_len = device->spec.size;
  1159     }
  1160     device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
  1161     if (device->fake_stream == NULL) {
  1162         close_audio_device(device);
  1163         SDL_OutOfMemory();
  1164         return 0;
  1165     }
  1166 
  1167     if (device->spec.callback == NULL) {  /* use buffer queueing? */
  1168         /* pool a few packets to start. Enough for two callbacks. */
  1169         const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
  1170         const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
  1171         const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
  1172         for (i = 0; i < wantpackets; i++) {
  1173             SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
  1174             if (packet) { /* don't care if this fails, we'll deal later. */
  1175                 packet->datalen = 0;
  1176                 packet->startpos = 0;
  1177                 packet->next = device->buffer_queue_pool;
  1178                 device->buffer_queue_pool = packet;
  1179             }
  1180         }
  1181 
  1182         device->spec.callback = SDL_BufferQueueDrainCallback;
  1183         device->spec.userdata = device;
  1184     }
  1185 
  1186     /* add it to our list of open devices. */
  1187     open_devices[id] = device;
  1188 
  1189     /* Start the audio thread if necessary */
  1190     if (!current_audio.impl.ProvidesOwnCallbackThread) {
  1191         /* Start the audio thread */
  1192         char name[64];
  1193         SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
  1194 /* !!! FIXME: this is nasty. */
  1195 #if defined(__WIN32__) && !defined(HAVE_LIBC)
  1196 #undef SDL_CreateThread
  1197 #if SDL_DYNAMIC_API
  1198         device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
  1199 #else
  1200         device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
  1201 #endif
  1202 #else
  1203         device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
  1204 #endif
  1205         if (device->thread == NULL) {
  1206             SDL_CloseAudioDevice(device->id);
  1207             SDL_SetError("Couldn't create audio thread");
  1208             return 0;
  1209         }
  1210     }
  1211 
  1212     return device->id;
  1213 }
  1214 
  1215 
  1216 int
  1217 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
  1218 {
  1219     SDL_AudioDeviceID id = 0;
  1220 
  1221     /* Start up the audio driver, if necessary. This is legacy behaviour! */
  1222     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1223         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  1224             return -1;
  1225         }
  1226     }
  1227 
  1228     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  1229     if (open_devices[0] != NULL) {
  1230         SDL_SetError("Audio device is already opened");
  1231         return -1;
  1232     }
  1233 
  1234     if (obtained) {
  1235         id = open_audio_device(NULL, 0, desired, obtained,
  1236                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
  1237     } else {
  1238         id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
  1239     }
  1240 
  1241     SDL_assert((id == 0) || (id == 1));
  1242     return (id == 0) ? -1 : 0;
  1243 }
  1244 
  1245 SDL_AudioDeviceID
  1246 SDL_OpenAudioDevice(const char *device, int iscapture,
  1247                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1248                     int allowed_changes)
  1249 {
  1250     return open_audio_device(device, iscapture, desired, obtained,
  1251                              allowed_changes, 2);
  1252 }
  1253 
  1254 SDL_AudioStatus
  1255 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
  1256 {
  1257     SDL_AudioDevice *device = get_audio_device(devid);
  1258     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
  1259     if (device && device->enabled) {
  1260         if (device->paused) {
  1261             status = SDL_AUDIO_PAUSED;
  1262         } else {
  1263             status = SDL_AUDIO_PLAYING;
  1264         }
  1265     }
  1266     return status;
  1267 }
  1268 
  1269 
  1270 SDL_AudioStatus
  1271 SDL_GetAudioStatus(void)
  1272 {
  1273     return SDL_GetAudioDeviceStatus(1);
  1274 }
  1275 
  1276 void
  1277 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
  1278 {
  1279     SDL_AudioDevice *device = get_audio_device(devid);
  1280     if (device) {
  1281         current_audio.impl.LockDevice(device);
  1282         device->paused = pause_on;
  1283         current_audio.impl.UnlockDevice(device);
  1284     }
  1285 }
  1286 
  1287 void
  1288 SDL_PauseAudio(int pause_on)
  1289 {
  1290     SDL_PauseAudioDevice(1, pause_on);
  1291 }
  1292 
  1293 
  1294 void
  1295 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
  1296 {
  1297     /* Obtain a lock on the mixing buffers */
  1298     SDL_AudioDevice *device = get_audio_device(devid);
  1299     if (device) {
  1300         current_audio.impl.LockDevice(device);
  1301     }
  1302 }
  1303 
  1304 void
  1305 SDL_LockAudio(void)
  1306 {
  1307     SDL_LockAudioDevice(1);
  1308 }
  1309 
  1310 void
  1311 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
  1312 {
  1313     /* Obtain a lock on the mixing buffers */
  1314     SDL_AudioDevice *device = get_audio_device(devid);
  1315     if (device) {
  1316         current_audio.impl.UnlockDevice(device);
  1317     }
  1318 }
  1319 
  1320 void
  1321 SDL_UnlockAudio(void)
  1322 {
  1323     SDL_UnlockAudioDevice(1);
  1324 }
  1325 
  1326 void
  1327 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
  1328 {
  1329     SDL_AudioDevice *device = get_audio_device(devid);
  1330     if (device) {
  1331         close_audio_device(device);
  1332         open_devices[devid - 1] = NULL;
  1333     }
  1334 }
  1335 
  1336 void
  1337 SDL_CloseAudio(void)
  1338 {
  1339     SDL_CloseAudioDevice(1);
  1340 }
  1341 
  1342 void
  1343 SDL_AudioQuit(void)
  1344 {
  1345     SDL_AudioDeviceID i;
  1346 
  1347     if (!current_audio.name) {  /* not initialized?! */
  1348         return;
  1349     }
  1350 
  1351     for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1352         if (open_devices[i] != NULL) {
  1353             SDL_CloseAudioDevice(i+1);
  1354         }
  1355     }
  1356 
  1357     free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
  1358     free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
  1359 
  1360     /* Free the driver data */
  1361     current_audio.impl.Deinitialize();
  1362 
  1363     SDL_DestroyMutex(current_audio.detectionLock);
  1364 
  1365     SDL_zero(current_audio);
  1366     SDL_zero(open_devices);
  1367 }
  1368 
  1369 #define NUM_FORMATS 10
  1370 static int format_idx;
  1371 static int format_idx_sub;
  1372 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
  1373     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1374      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1375     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1376      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1377     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
  1378      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1379     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
  1380      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1381     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
  1382      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1383     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
  1384      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1385     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
  1386      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1387     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
  1388      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1389     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
  1390      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1391     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
  1392      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1393 };
  1394 
  1395 SDL_AudioFormat
  1396 SDL_FirstAudioFormat(SDL_AudioFormat format)
  1397 {
  1398     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
  1399         if (format_list[format_idx][0] == format) {
  1400             break;
  1401         }
  1402     }
  1403     format_idx_sub = 0;
  1404     return SDL_NextAudioFormat();
  1405 }
  1406 
  1407 SDL_AudioFormat
  1408 SDL_NextAudioFormat(void)
  1409 {
  1410     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
  1411         return 0;
  1412     }
  1413     return format_list[format_idx][format_idx_sub++];
  1414 }
  1415 
  1416 void
  1417 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
  1418 {
  1419     switch (spec->format) {
  1420     case AUDIO_U8:
  1421         spec->silence = 0x80;
  1422         break;
  1423     default:
  1424         spec->silence = 0x00;
  1425         break;
  1426     }
  1427     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  1428     spec->size *= spec->channels;
  1429     spec->size *= spec->samples;
  1430 }
  1431 
  1432 
  1433 /*
  1434  * Moved here from SDL_mixer.c, since it relies on internals of an opened
  1435  *  audio device (and is deprecated, by the way!).
  1436  */
  1437 void
  1438 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
  1439 {
  1440     /* Mix the user-level audio format */
  1441     SDL_AudioDevice *device = get_audio_device(1);
  1442     if (device != NULL) {
  1443         SDL_AudioFormat format;
  1444         if (device->convert.needed) {
  1445             format = device->convert.src_format;
  1446         } else {
  1447             format = device->spec.format;
  1448         }
  1449         SDL_MixAudioFormat(dst, src, format, len, volume);
  1450     }
  1451 }
  1452 
  1453 /* vi: set ts=4 sw=4 expandtab: */