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