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