Moved windib (waveout) audio to 1.3 API and made other cleanups. SDL-ryan-multiple-audio-device
authorRyan C. Gordon <icculus@icculus.org>
Sun, 08 Oct 2006 23:04:24 +0000
branchSDL-ryan-multiple-audio-device
changeset 38413479f939987c
parent 3840 be9bd1067c6c
child 3842 6b04ca2f1016
Moved windib (waveout) audio to 1.3 API and made other cleanups.
src/audio/windib/SDL_dibaudio.c
src/audio/windib/SDL_dibaudio.h
     1.1 --- a/src/audio/windib/SDL_dibaudio.c	Sun Oct 08 08:58:36 2006 +0000
     1.2 +++ b/src/audio/windib/SDL_dibaudio.c	Sun Oct 08 23:04:24 2006 +0000
     1.3 @@ -35,72 +35,20 @@
     1.4  #include "win_ce_semaphore.h"
     1.5  #endif
     1.6  
     1.7 -
     1.8 -/* Audio driver functions */
     1.9 -static int DIB_OpenAudio(_THIS, SDL_AudioSpec * spec);
    1.10 -static void DIB_ThreadInit(_THIS);
    1.11 -static void DIB_WaitAudio(_THIS);
    1.12 -static Uint8 *DIB_GetAudioBuf(_THIS);
    1.13 -static void DIB_PlayAudio(_THIS);
    1.14 -static void DIB_WaitDone(_THIS);
    1.15 -static void DIB_CloseAudio(_THIS);
    1.16 -
    1.17 -/* Audio driver bootstrap functions */
    1.18 +#if defined(_WIN32_WCE)
    1.19 +#define WINDOWS_OS_NAME "Windows CE/PocketPC"
    1.20 +#elif defined(WIN64)
    1.21 +#define WINDOWS_OS_NAME "Win64"
    1.22 +#else
    1.23 +#define WINDOWS_OS_NAME "Win32"
    1.24 +#endif
    1.25  
    1.26  static int
    1.27 -Audio_Available(void)
    1.28 -{
    1.29 -    return (1);
    1.30 -}
    1.31 -
    1.32 -static void
    1.33 -Audio_DeleteDevice(SDL_AudioDevice * device)
    1.34 -{
    1.35 -    SDL_free(device->hidden);
    1.36 -    SDL_free(device);
    1.37 -}
    1.38 -
    1.39 -static SDL_AudioDevice *
    1.40 -Audio_CreateDevice(int devindex)
    1.41 +WINWAVEOUT_Available(void)
    1.42  {
    1.43 -    SDL_AudioDevice *this;
    1.44 -
    1.45 -    /* Initialize all variables that we clean on shutdown */
    1.46 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
    1.47 -    if (this) {
    1.48 -        SDL_memset(this, 0, (sizeof *this));
    1.49 -        this->hidden = (struct SDL_PrivateAudioData *)
    1.50 -            SDL_malloc((sizeof *this->hidden));
    1.51 -    }
    1.52 -    if ((this == NULL) || (this->hidden == NULL)) {
    1.53 -        SDL_OutOfMemory();
    1.54 -        if (this) {
    1.55 -            SDL_free(this);
    1.56 -        }
    1.57 -        return (0);
    1.58 -    }
    1.59 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
    1.60 -
    1.61 -    /* Set the function pointers */
    1.62 -    this->OpenAudio = DIB_OpenAudio;
    1.63 -    this->ThreadInit = DIB_ThreadInit;
    1.64 -    this->WaitAudio = DIB_WaitAudio;
    1.65 -    this->PlayAudio = DIB_PlayAudio;
    1.66 -    this->GetAudioBuf = DIB_GetAudioBuf;
    1.67 -    this->WaitDone = DIB_WaitDone;
    1.68 -    this->CloseAudio = DIB_CloseAudio;
    1.69 -
    1.70 -    this->free = Audio_DeleteDevice;
    1.71 -
    1.72 -    return this;
    1.73 +    return 1;   /* Always available on win32/pocketpc systems... */
    1.74  }
    1.75  
    1.76 -AudioBootStrap WAVEOUT_bootstrap = {
    1.77 -    "waveout", "Win95/98/NT/2000 WaveOut",
    1.78 -    Audio_Available, Audio_CreateDevice, 0
    1.79 -};
    1.80 -
    1.81 -
    1.82  /* The Win32 callback for filling the WAVE device */
    1.83  static void CALLBACK
    1.84  FillSound(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwInstance,
    1.85 @@ -114,9 +62,9 @@
    1.86  
    1.87      /* Signal that we are done playing a buffer */
    1.88  #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
    1.89 -    ReleaseSemaphoreCE(audio_sem, 1, NULL);
    1.90 +    ReleaseSemaphoreCE(this->hidden->audio_sem, 1, NULL);
    1.91  #else
    1.92 -    ReleaseSemaphore(audio_sem, 1, NULL);
    1.93 +    ReleaseSemaphore(this->hidden->audio_sem, 1, NULL);
    1.94  #endif
    1.95  }
    1.96  
    1.97 @@ -146,48 +94,47 @@
    1.98  
    1.99  /* Set high priority for the audio thread */
   1.100  static void
   1.101 -DIB_ThreadInit(_THIS)
   1.102 +WINWAVEOUT_ThreadInit(_THIS)
   1.103  {
   1.104      SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
   1.105  }
   1.106  
   1.107  void
   1.108 -DIB_WaitAudio(_THIS)
   1.109 +WINWAVEOUT_WaitDevice(_THIS)
   1.110  {
   1.111      /* Wait for an audio chunk to finish */
   1.112  #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
   1.113 -    WaitForSemaphoreCE(audio_sem, INFINITE);
   1.114 +    WaitForSemaphoreCE(this->hidden->audio_sem, INFINITE);
   1.115  #else
   1.116 -    WaitForSingleObject(audio_sem, INFINITE);
   1.117 +    WaitForSingleObject(this->hidden->audio_sem, INFINITE);
   1.118  #endif
   1.119  }
   1.120  
   1.121  Uint8 *
   1.122 -DIB_GetAudioBuf(_THIS)
   1.123 +WINWAVEOUT_GetDeviceBuf(_THIS)
   1.124  {
   1.125 -    Uint8 *retval;
   1.126 -
   1.127 -    retval = (Uint8 *) (wavebuf[next_buffer].lpData);
   1.128 -    return retval;
   1.129 +    return (Uint8 *) (this->hidden->wavebuf[this->hidden->next_buffer].lpData);
   1.130  }
   1.131  
   1.132  void
   1.133 -DIB_PlayAudio(_THIS)
   1.134 +WINWAVEOUT_PlayDevice(_THIS)
   1.135  {
   1.136      /* Queue it up */
   1.137 -    waveOutWrite(sound, &wavebuf[next_buffer], sizeof(wavebuf[0]));
   1.138 -    next_buffer = (next_buffer + 1) % NUM_BUFFERS;
   1.139 +    waveOutWrite(this->hidden->sound,
   1.140 +                 &this->hidden->wavebuf[this->hidden->next_buffer],
   1.141 +                 sizeof (this->hidden->wavebuf[0]));
   1.142 +    this->hidden->next_buffer = (this->hidden->next_buffer + 1) % NUM_BUFFERS;
   1.143  }
   1.144  
   1.145  void
   1.146 -DIB_WaitDone(_THIS)
   1.147 +WINWAVEOUT_WaitDone(_THIS)
   1.148  {
   1.149      int i, left;
   1.150  
   1.151      do {
   1.152          left = NUM_BUFFERS;
   1.153          for (i = 0; i < NUM_BUFFERS; ++i) {
   1.154 -            if (wavebuf[i].dwFlags & WHDR_DONE) {
   1.155 +            if (this->hidden->wavebuf[i].dwFlags & WHDR_DONE) {
   1.156                  --left;
   1.157              }
   1.158          }
   1.159 @@ -199,143 +146,198 @@
   1.160  }
   1.161  
   1.162  void
   1.163 -DIB_CloseAudio(_THIS)
   1.164 +WINWAVEOUT_CloseDevice(_THIS)
   1.165  {
   1.166 -    int i;
   1.167 -
   1.168      /* Close up audio */
   1.169 -    if (audio_sem) {
   1.170 +    if (this->hidden != NULL) {
   1.171 +        int i;
   1.172 +
   1.173 +        if (this->hidden->audio_sem) {
   1.174  #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
   1.175 -        CloseSynchHandle(audio_sem);
   1.176 +            CloseSynchHandle(this->hidden->audio_sem);
   1.177  #else
   1.178 -        CloseHandle(audio_sem);
   1.179 +            CloseHandle(this->hidden->audio_sem);
   1.180  #endif
   1.181 -    }
   1.182 -    if (sound) {
   1.183 -        waveOutClose(sound);
   1.184 -    }
   1.185 +            this->hidden->audio_sem = 0;
   1.186 +        }
   1.187 +
   1.188 +        if (this->hidden->sound) {
   1.189 +            waveOutClose(this->hidden->sound);
   1.190 +            this->hidden->sound = 0;
   1.191 +        }
   1.192  
   1.193 -    /* Clean up mixing buffers */
   1.194 -    for (i = 0; i < NUM_BUFFERS; ++i) {
   1.195 -        if (wavebuf[i].dwUser != 0xFFFF) {
   1.196 -            waveOutUnprepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i]));
   1.197 -            wavebuf[i].dwUser = 0xFFFF;
   1.198 +        /* Clean up mixing buffers */
   1.199 +        for (i = 0; i < NUM_BUFFERS; ++i) {
   1.200 +            if (this->hidden->wavebuf[i].dwUser != 0xFFFF) {
   1.201 +                waveOutUnprepareHeader(this->hidden->sound,
   1.202 +                                       &this->hidden->wavebuf[i],
   1.203 +                                       sizeof (this->hidden->wavebuf[i]));
   1.204 +                this->hidden->wavebuf[i].dwUser = 0xFFFF;
   1.205 +            }
   1.206          }
   1.207 -    }
   1.208 -    /* Free raw mixing buffer */
   1.209 -    if (mixbuf != NULL) {
   1.210 -        SDL_free(mixbuf);
   1.211 -        mixbuf = NULL;
   1.212 +
   1.213 +        if (this->hidden->mixbuf != NULL) {
   1.214 +            /* Free raw mixing buffer */
   1.215 +            SDL_free(this->hidden->mixbuf);
   1.216 +            this->hidden->mixbuf = NULL;
   1.217 +        }
   1.218 +
   1.219 +        SDL_free(this->hidden);
   1.220 +        this->hidden = NULL;
   1.221      }
   1.222  }
   1.223  
   1.224  int
   1.225 -DIB_OpenAudio(_THIS, SDL_AudioSpec * spec)
   1.226 +WINWAVEOUT_OpenDevice(_THIS, const char *devname, int iscapture)
   1.227  {
   1.228 +    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   1.229 +    int valid_datatype = 0;
   1.230      MMRESULT result;
   1.231 +    WAVEFORMATEX waveformat;
   1.232      int i;
   1.233 -    WAVEFORMATEX waveformat;
   1.234 +
   1.235 +    /* Initialize all variables that we clean on shutdown */
   1.236 +    this->hidden = (struct SDL_PrivateAudioData *)
   1.237 +                        SDL_malloc((sizeof *this->hidden));
   1.238 +    if (this->hidden == NULL) {
   1.239 +        SDL_OutOfMemory();
   1.240 +        return 0;
   1.241 +    }
   1.242 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   1.243  
   1.244      /* Initialize the wavebuf structures for closing */
   1.245 -    sound = NULL;
   1.246 -    audio_sem = NULL;
   1.247      for (i = 0; i < NUM_BUFFERS; ++i)
   1.248 -        wavebuf[i].dwUser = 0xFFFF;
   1.249 -    mixbuf = NULL;
   1.250 +        this->hidden->wavebuf[i].dwUser = 0xFFFF;
   1.251 +
   1.252 +    while ((!valid_datatype) && (test_format)) {
   1.253 +        valid_datatype = 1;
   1.254 +        _this->spec.format = test_format;
   1.255 +        switch (test_format) {
   1.256 +            case AUDIO_U8:
   1.257 +            case AUDIO_S16:
   1.258 +            case AUDIO_S32:
   1.259 +                break;  /* valid. */
   1.260 +
   1.261 +            default:
   1.262 +                valid_datatype = 0;
   1.263 +                test_format = SDL_NextAudioFormat();
   1.264 +                break;
   1.265 +        }
   1.266 +    }
   1.267 +
   1.268 +    if (!valid_datatype) {
   1.269 +        WINWAVEOUT_CloseDevice(this);
   1.270 +        SDL_SetError("Unsupported audio format");
   1.271 +        return 0;
   1.272 +    }
   1.273  
   1.274      /* Set basic WAVE format parameters */
   1.275 -    SDL_memset(&waveformat, 0, sizeof(waveformat));
   1.276 +    SDL_memset(&waveformat, '\0', sizeof (waveformat));
   1.277      waveformat.wFormatTag = WAVE_FORMAT_PCM;
   1.278 +    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
   1.279  
   1.280 -    /* Determine the audio parameters from the AudioSpec */
   1.281 -    switch (SDL_AUDIO_BITSIZE(spec->format)) {
   1.282 -    case 8:
   1.283 -        /* Unsigned 8 bit audio data */
   1.284 -        spec->format = AUDIO_U8;
   1.285 -        waveformat.wBitsPerSample = 8;
   1.286 -        break;
   1.287 -    case 16:
   1.288 -        /* Signed 16 bit audio data */
   1.289 -        spec->format = AUDIO_S16;
   1.290 -        waveformat.wBitsPerSample = 16;
   1.291 -        break;
   1.292 -    case 32:
   1.293 -        /* Signed 32 bit audio data */
   1.294 -        spec->format = AUDIO_S32;
   1.295 -        waveformat.wBitsPerSample = 32;
   1.296 -        break;
   1.297 -    default:
   1.298 -        SDL_SetError("Unsupported audio format");
   1.299 -        return (-1);
   1.300 -    }
   1.301 -    waveformat.nChannels = spec->channels;
   1.302 -    waveformat.nSamplesPerSec = spec->freq;
   1.303 +    if (this->spec.channels > 2)
   1.304 +        this->spec.channels = 2;  /* !!! FIXME: is this right? */
   1.305 +
   1.306 +    waveformat.nChannels = this->spec.channels;
   1.307 +    waveformat.nSamplesPerSec = this->spec.freq;
   1.308      waveformat.nBlockAlign =
   1.309          waveformat.nChannels * (waveformat.wBitsPerSample / 8);
   1.310      waveformat.nAvgBytesPerSec =
   1.311          waveformat.nSamplesPerSec * waveformat.nBlockAlign;
   1.312  
   1.313      /* Check the buffer size -- minimum of 1/4 second (word aligned) */
   1.314 -    if (spec->samples < (spec->freq / 4))
   1.315 -        spec->samples = ((spec->freq / 4) + 3) & ~3;
   1.316 +    if (this->spec.samples < (this->spec.freq / 4))
   1.317 +        this->spec.samples = ((this->spec.freq / 4) + 3) & ~3;
   1.318  
   1.319      /* Update the fragment size as size in bytes */
   1.320 -    SDL_CalculateAudioSpec(spec);
   1.321 +    SDL_CalculateAudioSpec(&this->spec);
   1.322  
   1.323      /* Open the audio device */
   1.324 -    result = waveOutOpen(&sound, WAVE_MAPPER, &waveformat,
   1.325 +    result = waveOutOpen(&this->hidden->sound, WAVE_MAPPER, &waveformat,
   1.326                           (DWORD_PTR) FillSound, (DWORD_PTR) this,
   1.327                           CALLBACK_FUNCTION);
   1.328      if (result != MMSYSERR_NOERROR) {
   1.329 +        WINWAVEOUT_CloseDevice(this);
   1.330          SetMMerror("waveOutOpen()", result);
   1.331 -        return (-1);
   1.332 +        return 0;
   1.333      }
   1.334  #ifdef SOUND_DEBUG
   1.335      /* Check the sound device we retrieved */
   1.336      {
   1.337          WAVEOUTCAPS caps;
   1.338  
   1.339 -        result = waveOutGetDevCaps((UINT) sound, &caps, sizeof(caps));
   1.340 +        result = waveOutGetDevCaps((UINT) this->hidden->sound,
   1.341 +                                   &caps, sizeof(caps));
   1.342          if (result != MMSYSERR_NOERROR) {
   1.343 +            WINWAVEOUT_CloseDevice(this);
   1.344              SetMMerror("waveOutGetDevCaps()", result);
   1.345 -            return (-1);
   1.346 +            return 0;
   1.347          }
   1.348          printf("Audio device: %s\n", caps.szPname);
   1.349      }
   1.350  #endif
   1.351  
   1.352      /* Create the audio buffer semaphore */
   1.353 +    this->hidden->audio_sem = 
   1.354  #if defined(_WIN32_WCE) && (_WIN32_WCE < 300)
   1.355 -    audio_sem = CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
   1.356 +            CreateSemaphoreCE(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
   1.357  #else
   1.358 -    audio_sem = CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
   1.359 +            CreateSemaphore(NULL, NUM_BUFFERS - 1, NUM_BUFFERS, NULL);
   1.360  #endif
   1.361 -    if (audio_sem == NULL) {
   1.362 +    if (this->hidden->audio_sem == NULL) {
   1.363 +        WINWAVEOUT_CloseDevice(this);
   1.364          SDL_SetError("Couldn't create semaphore");
   1.365 -        return (-1);
   1.366 +        return 0;
   1.367      }
   1.368  
   1.369      /* Create the sound buffers */
   1.370 -    mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * spec->size);
   1.371 +    this->hidden->mixbuf = (Uint8 *) SDL_malloc(NUM_BUFFERS * this->spec.size);
   1.372      if (mixbuf == NULL) {
   1.373 -        SDL_SetError("Out of memory");
   1.374 -        return (-1);
   1.375 +        WINWAVEOUT_CloseDevice(this);
   1.376 +        SDL_OutOfMemory();
   1.377 +        return 0;
   1.378      }
   1.379      for (i = 0; i < NUM_BUFFERS; ++i) {
   1.380 -        SDL_memset(&wavebuf[i], 0, sizeof(wavebuf[i]));
   1.381 -        wavebuf[i].lpData = (LPSTR) & mixbuf[i * spec->size];
   1.382 -        wavebuf[i].dwBufferLength = spec->size;
   1.383 -        wavebuf[i].dwFlags = WHDR_DONE;
   1.384 -        result = waveOutPrepareHeader(sound, &wavebuf[i], sizeof(wavebuf[i]));
   1.385 +        SDL_memset(&this->hidden->wavebuf[i], '\0',
   1.386 +                    sizeof (this->hidden->wavebuf[i]));
   1.387 +        this->hidden->wavebuf[i].dwBufferLength = this->spec.size;
   1.388 +        this->hidden->wavebuf[i].dwFlags = WHDR_DONE;
   1.389 +        this->hidden->wavebuf[i].lpData =
   1.390 +                            (LPSTR) &this->hidden->mixbuf[i * this->spec.size];
   1.391 +        result = waveOutPrepareHeader(this->hidden->sound,
   1.392 +                                      &this->hidden->wavebuf[i],
   1.393 +                                      sizeof (this->hidden->wavebuf[i]));
   1.394          if (result != MMSYSERR_NOERROR) {
   1.395 +            WINWAVEOUT_CloseDevice(this);
   1.396              SetMMerror("waveOutPrepareHeader()", result);
   1.397 -            return (-1);
   1.398 +            return 0;
   1.399          }
   1.400      }
   1.401  
   1.402 -    /* Ready to go! */
   1.403 -    next_buffer = 0;
   1.404 -    return (0);
   1.405 +    return 1;   /* Ready to go! */
   1.406  }
   1.407  
   1.408 +
   1.409 +static int
   1.410 +WINWAVEOUT_Init(SDL_AudioDriverImpl *impl)
   1.411 +{
   1.412 +    /* Set the function pointers */
   1.413 +    impl->OpenDevice = WINWAVEOUT_OpenDevice;
   1.414 +    impl->ThreadInit = WINWAVEOUT_ThreadInit;
   1.415 +    impl->PlayDevice = WINWAVEOUT_PlayDevice;
   1.416 +    impl->WaitDevice = WINWAVEOUT_WaitDevice;
   1.417 +    impl->WaitDone = WINWAVEOUT_WaitDone;
   1.418 +    impl->GetDeviceBuf = WINWAVEOUT_GetDeviceBuf;
   1.419 +    impl->CloseDevice = WINWAVEOUT_CloseDevice;
   1.420 +    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME: Is this true? */
   1.421 +
   1.422 +    return 1;
   1.423 +}
   1.424 +
   1.425 +AudioBootStrap WINWAVEOUT_bootstrap = {
   1.426 +    "waveout", WINDOWS_OS_NAME " WaveOut",
   1.427 +    WINWAVEOUT_Available, WINWAVEOUT_Init, 0
   1.428 +};
   1.429 +
   1.430  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/audio/windib/SDL_dibaudio.h	Sun Oct 08 08:58:36 2006 +0000
     2.2 +++ b/src/audio/windib/SDL_dibaudio.h	Sun Oct 08 23:04:24 2006 +0000
     2.3 @@ -40,13 +40,6 @@
     2.4      int next_buffer;
     2.5  };
     2.6  
     2.7 -/* Old variable names */
     2.8 -#define sound			(this->hidden->sound)
     2.9 -#define audio_sem 		(this->hidden->audio_sem)
    2.10 -#define mixbuf			(this->hidden->mixbuf)
    2.11 -#define wavebuf			(this->hidden->wavebuf)
    2.12 -#define next_buffer		(this->hidden->next_buffer)
    2.13 -
    2.14  #endif /* _SDL_dibaudio_h */
    2.15  
    2.16  /* vi: set ts=4 sw=4 expandtab: */