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