src/audio/SDL_audio.c
changeset 2049 5f6550e5184f
parent 2045 510892a215a2
child 2053 716cf90f24a0
equal deleted inserted replaced
2048:6067c7f9a672 2049:5f6550e5184f
    26 #include "SDL.h"
    26 #include "SDL.h"
    27 #include "SDL_audio_c.h"
    27 #include "SDL_audio_c.h"
    28 #include "SDL_audiomem.h"
    28 #include "SDL_audiomem.h"
    29 #include "SDL_sysaudio.h"
    29 #include "SDL_sysaudio.h"
    30 
    30 
    31 #ifdef __OS2__
    31 #define _THIS	SDL_AudioDevice *this
    32 /* We'll need the DosSetPriority() API! */
    32 
    33 #define INCL_DOSPROCESS
    33 static SDL_AudioDriver current_audio;
    34 #include <os2.h>
    34 static SDL_AudioDevice *open_devices[16];
    35 #endif
    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 QNXNTOAUDIO_bootstrap;
       
    51 extern AudioBootStrap SUNAUDIO_bootstrap;
       
    52 extern AudioBootStrap DMEDIA_bootstrap;
       
    53 extern AudioBootStrap ARTS_bootstrap;
       
    54 extern AudioBootStrap ESD_bootstrap;
       
    55 extern AudioBootStrap NAS_bootstrap;
       
    56 extern AudioBootStrap DSOUND_bootstrap;
       
    57 extern AudioBootStrap WAVEOUT_bootstrap;
       
    58 extern AudioBootStrap PAUDIO_bootstrap;
       
    59 extern AudioBootStrap BEOSAUDIO_bootstrap;
       
    60 extern AudioBootStrap COREAUDIO_bootstrap;
       
    61 extern AudioBootStrap SNDMGR_bootstrap;
       
    62 extern AudioBootStrap MINTAUDIO_GSXB_bootstrap;
       
    63 extern AudioBootStrap MINTAUDIO_MCSN_bootstrap;
       
    64 extern AudioBootStrap MINTAUDIO_STFA_bootstrap;
       
    65 extern AudioBootStrap MINTAUDIO_XBIOS_bootstrap;
       
    66 extern AudioBootStrap MINTAUDIO_DMA8_bootstrap;
       
    67 extern AudioBootStrap DISKAUD_bootstrap;
       
    68 extern AudioBootStrap DUMMYAUD_bootstrap;
       
    69 extern AudioBootStrap DCAUD_bootstrap;
       
    70 extern AudioBootStrap MMEAUDIO_bootstrap;
       
    71 extern AudioBootStrap DART_bootstrap;
       
    72 
    36 
    73 
    37 /* Available audio drivers */
    74 /* Available audio drivers */
    38 static AudioBootStrap *bootstrap[] = {
    75 static AudioBootStrap *bootstrap[] = {
    39 #if SDL_AUDIO_DRIVER_BSD
    76 #if SDL_AUDIO_DRIVER_BSD
    40     &BSD_AUDIO_bootstrap,
    77     &BSD_AUDIO_bootstrap,
    68     &DSOUND_bootstrap,
   105     &DSOUND_bootstrap,
    69 #endif
   106 #endif
    70 #if SDL_AUDIO_DRIVER_WAVEOUT
   107 #if SDL_AUDIO_DRIVER_WAVEOUT
    71     &WAVEOUT_bootstrap,
   108     &WAVEOUT_bootstrap,
    72 #endif
   109 #endif
    73 #if SDL_AUDIO_DRIVER_PAUD
   110 #if SDL_AUDIO_DRIVER_PAUDIO
    74     &Paud_bootstrap,
   111     &PAUDIO_bootstrap,
    75 #endif
   112 #endif
    76 #if SDL_AUDIO_DRIVER_BAUDIO
   113 #if SDL_AUDIO_DRIVER_BEOSAUDIO
    77     &BAUDIO_bootstrap,
   114     &BEOSAUDIO_bootstrap,
    78 #endif
   115 #endif
    79 #if SDL_AUDIO_DRIVER_COREAUDIO
   116 #if SDL_AUDIO_DRIVER_COREAUDIO
    80     &COREAUDIO_bootstrap,
   117     &COREAUDIO_bootstrap,
    81 #endif
   118 #endif
    82 #if SDL_AUDIO_DRIVER_SNDMGR
   119 #if SDL_AUDIO_DRIVER_SNDMGR
    83     &SNDMGR_bootstrap,
   120     &SNDMGR_bootstrap,
    84 #endif
       
    85 #if SDL_AUDIO_DRIVER_AHI
       
    86     &AHI_bootstrap,
       
    87 #endif
   121 #endif
    88 #if SDL_AUDIO_DRIVER_MINT
   122 #if SDL_AUDIO_DRIVER_MINT
    89     &MINTAUDIO_GSXB_bootstrap,
   123     &MINTAUDIO_GSXB_bootstrap,
    90     &MINTAUDIO_MCSN_bootstrap,
   124     &MINTAUDIO_MCSN_bootstrap,
    91     &MINTAUDIO_STFA_bootstrap,
   125     &MINTAUDIO_STFA_bootstrap,
   107 #if SDL_AUDIO_DRIVER_DART
   141 #if SDL_AUDIO_DRIVER_DART
   108     &DART_bootstrap,
   142     &DART_bootstrap,
   109 #endif
   143 #endif
   110     NULL
   144     NULL
   111 };
   145 };
   112 SDL_AudioDevice *current_audio = NULL;
   146 
   113 
   147 static SDL_AudioDevice *get_audio_device(SDL_AudioDeviceID id)
   114 /* Various local functions */
   148 {
   115 int SDL_AudioInit(const char *driver_name);
   149     id--;
   116 void SDL_AudioQuit(void);
   150     if ( (id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL) ) {
   117 
   151         SDL_SetError("Invalid audio device ID");
   118 #if SDL_AUDIO_DRIVER_AHI
   152         return NULL;
   119 static int audio_configured = 0;
   153     }
   120 #endif
   154 
       
   155     return open_devices[id];
       
   156 }
       
   157 
       
   158 
       
   159 /* stubs for audio drivers that don't need a specific entry point... */
       
   160 static int SDL_AudioDetectDevices_Default(int iscapture) { return -1; }
       
   161 static void SDL_AudioThreadInit_Default(_THIS) { /* no-op. */ }
       
   162 static void SDL_AudioWaitDevice_Default(_THIS) { /* no-op. */ }
       
   163 static void SDL_AudioPlayDevice_Default(_THIS) { /* no-op. */ }
       
   164 static Uint8 *SDL_AudioGetDeviceBuf_Default(_THIS) { return NULL; }
       
   165 static void SDL_AudioWaitDone_Default(_THIS) { /* no-op. */ }
       
   166 static void SDL_AudioCloseDevice_Default(_THIS) { /* no-op. */ }
       
   167 static void SDL_AudioDeinitialize_Default(void) { /* no-op. */ }
       
   168 
       
   169 static int
       
   170 SDL_AudioOpenDevice_Default(_THIS, const char *devname, int iscapture)
       
   171 {
       
   172     return 0;
       
   173 }
       
   174 
       
   175 static const char *SDL_AudioGetDeviceName_Default(int index, int iscapture)
       
   176 {
       
   177     SDL_SetError("No such device");
       
   178     return NULL;
       
   179 }
       
   180 
       
   181 static void
       
   182 SDL_AudioLockDevice_Default(SDL_AudioDevice * device)
       
   183 {
       
   184     if (device->thread && (SDL_ThreadID() == device->threadid)) {
       
   185         return;
       
   186     }
       
   187     SDL_mutexP(device->mixer_lock);
       
   188 }
       
   189 
       
   190 static void
       
   191 SDL_AudioUnlockDevice_Default(SDL_AudioDevice * device)
       
   192 {
       
   193     if (device->thread && (SDL_ThreadID() == device->threadid)) {
       
   194         return;
       
   195     }
       
   196     SDL_mutexV(device->mixer_lock);
       
   197 }
       
   198 
       
   199 
       
   200 static void finalize_audio_entry_points(void)
       
   201 {
       
   202     /*
       
   203      * Fill in stub functions for unused driver entry points. This lets us
       
   204      *  blindly call them without having to check for validity first.
       
   205      */
       
   206 
       
   207     #define FILL_STUB(x) \
       
   208         if (current_audio.impl.x == NULL) { \
       
   209             current_audio.impl.x = SDL_Audio##x##_Default; \
       
   210         }
       
   211     FILL_STUB(DetectDevices);
       
   212     FILL_STUB(GetDeviceName);
       
   213     FILL_STUB(OpenDevice);
       
   214     FILL_STUB(ThreadInit);
       
   215     FILL_STUB(WaitDevice);
       
   216     FILL_STUB(PlayDevice);
       
   217     FILL_STUB(GetDeviceBuf);
       
   218     FILL_STUB(WaitDone);
       
   219     FILL_STUB(CloseDevice);
       
   220     FILL_STUB(LockDevice);
       
   221     FILL_STUB(UnlockDevice);
       
   222     FILL_STUB(Deinitialize);
       
   223     #undef FILL_STUB
       
   224 }
       
   225 
   121 
   226 
   122 /* The general mixing thread function */
   227 /* The general mixing thread function */
   123 int SDLCALL
   228 int SDLCALL
   124 SDL_RunAudio(void *audiop)
   229 SDL_RunAudio(void *devicep)
   125 {
   230 {
   126     SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop;
   231     SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
       
   232     const int legacy_device = (device == open_devices[0]);
   127     Uint8 *stream;
   233     Uint8 *stream;
   128     int stream_len;
   234     int stream_len;
   129     void *udata;
   235     void *udata;
   130     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   236     void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
   131     int silence;
   237     int silence;
   132 #if SDL_AUDIO_DRIVER_AHI
       
   133     int started = 0;
       
   134 
       
   135 /* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
       
   136 
       
   137     D(bug("Task audio started audio struct:<%lx>...\n", audiop));
       
   138 
       
   139     D(bug("Before Openaudio..."));
       
   140     if (audio->OpenAudio(audio, &audio->spec) == -1) {
       
   141         D(bug("Open audio failed...\n"));
       
   142         return (-1);
       
   143     }
       
   144     D(bug("OpenAudio...OK\n"));
       
   145 #endif
       
   146 
   238 
   147     /* Perform any thread setup */
   239     /* Perform any thread setup */
   148     if (audio->ThreadInit) {
   240     device->threadid = SDL_ThreadID();
   149         audio->ThreadInit(audio);
   241     current_audio.impl.ThreadInit(device);
   150     }
       
   151     audio->threadid = SDL_ThreadID();
       
   152 
   242 
   153     /* Set up the mixing function */
   243     /* Set up the mixing function */
   154     fill = audio->spec.callback;
   244     fill = device->spec.callback;
   155     udata = audio->spec.userdata;
   245     udata = device->spec.userdata;
   156 
   246 
   157 #if SDL_AUDIO_DRIVER_AHI
   247     if (device->convert.needed) {
   158     audio_configured = 1;
   248         if (device->convert.src_format == AUDIO_U8) {
   159 
       
   160     D(bug("Audio configured... Checking for conversion\n"));
       
   161     SDL_mutexP(audio->mixer_lock);
       
   162     D(bug("Semaphore obtained...\n"));
       
   163 #endif
       
   164 
       
   165     if (audio->convert.needed) {
       
   166         if (audio->convert.src_format == AUDIO_U8) {
       
   167             silence = 0x80;
   249             silence = 0x80;
   168         } else {
   250         } else {
   169             silence = 0;
   251             silence = 0;
   170         }
   252         }
   171         stream_len = audio->convert.len;
   253         stream_len = device->convert.len;
   172     } else {
   254     } else {
   173         silence = audio->spec.silence;
   255         silence = device->spec.silence;
   174         stream_len = audio->spec.size;
   256         stream_len = device->spec.size;
   175     }
   257     }
   176 
       
   177 #if SDL_AUDIO_DRIVER_AHI
       
   178     SDL_mutexV(audio->mixer_lock);
       
   179     D(bug("Entering audio loop...\n"));
       
   180 #endif
       
   181 
       
   182 #ifdef __OS2__
       
   183     /* Increase the priority of this thread to make sure that
       
   184        the audio will be continuous all the time! */
       
   185 #ifdef USE_DOSSETPRIORITY
       
   186     if (SDL_getenv("SDL_USE_TIMECRITICAL_AUDIO")) {
       
   187 #ifdef DEBUG_BUILD
       
   188         printf
       
   189             ("[SDL_RunAudio] : Setting priority to TimeCritical+0! (TID%d)\n",
       
   190              SDL_ThreadID());
       
   191 #endif
       
   192         DosSetPriority(PRTYS_THREAD, PRTYC_TIMECRITICAL, 0, 0);
       
   193     } else {
       
   194 #ifdef DEBUG_BUILD
       
   195         printf
       
   196             ("[SDL_RunAudio] : Setting priority to ForegroundServer+0! (TID%d)\n",
       
   197              SDL_ThreadID());
       
   198 #endif
       
   199         DosSetPriority(PRTYS_THREAD, PRTYC_FOREGROUNDSERVER, 0, 0);
       
   200     }
       
   201 #endif
       
   202 #endif
       
   203 
   258 
   204     /* Loop, filling the audio buffers */
   259     /* Loop, filling the audio buffers */
   205     while (audio->enabled) {
   260     while (device->enabled) {
   206 
   261 
   207         /* Fill the current buffer with sound */
   262         /* Fill the current buffer with sound */
   208         if (audio->convert.needed) {
   263         if (device->convert.needed) {
   209             if (audio->convert.buf) {
   264             if (device->convert.buf) {
   210                 stream = audio->convert.buf;
   265                 stream = device->convert.buf;
   211             } else {
   266             } else {
   212                 continue;
   267                 continue;
   213             }
   268             }
   214         } else {
   269         } else {
   215             stream = audio->GetAudioBuf(audio);
   270             stream = current_audio.impl.GetDeviceBuf(device);
   216             if (stream == NULL) {
   271             if (stream == NULL) {
   217                 stream = audio->fake_stream;
   272                 stream = device->fake_stream;
   218             }
   273             }
   219         }
   274         }
   220         SDL_memset(stream, silence, stream_len);
   275 
   221 
   276         /* New code should fill buffer or set it to silence themselves. */
   222         if (!audio->paused) {
   277         if (legacy_device) {
   223             SDL_mutexP(audio->mixer_lock);
   278             SDL_memset(stream, silence, stream_len);
       
   279         }
       
   280 
       
   281         if (!device->paused) {
       
   282             SDL_mutexP(device->mixer_lock);
   224             (*fill) (udata, stream, stream_len);
   283             (*fill) (udata, stream, stream_len);
   225             SDL_mutexV(audio->mixer_lock);
   284             SDL_mutexV(device->mixer_lock);
   226         }
   285         }
   227 
   286 
   228         /* Convert the audio if necessary */
   287         /* Convert the audio if necessary */
   229         if (audio->convert.needed) {
   288         if (device->convert.needed) {
   230             SDL_ConvertAudio(&audio->convert);
   289             SDL_ConvertAudio(&device->convert);
   231             stream = audio->GetAudioBuf(audio);
   290             stream = current_audio.impl.GetDeviceBuf(device);
   232             if (stream == NULL) {
   291             if (stream == NULL) {
   233                 stream = audio->fake_stream;
   292                 stream = device->fake_stream;
   234             }
   293             }
   235             SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
   294             SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
   236         }
   295         }
   237 
   296 
   238         /* Ready current buffer for play and change current buffer */
   297         /* Ready current buffer for play and change current buffer */
   239         if (stream != audio->fake_stream) {
   298         if (stream != device->fake_stream) {
   240             audio->PlayAudio(audio);
   299             current_audio.impl.PlayDevice(device);
   241         }
   300         }
   242 
   301 
   243         /* Wait for an audio buffer to become available */
   302         /* Wait for an audio buffer to become available */
   244         if (stream == audio->fake_stream) {
   303         if (stream == device->fake_stream) {
   245             SDL_Delay((audio->spec.samples * 1000) / audio->spec.freq);
   304             SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
   246         } else {
   305         } else {
   247             audio->WaitAudio(audio);
   306             current_audio.impl.WaitDevice(device);
   248         }
   307         }
   249     }
   308     }
   250 
   309 
   251     /* Wait for the audio to drain.. */
   310     /* Wait for the audio to drain.. */
   252     if (audio->WaitDone) {
   311     current_audio.impl.WaitDone(device);
   253         audio->WaitDone(audio);
   312 
   254     }
       
   255 #if SDL_AUDIO_DRIVER_AHI
       
   256     D(bug("WaitAudio...Done\n"));
       
   257 
       
   258     audio->CloseAudio(audio);
       
   259 
       
   260     D(bug("CloseAudio..Done, subtask exiting...\n"));
       
   261     audio_configured = 0;
       
   262 #endif
       
   263 #ifdef __OS2__
       
   264 #ifdef DEBUG_BUILD
       
   265     printf("[SDL_RunAudio] : Task exiting. (TID%d)\n", SDL_ThreadID());
       
   266 #endif
       
   267 #endif
       
   268     return (0);
   313     return (0);
   269 }
   314 }
   270 
   315 
   271 static void
       
   272 SDL_LockAudio_Default(SDL_AudioDevice * audio)
       
   273 {
       
   274     if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
       
   275         return;
       
   276     }
       
   277     SDL_mutexP(audio->mixer_lock);
       
   278 }
       
   279 
       
   280 static void
       
   281 SDL_UnlockAudio_Default(SDL_AudioDevice * audio)
       
   282 {
       
   283     if (audio->thread && (SDL_ThreadID() == audio->threadid)) {
       
   284         return;
       
   285     }
       
   286     SDL_mutexV(audio->mixer_lock);
       
   287 }
       
   288 
   316 
   289 static SDL_AudioFormat
   317 static SDL_AudioFormat
   290 SDL_ParseAudioFormat(const char *string)
   318 SDL_ParseAudioFormat(const char *string)
   291 {
   319 {
   292     SDL_AudioFormat format = 0;
   320     #define CHECK_FMT_STRING(x) if (strcmp(string, #x) == 0) return AUDIO_##x
   293 
   321     CHECK_FMT_STRING(U8);
   294     switch (*string) {
   322     CHECK_FMT_STRING(S8);
   295     case 'U':
   323     CHECK_FMT_STRING(U16LSB);
   296         ++string;
   324     CHECK_FMT_STRING(S16LSB);
   297         format |= 0x0000;
   325     CHECK_FMT_STRING(U16MSB);
   298         break;
   326     CHECK_FMT_STRING(S16MSB);
   299     case 'S':
   327     CHECK_FMT_STRING(U16SYS);
   300         ++string;
   328     CHECK_FMT_STRING(S16SYS);
   301         format |= 0x8000;
   329     CHECK_FMT_STRING(U16);
   302         break;
   330     CHECK_FMT_STRING(S16);
   303     default:
   331     CHECK_FMT_STRING(S32LSB);
   304         return 0;
   332     CHECK_FMT_STRING(S32MSB);
   305     }
   333     CHECK_FMT_STRING(S32SYS);
   306     switch (SDL_atoi(string)) {
   334     CHECK_FMT_STRING(S32);
   307     case 8:
   335     CHECK_FMT_STRING(F32LSB);
   308         string += 1;
   336     CHECK_FMT_STRING(F32MSB);
   309         format |= 8;
   337     CHECK_FMT_STRING(F32SYS);
   310         break;
   338     CHECK_FMT_STRING(F32);
   311     case 16:
   339     #undef CHECK_FMT_STRING
   312         string += 2;
   340     return 0;
   313         format |= 16;
       
   314         if (SDL_strcmp(string, "LSB") == 0
       
   315 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
       
   316             || SDL_strcmp(string, "SYS") == 0
       
   317 #endif
       
   318             ) {
       
   319             format |= 0x0000;
       
   320         }
       
   321         if (SDL_strcmp(string, "MSB") == 0
       
   322 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
       
   323             || SDL_strcmp(string, "SYS") == 0
       
   324 #endif
       
   325             ) {
       
   326             format |= 0x1000;
       
   327         }
       
   328         break;
       
   329     default:
       
   330         return 0;
       
   331     }
       
   332     return format;
       
   333 }
   341 }
   334 
   342 
   335 int
   343 int
   336 SDL_GetNumAudioDrivers(void)
   344 SDL_GetNumAudioDrivers(void)
   337 {
   345 {
   348 }
   356 }
   349 
   357 
   350 int
   358 int
   351 SDL_AudioInit(const char *driver_name)
   359 SDL_AudioInit(const char *driver_name)
   352 {
   360 {
   353     SDL_AudioDevice *audio;
   361     int i = 0;
   354     int i = 0, idx;
   362     int initialized = 0;
   355 
   363     int tried_to_init = 0;
   356     /* Check to make sure we don't overwrite 'current_audio' */
   364 
   357     if (current_audio != NULL) {
   365     if (SDL_WasInit(SDL_INIT_AUDIO)) {
   358         SDL_AudioQuit();
   366         SDL_AudioQuit();  /* shutdown driver if already running. */
   359     }
   367     }
       
   368 
       
   369     SDL_memset(&current_audio, '\0', sizeof (current_audio));
       
   370     SDL_memset(open_devices, '\0', sizeof (open_devices));
   360 
   371 
   361     /* Select the proper audio driver */
   372     /* Select the proper audio driver */
   362     audio = NULL;
       
   363     idx = 0;
       
   364     if (driver_name == NULL) {
   373     if (driver_name == NULL) {
   365         driver_name = SDL_getenv("SDL_AUDIODRIVER");
   374         driver_name = SDL_getenv("SDL_AUDIODRIVER");
   366     }
   375     }
   367 #if SDL_AUDIO_DRIVER_ESD
   376 
   368     if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) {
   377     for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
   369         /* Ahem, we know that if ESPEAKER is set, user probably wants
   378         /* make sure we should even try this driver before doing so... */
   370            to use ESD, but don't start it if it's not already running.
   379         const AudioBootStrap *backend = bootstrap[i];
   371            This probably isn't the place to do this, but... Shh! :)
   380         if ( ((driver_name) && (SDL_strcasecmp(backend->name, driver_name))) ||
   372          */
   381              ((!driver_name) && (backend->demand_only)) ) {
   373         for (i = 0; bootstrap[i]; ++i) {
   382             continue;
   374             if (SDL_strcasecmp(bootstrap[i]->name, "esd") == 0) {
   383         }
   375 #ifdef HAVE_PUTENV
   384 
   376                 const char *esd_no_spawn;
   385         tried_to_init = 1;
   377 
   386         SDL_memset(&current_audio, 0, sizeof (current_audio));
   378                 /* Don't start ESD if it's not running */
   387         current_audio.name = backend->name;
   379                 esd_no_spawn = getenv("ESD_NO_SPAWN");
   388         current_audio.desc = backend->desc;
   380                 if (esd_no_spawn == NULL) {
   389         initialized = backend->init(&current_audio.impl);
   381                     putenv("ESD_NO_SPAWN=1");
   390     }
   382                 }
   391 
   383 #endif
   392     if (!initialized) {
   384                 if (bootstrap[i]->available()) {
   393         /* specific drivers will set the error message if they fail... */
   385                     audio = bootstrap[i]->create(0);
   394         if (!tried_to_init) {
   386                     break;
       
   387                 }
       
   388 #ifdef HAVE_UNSETENV
       
   389                 if (esd_no_spawn == NULL) {
       
   390                     unsetenv("ESD_NO_SPAWN");
       
   391                 }
       
   392 #endif
       
   393             }
       
   394         }
       
   395     }
       
   396 #endif /* SDL_AUDIO_DRIVER_ESD */
       
   397     if (audio == NULL) {
       
   398         if (driver_name != NULL) {
       
   399             for (i = 0; bootstrap[i]; ++i) {
       
   400                 if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
       
   401                     if (bootstrap[i]->available()) {
       
   402                         audio = bootstrap[i]->create(idx);
       
   403                     }
       
   404                     break;
       
   405                 }
       
   406             }
       
   407         } else {
       
   408             for (i = 0; bootstrap[i]; ++i) {
       
   409                 if (bootstrap[i]->available()) {
       
   410                     audio = bootstrap[i]->create(idx);
       
   411                     if (audio != NULL) {
       
   412                         break;
       
   413                     }
       
   414                 }
       
   415             }
       
   416         }
       
   417         if (audio == NULL) {
       
   418             if (driver_name) {
   395             if (driver_name) {
   419                 SDL_SetError("%s not available", driver_name);
   396                 SDL_SetError("%s not available", driver_name);
   420             } else {
   397             } else {
   421                 SDL_SetError("No available audio device");
   398                 SDL_SetError("No available audio device");
   422             }
   399             }
   423 #if 0
   400         }
   424             /* Don't fail SDL_Init() if audio isn't available.
   401 
   425                SDL_OpenAudio() will handle it at that point.  *sigh*
   402         SDL_memset(&current_audio, 0, sizeof (current_audio));
   426              */
   403         return (-1);  /* No driver was available, so fail. */
   427             return (-1);
   404     }
   428 #endif
   405 
   429         }
   406     finalize_audio_entry_points();
   430     }
   407 
   431     current_audio = audio;
       
   432     if (current_audio) {
       
   433         current_audio->name = bootstrap[i]->name;
       
   434         if (!current_audio->LockAudio && !current_audio->UnlockAudio) {
       
   435             current_audio->LockAudio = SDL_LockAudio_Default;
       
   436             current_audio->UnlockAudio = SDL_UnlockAudio_Default;
       
   437         }
       
   438     }
       
   439     return (0);
   408     return (0);
   440 }
   409 }
   441 
   410 
   442 /*
   411 /*
   443  * Get the current audio driver name
   412  * Get the current audio driver name
   444  */
   413  */
   445 const char *
   414 const char *
   446 SDL_GetCurrentAudioDriver()
   415 SDL_GetCurrentAudioDriver()
   447 {
   416 {
   448     if (current_audio) {
   417     return current_audio.name;
   449         return current_audio->name;
   418 }
   450     }
   419 
   451     return (NULL);
       
   452 }
       
   453 
   420 
   454 int
   421 int
   455 SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   422 SDL_GetNumAudioDevices(int iscapture)
   456 {
   423 {
   457     SDL_AudioDevice *audio;
   424     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   458     const char *env;
   425         return -1;
   459 
   426     }
   460     /* Start up the audio driver, if necessary */
   427     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   461     if (!current_audio) {
   428         return 0;
   462         if ((SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
   429     }
   463             (current_audio == NULL)) {
   430 
   464             return (-1);
   431     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   465         }
   432         return 1;
   466     }
   433     }
   467     audio = current_audio;
   434 
   468 
   435     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   469     if (audio->opened) {
   436         return 1;
   470         SDL_SetError("Audio device is already opened");
   437     }
   471         return (-1);
   438 
   472     }
   439     return current_audio.impl.DetectDevices(iscapture);
   473 
   440 }
   474     /* Verify some parameters */
   441 
   475     if (desired->freq == 0) {
   442 
   476         env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   443 const char *
   477         if (env) {
   444 SDL_GetAudioDeviceName(int index, int iscapture)
   478             desired->freq = SDL_atoi(env);
   445 {
   479         }
   446     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   480     }
   447         SDL_SetError("Audio subsystem is not initialized");
   481     if (desired->freq == 0) {
   448         return NULL;
   482         /* Pick some default audio frequency */
   449     }
   483         desired->freq = 22050;
   450 
   484     }
   451     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
   485     if (desired->format == 0) {
   452         SDL_SetError("No capture support");
   486         env = SDL_getenv("SDL_AUDIO_FORMAT");
   453         return NULL;
   487         if (env) {
   454     }
   488             desired->format = SDL_ParseAudioFormat(env);
   455 
   489         }
   456     if (index < 0) {
   490     }
   457         SDL_SetError("No such device");
   491     if (desired->format == 0) {
   458         return NULL;
   492         /* Pick some default audio format */
   459     }
   493         desired->format = AUDIO_S16;
   460 
   494     }
   461     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
   495     if (desired->channels == 0) {
   462         return DEFAULT_INPUT_DEVNAME;
   496         env = SDL_getenv("SDL_AUDIO_CHANNELS");
   463     }
   497         if (env) {
   464 
   498             desired->channels = (Uint8) SDL_atoi(env);
   465     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
   499         }
   466         return DEFAULT_OUTPUT_DEVNAME;
   500     }
   467     }
   501     if (desired->channels == 0) {
   468 
   502         /* Pick a default number of channels */
   469     return current_audio.impl.GetDeviceName(index, iscapture);
   503         desired->channels = 2;
   470 }
   504     }
   471 
   505     switch (desired->channels) {
   472 
       
   473 static void
       
   474 close_audio_device(SDL_AudioDevice *device)
       
   475 {
       
   476     device->enabled = 0;
       
   477     if (device->thread != NULL) {
       
   478         SDL_WaitThread(device->thread, NULL);
       
   479     }
       
   480     if (device->mixer_lock != NULL) {
       
   481         SDL_DestroyMutex(device->mixer_lock);
       
   482     }
       
   483     if (device->fake_stream != NULL) {
       
   484         SDL_FreeAudioMem(device->fake_stream);
       
   485     }
       
   486     if (device->convert.needed) {
       
   487         SDL_FreeAudioMem(device->convert.buf);
       
   488     }
       
   489     if (device->opened) {
       
   490         current_audio.impl.CloseDevice(device);
       
   491         device->opened = 0;
       
   492     }
       
   493     SDL_FreeAudioMem(device);
       
   494 }
       
   495 
       
   496 
       
   497 /*
       
   498  * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
       
   499  *  Fills in a sanitized copy in (prepared).
       
   500  *  Returns non-zero if okay, zero on fatal parameters in (orig).
       
   501  */
       
   502 static int
       
   503 prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
       
   504 {
       
   505     SDL_memcpy(prepared, orig, sizeof (SDL_AudioSpec));
       
   506 
       
   507     if (orig->callback == NULL) {
       
   508         SDL_SetError("SDL_OpenAudio() passed a NULL callback");
       
   509         return 0;
       
   510     }
       
   511 
       
   512     if (orig->freq == 0) {
       
   513         const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
       
   514         if ( (!env) || ((prepared->freq = SDL_atoi(env)) == 0) ) {
       
   515             prepared->freq = 22050;  /* a reasonable default */
       
   516         }
       
   517     }
       
   518 
       
   519     if (orig->format == 0) {
       
   520         const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
       
   521         if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
       
   522             prepared->format = AUDIO_S16;  /* a reasonable default */
       
   523         }
       
   524     }
       
   525 
       
   526     switch (orig->channels) {
       
   527     case 0: {
       
   528         const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
       
   529         if ( (!env) || ((prepared->channels = SDL_atoi(env)) == 0) ) {
       
   530             prepared->channels = 2;  /* a reasonable default */
       
   531         }
       
   532         break;
       
   533     }
   506     case 1:                    /* Mono */
   534     case 1:                    /* Mono */
   507     case 2:                    /* Stereo */
   535     case 2:                    /* Stereo */
   508     case 4:                    /* surround */
   536     case 4:                    /* surround */
   509     case 6:                    /* surround with center and lfe */
   537     case 6:                    /* surround with center and lfe */
   510         break;
   538         break;
   511     default:
   539     default:
   512         SDL_SetError("1 (mono) and 2 (stereo) channels supported");
   540         SDL_SetError("Unsupported number of audio channels.");
   513         return (-1);
   541         return 0;
   514     }
   542     }
   515     if (desired->samples == 0) {
   543 
   516         env = SDL_getenv("SDL_AUDIO_SAMPLES");
   544     if (orig->samples == 0) {
   517         if (env) {
   545         const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
   518             desired->samples = (Uint16) SDL_atoi(env);
   546         if ( (!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0) ) {
   519         }
   547             /* Pick a default of ~46 ms at desired frequency */
   520     }
   548             /* !!! FIXME: remove this when the non-Po2 resampling is in. */
   521     if (desired->samples == 0) {
   549             const int samples = (prepared->freq / 1000) * 46;
   522         /* Pick a default of ~46 ms at desired frequency */
   550             int power2 = 1;
   523         int samples = (desired->freq / 1000) * 46;
   551             while (power2 < samples) {
   524         int power2 = 1;
   552                 power2 *= 2;
   525         while (power2 < samples) {
   553             }
   526             power2 *= 2;
   554             prepared->samples = power2;
   527         }
   555         }
   528         desired->samples = power2;
   556     }
   529     }
   557 
   530     if (desired->callback == NULL) {
   558     /* Calculate the silence and size of the audio specification */
   531         SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   559     SDL_CalculateAudioSpec(prepared);
   532         return (-1);
   560 
   533     }
   561     return 1;
   534 #if defined(__MINT__) && SDL_THREADS_DISABLED
   562 }
   535     /* Uses interrupt driven audio, without thread */
   563 
   536 #else
   564 
       
   565 static SDL_AudioDeviceID
       
   566 open_audio_device(const char *devname, int iscapture,
       
   567                     const SDL_AudioSpec *_desired, SDL_AudioSpec *obtained,
       
   568                     int min_id)
       
   569 {
       
   570     SDL_AudioDeviceID id = 0;
       
   571     SDL_AudioSpec desired;
       
   572     SDL_AudioDevice *device;
       
   573     int i = 0;
       
   574 
       
   575     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
       
   576         SDL_SetError("Audio subsystem is not initialized");
       
   577         return 0;
       
   578     }
       
   579 
       
   580     if ((iscapture) && (!current_audio.impl.HasCaptureSupport)) {
       
   581         SDL_SetError("No capture support");
       
   582         return 0;
       
   583     }
       
   584 
       
   585     if (!prepare_audiospec(_desired, &desired)) {
       
   586         return 0;
       
   587     }
       
   588 
       
   589     /* If app doesn't care about a specific device, let the user override. */
       
   590     if (devname == NULL) {
       
   591         devname = SDL_getenv("SDL_AUDIO_DEVICE_NAME");
       
   592     }
       
   593 
       
   594     /*
       
   595      * Catch device names at the high level for the simple case...
       
   596      * This lets us have a basic "device enumeration" for systems that
       
   597      *  don't have multiple devices, but makes sure the device name is
       
   598      *  always NULL when it hits the low level.
       
   599      *
       
   600      * Also make sure that the simple case prevents multiple simultaneous
       
   601      *  opens of the default system device.
       
   602      */
       
   603 
       
   604     if ((iscapture) && (current_audio.impl.OnlyHasDefaultInputDevice)) {
       
   605         if ((devname) && (SDL_strcmp(devname, DEFAULT_INPUT_DEVNAME) != 0)) {
       
   606             SDL_SetError("No such device");
       
   607             return 0;
       
   608         }
       
   609         devname = NULL;
       
   610 
       
   611         for (i = 0; i < SDL_arraysize(open_devices); i++) {
       
   612             if ((open_devices[i]) && (open_devices[i]->iscapture)) {
       
   613                 SDL_SetError("Audio device already open");
       
   614                 return 0;
       
   615             }
       
   616         }
       
   617     }
       
   618 
       
   619     if ((!iscapture) && (current_audio.impl.OnlyHasDefaultOutputDevice)) {
       
   620         if ((devname) && (SDL_strcmp(devname, DEFAULT_OUTPUT_DEVNAME) != 0)) {
       
   621             SDL_SetError("No such device");
       
   622             return 0;
       
   623         }
       
   624         devname = NULL;
       
   625 
       
   626         for (i = 0; i < SDL_arraysize(open_devices); i++) {
       
   627             if ((open_devices[i]) && (!open_devices[i]->iscapture)) {
       
   628                 SDL_SetError("Audio device already open");
       
   629                 return 0;
       
   630             }
       
   631         }
       
   632     }
       
   633 
       
   634     device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof (SDL_AudioDevice));
       
   635     if (device == NULL) {
       
   636         SDL_OutOfMemory();
       
   637         return 0;
       
   638     }
       
   639     SDL_memset(device, '\0', sizeof (SDL_AudioDevice));
       
   640     SDL_memcpy(&device->spec, &desired, sizeof (SDL_AudioSpec));
       
   641     device->enabled = 1;
       
   642     device->paused = 1;
       
   643     device->iscapture = iscapture;
       
   644 
   537     /* Create a semaphore for locking the sound buffers */
   645     /* Create a semaphore for locking the sound buffers */
   538     audio->mixer_lock = SDL_CreateMutex();
   646     if (!current_audio.impl.SkipMixerLock) {
   539     if (audio->mixer_lock == NULL) {
   647         device->mixer_lock = SDL_CreateMutex();
   540         SDL_SetError("Couldn't create mixer lock");
   648         if (device->mixer_lock == NULL) {
   541         SDL_CloseAudio();
   649             close_audio_device(device);
   542         return (-1);
   650             SDL_SetError("Couldn't create mixer lock");
   543     }
   651             return 0;
   544 #endif /* __MINT__ */
   652         }
   545 
   653     }
   546     /* Calculate the silence and size of the audio specification */
   654 
   547     SDL_CalculateAudioSpec(desired);
   655     if (!current_audio.impl.OpenDevice(device, devname, iscapture)) {
   548 
   656         close_audio_device(device);
   549     /* Open the audio subsystem */
   657         return 0;
   550     SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
   658     }
   551     audio->convert.needed = 0;
   659     device->opened = 1;
   552     audio->enabled = 1;
       
   553     audio->paused = 1;
       
   554 
       
   555 #if !SDL_AUDIO_DRIVER_AHI
       
   556 
       
   557 /* AmigaOS opens audio inside the main loop */
       
   558     audio->opened = audio->OpenAudio(audio, &audio->spec) + 1;
       
   559 
       
   560     if (!audio->opened) {
       
   561         SDL_CloseAudio();
       
   562         return (-1);
       
   563     }
       
   564 #else
       
   565     D(bug("Locking semaphore..."));
       
   566     SDL_mutexP(audio->mixer_lock);
       
   567 
       
   568 
       
   569     audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
       
   570     D(bug("Created thread...\n"));
       
   571 
       
   572     if (audio->thread == NULL) {
       
   573         SDL_mutexV(audio->mixer_lock);
       
   574         SDL_CloseAudio();
       
   575         SDL_SetError("Couldn't create audio thread");
       
   576         return (-1);
       
   577     }
       
   578 
       
   579     while (!audio_configured)
       
   580         SDL_Delay(100);
       
   581 #endif
       
   582 
   660 
   583     /* If the audio driver changes the buffer size, accept it */
   661     /* If the audio driver changes the buffer size, accept it */
   584     if (audio->spec.samples != desired->samples) {
   662     if (device->spec.samples != desired.samples) {
   585         desired->samples = audio->spec.samples;
   663         desired.samples = device->spec.samples;
   586         SDL_CalculateAudioSpec(desired);
   664         SDL_CalculateAudioSpec(&device->spec);
   587     }
   665     }
   588 
   666 
   589     /* Allocate a fake audio memory buffer */
   667     /* Allocate a fake audio memory buffer */
   590     audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
   668     device->fake_stream = SDL_AllocAudioMem(device->spec.size);
   591     if (audio->fake_stream == NULL) {
   669     if (device->fake_stream == NULL) {
   592         SDL_CloseAudio();
   670         close_audio_device(device);
   593         SDL_OutOfMemory();
   671         SDL_OutOfMemory();
   594         return (-1);
   672         return 0;
   595     }
   673     }
   596 
   674 
   597     /* See if we need to do any conversion */
   675     /* See if we need to do any conversion */
   598     if (obtained != NULL) {
   676     if (obtained != NULL) {
   599         SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
   677         SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec));
   600     } else if (desired->freq != audio->spec.freq ||
   678     } else if (desired.freq != device->spec.freq ||
   601                desired->format != audio->spec.format ||
   679                desired.format != device->spec.format ||
   602                desired->channels != audio->spec.channels) {
   680                desired.channels != device->spec.channels) {
   603         /* Build an audio conversion block */
   681         /* Build an audio conversion block */
   604         if (SDL_BuildAudioCVT(&audio->convert,
   682         if (SDL_BuildAudioCVT(&device->convert,
   605                               desired->format, desired->channels,
   683                               desired.format, desired.channels,
   606                               desired->freq,
   684                               desired.freq,
   607                               audio->spec.format, audio->spec.channels,
   685                               device->spec.format, device->spec.channels,
   608                               audio->spec.freq) < 0) {
   686                               device->spec.freq) < 0) {
   609             SDL_CloseAudio();
   687             close_audio_device(device);
   610             return (-1);
   688             return 0;
   611         }
   689         }
   612         if (audio->convert.needed) {
   690         if (device->convert.needed) {
   613             audio->convert.len = desired->size;
   691             device->convert.len = desired.size;
   614             audio->convert.buf =
   692             device->convert.buf =
   615                 (Uint8 *) SDL_AllocAudioMem(audio->convert.len *
   693                 (Uint8 *) SDL_AllocAudioMem(device->convert.len *
   616                                             audio->convert.len_mult);
   694                                             device->convert.len_mult);
   617             if (audio->convert.buf == NULL) {
   695             if (device->convert.buf == NULL) {
   618                 SDL_CloseAudio();
   696                 close_audio_device(device);
   619                 SDL_OutOfMemory();
   697                 SDL_OutOfMemory();
   620                 return (-1);
   698                 return 0;
   621             }
   699             }
   622         }
   700         }
   623     }
   701     }
   624 #if !SDL_AUDIO_DRIVER_AHI
   702 
       
   703     /* Find an available device ID and store the structure... */
       
   704     for (id = min_id-1; id < SDL_arraysize(open_devices); id++) {
       
   705         if (open_devices[id] == NULL) {
       
   706             open_devices[id] = device;
       
   707             break;
       
   708         }
       
   709     }
       
   710 
       
   711     if (id == SDL_arraysize(open_devices)) {
       
   712         SDL_SetError("Too many open audio devices");
       
   713         close_audio_device(device);
       
   714         return 0;
       
   715     }
       
   716 
   625     /* Start the audio thread if necessary */
   717     /* Start the audio thread if necessary */
   626     switch (audio->opened) {
   718     if (!current_audio.impl.ProvidesOwnCallbackThread) {
   627     case 1:
       
   628         /* Start the audio thread */
   719         /* Start the audio thread */
       
   720 /* !!! FIXME: this is nasty. */
   629 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
   721 #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
   630 #undef SDL_CreateThread
   722 #undef SDL_CreateThread
   631         audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
   723         device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL);
   632 #else
   724 #else
   633         audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
   725         device->thread = SDL_CreateThread(SDL_RunAudio, device);
   634 #endif
   726 #endif
   635         if (audio->thread == NULL) {
   727         if (device->thread == NULL) {
   636             SDL_CloseAudio();
   728             SDL_CloseAudioDevice(id+1);
   637             SDL_SetError("Couldn't create audio thread");
   729             SDL_SetError("Couldn't create audio thread");
       
   730             return 0;
       
   731         }
       
   732     }
       
   733 
       
   734     return id+1;
       
   735 }
       
   736 
       
   737 
       
   738 int
       
   739 SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
       
   740 {
       
   741     SDL_AudioDeviceID id = 0;
       
   742 
       
   743     /* Start up the audio driver, if necessary. This is legacy behaviour! */
       
   744     if (!SDL_WasInit(SDL_INIT_AUDIO)) {
       
   745         if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
   638             return (-1);
   746             return (-1);
   639         }
   747         }
   640         break;
   748     }
   641 
   749 
   642     default:
   750     /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
   643         /* The audio is now playing */
   751     if (open_devices[0] != NULL) {
   644         break;
   752         SDL_SetError("Audio device is already opened");
   645     }
   753         return (-1);
   646 #else
   754     }
   647     SDL_mutexV(audio->mixer_lock);
   755 
   648     D(bug("SDL_OpenAudio USCITA...\n"));
   756     id = open_audio_device(NULL, 0, desired, obtained, 1);
   649 
   757     if (id > 1) {  /* this should never happen in theory... */
   650 #endif
   758         SDL_CloseAudioDevice(id);
   651 
   759         SDL_SetError("Internal error");  /* MUST be Device ID #1! */
   652     return (0);
   760         return (-1);
       
   761     }
       
   762 
       
   763     return ((id == 0) ? -1 : 0);
       
   764 }
       
   765 
       
   766 SDL_AudioDeviceID
       
   767 SDL_OpenAudioDevice(const char *device, int iscapture,
       
   768                     const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
       
   769 {
       
   770     return open_audio_device(device, iscapture, desired, obtained, 2);
   653 }
   771 }
   654 
   772 
   655 SDL_audiostatus
   773 SDL_audiostatus
   656 SDL_GetAudioStatus(void)
   774 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
   657 {
   775 {
   658     SDL_AudioDevice *audio = current_audio;
   776     SDL_AudioDevice *device = get_audio_device(devid);
   659     SDL_audiostatus status;
   777     SDL_audiostatus status = SDL_AUDIO_STOPPED;
   660 
   778     if (device && device->enabled) {
   661     status = SDL_AUDIO_STOPPED;
   779         if (device->paused) {
   662     if (audio && audio->enabled) {
       
   663         if (audio->paused) {
       
   664             status = SDL_AUDIO_PAUSED;
   780             status = SDL_AUDIO_PAUSED;
   665         } else {
   781         } else {
   666             status = SDL_AUDIO_PLAYING;
   782             status = SDL_AUDIO_PLAYING;
   667         }
   783         }
   668     }
   784     }
   669     return (status);
   785     return (status);
   670 }
   786 }
   671 
   787 
       
   788 
       
   789 SDL_audiostatus
       
   790 SDL_GetAudioStatus(void)
       
   791 {
       
   792     return SDL_GetAudioDeviceStatus(1);
       
   793 }
       
   794 
       
   795 void
       
   796 SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
       
   797 {
       
   798     SDL_AudioDevice *device = get_audio_device(devid);
       
   799     if (device) {
       
   800         device->paused = pause_on;
       
   801     }
       
   802 }
       
   803 
   672 void
   804 void
   673 SDL_PauseAudio(int pause_on)
   805 SDL_PauseAudio(int pause_on)
   674 {
   806 {
   675     SDL_AudioDevice *audio = current_audio;
   807     SDL_PauseAudioDevice(1, pause_on);
   676 
   808 }
   677     if (audio) {
   809 
   678         audio->paused = pause_on;
   810 
       
   811 void
       
   812 SDL_LockAudioDevice(SDL_AudioDeviceID devid)
       
   813 {
       
   814     /* Obtain a lock on the mixing buffers */
       
   815     SDL_AudioDevice *device = get_audio_device(devid);
       
   816     if (device) {
       
   817         current_audio.impl.LockDevice(device);
   679     }
   818     }
   680 }
   819 }
   681 
   820 
   682 void
   821 void
   683 SDL_LockAudio(void)
   822 SDL_LockAudio(void)
   684 {
   823 {
   685     SDL_AudioDevice *audio = current_audio;
   824     SDL_LockAudioDevice(1);
   686 
   825 }
       
   826 
       
   827 void
       
   828 SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
       
   829 {
   687     /* Obtain a lock on the mixing buffers */
   830     /* Obtain a lock on the mixing buffers */
   688     if (audio && audio->LockAudio) {
   831     SDL_AudioDevice *device = get_audio_device(devid);
   689         audio->LockAudio(audio);
   832     if (device) {
       
   833         current_audio.impl.UnlockDevice(device);
   690     }
   834     }
   691 }
   835 }
   692 
   836 
   693 void
   837 void
   694 SDL_UnlockAudio(void)
   838 SDL_UnlockAudio(void)
   695 {
   839 {
   696     SDL_AudioDevice *audio = current_audio;
   840     SDL_UnlockAudioDevice(1);
   697 
   841 }
   698     /* Release lock on the mixing buffers */
   842 
   699     if (audio && audio->UnlockAudio) {
   843 void
   700         audio->UnlockAudio(audio);
   844 SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
       
   845 {
       
   846     SDL_AudioDevice *device = get_audio_device(devid);
       
   847     if (device) {
       
   848         close_audio_device(device);
       
   849         open_devices[devid-1] = NULL;
   701     }
   850     }
   702 }
   851 }
   703 
   852 
   704 void
   853 void
   705 SDL_CloseAudio(void)
   854 SDL_CloseAudio(void)
   706 {
   855 {
   707     SDL_QuitSubSystem(SDL_INIT_AUDIO);
   856     SDL_CloseAudioDevice(1);
   708 }
   857 }
   709 
   858 
   710 void
   859 void
   711 SDL_AudioQuit(void)
   860 SDL_AudioQuit(void)
   712 {
   861 {
   713     SDL_AudioDevice *audio = current_audio;
   862     SDL_AudioDeviceID i;
   714 
   863     for (i = 0; i < SDL_arraysize(open_devices); i++) {
   715     if (audio) {
   864         SDL_CloseAudioDevice(i);
   716         audio->enabled = 0;
   865     }
   717         if (audio->thread != NULL) {
   866 
   718             SDL_WaitThread(audio->thread, NULL);
   867     /* Free the driver data */
   719         }
   868     current_audio.impl.Deinitialize();
   720         if (audio->mixer_lock != NULL) {
   869     SDL_memset(&current_audio, '\0', sizeof (current_audio));
   721             SDL_DestroyMutex(audio->mixer_lock);
   870     SDL_memset(open_devices, '\0', sizeof (open_devices));
   722         }
       
   723         if (audio->fake_stream != NULL) {
       
   724             SDL_FreeAudioMem(audio->fake_stream);
       
   725         }
       
   726         if (audio->convert.needed) {
       
   727             SDL_FreeAudioMem(audio->convert.buf);
       
   728 
       
   729         }
       
   730 #if !SDL_AUDIO_DRIVER_AHI
       
   731         if (audio->opened) {
       
   732             audio->CloseAudio(audio);
       
   733             audio->opened = 0;
       
   734         }
       
   735 #endif
       
   736         /* Free the driver data */
       
   737         audio->free(audio);
       
   738         current_audio = NULL;
       
   739     }
       
   740 }
   871 }
   741 
   872 
   742 #define NUM_FORMATS 10
   873 #define NUM_FORMATS 10
   743 static int format_idx;
   874 static int format_idx;
   744 static int format_idx_sub;
   875 static int format_idx_sub;
   795         break;
   926         break;
   796     default:
   927     default:
   797         spec->silence = 0x00;
   928         spec->silence = 0x00;
   798         break;
   929         break;
   799     }
   930     }
   800     spec->size = (spec->format & 0xFF) / 8;
   931     spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
   801     spec->size *= spec->channels;
   932     spec->size *= spec->channels;
   802     spec->size *= spec->samples;
   933     spec->size *= spec->samples;
   803 }
   934 }
   804 
   935 
       
   936 
       
   937 /*
       
   938  * Moved here from SDL_mixer.c, since it relies on internals of an opened
       
   939  *  audio device (and is deprecated, by the way!).
       
   940  */
       
   941 void
       
   942 SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
       
   943 {
       
   944     /* Mix the user-level audio format */
       
   945     SDL_AudioDevice *device = get_audio_device(1);
       
   946     if (device != NULL) {
       
   947         SDL_AudioFormat format;
       
   948         if (device->convert.needed) {
       
   949             format = device->convert.src_format;
       
   950         } else {
       
   951             format = device->spec.format;
       
   952         }
       
   953         SDL_MixAudioFormat(dst, src, format, len, volume);
       
   954     }
       
   955 }
       
   956 
   805 /* vi: set ts=4 sw=4 expandtab: */
   957 /* vi: set ts=4 sw=4 expandtab: */