Moved DirectSound audio target to SDL 1.3 API and did some house cleaning. SDL-ryan-multiple-audio-device
authorRyan C. Gordon <icculus@icculus.org>
Tue, 17 Oct 2006 06:37:42 +0000
branchSDL-ryan-multiple-audio-device
changeset 38426b04ca2f1016
parent 3841 3479f939987c
child 3843 ce229f6b5ce0
Moved DirectSound audio target to SDL 1.3 API and did some house cleaning.
src/audio/windx5/SDL_dx5audio.c
src/audio/windx5/SDL_dx5audio.h
     1.1 --- a/src/audio/windx5/SDL_dx5audio.c	Sun Oct 08 23:04:24 2006 +0000
     1.2 +++ b/src/audio/windx5/SDL_dx5audio.c	Tue Oct 17 06:37:42 2006 +0000
     1.3 @@ -28,160 +28,96 @@
     1.4  #include "../SDL_audio_c.h"
     1.5  #include "SDL_dx5audio.h"
     1.6  
     1.7 -/* Define this if you want to use DirectX 6 DirectSoundNotify interface */
     1.8 -//#define USE_POSITION_NOTIFY
     1.9 +/* !!! FIXME: move this somewhere that other drivers can use it... */
    1.10 +#if defined(_WIN32_WCE)
    1.11 +#define WINDOWS_OS_NAME "Windows CE/PocketPC"
    1.12 +#elif defined(WIN64)
    1.13 +#define WINDOWS_OS_NAME "Win64"
    1.14 +#else
    1.15 +#define WINDOWS_OS_NAME "Win32"
    1.16 +#endif
    1.17  
    1.18  /* DirectX function pointers for audio */
    1.19 -HRESULT(WINAPI * DSoundCreate) (LPGUID, LPDIRECTSOUND *, LPUNKNOWN);
    1.20 +static HINSTANCE DSoundDLL = NULL;
    1.21 +static HRESULT (WINAPI *DSoundCreate)(LPGUID,LPDIRECTSOUND*,LPUNKNOWN) = NULL;
    1.22  
    1.23 -/* Audio driver functions */
    1.24 -static int DX5_OpenAudio(_THIS, SDL_AudioSpec * spec);
    1.25 -static void DX5_ThreadInit(_THIS);
    1.26 -static void DX5_WaitAudio_BusyWait(_THIS);
    1.27 -#ifdef USE_POSITION_NOTIFY
    1.28 -static void DX6_WaitAudio_EventWait(_THIS);
    1.29 -#endif
    1.30 -static void DX5_PlayAudio(_THIS);
    1.31 -static Uint8 *DX5_GetAudioBuf(_THIS);
    1.32 -static void DX5_WaitDone(_THIS);
    1.33 -static void DX5_CloseAudio(_THIS);
    1.34 +static void
    1.35 +DSOUND_Unload(void)
    1.36 +{
    1.37 +    if (DSoundDLL != NULL) {
    1.38 +        FreeLibrary(DSoundDLL);
    1.39 +    }
    1.40  
    1.41 -/* Audio driver bootstrap functions */
    1.42 +    DSoundCreate = NULL;
    1.43 +    DSoundDLL = NULL;
    1.44 +}
    1.45 +
    1.46  
    1.47  static int
    1.48 -Audio_Available(void)
    1.49 +DSOUND_Load(void)
    1.50  {
    1.51 -    HINSTANCE DSoundDLL;
    1.52 -    int dsound_ok;
    1.53 +    int loaded = 0;
    1.54  
    1.55 -    /* Version check DSOUND.DLL (Is DirectX okay?) */
    1.56 -    dsound_ok = 0;
    1.57 +    DSOUND_Unload();
    1.58 +
    1.59      DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL"));
    1.60 -    if (DSoundDLL != NULL) {
    1.61 -        /* We just use basic DirectSound, we're okay */
    1.62 -        /* Yay! */
    1.63 -        /* Unfortunately, the sound drivers on NT have
    1.64 -           higher latencies than the audio buffers used
    1.65 -           by many SDL applications, so there are gaps
    1.66 -           in the audio - it sounds terrible.  Punt for now.
    1.67 -         */
    1.68 -        OSVERSIONINFO ver;
    1.69 -        ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
    1.70 -        GetVersionEx(&ver);
    1.71 -        switch (ver.dwPlatformId) {
    1.72 -        case VER_PLATFORM_WIN32_NT:
    1.73 -            if (ver.dwMajorVersion > 4) {
    1.74 -                /* Win2K */
    1.75 -                dsound_ok = 1;
    1.76 -            } else {
    1.77 -                /* WinNT */
    1.78 -                dsound_ok = 0;
    1.79 -            }
    1.80 -            break;
    1.81 -        default:
    1.82 -            /* Win95 or Win98 */
    1.83 -            dsound_ok = 1;
    1.84 -            break;
    1.85 +    if (DSoundDLL == NULL) {
    1.86 +        SDL_SetError("DirectSound: failed to load DSOUND.DLL");
    1.87 +    } else {
    1.88 +        /* Now make sure we have DirectX 5 or better... */
    1.89 +        /*  (DirectSoundCaptureCreate was added in DX5) */
    1.90 +        if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate"))) {
    1.91 +            SDL_SetError("DirectSound: System doesn't appear to have DX5.");
    1.92 +        } else {
    1.93 +            DSoundCreate = (void *) GetProcAddress(DSoundDLL,
    1.94 +                                               TEXT("DirectSoundCreate"));
    1.95 +        }
    1.96 +
    1.97 +        if (!DSoundCreate) {
    1.98 +            SDL_SetError("DirectSound: Failed to find DirectSoundCreate");
    1.99 +        } else {
   1.100 +            loaded = 1;
   1.101          }
   1.102 -        /* Now check for DirectX 5 or better - otherwise
   1.103 -         * we will fail later in DX5_OpenAudio without a chance
   1.104 -         * to fall back to the DIB driver. */
   1.105 -        if (dsound_ok) {
   1.106 -            /* DirectSoundCaptureCreate was added in DX5 */
   1.107 -            if (!GetProcAddress(DSoundDLL, TEXT("DirectSoundCaptureCreate")))
   1.108 -                dsound_ok = 0;
   1.109 +    }
   1.110 +
   1.111 +    if (!loaded) {
   1.112 +        DSOUND_Unload();
   1.113 +    }
   1.114 +
   1.115 +    return loaded;
   1.116 +}
   1.117 +
   1.118 +
   1.119 +
   1.120 +
   1.121 +static int
   1.122 +DSOUND_Available(void)
   1.123 +{
   1.124 +    int dsound_ok = 1;
   1.125 +    OSVERSIONINFO ver;
   1.126  
   1.127 +    /*
   1.128 +     * Unfortunately, the sound drivers on NT have higher latencies than the
   1.129 +     *  audio buffers used by many SDL applications, so there are gaps in the
   1.130 +     *  audio - it sounds terrible.  Punt for now.
   1.131 +     */
   1.132 +    SDL_memset(&ver, '\0', sizeof (OSVERSIONINFO));
   1.133 +    ver.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   1.134 +    GetVersionEx(&ver);
   1.135 +    if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT)
   1.136 +        if (ver.dwMajorVersion <= 4) {
   1.137 +            dsound_ok = 0;  /* NT4.0 or earlier. Disable dsound support. */
   1.138          }
   1.139 -        /* Clean up.. */
   1.140 -        FreeLibrary(DSoundDLL);
   1.141      }
   1.142 +
   1.143 +    if (dsound_ok) {
   1.144 +        dsound_ok = DSOUND_Load();  /* make sure we really have DX5. */
   1.145 +        DSOUND_Unload();
   1.146 +    }
   1.147 +
   1.148      return (dsound_ok);
   1.149  }
   1.150  
   1.151 -/* Functions for loading the DirectX functions dynamically */
   1.152 -static HINSTANCE DSoundDLL = NULL;
   1.153 -
   1.154 -static void
   1.155 -DX5_Unload(void)
   1.156 -{
   1.157 -    if (DSoundDLL != NULL) {
   1.158 -        FreeLibrary(DSoundDLL);
   1.159 -        DSoundCreate = NULL;
   1.160 -        DSoundDLL = NULL;
   1.161 -    }
   1.162 -}
   1.163 -static int
   1.164 -DX5_Load(void)
   1.165 -{
   1.166 -    int status;
   1.167 -
   1.168 -    DX5_Unload();
   1.169 -    DSoundDLL = LoadLibrary(TEXT("DSOUND.DLL"));
   1.170 -    if (DSoundDLL != NULL) {
   1.171 -        DSoundCreate = (void *) GetProcAddress(DSoundDLL,
   1.172 -                                               TEXT("DirectSoundCreate"));
   1.173 -    }
   1.174 -    if (DSoundDLL && DSoundCreate) {
   1.175 -        status = 0;
   1.176 -    } else {
   1.177 -        DX5_Unload();
   1.178 -        status = -1;
   1.179 -    }
   1.180 -    return status;
   1.181 -}
   1.182 -
   1.183 -static void
   1.184 -Audio_DeleteDevice(SDL_AudioDevice * device)
   1.185 -{
   1.186 -    DX5_Unload();
   1.187 -    SDL_free(device->hidden);
   1.188 -    SDL_free(device);
   1.189 -}
   1.190 -
   1.191 -static SDL_AudioDevice *
   1.192 -Audio_CreateDevice(int devindex)
   1.193 -{
   1.194 -    SDL_AudioDevice *this;
   1.195 -
   1.196 -    /* Load DirectX */
   1.197 -    if (DX5_Load() < 0) {
   1.198 -        return (NULL);
   1.199 -    }
   1.200 -
   1.201 -    /* Initialize all variables that we clean on shutdown */
   1.202 -    this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
   1.203 -    if (this) {
   1.204 -        SDL_memset(this, 0, (sizeof *this));
   1.205 -        this->hidden = (struct SDL_PrivateAudioData *)
   1.206 -            SDL_malloc((sizeof *this->hidden));
   1.207 -    }
   1.208 -    if ((this == NULL) || (this->hidden == NULL)) {
   1.209 -        SDL_OutOfMemory();
   1.210 -        if (this) {
   1.211 -            SDL_free(this);
   1.212 -        }
   1.213 -        return (0);
   1.214 -    }
   1.215 -    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   1.216 -
   1.217 -    /* Set the function pointers */
   1.218 -    this->OpenAudio = DX5_OpenAudio;
   1.219 -    this->ThreadInit = DX5_ThreadInit;
   1.220 -    this->WaitAudio = DX5_WaitAudio_BusyWait;
   1.221 -    this->PlayAudio = DX5_PlayAudio;
   1.222 -    this->GetAudioBuf = DX5_GetAudioBuf;
   1.223 -    this->WaitDone = DX5_WaitDone;
   1.224 -    this->CloseAudio = DX5_CloseAudio;
   1.225 -
   1.226 -    this->free = Audio_DeleteDevice;
   1.227 -
   1.228 -    return this;
   1.229 -}
   1.230 -
   1.231 -AudioBootStrap DSOUND_bootstrap = {
   1.232 -    "dsound", "Win95/98/2000 DirectSound",
   1.233 -    Audio_Available, Audio_CreateDevice, 0
   1.234 -};
   1.235  
   1.236  static void
   1.237  SetDSerror(const char *function, int code)
   1.238 @@ -192,8 +128,7 @@
   1.239      errbuf[0] = 0;
   1.240      switch (code) {
   1.241      case E_NOINTERFACE:
   1.242 -        error =
   1.243 -            "Unsupported interface\n-- Is DirectX 5.0 or later installed?";
   1.244 +        error = "Unsupported interface -- Is DirectX 5.0 or later installed?";
   1.245          break;
   1.246      case DSERR_ALLOCATED:
   1.247          error = "Audio device in use";
   1.248 @@ -241,32 +176,36 @@
   1.249  /* DirectSound needs to be associated with a window */
   1.250  static HWND mainwin = NULL;
   1.251  /* */
   1.252 +
   1.253  void
   1.254 -DX5_SoundFocus(HWND hwnd)
   1.255 +DSOUND_SoundFocus(HWND hwnd)
   1.256  {
   1.257 +    /* !!! FIXME: probably broken with multi-window support in SDL 1.3 ... */
   1.258      mainwin = hwnd;
   1.259  }
   1.260  
   1.261  static void
   1.262 -DX5_ThreadInit(_THIS)
   1.263 +DSOUND_ThreadInit(_THIS)
   1.264  {
   1.265      SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
   1.266  }
   1.267  
   1.268  static void
   1.269 -DX5_WaitAudio_BusyWait(_THIS)
   1.270 +DSOUND_WaitDevice(_THIS)
   1.271  {
   1.272 -    DWORD status;
   1.273 -    DWORD cursor, junk;
   1.274 -    HRESULT result;
   1.275 +    DWORD status = 0;
   1.276 +    DWORD cursor = 0;
   1.277 +    DWORD junk = 0;
   1.278 +    HRESULT result = DS_OK;
   1.279  
   1.280      /* Semi-busy wait, since we have no way of getting play notification
   1.281         on a primary mixing buffer located in hardware (DirectX 5.0)
   1.282       */
   1.283 -    result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor);
   1.284 +    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
   1.285 +                                                   &junk, &cursor);
   1.286      if (result != DS_OK) {
   1.287          if (result == DSERR_BUFFERLOST) {
   1.288 -            IDirectSoundBuffer_Restore(mixbuf);
   1.289 +            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
   1.290          }
   1.291  #ifdef DEBUG_SOUND
   1.292          SetDSerror("DirectSound GetCurrentPosition", result);
   1.293 @@ -274,21 +213,22 @@
   1.294          return;
   1.295      }
   1.296  
   1.297 -    while ((cursor / mixlen) == lastchunk) {
   1.298 +    while ((cursor / this->hidden->mixlen) == this->hidden->lastchunk) {
   1.299          /* FIXME: find out how much time is left and sleep that long */
   1.300          SDL_Delay(1);
   1.301  
   1.302          /* Try to restore a lost sound buffer */
   1.303 -        IDirectSoundBuffer_GetStatus(mixbuf, &status);
   1.304 +        IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
   1.305          if ((status & DSBSTATUS_BUFFERLOST)) {
   1.306 -            IDirectSoundBuffer_Restore(mixbuf);
   1.307 -            IDirectSoundBuffer_GetStatus(mixbuf, &status);
   1.308 +            IDirectSoundBuffer_Restore(this->hidden->mixbuf);
   1.309 +            IDirectSoundBuffer_GetStatus(this->hidden->mixbuf, &status);
   1.310              if ((status & DSBSTATUS_BUFFERLOST)) {
   1.311                  break;
   1.312              }
   1.313          }
   1.314          if (!(status & DSBSTATUS_PLAYING)) {
   1.315 -            result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING);
   1.316 +            result = IDirectSoundBuffer_Play(this->hidden->mixbuf, 0, 0,
   1.317 +                                             DSBPLAY_LOOPING);
   1.318              if (result == DS_OK) {
   1.319                  continue;
   1.320              }
   1.321 @@ -299,7 +239,7 @@
   1.322          }
   1.323  
   1.324          /* Find out where we are playing */
   1.325 -        result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
   1.326 +        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
   1.327                                                         &junk, &cursor);
   1.328          if (result != DS_OK) {
   1.329              SetDSerror("DirectSound GetCurrentPosition", result);
   1.330 @@ -308,222 +248,122 @@
   1.331      }
   1.332  }
   1.333  
   1.334 -#ifdef USE_POSITION_NOTIFY
   1.335  static void
   1.336 -DX6_WaitAudio_EventWait(_THIS)
   1.337 -{
   1.338 -    DWORD status;
   1.339 -    HRESULT result;
   1.340 -
   1.341 -    /* Try to restore a lost sound buffer */
   1.342 -    IDirectSoundBuffer_GetStatus(mixbuf, &status);
   1.343 -    if ((status & DSBSTATUS_BUFFERLOST)) {
   1.344 -        IDirectSoundBuffer_Restore(mixbuf);
   1.345 -        IDirectSoundBuffer_GetStatus(mixbuf, &status);
   1.346 -        if ((status & DSBSTATUS_BUFFERLOST)) {
   1.347 -            return;
   1.348 -        }
   1.349 -    }
   1.350 -    if (!(status & DSBSTATUS_PLAYING)) {
   1.351 -        result = IDirectSoundBuffer_Play(mixbuf, 0, 0, DSBPLAY_LOOPING);
   1.352 -        if (result != DS_OK) {
   1.353 -#ifdef DEBUG_SOUND
   1.354 -            SetDSerror("DirectSound Play", result);
   1.355 -#endif
   1.356 -            return;
   1.357 -        }
   1.358 -    }
   1.359 -    WaitForSingleObject(audio_event, INFINITE);
   1.360 -}
   1.361 -#endif /* USE_POSITION_NOTIFY */
   1.362 -
   1.363 -static void
   1.364 -DX5_PlayAudio(_THIS)
   1.365 +DSOUND_PlayDevice(_THIS)
   1.366  {
   1.367      /* Unlock the buffer, allowing it to play */
   1.368 -    if (locked_buf) {
   1.369 -        IDirectSoundBuffer_Unlock(mixbuf, locked_buf, mixlen, NULL, 0);
   1.370 +    if (this->hidden->locked_buf) {
   1.371 +        IDirectSoundBuffer_Unlock(this->hidden->mixbuf,
   1.372 +                                  this->hidden->locked_buf,
   1.373 +                                  this->hidden->mixlen, NULL, 0);
   1.374      }
   1.375  
   1.376  }
   1.377  
   1.378  static Uint8 *
   1.379 -DX5_GetAudioBuf(_THIS)
   1.380 +DSOUND_GetDeviceBuf(_THIS)
   1.381  {
   1.382 -    DWORD cursor, junk;
   1.383 -    HRESULT result;
   1.384 -    DWORD rawlen;
   1.385 +    DWORD cursor = 0;
   1.386 +    DWORD junk = 0;
   1.387 +    HRESULT result = DS_OK;
   1.388 +    DWORD rawlen = 0;
   1.389  
   1.390      /* Figure out which blocks to fill next */
   1.391 -    locked_buf = NULL;
   1.392 -    result = IDirectSoundBuffer_GetCurrentPosition(mixbuf, &junk, &cursor);
   1.393 +    this->hidden->locked_buf = NULL;
   1.394 +    result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
   1.395 +                                                   &junk, &cursor);
   1.396      if (result == DSERR_BUFFERLOST) {
   1.397 -        IDirectSoundBuffer_Restore(mixbuf);
   1.398 -        result = IDirectSoundBuffer_GetCurrentPosition(mixbuf,
   1.399 +        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
   1.400 +        result = IDirectSoundBuffer_GetCurrentPosition(this->hidden->mixbuf,
   1.401                                                         &junk, &cursor);
   1.402      }
   1.403      if (result != DS_OK) {
   1.404          SetDSerror("DirectSound GetCurrentPosition", result);
   1.405          return (NULL);
   1.406      }
   1.407 -    cursor /= mixlen;
   1.408 +    cursor /= this->hidden->mixlen;
   1.409  #ifdef DEBUG_SOUND
   1.410      /* Detect audio dropouts */
   1.411      {
   1.412          DWORD spot = cursor;
   1.413 -        if (spot < lastchunk) {
   1.414 -            spot += NUM_BUFFERS;
   1.415 +        if (spot < this->hidden->lastchunk) {
   1.416 +            spot += this->hidden->num_buffers;
   1.417          }
   1.418 -        if (spot > lastchunk + 1) {
   1.419 +        if (spot > this->hidden->lastchunk + 1) {
   1.420              fprintf(stderr, "Audio dropout, missed %d fragments\n",
   1.421 -                    (spot - (lastchunk + 1)));
   1.422 +                    (spot - (this->hidden->lastchunk + 1)));
   1.423          }
   1.424      }
   1.425  #endif
   1.426 -    lastchunk = cursor;
   1.427 -    cursor = (cursor + 1) % NUM_BUFFERS;
   1.428 -    cursor *= mixlen;
   1.429 +    this->hidden->lastchunk = cursor;
   1.430 +    cursor = (cursor + 1) % this->hidden->num_buffers;
   1.431 +    cursor *= this->hidden->mixlen;
   1.432  
   1.433      /* Lock the audio buffer */
   1.434 -    result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
   1.435 -                                     (LPVOID *) & locked_buf, &rawlen, NULL,
   1.436 -                                     &junk, 0);
   1.437 +    result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
   1.438 +                                     this->hidden->mixlen,
   1.439 +                                     (LPVOID *) &this->hidden->locked_buf,
   1.440 +                                     &rawlen, NULL, &junk, 0);
   1.441      if (result == DSERR_BUFFERLOST) {
   1.442 -        IDirectSoundBuffer_Restore(mixbuf);
   1.443 -        result = IDirectSoundBuffer_Lock(mixbuf, cursor, mixlen,
   1.444 -                                         (LPVOID *) & locked_buf, &rawlen,
   1.445 -                                         NULL, &junk, 0);
   1.446 +        IDirectSoundBuffer_Restore(this->hidden->mixbuf);
   1.447 +        result = IDirectSoundBuffer_Lock(this->hidden->mixbuf, cursor,
   1.448 +                                         this->hidden->mixlen,
   1.449 +                                         (LPVOID *) &this->hidden->locked_buf,
   1.450 +                                         &rawlen, NULL, &junk, 0);
   1.451      }
   1.452      if (result != DS_OK) {
   1.453          SetDSerror("DirectSound Lock", result);
   1.454          return (NULL);
   1.455      }
   1.456 -    return (locked_buf);
   1.457 -}
   1.458 -
   1.459 -static void
   1.460 -DX5_WaitDone(_THIS)
   1.461 -{
   1.462 -    Uint8 *stream;
   1.463 -
   1.464 -    /* Wait for the playing chunk to finish */
   1.465 -    stream = this->GetAudioBuf(this);
   1.466 -    if (stream != NULL) {
   1.467 -        SDL_memset(stream, silence, mixlen);
   1.468 -        this->PlayAudio(this);
   1.469 -    }
   1.470 -    this->WaitAudio(this);
   1.471 -
   1.472 -    /* Stop the looping sound buffer */
   1.473 -    IDirectSoundBuffer_Stop(mixbuf);
   1.474 +    return (this->hidden->locked_buf);
   1.475  }
   1.476  
   1.477  static void
   1.478 -DX5_CloseAudio(_THIS)
   1.479 +DSOUND_WaitDone(_THIS)
   1.480  {
   1.481 -    if (sound != NULL) {
   1.482 -        if (mixbuf != NULL) {
   1.483 -            /* Clean up the audio buffer */
   1.484 -            IDirectSoundBuffer_Release(mixbuf);
   1.485 -            mixbuf = NULL;
   1.486 -        }
   1.487 -        if (audio_event != NULL) {
   1.488 -            CloseHandle(audio_event);
   1.489 -            audio_event = NULL;
   1.490 -        }
   1.491 -        IDirectSound_Release(sound);
   1.492 -        sound = NULL;
   1.493 +    Uint8 *stream = DSOUND_GetDeviceBuf(this);
   1.494 +
   1.495 +    /* Wait for the playing chunk to finish */
   1.496 +    if (stream != NULL) {
   1.497 +        SDL_memset(stream, this->spec.silence, this->hidden->mixlen);
   1.498 +        DSOUND_PlayDevice(this);
   1.499      }
   1.500 +    DSOUND_WaitDevice(this);
   1.501 +
   1.502 +    /* Stop the looping sound buffer */
   1.503 +    IDirectSoundBuffer_Stop(this->hidden->mixbuf);
   1.504  }
   1.505  
   1.506 -#ifdef USE_PRIMARY_BUFFER
   1.507 -/* This function tries to create a primary audio buffer, and returns the
   1.508 -   number of audio chunks available in the created buffer.
   1.509 -*/
   1.510 -static int
   1.511 -CreatePrimary(LPDIRECTSOUND sndObj, HWND focus,
   1.512 -              LPDIRECTSOUNDBUFFER * sndbuf, WAVEFORMATEX * wavefmt,
   1.513 -              Uint32 chunksize)
   1.514 +static void
   1.515 +DSOUND_CloseDevice(_THIS)
   1.516  {
   1.517 -    HRESULT result;
   1.518 -    DSBUFFERDESC format;
   1.519 -    DSBCAPS caps;
   1.520 -    int numchunks;
   1.521 +    if (this->hidden != NULL) {
   1.522 +        if (this->hidden->sound != NULL) {
   1.523 +            if (this->hidden->mixbuf != NULL) {
   1.524 +                /* Clean up the audio buffer */
   1.525 +                IDirectSoundBuffer_Release(this->hidden->mixbuf);
   1.526 +                this->hidden->mixbuf = NULL;
   1.527 +            }
   1.528 +            IDirectSound_Release(this->hidden->sound);
   1.529 +            this->hidden->sound = NULL;
   1.530 +        }
   1.531  
   1.532 -    /* Try to set primary mixing privileges */
   1.533 -    result = IDirectSound_SetCooperativeLevel(sndObj, focus,
   1.534 -                                              DSSCL_WRITEPRIMARY);
   1.535 -    if (result != DS_OK) {
   1.536 -#ifdef DEBUG_SOUND
   1.537 -        SetDSerror("DirectSound SetCooperativeLevel", result);
   1.538 -#endif
   1.539 -        return (-1);
   1.540 -    }
   1.541 -
   1.542 -    /* Try to create the primary buffer */
   1.543 -    SDL_memset(&format, 0, sizeof(format));
   1.544 -    format.dwSize = sizeof(format);
   1.545 -    format.dwFlags = (DSBCAPS_PRIMARYBUFFER | DSBCAPS_GETCURRENTPOSITION2);
   1.546 -    format.dwFlags |= DSBCAPS_STICKYFOCUS;
   1.547 -#ifdef USE_POSITION_NOTIFY
   1.548 -    format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;
   1.549 -#endif
   1.550 -    result = IDirectSound_CreateSoundBuffer(sndObj, &format, sndbuf, NULL);
   1.551 -    if (result != DS_OK) {
   1.552 -#ifdef DEBUG_SOUND
   1.553 -        SetDSerror("DirectSound CreateSoundBuffer", result);
   1.554 -#endif
   1.555 -        return (-1);
   1.556 +        SDL_free(this->hidden);
   1.557 +        this->hidden = NULL;
   1.558      }
   1.559 -
   1.560 -    /* Check the size of the fragment buffer */
   1.561 -    SDL_memset(&caps, 0, sizeof(caps));
   1.562 -    caps.dwSize = sizeof(caps);
   1.563 -    result = IDirectSoundBuffer_GetCaps(*sndbuf, &caps);
   1.564 -    if (result != DS_OK) {
   1.565 -#ifdef DEBUG_SOUND
   1.566 -        SetDSerror("DirectSound GetCaps", result);
   1.567 -#endif
   1.568 -        IDirectSoundBuffer_Release(*sndbuf);
   1.569 -        return (-1);
   1.570 -    }
   1.571 -    if ((chunksize > caps.dwBufferBytes) ||
   1.572 -        ((caps.dwBufferBytes % chunksize) != 0)) {
   1.573 -        /* The primary buffer size is not a multiple of 'chunksize'
   1.574 -           -- this hopefully doesn't happen when 'chunksize' is a 
   1.575 -           power of 2.
   1.576 -         */
   1.577 -        IDirectSoundBuffer_Release(*sndbuf);
   1.578 -        SDL_SetError
   1.579 -            ("Primary buffer size is: %d, cannot break it into chunks of %d bytes\n",
   1.580 -             caps.dwBufferBytes, chunksize);
   1.581 -        return (-1);
   1.582 -    }
   1.583 -    numchunks = (caps.dwBufferBytes / chunksize);
   1.584 -
   1.585 -    /* Set the primary audio format */
   1.586 -    result = IDirectSoundBuffer_SetFormat(*sndbuf, wavefmt);
   1.587 -    if (result != DS_OK) {
   1.588 -#ifdef DEBUG_SOUND
   1.589 -        SetDSerror("DirectSound SetFormat", result);
   1.590 -#endif
   1.591 -        IDirectSoundBuffer_Release(*sndbuf);
   1.592 -        return (-1);
   1.593 -    }
   1.594 -    return (numchunks);
   1.595  }
   1.596 -#endif /* USE_PRIMARY_BUFFER */
   1.597  
   1.598  /* This function tries to create a secondary audio buffer, and returns the
   1.599     number of audio chunks available in the created buffer.
   1.600  */
   1.601  static int
   1.602 -CreateSecondary(LPDIRECTSOUND sndObj, HWND focus,
   1.603 -                LPDIRECTSOUNDBUFFER * sndbuf, WAVEFORMATEX * wavefmt,
   1.604 -                Uint32 chunksize)
   1.605 +CreateSecondary(_THIS, HWND focus, WAVEFORMATEX *wavefmt)
   1.606  {
   1.607 +    LPDIRECTSOUND sndObj = this->hidden->sound;
   1.608 +    LPDIRECTSOUNDBUFFER *sndbuf = this->hidden->mixbuf;
   1.609 +    Uint32 chunksize = this->spec.size;
   1.610      const int numchunks = 8;
   1.611 -    HRESULT result;
   1.612 +    HRESULT result = DS_OK;
   1.613      DSBUFFERDESC format;
   1.614      LPVOID pvAudioPtr1, pvAudioPtr2;
   1.615      DWORD dwAudioBytes1, dwAudioBytes2;
   1.616 @@ -538,9 +378,7 @@
   1.617                                                    DSSCL_NORMAL);
   1.618      }
   1.619      if (result != DS_OK) {
   1.620 -#ifdef DEBUG_SOUND
   1.621          SetDSerror("DirectSound SetCooperativeLevel", result);
   1.622 -#endif
   1.623          return (-1);
   1.624      }
   1.625  
   1.626 @@ -548,9 +386,6 @@
   1.627      SDL_memset(&format, 0, sizeof(format));
   1.628      format.dwSize = sizeof(format);
   1.629      format.dwFlags = DSBCAPS_GETCURRENTPOSITION2;
   1.630 -#ifdef USE_POSITION_NOTIFY
   1.631 -    format.dwFlags |= DSBCAPS_CTRLPOSITIONNOTIFY;
   1.632 -#endif
   1.633      if (!focus) {
   1.634          format.dwFlags |= DSBCAPS_GLOBALFOCUS;
   1.635      } else {
   1.636 @@ -578,11 +413,7 @@
   1.637                                       (LPVOID *) & pvAudioPtr2, &dwAudioBytes2,
   1.638                                       DSBLOCK_ENTIREBUFFER);
   1.639      if (result == DS_OK) {
   1.640 -        if (wavefmt->wBitsPerSample == 8) {
   1.641 -            SDL_memset(pvAudioPtr1, 0x80, dwAudioBytes1);
   1.642 -        } else {
   1.643 -            SDL_memset(pvAudioPtr1, 0x00, dwAudioBytes1);
   1.644 -        }
   1.645 +        SDL_memset(pvAudioPtr1, this->spec.silence, dwAudioBytes1);
   1.646          IDirectSoundBuffer_Unlock(*sndbuf,
   1.647                                    (LPVOID) pvAudioPtr1, dwAudioBytes1,
   1.648                                    (LPVOID) pvAudioPtr2, dwAudioBytes2);
   1.649 @@ -592,148 +423,111 @@
   1.650      return (numchunks);
   1.651  }
   1.652  
   1.653 -/* This function tries to set position notify events on the mixing buffer */
   1.654 -#ifdef USE_POSITION_NOTIFY
   1.655  static int
   1.656 -CreateAudioEvent(_THIS)
   1.657 -{
   1.658 -    LPDIRECTSOUNDNOTIFY notify;
   1.659 -    DSBPOSITIONNOTIFY *notify_positions;
   1.660 -    int i, retval;
   1.661 -    HRESULT result;
   1.662 -
   1.663 -    /* Default to fail on exit */
   1.664 -    retval = -1;
   1.665 -    notify = NULL;
   1.666 -
   1.667 -    /* Query for the interface */
   1.668 -    result = IDirectSoundBuffer_QueryInterface(mixbuf,
   1.669 -                                               &IID_IDirectSoundNotify,
   1.670 -                                               (void *) &notify);
   1.671 -    if (result != DS_OK) {
   1.672 -        goto done;
   1.673 -    }
   1.674 -
   1.675 -    /* Allocate the notify structures */
   1.676 -    notify_positions = (DSBPOSITIONNOTIFY *) SDL_malloc(NUM_BUFFERS *
   1.677 -                                                        sizeof
   1.678 -                                                        (*notify_positions));
   1.679 -    if (notify_positions == NULL) {
   1.680 -        goto done;
   1.681 -    }
   1.682 -
   1.683 -    /* Create the notify event */
   1.684 -    audio_event = CreateEvent(NULL, FALSE, FALSE, NULL);
   1.685 -    if (audio_event == NULL) {
   1.686 -        goto done;
   1.687 -    }
   1.688 -
   1.689 -    /* Set up the notify structures */
   1.690 -    for (i = 0; i < NUM_BUFFERS; ++i) {
   1.691 -        notify_positions[i].dwOffset = i * mixlen;
   1.692 -        notify_positions[i].hEventNotify = audio_event;
   1.693 -    }
   1.694 -    result = IDirectSoundNotify_SetNotificationPositions(notify,
   1.695 -                                                         NUM_BUFFERS,
   1.696 -                                                         notify_positions);
   1.697 -    if (result == DS_OK) {
   1.698 -        retval = 0;
   1.699 -    }
   1.700 -  done:
   1.701 -    if (notify != NULL) {
   1.702 -        IDirectSoundNotify_Release(notify);
   1.703 -    }
   1.704 -    return (retval);
   1.705 -}
   1.706 -#endif /* USE_POSITION_NOTIFY */
   1.707 -
   1.708 -static int
   1.709 -DX5_OpenAudio(_THIS, SDL_AudioSpec * spec)
   1.710 +DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
   1.711  {
   1.712      HRESULT result;
   1.713      WAVEFORMATEX waveformat;
   1.714 +    int valid_format = 0;
   1.715 +    SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
   1.716  
   1.717 -    /* Set basic WAVE format parameters */
   1.718 +    /* !!! FIXME: handle devname */
   1.719 +    /* !!! FIXME: handle iscapture */
   1.720 +
   1.721 +    /* Initialize all variables that we clean on shutdown */
   1.722 +    this->hidden = (struct SDL_PrivateAudioData *)
   1.723 +                        SDL_malloc((sizeof *this->hidden));
   1.724 +    if (this->hidden == NULL) {
   1.725 +        SDL_OutOfMemory();
   1.726 +        return 0;
   1.727 +    }
   1.728 +    SDL_memset(this->hidden, 0, (sizeof *this->hidden));
   1.729 +
   1.730 +    while ((!valid_format) && (test_format)) {
   1.731 +        switch (test_format) {
   1.732 +            case AUDIO_U8:
   1.733 +            case AUDIO_S16:
   1.734 +            case AUDIO_S32:
   1.735 +                this->spec.format = test_format;
   1.736 +                valid_format = 1;
   1.737 +                break;
   1.738 +        }
   1.739 +        test_format = SDL_NextAudioFormat();
   1.740 +    }
   1.741 +
   1.742 +    if (!valid_format) {
   1.743 +        DSOUND_CloseDevice(this);
   1.744 +        SDL_SetError("DirectSound: Unsupported audio format");
   1.745 +        return 0;
   1.746 +    }
   1.747 +
   1.748      SDL_memset(&waveformat, 0, sizeof(waveformat));
   1.749      waveformat.wFormatTag = WAVE_FORMAT_PCM;
   1.750 -
   1.751 -    /* Determine the audio parameters from the AudioSpec */
   1.752 -    switch (SDL_AUDIO_BITSIZE(spec->format)) {
   1.753 -    case 8:
   1.754 -        /* Unsigned 8 bit audio data */
   1.755 -        spec->format = AUDIO_U8;
   1.756 -        silence = 0x80;
   1.757 -        waveformat.wBitsPerSample = 8;
   1.758 -        break;
   1.759 -    case 16:
   1.760 -        /* Signed 16 bit audio data */
   1.761 -        spec->format = AUDIO_S16;
   1.762 -        silence = 0x00;
   1.763 -        waveformat.wBitsPerSample = 16;
   1.764 -        break;
   1.765 -    case 32:
   1.766 -        /* Signed 32 bit audio data */
   1.767 -        spec->format = AUDIO_S32;
   1.768 -        silence = 0x00;
   1.769 -        waveformat.wBitsPerSample = 32;
   1.770 -        break;
   1.771 -    default:
   1.772 -        SDL_SetError("Unsupported audio format");
   1.773 -        return (-1);
   1.774 -    }
   1.775 -    waveformat.nChannels = spec->channels;
   1.776 -    waveformat.nSamplesPerSec = spec->freq;
   1.777 +    waveformat.wBitsPerSample = SDL_AUDIO_BITSIZE(this->spec.format);
   1.778 +    waveformat.nChannels = this->spec.channels;
   1.779 +    waveformat.nSamplesPerSec = this->spec.freq;
   1.780      waveformat.nBlockAlign =
   1.781          waveformat.nChannels * (waveformat.wBitsPerSample / 8);
   1.782      waveformat.nAvgBytesPerSec =
   1.783          waveformat.nSamplesPerSec * waveformat.nBlockAlign;
   1.784  
   1.785      /* Update the fragment size as size in bytes */
   1.786 -    SDL_CalculateAudioSpec(spec);
   1.787 +    SDL_CalculateAudioSpec(&this->spec);
   1.788  
   1.789      /* Open the audio device */
   1.790 -    result = DSoundCreate(NULL, &sound, NULL);
   1.791 +    result = DSoundCreate(NULL, &this->hidden->sound, NULL);
   1.792      if (result != DS_OK) {
   1.793 +        DSOUND_CloseDevice(this);
   1.794          SetDSerror("DirectSoundCreate", result);
   1.795 -        return (-1);
   1.796 +        return 0;
   1.797      }
   1.798  
   1.799      /* Create the audio buffer to which we write */
   1.800 -    NUM_BUFFERS = -1;
   1.801 -#ifdef USE_PRIMARY_BUFFER
   1.802 -    if (mainwin) {
   1.803 -        NUM_BUFFERS = CreatePrimary(sound, mainwin, &mixbuf,
   1.804 -                                    &waveformat, spec->size);
   1.805 -    }
   1.806 -#endif /* USE_PRIMARY_BUFFER */
   1.807 -    if (NUM_BUFFERS < 0) {
   1.808 -        NUM_BUFFERS = CreateSecondary(sound, mainwin, &mixbuf,
   1.809 -                                      &waveformat, spec->size);
   1.810 -        if (NUM_BUFFERS < 0) {
   1.811 -            return (-1);
   1.812 -        }
   1.813 -#ifdef DEBUG_SOUND
   1.814 -        fprintf(stderr, "Using secondary audio buffer\n");
   1.815 -#endif
   1.816 +    this->hidden->num_buffers = CreateSecondary(this, mainwin, &waveformat);
   1.817 +    if (this->hidden->num_buffers < 0) {
   1.818 +        DSOUND_CloseDevice(this);
   1.819 +        return 0;
   1.820      }
   1.821 -#ifdef DEBUG_SOUND
   1.822 -    else
   1.823 -        fprintf(stderr, "Using primary audio buffer\n");
   1.824 -#endif
   1.825  
   1.826 -    /* The buffer will auto-start playing in DX5_WaitAudio() */
   1.827 -    lastchunk = 0;
   1.828 -    mixlen = spec->size;
   1.829 +    /* The buffer will auto-start playing in DSOUND_WaitDevice() */
   1.830 +    this->hidden->mixlen = this->spec.size;
   1.831  
   1.832 -#ifdef USE_POSITION_NOTIFY
   1.833 -    /* See if we can use DirectX 6 event notification */
   1.834 -    if (CreateAudioEvent(this) == 0) {
   1.835 -        this->WaitAudio = DX6_WaitAudio_EventWait;
   1.836 -    } else {
   1.837 -        this->WaitAudio = DX5_WaitAudio_BusyWait;
   1.838 -    }
   1.839 -#endif
   1.840 -    return (0);
   1.841 +    return 1;  /* good to go. */
   1.842 +}
   1.843 +
   1.844 +
   1.845 +static void
   1.846 +DSOUND_Deinitialize(void)
   1.847 +{
   1.848 +    DSOUND_Unload();
   1.849  }
   1.850  
   1.851 +
   1.852 +static int
   1.853 +DSOUND_Init(SDL_AudioDriverImpl *impl)
   1.854 +{
   1.855 +    /* Load DirectX */
   1.856 +    if (DSOUND_Load() < 0) {
   1.857 +        return 0;
   1.858 +    }
   1.859 +
   1.860 +    /* Set the function pointers */
   1.861 +    impl->OpenDevice = DSOUND_OpenDevice;
   1.862 +    impl->PlayDevice = DSOUND_PlayDevice;
   1.863 +    impl->WaitDevice = DSOUND_WaitDevice;
   1.864 +    impl->WaitDone = DSOUND_WaitDone;
   1.865 +    impl->ThreadInit = DSOUND_ThreadInit;
   1.866 +    impl->GetDeviceBuf = DSOUND_GetDeviceBuf;
   1.867 +    impl->CloseDevice = DSOUND_CloseDevice;
   1.868 +    impl->Deinitialize = DSOUND_Deinitialize;
   1.869 +    impl->OnlyHasDefaultOutputDevice = 1;  /* !!! FIXME */
   1.870 +
   1.871 +    return 1;
   1.872 +}
   1.873 +
   1.874 +AudioBootStrap DSOUND_bootstrap = {
   1.875 +    "dsound", WINDOWS_OS_NAME "DirectSound",
   1.876 +    DSOUND_Available, DSOUND_Init, 0
   1.877 +};
   1.878 +
   1.879  /* vi: set ts=4 sw=4 expandtab: */
     2.1 --- a/src/audio/windx5/SDL_dx5audio.h	Sun Oct 08 23:04:24 2006 +0000
     2.2 +++ b/src/audio/windx5/SDL_dx5audio.h	Tue Oct 17 06:37:42 2006 +0000
     2.3 @@ -36,23 +36,12 @@
     2.4  {
     2.5      LPDIRECTSOUND sound;
     2.6      LPDIRECTSOUNDBUFFER mixbuf;
     2.7 -    int NUM_BUFFERS;
     2.8 -    int mixlen, silence;
     2.9 +    int num_buffers;
    2.10 +    int mixlen;
    2.11      DWORD lastchunk;
    2.12      Uint8 *locked_buf;
    2.13 -    HANDLE audio_event;
    2.14  };
    2.15  
    2.16 -/* Old variable names */
    2.17 -#define sound			(this->hidden->sound)
    2.18 -#define mixbuf			(this->hidden->mixbuf)
    2.19 -#define NUM_BUFFERS		(this->hidden->NUM_BUFFERS)
    2.20 -#define mixlen			(this->hidden->mixlen)
    2.21 -#define silence			(this->hidden->silence)
    2.22 -#define lastchunk		(this->hidden->lastchunk)
    2.23 -#define locked_buf		(this->hidden->locked_buf)
    2.24 -#define audio_event		(this->hidden->audio_event)
    2.25 -
    2.26  #endif /* _SDL_dx5audio_h */
    2.27  
    2.28  /* vi: set ts=4 sw=4 expandtab: */