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