First batch of heavy lifting on supporting multiple audio devices at once. SDL-ryan-multiple-audio-device
authorRyan C. Gordon <icculus@icculus.org>
Sun, 01 Oct 2006 05:24:03 +0000
branchSDL-ryan-multiple-audio-device
changeset 378437c9c4590689
parent 3783 dc3870a3f30d
child 3785 da2ea0694d11
First batch of heavy lifting on supporting multiple audio devices at once.
This has a long way to go yet, most of the drivers aren't updated for the
new interfaces, and it's still got some obvious bugs, FIXMEs, and wistlist
items.

Don't use yet.
include/SDL_audio.h
src/audio/SDL_audio.c
src/audio/SDL_mixer.c
src/audio/SDL_sysaudio.h
src/audio/disk/SDL_diskaudio.c
src/audio/dummy/SDL_dummyaudio.c
src/audio/macosx/SDL_coreaudio.c
src/audio/macosx/SDL_coreaudio.h
src/audio/macrom/SDL_romaudio.c
src/audio/macrom/SDL_romaudio.h
     1.1 --- a/include/SDL_audio.h	Sun Oct 01 05:21:40 2006 +0000
     1.2 +++ b/include/SDL_audio.h	Sun Oct 01 05:24:03 2006 +0000
     1.3 @@ -212,7 +212,7 @@
     1.4   * may modify the requested size of the audio buffer, you should allocate
     1.5   * any local mixing buffers after you open the audio device.
     1.6   */
     1.7 -extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,
     1.8 +extern DECLSPEC int SDLCALL SDL_OpenAudio(const SDL_AudioSpec * desired,
     1.9                                            SDL_AudioSpec * obtained);
    1.10  
    1.11  /*
    1.12 @@ -243,7 +243,8 @@
    1.13  /*
    1.14   * Open a specific audio device. Passing in a device name of NULL is
    1.15   *  equivalent to SDL_OpenAudio(). Returns 0 on error, a valid device ID
    1.16 - *  on success.
    1.17 + *  on success. SDL_OpenAudio(), unlike this function, always acts on device
    1.18 + *  ID 1.
    1.19   */
    1.20  extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(const char
    1.21                                                                *device,
     2.1 --- a/src/audio/SDL_audio.c	Sun Oct 01 05:21:40 2006 +0000
     2.2 +++ b/src/audio/SDL_audio.c	Sun Oct 01 05:24:03 2006 +0000
     2.3 @@ -34,6 +34,12 @@
     2.4  #include <os2.h>
     2.5  #endif
     2.6  
     2.7 +static SDL_AudioDriver current_audio;
     2.8 +
     2.9 +/* !!! FIXME: don't use a static array, but it's Good Enough For Now... */
    2.10 +static SDL_AudioDevice *open_devices[16];
    2.11 +
    2.12 +
    2.13  /* Available audio drivers */
    2.14  static AudioBootStrap *bootstrap[] = {
    2.15  #if SDL_AUDIO_DRIVER_BSD
    2.16 @@ -109,27 +115,38 @@
    2.17  #endif
    2.18      NULL
    2.19  };
    2.20 -SDL_AudioDevice *current_audio = NULL;
    2.21 -
    2.22 -/* Various local functions */
    2.23 -int SDL_AudioInit(const char *driver_name);
    2.24 -void SDL_AudioQuit(void);
    2.25  
    2.26  #if SDL_AUDIO_DRIVER_AHI
    2.27  static int audio_configured = 0;
    2.28  #endif
    2.29  
    2.30 +static SDL_AudioDevice *get_audio_device(SDL_AudioDeviceID id)
    2.31 +{
    2.32 +    id--;
    2.33 +    if ( (id >= SDL_arraysize(open_devices)) || (open_devices[id] == NULL) ) {
    2.34 +        SDL_SetError("Invalid audio device ID");
    2.35 +        return NULL;
    2.36 +    }
    2.37 +
    2.38 +    return open_devices[id];
    2.39 +}
    2.40 +
    2.41 +
    2.42  /* The general mixing thread function */
    2.43  int SDLCALL
    2.44 -SDL_RunAudio(void *audiop)
    2.45 +SDL_RunAudio(void *devicep)
    2.46  {
    2.47 -    SDL_AudioDevice *audio = (SDL_AudioDevice *) audiop;
    2.48 +    SDL_AudioDevice *device = (SDL_AudioDevice *) devicep;
    2.49 +    const int legacy_device = (device == open_devices[0]);
    2.50      Uint8 *stream;
    2.51      int stream_len;
    2.52      void *udata;
    2.53      void (SDLCALL * fill) (void *userdata, Uint8 * stream, int len);
    2.54      int silence;
    2.55 +
    2.56 +/* !!! FIXME: can we push this into the Amiga driver? */
    2.57  #if SDL_AUDIO_DRIVER_AHI
    2.58 +#error this is probably broken.
    2.59      int started = 0;
    2.60  
    2.61  /* AmigaOS NEEDS that the audio driver is opened in the thread that uses it! */
    2.62 @@ -145,14 +162,14 @@
    2.63  #endif
    2.64  
    2.65      /* Perform any thread setup */
    2.66 -    if (audio->ThreadInit) {
    2.67 -        audio->ThreadInit(audio);
    2.68 +    if (current_audio.impl.ThreadInit != NULL) {
    2.69 +        current_audio.impl.ThreadInit(device);
    2.70      }
    2.71 -    audio->threadid = SDL_ThreadID();
    2.72 +    device->threadid = SDL_ThreadID();
    2.73  
    2.74      /* Set up the mixing function */
    2.75 -    fill = audio->spec.callback;
    2.76 -    udata = audio->spec.userdata;
    2.77 +    fill = device->spec.callback;
    2.78 +    udata = device->spec.userdata;
    2.79  
    2.80  #if SDL_AUDIO_DRIVER_AHI
    2.81      audio_configured = 1;
    2.82 @@ -162,23 +179,24 @@
    2.83      D(bug("Semaphore obtained...\n"));
    2.84  #endif
    2.85  
    2.86 -    if (audio->convert.needed) {
    2.87 -        if (audio->convert.src_format == AUDIO_U8) {
    2.88 +    if (device->convert.needed) {
    2.89 +        if (device->convert.src_format == AUDIO_U8) {
    2.90              silence = 0x80;
    2.91          } else {
    2.92              silence = 0;
    2.93          }
    2.94 -        stream_len = audio->convert.len;
    2.95 +        stream_len = device->convert.len;
    2.96      } else {
    2.97 -        silence = audio->spec.silence;
    2.98 -        stream_len = audio->spec.size;
    2.99 +        silence = device->spec.silence;
   2.100 +        stream_len = device->spec.size;
   2.101      }
   2.102  
   2.103  #if SDL_AUDIO_DRIVER_AHI
   2.104 -    SDL_mutexV(audio->mixer_lock);
   2.105 +    SDL_mutexV(device->mixer_lock);
   2.106      D(bug("Entering audio loop...\n"));
   2.107  #endif
   2.108  
   2.109 +/* !!! FIXME: push this out of core. */
   2.110  #ifdef __OS2__
   2.111      /* Increase the priority of this thread to make sure that
   2.112         the audio will be continuous all the time! */
   2.113 @@ -202,55 +220,59 @@
   2.114  #endif
   2.115  
   2.116      /* Loop, filling the audio buffers */
   2.117 -    while (audio->enabled) {
   2.118 +    while (device->enabled) {
   2.119  
   2.120          /* Fill the current buffer with sound */
   2.121 -        if (audio->convert.needed) {
   2.122 -            if (audio->convert.buf) {
   2.123 -                stream = audio->convert.buf;
   2.124 +        if (device->convert.needed) {
   2.125 +            if (device->convert.buf) {
   2.126 +                stream = device->convert.buf;
   2.127              } else {
   2.128                  continue;
   2.129              }
   2.130          } else {
   2.131 -            stream = audio->GetAudioBuf(audio);
   2.132 +            stream = current_audio.impl.GetAudioBuf(device);
   2.133              if (stream == NULL) {
   2.134 -                stream = audio->fake_stream;
   2.135 +                stream = device->fake_stream;
   2.136              }
   2.137          }
   2.138 -        SDL_memset(stream, silence, stream_len);
   2.139  
   2.140 -        if (!audio->paused) {
   2.141 -            SDL_mutexP(audio->mixer_lock);
   2.142 +        /* New code should fill buffer or set it to silence themselves. */
   2.143 +        if (legacy_device) {
   2.144 +            SDL_memset(stream, silence, stream_len);
   2.145 +        }
   2.146 +
   2.147 +        if (!device->paused) {
   2.148 +            SDL_mutexP(device->mixer_lock);
   2.149              (*fill) (udata, stream, stream_len);
   2.150 -            SDL_mutexV(audio->mixer_lock);
   2.151 +            SDL_mutexV(device->mixer_lock);
   2.152          }
   2.153  
   2.154          /* Convert the audio if necessary */
   2.155 -        if (audio->convert.needed) {
   2.156 -            SDL_ConvertAudio(&audio->convert);
   2.157 -            stream = audio->GetAudioBuf(audio);
   2.158 +        if (device->convert.needed) {
   2.159 +            SDL_ConvertAudio(&device->convert);
   2.160 +            stream = current_audio.impl.GetAudioBuf(device);
   2.161              if (stream == NULL) {
   2.162 -                stream = audio->fake_stream;
   2.163 +                stream = device->fake_stream;
   2.164              }
   2.165 -            SDL_memcpy(stream, audio->convert.buf, audio->convert.len_cvt);
   2.166 +            SDL_memcpy(stream, device->convert.buf, device->convert.len_cvt);
   2.167          }
   2.168  
   2.169          /* Ready current buffer for play and change current buffer */
   2.170 -        if (stream != audio->fake_stream) {
   2.171 -            audio->PlayAudio(audio);
   2.172 +        if (stream != device->fake_stream) {
   2.173 +            current_audio.impl.PlayAudio(device);
   2.174          }
   2.175  
   2.176          /* Wait for an audio buffer to become available */
   2.177 -        if (stream == audio->fake_stream) {
   2.178 -            SDL_Delay((audio->spec.samples * 1000) / audio->spec.freq);
   2.179 +        if (stream == device->fake_stream) {
   2.180 +            SDL_Delay((device->spec.samples * 1000) / device->spec.freq);
   2.181          } else {
   2.182 -            audio->WaitAudio(audio);
   2.183 +            current_audio.impl.WaitAudio(device);
   2.184          }
   2.185      }
   2.186  
   2.187      /* Wait for the audio to drain.. */
   2.188 -    if (audio->WaitDone) {
   2.189 -        audio->WaitDone(audio);
   2.190 +    if (current_audio.impl.WaitDone) {
   2.191 +        current_audio.impl.WaitDone(device);
   2.192      }
   2.193  #if SDL_AUDIO_DRIVER_AHI
   2.194      D(bug("WaitAudio...Done\n"));
   2.195 @@ -330,20 +352,24 @@
   2.196  int
   2.197  SDL_AudioInit(const char *driver_name)
   2.198  {
   2.199 -    SDL_AudioDevice *audio;
   2.200 -    int i = 0, idx;
   2.201 +    int i = 0;
   2.202 +    int initialized = 0;
   2.203  
   2.204 -    /* Check to make sure we don't overwrite 'current_audio' */
   2.205 -    if (current_audio != NULL) {
   2.206 -        SDL_AudioQuit();
   2.207 +    if (SDL_WasInit(SDL_INIT_AUDIO)) {
   2.208 +        SDL_AudioQuit();  /* shutdown driver if already running. */
   2.209      }
   2.210  
   2.211 +    SDL_memset(&current_audio, '\0', sizeof (current_audio));
   2.212 +    SDL_memset(open_devices, '\0', sizeof (open_devices));
   2.213 +
   2.214 +    /* !!! FIXME: build a priority list of available drivers... */
   2.215 +
   2.216      /* Select the proper audio driver */
   2.217 -    audio = NULL;
   2.218 -    idx = 0;
   2.219      if (driver_name == NULL) {
   2.220          driver_name = SDL_getenv("SDL_AUDIODRIVER");
   2.221      }
   2.222 +
   2.223 +/* !!! FIXME: move this esound shite into the esound driver... */
   2.224  #if SDL_AUDIO_DRIVER_ESD
   2.225      if ((driver_name == NULL) && (SDL_getenv("ESPEAKER") != NULL)) {
   2.226          /* Ahem, we know that if ESPEAKER is set, user probably wants
   2.227 @@ -362,7 +388,10 @@
   2.228                  }
   2.229  #endif
   2.230                  if (bootstrap[i]->available()) {
   2.231 -                    audio = bootstrap[i]->create(0);
   2.232 +                    SDL_memset(&current_audio, 0, sizeof (current_audio));
   2.233 +                    current_audio.name = bootstrap[i]->name;
   2.234 +                    current_audio.desc = bootstrap[i]->desc;
   2.235 +                    initialized = bootstrap[i]->init(&current_audio.impl);
   2.236                      break;
   2.237                  }
   2.238  #ifdef HAVE_UNSETENV
   2.239 @@ -374,47 +403,44 @@
   2.240          }
   2.241      }
   2.242  #endif /* SDL_AUDIO_DRIVER_ESD */
   2.243 -    if (audio == NULL) {
   2.244 +
   2.245 +    if (!initialized) {
   2.246          if (driver_name != NULL) {
   2.247              for (i = 0; bootstrap[i]; ++i) {
   2.248                  if (SDL_strcasecmp(bootstrap[i]->name, driver_name) == 0) {
   2.249                      if (bootstrap[i]->available()) {
   2.250 -                        audio = bootstrap[i]->create(idx);
   2.251 +                        SDL_memset(&current_audio, 0, sizeof (current_audio));
   2.252 +                        current_audio.name = bootstrap[i]->name;
   2.253 +                        current_audio.desc = bootstrap[i]->desc;
   2.254 +                        initialized = bootstrap[i]->init(&current_audio.impl);
   2.255                      }
   2.256                      break;
   2.257                  }
   2.258              }
   2.259          } else {
   2.260 -            for (i = 0; bootstrap[i]; ++i) {
   2.261 +            for (i = 0; (!initialized) && (bootstrap[i]); ++i) {
   2.262                  if (bootstrap[i]->available()) {
   2.263 -                    audio = bootstrap[i]->create(idx);
   2.264 -                    if (audio != NULL) {
   2.265 -                        break;
   2.266 -                    }
   2.267 +                    SDL_memset(&current_audio, 0, sizeof (current_audio));
   2.268 +                    current_audio.name = bootstrap[i]->name;
   2.269 +                    current_audio.desc = bootstrap[i]->desc;
   2.270 +                    initialized = bootstrap[i]->init(&current_audio.impl);
   2.271                  }
   2.272              }
   2.273          }
   2.274 -        if (audio == NULL) {
   2.275 +        if (!initialized) {
   2.276              if (driver_name) {
   2.277                  SDL_SetError("%s not available", driver_name);
   2.278              } else {
   2.279                  SDL_SetError("No available audio device");
   2.280              }
   2.281 -#if 0
   2.282 -            /* Don't fail SDL_Init() if audio isn't available.
   2.283 -               SDL_OpenAudio() will handle it at that point.  *sigh*
   2.284 -             */
   2.285 -            return (-1);
   2.286 -#endif
   2.287 +            SDL_memset(&current_audio, 0, sizeof (current_audio));
   2.288 +            return (-1);  /* No driver was available, so fail. */
   2.289          }
   2.290      }
   2.291 -    current_audio = audio;
   2.292 -    if (current_audio) {
   2.293 -        current_audio->name = bootstrap[i]->name;
   2.294 -        if (!current_audio->LockAudio && !current_audio->UnlockAudio) {
   2.295 -            current_audio->LockAudio = SDL_LockAudio_Default;
   2.296 -            current_audio->UnlockAudio = SDL_UnlockAudio_Default;
   2.297 -        }
   2.298 +
   2.299 +    if (!current_audio.impl.LockAudio && !current_audio.impl.UnlockAudio) {
   2.300 +        current_audio.impl.LockAudio = SDL_LockAudio_Default;
   2.301 +        current_audio.impl.UnlockAudio = SDL_UnlockAudio_Default;
   2.302      }
   2.303      return (0);
   2.304  }
   2.305 @@ -425,123 +451,161 @@
   2.306  const char *
   2.307  SDL_GetCurrentAudioDriver()
   2.308  {
   2.309 -    if (current_audio) {
   2.310 -        return current_audio->name;
   2.311 -    }
   2.312 -    return (NULL);
   2.313 +    return current_audio.name;
   2.314  }
   2.315  
   2.316 -int
   2.317 -SDL_OpenAudio(SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   2.318 +static void
   2.319 +close_audio_device(SDL_AudioDevice *device)
   2.320  {
   2.321 -    SDL_AudioDevice *audio;
   2.322 -    const char *env;
   2.323 +    device->enabled = 0;
   2.324 +    if (device->thread != NULL) {
   2.325 +        SDL_WaitThread(device->thread, NULL);
   2.326 +    }
   2.327 +    if (device->mixer_lock != NULL) {
   2.328 +        SDL_DestroyMutex(device->mixer_lock);
   2.329 +    }
   2.330 +    if (device->fake_stream != NULL) {
   2.331 +        SDL_FreeAudioMem(device->fake_stream);
   2.332 +    }
   2.333 +    if (device->convert.needed) {
   2.334 +        SDL_FreeAudioMem(device->convert.buf);
   2.335 +    }
   2.336 +#if !SDL_AUDIO_DRIVER_AHI   /* !!! FIXME: get rid of this #if. */
   2.337 +    if (device->opened) {
   2.338 +        current_audio.impl.CloseAudio(device);
   2.339 +        device->opened = 0;
   2.340 +    }
   2.341 +#endif
   2.342 +    SDL_FreeAudioMem(device);
   2.343 +}
   2.344  
   2.345 -    /* Start up the audio driver, if necessary */
   2.346 -    if (!current_audio) {
   2.347 -        if ((SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) ||
   2.348 -            (current_audio == NULL)) {
   2.349 -            return (-1);
   2.350 +
   2.351 +/*
   2.352 + * Sanity check desired AudioSpec for SDL_OpenAudio() in (orig).
   2.353 + *  Fills in a sanitized copy in (prepared).
   2.354 + *  Returns non-zero if okay, zero on fatal parameters in (orig).
   2.355 + */
   2.356 +static int
   2.357 +prepare_audiospec(const SDL_AudioSpec *orig, SDL_AudioSpec *prepared)
   2.358 +{
   2.359 +    SDL_memcpy(prepared, orig, sizeof (SDL_AudioSpec));
   2.360 +
   2.361 +    if (orig->callback == NULL) {
   2.362 +        SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   2.363 +        return 0;
   2.364 +    }
   2.365 +
   2.366 +    if (orig->freq == 0) {
   2.367 +        const char *env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   2.368 +        if ( (!env) || ((prepared->freq = SDL_atoi(env)) == 0) ) {
   2.369 +            prepared->freq = 22050;  /* a reasonable default */
   2.370          }
   2.371      }
   2.372 -    audio = current_audio;
   2.373  
   2.374 -    if (audio->opened) {
   2.375 -        SDL_SetError("Audio device is already opened");
   2.376 -        return (-1);
   2.377 +    if (orig->format == 0) {
   2.378 +        const char *env = SDL_getenv("SDL_AUDIO_FORMAT");
   2.379 +        if ((!env) || ((prepared->format = SDL_ParseAudioFormat(env)) == 0)) {
   2.380 +            prepared->format = AUDIO_S16;  /* a reasonable default */
   2.381 +        }
   2.382      }
   2.383  
   2.384 -    /* Verify some parameters */
   2.385 -    if (desired->freq == 0) {
   2.386 -        env = SDL_getenv("SDL_AUDIO_FREQUENCY");
   2.387 -        if (env) {
   2.388 -            desired->freq = SDL_atoi(env);
   2.389 +    switch (orig->channels) {
   2.390 +    case 0: {
   2.391 +        const char *env = SDL_getenv("SDL_AUDIO_CHANNELS");
   2.392 +        if ( (!env) || ((prepared->channels = SDL_atoi(env)) == 0) ) {
   2.393 +            prepared->channels = 2;  /* a reasonable default */
   2.394          }
   2.395 +        break;
   2.396      }
   2.397 -    if (desired->freq == 0) {
   2.398 -        /* Pick some default audio frequency */
   2.399 -        desired->freq = 22050;
   2.400 -    }
   2.401 -    if (desired->format == 0) {
   2.402 -        env = SDL_getenv("SDL_AUDIO_FORMAT");
   2.403 -        if (env) {
   2.404 -            desired->format = SDL_ParseAudioFormat(env);
   2.405 -        }
   2.406 -    }
   2.407 -    if (desired->format == 0) {
   2.408 -        /* Pick some default audio format */
   2.409 -        desired->format = AUDIO_S16;
   2.410 -    }
   2.411 -    if (desired->channels == 0) {
   2.412 -        env = SDL_getenv("SDL_AUDIO_CHANNELS");
   2.413 -        if (env) {
   2.414 -            desired->channels = (Uint8) SDL_atoi(env);
   2.415 -        }
   2.416 -    }
   2.417 -    if (desired->channels == 0) {
   2.418 -        /* Pick a default number of channels */
   2.419 -        desired->channels = 2;
   2.420 -    }
   2.421 -    switch (desired->channels) {
   2.422      case 1:                    /* Mono */
   2.423      case 2:                    /* Stereo */
   2.424      case 4:                    /* surround */
   2.425      case 6:                    /* surround with center and lfe */
   2.426          break;
   2.427      default:
   2.428 -        SDL_SetError("1 (mono) and 2 (stereo) channels supported");
   2.429 -        return (-1);
   2.430 +        SDL_SetError("Unsupported number of audio channels.");
   2.431 +        return 0;
   2.432      }
   2.433 -    if (desired->samples == 0) {
   2.434 -        env = SDL_getenv("SDL_AUDIO_SAMPLES");
   2.435 -        if (env) {
   2.436 -            desired->samples = (Uint16) SDL_atoi(env);
   2.437 +
   2.438 +    if (orig->samples == 0) {
   2.439 +        const char *env = SDL_getenv("SDL_AUDIO_SAMPLES");
   2.440 +        if ( (!env) || ((prepared->samples = (Uint16) SDL_atoi(env)) == 0) ) {
   2.441 +            /* Pick a default of ~46 ms at desired frequency */
   2.442 +            /* !!! FIXME: remove this when the non-Po2 resampling is in. */
   2.443 +            const int samples = (prepared->freq / 1000) * 46;
   2.444 +            int power2 = 1;
   2.445 +            while (power2 < samples) {
   2.446 +                power2 *= 2;
   2.447 +            }
   2.448 +            prepared->samples = power2;
   2.449          }
   2.450      }
   2.451 -    if (desired->samples == 0) {
   2.452 -        /* Pick a default of ~46 ms at desired frequency */
   2.453 -        int samples = (desired->freq / 1000) * 46;
   2.454 -        int power2 = 1;
   2.455 -        while (power2 < samples) {
   2.456 -            power2 *= 2;
   2.457 -        }
   2.458 -        desired->samples = power2;
   2.459 +
   2.460 +    /* Calculate the silence and size of the audio specification */
   2.461 +    SDL_CalculateAudioSpec(prepared);
   2.462 +
   2.463 +    return 1;
   2.464 +}
   2.465 +
   2.466 +
   2.467 +static SDL_AudioDeviceID
   2.468 +open_audio_device(const char *devname, int iscapture,
   2.469 +                    const SDL_AudioSpec *_desired, SDL_AudioSpec *obtained,
   2.470 +                    int min_id)
   2.471 +{
   2.472 +    int i = 0;
   2.473 +    SDL_AudioDeviceID id = 0;
   2.474 +    SDL_AudioSpec desired;
   2.475 +    SDL_AudioDevice *device;
   2.476 +
   2.477 +    if (iscapture) {
   2.478 +        SDL_SetError("Audio capture support not implemented yet!");
   2.479 +        return 0;  /* !!! FIXME */
   2.480      }
   2.481 -    if (desired->callback == NULL) {
   2.482 -        SDL_SetError("SDL_OpenAudio() passed a NULL callback");
   2.483 -        return (-1);
   2.484 +
   2.485 +    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   2.486 +        SDL_SetError("Audio subsystem is not initialized");
   2.487 +        return 0;
   2.488      }
   2.489 +
   2.490 +    if (!prepare_audiospec(_desired, &desired)) {
   2.491 +        return 0;
   2.492 +    }
   2.493 +
   2.494 +    device = (SDL_AudioDevice *) SDL_AllocAudioMem(sizeof (SDL_AudioDevice));
   2.495 +    if (device == NULL) {
   2.496 +        SDL_OutOfMemory();
   2.497 +        return 0;
   2.498 +    }
   2.499 +    SDL_memset(device, '\0', sizeof (SDL_AudioDevice));
   2.500 +    SDL_memcpy(&device->spec, &desired, sizeof (SDL_AudioSpec));
   2.501 +    device->driver = &current_audio;  /* !!! FIXME: unused... */
   2.502 +    device->enabled = 1;
   2.503 +    device->paused = 1;
   2.504 +
   2.505 +/* !!! FIXME: Get this out of the core. */
   2.506  #if defined(__MINT__) && SDL_THREADS_DISABLED
   2.507      /* Uses interrupt driven audio, without thread */
   2.508  #else
   2.509      /* Create a semaphore for locking the sound buffers */
   2.510 -    audio->mixer_lock = SDL_CreateMutex();
   2.511 -    if (audio->mixer_lock == NULL) {
   2.512 +    device->mixer_lock = SDL_CreateMutex();
   2.513 +    if (device->mixer_lock == NULL) {
   2.514          SDL_SetError("Couldn't create mixer lock");
   2.515 -        SDL_CloseAudio();
   2.516 -        return (-1);
   2.517 +        return 0;
   2.518      }
   2.519  #endif /* __MINT__ */
   2.520  
   2.521 -    /* Calculate the silence and size of the audio specification */
   2.522 -    SDL_CalculateAudioSpec(desired);
   2.523 +/* !!! FIXME: Get this #if out of the core. */
   2.524 +/* AmigaOS opens audio inside the main loop */
   2.525 +#if !SDL_AUDIO_DRIVER_AHI
   2.526 +    if (!current_audio.impl.OpenAudio(device, devname, iscapture)) {
   2.527 +        close_audio_device(device);
   2.528 +        return 0;
   2.529 +    }
   2.530 +    device->opened = 2;  /* !!! FIXME */
   2.531 +#else
   2.532 +#   error needs to be fixed for new internal API. Email Ryan for details.
   2.533  
   2.534 -    /* Open the audio subsystem */
   2.535 -    SDL_memcpy(&audio->spec, desired, sizeof(audio->spec));
   2.536 -    audio->convert.needed = 0;
   2.537 -    audio->enabled = 1;
   2.538 -    audio->paused = 1;
   2.539 -
   2.540 -#if !SDL_AUDIO_DRIVER_AHI
   2.541 -
   2.542 -/* AmigaOS opens audio inside the main loop */
   2.543 -    audio->opened = audio->OpenAudio(audio, &audio->spec) + 1;
   2.544 -
   2.545 -    if (!audio->opened) {
   2.546 -        SDL_CloseAudio();
   2.547 -        return (-1);
   2.548 -    }
   2.549 -#else
   2.550      D(bug("Locking semaphore..."));
   2.551      SDL_mutexP(audio->mixer_lock);
   2.552  
   2.553 @@ -553,7 +617,7 @@
   2.554          SDL_mutexV(audio->mixer_lock);
   2.555          SDL_CloseAudio();
   2.556          SDL_SetError("Couldn't create audio thread");
   2.557 -        return (-1);
   2.558 +        return 0;
   2.559      }
   2.560  
   2.561      while (!audio_configured)
   2.562 @@ -561,61 +625,78 @@
   2.563  #endif
   2.564  
   2.565      /* If the audio driver changes the buffer size, accept it */
   2.566 -    if (audio->spec.samples != desired->samples) {
   2.567 -        desired->samples = audio->spec.samples;
   2.568 -        SDL_CalculateAudioSpec(desired);
   2.569 +    if (device->spec.samples != desired.samples) {
   2.570 +        desired.samples = device->spec.samples;
   2.571 +        SDL_CalculateAudioSpec(&device->spec);
   2.572      }
   2.573  
   2.574      /* Allocate a fake audio memory buffer */
   2.575 -    audio->fake_stream = SDL_AllocAudioMem(audio->spec.size);
   2.576 -    if (audio->fake_stream == NULL) {
   2.577 -        SDL_CloseAudio();
   2.578 +    device->fake_stream = SDL_AllocAudioMem(device->spec.size);
   2.579 +    if (device->fake_stream == NULL) {
   2.580 +        close_audio_device(device);
   2.581          SDL_OutOfMemory();
   2.582 -        return (-1);
   2.583 +        return 0;
   2.584      }
   2.585  
   2.586      /* See if we need to do any conversion */
   2.587      if (obtained != NULL) {
   2.588 -        SDL_memcpy(obtained, &audio->spec, sizeof(audio->spec));
   2.589 -    } else if (desired->freq != audio->spec.freq ||
   2.590 -               desired->format != audio->spec.format ||
   2.591 -               desired->channels != audio->spec.channels) {
   2.592 +        SDL_memcpy(obtained, &device->spec, sizeof(SDL_AudioSpec));
   2.593 +    } else if (desired.freq != device->spec.freq ||
   2.594 +               desired.format != device->spec.format ||
   2.595 +               desired.channels != device->spec.channels) {
   2.596          /* Build an audio conversion block */
   2.597 -        if (SDL_BuildAudioCVT(&audio->convert,
   2.598 -                              desired->format, desired->channels,
   2.599 -                              desired->freq,
   2.600 -                              audio->spec.format, audio->spec.channels,
   2.601 -                              audio->spec.freq) < 0) {
   2.602 -            SDL_CloseAudio();
   2.603 -            return (-1);
   2.604 +        if (SDL_BuildAudioCVT(&device->convert,
   2.605 +                              desired.format, desired.channels,
   2.606 +                              desired.freq,
   2.607 +                              device->spec.format, device->spec.channels,
   2.608 +                              device->spec.freq) < 0) {
   2.609 +            close_audio_device(device);
   2.610 +            return 0;
   2.611          }
   2.612 -        if (audio->convert.needed) {
   2.613 -            audio->convert.len = desired->size;
   2.614 -            audio->convert.buf =
   2.615 -                (Uint8 *) SDL_AllocAudioMem(audio->convert.len *
   2.616 -                                            audio->convert.len_mult);
   2.617 -            if (audio->convert.buf == NULL) {
   2.618 -                SDL_CloseAudio();
   2.619 +        if (device->convert.needed) {
   2.620 +            device->convert.len = desired.size;
   2.621 +            device->convert.buf =
   2.622 +                (Uint8 *) SDL_AllocAudioMem(device->convert.len *
   2.623 +                                            device->convert.len_mult);
   2.624 +            if (device->convert.buf == NULL) {
   2.625 +                close_audio_device(device);
   2.626                  SDL_OutOfMemory();
   2.627 -                return (-1);
   2.628 +                return 0;
   2.629              }
   2.630          }
   2.631      }
   2.632 +
   2.633 +    /* Find an available device ID and store the structure... */
   2.634 +    for (id = min_id-1; id < SDL_arraysize(open_devices); id++) {
   2.635 +        if (open_devices[id] == NULL) {
   2.636 +            open_devices[id] = device;
   2.637 +            break;
   2.638 +        }
   2.639 +    }
   2.640 +
   2.641 +    /* !!! FIXME: remove static array... */
   2.642 +    if (id == SDL_arraysize(open_devices)) {
   2.643 +        SDL_SetError("Too many open audio devices");
   2.644 +        close_audio_device(device);
   2.645 +        return 0;
   2.646 +    }
   2.647 +
   2.648  #if !SDL_AUDIO_DRIVER_AHI
   2.649      /* Start the audio thread if necessary */
   2.650 -    switch (audio->opened) {
   2.651 +    switch (device->opened) {  /* !!! FIXME: what is this?! */
   2.652      case 1:
   2.653          /* Start the audio thread */
   2.654 +/* !!! FIXME: this is nasty. */
   2.655  #if (defined(__WIN32__) && !defined(_WIN32_WCE)) && !defined(HAVE_LIBC)
   2.656  #undef SDL_CreateThread
   2.657 -        audio->thread = SDL_CreateThread(SDL_RunAudio, audio, NULL, NULL);
   2.658 +        device->thread = SDL_CreateThread(SDL_RunAudio, device, NULL, NULL);
   2.659  #else
   2.660 -        audio->thread = SDL_CreateThread(SDL_RunAudio, audio);
   2.661 +        device->thread = SDL_CreateThread(SDL_RunAudio, device);
   2.662  #endif
   2.663 -        if (audio->thread == NULL) {
   2.664 -            SDL_CloseAudio();
   2.665 +        if (device->thread == NULL) {
   2.666 +            SDL_CloseAudioDevice(id+1);
   2.667              SDL_SetError("Couldn't create audio thread");
   2.668 -            return (-1);
   2.669 +            return 0;
   2.670          }
   2.671          break;
   2.672  
   2.673 @@ -629,18 +710,52 @@
   2.674  
   2.675  #endif
   2.676  
   2.677 -    return (0);
   2.678 +    return id+1;
   2.679 +}
   2.680 +
   2.681 +
   2.682 +int
   2.683 +SDL_OpenAudio(const SDL_AudioSpec * desired, SDL_AudioSpec * obtained)
   2.684 +{
   2.685 +    SDL_AudioDeviceID id = 0;
   2.686 +
   2.687 +    /* Start up the audio driver, if necessary. This is legacy behaviour! */
   2.688 +    if (!SDL_WasInit(SDL_INIT_AUDIO)) {
   2.689 +        if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
   2.690 +            return (-1);
   2.691 +        }
   2.692 +    }
   2.693 +
   2.694 +    /* SDL_OpenAudio() is legacy and can only act on Device ID #1. */
   2.695 +    if (open_devices[0] != NULL) {
   2.696 +        SDL_SetError("Audio device is already opened");
   2.697 +        return (-1);
   2.698 +    }
   2.699 +
   2.700 +    id = open_audio_device(NULL, 0, desired, obtained, 1);
   2.701 +    if (id > 1) {  /* this should never happen in theory... */
   2.702 +        SDL_CloseAudioDevice(id);
   2.703 +        SDL_SetError("Internal error");  /* MUST be Device ID #1! */
   2.704 +        return (-1);
   2.705 +    }
   2.706 +
   2.707 +    return ((id == 0) ? -1 : 0);
   2.708 +}
   2.709 +
   2.710 +SDL_AudioDeviceID
   2.711 +SDL_OpenAudioDevice(const char *device, int iscapture,
   2.712 +                    const SDL_AudioSpec *desired, SDL_AudioSpec *obtained)
   2.713 +{
   2.714 +    return open_audio_device(device, iscapture, desired, obtained, 2);
   2.715  }
   2.716  
   2.717  SDL_audiostatus
   2.718 -SDL_GetAudioStatus(void)
   2.719 +SDL_GetAudioDeviceStatus(SDL_AudioDeviceID devid)
   2.720  {
   2.721 -    SDL_AudioDevice *audio = current_audio;
   2.722 -    SDL_audiostatus status;
   2.723 -
   2.724 -    status = SDL_AUDIO_STOPPED;
   2.725 -    if (audio && audio->enabled) {
   2.726 -        if (audio->paused) {
   2.727 +    SDL_AudioDevice *device = get_audio_device(devid);
   2.728 +    SDL_audiostatus status = SDL_AUDIO_STOPPED;
   2.729 +    if (device && device->enabled) {
   2.730 +        if (device->paused) {
   2.731              status = SDL_AUDIO_PAUSED;
   2.732          } else {
   2.733              status = SDL_AUDIO_PLAYING;
   2.734 @@ -649,74 +764,93 @@
   2.735      return (status);
   2.736  }
   2.737  
   2.738 +
   2.739 +SDL_audiostatus
   2.740 +SDL_GetAudioStatus(void)
   2.741 +{
   2.742 +    return SDL_GetAudioDeviceStatus(1);
   2.743 +}
   2.744 +
   2.745 +void
   2.746 +SDL_PauseAudioDevice(SDL_AudioDeviceID devid, int pause_on)
   2.747 +{
   2.748 +    SDL_AudioDevice *device = get_audio_device(devid);
   2.749 +    if (device) {
   2.750 +        device->paused = pause_on;
   2.751 +    }
   2.752 +}
   2.753 +
   2.754  void
   2.755  SDL_PauseAudio(int pause_on)
   2.756  {
   2.757 -    SDL_AudioDevice *audio = current_audio;
   2.758 +    SDL_PauseAudioDevice(1, pause_on);
   2.759 +}
   2.760  
   2.761 -    if (audio) {
   2.762 -        audio->paused = pause_on;
   2.763 +
   2.764 +void
   2.765 +SDL_LockAudioDevice(SDL_AudioDeviceID devid)
   2.766 +{
   2.767 +    if (current_audio.impl.LockAudio != NULL) {
   2.768 +        SDL_AudioDevice *device = get_audio_device(devid);
   2.769 +        /* Obtain a lock on the mixing buffers */
   2.770 +        if (device) {
   2.771 +            current_audio.impl.LockAudio(device);
   2.772 +        }
   2.773      }
   2.774  }
   2.775  
   2.776  void
   2.777  SDL_LockAudio(void)
   2.778  {
   2.779 -    SDL_AudioDevice *audio = current_audio;
   2.780 +    SDL_LockAudioDevice(1);
   2.781 +}
   2.782  
   2.783 -    /* Obtain a lock on the mixing buffers */
   2.784 -    if (audio && audio->LockAudio) {
   2.785 -        audio->LockAudio(audio);
   2.786 +void
   2.787 +SDL_UnlockAudioDevice(SDL_AudioDeviceID devid)
   2.788 +{
   2.789 +    if (current_audio.impl.UnlockAudio != NULL) {
   2.790 +        SDL_AudioDevice *device = get_audio_device(devid);
   2.791 +        /* Obtain a lock on the mixing buffers */
   2.792 +        if (device) {
   2.793 +            current_audio.impl.UnlockAudio(device);
   2.794 +        }
   2.795      }
   2.796  }
   2.797  
   2.798  void
   2.799  SDL_UnlockAudio(void)
   2.800  {
   2.801 -    SDL_AudioDevice *audio = current_audio;
   2.802 +    SDL_UnlockAudioDevice(1);
   2.803 +}
   2.804  
   2.805 -    /* Release lock on the mixing buffers */
   2.806 -    if (audio && audio->UnlockAudio) {
   2.807 -        audio->UnlockAudio(audio);
   2.808 +void
   2.809 +SDL_CloseAudioDevice(SDL_AudioDeviceID devid)
   2.810 +{
   2.811 +    SDL_AudioDevice *device = get_audio_device(devid);
   2.812 +    if (device) {
   2.813 +        close_audio_device(device);
   2.814 +        open_devices[devid-1] = NULL;
   2.815      }
   2.816  }
   2.817  
   2.818  void
   2.819  SDL_CloseAudio(void)
   2.820  {
   2.821 -    SDL_QuitSubSystem(SDL_INIT_AUDIO);
   2.822 +    SDL_CloseAudioDevice(1);
   2.823  }
   2.824  
   2.825  void
   2.826  SDL_AudioQuit(void)
   2.827  {
   2.828 -    SDL_AudioDevice *audio = current_audio;
   2.829 +    SDL_AudioDeviceID i;
   2.830 +    for (i = 0; i < SDL_arraysize(open_devices); i++) {
   2.831 +        SDL_CloseAudioDevice(i);
   2.832 +    }
   2.833 +    /* Free the driver data */
   2.834  
   2.835 -    if (audio) {
   2.836 -        audio->enabled = 0;
   2.837 -        if (audio->thread != NULL) {
   2.838 -            SDL_WaitThread(audio->thread, NULL);
   2.839 -        }
   2.840 -        if (audio->mixer_lock != NULL) {
   2.841 -            SDL_DestroyMutex(audio->mixer_lock);
   2.842 -        }
   2.843 -        if (audio->fake_stream != NULL) {
   2.844 -            SDL_FreeAudioMem(audio->fake_stream);
   2.845 -        }
   2.846 -        if (audio->convert.needed) {
   2.847 -            SDL_FreeAudioMem(audio->convert.buf);
   2.848 -
   2.849 -        }
   2.850 -#if !SDL_AUDIO_DRIVER_AHI
   2.851 -        if (audio->opened) {
   2.852 -            audio->CloseAudio(audio);
   2.853 -            audio->opened = 0;
   2.854 -        }
   2.855 -#endif
   2.856 -        /* Free the driver data */
   2.857 -        audio->free(audio);
   2.858 -        current_audio = NULL;
   2.859 -    }
   2.860 +/* !!! FIXME!    current_audio.free(&current_audio); */
   2.861 +    SDL_memset(&current_audio, '\0', sizeof (current_audio));
   2.862 +    SDL_memset(open_devices, '\0', sizeof (open_devices));
   2.863  }
   2.864  
   2.865  #define NUM_FORMATS 10
   2.866 @@ -777,9 +911,30 @@
   2.867          spec->silence = 0x00;
   2.868          break;
   2.869      }
   2.870 -    spec->size = (spec->format & 0xFF) / 8;
   2.871 +    spec->size = SDL_AUDIO_BITSIZE(spec->format) / 8;
   2.872      spec->size *= spec->channels;
   2.873      spec->size *= spec->samples;
   2.874  }
   2.875  
   2.876 +
   2.877 +/*
   2.878 + * Moved here from SDL_mixer.c, since it relies on internals of an opened
   2.879 + *  audio device (and is deprecated, by the way!).
   2.880 + */
   2.881 +void
   2.882 +SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
   2.883 +{
   2.884 +    /* Mix the user-level audio format */
   2.885 +    SDL_AudioDevice *device = get_audio_device(1);
   2.886 +    if (device != NULL) {
   2.887 +        SDL_AudioFormat format;
   2.888 +        if (device->convert.needed) {
   2.889 +            format = device->convert.src_format;
   2.890 +        } else {
   2.891 +            format = device->spec.format;
   2.892 +        }
   2.893 +        SDL_MixAudioFormat(dst, src, format, len, volume);
   2.894 +    }
   2.895 +}
   2.896 +
   2.897  /* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/src/audio/SDL_mixer.c	Sun Oct 01 05:21:40 2006 +0000
     3.2 +++ b/src/audio/SDL_mixer.c	Sun Oct 01 05:24:03 2006 +0000
     3.3 @@ -89,21 +89,6 @@
     3.4  #define ADJUST_VOLUME(s, v)	(s = (s*v)/SDL_MIX_MAXVOLUME)
     3.5  #define ADJUST_VOLUME_U8(s, v)	(s = (((s-128)*v)/SDL_MIX_MAXVOLUME)+128)
     3.6  
     3.7 -void
     3.8 -SDL_MixAudio(Uint8 * dst, const Uint8 * src, Uint32 len, int volume)
     3.9 -{
    3.10 -    /* Mix the user-level audio format */
    3.11 -    if (current_audio) {
    3.12 -        SDL_AudioFormat format;
    3.13 -        if (current_audio->convert.needed) {
    3.14 -            format = current_audio->convert.src_format;
    3.15 -        } else {
    3.16 -            format = current_audio->spec.format;
    3.17 -        }
    3.18 -        SDL_MixAudioFormat(dst, src, format, len, volume);
    3.19 -    }
    3.20 -}
    3.21 -
    3.22  
    3.23  void
    3.24  SDL_MixAudioFormat(Uint8 * dst, const Uint8 * src, SDL_AudioFormat format,
     4.1 --- a/src/audio/SDL_sysaudio.h	Sun Oct 01 05:21:40 2006 +0000
     4.2 +++ b/src/audio/SDL_sysaudio.h	Sun Oct 01 05:24:03 2006 +0000
     4.3 @@ -29,13 +29,23 @@
     4.4  
     4.5  /* The SDL audio driver */
     4.6  typedef struct SDL_AudioDevice SDL_AudioDevice;
     4.7 +#define _THIS	SDL_AudioDevice *_this
     4.8  
     4.9 -/* Define the SDL audio driver structure */
    4.10 -#define _THIS	SDL_AudioDevice *_this
    4.11 -#ifndef _STATUS
    4.12 -#define _STATUS	SDL_status *status
    4.13 -#endif
    4.14 -struct SDL_AudioDevice
    4.15 +/* !!! FIXME: rename these from "Audio" to "Device" ... */
    4.16 +typedef struct SDL_AudioDriverImpl
    4.17 +{
    4.18 +    int (*OpenAudio) (_THIS, const char *devname, int iscapture);
    4.19 +    void (*ThreadInit) (_THIS); /* Called by audio thread at start */
    4.20 +    void (*WaitAudio) (_THIS);
    4.21 +    void (*PlayAudio) (_THIS);
    4.22 +    Uint8 *(*GetAudioBuf) (_THIS);
    4.23 +    void (*WaitDone) (_THIS);
    4.24 +    void (*CloseAudio) (_THIS);
    4.25 +    void (*LockAudio) (_THIS);
    4.26 +    void (*UnlockAudio) (_THIS);
    4.27 +} SDL_AudioDriverImpl;
    4.28 +
    4.29 +typedef struct SDL_AudioDriver
    4.30  {
    4.31      /* * * */
    4.32      /* The name of this audio driver */
    4.33 @@ -45,20 +55,16 @@
    4.34      /* The description of this audio driver */
    4.35      const char *desc;
    4.36  
    4.37 +    SDL_AudioDriverImpl impl;
    4.38 +} SDL_AudioDriver;
    4.39 +
    4.40 +
    4.41 +/* Define the SDL audio driver structure */
    4.42 +struct SDL_AudioDevice
    4.43 +{
    4.44      /* * * */
    4.45 -    /* Public driver functions */
    4.46 -    int (*OpenAudio) (_THIS, SDL_AudioSpec * spec);
    4.47 -    void (*ThreadInit) (_THIS); /* Called by audio thread at start */
    4.48 -    void (*WaitAudio) (_THIS);
    4.49 -    void (*PlayAudio) (_THIS);
    4.50 -    Uint8 *(*GetAudioBuf) (_THIS);
    4.51 -    void (*WaitDone) (_THIS);
    4.52 -    void (*CloseAudio) (_THIS);
    4.53 -
    4.54 -    /* * * */
    4.55 -    /* Lock / Unlock functions added for the Mac port */
    4.56 -    void (*LockAudio) (_THIS);
    4.57 -    void (*UnlockAudio) (_THIS);
    4.58 +    /* Lowlevel audio implementation */
    4.59 +    const SDL_AudioDriver *driver;
    4.60  
    4.61      /* * * */
    4.62      /* Data common to all devices */
    4.63 @@ -99,7 +105,7 @@
    4.64      const char *name;
    4.65      const char *desc;
    4.66      int (*available) (void);
    4.67 -    SDL_AudioDevice *(*create) (int devindex);
    4.68 +    int (*init) (SDL_AudioDriverImpl *impl);
    4.69  } AudioBootStrap;
    4.70  
    4.71  #if SDL_AUDIO_DRIVER_BSD
    4.72 @@ -174,8 +180,5 @@
    4.73  extern AudioBootStrap DART_bootstrap;
    4.74  #endif
    4.75  
    4.76 -/* This is the current audio device */
    4.77 -extern SDL_AudioDevice *current_audio;
    4.78 -
    4.79  #endif /* _SDL_sysaudio_h */
    4.80  /* vi: set ts=4 sw=4 expandtab: */
     5.1 --- a/src/audio/disk/SDL_diskaudio.c	Sun Oct 01 05:21:40 2006 +0000
     5.2 +++ b/src/audio/disk/SDL_diskaudio.c	Sun Oct 01 05:24:03 2006 +0000
     5.3 @@ -47,7 +47,7 @@
     5.4  #define DISKDEFAULT_WRITEDELAY   150
     5.5  
     5.6  /* Audio driver functions */
     5.7 -static int DISKAUD_OpenAudio(_THIS, SDL_AudioSpec * spec);
     5.8 +static int DISKAUD_OpenAudio(_THIS, const char *devname, int iscapture);
     5.9  static void DISKAUD_WaitAudio(_THIS);
    5.10  static void DISKAUD_PlayAudio(_THIS);
    5.11  static Uint8 *DISKAUD_GetAudioBuf(_THIS);
    5.12 @@ -64,61 +64,34 @@
    5.13  static int
    5.14  DISKAUD_Available(void)
    5.15  {
    5.16 +    /* !!! FIXME: check this at a higher level... */
    5.17 +    /* only ever use this driver if explicitly requested. */
    5.18      const char *envr = SDL_getenv("SDL_AUDIODRIVER");
    5.19 -    if (envr && (SDL_strcmp(envr, DISKAUD_DRIVER_NAME) == 0)) {
    5.20 +    if (envr && (SDL_strcasecmp(envr, DISKAUD_DRIVER_NAME) == 0)) {
    5.21          return (1);
    5.22      }
    5.23      return (0);
    5.24  }
    5.25  
    5.26 -static void
    5.27 -DISKAUD_DeleteDevice(SDL_AudioDevice * device)
    5.28 +static int
    5.29 +DISKAUD_Init(SDL_AudioDriverImpl *impl)
    5.30  {
    5.31 -    SDL_free(device->hidden);
    5.32 -    SDL_free(device);
    5.33 -}
    5.34 -
    5.35 -static SDL_AudioDevice *
    5.36 -DISKAUD_CreateDevice(int devindex)
    5.37 -{
    5.38 -    SDL_AudioDevice *this;
    5.39 -    const char *envr;
    5.40 -
    5.41      /* Initialize all variables that we clean on shutdown */
    5.42 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
    5.43 -    if (this) {
    5.44 -        SDL_memset(this, 0, (sizeof *this));
    5.45 -        this->hidden = (struct SDL_PrivateAudioData *)
    5.46 -            SDL_malloc((sizeof *this->hidden));
    5.47 -    }
    5.48 -    if ((this == NULL) || (this->hidden == NULL)) {
    5.49 -        SDL_OutOfMemory();
    5.50 -        if (this) {
    5.51 -            SDL_free(this);
    5.52 -        }
    5.53 -        return (0);
    5.54 -    }
    5.55 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
    5.56 -
    5.57 -    envr = SDL_getenv(DISKENVR_WRITEDELAY);
    5.58 -    this->hidden->write_delay =
    5.59 -        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
    5.60 +    SDL_memset(impl, '\0', sizeof (SDL_AudioDriverImpl));
    5.61  
    5.62      /* Set the function pointers */
    5.63 -    this->OpenAudio = DISKAUD_OpenAudio;
    5.64 -    this->WaitAudio = DISKAUD_WaitAudio;
    5.65 -    this->PlayAudio = DISKAUD_PlayAudio;
    5.66 -    this->GetAudioBuf = DISKAUD_GetAudioBuf;
    5.67 -    this->CloseAudio = DISKAUD_CloseAudio;
    5.68 +    impl->OpenAudio = DISKAUD_OpenAudio;
    5.69 +    impl->WaitAudio = DISKAUD_WaitAudio;
    5.70 +    impl->PlayAudio = DISKAUD_PlayAudio;
    5.71 +    impl->GetAudioBuf = DISKAUD_GetAudioBuf;
    5.72 +    impl->CloseAudio = DISKAUD_CloseAudio;
    5.73  
    5.74 -    this->free = DISKAUD_DeleteDevice;
    5.75 -
    5.76 -    return this;
    5.77 +    return 1;
    5.78  }
    5.79  
    5.80  AudioBootStrap DISKAUD_bootstrap = {
    5.81      DISKAUD_DRIVER_NAME, "direct-to-disk audio",
    5.82 -    DISKAUD_Available, DISKAUD_CreateDevice
    5.83 +    DISKAUD_Available, DISKAUD_Init
    5.84  };
    5.85  
    5.86  /* This function waits until it is possible to write a full sound buffer */
    5.87 @@ -163,33 +136,57 @@
    5.88          SDL_RWclose(this->hidden->output);
    5.89          this->hidden->output = NULL;
    5.90      }
    5.91 +    SDL_free(this->hidden);
    5.92 +    this->hidden = NULL;
    5.93  }
    5.94  
    5.95  static int
    5.96 -DISKAUD_OpenAudio(_THIS, SDL_AudioSpec * spec)
    5.97 +DISKAUD_OpenAudio(_THIS, const char *devname, int iscapture)
    5.98  {
    5.99 +    const char *envr = SDL_getenv(DISKENVR_WRITEDELAY);
   5.100      const char *fname = DISKAUD_GetOutputFilename();
   5.101  
   5.102 +    /* !!! FIXME: use device name for non-default filename? */
   5.103 +    if (devname != NULL) {
   5.104 +        SDL_SetError("Disk audio device name must be NULL");
   5.105 +        return 0;
   5.106 +    }
   5.107 +
   5.108 +    this->hidden = (struct SDL_PrivateAudioData *)
   5.109 +            SDL_malloc(sizeof (*this->hidden));
   5.110 +    if (this->hidden == NULL) {
   5.111 +        SDL_OutOfMemory();
   5.112 +        return 0;
   5.113 +    }
   5.114 +    SDL_memset(this->hidden, 0, sizeof (*this->hidden));
   5.115 +
   5.116      /* Open the audio device */
   5.117      this->hidden->output = SDL_RWFromFile(fname, "wb");
   5.118      if (this->hidden->output == NULL) {
   5.119 -        return (-1);
   5.120 +        DISKAUD_CloseAudio(this);
   5.121 +        return 0;
   5.122      }
   5.123 +
   5.124 +    /* Allocate mixing buffer */
   5.125 +    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
   5.126 +    if (this->hidden->mixbuf == NULL) {
   5.127 +        DISKAUD_CloseAudio(this);
   5.128 +        return 0;
   5.129 +    }
   5.130 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
   5.131 +
   5.132 +    this->hidden->mixlen = this->spec.size;
   5.133 +    this->hidden->write_delay =
   5.134 +        (envr) ? SDL_atoi(envr) : DISKDEFAULT_WRITEDELAY;
   5.135 +
   5.136  #if HAVE_STDIO_H
   5.137 -    fprintf(stderr, "WARNING: You are using the SDL disk writer"
   5.138 -            " audio driver!\n Writing to file [%s].\n", fname);
   5.139 +    fprintf(stderr,
   5.140 +            "WARNING: You are using the SDL disk writer audio driver!\n"
   5.141 +            " Writing to file [%s].\n", fname);
   5.142  #endif
   5.143  
   5.144 -    /* Allocate mixing buffer */
   5.145 -    this->hidden->mixlen = spec->size;
   5.146 -    this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
   5.147 -    if (this->hidden->mixbuf == NULL) {
   5.148 -        return (-1);
   5.149 -    }
   5.150 -    SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
   5.151 -
   5.152      /* We're ready to rock and roll. :-) */
   5.153 -    return (0);
   5.154 +    return 1;
   5.155  }
   5.156  
   5.157  /* vi: set ts=4 sw=4 expandtab: */
     6.1 --- a/src/audio/dummy/SDL_dummyaudio.c	Sun Oct 01 05:21:40 2006 +0000
     6.2 +++ b/src/audio/dummy/SDL_dummyaudio.c	Sun Oct 01 05:24:03 2006 +0000
     6.3 @@ -37,7 +37,7 @@
     6.4  #define DUMMYAUD_DRIVER_NAME         "dummy"
     6.5  
     6.6  /* Audio driver functions */
     6.7 -static int DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec * spec);
     6.8 +static int DUMMYAUD_OpenAudio(_THIS, const char *devname, int iscapture);
     6.9  static void DUMMYAUD_WaitAudio(_THIS);
    6.10  static void DUMMYAUD_PlayAudio(_THIS);
    6.11  static Uint8 *DUMMYAUD_GetAudioBuf(_THIS);
    6.12 @@ -47,6 +47,8 @@
    6.13  static int
    6.14  DUMMYAUD_Available(void)
    6.15  {
    6.16 +    /* !!! FIXME: check this at a higher level... */
    6.17 +    /* only ever use this driver if explicitly requested. */
    6.18      const char *envr = SDL_getenv("SDL_AUDIODRIVER");
    6.19      if (envr && (SDL_strcmp(envr, DUMMYAUD_DRIVER_NAME) == 0)) {
    6.20          return (1);
    6.21 @@ -54,49 +56,22 @@
    6.22      return (0);
    6.23  }
    6.24  
    6.25 -static void
    6.26 -DUMMYAUD_DeleteDevice(SDL_AudioDevice * device)
    6.27 +static int
    6.28 +DUMMYAUD_Init(SDL_AudioDriverImpl *impl)
    6.29  {
    6.30 -    SDL_free(device->hidden);
    6.31 -    SDL_free(device);
    6.32 -}
    6.33 +    /* Set the function pointers */
    6.34 +    impl->OpenAudio = DUMMYAUD_OpenAudio;
    6.35 +    impl->WaitAudio = DUMMYAUD_WaitAudio;
    6.36 +    impl->PlayAudio = DUMMYAUD_PlayAudio;
    6.37 +    impl->GetAudioBuf = DUMMYAUD_GetAudioBuf;
    6.38 +    impl->CloseAudio = DUMMYAUD_CloseAudio;
    6.39  
    6.40 -static SDL_AudioDevice *
    6.41 -DUMMYAUD_CreateDevice(int devindex)
    6.42 -{
    6.43 -    SDL_AudioDevice *this;
    6.44 -
    6.45 -    /* Initialize all variables that we clean on shutdown */
    6.46 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
    6.47 -    if (this) {
    6.48 -        SDL_memset(this, 0, (sizeof *this));
    6.49 -        this->hidden = (struct SDL_PrivateAudioData *)
    6.50 -            SDL_malloc((sizeof *this->hidden));
    6.51 -    }
    6.52 -    if ((this == NULL) || (this->hidden == NULL)) {
    6.53 -        SDL_OutOfMemory();
    6.54 -        if (this) {
    6.55 -            SDL_free(this);
    6.56 -        }
    6.57 -        return (0);
    6.58 -    }
    6.59 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
    6.60 -
    6.61 -    /* Set the function pointers */
    6.62 -    this->OpenAudio = DUMMYAUD_OpenAudio;
    6.63 -    this->WaitAudio = DUMMYAUD_WaitAudio;
    6.64 -    this->PlayAudio = DUMMYAUD_PlayAudio;
    6.65 -    this->GetAudioBuf = DUMMYAUD_GetAudioBuf;
    6.66 -    this->CloseAudio = DUMMYAUD_CloseAudio;
    6.67 -
    6.68 -    this->free = DUMMYAUD_DeleteDevice;
    6.69 -
    6.70 -    return this;
    6.71 +    return 1;
    6.72  }
    6.73  
    6.74  AudioBootStrap DUMMYAUD_bootstrap = {
    6.75      DUMMYAUD_DRIVER_NAME, "SDL dummy audio driver",
    6.76 -    DUMMYAUD_Available, DUMMYAUD_CreateDevice
    6.77 +    DUMMYAUD_Available, DUMMYAUD_Init
    6.78  };
    6.79  
    6.80  /* This function waits until it is possible to write a full sound buffer */
    6.81 @@ -129,23 +104,35 @@
    6.82          SDL_FreeAudioMem(this->hidden->mixbuf);
    6.83          this->hidden->mixbuf = NULL;
    6.84      }
    6.85 +    SDL_free(this->hidden);
    6.86 +    this->hidden = NULL;
    6.87  }
    6.88  
    6.89  static int
    6.90 -DUMMYAUD_OpenAudio(_THIS, SDL_AudioSpec * spec)
    6.91 +DUMMYAUD_OpenAudio(_THIS, const char *devname, int iscapture)
    6.92  {
    6.93      float bytes_per_sec = 0.0f;
    6.94  
    6.95 +    /* Initialize all variables that we clean on shutdown */
    6.96 +    this->hidden = (struct SDL_PrivateAudioData *)
    6.97 +                    SDL_malloc((sizeof *this->hidden));
    6.98 +    if (this->hidden == NULL) {
    6.99 +        SDL_OutOfMemory();
   6.100 +        return 0;
   6.101 +    }
   6.102 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   6.103 +
   6.104      /* Allocate mixing buffer */
   6.105 -    this->hidden->mixlen = spec->size;
   6.106 +    this->hidden->mixlen = this->spec.size;
   6.107      this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen);
   6.108      if (this->hidden->mixbuf == NULL) {
   6.109 -        return (-1);
   6.110 +        DUMMYAUD_CloseAudio(this);
   6.111 +        return 0;
   6.112      }
   6.113 -    SDL_memset(this->hidden->mixbuf, spec->silence, spec->size);
   6.114 +    SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size);
   6.115  
   6.116 -    bytes_per_sec = (float) (((spec->format & 0xFF) / 8) *
   6.117 -                             spec->channels * spec->freq);
   6.118 +    bytes_per_sec = (float) (SDL_AUDIO_BITSIZE(this->spec.format) / 8) *
   6.119 +                             this->spec.channels * this->spec.freq;
   6.120  
   6.121      /*
   6.122       * We try to make this request more audio at the correct rate for
   6.123 @@ -156,10 +143,10 @@
   6.124       */
   6.125      this->hidden->initial_calls = 2;
   6.126      this->hidden->write_delay =
   6.127 -        (Uint32) ((((float) spec->size) / bytes_per_sec) * 1000.0f);
   6.128 +        (Uint32) ((((float) this->spec.size) / bytes_per_sec) * 1000.0f);
   6.129  
   6.130      /* We're ready to rock and roll. :-) */
   6.131 -    return (0);
   6.132 +    return 1;
   6.133  }
   6.134  
   6.135  /* vi: set ts=4 sw=4 expandtab: */
     7.1 --- a/src/audio/macosx/SDL_coreaudio.c	Sun Oct 01 05:21:40 2006 +0000
     7.2 +++ b/src/audio/macosx/SDL_coreaudio.c	Sun Oct 01 05:24:03 2006 +0000
     7.3 @@ -31,63 +31,36 @@
     7.4  
     7.5  /* Audio driver functions */
     7.6  
     7.7 -static int Core_OpenAudio(_THIS, SDL_AudioSpec * spec);
     7.8 -static void Core_WaitAudio(_THIS);
     7.9 -static void Core_PlayAudio(_THIS);
    7.10 -static Uint8 *Core_GetAudioBuf(_THIS);
    7.11 -static void Core_CloseAudio(_THIS);
    7.12 +static int COREAUDIO_OpenAudio(_THIS, const char *devname, int iscapture);
    7.13 +static void COREAUDIO_WaitAudio(_THIS);
    7.14 +static void COREAUDIO_PlayAudio(_THIS);
    7.15 +static Uint8 *COREAUDIO_GetAudioBuf(_THIS);
    7.16 +static void COREAUDIO_CloseAudio(_THIS);
    7.17  
    7.18  /* Audio driver bootstrap functions */
    7.19  
    7.20  static int
    7.21 -Audio_Available(void)
    7.22 +COREAUDIO_Available(void)
    7.23  {
    7.24      return (1);
    7.25  }
    7.26  
    7.27 -static void
    7.28 -Audio_DeleteDevice(SDL_AudioDevice * device)
    7.29 +static int
    7.30 +COREAUDIO_Init(SDL_AudioDriverImpl *impl)
    7.31  {
    7.32 -    SDL_free(device->hidden);
    7.33 -    SDL_free(device);
    7.34 -}
    7.35 +    /* Set the function pointers */
    7.36 +    impl->OpenAudio = COREAUDIO_OpenAudio;
    7.37 +    impl->WaitAudio = COREAUDIO_WaitAudio;
    7.38 +    impl->PlayAudio = COREAUDIO_PlayAudio;
    7.39 +    impl->GetAudioBuf = COREAUDIO_GetAudioBuf;
    7.40 +    impl->CloseAudio = COREAUDIO_CloseAudio;
    7.41  
    7.42 -static SDL_AudioDevice *
    7.43 -Audio_CreateDevice(int devindex)
    7.44 -{
    7.45 -    SDL_AudioDevice *this;
    7.46 -
    7.47 -    /* Initialize all variables that we clean on shutdown */
    7.48 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
    7.49 -    if (this) {
    7.50 -        SDL_memset(this, 0, (sizeof *this));
    7.51 -        this->hidden = (struct SDL_PrivateAudioData *)
    7.52 -            SDL_malloc((sizeof *this->hidden));
    7.53 -    }
    7.54 -    if ((this == NULL) || (this->hidden == NULL)) {
    7.55 -        SDL_OutOfMemory();
    7.56 -        if (this) {
    7.57 -            SDL_free(this);
    7.58 -        }
    7.59 -        return (0);
    7.60 -    }
    7.61 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
    7.62 -
    7.63 -    /* Set the function pointers */
    7.64 -    this->OpenAudio = Core_OpenAudio;
    7.65 -    this->WaitAudio = Core_WaitAudio;
    7.66 -    this->PlayAudio = Core_PlayAudio;
    7.67 -    this->GetAudioBuf = Core_GetAudioBuf;
    7.68 -    this->CloseAudio = Core_CloseAudio;
    7.69 -
    7.70 -    this->free = Audio_DeleteDevice;
    7.71 -
    7.72 -    return this;
    7.73 +    return 1;
    7.74  }
    7.75  
    7.76  AudioBootStrap COREAUDIO_bootstrap = {
    7.77      "coreaudio", "Mac OS X CoreAudio",
    7.78 -    Audio_Available, Audio_CreateDevice
    7.79 +    COREAUDIO_Available, COREAUDIO_Init
    7.80  };
    7.81  
    7.82  /* The CoreAudio callback */
    7.83 @@ -118,22 +91,26 @@
    7.84      remaining = ioData->mDataByteSize;
    7.85      ptr = ioData->mData;
    7.86      while (remaining > 0) {
    7.87 -        if (bufferOffset >= bufferSize) {
    7.88 +        if (this->hidden->bufferOffset >= this->hidden->bufferSize) {
    7.89              /* Generate the data */
    7.90 -            SDL_memset(buffer, this->spec.silence, bufferSize);
    7.91 +            SDL_memset(this->hidden->buffer, this->spec.silence,
    7.92 +                       this->hidden->bufferSize);
    7.93              SDL_mutexP(this->mixer_lock);
    7.94 -            (*this->spec.callback) (this->spec.userdata, buffer, bufferSize);
    7.95 +            (*this->spec.callback) (this->spec.userdata, this->hidden->buffer,
    7.96 +                                    this->hidden->bufferSize);
    7.97              SDL_mutexV(this->mixer_lock);
    7.98 -            bufferOffset = 0;
    7.99 +            this->hidden->bufferOffset = 0;
   7.100          }
   7.101  
   7.102 -        len = bufferSize - bufferOffset;
   7.103 +        len = this->hidden->bufferSize - this->hidden->bufferOffset;
   7.104          if (len > remaining)
   7.105              len = remaining;
   7.106 -        SDL_memcpy(ptr, (char *) buffer + bufferOffset, len);
   7.107 +        SDL_memcpy(ptr,
   7.108 +                    (char *) this->hidden->buffer + this->hidden->bufferOffset,
   7.109 +                    len);
   7.110          ptr = (char *) ptr + len;
   7.111          remaining -= len;
   7.112 -        bufferOffset += len;
   7.113 +        this->hidden->bufferOffset += len;
   7.114      }
   7.115  
   7.116      return 0;
   7.117 @@ -141,86 +118,104 @@
   7.118  
   7.119  /* Dummy functions -- we don't use thread-based audio */
   7.120  void
   7.121 -Core_WaitAudio(_THIS)
   7.122 +COREAUDIO_WaitAudio(_THIS)
   7.123  {
   7.124      return;
   7.125  }
   7.126  
   7.127  void
   7.128 -Core_PlayAudio(_THIS)
   7.129 +COREAUDIO_PlayAudio(_THIS)
   7.130  {
   7.131      return;
   7.132  }
   7.133  
   7.134  Uint8 *
   7.135 -Core_GetAudioBuf(_THIS)
   7.136 +COREAUDIO_GetAudioBuf(_THIS)
   7.137  {
   7.138      return (NULL);
   7.139  }
   7.140  
   7.141  void
   7.142 -Core_CloseAudio(_THIS)
   7.143 +COREAUDIO_CloseAudio(_THIS)
   7.144  {
   7.145      OSStatus result;
   7.146      struct AudioUnitInputCallback callback;
   7.147  
   7.148 +    if (this->hidden == NULL) {
   7.149 +        return;
   7.150 +    }
   7.151 +
   7.152      /* stop processing the audio unit */
   7.153 -    result = AudioOutputUnitStop(outputAudioUnit);
   7.154 +    result = AudioOutputUnitStop(this->hidden->outputAudioUnit);
   7.155      if (result != noErr) {
   7.156 -        SDL_SetError("Core_CloseAudio: AudioOutputUnitStop");
   7.157 +        SDL_SetError("COREAUDIO_CloseAudio: AudioOutputUnitStop");
   7.158          return;
   7.159      }
   7.160  
   7.161      /* Remove the input callback */
   7.162      callback.inputProc = 0;
   7.163      callback.inputProcRefCon = 0;
   7.164 -    result = AudioUnitSetProperty(outputAudioUnit,
   7.165 +    result = AudioUnitSetProperty(this->hidden->outputAudioUnit,
   7.166                                    kAudioUnitProperty_SetInputCallback,
   7.167                                    kAudioUnitScope_Input,
   7.168                                    0, &callback, sizeof(callback));
   7.169      if (result != noErr) {
   7.170          SDL_SetError
   7.171 -            ("Core_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)");
   7.172 +            ("COREAUDIO_CloseAudio: AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)");
   7.173          return;
   7.174      }
   7.175  
   7.176 -    result = CloseComponent(outputAudioUnit);
   7.177 +    result = CloseComponent(this->hidden->outputAudioUnit);
   7.178      if (result != noErr) {
   7.179 -        SDL_SetError("Core_CloseAudio: CloseComponent");
   7.180 +        SDL_SetError("COREAUDIO_CloseAudio: CloseComponent");
   7.181          return;
   7.182      }
   7.183  
   7.184 -    SDL_free(buffer);
   7.185 +    SDL_free(this->hidden->buffer);
   7.186 +    SDL_free(this->hidden);
   7.187 +    this->hidden = NULL;
   7.188  }
   7.189  
   7.190  #define CHECK_RESULT(msg) \
   7.191      if (result != noErr) { \
   7.192 +        COREAUDIO_CloseAudio(this); \
   7.193          SDL_SetError("CoreAudio error (%s): %d", msg, (int) result); \
   7.194          return -1; \
   7.195      }
   7.196  
   7.197  
   7.198  int
   7.199 -Core_OpenAudio(_THIS, SDL_AudioSpec * spec)
   7.200 +COREAUDIO_OpenAudio(_THIS, const char *devname, int iscapture)
   7.201  {
   7.202      OSStatus result = noErr;
   7.203      Component comp;
   7.204      ComponentDescription desc;
   7.205      struct AudioUnitInputCallback callback;
   7.206      AudioStreamBasicDescription strdesc;
   7.207 -    SDL_AudioFormat test_format = SDL_FirstAudioFormat(spec->format);
   7.208 +    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   7.209      int valid_datatype = 0;
   7.210  
   7.211 +    /* Initialize all variables that we clean on shutdown */
   7.212 +    this->hidden = (struct SDL_PrivateAudioData *)
   7.213 +                        SDL_malloc((sizeof *this->hidden));
   7.214 +    if (this->hidden == NULL) {
   7.215 +        SDL_OutOfMemory();
   7.216 +        return (0);
   7.217 +    }
   7.218 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   7.219 +
   7.220 +    /* !!! FIXME: check devname and iscapture... */
   7.221 +
   7.222      /* Setup a AudioStreamBasicDescription with the requested format */
   7.223      memset(&strdesc, '\0', sizeof(AudioStreamBasicDescription));
   7.224      strdesc.mFormatID = kAudioFormatLinearPCM;
   7.225      strdesc.mFormatFlags = kLinearPCMFormatFlagIsPacked;
   7.226 -    strdesc.mChannelsPerFrame = spec->channels;
   7.227 -    strdesc.mSampleRate = spec->freq;
   7.228 +    strdesc.mChannelsPerFrame = this->spec.channels;
   7.229 +    strdesc.mSampleRate = this->spec.freq;
   7.230      strdesc.mFramesPerPacket = 1;
   7.231  
   7.232      while ((!valid_datatype) && (test_format)) {
   7.233 -        spec->format = test_format;
   7.234 +        this->spec.format = test_format;
   7.235          /* Just a list of valid SDL formats, so people don't pass junk here. */
   7.236          switch (test_format) {
   7.237          case AUDIO_U8:
   7.238 @@ -234,13 +229,13 @@
   7.239          case AUDIO_F32LSB:
   7.240          case AUDIO_F32MSB:
   7.241              valid_datatype = 1;
   7.242 -            strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(spec->format);
   7.243 -            if (SDL_AUDIO_ISBIGENDIAN(spec->format))
   7.244 +            strdesc.mBitsPerChannel = SDL_AUDIO_BITSIZE(this->spec.format);
   7.245 +            if (SDL_AUDIO_ISBIGENDIAN(this->spec.format))
   7.246                  strdesc.mFormatFlags |= kLinearPCMFormatFlagIsBigEndian;
   7.247  
   7.248 -            if (SDL_AUDIO_ISFLOAT(spec->format))
   7.249 +            if (SDL_AUDIO_ISFLOAT(this->spec.format))
   7.250                  strdesc.mFormatFlags |= kLinearPCMFormatFlagIsFloat;
   7.251 -            else if (SDL_AUDIO_ISSIGNED(spec->format))
   7.252 +            else if (SDL_AUDIO_ISSIGNED(this->spec.format))
   7.253                  strdesc.mFormatFlags |= kLinearPCMFormatFlagIsSignedInteger;
   7.254              break;
   7.255          }
   7.256 @@ -248,7 +243,7 @@
   7.257  
   7.258      if (!valid_datatype) {      /* shouldn't happen, but just in case... */
   7.259          SDL_SetError("Unsupported audio format");
   7.260 -        return (-1);
   7.261 +        return 0;
   7.262      }
   7.263  
   7.264      strdesc.mBytesPerFrame =
   7.265 @@ -266,18 +261,19 @@
   7.266  
   7.267      comp = FindNextComponent(NULL, &desc);
   7.268      if (comp == NULL) {
   7.269 +        COREAUDIO_CloseAudio(this);
   7.270          SDL_SetError
   7.271              ("Failed to start CoreAudio: FindNextComponent returned NULL");
   7.272 -        return -1;
   7.273 +        return 0;
   7.274      }
   7.275  
   7.276      /* Open & initialize the default output audio unit */
   7.277 -    result = OpenAComponent(comp, &outputAudioUnit);
   7.278 +    result = OpenAComponent(comp, &this->hidden->outputAudioUnit);
   7.279      CHECK_RESULT("OpenAComponent")
   7.280 -        result = AudioUnitInitialize(outputAudioUnit);
   7.281 +        result = AudioUnitInitialize(this->hidden->outputAudioUnit);
   7.282      CHECK_RESULT("AudioUnitInitialize")
   7.283          /* Set the input format of the audio unit. */
   7.284 -        result = AudioUnitSetProperty(outputAudioUnit,
   7.285 +        result = AudioUnitSetProperty(this->hidden->outputAudioUnit,
   7.286                                        kAudioUnitProperty_StreamFormat,
   7.287                                        kAudioUnitScope_Input,
   7.288                                        0, &strdesc, sizeof(strdesc));
   7.289 @@ -285,20 +281,20 @@
   7.290          /* Set the audio callback */
   7.291          callback.inputProc = audioCallback;
   7.292      callback.inputProcRefCon = this;
   7.293 -    result = AudioUnitSetProperty(outputAudioUnit,
   7.294 +    result = AudioUnitSetProperty(this->hidden->outputAudioUnit,
   7.295                                    kAudioUnitProperty_SetInputCallback,
   7.296                                    kAudioUnitScope_Input,
   7.297                                    0, &callback, sizeof(callback));
   7.298      CHECK_RESULT("AudioUnitSetProperty (kAudioUnitProperty_SetInputCallback)")
   7.299          /* Calculate the final parameters for this audio specification */
   7.300 -        SDL_CalculateAudioSpec(spec);
   7.301 +        SDL_CalculateAudioSpec(&this->spec);
   7.302  
   7.303      /* Allocate a sample buffer */
   7.304 -    bufferOffset = bufferSize = this->spec.size;
   7.305 -    buffer = SDL_malloc(bufferSize);
   7.306 +    this->hidden->bufferOffset = this->hidden->bufferSize = this->spec.size;
   7.307 +    this->hidden->buffer = SDL_malloc(this->hidden->bufferSize);
   7.308  
   7.309      /* Finally, start processing of the audio unit */
   7.310 -    result = AudioOutputUnitStart(outputAudioUnit);
   7.311 +    result = AudioOutputUnitStart(this->hidden->outputAudioUnit);
   7.312      CHECK_RESULT("AudioOutputUnitStart")
   7.313          /* We're running! */
   7.314          return (1);
     8.1 --- a/src/audio/macosx/SDL_coreaudio.h	Sun Oct 01 05:21:40 2006 +0000
     8.2 +++ b/src/audio/macosx/SDL_coreaudio.h	Sun Oct 01 05:24:03 2006 +0000
     8.3 @@ -37,11 +37,5 @@
     8.4      UInt32 bufferSize;
     8.5  };
     8.6  
     8.7 -/* Old variable names */
     8.8 -#define outputAudioUnit		(this->hidden->outputAudioUnit)
     8.9 -#define buffer		(this->hidden->buffer)
    8.10 -#define bufferOffset		(this->hidden->bufferOffset)
    8.11 -#define bufferSize		(this->hidden->bufferSize)
    8.12 -
    8.13  #endif /* _SDL_coreaudio_h */
    8.14  /* vi: set ts=4 sw=4 expandtab: */
     9.1 --- a/src/audio/macrom/SDL_romaudio.c	Sun Oct 01 05:21:40 2006 +0000
     9.2 +++ b/src/audio/macrom/SDL_romaudio.c	Sun Oct 01 05:24:03 2006 +0000
     9.3 @@ -52,69 +52,46 @@
     9.4  
     9.5  /* Audio driver functions */
     9.6  
     9.7 -static void Mac_CloseAudio(_THIS);
     9.8 -static int Mac_OpenAudio(_THIS, SDL_AudioSpec * spec);
     9.9 -static void Mac_LockAudio(_THIS);
    9.10 -static void Mac_UnlockAudio(_THIS);
    9.11 +static void SNDMGR_CloseAudio(_THIS);
    9.12 +static int SNDMGR_OpenAudio(_THIS, const char *devname, int iscapture);
    9.13 +static void SNDMGR_LockAudio(_THIS);
    9.14 +static void SNDMGR_UnlockAudio(_THIS);
    9.15  
    9.16  /* Audio driver bootstrap functions */
    9.17  
    9.18  
    9.19  static int
    9.20 -Audio_Available(void)
    9.21 +SNDMGR_Available(void)
    9.22  {
    9.23      return (1);
    9.24  }
    9.25  
    9.26 -static void
    9.27 -Audio_DeleteDevice(SDL_AudioDevice * device)
    9.28 +
    9.29 +static int
    9.30 +SNDMGR_Init(SDL_AudioDriverImpl *impl)
    9.31  {
    9.32 -    SDL_free(device->hidden);
    9.33 -    SDL_free(device);
    9.34 -}
    9.35 -
    9.36 -static SDL_AudioDevice *
    9.37 -Audio_CreateDevice(int devindex)
    9.38 -{
    9.39 -    SDL_AudioDevice *this;
    9.40 -
    9.41 -    /* Initialize all variables that we clean on shutdown */
    9.42 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
    9.43 -    if (this) {
    9.44 -        SDL_memset(this, 0, (sizeof *this));
    9.45 -        this->hidden = (struct SDL_PrivateAudioData *)
    9.46 -            SDL_malloc((sizeof *this->hidden));
    9.47 -    }
    9.48 -    if ((this == NULL) || (this->hidden == NULL)) {
    9.49 -        SDL_OutOfMemory();
    9.50 -        if (this) {
    9.51 -            SDL_free(this);
    9.52 -        }
    9.53 -        return (0);
    9.54 -    }
    9.55 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
    9.56 -
    9.57      /* Set the function pointers */
    9.58 -    this->OpenAudio = Mac_OpenAudio;
    9.59 -    this->CloseAudio = Mac_CloseAudio;
    9.60 -    this->LockAudio = Mac_LockAudio;
    9.61 -    this->UnlockAudio = Mac_UnlockAudio;
    9.62 -    this->free = Audio_DeleteDevice;
    9.63 +    impl->OpenAudio = SNDMGR_OpenAudio;
    9.64 +    impl->CloseAudio = SNDMGR_CloseAudio;
    9.65 +    impl->LockAudio = SNDMGR_LockAudio;
    9.66 +    impl->UnlockAudio = SNDMGR_UnlockAudio;
    9.67  
    9.68  #ifdef __MACOSX__               /* Mac OS X uses threaded audio, so normal thread code is okay */
    9.69 -    this->LockAudio = NULL;
    9.70 -    this->UnlockAudio = NULL;
    9.71 +    impl->LockAudio = NULL;
    9.72 +    impl->UnlockAudio = NULL;
    9.73  #endif
    9.74 -    return this;
    9.75 +
    9.76 +    return 1;
    9.77  }
    9.78  
    9.79  AudioBootStrap SNDMGR_bootstrap = {
    9.80      "sndmgr", SDL_MACOS_NAME " SoundManager",
    9.81 -    Audio_Available, Audio_CreateDevice
    9.82 +    SNDMGR_Available, SNDMGR_Init
    9.83  };
    9.84  
    9.85  #pragma options align=power
    9.86  
    9.87 +static volatile int audio_is_opened = 0;
    9.88  static volatile SInt32 audio_is_locked = 0;
    9.89  static volatile SInt32 need_to_mix = 0;
    9.90  
    9.91 @@ -152,13 +129,13 @@
    9.92  }
    9.93  
    9.94  static void
    9.95 -Mac_LockAudio(_THIS)
    9.96 +SNDMGR_LockAudio(_THIS)
    9.97  {
    9.98      IncrementAtomic((SInt32 *) & audio_is_locked);
    9.99  }
   9.100  
   9.101  static void
   9.102 -Mac_UnlockAudio(_THIS)
   9.103 +SNDMGR_UnlockAudio(_THIS)
   9.104  {
   9.105      SInt32 oldval;
   9.106  
   9.107 @@ -221,14 +198,39 @@
   9.108  }
   9.109  
   9.110  static int
   9.111 -Mac_OpenAudio(_THIS, SDL_AudioSpec * spec)
   9.112 +SNDMGR_OpenAudio(_THIS, const char *devname, int iscapture)
   9.113  {
   9.114 -
   9.115 +    SDL_AudioSpec *spec = &this->spec;
   9.116 +    SndChannelPtr channel = NULL;
   9.117      SndCallBackUPP callback;
   9.118      int sample_bits;
   9.119      int i;
   9.120      long initOptions;
   9.121  
   9.122 +    if (audio_is_opened) {
   9.123 +        SDL_SetError("SoundManager driver doesn't support multiple opens");
   9.124 +        return 0;
   9.125 +    }
   9.126 +
   9.127 +    if (iscapture) {
   9.128 +        SDL_SetError("SoundManager driver doesn't support recording");
   9.129 +        return 0;
   9.130 +    }
   9.131 +
   9.132 +    /* !!! FIXME: ignore devname? */
   9.133 +
   9.134 +    /* Initialize all variables that we clean on shutdown */
   9.135 +    this->hidden = (struct SDL_PrivateAudioData *)
   9.136 +                        SDL_malloc((sizeof *this->hidden));
   9.137 +    if (this->hidden == NULL) {
   9.138 +        SDL_OutOfMemory();
   9.139 +        return 0;
   9.140 +    }
   9.141 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   9.142 +
   9.143 +    /* !!! FIXME: check devname and iscapture... */
   9.144 +
   9.145 +    /* !!! FIXME: iterate through format matrix... */
   9.146      /* Very few conversions are required, but... */
   9.147      switch (spec->format) {
   9.148      case AUDIO_S8:
   9.149 @@ -244,7 +246,7 @@
   9.150          spec->format = AUDIO_F32MSB;
   9.151          break;
   9.152      }
   9.153 -    SDL_CalculateAudioSpec(spec);
   9.154 +    SDL_CalculateAudioSpec(&this->spec);
   9.155  
   9.156      /* initialize bufferCmd header */
   9.157      memset(&header, 0, sizeof(header));
   9.158 @@ -282,8 +284,9 @@
   9.159      for (i = 0; i < 2; i++) {
   9.160          buffer[i] = (UInt8 *) malloc(sizeof(UInt8) * spec->size);
   9.161          if (buffer[i] == NULL) {
   9.162 +            SNDMGR_CloseAudio(this);
   9.163              SDL_OutOfMemory();
   9.164 -            return (-1);
   9.165 +            return 0;
   9.166          }
   9.167          memset(buffer[i], 0, spec->size);
   9.168      }
   9.169 @@ -291,9 +294,11 @@
   9.170      /* Create the sound manager channel */
   9.171      channel = (SndChannelPtr) SDL_malloc(sizeof(*channel));
   9.172      if (channel == NULL) {
   9.173 +        SNDMGR_CloseAudio(this);
   9.174          SDL_OutOfMemory();
   9.175 -        return (-1);
   9.176 +        return 0;
   9.177      }
   9.178 +    this->hidden->channel = channel;
   9.179      if (spec->channels >= 2) {
   9.180          initOptions = initStereo;
   9.181      } else {
   9.182 @@ -302,10 +307,9 @@
   9.183      channel->userInfo = (long) this;
   9.184      channel->qLength = 128;
   9.185      if (SndNewChannel(&channel, sampledSynth, initOptions, callback) != noErr) {
   9.186 +        SNDMGR_CloseAudio(this);
   9.187          SDL_SetError("Unable to create audio channel");
   9.188 -        SDL_free(channel);
   9.189 -        channel = NULL;
   9.190 -        return (-1);
   9.191 +        return 0;
   9.192      }
   9.193  
   9.194      /* start playback */
   9.195 @@ -317,20 +321,21 @@
   9.196          SndDoCommand(channel, &cmd, 0);
   9.197      }
   9.198  
   9.199 +    audio_is_opened = 1;
   9.200      return 1;
   9.201  }
   9.202  
   9.203  static void
   9.204 -Mac_CloseAudio(_THIS)
   9.205 +SNDMGR_CloseAudio(_THIS)
   9.206  {
   9.207  
   9.208      int i;
   9.209  
   9.210      running = 0;
   9.211  
   9.212 -    if (channel) {
   9.213 -        SndDisposeChannel(channel, true);
   9.214 -        channel = NULL;
   9.215 +    if (this->hidden->channel) {
   9.216 +        SndDisposeChannel(this->hidden->channel, true);
   9.217 +        this->hidden->channel = NULL;
   9.218      }
   9.219  
   9.220      for (i = 0; i < 2; ++i) {
   9.221 @@ -339,6 +344,9 @@
   9.222              buffer[i] = NULL;
   9.223          }
   9.224      }
   9.225 +    SDL_free(this->hidden);
   9.226 +    this->hidden = NULL;
   9.227 +    audio_is_opened = 0;
   9.228  }
   9.229  
   9.230  /* vi: set ts=4 sw=4 expandtab: */
    10.1 --- a/src/audio/macrom/SDL_romaudio.h	Sun Oct 01 05:21:40 2006 +0000
    10.2 +++ b/src/audio/macrom/SDL_romaudio.h	Sun Oct 01 05:24:03 2006 +0000
    10.3 @@ -35,9 +35,5 @@
    10.4      SndChannelPtr channel;
    10.5  };
    10.6  
    10.7 -/* Old variable names */
    10.8 -#define channel		(this->hidden->channel)
    10.9 -#define audio_buf	(this->hidden->audio_buf)
   10.10 -
   10.11  #endif /* _SDL_romaudio_h */
   10.12  /* vi: set ts=4 sw=4 expandtab: */