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