src/audio/SDL_audio.c
author Philipp Wiesemann <philipp.wiesemann@arcor.de>
Sun, 22 Feb 2015 23:21:32 +0100
changeset 9373 679eb3986e37
parent 9278 8900afb78a19
child 9381 812b2dabf8a4
permissions -rw-r--r--
Emscripten: Fixed out of range joystick device index after joystick disconnect.

After disconnecting a joystick the remaining kept their original device index.
This was not correct because the device index must be a number between 0 and
SDL_NumJoysticks(). It was fixed with ideas from SDL's joystick implementation
for Android. Some range checks were removed as the caller already checks them.
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "../SDL_internal.h"
    22 
    23 /* Allow access to a raw mixing buffer */
    24 
    25 #include "SDL.h"
    26 #include "SDL_audio.h"
    27 #include "SDL_audio_c.h"
    28 #include "SDL_audiomem.h"
    29 #include "SDL_sysaudio.h"
    30 
    31 #define _THIS SDL_AudioDevice *_this
    32 
    33 static SDL_AudioDriver current_audio;
    34 static SDL_AudioDevice *open_devices[16];
    35 
    36 /* !!! FIXME: These are wordy and unlocalized... */
    37 #define DEFAULT_OUTPUT_DEVNAME "System audio output device"
    38 #define DEFAULT_INPUT_DEVNAME "System audio capture device"
    39 
    40 
    41 /*
    42  * Not all of these will be compiled and linked in, but it's convenient
    43  *  to have a complete list here and saves yet-another block of #ifdefs...
    44  *  Please see bootstrap[], below, for the actual #ifdef mess.
    45  */
    46 extern AudioBootStrap BSD_AUDIO_bootstrap;
    47 extern AudioBootStrap DSP_bootstrap;
    48 extern AudioBootStrap ALSA_bootstrap;
    49 extern AudioBootStrap PULSEAUDIO_bootstrap;
    50 extern AudioBootStrap QSAAUDIO_bootstrap;
    51 extern AudioBootStrap SUNAUDIO_bootstrap;
    52 extern AudioBootStrap ARTS_bootstrap;
    53 extern AudioBootStrap ESD_bootstrap;
    54 #if SDL_AUDIO_DRIVER_NACL
    55 extern AudioBootStrap NACLAUD_bootstrap;
    56 #endif
    57 extern AudioBootStrap NAS_bootstrap;
    58 extern AudioBootStrap XAUDIO2_bootstrap;
    59 extern AudioBootStrap DSOUND_bootstrap;
    60 extern AudioBootStrap WINMM_bootstrap;
    61 extern AudioBootStrap PAUDIO_bootstrap;
    62 extern AudioBootStrap HAIKUAUDIO_bootstrap;
    63 extern AudioBootStrap COREAUDIO_bootstrap;
    64 extern AudioBootStrap SNDMGR_bootstrap;
    65 extern AudioBootStrap DISKAUD_bootstrap;
    66 extern AudioBootStrap DUMMYAUD_bootstrap;
    67 extern AudioBootStrap DCAUD_bootstrap;
    68 extern AudioBootStrap DART_bootstrap;
    69 extern AudioBootStrap NDSAUD_bootstrap;
    70 extern AudioBootStrap FUSIONSOUND_bootstrap;
    71 extern AudioBootStrap ANDROIDAUD_bootstrap;
    72 extern AudioBootStrap PSPAUD_bootstrap;
    73 extern AudioBootStrap SNDIO_bootstrap;
    74 extern AudioBootStrap EmscriptenAudio_bootstrap;
    75 
    76 
    77 /* Available audio drivers */
    78 static const AudioBootStrap *const bootstrap[] = {
    79 #if SDL_AUDIO_DRIVER_PULSEAUDIO
    80     &PULSEAUDIO_bootstrap,
    81 #endif
    82 #if SDL_AUDIO_DRIVER_ALSA
    83     &ALSA_bootstrap,
    84 #endif
    85 #if SDL_AUDIO_DRIVER_SNDIO
    86     &SNDIO_bootstrap,
    87 #endif
    88 #if SDL_AUDIO_DRIVER_BSD
    89     &BSD_AUDIO_bootstrap,
    90 #endif
    91 #if SDL_AUDIO_DRIVER_OSS
    92     &DSP_bootstrap,
    93 #endif
    94 #if SDL_AUDIO_DRIVER_QSA
    95     &QSAAUDIO_bootstrap,
    96 #endif
    97 #if SDL_AUDIO_DRIVER_SUNAUDIO
    98     &SUNAUDIO_bootstrap,
    99 #endif
   100 #if SDL_AUDIO_DRIVER_ARTS
   101     &ARTS_bootstrap,
   102 #endif
   103 #if SDL_AUDIO_DRIVER_ESD
   104     &ESD_bootstrap,
   105 #endif
   106 #if SDL_AUDIO_DRIVER_NACL
   107    &NACLAUD_bootstrap,
   108 #endif
   109 #if SDL_AUDIO_DRIVER_NAS
   110     &NAS_bootstrap,
   111 #endif
   112 #if SDL_AUDIO_DRIVER_XAUDIO2
   113     &XAUDIO2_bootstrap,
   114 #endif
   115 #if SDL_AUDIO_DRIVER_DSOUND
   116     &DSOUND_bootstrap,
   117 #endif
   118 #if SDL_AUDIO_DRIVER_WINMM
   119     &WINMM_bootstrap,
   120 #endif
   121 #if SDL_AUDIO_DRIVER_PAUDIO
   122     &PAUDIO_bootstrap,
   123 #endif
   124 #if SDL_AUDIO_DRIVER_HAIKU
   125     &HAIKUAUDIO_bootstrap,
   126 #endif
   127 #if SDL_AUDIO_DRIVER_COREAUDIO
   128     &COREAUDIO_bootstrap,
   129 #endif
   130 #if SDL_AUDIO_DRIVER_DISK
   131     &DISKAUD_bootstrap,
   132 #endif
   133 #if SDL_AUDIO_DRIVER_DUMMY
   134     &DUMMYAUD_bootstrap,
   135 #endif
   136 #if SDL_AUDIO_DRIVER_FUSIONSOUND
   137     &FUSIONSOUND_bootstrap,
   138 #endif
   139 #if SDL_AUDIO_DRIVER_ANDROID
   140     &ANDROIDAUD_bootstrap,
   141 #endif
   142 #if SDL_AUDIO_DRIVER_PSP
   143     &PSPAUD_bootstrap,
   144 #endif
   145 #if SDL_AUDIO_DRIVER_EMSCRIPTEN
   146     &EmscriptenAudio_bootstrap,
   147 #endif
   148     NULL
   149 };
   150 
   151 static SDL_AudioDevice *
   152 get_audio_device(SDL_AudioDeviceID id)
   153 {
   154     id--;
   155     if ((id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL)) {
   156         SDL_SetError("Invalid audio device ID");
   157         return NULL;
   158     }
   159 
   160     return open_devices[id];
   161 }
   162 
   163 
   164 /* stubs for audio drivers that don't need a specific entry point... */
   165 static void
   166 SDL_AudioDetectDevices_Default(int iscapture, SDL_AddAudioDevice addfn)
   167 {                               /* no-op. */
   168 }
   169 
   170 static void
   171 SDL_AudioThreadInit_Default(_THIS)
   172 {                               /* no-op. */
   173 }
   174 
   175 static void
   176 SDL_AudioWaitDevice_Default(_THIS)
   177 {                               /* no-op. */
   178 }
   179 
   180 static void
   181 SDL_AudioPlayDevice_Default(_THIS)
   182 {                               /* no-op. */
   183 }
   184 
   185 static int
   186 SDL_AudioGetPendingBytes_Default(_THIS)
   187 {
   188     return 0;
   189 }
   190 
   191 static Uint8 *
   192 SDL_AudioGetDeviceBuf_Default(_THIS)
   193 {
   194     return NULL;
   195 }
   196 
   197 static void
   198 SDL_AudioWaitDone_Default(_THIS)
   199 {                               /* no-op. */
   200 }
   201 
   202 static void
   203 SDL_AudioCloseDevice_Default(_THIS)
   204 {                               /* no-op. */
   205 }
   206 
   207 static void
   208 SDL_AudioDeinitialize_Default(void)
   209 {                               /* no-op. */
   210 }
   211 
   212 static int
   213 SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
   214 {
   215     return -1;
   216 }
   217 
   218 static SDL_INLINE SDL_bool
   219 is_in_audio_device_thread(SDL_AudioDevice * device)
   220 {
   221     /* The device thread locks the same mutex, but not through the public API.
   222        This check is in case the application, in the audio callback,
   223        tries to lock the thread that we've already locked from the
   224        device thread...just in case we only have non-recursive mutexes. */
   225     if (device->thread && (SDL_ThreadID() == device->threadid)) {
   226         return SDL_TRUE;
   227     }
   228 
   229     return SDL_FALSE;
   230 }
   231 
   232 static void
   233 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
   234 {
   235     if (!is_in_audio_device_thread(device)) {
   236         SDL_LockMutex(device->mixer_lock);
   237     }
   238 }
   239 
   240 static void
   241 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
   242 {
   243     if (!is_in_audio_device_thread(device)) {
   244         SDL_UnlockMutex(device->mixer_lock);
   245     }
   246 }
   247 
   248 
   249 static void
   250 finalize_audio_entry_points(void)
   251 {
   252     /*
   253      * Fill in stub functions for unused driver entry points. This lets us
   254      *  blindly call them without having to check for validity first.
   255      */
   256 
   257 #define FILL_STUB(x) \
   258         if (current_audio.impl.x == NULL) { \
   259             current_audio.impl.x = SDL_Audio##x##_Default; \
   260         }
   261     FILL_STUB(DetectDevices);
   262     FILL_STUB(OpenDevice);
   263     FILL_STUB(ThreadInit);
   264     FILL_STUB(WaitDevice);
   265     FILL_STUB(PlayDevice);
   266     FILL_STUB(GetPendingBytes);
   267     FILL_STUB(GetDeviceBuf);
   268     FILL_STUB(WaitDone);
   269     FILL_STUB(CloseDevice);
   270     FILL_STUB(LockDevice);
   271     FILL_STUB(UnlockDevice);
   272     FILL_STUB(Deinitialize);
   273 #undef FILL_STUB
   274 }
   275 
   276 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   277 /* Streaming functions (for when the input and output buffer sizes are different) */
   278 /* Write [length] bytes from buf into the streamer */
   279 static void
   280 SDL_StreamWrite(SDL_AudioStreamer * stream, Uint8 * buf, int length)
   281 {
   282     int i;
   283 
   284     for (i = 0; i < length; ++i) {
   285         stream->buffer[stream->write_pos] = buf[i];
   286         ++stream->write_pos;
   287     }
   288 }
   289 
   290 /* Read [length] bytes out of the streamer into buf */
   291 static void
   292 SDL_StreamRead(SDL_AudioStreamer * stream, Uint8 * buf, int length)
   293 {
   294     int i;
   295 
   296     for (i = 0; i < length; ++i) {
   297         buf[i] = stream->buffer[stream->read_pos];
   298         ++stream->read_pos;
   299     }
   300 }
   301 
   302 static int
   303 SDL_StreamLength(SDL_AudioStreamer * stream)
   304 {
   305     return (stream->write_pos - stream->read_pos) % stream->max_len;
   306 }
   307 
   308 /* Initialize the stream by allocating the buffer and setting the read/write heads to the beginning */
   309 #if 0
   310 static int
   311 SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
   312 {
   313     /* First try to allocate the buffer */
   314     stream->buffer = (Uint8 *) SDL_malloc(max_len);
   315     if (stream->buffer == NULL) {
   316         return -1;
   317     }
   318 
   319     stream->max_len = max_len;
   320     stream->read_pos = 0;
   321     stream->write_pos = 0;
   322 
   323     /* Zero out the buffer */
   324     SDL_memset(stream->buffer, silence, max_len);
   325 
   326     return 0;
   327 }
   328 #endif
   329 
   330 /* Deinitialize the stream simply by freeing the buffer */
   331 static void
   332 SDL_StreamDeinit(SDL_AudioStreamer * stream)
   333 {
   334     SDL_free(stream->buffer);
   335 }
   336 #endif
   337 
   338 
   339 /* buffer queueing support... */
   340 
   341 /* this expects that you managed thread safety elsewhere. */
   342 static void
   343 free_audio_queue(SDL_AudioBufferQueue *buffer)
   344 {
   345     while (buffer) {
   346         SDL_AudioBufferQueue *next = buffer->next;
   347         SDL_free(buffer);
   348         buffer = next;
   349     }
   350 }
   351 
   352 static void SDLCALL
   353 SDL_BufferQueueDrainCallback(void *userdata, Uint8 *stream, int _len)
   354 {
   355     /* this function always holds the mixer lock before being called. */
   356     Uint32 len = (Uint32) _len;
   357     SDL_AudioDevice *device = (SDL_AudioDevice *) userdata;
   358     SDL_AudioBufferQueue *buffer;
   359 
   360     SDL_assert(device != NULL);  /* this shouldn't ever happen, right?! */
   361     SDL_assert(_len >= 0);  /* this shouldn't ever happen, right?! */
   362 
   363     while ((len > 0) && ((buffer = device->buffer_queue_head) != NULL)) {
   364         const Uint32 avail = buffer->datalen - buffer->startpos;
   365         const Uint32 cpy = SDL_min(len, avail);
   366         SDL_assert(device->queued_bytes >= avail);
   367 
   368         SDL_memcpy(stream, buffer->data + buffer->startpos, cpy);
   369         buffer->startpos += cpy;
   370         stream += cpy;
   371         device->queued_bytes -= cpy;
   372         len -= cpy;
   373 
   374         if (buffer->startpos == buffer->datalen) {  /* packet is done, put it in the pool. */
   375             device->buffer_queue_head = buffer->next;
   376             SDL_assert((buffer->next != NULL) || (buffer == device->buffer_queue_tail));
   377             buffer->next = device->buffer_queue_pool;
   378             device->buffer_queue_pool = buffer;
   379         }
   380     }
   381 
   382     SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
   383 
   384     if (len > 0) {  /* fill any remaining space in the stream with silence. */
   385         SDL_assert(device->buffer_queue_head == NULL);
   386         SDL_memset(stream, device->spec.silence, len);
   387     }
   388 
   389     if (device->buffer_queue_head == NULL) {
   390         device->buffer_queue_tail = NULL;  /* in case we drained the queue entirely. */
   391     }
   392 }
   393 
   394 int
   395 SDL_QueueAudio(SDL_AudioDeviceID devid, const void *_data, Uint32 len)
   396 {
   397     SDL_AudioDevice *device = get_audio_device(devid);
   398     const Uint8 *data = (const Uint8 *) _data;
   399     SDL_AudioBufferQueue *orighead;
   400     SDL_AudioBufferQueue *origtail;
   401     Uint32 origlen;
   402     Uint32 datalen;
   403 
   404     if (!device) {
   405         return -1;  /* get_audio_device() will have set the error state */
   406     }
   407 
   408     if (device->spec.callback != SDL_BufferQueueDrainCallback) {
   409         return SDL_SetError("Audio device has a callback, queueing not allowed");
   410     }
   411 
   412     current_audio.impl.LockDevice(device);
   413 
   414     orighead = device->buffer_queue_head;
   415     origtail = device->buffer_queue_tail;
   416     origlen = origtail ? origtail->datalen : 0;
   417 
   418     while (len > 0) {
   419         SDL_AudioBufferQueue *packet = device->buffer_queue_tail;
   420         SDL_assert(!packet || (packet->datalen <= SDL_AUDIOBUFFERQUEUE_PACKETLEN));
   421         if (!packet || (packet->datalen >= SDL_AUDIOBUFFERQUEUE_PACKETLEN)) {
   422             /* tail packet missing or completely full; we need a new packet. */
   423             packet = device->buffer_queue_pool;
   424             if (packet != NULL) {
   425                 /* we have one available in the pool. */
   426                 device->buffer_queue_pool = packet->next;
   427             } else {
   428                 /* Have to allocate a new one! */
   429                 packet = (SDL_AudioBufferQueue *) SDL_malloc(sizeof (SDL_AudioBufferQueue));
   430                 if (packet == NULL) {
   431                     /* uhoh, reset so we've queued nothing new, free what we can. */
   432                     if (!origtail) {
   433                         packet = device->buffer_queue_head;  /* whole queue. */
   434                     } else {
   435                         packet = origtail->next;  /* what we added to existing queue. */
   436                         origtail->next = NULL;
   437                         origtail->datalen = origlen;
   438                     }
   439                     device->buffer_queue_head = orighead;
   440                     device->buffer_queue_tail = origtail;
   441                     device->buffer_queue_pool = NULL;
   442 
   443                     current_audio.impl.UnlockDevice(device);
   444 
   445                     free_audio_queue(packet);  /* give back what we can. */
   446 
   447                     return SDL_OutOfMemory();
   448                 }
   449             }
   450             packet->datalen = 0;
   451             packet->startpos = 0;
   452             packet->next = NULL;
   453 
   454             SDL_assert((device->buffer_queue_head != NULL) == (device->queued_bytes != 0));
   455             if (device->buffer_queue_tail == NULL) {
   456                 device->buffer_queue_head = packet;
   457             } else {
   458                 device->buffer_queue_tail->next = packet;
   459             }
   460             device->buffer_queue_tail = packet;
   461         }
   462 
   463         datalen = SDL_min(len, SDL_AUDIOBUFFERQUEUE_PACKETLEN - packet->datalen);
   464         SDL_memcpy(packet->data + packet->datalen, data, datalen);
   465         data += datalen;
   466         len -= datalen;
   467         packet->datalen += datalen;
   468         device->queued_bytes += datalen;
   469     }
   470 
   471     current_audio.impl.UnlockDevice(device);
   472 
   473     return 0;
   474 }
   475 
   476 Uint32
   477 SDL_GetQueuedAudioSize(SDL_AudioDeviceID devid)
   478 {
   479     Uint32 retval = 0;
   480     SDL_AudioDevice *device = get_audio_device(devid);
   481 
   482     /* Nothing to do unless we're set up for queueing. */
   483     if (device && (device->spec.callback == SDL_BufferQueueDrainCallback)) {
   484         current_audio.impl.LockDevice(device);
   485         retval = device->queued_bytes + current_audio.impl.GetPendingBytes(device);
   486         current_audio.impl.UnlockDevice(device);
   487     }
   488 
   489     return retval;
   490 }
   491 
   492 void
   493 SDL_ClearQueuedAudio(SDL_AudioDeviceID devid)
   494 {
   495     SDL_AudioDevice *device = get_audio_device(devid);
   496     SDL_AudioBufferQueue *buffer = NULL;
   497     if (!device) {
   498         return;  /* nothing to do. */
   499     }
   500 
   501     /* Blank out the device and release the mutex. Free it afterwards. */
   502     current_audio.impl.LockDevice(device);
   503     buffer = device->buffer_queue_head;
   504     device->buffer_queue_tail = NULL;
   505     device->buffer_queue_head = NULL;
   506     device->queued_bytes = 0;
   507     current_audio.impl.UnlockDevice(device);
   508 
   509     free_audio_queue(buffer);
   510 }
   511 
   512 
   513 #if defined(__ANDROID__)
   514 #include <android/log.h>
   515 #endif
   516 
   517 /* The general mixing thread function */
   518 int SDLCALL
   519 SDL_RunAudio(void *devicep)
   520 {
   521     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
   522     Uint8 *stream;
   523     int stream_len;
   524     void *udata;
   525     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   526     Uint32 delay;
   527 
   528 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   529     /* For streaming when the buffer sizes don't match up */
   530     Uint8 *istream;
   531     int istream_len = 0;
   532 #endif
   533 
   534     /* The audio mixing is always a high priority thread */
   535     SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
   536 
   537     /* Perform any thread setup */
   538     device->threadid = SDL_ThreadID();
   539     current_audio.impl.ThreadInit(device);
   540 
   541     /* Set up the mixing function */
   542     fill = device->spec.callback;
   543     udata = device->spec.userdata;
   544 
   545     /* By default do not stream */
   546     device->use_streamer = 0;
   547 
   548     if (device->convert.needed) {
   549 #if 0                           /* !!! FIXME: I took len_div out of the structure. Use rate_incr instead? */
   550         /* If the result of the conversion alters the length, i.e. resampling is being used, use the streamer */
   551         if (device->convert.len_mult != 1 || device->convert.len_div != 1) {
   552             /* The streamer's maximum length should be twice whichever is larger: spec.size or len_cvt */
   553             stream_max_len = 2 * device->spec.size;
   554             if (device->convert.len_mult > device->convert.len_div) {
   555                 stream_max_len *= device->convert.len_mult;
   556                 stream_max_len /= device->convert.len_div;
   557             }
   558             if (SDL_StreamInit(&device->streamer, stream_max_len, silence) <
   559                 0)
   560                 return -1;
   561             device->use_streamer = 1;
   562 
   563             /* istream_len should be the length of what we grab from the callback and feed to conversion,
   564                so that we get close to spec_size. I.e. we want device.spec_size = istream_len * u / d
   565              */
   566             istream_len =
   567                 device->spec.size * device->convert.len_div /
   568                 device->convert.len_mult;
   569         }
   570 #endif
   571         stream_len = device->convert.len;
   572     } else {
   573         stream_len = device->spec.size;
   574     }
   575 
   576     /* Calculate the delay while paused */
   577     delay = ((device->spec.samples * 1000) / device->spec.freq);
   578 
   579     /* Determine if the streamer is necessary here */
   580 #if 0  /* !!! FIXME: rewrite/remove this streamer code. */
   581     if (device->use_streamer == 1) {
   582         /* This code is almost the same as the old code. The difference is, instead of reading
   583            directly from the callback into "stream", then converting and sending the audio off,
   584            we go: callback -> "istream" -> (conversion) -> streamer -> stream -> device.
   585            However, reading and writing with streamer are done separately:
   586            - We only call the callback and write to the streamer when the streamer does not
   587            contain enough samples to output to the device.
   588            - We only read from the streamer and tell the device to play when the streamer
   589            does have enough samples to output.
   590            This allows us to perform resampling in the conversion step, where the output of the
   591            resampling process can be any number. We will have to see what a good size for the
   592            stream's maximum length is, but I suspect 2*max(len_cvt, stream_len) is a good figure.
   593          */
   594         while (device->enabled) {
   595 
   596             if (device->paused) {
   597                 SDL_Delay(delay);
   598                 continue;
   599             }
   600 
   601             /* Only read in audio if the streamer doesn't have enough already (if it does not have enough samples to output) */
   602             if (SDL_StreamLength(&device->streamer) < stream_len) {
   603                 /* Set up istream */
   604                 if (device->convert.needed) {
   605                     if (device->convert.buf) {
   606                         istream = device->convert.buf;
   607                     } else {
   608                         continue;
   609                     }
   610                 } else {
   611 /* FIXME: Ryan, this is probably wrong.  I imagine we don't want to get
   612  * a device buffer both here and below in the stream output.
   613  */
   614                     istream = current_audio.impl.GetDeviceBuf(device);
   615                     if (istream == NULL) {
   616                         istream = device->fake_stream;
   617                     }
   618                 }
   619 
   620                 /* Read from the callback into the _input_ stream */
   621                 SDL_LockMutex(device->mixer_lock);
   622                 (*fill) (udata, istream, istream_len);
   623                 SDL_UnlockMutex(device->mixer_lock);
   624 
   625                 /* Convert the audio if necessary and write to the streamer */
   626                 if (device->convert.needed) {
   627                     SDL_ConvertAudio(&device->convert);
   628                     if (istream == NULL) {
   629                         istream = device->fake_stream;
   630                     }
   631                     /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
   632                     SDL_StreamWrite(&device->streamer, device->convert.buf,
   633                                     device->convert.len_cvt);
   634                 } else {
   635                     SDL_StreamWrite(&device->streamer, istream, istream_len);
   636                 }
   637             }
   638 
   639             /* Only output audio if the streamer has enough to output */
   640             if (SDL_StreamLength(&device->streamer) >= stream_len) {
   641                 /* Set up the output stream */
   642                 if (device->convert.needed) {
   643                     if (device->convert.buf) {
   644                         stream = device->convert.buf;
   645                     } else {
   646                         continue;
   647                     }
   648                 } else {
   649                     stream = current_audio.impl.GetDeviceBuf(device);
   650                     if (stream == NULL) {
   651                         stream = device->fake_stream;
   652                     }
   653                 }
   654 
   655                 /* Now read from the streamer */
   656                 SDL_StreamRead(&device->streamer, stream, stream_len);
   657 
   658                 /* Ready current buffer for play and change current buffer */
   659                 if (stream != device->fake_stream) {
   660                     current_audio.impl.PlayDevice(device);
   661                     /* Wait for an audio buffer to become available */
   662                     current_audio.impl.WaitDevice(device);
   663                 } else {
   664                     SDL_Delay(delay);
   665                 }
   666             }
   667 
   668         }
   669     } else
   670 #endif
   671     {
   672         /* Otherwise, do not use the streamer. This is the old code. */
   673         const int silence = (int) device->spec.silence;
   674 
   675         /* Loop, filling the audio buffers */
   676         while (device->enabled) {
   677 
   678             /* Fill the current buffer with sound */
   679             if (device->convert.needed) {
   680                 if (device->convert.buf) {
   681                     stream = device->convert.buf;
   682                 } else {
   683                     continue;
   684                 }
   685             } else {
   686                 stream = current_audio.impl.GetDeviceBuf(device);
   687                 if (stream == NULL) {
   688                     stream = device->fake_stream;
   689                 }
   690             }
   691 
   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_memset(&current_audio, '\0', sizeof(current_audio));
   788     SDL_memset(open_devices, '\0', sizeof(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_memset(&current_audio, 0, sizeof(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_memset(&current_audio, 0, sizeof(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 semaphore 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: */