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