src/audio/SDL_audio.c
author Ryan C. Gordon
Thu, 19 Mar 2015 22:11:20 -0400
changeset 9401 529007547fb6
parent 9399 a684dbd185c7
child 9404 f48039db971c
permissions -rw-r--r--
Zero out the audio hotplug event structure, so the "padded" fields are sane.

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