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