src/audio/SDL_audio.c
author Ryan C. Gordon <icculus@icculus.org>
Tue, 26 May 2015 21:19:23 -0400
changeset 9649 d7762e30ba24
parent 9619 b94b6d0bff0f
child 9998 f67cf37e9cd4
permissions -rw-r--r--
Stack hint should look for 0, not -1, and not care about environment variables.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2015 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);  /* we reserve NULL, audio backends can't use it. */
   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 /* The general mixing thread function */
   594 int SDLCALL
   595 SDL_RunAudio(void *devicep)
   596 {
   597     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
   598     const int silence = (int) device->spec.silence;
   599     const Uint32 delay = ((device->spec.samples * 1000) / device->spec.freq);
   600     const int stream_len = (device->convert.needed) ? device->convert.len : device->spec.size;
   601     Uint8 *stream;
   602     void *udata = device->spec.userdata;
   603     void (SDLCALL *fill) (void *, Uint8 *, int) = device->spec.callback;
   604 
   605     /* The audio mixing is always a high priority thread */
   606     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
   607 
   608     /* Perform any thread setup */
   609     device->threadid = SDL_ThreadID();
   610     current_audio.impl.ThreadInit(device);
   611 
   612     /* Loop, filling the audio buffers */
   613     while (!device->shutdown) {
   614         /* Fill the current buffer with sound */
   615         if (device->convert.needed) {
   616             stream = device->convert.buf;
   617         } else if (device->enabled) {
   618             stream = current_audio.impl.GetDeviceBuf(device);
   619         } else {
   620             /* if the device isn't enabled, we still write to the
   621                fake_stream, so the app's callback will fire with
   622                a regular frequency, in case they depend on that
   623                for timing or progress. They can use hotplug
   624                now to know if the device failed. */
   625             stream = NULL;
   626         }
   627 
   628         if (stream == NULL) {
   629             stream = device->fake_stream;
   630         }
   631 
   632         /* !!! FIXME: this should be LockDevice. */
   633         SDL_LockMutex(device->mixer_lock);
   634         if (device->paused) {
   635             SDL_memset(stream, silence, stream_len);
   636         } else {
   637             (*fill) (udata, stream, stream_len);
   638         }
   639         SDL_UnlockMutex(device->mixer_lock);
   640 
   641         /* Convert the audio if necessary */
   642         if (device->enabled && device->convert.needed) {
   643             SDL_ConvertAudio(&device->convert);
   644             stream = current_audio.impl.GetDeviceBuf(device);
   645             if (stream == NULL) {
   646                 stream = device->fake_stream;
   647             } else {
   648                 SDL_memcpy(stream, device->convert.buf,
   649                            device->convert.len_cvt);
   650             }
   651         }
   652 
   653         /* Ready current buffer for play and change current buffer */
   654         if (stream == device->fake_stream) {
   655             SDL_Delay(delay);
   656         } else {
   657             current_audio.impl.PlayDevice(device);
   658             current_audio.impl.WaitDevice(device);
   659         }
   660     }
   661 
   662     /* Wait for the audio to drain. */
   663     current_audio.impl.WaitDone(device);
   664 
   665     return 0;
   666 }
   667 
   668 
   669 static SDL_AudioFormat
   670 SDL_ParseAudioFormat(const char *string)
   671 {
   672 #define CHECK_FMT_STRING(x) if (SDL_strcmp(string, #x) == 0) return AUDIO_##x
   673     CHECK_FMT_STRING(U8);
   674     CHECK_FMT_STRING(S8);
   675     CHECK_FMT_STRING(U16LSB);
   676     CHECK_FMT_STRING(S16LSB);
   677     CHECK_FMT_STRING(U16MSB);
   678     CHECK_FMT_STRING(S16MSB);
   679     CHECK_FMT_STRING(U16SYS);
   680     CHECK_FMT_STRING(S16SYS);
   681     CHECK_FMT_STRING(U16);
   682     CHECK_FMT_STRING(S16);
   683     CHECK_FMT_STRING(S32LSB);
   684     CHECK_FMT_STRING(S32MSB);
   685     CHECK_FMT_STRING(S32SYS);
   686     CHECK_FMT_STRING(S32);
   687     CHECK_FMT_STRING(F32LSB);
   688     CHECK_FMT_STRING(F32MSB);
   689     CHECK_FMT_STRING(F32SYS);
   690     CHECK_FMT_STRING(F32);
   691 #undef CHECK_FMT_STRING
   692     return 0;
   693 }
   694 
   695 int
   696 SDL_GetNumAudioDrivers(void)
   697 {
   698     return SDL_arraysize(bootstrap) - 1;
   699 }
   700 
   701 const char *
   702 SDL_GetAudioDriver(int index)
   703 {
   704     if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
   705         return bootstrap[index]->name;
   706     }
   707     return NULL;
   708 }
   709 
   710 int
   711 SDL_AudioInit(const char *driver_name)
   712 {
   713     int i = 0;
   714     int initialized = 0;
   715     int tried_to_init = 0;
   716 
   717     if (SDL_WasInit(SDL_INIT_AUDIO)) {
   718         SDL_AudioQuit();        /* shutdown driver if already running. */
   719     }
   720 
   721     SDL_zero(current_audio);
   722     SDL_zero(open_devices);
   723 
   724     /* Select the proper audio driver */
   725     if (driver_name == NULL) {
   726         driver_name = SDL_getenv("SDL_AUDIODRIVER");
   727     }
   728 
   729     for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
   730         /* make sure we should even try this driver before doing so... */
   731         const AudioBootStrap *backend = bootstrap[i];
   732         if ((driver_name && (SDL_strncasecmp(backend->name, driver_name, SDL_strlen(driver_name)) != 0)) ||
   733             (!driver_name && backend->demand_only)) {
   734             continue;
   735         }
   736 
   737         tried_to_init = 1;
   738         SDL_zero(current_audio);
   739         current_audio.name = backend->name;
   740         current_audio.desc = backend->desc;
   741         initialized = backend->init(&current_audio.impl);
   742     }
   743 
   744     if (!initialized) {
   745         /* specific drivers will set the error message if they fail... */
   746         if (!tried_to_init) {
   747             if (driver_name) {
   748                 SDL_SetError("Audio target '%s' not available", driver_name);
   749             } else {
   750                 SDL_SetError("No available audio device");
   751             }
   752         }
   753 
   754         SDL_zero(current_audio);
   755         return -1;            /* No driver was available, so fail. */
   756     }
   757 
   758     current_audio.detectionLock = SDL_CreateMutex();
   759 
   760     finalize_audio_entry_points();
   761 
   762     /* Make sure we have a list of devices available at startup. */
   763     current_audio.impl.DetectDevices();
   764 
   765     return 0;
   766 }
   767 
   768 /*
   769  * Get the current audio driver name
   770  */
   771 const char *
   772 SDL_GetCurrentAudioDriver()
   773 {
   774     return current_audio.name;
   775 }
   776 
   777 /* Clean out devices that we've removed but had to keep around for stability. */
   778 static void
   779 clean_out_device_list(SDL_AudioDeviceItem **devices, int *devCount, SDL_bool *removedFlag)
   780 {
   781     SDL_AudioDeviceItem *item = *devices;
   782     SDL_AudioDeviceItem *prev = NULL;
   783     int total = 0;
   784 
   785     while (item) {
   786         SDL_AudioDeviceItem *next = item->next;
   787         if (item->handle != NULL) {
   788             total++;
   789             prev = item;
   790         } else {
   791             if (prev) {
   792                 prev->next = next;
   793             } else {
   794                 *devices = next;
   795             }
   796             SDL_free(item);
   797         }
   798         item = next;
   799     }
   800 
   801     *devCount = total;
   802     *removedFlag = SDL_FALSE;
   803 }
   804 
   805 
   806 int
   807 SDL_GetNumAudioDevices(int iscapture)
   808 {
   809     int retval = 0;
   810 
   811     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   812         return -1;
   813     }
   814 
   815     SDL_LockMutex(current_audio.detectionLock);
   816     if (iscapture && current_audio.captureDevicesRemoved) {
   817         clean_out_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount, &current_audio.captureDevicesRemoved);
   818     }
   819 
   820     if (!iscapture && current_audio.outputDevicesRemoved) {
   821         clean_out_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount, &current_audio.outputDevicesRemoved);
   822         current_audio.outputDevicesRemoved = SDL_FALSE;
   823     }
   824 
   825     retval = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
   826     SDL_UnlockMutex(current_audio.detectionLock);
   827 
   828     return retval;
   829 }
   830 
   831 
   832 const char *
   833 SDL_GetAudioDeviceName(int index, int iscapture)
   834 {
   835     const char *retval = NULL;
   836 
   837     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   838         SDL_SetError("Audio subsystem is not initialized");
   839         return NULL;
   840     }
   841 
   842     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   843         SDL_SetError("No capture support");
   844         return NULL;
   845     }
   846 
   847     if (index >= 0) {
   848         SDL_AudioDeviceItem *item;
   849         int i;
   850 
   851         SDL_LockMutex(current_audio.detectionLock);
   852         item = iscapture ? current_audio.inputDevices : current_audio.outputDevices;
   853         i = iscapture ? current_audio.inputDeviceCount : current_audio.outputDeviceCount;
   854         if (index < i) {
   855             for (i--; i > index; i--, item = item->next) {
   856                 SDL_assert(item != NULL);
   857             }
   858             SDL_assert(item != NULL);
   859             retval = item->name;
   860         }
   861         SDL_UnlockMutex(current_audio.detectionLock);
   862     }
   863 
   864     if (retval == NULL) {
   865         SDL_SetError("No such device");
   866     }
   867 
   868     return retval;
   869 }
   870 
   871 
   872 static void
   873 close_audio_device(SDL_AudioDevice * device)
   874 {
   875     device->enabled = 0;
   876     device->shutdown = 1;
   877     if (device->thread != NULL) {
   878         SDL_WaitThread(device->thread, NULL);
   879     }
   880     if (device->mixer_lock != NULL) {
   881         SDL_DestroyMutex(device->mixer_lock);
   882     }
   883     SDL_FreeAudioMem(device->fake_stream);
   884     if (device->convert.needed) {
   885         SDL_FreeAudioMem(device->convert.buf);
   886     }
   887     if (device->opened) {
   888         current_audio.impl.CloseDevice(device);
   889         device->opened = 0;
   890     }
   891 
   892     free_audio_queue(device->buffer_queue_head);
   893     free_audio_queue(device->buffer_queue_pool);
   894 
   895     SDL_FreeAudioMem(device);
   896 }
   897 
   898 
   899 /*
   900  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
   901  *  Fills in a sanitized copy in (prepared).
   902  *  Returns non-zero if okay, zero on fatal parameters in (orig).
   903  */
   904 static int
   905 prepare_audiospec(const SDL_AudioSpec * orig, SDL_AudioSpec * prepared)
   906 {
   907     SDL_memcpy(prepared, orig, sizeof(SDL_AudioSpec));
   908 
   909     if (orig->freq == 0) {
   910         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   911         if ((!env) || ((prepared->freq = SDL_atoi(env)) == 0)) {
   912             prepared->freq = 22050;     /* a reasonable default */
   913         }
   914     }
   915 
   916     if (orig->format == 0) {
   917         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
   918         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
   919             prepared->format = AUDIO_S16;       /* a reasonable default */
   920         }
   921     }
   922 
   923     switch (orig->channels) {
   924     case 0:{
   925             const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
   926             if ((!env) || ((prepared->channels = (Uint8) SDL_atoi(env)) == 0)) {
   927                 prepared->channels = 2; /* a reasonable default */
   928             }
   929             break;
   930         }
   931     case 1:                    /* Mono */
   932     case 2:                    /* Stereo */
   933     case 4:                    /* surround */
   934     case 6:                    /* surround with center and lfe */
   935         break;
   936     default:
   937         SDL_SetError("Unsupported number of audio channels.");
   938         return 0;
   939     }
   940 
   941     if (orig->samples == 0) {
   942         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
   943         if ((!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0)) {
   944             /* Pick a default of ~46 ms at desired frequency */
   945             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
   946             const int samples = (prepared->freq / 1000) * 46;
   947             int power2 = 1;
   948             while (power2 < samples) {
   949                 power2 *= 2;
   950             }
   951             prepared->samples = power2;
   952         }
   953     }
   954 
   955     /* Calculate the silence and size of the audio specification */
   956     SDL_CalculateAudioSpec(prepared);
   957 
   958     return 1;
   959 }
   960 
   961 static SDL_AudioDeviceID
   962 open_audio_device(const char *devname, int iscapture,
   963                   const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
   964                   int allowed_changes, int min_id)
   965 {
   966     SDL_AudioDeviceID id = 0;
   967     SDL_AudioSpec _obtained;
   968     SDL_AudioDevice *device;
   969     SDL_bool build_cvt;
   970     void *handle = NULL;
   971     Uint32 stream_len;
   972     int i = 0;
   973 
   974     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   975         SDL_SetError("Audio subsystem is not initialized");
   976         return 0;
   977     }
   978 
   979     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   980         SDL_SetError("No capture support");
   981         return 0;
   982     }
   983 
   984     /* Find an available device ID... */
   985     for (id = min_id - 1; id < SDL_arraysize(open_devices); id++) {
   986         if (open_devices[id] == NULL) {
   987             break;
   988         }
   989     }
   990 
   991     if (id == SDL_arraysize(open_devices)) {
   992         SDL_SetError("Too many open audio devices");
   993         return 0;
   994     }
   995 
   996     if (!obtained) {
   997         obtained = &_obtained;
   998     }
   999     if (!prepare_audiospec(desired, obtained)) {
  1000         return 0;
  1001     }
  1002 
  1003     /* If app doesn't care about a specific device, let the user override. */
  1004     if (devname == NULL) {
  1005         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
  1006     }
  1007 
  1008     /*
  1009      * Catch device names at the high level for the simple case...
  1010      * This lets us have a basic "device enumeration" for systems that
  1011      *  don't have multiple devices, but makes sure the device name is
  1012      *  always NULL when it hits the low level.
  1013      *
  1014      * Also make sure that the simple case prevents multiple simultaneous
  1015      *  opens of the default system device.
  1016      */
  1017 
  1018     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
  1019         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
  1020             SDL_SetError("No such device");
  1021             return 0;
  1022         }
  1023         devname = NULL;
  1024 
  1025         for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1026             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
  1027                 SDL_SetError("Audio device already open");
  1028                 return 0;
  1029             }
  1030         }
  1031     } else if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
  1032         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
  1033             SDL_SetError("No such device");
  1034             return 0;
  1035         }
  1036         devname = NULL;
  1037 
  1038         for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1039             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
  1040                 SDL_SetError("Audio device already open");
  1041                 return 0;
  1042             }
  1043         }
  1044     } else if (devname != NULL) {
  1045         /* if the app specifies an exact string, we can pass the backend
  1046            an actual device handle thingey, which saves them the effort of
  1047            figuring out what device this was (such as, reenumerating
  1048            everything again to find the matching human-readable name).
  1049            It might still need to open a device based on the string for,
  1050            say, a network audio server, but this optimizes some cases. */
  1051         SDL_AudioDeviceItem *item;
  1052         SDL_LockMutex(current_audio.detectionLock);
  1053         for (item = iscapture ? current_audio.inputDevices : current_audio.outputDevices; item; item = item->next) {
  1054             if ((item->handle != NULL) && (SDL_strcmp(item->name, devname) == 0)) {
  1055                 handle = item->handle;
  1056                 break;
  1057             }
  1058         }
  1059         SDL_UnlockMutex(current_audio.detectionLock);
  1060     }
  1061 
  1062     if (!current_audio.impl.AllowsArbitraryDeviceNames) {
  1063         /* has to be in our device list, or the default device. */
  1064         if ((handle == NULL) && (devname != NULL)) {
  1065             SDL_SetError("No such device.");
  1066             return 0;
  1067         }
  1068     }
  1069 
  1070     device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof(SDL_AudioDevice));
  1071     if (device == NULL) {
  1072         SDL_OutOfMemory();
  1073         return 0;
  1074     }
  1075     SDL_zerop(device);
  1076     device->id = id + 1;
  1077     device->spec = *obtained;
  1078     device->enabled = 1;
  1079     device->paused = 1;
  1080     device->iscapture = iscapture;
  1081 
  1082     /* Create a mutex for locking the sound buffers */
  1083     if (!current_audio.impl.SkipMixerLock) {
  1084         device->mixer_lock = SDL_CreateMutex();
  1085         if (device->mixer_lock == NULL) {
  1086             close_audio_device(device);
  1087             SDL_SetError("Couldn't create mixer lock");
  1088             return 0;
  1089         }
  1090     }
  1091 
  1092     if (current_audio.impl.OpenDevice(device, handle, devname, iscapture) < 0) {
  1093         close_audio_device(device);
  1094         return 0;
  1095     }
  1096     device->opened = 1;
  1097 
  1098     /* See if we need to do any conversion */
  1099     build_cvt = SDL_FALSE;
  1100     if (obtained->freq != device->spec.freq) {
  1101         if (allowed_changes & SDL_AUDIO_ALLOW_FREQUENCY_CHANGE) {
  1102             obtained->freq = device->spec.freq;
  1103         } else {
  1104             build_cvt = SDL_TRUE;
  1105         }
  1106     }
  1107     if (obtained->format != device->spec.format) {
  1108         if (allowed_changes & SDL_AUDIO_ALLOW_FORMAT_CHANGE) {
  1109             obtained->format = device->spec.format;
  1110         } else {
  1111             build_cvt = SDL_TRUE;
  1112         }
  1113     }
  1114     if (obtained->channels != device->spec.channels) {
  1115         if (allowed_changes & SDL_AUDIO_ALLOW_CHANNELS_CHANGE) {
  1116             obtained->channels = device->spec.channels;
  1117         } else {
  1118             build_cvt = SDL_TRUE;
  1119         }
  1120     }
  1121 
  1122     /* If the audio driver changes the buffer size, accept it.
  1123        This needs to be done after the format is modified above,
  1124        otherwise it might not have the correct buffer size.
  1125      */
  1126     if (device->spec.samples != obtained->samples) {
  1127         obtained->samples = device->spec.samples;
  1128         SDL_CalculateAudioSpec(obtained);
  1129     }
  1130 
  1131     if (build_cvt) {
  1132         /* Build an audio conversion block */
  1133         if (SDL_BuildAudioCVT(&device->convert,
  1134                               obtained->format, obtained->channels,
  1135                               obtained->freq,
  1136                               device->spec.format, device->spec.channels,
  1137                               device->spec.freq) < 0) {
  1138             close_audio_device(device);
  1139             return 0;
  1140         }
  1141         if (device->convert.needed) {
  1142             device->convert.len = (int) (((double) device->spec.size) /
  1143                                          device->convert.len_ratio);
  1144 
  1145             device->convert.buf =
  1146                 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
  1147                                             device->convert.len_mult);
  1148             if (device->convert.buf == NULL) {
  1149                 close_audio_device(device);
  1150                 SDL_OutOfMemory();
  1151                 return 0;
  1152             }
  1153         }
  1154     }
  1155 
  1156     /* Allocate a fake audio memory buffer */
  1157     stream_len = (device->convert.needed) ? device->convert.len_cvt : 0;
  1158     if (device->spec.size > stream_len) {
  1159         stream_len = device->spec.size;
  1160     }
  1161     SDL_assert(stream_len > 0);
  1162     device->fake_stream = (Uint8 *)SDL_AllocAudioMem(stream_len);
  1163     if (device->fake_stream == NULL) {
  1164         close_audio_device(device);
  1165         SDL_OutOfMemory();
  1166         return 0;
  1167     }
  1168 
  1169     if (device->spec.callback == NULL) {  /* use buffer queueing? */
  1170         /* pool a few packets to start. Enough for two callbacks. */
  1171         const int packetlen = SDL_AUDIOBUFFERQUEUE_PACKETLEN;
  1172         const int wantbytes = ((device->convert.needed) ? device->convert.len : device->spec.size) * 2;
  1173         const int wantpackets = (wantbytes / packetlen) + ((wantbytes % packetlen) ? packetlen : 0);
  1174         for (i = 0; i < wantpackets; i++) {
  1175             SDL_AudioBufferQueue *packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
  1176             if (packet) { /* don't care if this fails, we'll deal later. */
  1177                 packet->datalen = 0;
  1178                 packet->startpos = 0;
  1179                 packet->next = device->buffer_queue_pool;
  1180                 device->buffer_queue_pool = packet;
  1181             }
  1182         }
  1183 
  1184         device->spec.callback = SDL_BufferQueueDrainCallback;
  1185         device->spec.userdata = device;
  1186     }
  1187 
  1188     /* add it to our list of open devices. */
  1189     open_devices[id] = device;
  1190 
  1191     /* Start the audio thread if necessary */
  1192     if (!current_audio.impl.ProvidesOwnCallbackThread) {
  1193         /* Start the audio thread */
  1194         char name[64];
  1195         SDL_snprintf(name, sizeof (name), "SDLAudioDev%d", (int) device->id);
  1196 /* !!! FIXME: this is nasty. */
  1197 #if defined(__WIN32__) && !defined(HAVE_LIBC)
  1198 #undef SDL_CreateThread
  1199 #if SDL_DYNAMIC_API
  1200         device->thread = SDL_CreateThread_REAL(SDL_RunAudio, name, device, NULL, NULL);
  1201 #else
  1202         device->thread = SDL_CreateThread(SDL_RunAudio, name, device, NULL, NULL);
  1203 #endif
  1204 #else
  1205         device->thread = SDL_CreateThread(SDL_RunAudio, name, device);
  1206 #endif
  1207         if (device->thread == NULL) {
  1208             SDL_CloseAudioDevice(device->id);
  1209             SDL_SetError("Couldn't create audio thread");
  1210             return 0;
  1211         }
  1212     }
  1213 
  1214     return device->id;
  1215 }
  1216 
  1217 
  1218 int
  1219 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
  1220 {
  1221     SDL_AudioDeviceID id = 0;
  1222 
  1223     /* Start up the audio driver, if necessary. This is legacy behaviour! */
  1224     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
  1225         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
  1226             return -1;
  1227         }
  1228     }
  1229 
  1230     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
  1231     if (open_devices[0] != NULL) {
  1232         SDL_SetError("Audio device is already opened");
  1233         return -1;
  1234     }
  1235 
  1236     if (obtained) {
  1237         id = open_audio_device(NULL, 0, desired, obtained,
  1238                                SDL_AUDIO_ALLOW_ANY_CHANGE, 1);
  1239     } else {
  1240         id = open_audio_device(NULL, 0, desired, NULL, 0, 1);
  1241     }
  1242 
  1243     SDL_assert((id == 0) || (id == 1));
  1244     return (id == 0) ? -1 : 0;
  1245 }
  1246 
  1247 SDL_AudioDeviceID
  1248 SDL_OpenAudioDevice(const char *device, int iscapture,
  1249                     const SDL_AudioSpec * desired, SDL_AudioSpec * obtained,
  1250                     int allowed_changes)
  1251 {
  1252     return open_audio_device(device, iscapture, desired, obtained,
  1253                              allowed_changes, 2);
  1254 }
  1255 
  1256 SDL_AudioStatus
  1257 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
  1258 {
  1259     SDL_AudioDevice *device = get_audio_device(devid);
  1260     SDL_AudioStatus status = SDL_AUDIO_STOPPED;
  1261     if (device && device->enabled) {
  1262         if (device->paused) {
  1263             status = SDL_AUDIO_PAUSED;
  1264         } else {
  1265             status = SDL_AUDIO_PLAYING;
  1266         }
  1267     }
  1268     return status;
  1269 }
  1270 
  1271 
  1272 SDL_AudioStatus
  1273 SDL_GetAudioStatus(void)
  1274 {
  1275     return SDL_GetAudioDeviceStatus(1);
  1276 }
  1277 
  1278 void
  1279 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
  1280 {
  1281     SDL_AudioDevice *device = get_audio_device(devid);
  1282     if (device) {
  1283         current_audio.impl.LockDevice(device);
  1284         device->paused = pause_on;
  1285         current_audio.impl.UnlockDevice(device);
  1286     }
  1287 }
  1288 
  1289 void
  1290 SDL_PauseAudio(int pause_on)
  1291 {
  1292     SDL_PauseAudioDevice(1, pause_on);
  1293 }
  1294 
  1295 
  1296 void
  1297 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
  1298 {
  1299     /* Obtain a lock on the mixing buffers */
  1300     SDL_AudioDevice *device = get_audio_device(devid);
  1301     if (device) {
  1302         current_audio.impl.LockDevice(device);
  1303     }
  1304 }
  1305 
  1306 void
  1307 SDL_LockAudio(void)
  1308 {
  1309     SDL_LockAudioDevice(1);
  1310 }
  1311 
  1312 void
  1313 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
  1314 {
  1315     /* Obtain a lock on the mixing buffers */
  1316     SDL_AudioDevice *device = get_audio_device(devid);
  1317     if (device) {
  1318         current_audio.impl.UnlockDevice(device);
  1319     }
  1320 }
  1321 
  1322 void
  1323 SDL_UnlockAudio(void)
  1324 {
  1325     SDL_UnlockAudioDevice(1);
  1326 }
  1327 
  1328 void
  1329 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
  1330 {
  1331     SDL_AudioDevice *device = get_audio_device(devid);
  1332     if (device) {
  1333         close_audio_device(device);
  1334         open_devices[devid - 1] = NULL;
  1335     }
  1336 }
  1337 
  1338 void
  1339 SDL_CloseAudio(void)
  1340 {
  1341     SDL_CloseAudioDevice(1);
  1342 }
  1343 
  1344 void
  1345 SDL_AudioQuit(void)
  1346 {
  1347     SDL_AudioDeviceID i;
  1348 
  1349     if (!current_audio.name) {  /* not initialized?! */
  1350         return;
  1351     }
  1352 
  1353     for (i = 0; i < SDL_arraysize(open_devices); i++) {
  1354         if (open_devices[i] != NULL) {
  1355             SDL_CloseAudioDevice(i+1);
  1356         }
  1357     }
  1358 
  1359     free_device_list(&current_audio.outputDevices, &current_audio.outputDeviceCount);
  1360     free_device_list(&current_audio.inputDevices, &current_audio.inputDeviceCount);
  1361 
  1362     /* Free the driver data */
  1363     current_audio.impl.Deinitialize();
  1364 
  1365     SDL_DestroyMutex(current_audio.detectionLock);
  1366 
  1367     SDL_zero(current_audio);
  1368     SDL_zero(open_devices);
  1369 }
  1370 
  1371 #define NUM_FORMATS 10
  1372 static int format_idx;
  1373 static int format_idx_sub;
  1374 static SDL_AudioFormat format_list[NUM_FORMATS][NUM_FORMATS] = {
  1375     {AUDIO_U8, AUDIO_S8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1376      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1377     {AUDIO_S8, AUDIO_U8, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB,
  1378      AUDIO_U16MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB},
  1379     {AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S32LSB,
  1380      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1381     {AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S32MSB,
  1382      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1383     {AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_S16LSB, AUDIO_S16MSB, AUDIO_S32LSB,
  1384      AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_U8, AUDIO_S8},
  1385     {AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_S16MSB, AUDIO_S16LSB, AUDIO_S32MSB,
  1386      AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_U8, AUDIO_S8},
  1387     {AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S16LSB,
  1388      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1389     {AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S16MSB,
  1390      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1391     {AUDIO_F32LSB, AUDIO_F32MSB, AUDIO_S32LSB, AUDIO_S32MSB, AUDIO_S16LSB,
  1392      AUDIO_S16MSB, AUDIO_U16LSB, AUDIO_U16MSB, AUDIO_U8, AUDIO_S8},
  1393     {AUDIO_F32MSB, AUDIO_F32LSB, AUDIO_S32MSB, AUDIO_S32LSB, AUDIO_S16MSB,
  1394      AUDIO_S16LSB, AUDIO_U16MSB, AUDIO_U16LSB, AUDIO_U8, AUDIO_S8},
  1395 };
  1396 
  1397 SDL_AudioFormat
  1398 SDL_FirstAudioFormat(SDL_AudioFormat format)
  1399 {
  1400     for (format_idx = 0; format_idx < NUM_FORMATS; ++format_idx) {
  1401         if (format_list[format_idx][0] == format) {
  1402             break;
  1403         }
  1404     }
  1405     format_idx_sub = 0;
  1406     return SDL_NextAudioFormat();
  1407 }
  1408 
  1409 SDL_AudioFormat
  1410 SDL_NextAudioFormat(void)
  1411 {
  1412     if ((format_idx == NUM_FORMATS) || (format_idx_sub == NUM_FORMATS)) {
  1413         return 0;
  1414     }
  1415     return format_list[format_idx][format_idx_sub++];
  1416 }
  1417 
  1418 void
  1419 SDL_CalculateAudioSpec(SDL_AudioSpec * spec)
  1420 {
  1421     switch (spec->format) {
  1422     case AUDIO_U8:
  1423         spec->silence = 0x80;
  1424         break;
  1425     default:
  1426         spec->silence = 0x00;
  1427         break;
  1428     }
  1429     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
  1430     spec->size *= spec->channels;
  1431     spec->size *= spec->samples;
  1432 }
  1433 
  1434 
  1435 /*
  1436  * Moved here from SDL_mixer.c, since it relies on internals of an opened
  1437  *  audio device (and is deprecated, by the way!).
  1438  */
  1439 void
  1440 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
  1441 {
  1442     /* Mix the user-level audio format */
  1443     SDL_AudioDevice *device = get_audio_device(1);
  1444     if (device != NULL) {
  1445         SDL_AudioFormat format;
  1446         if (device->convert.needed) {
  1447             format = device->convert.src_format;
  1448         } else {
  1449             format = device->spec.format;
  1450         }
  1451         SDL_MixAudioFormat(dst, src, format, len, volume);
  1452     }
  1453 }
  1454 
  1455 /* vi: set ts=4 sw=4 expandtab: */