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