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