[DSOUND] dsound patch

Robert Reif reif at earthlink.net
Mon Jan 16 17:17:19 CST 2006


Convert IDirectSoundImpl from a COM class to a regular class and move 
most of the COM functions to the DirectSoundDevice class.

Sorry about the size of this patch but this last step is hard to break 
up into smaller patches.

This is the last patch related to refactoring dsound to allow device 
sharing between playback/capture and full duplex.
-------------- next part --------------
Index: dlls/dsound/dsound.c
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound.c,v
retrieving revision 1.47
diff -p -u -r1.47 dsound.c
--- dlls/dsound/dsound.c	16 Jan 2006 20:40:33 -0000	1.47
+++ dlls/dsound/dsound.c	16 Jan 2006 23:03:00 -0000
@@ -117,17 +117,7 @@ static void _dump_DSBCAPS(DWORD xmask) {
 /*******************************************************************************
  *		IDirectSoundImpl_DirectSound
  */
-static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
-    LPDIRECTSOUND8 iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    TRACE("(%p,%s,%p)\n",iface,debugstr_guid(riid),ppobj);
-    FIXME("shouldn't be called directly\n");
-    return E_NOINTERFACE;
-}
-
-static HRESULT WINAPI DSOUND_QueryInterface(
+static HRESULT DSOUND_QueryInterface(
     LPDIRECTSOUND8 iface,
     REFIID riid,
     LPVOID * ppobj)
@@ -171,7 +161,7 @@ static HRESULT WINAPI DSOUND_QueryInterf
     return E_NOINTERFACE;
 }
 
-static HRESULT WINAPI DSOUND_QueryInterface8(
+static HRESULT DSOUND_QueryInterface8(
     LPDIRECTSOUND8 iface,
     REFIID riid,
     LPVOID * ppobj)
@@ -227,7 +217,7 @@ static HRESULT WINAPI DSOUND_QueryInterf
     return E_NOINTERFACE;
 }
 
-static ULONG WINAPI IDirectSoundImpl_AddRef(
+static ULONG IDirectSoundImpl_AddRef(
     LPDIRECTSOUND8 iface)
 {
     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
@@ -236,7 +226,7 @@ static ULONG WINAPI IDirectSoundImpl_Add
     return ref;
 }
 
-static ULONG WINAPI IDirectSoundImpl_Release(
+static ULONG IDirectSoundImpl_Release(
     LPDIRECTSOUND8 iface)
 {
     IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
@@ -252,1511 +242,1460 @@ static ULONG WINAPI IDirectSoundImpl_Rel
     return ref;
 }
 
-static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
+HRESULT IDirectSoundImpl_Create(
+    LPDIRECTSOUND8 * ppDS)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    FIXME("shouldn't be called directly\n");
-    return DSERR_GENERIC;
+    IDirectSoundImpl* pDS;
+    TRACE("(%p)\n",ppDS);
+
+    /* Allocate memory */
+    pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
+    if (pDS == NULL) {
+        WARN("out of memory\n");
+        *ppDS = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
+
+    pDS->ref    = 0;
+    pDS->device = NULL;
+
+    *ppDS = (LPDIRECTSOUND8)pDS;
+
+    return DS_OK;
 }
 
-static HRESULT WINAPI DSOUND_CreateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk,
-    BOOL from8)
+/*******************************************************************************
+ *		IDirectSound_IUnknown
+ */
+static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
+    LPUNKNOWN iface,
+    REFIID riid,
+    LPVOID * ppobj)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    HRESULT hres = DS_OK;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface(This->pds, riid, ppobj);
+}
 
-    if (This == NULL) {
-        WARN("invalid parameter: This == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+static ULONG WINAPI IDirectSound_IUnknown_AddRef(
+    LPUNKNOWN iface)
+{
+    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref - 1);
+    return ref;
+}
 
-    if (This->device == NULL) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
+static ULONG WINAPI IDirectSound_IUnknown_Release(
+    LPUNKNOWN iface)
+{
+    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref + 1);
+    if (!ref) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
+    return ref;
+}
 
-    if (dsbd == NULL) {
-        WARN("invalid parameter: dsbd == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+static const IUnknownVtbl DirectSound_Unknown_Vtbl =
+{
+    IDirectSound_IUnknown_QueryInterface,
+    IDirectSound_IUnknown_AddRef,
+    IDirectSound_IUnknown_Release
+};
 
-    if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
-        dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
-        WARN("invalid parameter: dsbd\n");
+HRESULT IDirectSound_IUnknown_Create(
+    LPDIRECTSOUND8 pds,
+    LPUNKNOWN * ppunk)
+{
+    IDirectSound_IUnknown * pdsunk;
+    TRACE("(%p,%p)\n",pds,ppunk);
+
+    if (ppunk == NULL) {
+        ERR("invalid parameter: ppunk == NULL\n");
         return DSERR_INVALIDPARAM;
     }
 
-    if (ppdsb == NULL) {
-        WARN("invalid parameter: ppdsb == NULL\n");
+    if (pds == NULL) {
+        ERR("invalid parameter: pds == NULL\n");
+        *ppunk = NULL;
         return DSERR_INVALIDPARAM;
     }
 
-    if (TRACE_ON(dsound)) {
-        TRACE("(structsize=%ld)\n",dsbd->dwSize);
-        TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
-        _dump_DSBCAPS(dsbd->dwFlags);
-        DPRINTF(")\n");
-        TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
-        TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
+    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
+    if (pdsunk == NULL) {
+        WARN("out of memory\n");
+        *ppunk = NULL;
+        return DSERR_OUTOFMEMORY;
     }
 
-    if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
-        if (dsbd->lpwfxFormat != NULL) {
-            WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
-                 "primary buffer\n");
-            return DSERR_INVALIDPARAM;
-        }
+    pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
+    pdsunk->ref = 0;
+    pdsunk->pds = pds;
 
-        if (This->device->primary) {
-            WARN("Primary Buffer already created\n");
-            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
-            *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
-        } else {
-           This->device->dsbd = *dsbd;
-           hres = PrimaryBufferImpl_Create(This->device, (PrimaryBufferImpl**)&(This->device->primary), &(This->device->dsbd));
-           if (This->device->primary) {
-               IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary));
-               *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary);
-           } else
-               WARN("PrimaryBufferImpl_Create failed\n");
-        }
-    } else {
-        IDirectSoundBufferImpl * dsb;
+    IDirectSoundImpl_AddRef(pds);
+    *ppunk = (LPUNKNOWN)pdsunk;
 
-        if (dsbd->lpwfxFormat == NULL) {
-            WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
-                 "secondary buffer\n");
-            return DSERR_INVALIDPARAM;
-        }
+    return DS_OK;
+}
 
-        TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
-              "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
-              dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
-              dsbd->lpwfxFormat->nSamplesPerSec,
-              dsbd->lpwfxFormat->nAvgBytesPerSec,
-              dsbd->lpwfxFormat->nBlockAlign,
-              dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
+/*******************************************************************************
+ *		IDirectSound_IDirectSound
+ */
+static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
+    LPDIRECTSOUND iface,
+    REFIID riid,
+    LPVOID * ppobj)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface(This->pds, riid, ppobj);
+}
 
-        if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
-            WARN("invalid parameter: 3D buffer format must be mono\n");
-            return DSERR_INVALIDPARAM;
-        }
+static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
+    LPDIRECTSOUND iface)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref - 1);
+    return ref;
+}
 
-        hres = IDirectSoundBufferImpl_Create(This->device, (IDirectSoundBufferImpl**)&dsb, dsbd);
-        if (dsb) {
-            hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
-            if (*ppdsb) {
-                dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
-                IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
-            } else
-                WARN("SecondaryBufferImpl_Create failed\n");
-        } else
-           WARN("IDirectSoundBufferImpl_Create failed\n");
-   }
+static ULONG WINAPI IDirectSound_IDirectSound_Release(
+    LPDIRECTSOUND iface)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref + 1);
+    if (!ref) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
+    }
+    return ref;
+}
 
-   return hres;
+static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
+    LPDIRECTSOUND iface,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+    return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_GetCaps(
-    LPDIRECTSOUND8 iface,
+static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
+    LPDIRECTSOUND iface,
     LPDSCAPS lpDSCaps)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    DirectSoundDevice *device;
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
     TRACE("(%p,%p)\n",This,lpDSCaps);
+    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
+}
 
-    if (This == NULL) {
-        WARN("invalid parameter: This == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    device = This->device;
+static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
+    LPDIRECTSOUND iface,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
+}
 
-    if (device == NULL) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
+static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
+    LPDIRECTSOUND iface,
+    HWND hwnd,
+    DWORD level)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+    return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
+}
 
-    if (lpDSCaps == NULL) {
-        WARN("invalid parameter: lpDSCaps = NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
+    LPDIRECTSOUND iface)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p)\n", This);
+    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
+}
 
-    /* check if there is enough room */
-    if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
-        WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
-             lpDSCaps->dwSize, sizeof(*lpDSCaps));
-        return DSERR_INVALIDPARAM;
-    }
+static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
+    LPDIRECTSOUND iface,
+    LPDWORD lpdwSpeakerConfig)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
+}
 
-    lpDSCaps->dwFlags                           = device->drvcaps.dwFlags;
-    if (TRACE_ON(dsound)) {
-        TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
-        _dump_DSCAPS(lpDSCaps->dwFlags);
-        DPRINTF(")\n");
-    }
-    lpDSCaps->dwMinSecondarySampleRate          = device->drvcaps.dwMinSecondarySampleRate;
-    lpDSCaps->dwMaxSecondarySampleRate          = device->drvcaps.dwMaxSecondarySampleRate;
-    lpDSCaps->dwPrimaryBuffers                  = device->drvcaps.dwPrimaryBuffers;
-    lpDSCaps->dwMaxHwMixingAllBuffers           = device->drvcaps.dwMaxHwMixingAllBuffers;
-    lpDSCaps->dwMaxHwMixingStaticBuffers        = device->drvcaps.dwMaxHwMixingStaticBuffers;
-    lpDSCaps->dwMaxHwMixingStreamingBuffers     = device->drvcaps.dwMaxHwMixingStreamingBuffers;
-    lpDSCaps->dwFreeHwMixingAllBuffers          = device->drvcaps.dwFreeHwMixingAllBuffers;
-    lpDSCaps->dwFreeHwMixingStaticBuffers       = device->drvcaps.dwFreeHwMixingStaticBuffers;
-    lpDSCaps->dwFreeHwMixingStreamingBuffers    = device->drvcaps.dwFreeHwMixingStreamingBuffers;
-    lpDSCaps->dwMaxHw3DAllBuffers               = device->drvcaps.dwMaxHw3DAllBuffers;
-    lpDSCaps->dwMaxHw3DStaticBuffers            = device->drvcaps.dwMaxHw3DStaticBuffers;
-    lpDSCaps->dwMaxHw3DStreamingBuffers         = device->drvcaps.dwMaxHw3DStreamingBuffers;
-    lpDSCaps->dwFreeHw3DAllBuffers              = device->drvcaps.dwFreeHw3DAllBuffers;
-    lpDSCaps->dwFreeHw3DStaticBuffers           = device->drvcaps.dwFreeHw3DStaticBuffers;
-    lpDSCaps->dwFreeHw3DStreamingBuffers        = device->drvcaps.dwFreeHw3DStreamingBuffers;
-    lpDSCaps->dwTotalHwMemBytes                 = device->drvcaps.dwTotalHwMemBytes;
-    lpDSCaps->dwFreeHwMemBytes                  = device->drvcaps.dwFreeHwMemBytes;
-    lpDSCaps->dwMaxContigFreeHwMemBytes         = device->drvcaps.dwMaxContigFreeHwMemBytes;
-
-    /* driver doesn't have these */
-    lpDSCaps->dwUnlockTransferRateHwBuffers     = 4096; /* But we have none... */
-    lpDSCaps->dwPlayCpuOverheadSwBuffers        = 1;    /* 1% */
-
-    return DS_OK;
+static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
+    LPDIRECTSOUND iface,
+    DWORD config)
+{
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p,0x%08lx)\n",This,config);
+    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
+static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
+    LPDIRECTSOUND iface,
+    LPCGUID lpcGuid)
 {
-    IDirectSoundBufferImpl* dsb;
-    HRESULT hres = DS_OK;
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
+    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
+}
 
-    if (This == NULL) {
-        WARN("invalid parameter: This == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
+{
+    IDirectSound_IDirectSound_QueryInterface,
+    IDirectSound_IDirectSound_AddRef,
+    IDirectSound_IDirectSound_Release,
+    IDirectSound_IDirectSound_CreateSoundBuffer,
+    IDirectSound_IDirectSound_GetCaps,
+    IDirectSound_IDirectSound_DuplicateSoundBuffer,
+    IDirectSound_IDirectSound_SetCooperativeLevel,
+    IDirectSound_IDirectSound_Compact,
+    IDirectSound_IDirectSound_GetSpeakerConfig,
+    IDirectSound_IDirectSound_SetSpeakerConfig,
+    IDirectSound_IDirectSound_Initialize
+};
 
-    if (This->device == NULL) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
+HRESULT IDirectSound_IDirectSound_Create(
+    LPDIRECTSOUND8  pds,
+    LPDIRECTSOUND * ppds)
+{
+    IDirectSound_IDirectSound * pdsds;
+    TRACE("(%p,%p)\n",pds,ppds);
 
-    if (psb == NULL) {
-        WARN("invalid parameter: psb == NULL\n");
+    if (ppds == NULL) {
+        ERR("invalid parameter: ppds == NULL\n");
         return DSERR_INVALIDPARAM;
     }
 
-    if (ppdsb == NULL) {
-        WARN("invalid parameter: ppdsb == NULL\n");
+    if (pds == NULL) {
+        ERR("invalid parameter: pds == NULL\n");
+        *ppds = NULL;
         return DSERR_INVALIDPARAM;
     }
 
-    /* make sure we have a secondary buffer */
-    if ((PrimaryBufferImpl *)psb == This->device->primary) {
-        WARN("trying to duplicate primary buffer\n");
-        *ppdsb = NULL;
-        return DSERR_INVALIDCALL;
+    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+    if (pdsds == NULL) {
+        WARN("out of memory\n");
+        *ppds = NULL;
+        return DSERR_OUTOFMEMORY;
     }
 
-    /* duplicate the actual buffer implementation */
-    hres = IDirectSoundBufferImpl_Duplicate(This->device, &dsb,
-                                           ((SecondaryBufferImpl *)psb)->dsb);
+    pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
+    pdsds->ref = 0;
+    pdsds->pds = pds;
 
-    if (hres == DS_OK) {
-        hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
-        if (*ppdsb) {
-            dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
-            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
-        } else
-            WARN("SecondaryBufferImpl_Create failed\n");
-    }
+    IDirectSoundImpl_AddRef(pds);
+    *ppds = (LPDIRECTSOUND)pdsds;
 
-    return hres;
+    return DS_OK;
 }
 
-static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
-    LPDIRECTSOUND8 iface,
-    HWND hwnd,
-    DWORD level)
+/*******************************************************************************
+ *		IDirectSound8_IUnknown
+ */
+static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
+    LPUNKNOWN iface,
+    REFIID riid,
+    LPVOID * ppobj)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-
-    if (This->device == NULL) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
-
-    if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
-        WARN("level=%s not fully supported\n",
-             level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
-    }
-
-    This->device->priolevel = level;
-    return DS_OK;
+    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
 }
 
-static HRESULT WINAPI IDirectSoundImpl_Compact(
-    LPDIRECTSOUND8 iface)
+static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
+    LPUNKNOWN iface)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p)\n",This);
-
-    if (This->device == NULL) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
+    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref - 1);
+    return ref;
+}
 
-    if (This->device->priolevel != DSSCL_PRIORITY) {
-        WARN("incorrect priority level\n");
-        return DSERR_PRIOLEVELNEEDED;
+static ULONG WINAPI IDirectSound8_IUnknown_Release(
+    LPUNKNOWN iface)
+{
+    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref + 1);
+    if (!ref) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
-
-    return DS_OK;
+    return ref;
 }
 
-static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
-    LPDWORD lpdwSpeakerConfig)
+static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p, %p)\n",This,lpdwSpeakerConfig);
+    IDirectSound8_IUnknown_QueryInterface,
+    IDirectSound8_IUnknown_AddRef,
+    IDirectSound8_IUnknown_Release
+};
 
-    if (This->device == NULL) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
+HRESULT IDirectSound8_IUnknown_Create(
+    LPDIRECTSOUND8 pds,
+    LPUNKNOWN * ppunk)
+{
+    IDirectSound8_IUnknown * pdsunk;
+    TRACE("(%p,%p)\n",pds,ppunk);
+
+    if (ppunk == NULL) {
+        ERR("invalid parameter: ppunk == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
 
-    if (lpdwSpeakerConfig == NULL) {
-        WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
+    if (pds == NULL) {
+        ERR("invalid parameter: pds == NULL\n");
+        *ppunk = NULL;
         return DSERR_INVALIDPARAM;
     }
 
-    WARN("not fully functional\n");
-    *lpdwSpeakerConfig = This->device->speaker_config;
-    return DS_OK;
-}
+    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
+    if (pdsunk == NULL) {
+        WARN("out of memory\n");
+        *ppunk = NULL;
+        return DSERR_OUTOFMEMORY;
+    }
 
-static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
-    DWORD config)
-{
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p,0x%08lx)\n",This,config);
+    pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
+    pdsunk->ref = 0;
+    pdsunk->pds = pds;
 
-    if (This->device == NULL) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
+    IDirectSoundImpl_AddRef(pds);
+    *ppunk = (LPUNKNOWN)pdsunk;
 
-    This->device->speaker_config = config;
-    WARN("not fully functional\n");
     return DS_OK;
 }
 
-static HRESULT WINAPI IDirectSoundImpl_Initialize(
-    LPDIRECTSOUND8 iface,
-    LPCGUID lpcGUID)
+/*******************************************************************************
+ *		IDirectSound8_IDirectSound
+ */
+static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
+    LPDIRECTSOUND iface,
+    REFIID riid,
+    LPVOID * ppobj)
 {
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    DirectSoundDevice *device = This->device;
-    HRESULT hr = DS_OK;
-    unsigned wod, wodn;
-    BOOLEAN found = FALSE;
-    GUID devGUID;
-    TRACE("(%p,%s)\n",This,debugstr_guid(lpcGUID));
-
-    if (device != NULL) {
-        WARN("already initialized\n");
-        return DSERR_ALREADYINITIALIZED;
-    }
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
+}
 
-    /* Default device? */
-    if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
-        lpcGUID = &DSDEVID_DefaultPlayback;
+static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
+    LPDIRECTSOUND iface)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref - 1);
+    return ref;
+}
 
-    if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
-        WARN("invalid parameter: lpcGUID\n");
-        return DSERR_INVALIDPARAM;
-    }
-
-    /* Enumerate WINMM audio devices and find the one we want */
-    wodn = waveOutGetNumDevs();
-    if (!wodn) {
-        WARN("no driver\n");
-        return DSERR_NODRIVER;
+static ULONG WINAPI IDirectSound8_IDirectSound_Release(
+    LPDIRECTSOUND iface)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref + 1);
+    if (!ref) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
+    return ref;
+}
 
-    for (wod=0; wod<wodn; wod++) {
-        if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
-            found = TRUE;
-            break;
-        }
-    }
+static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
+    LPDIRECTSOUND iface,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+    return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
+}
 
-    if (found == FALSE) {
-        WARN("No device found matching given ID!\n");
-        return DSERR_NODRIVER;
-    }
+static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
+    LPDIRECTSOUND iface,
+    LPDSCAPS lpDSCaps)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p,%p)\n",This,lpDSCaps);
+    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
+}
 
-    if (DSOUND_renderer[wod]) {
-        if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
-            device = DSOUND_renderer[wod];
-            DirectSoundDevice_AddRef(device);
-            This->device = device;
-            return DS_OK;
-        } else {
-            ERR("device GUID doesn't match\n");
-            hr = DSERR_GENERIC;
-            return hr;
-        }
-    } else {
-        hr = DirectSoundDevice_Create(&(device));
-        if (hr != DS_OK) {
-            WARN("DirectSoundDevice_Create failed\n");
-            return hr;
-        }
-    }
+static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
+    LPDIRECTSOUND iface,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
+}
 
-    This->device = device;
-    device->guid = devGUID;
+static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
+    LPDIRECTSOUND iface,
+    HWND hwnd,
+    DWORD level)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+    return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
+}
 
-    /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
-    waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
+static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
+    LPDIRECTSOUND iface)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p)\n", This);
+    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
+}
 
-    /* Disable the direct sound driver to force emulation if requested. */
-    if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
-        device->driver = NULL;
+static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
+    LPDIRECTSOUND iface,
+    LPDWORD lpdwSpeakerConfig)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
+}
 
-    /* Get driver description */
-    if (device->driver) {
-        hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
-        if (hr != DS_OK) {
-            WARN("IDsDriver_GetDriverDesc failed\n");
-            return hr;
-        }
-    } else {
-        /* if no DirectSound interface available, use WINMM API instead */
-        device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
-    }
+static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
+    LPDIRECTSOUND iface,
+    DWORD config)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p,0x%08lx)\n",This,config);
+    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
+}
 
-    device->drvdesc.dnDevNode = wod;
+static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
+    LPDIRECTSOUND iface,
+    LPCGUID lpcGuid)
+{
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
+}
 
-    /* If the driver requests being opened through MMSYSTEM
-     * (which is recommended by the DDK), it is supposed to happen
-     * before the DirectSound interface is opened */
-    if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
-    {
-        DWORD flags = CALLBACK_FUNCTION;
+static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
+{
+    IDirectSound8_IDirectSound_QueryInterface,
+    IDirectSound8_IDirectSound_AddRef,
+    IDirectSound8_IDirectSound_Release,
+    IDirectSound8_IDirectSound_CreateSoundBuffer,
+    IDirectSound8_IDirectSound_GetCaps,
+    IDirectSound8_IDirectSound_DuplicateSoundBuffer,
+    IDirectSound8_IDirectSound_SetCooperativeLevel,
+    IDirectSound8_IDirectSound_Compact,
+    IDirectSound8_IDirectSound_GetSpeakerConfig,
+    IDirectSound8_IDirectSound_SetSpeakerConfig,
+    IDirectSound8_IDirectSound_Initialize
+};
 
-        /* disable direct sound if requested */
-        if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
-            flags |= WAVE_DIRECTSOUND;
+HRESULT IDirectSound8_IDirectSound_Create(
+    LPDIRECTSOUND8 pds,
+    LPDIRECTSOUND * ppds)
+{
+    IDirectSound8_IDirectSound * pdsds;
+    TRACE("(%p,%p)\n",pds,ppds);
 
-        hr = mmErr(waveOutOpen(&(device->hwo),
-                                device->drvdesc.dnDevNode, device->pwfx,
-                                (DWORD_PTR)DSOUND_callback, (DWORD)device,
-                                flags));
-        if (hr != DS_OK) {
-            WARN("waveOutOpen failed\n");
-            return hr;
-        }
+    if (ppds == NULL) {
+        ERR("invalid parameter: ppds == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
 
-    if (device->driver) {
-        hr = IDsDriver_Open(device->driver);
-        if (hr != DS_OK) {
-            WARN("IDsDriver_Open failed\n");
-            return hr;
-        }
-
-        /* the driver is now open, so it's now allowed to call GetCaps */
-        hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
-        if (hr != DS_OK) {
-            WARN("IDsDriver_GetCaps failed\n");
-            return hr;
-        }
-    } else {
-        WAVEOUTCAPSA woc;
-        hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
-        if (hr != DS_OK) {
-            WARN("waveOutGetDevCaps failed\n");
-            return hr;
-        }
-        ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
-        if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
-            (woc.dwFormats & WAVE_FORMAT_2M08) ||
-            (woc.dwFormats & WAVE_FORMAT_4M08) ||
-            (woc.dwFormats & WAVE_FORMAT_48M08) ||
-            (woc.dwFormats & WAVE_FORMAT_96M08)) {
-            device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
-            device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
-        }
-        if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
-            (woc.dwFormats & WAVE_FORMAT_2M16) ||
-            (woc.dwFormats & WAVE_FORMAT_4M16) ||
-            (woc.dwFormats & WAVE_FORMAT_48M16) ||
-            (woc.dwFormats & WAVE_FORMAT_96M16)) {
-            device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
-            device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
-        }
-        if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
-            (woc.dwFormats & WAVE_FORMAT_2S08) ||
-            (woc.dwFormats & WAVE_FORMAT_4S08) ||
-            (woc.dwFormats & WAVE_FORMAT_48S08) ||
-            (woc.dwFormats & WAVE_FORMAT_96S08)) {
-            device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
-            device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
-        }
-        if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
-            (woc.dwFormats & WAVE_FORMAT_2S16) ||
-            (woc.dwFormats & WAVE_FORMAT_4S16) ||
-            (woc.dwFormats & WAVE_FORMAT_48S16) ||
-            (woc.dwFormats & WAVE_FORMAT_96S16)) {
-            device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
-            device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
-        }
-        if (ds_emuldriver)
-            device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
-        device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
-        device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
-        device->drvcaps.dwPrimaryBuffers = 1;
+    if (pds == NULL) {
+        ERR("invalid parameter: pds == NULL\n");
+        *ppds = NULL;
+        return DSERR_INVALIDPARAM;
     }
 
-    hr = DSOUND_PrimaryCreate(device);
-    if (hr == DS_OK) {
-        DSOUND_renderer[device->drvdesc.dnDevNode] = device;
-        timeBeginPeriod(DS_TIME_RES);
-        DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
-            (DWORD_PTR)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
-    } else {
-        WARN("DSOUND_PrimaryCreate failed\n");
+    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+    if (pdsds == NULL) {
+        WARN("out of memory\n");
+        *ppds = NULL;
+        return DSERR_OUTOFMEMORY;
     }
 
-    return hr;
-}
-
-static HRESULT WINAPI IDirectSoundImpl_VerifyCertification(
-    LPDIRECTSOUND8 iface,
-    LPDWORD pdwCertified)
-{
-    IDirectSoundImpl *This = (IDirectSoundImpl *)iface;
-    TRACE("(%p, %p)\n",This,pdwCertified);
+    pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
+    pdsds->ref = 0;
+    pdsds->pds = pds;
 
-    if (This->device == NULL) {
-        WARN("not initialized\n");
-        return DSERR_UNINITIALIZED;
-    }
+    IDirectSoundImpl_AddRef(pds);
+    *ppds = (LPDIRECTSOUND)pdsds;
 
-    if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
-        *pdwCertified = DS_CERTIFIED;
-    else
-        *pdwCertified = DS_UNCERTIFIED;
     return DS_OK;
 }
 
-static const IDirectSound8Vtbl IDirectSoundImpl_Vtbl =
+/*******************************************************************************
+ *		IDirectSound8_IDirectSound8
+ */
+static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
+    LPDIRECTSOUND8 iface,
+    REFIID riid,
+    LPVOID * ppobj)
 {
-    IDirectSoundImpl_QueryInterface,
-    IDirectSoundImpl_AddRef,
-    IDirectSoundImpl_Release,
-    IDirectSoundImpl_CreateSoundBuffer,
-    IDirectSoundImpl_GetCaps,
-    IDirectSoundImpl_DuplicateSoundBuffer,
-    IDirectSoundImpl_SetCooperativeLevel,
-    IDirectSoundImpl_Compact,
-    IDirectSoundImpl_GetSpeakerConfig,
-    IDirectSoundImpl_SetSpeakerConfig,
-    IDirectSoundImpl_Initialize,
-    IDirectSoundImpl_VerifyCertification
-};
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
+    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
+}
 
-HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
+static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
+    LPDIRECTSOUND8 iface)
 {
-    DirectSoundDevice * device;
-    TRACE("(%p)\n", ppDevice);
-
-    /* Allocate memory */
-    device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
-    if (device == NULL) {
-        WARN("out of memory\n");
-        return DSERR_OUTOFMEMORY;
-    }
-
-    device->ref            = 1;
-    device->driver         = NULL;
-    device->priolevel      = DSSCL_NORMAL;
-    device->fraglen        = 0;
-    device->hwbuf          = NULL;
-    device->buffer         = NULL;
-    device->buflen         = 0;
-    device->writelead      = 0;
-    device->state          = STATE_STOPPED;
-    device->nrofbuffers    = 0;
-    device->buffers        = NULL;
-    device->primary        = NULL;
-    device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
-    device->tmp_buffer     = NULL;
-    device->tmp_buffer_len = 0;
-
-    /* 3D listener initial parameters */
-    device->listener       = NULL;
-    device->ds3dl.dwSize   = sizeof(DS3DLISTENER);
-    device->ds3dl.vPosition.x = 0.0;
-    device->ds3dl.vPosition.y = 0.0;
-    device->ds3dl.vPosition.z = 0.0;
-    device->ds3dl.vVelocity.x = 0.0;
-    device->ds3dl.vVelocity.y = 0.0;
-    device->ds3dl.vVelocity.z = 0.0;
-    device->ds3dl.vOrientFront.x = 0.0;
-    device->ds3dl.vOrientFront.y = 0.0;
-    device->ds3dl.vOrientFront.z = 1.0;
-    device->ds3dl.vOrientTop.x = 0.0;
-    device->ds3dl.vOrientTop.y = 1.0;
-    device->ds3dl.vOrientTop.z = 0.0;
-    device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
-    device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
-    device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
-
-    device->prebuf         = ds_snd_queue_max;
-    device->guid           = GUID_NULL;
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    ULONG ref = InterlockedIncrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref - 1);
+    return ref;
+}
 
-    /* Set default wave format (may need it for waveOutOpen) */
-    device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
-    if (device->pwfx == NULL) {
-        WARN("out of memory\n");
-        HeapFree(GetProcessHeap(),0,device);
-        return DSERR_OUTOFMEMORY;
+static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
+    LPDIRECTSOUND8 iface)
+{
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    ULONG ref = InterlockedDecrement(&(This->ref));
+    TRACE("(%p) ref was %ld\n", This, ref + 1);
+    if (!ref) {
+        IDirectSoundImpl_Release(This->pds);
+        HeapFree(GetProcessHeap(), 0, This);
+        TRACE("(%p) released\n", This);
     }
+    return ref;
+}
 
-    /* We rely on the sound driver to return the actual sound format of
-     * the device if it does not support 22050x8x2 and is given the
-     * WAVE_DIRECTSOUND flag.
-     */
-    device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
-    device->pwfx->nSamplesPerSec = 22050;
-    device->pwfx->wBitsPerSample = 8;
-    device->pwfx->nChannels = 2;
-    device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
-    device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
-    device->pwfx->cbSize = 0;
-
-    InitializeCriticalSection(&(device->mixlock));
-    device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUND_mixlock";
-
-    RtlInitializeResource(&(device->buffer_list_lock));
-
-   *ppDevice = device;
-
-    return DS_OK;
+static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
+    LPDIRECTSOUND8 iface,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk)
+{
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
+    return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE);
 }
 
-ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
+static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
+    LPDIRECTSOUND8 iface,
+    LPDSCAPS lpDSCaps)
 {
-    ULONG ref = InterlockedIncrement(&(device->ref));
-    TRACE("(%p) ref was %ld\n", device, ref - 1);
-    return ref;
+    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
+    TRACE("(%p,%p)\n",This,lpDSCaps);
+    return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps);
 }
 
-ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
+static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
+    LPDIRECTSOUND8 iface,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
 {
-    HRESULT hr;
-    ULONG ref = InterlockedDecrement(&(device->ref));
-    TRACE("(%p) ref was %lu\n", device, ref + 1);
-    if (!ref) {
-        int i;
-        timeKillEvent(device->timerID);
-        timeEndPeriod(DS_TIME_RES);
-        /* wait for timer to expire */
-        Sleep(DS_TIME_RES+1);
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
+    return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb);
+}
 
-        /* The sleep above should have allowed the timer process to expire
-         * but try to grab the lock just in case. Can't hold lock because
-         * IDirectSoundBufferImpl_Destroy also grabs the lock */
-        RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
-        RtlReleaseResource(&(device->buffer_list_lock));
+static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
+    LPDIRECTSOUND8 iface,
+    HWND hwnd,
+    DWORD level)
+{
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
+    return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level);
+}
 
-        /* It is allowed to release this object even when buffers are playing */
-        if (device->buffers) {
-            WARN("%d secondary buffers not released\n", device->nrofbuffers);
-            for( i=0;i<device->nrofbuffers;i++)
-                IDirectSoundBufferImpl_Destroy(device->buffers[i]);
-        }
+static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
+    LPDIRECTSOUND8 iface)
+{
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p)\n", This);
+    return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device);
+}
 
-        if (device->primary) {
-            WARN("primary buffer not released\n");
-            IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
-        }
+static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
+    LPDIRECTSOUND8 iface,
+    LPDWORD lpdwSpeakerConfig)
+{
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
+    return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig);
+}
 
-        hr = DSOUND_PrimaryDestroy(device);
-        if (hr != DS_OK)
-            WARN("DSOUND_PrimaryDestroy failed\n");
+static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
+    LPDIRECTSOUND8 iface,
+    DWORD config)
+{
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p,0x%08lx)\n",This,config);
+    return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config);
+}
 
-        if (device->driver)
-            IDsDriver_Close(device->driver);
+static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
+    LPDIRECTSOUND8 iface,
+    LPCGUID lpcGuid)
+{
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
+    return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid);
+}
 
-        if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
-            waveOutClose(device->hwo);
+static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
+    LPDIRECTSOUND8 iface,
+    LPDWORD pdwCertified)
+{
+    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
+    TRACE("(%p, %p)\n", This, pdwCertified);
+    return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified);
+}
 
-        if (device->driver)
-            IDsDriver_Release(device->driver);
+static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
+{
+    IDirectSound8_IDirectSound8_QueryInterface,
+    IDirectSound8_IDirectSound8_AddRef,
+    IDirectSound8_IDirectSound8_Release,
+    IDirectSound8_IDirectSound8_CreateSoundBuffer,
+    IDirectSound8_IDirectSound8_GetCaps,
+    IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
+    IDirectSound8_IDirectSound8_SetCooperativeLevel,
+    IDirectSound8_IDirectSound8_Compact,
+    IDirectSound8_IDirectSound8_GetSpeakerConfig,
+    IDirectSound8_IDirectSound8_SetSpeakerConfig,
+    IDirectSound8_IDirectSound8_Initialize,
+    IDirectSound8_IDirectSound8_VerifyCertification
+};
 
-        DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
+HRESULT IDirectSound8_IDirectSound8_Create(
+    LPDIRECTSOUND8 pds,
+    LPDIRECTSOUND8 * ppds)
+{
+    IDirectSound8_IDirectSound8 * pdsds;
+    TRACE("(%p,%p)\n",pds,ppds);
 
-	HeapFree(GetProcessHeap(),0,device->tmp_buffer);
-	HeapFree(GetProcessHeap(),0,device->buffer);
-        RtlDeleteResource(&device->buffer_list_lock);
-        device->mixlock.DebugInfo->Spare[0] = 0;
-        DeleteCriticalSection(&device->mixlock);
-        HeapFree(GetProcessHeap(),0,device);
-        TRACE("(%p) released\n", device);
+    if (ppds == NULL) {
+        ERR("invalid parameter: ppds == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
-    return ref;
-}
 
-HRESULT IDirectSoundImpl_Create(
-    LPDIRECTSOUND8 * ppDS)
-{
-    IDirectSoundImpl* pDS;
-    TRACE("(%p)\n",ppDS);
+    if (pds == NULL) {
+        ERR("invalid parameter: pds == NULL\n");
+        *ppds = NULL;
+        return DSERR_INVALIDPARAM;
+    }
 
-    /* Allocate memory */
-    pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl));
-    if (pDS == NULL) {
+    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
+    if (pdsds == NULL) {
         WARN("out of memory\n");
-        *ppDS = NULL;
+        *ppds = NULL;
         return DSERR_OUTOFMEMORY;
     }
 
-    pDS->lpVtbl = &IDirectSoundImpl_Vtbl;
-    pDS->ref    = 0;
-    pDS->device = NULL;
+    pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
+    pdsds->ref = 0;
+    pdsds->pds = pds;
 
-    *ppDS = (LPDIRECTSOUND8)pDS;
+    IDirectSoundImpl_AddRef(pds);
+    *ppds = (LPDIRECTSOUND8)pdsds;
 
     return DS_OK;
 }
 
-/*******************************************************************************
- *		IDirectSound_IUnknown
- */
-static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface(
-    LPUNKNOWN iface,
-    REFIID riid,
-    LPVOID * ppobj)
+HRESULT DSOUND_Create(
+    LPDIRECTSOUND *ppDS,
+    IUnknown *pUnkOuter)
 {
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface(This->pds, riid, ppobj);
-}
+    LPDIRECTSOUND8 pDS;
+    HRESULT hr;
+    TRACE("(%p,%p)\n",ppDS,pUnkOuter);
 
-static ULONG WINAPI IDirectSound_IUnknown_AddRef(
-    LPUNKNOWN iface)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref - 1);
-    return ref;
-}
+    /* Get dsound configuration */
+    setup_dsound_options();
 
-static ULONG WINAPI IDirectSound_IUnknown_Release(
-    LPUNKNOWN iface)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
+    hr = IDirectSoundImpl_Create(&pDS);
+    if (hr == DS_OK) {
+        hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
+        if (*ppDS)
+            IDirectSound_IDirectSound_AddRef(*ppDS);
+        else {
+            WARN("IDirectSound_IDirectSound_Create failed\n");
+            IDirectSound8_Release(pDS);
+        }
+    } else {
+        WARN("IDirectSoundImpl_Create failed\n");
+        *ppDS = 0;
     }
-    return ref;
+
+    return hr;
 }
 
-static const IUnknownVtbl DirectSound_Unknown_Vtbl =
+/*******************************************************************************
+ *		DirectSoundCreate (DSOUND.1)
+ *
+ *  Creates and initializes a DirectSound interface.
+ *
+ *  PARAMS
+ *     lpcGUID   [I] Address of the GUID that identifies the sound device.
+ *     ppDS      [O] Address of a variable to receive the interface pointer.
+ *     pUnkOuter [I] Must be NULL.
+ *
+ *  RETURNS
+ *     Success: DS_OK
+ *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
+ *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
+ */
+HRESULT WINAPI DirectSoundCreate(
+    LPCGUID lpcGUID,
+    LPDIRECTSOUND *ppDS,
+    IUnknown *pUnkOuter)
 {
-    IDirectSound_IUnknown_QueryInterface,
-    IDirectSound_IUnknown_AddRef,
-    IDirectSound_IUnknown_Release
-};
+    HRESULT hr;
+    LPDIRECTSOUND pDS;
 
-HRESULT IDirectSound_IUnknown_Create(
-    LPDIRECTSOUND8 pds,
-    LPUNKNOWN * ppunk)
-{
-    IDirectSound_IUnknown * pdsunk;
-    TRACE("(%p,%p)\n",pds,ppunk);
+    TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
 
-    if (ppunk == NULL) {
-        ERR("invalid parameter: ppunk == NULL\n");
+    if (ppDS == NULL) {
+        WARN("invalid parameter: ppDS == NULL\n");
         return DSERR_INVALIDPARAM;
     }
 
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppunk = NULL;
+    if (pUnkOuter != NULL) {
+        WARN("invalid parameter: pUnkOuter != NULL\n");
+        *ppDS = 0;
         return DSERR_INVALIDPARAM;
     }
 
-    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
-    if (pdsunk == NULL) {
-        WARN("out of memory\n");
-        *ppunk = NULL;
-        return DSERR_OUTOFMEMORY;
+    hr = DSOUND_Create(&pDS, pUnkOuter);
+    if (hr == DS_OK) {
+        hr = IDirectSound_Initialize(pDS, lpcGUID);
+        if (hr != DS_OK) {
+            if (hr != DSERR_ALREADYINITIALIZED) {
+                IDirectSound_Release(pDS);
+                pDS = 0;
+            } else
+                hr = DS_OK;
+        }
     }
 
-    pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl;
-    pdsunk->ref = 0;
-    pdsunk->pds = pds;
+    *ppDS = pDS;
 
-    IDirectSoundImpl_AddRef(pds);
-    *ppunk = (LPUNKNOWN)pdsunk;
+    return hr;
+}
 
-    return DS_OK;
+HRESULT DSOUND_Create8(
+    LPDIRECTSOUND8 *ppDS,
+    IUnknown *pUnkOuter)
+{
+    LPDIRECTSOUND8 pDS;
+    HRESULT hr;
+    TRACE("(%p,%p)\n",ppDS,pUnkOuter);
+
+    /* Get dsound configuration */
+    setup_dsound_options();
+
+    hr = IDirectSoundImpl_Create(&pDS);
+    if (hr == DS_OK) {
+        hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
+        if (*ppDS)
+            IDirectSound8_IDirectSound8_AddRef(*ppDS);
+        else {
+            WARN("IDirectSound8_IDirectSound8_Create failed\n");
+            IDirectSound8_Release(pDS);
+        }
+    } else {
+        WARN("IDirectSoundImpl_Create failed\n");
+        *ppDS = 0;
+    }
+
+    return hr;
 }
 
 /*******************************************************************************
- *		IDirectSound_IDirectSound
+ *        DirectSoundCreate8 (DSOUND.11)
+ *
+ *  Creates and initializes a DirectSound8 interface.
+ *
+ *  PARAMS
+ *     lpcGUID   [I] Address of the GUID that identifies the sound device.
+ *     ppDS      [O] Address of a variable to receive the interface pointer.
+ *     pUnkOuter [I] Must be NULL.
+ *
+ *  RETURNS
+ *     Success: DS_OK
+ *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
+ *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
  */
-static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface(
-    LPDIRECTSOUND iface,
-    REFIID riid,
-    LPVOID * ppobj)
+HRESULT WINAPI DirectSoundCreate8(
+    LPCGUID lpcGUID,
+    LPDIRECTSOUND8 *ppDS,
+    IUnknown *pUnkOuter)
 {
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface(This->pds, riid, ppobj);
-}
+    HRESULT hr;
+    LPDIRECTSOUND8 pDS;
 
-static ULONG WINAPI IDirectSound_IDirectSound_AddRef(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref - 1);
-    return ref;
-}
+    TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
 
-static ULONG WINAPI IDirectSound_IDirectSound_Release(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
+    if (ppDS == NULL) {
+        WARN("invalid parameter: ppDS == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
-    return ref;
-}
 
-static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE);
-}
+    if (pUnkOuter != NULL) {
+        WARN("invalid parameter: pUnkOuter != NULL\n");
+        *ppDS = 0;
+        return DSERR_INVALIDPARAM;
+    }
 
-static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps(
-    LPDIRECTSOUND iface,
-    LPDSCAPS lpDSCaps)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
-}
+    hr = DSOUND_Create8(&pDS, pUnkOuter);
+    if (hr == DS_OK) {
+        hr = IDirectSound8_Initialize(pDS, lpcGUID);
+        if (hr != DS_OK) {
+            if (hr != DSERR_ALREADYINITIALIZED) {
+                IDirectSound8_Release(pDS);
+                pDS = 0;
+            } else
+                hr = DS_OK;
+        }
+    }
 
-static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
-}
+    *ppDS = pDS;
 
-static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel(
-    LPDIRECTSOUND iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
+    return hr;
 }
 
-static HRESULT WINAPI IDirectSound_IDirectSound_Compact(
-    LPDIRECTSOUND iface)
+/*******************************************************************************
+ *        DirectSoundDevice
+ */
+HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice)
 {
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p)\n", This);
-    return IDirectSoundImpl_Compact(This->pds);
-}
+    DirectSoundDevice * device;
+    TRACE("(%p)\n", ppDevice);
 
-static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    DWORD config)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p,0x%08lx)\n",This,config);
-    return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
-}
-
-static HRESULT WINAPI IDirectSound_IDirectSound_Initialize(
-    LPDIRECTSOUND iface,
-    LPCGUID lpcGuid)
-{
-    IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
-}
-
-static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl =
-{
-    IDirectSound_IDirectSound_QueryInterface,
-    IDirectSound_IDirectSound_AddRef,
-    IDirectSound_IDirectSound_Release,
-    IDirectSound_IDirectSound_CreateSoundBuffer,
-    IDirectSound_IDirectSound_GetCaps,
-    IDirectSound_IDirectSound_DuplicateSoundBuffer,
-    IDirectSound_IDirectSound_SetCooperativeLevel,
-    IDirectSound_IDirectSound_Compact,
-    IDirectSound_IDirectSound_GetSpeakerConfig,
-    IDirectSound_IDirectSound_SetSpeakerConfig,
-    IDirectSound_IDirectSound_Initialize
-};
+    /* Allocate memory */
+    device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice));
+    if (device == NULL) {
+        WARN("out of memory\n");
+        return DSERR_OUTOFMEMORY;
+    }
 
-HRESULT IDirectSound_IDirectSound_Create(
-    LPDIRECTSOUND8  pds,
-    LPDIRECTSOUND * ppds)
-{
-    IDirectSound_IDirectSound * pdsds;
-    TRACE("(%p,%p)\n",pds,ppds);
+    device->ref            = 1;
+    device->driver         = NULL;
+    device->priolevel      = DSSCL_NORMAL;
+    device->fraglen        = 0;
+    device->hwbuf          = NULL;
+    device->buffer         = NULL;
+    device->buflen         = 0;
+    device->writelead      = 0;
+    device->state          = STATE_STOPPED;
+    device->nrofbuffers    = 0;
+    device->buffers        = NULL;
+    device->primary        = NULL;
+    device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16);
+    device->tmp_buffer     = NULL;
+    device->tmp_buffer_len = 0;
 
-    if (ppds == NULL) {
-        ERR("invalid parameter: ppds == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+    /* 3D listener initial parameters */
+    device->listener       = NULL;
+    device->ds3dl.dwSize   = sizeof(DS3DLISTENER);
+    device->ds3dl.vPosition.x = 0.0;
+    device->ds3dl.vPosition.y = 0.0;
+    device->ds3dl.vPosition.z = 0.0;
+    device->ds3dl.vVelocity.x = 0.0;
+    device->ds3dl.vVelocity.y = 0.0;
+    device->ds3dl.vVelocity.z = 0.0;
+    device->ds3dl.vOrientFront.x = 0.0;
+    device->ds3dl.vOrientFront.y = 0.0;
+    device->ds3dl.vOrientFront.z = 1.0;
+    device->ds3dl.vOrientTop.x = 0.0;
+    device->ds3dl.vOrientTop.y = 1.0;
+    device->ds3dl.vOrientTop.z = 0.0;
+    device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
+    device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
+    device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
 
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppds = NULL;
-        return DSERR_INVALIDPARAM;
-    }
+    device->prebuf         = ds_snd_queue_max;
+    device->guid           = GUID_NULL;
 
-    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
-    if (pdsds == NULL) {
+    /* Set default wave format (may need it for waveOutOpen) */
+    device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX));
+    if (device->pwfx == NULL) {
         WARN("out of memory\n");
-        *ppds = NULL;
+        HeapFree(GetProcessHeap(),0,device);
         return DSERR_OUTOFMEMORY;
     }
 
-    pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl;
-    pdsds->ref = 0;
-    pdsds->pds = pds;
+    /* We rely on the sound driver to return the actual sound format of
+     * the device if it does not support 22050x8x2 and is given the
+     * WAVE_DIRECTSOUND flag.
+     */
+    device->pwfx->wFormatTag = WAVE_FORMAT_PCM;
+    device->pwfx->nSamplesPerSec = 22050;
+    device->pwfx->wBitsPerSample = 8;
+    device->pwfx->nChannels = 2;
+    device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8;
+    device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign;
+    device->pwfx->cbSize = 0;
 
-    IDirectSoundImpl_AddRef(pds);
-    *ppds = (LPDIRECTSOUND)pdsds;
+    InitializeCriticalSection(&(device->mixlock));
+    device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUND_mixlock";
 
-    return DS_OK;
-}
+    RtlInitializeResource(&(device->buffer_list_lock));
 
-/*******************************************************************************
- *		IDirectSound8_IUnknown
- */
-static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface(
-    LPUNKNOWN iface,
-    REFIID riid,
-    LPVOID * ppobj)
-{
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
+   *ppDevice = device;
+
+    return DS_OK;
 }
 
-static ULONG WINAPI IDirectSound8_IUnknown_AddRef(
-    LPUNKNOWN iface)
+ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device)
 {
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref - 1);
+    ULONG ref = InterlockedIncrement(&(device->ref));
+    TRACE("(%p) ref was %ld\n", device, ref - 1);
     return ref;
 }
 
-static ULONG WINAPI IDirectSound8_IUnknown_Release(
-    LPUNKNOWN iface)
+ULONG DirectSoundDevice_Release(DirectSoundDevice * device)
 {
-    IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref + 1);
+    HRESULT hr;
+    ULONG ref = InterlockedDecrement(&(device->ref));
+    TRACE("(%p) ref was %lu\n", device, ref + 1);
     if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
+        int i;
+        timeKillEvent(device->timerID);
+        timeEndPeriod(DS_TIME_RES);
+        /* wait for timer to expire */
+        Sleep(DS_TIME_RES+1);
+
+        /* The sleep above should have allowed the timer process to expire
+         * but try to grab the lock just in case. Can't hold lock because
+         * IDirectSoundBufferImpl_Destroy also grabs the lock */
+        RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE);
+        RtlReleaseResource(&(device->buffer_list_lock));
+
+        /* It is allowed to release this object even when buffers are playing */
+        if (device->buffers) {
+            WARN("%d secondary buffers not released\n", device->nrofbuffers);
+            for( i=0;i<device->nrofbuffers;i++)
+                IDirectSoundBufferImpl_Destroy(device->buffers[i]);
+        }
+
+        if (device->primary) {
+            WARN("primary buffer not released\n");
+            IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary);
+        }
+
+        hr = DSOUND_PrimaryDestroy(device);
+        if (hr != DS_OK)
+            WARN("DSOUND_PrimaryDestroy failed\n");
+
+        if (device->driver)
+            IDsDriver_Close(device->driver);
+
+        if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+            waveOutClose(device->hwo);
+
+        if (device->driver)
+            IDsDriver_Release(device->driver);
+
+        DSOUND_renderer[device->drvdesc.dnDevNode] = NULL;
+
+        HeapFree(GetProcessHeap(),0,device->tmp_buffer);
+        HeapFree(GetProcessHeap(),0,device->buffer);
+        RtlDeleteResource(&device->buffer_list_lock);
+        device->mixlock.DebugInfo->Spare[0] = 0;
+        DeleteCriticalSection(&device->mixlock);
+        HeapFree(GetProcessHeap(),0,device);
+        TRACE("(%p) released\n", device);
     }
     return ref;
 }
 
-static const IUnknownVtbl DirectSound8_Unknown_Vtbl =
+HRESULT DirectSoundDevice_GetCaps(
+    DirectSoundDevice * device,
+    LPDSCAPS lpDSCaps)
 {
-    IDirectSound8_IUnknown_QueryInterface,
-    IDirectSound8_IUnknown_AddRef,
-    IDirectSound8_IUnknown_Release
-};
+    TRACE("(%p,%p)\n",device,lpDSCaps);
 
-HRESULT IDirectSound8_IUnknown_Create(
-    LPDIRECTSOUND8 pds,
-    LPUNKNOWN * ppunk)
-{
-    IDirectSound8_IUnknown * pdsunk;
-    TRACE("(%p,%p)\n",pds,ppunk);
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
 
-    if (ppunk == NULL) {
-        ERR("invalid parameter: ppunk == NULL\n");
+    if (lpDSCaps == NULL) {
+        WARN("invalid parameter: lpDSCaps = NULL\n");
         return DSERR_INVALIDPARAM;
     }
 
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppunk = NULL;
+    /* check if there is enough room */
+    if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) {
+        WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n",
+             lpDSCaps->dwSize, sizeof(*lpDSCaps));
         return DSERR_INVALIDPARAM;
     }
 
-    pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk));
-    if (pdsunk == NULL) {
-        WARN("out of memory\n");
-        *ppunk = NULL;
-        return DSERR_OUTOFMEMORY;
+    lpDSCaps->dwFlags                           = device->drvcaps.dwFlags;
+    if (TRACE_ON(dsound)) {
+        TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags);
+        _dump_DSCAPS(lpDSCaps->dwFlags);
+        DPRINTF(")\n");
     }
+    lpDSCaps->dwMinSecondarySampleRate          = device->drvcaps.dwMinSecondarySampleRate;
+    lpDSCaps->dwMaxSecondarySampleRate          = device->drvcaps.dwMaxSecondarySampleRate;
+    lpDSCaps->dwPrimaryBuffers                  = device->drvcaps.dwPrimaryBuffers;
+    lpDSCaps->dwMaxHwMixingAllBuffers           = device->drvcaps.dwMaxHwMixingAllBuffers;
+    lpDSCaps->dwMaxHwMixingStaticBuffers        = device->drvcaps.dwMaxHwMixingStaticBuffers;
+    lpDSCaps->dwMaxHwMixingStreamingBuffers     = device->drvcaps.dwMaxHwMixingStreamingBuffers;
+    lpDSCaps->dwFreeHwMixingAllBuffers          = device->drvcaps.dwFreeHwMixingAllBuffers;
+    lpDSCaps->dwFreeHwMixingStaticBuffers       = device->drvcaps.dwFreeHwMixingStaticBuffers;
+    lpDSCaps->dwFreeHwMixingStreamingBuffers    = device->drvcaps.dwFreeHwMixingStreamingBuffers;
+    lpDSCaps->dwMaxHw3DAllBuffers               = device->drvcaps.dwMaxHw3DAllBuffers;
+    lpDSCaps->dwMaxHw3DStaticBuffers            = device->drvcaps.dwMaxHw3DStaticBuffers;
+    lpDSCaps->dwMaxHw3DStreamingBuffers         = device->drvcaps.dwMaxHw3DStreamingBuffers;
+    lpDSCaps->dwFreeHw3DAllBuffers              = device->drvcaps.dwFreeHw3DAllBuffers;
+    lpDSCaps->dwFreeHw3DStaticBuffers           = device->drvcaps.dwFreeHw3DStaticBuffers;
+    lpDSCaps->dwFreeHw3DStreamingBuffers        = device->drvcaps.dwFreeHw3DStreamingBuffers;
+    lpDSCaps->dwTotalHwMemBytes                 = device->drvcaps.dwTotalHwMemBytes;
+    lpDSCaps->dwFreeHwMemBytes                  = device->drvcaps.dwFreeHwMemBytes;
+    lpDSCaps->dwMaxContigFreeHwMemBytes         = device->drvcaps.dwMaxContigFreeHwMemBytes;
 
-    pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl;
-    pdsunk->ref = 0;
-    pdsunk->pds = pds;
-
-    IDirectSoundImpl_AddRef(pds);
-    *ppunk = (LPUNKNOWN)pdsunk;
+    /* driver doesn't have these */
+    lpDSCaps->dwUnlockTransferRateHwBuffers     = 4096; /* But we have none... */
+    lpDSCaps->dwPlayCpuOverheadSwBuffers        = 1;    /* 1% */
 
     return DS_OK;
 }
 
-/*******************************************************************************
- *		IDirectSound8_IDirectSound
- */
-static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface(
-    LPDIRECTSOUND iface,
-    REFIID riid,
-    LPVOID * ppobj)
+HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID)
 {
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
-}
+    HRESULT hr = DS_OK;
+    unsigned wod, wodn;
+    BOOLEAN found = FALSE;
+    GUID devGUID;
+    DirectSoundDevice * device = *ppDevice;
+    TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID));
 
-static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref - 1);
-    return ref;
-}
+    if (*ppDevice != NULL) {
+        WARN("already initialized\n");
+        return DSERR_ALREADYINITIALIZED;
+    }
 
-static ULONG WINAPI IDirectSound8_IDirectSound_Release(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
+    /* Default device? */
+    if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL))
+        lpcGUID = &DSDEVID_DefaultPlayback;
+
+    if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) {
+        WARN("invalid parameter: lpcGUID\n");
+        return DSERR_INVALIDPARAM;
     }
-    return ref;
-}
 
-static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
-}
+    /* Enumerate WINMM audio devices and find the one we want */
+    wodn = waveOutGetNumDevs();
+    if (!wodn) {
+        WARN("no driver\n");
+        return DSERR_NODRIVER;
+    }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps(
-    LPDIRECTSOUND iface,
-    LPDSCAPS lpDSCaps)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
-}
+    for (wod=0; wod<wodn; wod++) {
+        if (IsEqualGUID( &devGUID, &DSOUND_renderer_guids[wod])) {
+            found = TRUE;
+            break;
+        }
+    }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer(
-    LPDIRECTSOUND iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
-}
+    if (found == FALSE) {
+        WARN("No device found matching given ID!\n");
+        return DSERR_NODRIVER;
+    }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel(
-    LPDIRECTSOUND iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
-}
+    if (DSOUND_renderer[wod]) {
+        if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) {
+            device = DSOUND_renderer[wod];
+            DirectSoundDevice_AddRef(device);
+            *ppDevice = device;
+            return DS_OK;
+        } else {
+            ERR("device GUID doesn't match\n");
+            hr = DSERR_GENERIC;
+            return hr;
+        }
+    } else {
+        hr = DirectSoundDevice_Create(&device);
+        if (hr != DS_OK) {
+            WARN("DirectSoundDevice_Create failed\n");
+            return hr;
+        }
+    }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound_Compact(
-    LPDIRECTSOUND iface)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p)\n", This);
-    return IDirectSoundImpl_Compact(This->pds);
-}
+    *ppDevice = device;
+    device->guid = devGUID;
 
-static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
-}
+    /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */
+    waveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0);
 
-static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig(
-    LPDIRECTSOUND iface,
-    DWORD config)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,0x%08lx)\n",This,config);
-    return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
-}
+    /* Disable the direct sound driver to force emulation if requested. */
+    if (ds_hw_accel == DS_HW_ACCEL_EMULATION)
+        device->driver = NULL;
 
-static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize(
-    LPDIRECTSOUND iface,
-    LPCGUID lpcGuid)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
-}
+    /* Get driver description */
+    if (device->driver) {
+        hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc));
+        if (hr != DS_OK) {
+            WARN("IDsDriver_GetDriverDesc failed\n");
+            return hr;
+        }
+    } else {
+        /* if no DirectSound interface available, use WINMM API instead */
+        device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT;
+    }
 
-static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl =
-{
-    IDirectSound8_IDirectSound_QueryInterface,
-    IDirectSound8_IDirectSound_AddRef,
-    IDirectSound8_IDirectSound_Release,
-    IDirectSound8_IDirectSound_CreateSoundBuffer,
-    IDirectSound8_IDirectSound_GetCaps,
-    IDirectSound8_IDirectSound_DuplicateSoundBuffer,
-    IDirectSound8_IDirectSound_SetCooperativeLevel,
-    IDirectSound8_IDirectSound_Compact,
-    IDirectSound8_IDirectSound_GetSpeakerConfig,
-    IDirectSound8_IDirectSound_SetSpeakerConfig,
-    IDirectSound8_IDirectSound_Initialize
-};
+    device->drvdesc.dnDevNode = wod;
 
-HRESULT IDirectSound8_IDirectSound_Create(
-    LPDIRECTSOUND8 pds,
-    LPDIRECTSOUND * ppds)
-{
-    IDirectSound8_IDirectSound * pdsds;
-    TRACE("(%p,%p)\n",pds,ppds);
+    /* If the driver requests being opened through MMSYSTEM
+     * (which is recommended by the DDK), it is supposed to happen
+     * before the DirectSound interface is opened */
+    if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
+    {
+        DWORD flags = CALLBACK_FUNCTION;
 
-    if (ppds == NULL) {
-        ERR("invalid parameter: ppds == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+        /* disable direct sound if requested */
+        if (ds_hw_accel != DS_HW_ACCEL_EMULATION)
+            flags |= WAVE_DIRECTSOUND;
 
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppds = NULL;
-        return DSERR_INVALIDPARAM;
+        hr = mmErr(waveOutOpen(&(device->hwo),
+                                device->drvdesc.dnDevNode, device->pwfx,
+                                (DWORD_PTR)DSOUND_callback, (DWORD)device,
+                                flags));
+        if (hr != DS_OK) {
+            WARN("waveOutOpen failed\n");
+            return hr;
+        }
     }
 
-    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
-    if (pdsds == NULL) {
-        WARN("out of memory\n");
-        *ppds = NULL;
-        return DSERR_OUTOFMEMORY;
-    }
+    if (device->driver) {
+        hr = IDsDriver_Open(device->driver);
+        if (hr != DS_OK) {
+            WARN("IDsDriver_Open failed\n");
+            return hr;
+        }
 
-    pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl;
-    pdsds->ref = 0;
-    pdsds->pds = pds;
+        /* the driver is now open, so it's now allowed to call GetCaps */
+        hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps));
+        if (hr != DS_OK) {
+            WARN("IDsDriver_GetCaps failed\n");
+            return hr;
+        }
+    } else {
+        WAVEOUTCAPSA woc;
+        hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc)));
+        if (hr != DS_OK) {
+            WARN("waveOutGetDevCaps failed\n");
+            return hr;
+        }
+        ZeroMemory(&device->drvcaps, sizeof(device->drvcaps));
+        if ((woc.dwFormats & WAVE_FORMAT_1M08) ||
+            (woc.dwFormats & WAVE_FORMAT_2M08) ||
+            (woc.dwFormats & WAVE_FORMAT_4M08) ||
+            (woc.dwFormats & WAVE_FORMAT_48M08) ||
+            (woc.dwFormats & WAVE_FORMAT_96M08)) {
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
+        }
+        if ((woc.dwFormats & WAVE_FORMAT_1M16) ||
+            (woc.dwFormats & WAVE_FORMAT_2M16) ||
+            (woc.dwFormats & WAVE_FORMAT_4M16) ||
+            (woc.dwFormats & WAVE_FORMAT_48M16) ||
+            (woc.dwFormats & WAVE_FORMAT_96M16)) {
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO;
+        }
+        if ((woc.dwFormats & WAVE_FORMAT_1S08) ||
+            (woc.dwFormats & WAVE_FORMAT_2S08) ||
+            (woc.dwFormats & WAVE_FORMAT_4S08) ||
+            (woc.dwFormats & WAVE_FORMAT_48S08) ||
+            (woc.dwFormats & WAVE_FORMAT_96S08)) {
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT;
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
+        }
+        if ((woc.dwFormats & WAVE_FORMAT_1S16) ||
+            (woc.dwFormats & WAVE_FORMAT_2S16) ||
+            (woc.dwFormats & WAVE_FORMAT_4S16) ||
+            (woc.dwFormats & WAVE_FORMAT_48S16) ||
+            (woc.dwFormats & WAVE_FORMAT_96S16)) {
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT;
+            device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO;
+        }
+        if (ds_emuldriver)
+            device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER;
+        device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN;
+        device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX;
+        device->drvcaps.dwPrimaryBuffers = 1;
+    }
 
-    IDirectSoundImpl_AddRef(pds);
-    *ppds = (LPDIRECTSOUND)pdsds;
+    hr = DSOUND_PrimaryCreate(device);
+    if (hr == DS_OK) {
+        DSOUND_renderer[device->drvdesc.dnDevNode] = device;
+        timeBeginPeriod(DS_TIME_RES);
+        DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
+            (DWORD_PTR)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
+    } else {
+        WARN("DSOUND_PrimaryCreate failed\n");
+    }
 
-    return DS_OK;
+    return hr;
 }
 
-/*******************************************************************************
- *		IDirectSound8_IDirectSound8
- */
-static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface(
-    LPDIRECTSOUND8 iface,
-    REFIID riid,
-    LPVOID * ppobj)
+HRESULT DirectSoundDevice_CreateSoundBuffer(
+    DirectSoundDevice * device,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk,
+    BOOL from8)
 {
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
-    return DSOUND_QueryInterface8(This->pds, riid, ppobj);
-}
+    HRESULT hres = DS_OK;
+    TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk);
 
-static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    ULONG ref = InterlockedIncrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref - 1);
-    return ref;
-}
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
 
-static ULONG WINAPI IDirectSound8_IDirectSound8_Release(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    ULONG ref = InterlockedDecrement(&(This->ref));
-    TRACE("(%p) ref was %ld\n", This, ref + 1);
-    if (!ref) {
-        IDirectSoundImpl_Release(This->pds);
-        HeapFree(GetProcessHeap(), 0, This);
-        TRACE("(%p) released\n", This);
+    if (dsbd == NULL) {
+        WARN("invalid parameter: dsbd == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
-    return ref;
-}
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPCDSBUFFERDESC dsbd,
-    LPLPDIRECTSOUNDBUFFER ppdsb,
-    LPUNKNOWN lpunk)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
-    return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE);
-}
+    if (dsbd->dwSize != sizeof(DSBUFFERDESC) &&
+        dsbd->dwSize != sizeof(DSBUFFERDESC1)) {
+        WARN("invalid parameter: dsbd\n");
+        return DSERR_INVALIDPARAM;
+    }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps(
-    LPDIRECTSOUND8 iface,
-    LPDSCAPS lpDSCaps)
-{
-    IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface;
-    TRACE("(%p,%p)\n",This,lpDSCaps);
-    return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps);
-}
+    if (ppdsb == NULL) {
+        WARN("invalid parameter: ppdsb == NULL\n");
+        return DSERR_INVALIDPARAM;
+    }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer(
-    LPDIRECTSOUND8 iface,
-    LPDIRECTSOUNDBUFFER psb,
-    LPLPDIRECTSOUNDBUFFER ppdsb)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%p)\n",This,psb,ppdsb);
-    return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb);
-}
+    if (TRACE_ON(dsound)) {
+        TRACE("(structsize=%ld)\n",dsbd->dwSize);
+        TRACE("(flags=0x%08lx:\n",dsbd->dwFlags);
+        _dump_DSBCAPS(dsbd->dwFlags);
+        DPRINTF(")\n");
+        TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes);
+        TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat);
+    }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel(
-    LPDIRECTSOUND8 iface,
-    HWND hwnd,
-    DWORD level)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level));
-    return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level);
-}
+    if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
+        if (dsbd->lpwfxFormat != NULL) {
+            WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for "
+                 "primary buffer\n");
+            return DSERR_INVALIDPARAM;
+        }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact(
-    LPDIRECTSOUND8 iface)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p)\n", This);
-    return IDirectSoundImpl_Compact(This->pds);
-}
+        if (device->primary) {
+            WARN("Primary Buffer already created\n");
+            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
+            *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
+        } else {
+           device->dsbd = *dsbd;
+           hres = PrimaryBufferImpl_Create(device, (PrimaryBufferImpl**)&(device->primary), &(device->dsbd));
+           if (device->primary) {
+               IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary));
+               *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary);
+           } else
+               WARN("PrimaryBufferImpl_Create failed\n");
+        }
+    } else {
+        IDirectSoundBufferImpl * dsb;
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
-    LPDWORD lpdwSpeakerConfig)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p, %p)\n", This, lpdwSpeakerConfig);
-    return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig);
-}
+        if (dsbd->lpwfxFormat == NULL) {
+            WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for "
+                 "secondary buffer\n");
+            return DSERR_INVALIDPARAM;
+        }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig(
-    LPDIRECTSOUND8 iface,
-    DWORD config)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p,0x%08lx)\n",This,config);
-    return IDirectSoundImpl_SetSpeakerConfig(This->pds,config);
-}
+        TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
+              "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n",
+              dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels,
+              dsbd->lpwfxFormat->nSamplesPerSec,
+              dsbd->lpwfxFormat->nAvgBytesPerSec,
+              dsbd->lpwfxFormat->nBlockAlign,
+              dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize);
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize(
-    LPDIRECTSOUND8 iface,
-    LPCGUID lpcGuid)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid));
-    return IDirectSoundImpl_Initialize(This->pds,lpcGuid);
-}
+        if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) {
+            WARN("invalid parameter: 3D buffer format must be mono\n");
+            return DSERR_INVALIDPARAM;
+        }
+
+        hres = IDirectSoundBufferImpl_Create(device, (IDirectSoundBufferImpl**)&dsb, dsbd);
+        if (dsb) {
+            hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
+            if (*ppdsb) {
+                dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
+                IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb);
+            } else
+                WARN("SecondaryBufferImpl_Create failed\n");
+        } else
+           WARN("IDirectSoundBufferImpl_Create failed\n");
+   }
 
-static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification(
-    LPDIRECTSOUND8 iface,
-    LPDWORD pdwCertified)
-{
-    IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface;
-    TRACE("(%p, %p)\n", This, pdwCertified);
-    return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified);
+   return hres;
 }
 
-static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl =
+HRESULT DirectSoundDevice_DuplicateSoundBuffer(
+    DirectSoundDevice * device,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb)
 {
-    IDirectSound8_IDirectSound8_QueryInterface,
-    IDirectSound8_IDirectSound8_AddRef,
-    IDirectSound8_IDirectSound8_Release,
-    IDirectSound8_IDirectSound8_CreateSoundBuffer,
-    IDirectSound8_IDirectSound8_GetCaps,
-    IDirectSound8_IDirectSound8_DuplicateSoundBuffer,
-    IDirectSound8_IDirectSound8_SetCooperativeLevel,
-    IDirectSound8_IDirectSound8_Compact,
-    IDirectSound8_IDirectSound8_GetSpeakerConfig,
-    IDirectSound8_IDirectSound8_SetSpeakerConfig,
-    IDirectSound8_IDirectSound8_Initialize,
-    IDirectSound8_IDirectSound8_VerifyCertification
-};
+    HRESULT hres = DS_OK;
+    IDirectSoundBufferImpl* dsb;
+    TRACE("(%p,%p,%p)\n",device,psb,ppdsb);
 
-HRESULT IDirectSound8_IDirectSound8_Create(
-    LPDIRECTSOUND8 pds,
-    LPDIRECTSOUND8 * ppds)
-{
-    IDirectSound8_IDirectSound8 * pdsds;
-    TRACE("(%p,%p)\n",pds,ppds);
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
 
-    if (ppds == NULL) {
-        ERR("invalid parameter: ppds == NULL\n");
+    if (psb == NULL) {
+        WARN("invalid parameter: psb == NULL\n");
         return DSERR_INVALIDPARAM;
     }
 
-    if (pds == NULL) {
-        ERR("invalid parameter: pds == NULL\n");
-        *ppds = NULL;
+    if (ppdsb == NULL) {
+        WARN("invalid parameter: ppdsb == NULL\n");
         return DSERR_INVALIDPARAM;
     }
 
-    pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds));
-    if (pdsds == NULL) {
-        WARN("out of memory\n");
-        *ppds = NULL;
-        return DSERR_OUTOFMEMORY;
+    /* make sure we have a secondary buffer */
+    if ((PrimaryBufferImpl *)psb == device->primary) {
+        WARN("trying to duplicate primary buffer\n");
+        *ppdsb = NULL;
+        return DSERR_INVALIDCALL;
     }
 
-    pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl;
-    pdsds->ref = 0;
-    pdsds->pds = pds;
+    /* duplicate the actual buffer implementation */
+    hres = IDirectSoundBufferImpl_Duplicate(device, &dsb,
+                                           ((SecondaryBufferImpl *)psb)->dsb);
 
-    IDirectSoundImpl_AddRef(pds);
-    *ppds = (LPDIRECTSOUND8)pdsds;
+    if (hres == DS_OK) {
+        /* create a new secondary buffer using the new implementation */
+        hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb);
+        if (*ppdsb) {
+            dsb->secondary = (SecondaryBufferImpl*)*ppdsb;
+            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb);
+        } else {
+            WARN("SecondaryBufferImpl_Create failed\n");
+            IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb);
+            IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)dsb);
+        }
+    }
 
-    return DS_OK;
+    return hres;
 }
 
-HRESULT DSOUND_Create(
-    LPDIRECTSOUND *ppDS,
-    IUnknown *pUnkOuter)
+HRESULT DirectSoundDevice_SetCooperativeLevel(
+    DirectSoundDevice * device,
+    HWND hwnd,
+    DWORD level)
 {
-    LPDIRECTSOUND8 pDS;
-    HRESULT hr;
-    TRACE("(%p,%p)\n",ppDS,pUnkOuter);
+    TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level));
 
-    /* Get dsound configuration */
-    setup_dsound_options();
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
 
-    hr = IDirectSoundImpl_Create(&pDS);
-    if (hr == DS_OK) {
-        hr = IDirectSound_IDirectSound_Create(pDS, ppDS);
-        if (*ppDS)
-            IDirectSound_IDirectSound_AddRef(*ppDS);
-        else {
-            WARN("IDirectSound_IDirectSound_Create failed\n");
-            IDirectSound8_Release(pDS);
-        }
-    } else {
-        WARN("IDirectSoundImpl_Create failed\n");
-        *ppDS = 0;
+    if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
+        WARN("level=%s not fully supported\n",
+             level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
     }
 
-    return hr;
+    device->priolevel = level;
+    return DS_OK;
 }
 
-/*******************************************************************************
- *		DirectSoundCreate (DSOUND.1)
- *
- *  Creates and initializes a DirectSound interface.
- *
- *  PARAMS
- *     lpcGUID   [I] Address of the GUID that identifies the sound device.
- *     ppDS      [O] Address of a variable to receive the interface pointer.
- *     pUnkOuter [I] Must be NULL.
- *
- *  RETURNS
- *     Success: DS_OK
- *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
- *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
- */
-HRESULT WINAPI DirectSoundCreate(
-    LPCGUID lpcGUID,
-    LPDIRECTSOUND *ppDS,
-    IUnknown *pUnkOuter)
+HRESULT DirectSoundDevice_Compact(
+    DirectSoundDevice * device)
 {
-    HRESULT hr;
-    LPDIRECTSOUND pDS;
-
-    TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
-
-    if (ppDS == NULL) {
-        WARN("invalid parameter: ppDS == NULL\n");
-        return DSERR_INVALIDPARAM;
-    }
+    TRACE("(%p)\n", device);
 
-    if (pUnkOuter != NULL) {
-        WARN("invalid parameter: pUnkOuter != NULL\n");
-        *ppDS = 0;
-        return DSERR_INVALIDPARAM;
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
     }
 
-    hr = DSOUND_Create(&pDS, pUnkOuter);
-    if (hr == DS_OK) {
-        hr = IDirectSound_Initialize(pDS, lpcGUID);
-        if (hr != DS_OK) {
-            if (hr != DSERR_ALREADYINITIALIZED) {
-                IDirectSound_Release(pDS);
-                pDS = 0;
-            } else
-                hr = DS_OK;
-        }
+    if (device->priolevel != DSSCL_PRIORITY) {
+        WARN("incorrect priority level\n");
+        return DSERR_PRIOLEVELNEEDED;
     }
 
-    *ppDS = pDS;
-
-    return hr;
+    return DS_OK;
 }
 
-HRESULT DSOUND_Create8(
-    LPDIRECTSOUND8 *ppDS,
-    IUnknown *pUnkOuter)
+HRESULT DirectSoundDevice_GetSpeakerConfig(
+    DirectSoundDevice * device,
+    LPDWORD lpdwSpeakerConfig)
 {
-    LPDIRECTSOUND8 pDS;
-    HRESULT hr;
-    TRACE("(%p,%p)\n",ppDS,pUnkOuter);
+    TRACE("(%p, %p)\n", device, lpdwSpeakerConfig);
 
-    /* Get dsound configuration */
-    setup_dsound_options();
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
+    }
 
-    hr = IDirectSoundImpl_Create(&pDS);
-    if (hr == DS_OK) {
-        hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS);
-        if (*ppDS)
-            IDirectSound8_IDirectSound8_AddRef(*ppDS);
-        else {
-            WARN("IDirectSound8_IDirectSound8_Create failed\n");
-            IDirectSound8_Release(pDS);
-        }
-    } else {
-        WARN("IDirectSoundImpl_Create failed\n");
-        *ppDS = 0;
+    if (lpdwSpeakerConfig == NULL) {
+        WARN("invalid parameter: lpdwSpeakerConfig == NULL\n");
+        return DSERR_INVALIDPARAM;
     }
 
-    return hr;
+    WARN("not fully functional\n");
+    *lpdwSpeakerConfig = device->speaker_config;
+    return DS_OK;
 }
 
-/*******************************************************************************
- *        DirectSoundCreate8 (DSOUND.11)
- *
- *  Creates and initializes a DirectSound8 interface.
- *
- *  PARAMS
- *     lpcGUID   [I] Address of the GUID that identifies the sound device.
- *     ppDS      [O] Address of a variable to receive the interface pointer.
- *     pUnkOuter [I] Must be NULL.
- *
- *  RETURNS
- *     Success: DS_OK
- *     Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION,
- *              DSERR_NODRIVER, DSERR_OUTOFMEMORY
- */
-HRESULT WINAPI DirectSoundCreate8(
-    LPCGUID lpcGUID,
-    LPDIRECTSOUND8 *ppDS,
-    IUnknown *pUnkOuter)
+HRESULT DirectSoundDevice_SetSpeakerConfig(
+    DirectSoundDevice * device,
+    DWORD config)
 {
-    HRESULT hr;
-    LPDIRECTSOUND8 pDS;
-
-    TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter);
+    TRACE("(%p,0x%08lx)\n",device,config);
 
-    if (ppDS == NULL) {
-        WARN("invalid parameter: ppDS == NULL\n");
-        return DSERR_INVALIDPARAM;
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
     }
 
-    if (pUnkOuter != NULL) {
-        WARN("invalid parameter: pUnkOuter != NULL\n");
-        *ppDS = 0;
-        return DSERR_INVALIDPARAM;
-    }
+    device->speaker_config = config;
+    WARN("not fully functional\n");
+    return DS_OK;
+}
 
-    hr = DSOUND_Create8(&pDS, pUnkOuter);
-    if (hr == DS_OK) {
-        hr = IDirectSound8_Initialize(pDS, lpcGUID);
-        if (hr != DS_OK) {
-            if (hr != DSERR_ALREADYINITIALIZED) {
-                IDirectSound8_Release(pDS);
-                pDS = 0;
-            } else
-                hr = DS_OK;
-        }
+HRESULT DirectSoundDevice_VerifyCertification(
+    DirectSoundDevice * device,
+    LPDWORD pdwCertified)
+{
+    TRACE("(%p, %p)\n",device,pdwCertified);
+
+    if (device == NULL) {
+        WARN("not initialized\n");
+        return DSERR_UNINITIALIZED;
     }
 
-    *ppDS = pDS;
+    if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED)
+        *pdwCertified = DS_CERTIFIED;
+    else
+        *pdwCertified = DS_UNCERTIFIED;
 
-    return hr;
+    return DS_OK;
 }
 
 /*
Index: dlls/dsound/dsound_private.h
===================================================================
RCS file: /home/wine/wine/dlls/dsound/dsound_private.h,v
retrieving revision 1.41
diff -p -u -r1.41 dsound_private.h
--- dlls/dsound/dsound_private.h	16 Jan 2006 20:40:33 -0000	1.41
+++ dlls/dsound/dsound_private.h	16 Jan 2006 23:03:01 -0000
@@ -71,8 +71,6 @@ typedef struct DirectSoundCaptureDevice 
  */
 struct IDirectSoundImpl
 {
-    /* IUnknown fields */
-    const IDirectSound8Vtbl    *lpVtbl;
     LONG                        ref;
 
     DirectSoundDevice          *device;
@@ -131,12 +129,40 @@ typedef struct BufferMemory
 HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice);
 ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device);
 ULONG DirectSoundDevice_Release(DirectSoundDevice * device);
+HRESULT DirectSoundDevice_Initialize(
+    DirectSoundDevice ** ppDevice,
+    LPCGUID lpcGUID);
 HRESULT DirectSoundDevice_AddBuffer(
-    DirectSoundDevice *device,
+    DirectSoundDevice * device,
     IDirectSoundBufferImpl * pDSB);
 HRESULT DirectSoundDevice_RemoveBuffer(
-    DirectSoundDevice *device,
+    DirectSoundDevice * device,
     IDirectSoundBufferImpl * pDSB);
+HRESULT DirectSoundDevice_GetCaps(DirectSoundDevice * device, LPDSCAPS lpDSCaps);
+HRESULT DirectSoundDevice_CreateSoundBuffer(
+    DirectSoundDevice * device,
+    LPCDSBUFFERDESC dsbd,
+    LPLPDIRECTSOUNDBUFFER ppdsb,
+    LPUNKNOWN lpunk,
+    BOOL from8);
+HRESULT DirectSoundDevice_DuplicateSoundBuffer(
+    DirectSoundDevice * device,
+    LPDIRECTSOUNDBUFFER psb,
+    LPLPDIRECTSOUNDBUFFER ppdsb);
+HRESULT DirectSoundDevice_SetCooperativeLevel(
+    DirectSoundDevice * devcie,
+    HWND hwnd,
+    DWORD level);
+HRESULT DirectSoundDevice_Compact(DirectSoundDevice * device);
+HRESULT DirectSoundDevice_GetSpeakerConfig(
+    DirectSoundDevice * device,
+    LPDWORD lpdwSpeakerConfig);
+HRESULT DirectSoundDevice_SetSpeakerConfig(
+    DirectSoundDevice * device,
+    DWORD config);
+HRESULT DirectSoundDevice_VerifyCertification(
+    DirectSoundDevice * device,
+    LPDWORD pdwCertified);
 
 /*****************************************************************************
  * IDirectSound COM components


More information about the wine-patches mailing list