Commit 9dacf206 authored by Robert Reif's avatar Robert Reif Committed by Alexandre Julliard

3D buffer and listener reference counts should be fixed.

3D sound now plays in 3D. COM interfaces should be correct for buffers and 3D stuff. The COM interface is broken on notifications but I will fix that next. Fixed the bug when closing and opening the same or another sound device quickly. Fixed some locking but there is a lot of work left yet.
parent 0d6a2e9a
...@@ -29,8 +29,10 @@ ...@@ -29,8 +29,10 @@
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> /* Insomnia - pow() function */ #include <math.h>
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "wingdi.h" #include "wingdi.h"
...@@ -56,6 +58,8 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface( ...@@ -56,6 +58,8 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
ICOM_THIS(IDirectSoundNotifyImpl,iface); ICOM_THIS(IDirectSoundNotifyImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
*ppobj = NULL; /* assume error */
if ( IsEqualGUID(riid, &IID_IUnknown) || if ( IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDirectSoundNotify) || IsEqualGUID(riid, &IID_IDirectSoundNotify) ||
IsEqualGUID(riid, &IID_IDirectSoundNotify8) ) { IsEqualGUID(riid, &IID_IDirectSoundNotify8) ) {
...@@ -65,9 +69,6 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface( ...@@ -65,9 +69,6 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface(
} }
FIXME( "Unknown IID %s\n", debugstr_guid( riid ) ); FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
*ppobj = 0;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
...@@ -75,7 +76,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) { ...@@ -75,7 +76,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) {
ICOM_THIS(IDirectSoundNotifyImpl,iface); ICOM_THIS(IDirectSoundNotifyImpl,iface);
DWORD ref; DWORD ref;
TRACE("(%p) ref was %ld\n", This, This->ref); TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedIncrement(&(This->ref)); ref = InterlockedIncrement(&(This->ref));
return ref; return ref;
...@@ -85,7 +86,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) { ...@@ -85,7 +86,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) {
ICOM_THIS(IDirectSoundNotifyImpl,iface); ICOM_THIS(IDirectSoundNotifyImpl,iface);
DWORD ref; DWORD ref;
TRACE("(%p) ref was %ld\n", This, This->ref); TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedDecrement(&(This->ref)); ref = InterlockedDecrement(&(This->ref));
/* FIXME: A notification should be a part of a buffer rather than pointed /* FIXME: A notification should be a part of a buffer rather than pointed
...@@ -186,8 +187,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume( ...@@ -186,8 +187,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume(
EnterCriticalSection(&(This->lock)); EnterCriticalSection(&(This->lock));
if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) { if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) {
oldVol = This->ds3db->lVolume; oldVol = This->ds3db_lVolume;
This->ds3db->lVolume = vol; This->ds3db_lVolume = vol;
} else { } else {
oldVol = This->volpan.lVolume; oldVol = This->volpan.lVolume;
This->volpan.lVolume = vol; This->volpan.lVolume = vol;
...@@ -223,7 +224,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume( ...@@ -223,7 +224,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetVolume(
} }
if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) if (This->dsbd.dwFlags & DSBCAPS_CTRL3D)
*vol = This->ds3db->lVolume; *vol = This->ds3db_lVolume;
else else
*vol = This->volpan.lVolume; *vol = This->volpan.lVolume;
return DS_OK; return DS_OK;
...@@ -340,6 +341,7 @@ static DWORD WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) { ...@@ -340,6 +341,7 @@ static DWORD WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) {
} }
return ref; return ref;
} }
static DWORD WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) { static DWORD WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
ICOM_THIS(IDirectSoundBufferImpl,iface); ICOM_THIS(IDirectSoundBufferImpl,iface);
int i; int i;
...@@ -366,25 +368,33 @@ static DWORD WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) { ...@@ -366,25 +368,33 @@ static DWORD WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
RtlReleaseResource(&(This->dsound->lock)); RtlReleaseResource(&(This->dsound->lock));
DeleteCriticalSection(&(This->lock)); DeleteCriticalSection(&(This->lock));
if (This->hwbuf) { if (This->hwbuf) {
IDsDriverBuffer_Release(This->hwbuf); IDsDriverBuffer_Release(This->hwbuf);
if (This->dsound->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) if (This->dsound->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) {
This->buffer->ref--;
if (This->buffer->ref==0) {
HeapFree(GetProcessHeap(),0,This->buffer->memory);
HeapFree(GetProcessHeap(),0,This->buffer);
}
}
} else {
This->buffer->ref--;
if (This->buffer->ref==0) {
HeapFree(GetProcessHeap(),0,This->buffer->memory);
HeapFree(GetProcessHeap(),0,This->buffer); HeapFree(GetProcessHeap(),0,This->buffer);
}
} }
else if (!This->parent)
HeapFree(GetProcessHeap(),0,This->buffer);
if (This->ds3db) { if (This->ds3db) {
IDirectSound3DBuffer_Release((LPDIRECTSOUND3DBUFFER)This->ds3db); WARN("ds3db still has reference\n");
} EnterCriticalSection(&(This->ds3db->lock));
if (This->dsound->listener) { This->ds3db->dsb = NULL;
if (IDirectSound3DListener_Release((LPDIRECTSOUND3DLISTENER)This->dsound->listener) == 0) LeaveCriticalSection(&(This->ds3db->lock));
This->dsound->listener = 0;
} }
if (This->iks) {
HeapFree(GetProcessHeap(), 0, This->iks); if (This->iks)
} IKsPropertySet_Release((LPKSPROPERTYSET)This->iks);
if (This->parent)
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->parent);
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
...@@ -622,7 +632,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock( ...@@ -622,7 +632,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
} else { } else {
BOOL remix = FALSE; BOOL remix = FALSE;
if (writecursor+writebytes <= This->buflen) { if (writecursor+writebytes <= This->buflen) {
*(LPBYTE*)lplpaudioptr1 = This->buffer+writecursor; *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
*audiobytes1 = writebytes; *audiobytes1 = writebytes;
if (lplpaudioptr2) if (lplpaudioptr2)
*(LPBYTE*)lplpaudioptr2 = NULL; *(LPBYTE*)lplpaudioptr2 = NULL;
...@@ -630,10 +640,10 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock( ...@@ -630,10 +640,10 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock(
*audiobytes2 = 0; *audiobytes2 = 0;
TRACE("->%ld.0\n",writebytes); TRACE("->%ld.0\n",writebytes);
} else { } else {
*(LPBYTE*)lplpaudioptr1 = This->buffer+writecursor; *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor;
*audiobytes1 = This->buflen-writecursor; *audiobytes1 = This->buflen-writecursor;
if (lplpaudioptr2) if (lplpaudioptr2)
*(LPBYTE*)lplpaudioptr2 = This->buffer; *(LPBYTE*)lplpaudioptr2 = This->buffer->memory;
if (audiobytes2) if (audiobytes2)
*audiobytes2 = writebytes-(This->buflen-writecursor); *audiobytes2 = writebytes-(This->buflen-writecursor);
TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0); TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0);
...@@ -757,14 +767,6 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock( ...@@ -757,14 +767,6 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2); TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2);
#if 0
/* Preprocess 3D buffers... */
/* This is highly experimental and liable to break things */
if (This->dsbd.dwFlags & DSBCAPS_CTRL3D)
DSOUND_Create3DBuffer(This);
#endif
if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { if (!(This->dsound->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) {
HRESULT hres; HRESULT hres;
hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2); hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2);
...@@ -774,8 +776,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock( ...@@ -774,8 +776,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Unlock(
} }
} }
if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer) + x2; if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer->memory) + x2;
else probably_valid_to = (((LPBYTE)p1)-This->buffer) + x1; else probably_valid_to = (((LPBYTE)p1)-This->buffer->memory) + x1;
while (probably_valid_to >= This->buflen) while (probably_valid_to >= This->buflen)
probably_valid_to -= This->buflen; probably_valid_to -= This->buflen;
if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) && if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) &&
...@@ -903,6 +905,16 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( ...@@ -903,6 +905,16 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
*ppobj = NULL; /* assume failure */
if ( IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDirectSoundBuffer) ||
IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) {
IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This);
*ppobj = This;
return S_OK;
}
if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) || if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ||
IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) { IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) {
if (!This->notify) { if (!This->notify) {
...@@ -918,9 +930,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( ...@@ -918,9 +930,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
*ppobj = (LPVOID)This->notify; *ppobj = (LPVOID)This->notify;
return S_OK; return S_OK;
} }
*ppobj = NULL;
WARN("IID_IDirectSoundNotify\n"); WARN("IID_IDirectSoundNotify\n");
return E_FAIL; return E_NOINTERFACE;
} }
if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) { if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
...@@ -931,15 +942,13 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( ...@@ -931,15 +942,13 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)*ppobj); IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)*ppobj);
return S_OK; return S_OK;
} }
*ppobj = NULL;
WARN("IID_IDirectSound3DBuffer\n"); WARN("IID_IDirectSound3DBuffer\n");
return E_FAIL; return E_NOINTERFACE;
} }
if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) { if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
ERR("app requested IDirectSound3DListener on secondary buffer\n"); ERR("app requested IDirectSound3DListener on secondary buffer\n");
*ppobj = NULL; return E_NOINTERFACE;
return E_FAIL;
} }
if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) { if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
...@@ -950,21 +959,12 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( ...@@ -950,21 +959,12 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface(
IKsPropertySet_AddRef((LPKSPROPERTYSET)*ppobj); IKsPropertySet_AddRef((LPKSPROPERTYSET)*ppobj);
return S_OK; return S_OK;
} }
*ppobj = NULL;
WARN("IID_IKsPropertySet\n"); WARN("IID_IKsPropertySet\n");
return E_FAIL; return E_NOINTERFACE;
}
if ( IsEqualGUID( &IID_IDirectSoundBuffer8, riid ) ) {
IDirectSoundBuffer8_AddRef(iface);
*ppobj = This;
return NO_ERROR;
} }
FIXME( "Unknown IID %s\n", debugstr_guid( riid ) ); FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
*ppobj = NULL;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
...@@ -1009,7 +1009,7 @@ HRESULT WINAPI SecondaryBuffer_Create( ...@@ -1009,7 +1009,7 @@ HRESULT WINAPI SecondaryBuffer_Create(
int use_hw; int use_hw;
if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) { if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) {
ERR("invalid parameter: dsbd->dwBufferBytes = %ld\n", dsbd->dwBufferBytes); WARN("invalid parameter: dsbd->dwBufferBytes = %ld\n", dsbd->dwBufferBytes);
*pdsb = NULL; *pdsb = NULL;
return DSERR_INVALIDPARAM; /* FIXME: which error? */ return DSERR_INVALIDPARAM; /* FIXME: which error? */
} }
...@@ -1021,9 +1021,8 @@ HRESULT WINAPI SecondaryBuffer_Create( ...@@ -1021,9 +1021,8 @@ HRESULT WINAPI SecondaryBuffer_Create(
*pdsb = NULL; *pdsb = NULL;
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
} }
dsb->ref = 1; dsb->ref = 0;
dsb->dsound = This; dsb->dsound = This;
dsb->parent = NULL;
dsb->lpVtbl = &dsbvt; dsb->lpVtbl = &dsbvt;
memcpy(&dsb->dsbd, dsbd, sizeof(*dsbd)); memcpy(&dsb->dsbd, dsbd, sizeof(*dsbd));
...@@ -1049,22 +1048,33 @@ HRESULT WINAPI SecondaryBuffer_Create( ...@@ -1049,22 +1048,33 @@ HRESULT WINAPI SecondaryBuffer_Create(
/* Allocate system memory if applicable */ /* Allocate system memory if applicable */
if ((This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) { if ((This->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) {
dsb->buffer = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsb->buflen); dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer)));
if (dsb->buffer == NULL) { if (dsb->buffer == NULL) {
WARN("out of memory\n"); WARN("out of memory\n");
HeapFree(GetProcessHeap(),0,dsb); HeapFree(GetProcessHeap(),0,dsb);
*pdsb = NULL; *pdsb = NULL;
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
} }
dsb->buffer->memory = (LPBYTE)HeapAlloc(GetProcessHeap(),0,dsb->buflen);
if (dsb->buffer->memory == NULL) {
WARN("out of memory\n");
HeapFree(GetProcessHeap(),0,dsb->buffer);
HeapFree(GetProcessHeap(),0,dsb);
*pdsb = NULL;
return DSERR_OUTOFMEMORY;
}
} }
/* Allocate the hardware buffer */ /* Allocate the hardware buffer */
if (use_hw) { if (use_hw) {
err = IDsDriver_CreateSoundBuffer(This->driver,wfex,dsbd->dwFlags,0, err = IDsDriver_CreateSoundBuffer(This->driver,wfex,dsbd->dwFlags,0,
&(dsb->buflen),&(dsb->buffer), &(dsb->buflen),&(dsb->buffer->memory),
(LPVOID*)&(dsb->hwbuf)); (LPVOID*)&(dsb->hwbuf));
if (err != DS_OK) { if (err != DS_OK) {
WARN("IDsDriver_CreateSoundBuffer failed\n"); WARN("IDsDriver_CreateSoundBuffer failed\n");
if (dsb->buffer->memory)
HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
if (dsb->buffer) if (dsb->buffer)
HeapFree(GetProcessHeap(),0,dsb->buffer); HeapFree(GetProcessHeap(),0,dsb->buffer);
HeapFree(GetProcessHeap(),0,dsb); HeapFree(GetProcessHeap(),0,dsb);
...@@ -1087,16 +1097,26 @@ HRESULT WINAPI SecondaryBuffer_Create( ...@@ -1087,16 +1097,26 @@ HRESULT WINAPI SecondaryBuffer_Create(
dsb->nAvgBytesPerSec = dsb->freq * dsb->nAvgBytesPerSec = dsb->freq *
dsbd->lpwfxFormat->nBlockAlign; dsbd->lpwfxFormat->nBlockAlign;
if (dsbd->dwFlags & DSBCAPS_CTRL3D) { if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) {
err = IDirectSound3DBufferImpl_Create(dsb, &dsb->ds3db); dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
if (err != DS_OK) { dsb->ds3db_ds3db.vPosition.u1.x = 0.0;
WARN("IDirectSound3DBufferImpl_Create failed\n"); dsb->ds3db_ds3db.vPosition.u2.y = 0.0;
if (dsb->buffer) dsb->ds3db_ds3db.vPosition.u3.z = 0.0;
HeapFree(GetProcessHeap(),0,dsb->buffer); dsb->ds3db_ds3db.vVelocity.u1.x = 0.0;
HeapFree(GetProcessHeap(),0,dsb); dsb->ds3db_ds3db.vVelocity.u2.y = 0.0;
dsb = NULL; dsb->ds3db_ds3db.vVelocity.u3.z = 0.0;
return err; dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
} dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
dsb->ds3db_ds3db.vConeOrientation.u1.x = 0.0;
dsb->ds3db_ds3db.vConeOrientation.u2.y = 0.0;
dsb->ds3db_ds3db.vConeOrientation.u3.z = 0.0;
dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
dsb->ds3db_need_recalc = FALSE;
DSOUND_Calc3DBuffer(dsb);
} else } else
DSOUND_RecalcVolPan(&(dsb->volpan)); DSOUND_RecalcVolPan(&(dsb->volpan));
...@@ -1113,12 +1133,14 @@ HRESULT WINAPI SecondaryBuffer_Create( ...@@ -1113,12 +1133,14 @@ HRESULT WINAPI SecondaryBuffer_Create(
TRACE("buffer count is now %d\n", This->nrofbuffers); TRACE("buffer count is now %d\n", This->nrofbuffers);
} else { } else {
ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers); ERR("out of memory for buffer list! Current buffer count is %d\n", This->nrofbuffers);
if (dsb->buffer->memory)
HeapFree(GetProcessHeap(),0,dsb->buffer->memory);
if (dsb->buffer) if (dsb->buffer)
HeapFree(GetProcessHeap(),0,dsb->buffer); HeapFree(GetProcessHeap(),0,dsb->buffer);
DeleteCriticalSection(&(dsb->lock)); DeleteCriticalSection(&(dsb->lock));
RtlReleaseResource(&(This->lock)); RtlReleaseResource(&(This->lock));
HeapFree(GetProcessHeap(),0,dsb); HeapFree(GetProcessHeap(),0,dsb);
dsb = NULL; *pdsb = NULL;
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
} }
} }
......
...@@ -48,8 +48,10 @@ ...@@ -48,8 +48,10 @@
#endif #endif
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> /* Insomnia - pow() function */ #include <math.h>
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include "windef.h" #include "windef.h"
#include "winbase.h" #include "winbase.h"
#include "winreg.h" #include "winreg.h"
...@@ -471,8 +473,12 @@ static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel( ...@@ -471,8 +473,12 @@ static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel(
LPDIRECTSOUND8 iface,HWND hwnd,DWORD level LPDIRECTSOUND8 iface,HWND hwnd,DWORD level
) { ) {
ICOM_THIS(IDirectSoundImpl,iface); ICOM_THIS(IDirectSoundImpl,iface);
TRACE("(%p,%08lx,%ld)\n",This,(DWORD)hwnd,level);
FIXME("(%p,%08lx,%ld):stub\n",This,(DWORD)hwnd,level); if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) {
FIXME("level=%s not fully supported\n",
level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE");
}
This->priolevel = level; This->priolevel = level;
...@@ -484,7 +490,7 @@ static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer( ...@@ -484,7 +490,7 @@ static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
) { ) {
ICOM_THIS(IDirectSoundImpl,iface); ICOM_THIS(IDirectSoundImpl,iface);
LPWAVEFORMATEX wfex; LPWAVEFORMATEX wfex;
HRESULT hres; HRESULT hres = DS_OK;
TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk);
...@@ -522,13 +528,19 @@ static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer( ...@@ -522,13 +528,19 @@ static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer(
wfex->wBitsPerSample, wfex->cbSize); wfex->wBitsPerSample, wfex->cbSize);
if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) { if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) {
hres = PrimaryBuffer_Create(This, (PrimaryBufferImpl**)ppdsb, dsbd); *ppdsb=(LPDIRECTSOUNDBUFFER8)This->primary;
if (hres != DS_OK) if (*ppdsb==NULL)
WARN("PrimaryBuffer_Create failed\n"); WARN("PrimaryBuffer_Create failed\n");
else {
This->dsbd = *dsbd;
IDirectSoundBuffer_AddRef(*ppdsb);
}
} else { } else {
hres = SecondaryBuffer_Create(This, (IDirectSoundBufferImpl**)ppdsb, dsbd); hres = SecondaryBuffer_Create(This, (IDirectSoundBufferImpl**)ppdsb, dsbd);
if (hres != DS_OK) if (hres != DS_OK)
WARN("SecondaryBuffer_Create failed\n"); WARN("SecondaryBuffer_Create failed\n");
else
IDirectSoundBuffer_AddRef(*ppdsb);
} }
return hres; return hres;
...@@ -577,28 +589,15 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer( ...@@ -577,28 +589,15 @@ static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer(
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
} }
IDirectSoundBuffer8_AddRef(pdsb);
memcpy(dsb, ipdsb, sizeof(IDirectSoundBufferImpl)); memcpy(dsb, ipdsb, sizeof(IDirectSoundBufferImpl));
dsb->ref = 1; dsb->ref = 1;
dsb->state = STATE_STOPPED; dsb->state = STATE_STOPPED;
dsb->playpos = 0; dsb->playpos = 0;
dsb->buf_mixpos = 0; dsb->buf_mixpos = 0;
dsb->dsound = This; dsb->dsound = This;
dsb->parent = ipdsb; dsb->buffer->ref++;
dsb->hwbuf = NULL; dsb->hwbuf = NULL;
if (ipdsb->ds3db != NULL) { dsb->ds3db = NULL;
HRESULT hres;
hres = IDirectSound3DBufferImpl_Create(dsb, &(dsb->ds3db));
if (hres != DS_OK) {
WARN("IDirectSound3DBufferImpl_Create failed\n");
} else {
IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)(dsb->ds3db));
dsb->dsbd.dwFlags |= DSBCAPS_CTRL3D;
memcpy(&(dsb->ds3db->ds3db), &(ipdsb->ds3db->ds3db), sizeof(DS3DBUFFER));
}
} else {
dsb->ds3db = NULL;
}
dsb->iks = NULL; /* FIXME? */ dsb->iks = NULL; /* FIXME? */
memcpy(&(dsb->wfx), &(ipdsb->wfx), sizeof(dsb->wfx)); memcpy(&(dsb->wfx), &(ipdsb->wfx), sizeof(dsb->wfx));
InitializeCriticalSection(&(dsb->lock)); InitializeCriticalSection(&(dsb->lock));
...@@ -689,45 +688,57 @@ static HRESULT WINAPI IDirectSoundImpl_GetCaps(LPDIRECTSOUND8 iface,LPDSCAPS lpD ...@@ -689,45 +688,57 @@ static HRESULT WINAPI IDirectSoundImpl_GetCaps(LPDIRECTSOUND8 iface,LPDSCAPS lpD
static ULONG WINAPI IDirectSoundImpl_AddRef(LPDIRECTSOUND8 iface) { static ULONG WINAPI IDirectSoundImpl_AddRef(LPDIRECTSOUND8 iface) {
ICOM_THIS(IDirectSoundImpl,iface); ICOM_THIS(IDirectSoundImpl,iface);
TRACE("(%p) ref was %ld\n", This, This->ref); TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
return ++(This->ref); return InterlockedIncrement(&This->ref);
} }
static ULONG WINAPI IDirectSoundImpl_Release(LPDIRECTSOUND8 iface) { static ULONG WINAPI IDirectSoundImpl_Release(LPDIRECTSOUND8 iface) {
HRESULT hres;
ICOM_THIS(IDirectSoundImpl,iface); ICOM_THIS(IDirectSoundImpl,iface);
TRACE("(%p), ref was %ld\n",This,This->ref); ULONG ulReturn;
if (!--(This->ref)) {
TRACE("(%p) ref was %ld, thread is %04lx\n", This, This->ref, GetCurrentThreadId());
ulReturn = InterlockedDecrement(&This->ref);
if (ulReturn == 0) {
HRESULT hres;
UINT i; UINT i;
timeKillEvent(This->timerID); timeKillEvent(This->timerID);
timeEndPeriod(DS_TIME_RES); timeEndPeriod(DS_TIME_RES);
/* wait for timer to expire */
Sleep(DS_TIME_RES+1);
RtlAcquireResourceShared(&(This->lock), TRUE);
if (This->buffers) { if (This->buffers) {
for( i=0;i<This->nrofbuffers;i++) for( i=0;i<This->nrofbuffers;i++)
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->buffers[i]); IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->buffers[i]);
} }
RtlReleaseResource(&(This->lock));
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->primary);
hres = DSOUND_PrimaryDestroy(This); hres = DSOUND_PrimaryDestroy(This);
if (hres != DS_OK) if (hres != DS_OK)
WARN("DSOUND_PrimaryDestroy failed\n"); WARN("DSOUND_PrimaryDestroy failed\n");
RtlDeleteResource(&This->lock); if (This->driver)
DeleteCriticalSection(&This->mixlock);
if (This->driver) {
IDsDriver_Close(This->driver); IDsDriver_Close(This->driver);
}
if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) { if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN)
waveOutClose(This->hwo); waveOutClose(This->hwo);
}
if (This->driver) if (This->driver)
IDsDriver_Release(This->driver); IDsDriver_Release(This->driver);
RtlDeleteResource(&This->lock);
DeleteCriticalSection(&This->mixlock);
DeleteCriticalSection(&This->ds3dl_lock);
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
dsound = NULL; dsound = NULL;
return 0; return 0;
} }
return This->ref; return ulReturn;
} }
static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig( static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig(
...@@ -742,14 +753,24 @@ static HRESULT WINAPI IDirectSoundImpl_QueryInterface( ...@@ -742,14 +753,24 @@ static HRESULT WINAPI IDirectSoundImpl_QueryInterface(
LPDIRECTSOUND8 iface,REFIID riid,LPVOID *ppobj LPDIRECTSOUND8 iface,REFIID riid,LPVOID *ppobj
) { ) {
ICOM_THIS(IDirectSoundImpl,iface); ICOM_THIS(IDirectSoundImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
*ppobj = NULL; /* assume failure */
if ( IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDirectSound) ||
IsEqualGUID(riid, &IID_IDirectSound8) ) {
IDirectSound8_AddRef((LPDIRECTSOUND8)This);
*ppobj = This;
return S_OK;
}
if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) { if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
ERR("app requested IDirectSound3DListener on dsound object\n"); WARN("app requested IDirectSound3DListener on dsound object\n");
*ppobj = NULL; return E_NOINTERFACE;
return E_FAIL;
} }
FIXME("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
return E_NOINTERFACE; return E_NOINTERFACE;
} }
...@@ -927,7 +948,28 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown ...@@ -927,7 +948,28 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown
(*ippDS)->state = STATE_STOPPED; (*ippDS)->state = STATE_STOPPED;
(*ippDS)->nrofbuffers = 0; (*ippDS)->nrofbuffers = 0;
(*ippDS)->buffers = NULL; (*ippDS)->buffers = NULL;
(*ippDS)->primary = NULL;
/* 3D listener initial parameters */
(*ippDS)->listener = NULL; (*ippDS)->listener = NULL;
(*ippDS)->ds3dl.dwSize = sizeof(DS3DLISTENER);
(*ippDS)->ds3dl.vPosition.u1.x = 0.0;
(*ippDS)->ds3dl.vPosition.u2.y = 0.0;
(*ippDS)->ds3dl.vPosition.u3.z = 0.0;
(*ippDS)->ds3dl.vVelocity.u1.x = 0.0;
(*ippDS)->ds3dl.vVelocity.u2.y = 0.0;
(*ippDS)->ds3dl.vVelocity.u3.z = 0.0;
(*ippDS)->ds3dl.vOrientFront.u1.x = 0.0;
(*ippDS)->ds3dl.vOrientFront.u2.y = 0.0;
(*ippDS)->ds3dl.vOrientFront.u3.z = 1.0;
(*ippDS)->ds3dl.vOrientTop.u1.x = 0.0;
(*ippDS)->ds3dl.vOrientTop.u2.y = 1.0;
(*ippDS)->ds3dl.vOrientTop.u3.z = 0.0;
(*ippDS)->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
(*ippDS)->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
(*ippDS)->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
InitializeCriticalSection(&(*ippDS)->ds3dl_lock);
(*ippDS)->prebuf = ds_snd_queue_max; (*ippDS)->prebuf = ds_snd_queue_max;
(*ippDS)->guid = devGuid; (*ippDS)->guid = devGuid;
...@@ -1064,7 +1106,14 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown ...@@ -1064,7 +1106,14 @@ HRESULT WINAPI DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown
dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer, dsound->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer,
(DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION); (DWORD)dsound, TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
} }
return DS_OK;
/* create a user accessable primary buffer */
(*ippDS)->dsbd.dwSize = sizeof((*ippDS)->dsbd);
err = PrimaryBuffer_Create((*ippDS), (PrimaryBufferImpl**)&((*ippDS)->primary), &((*ippDS)->dsbd));
if ((*ippDS)->primary)
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(*ippDS)->primary);
return err;
} }
......
...@@ -62,7 +62,7 @@ struct IDirectSoundImpl ...@@ -62,7 +62,7 @@ struct IDirectSoundImpl
{ {
/* IUnknown fields */ /* IUnknown fields */
ICOM_VFIELD(IDirectSound8); ICOM_VFIELD(IDirectSound8);
DWORD ref; DWORD ref;
/* IDirectSoundImpl fields */ /* IDirectSoundImpl fields */
GUID guid; GUID guid;
PIDSDRIVER driver; PIDSDRIVER driver;
...@@ -80,12 +80,26 @@ struct IDirectSoundImpl ...@@ -80,12 +80,26 @@ struct IDirectSoundImpl
BOOL need_remix; BOOL need_remix;
int nrofbuffers; int nrofbuffers;
IDirectSoundBufferImpl** buffers; IDirectSoundBufferImpl** buffers;
IDirectSound3DListenerImpl* listener;
RTL_RWLOCK lock; RTL_RWLOCK lock;
CRITICAL_SECTION mixlock; CRITICAL_SECTION mixlock;
DSVOLUMEPAN volpan; DSVOLUMEPAN volpan;
PrimaryBufferImpl* primary;
DSBUFFERDESC dsbd;
/* DirectSound3DListener fields */
IDirectSound3DListenerImpl* listener;
DS3DLISTENER ds3dl;
CRITICAL_SECTION ds3dl_lock;
BOOL ds3dl_need_recalc;
}; };
/* reference counted buffer memory for duplicated buffer memory */
typedef struct BufferMemory
{
DWORD ref;
LPBYTE memory;
} BufferMemory;
/***************************************************************************** /*****************************************************************************
* IDirectSoundBuffer implementation structure * IDirectSoundBuffer implementation structure
*/ */
...@@ -94,30 +108,34 @@ struct IDirectSoundBufferImpl ...@@ -94,30 +108,34 @@ struct IDirectSoundBufferImpl
/* FIXME: document */ /* FIXME: document */
/* IUnknown fields */ /* IUnknown fields */
ICOM_VFIELD(IDirectSoundBuffer8); ICOM_VFIELD(IDirectSoundBuffer8);
DWORD ref; DWORD ref;
/* IDirectSoundBufferImpl fields */ /* IDirectSoundBufferImpl fields */
IDirectSoundImpl* dsound; IDirectSoundImpl* dsound;
IDirectSoundBufferImpl* parent; /* for duplicates */ IDirectSound3DBufferImpl* ds3db;
IDirectSound3DBufferImpl* ds3db; IKsPropertySetImpl* iks;
IKsPropertySetImpl* iks; CRITICAL_SECTION lock;
CRITICAL_SECTION lock; PIDSDRIVERBUFFER hwbuf;
PIDSDRIVERBUFFER hwbuf; WAVEFORMATEX wfx;
WAVEFORMATEX wfx; BufferMemory* buffer;
LPBYTE buffer; DWORD playflags,state,leadin;
DWORD playflags,state,leadin; DWORD playpos,startpos,writelead,buflen;
DWORD playpos,startpos,writelead,buflen; DWORD nAvgBytesPerSec;
DWORD nAvgBytesPerSec; DWORD freq;
DWORD freq; DSVOLUMEPAN volpan, cvolpan;
DSVOLUMEPAN volpan, cvolpan; DSBUFFERDESC dsbd;
DSBUFFERDESC dsbd;
/* used for frequency conversion (PerfectPitch) */ /* used for frequency conversion (PerfectPitch) */
ULONG freqAdjust, freqAcc; ULONG freqAdjust, freqAcc;
/* used for intelligent (well, sort of) prebuffering */ /* used for intelligent (well, sort of) prebuffering */
DWORD probably_valid_to, last_playpos; DWORD probably_valid_to, last_playpos;
DWORD primary_mixpos, buf_mixpos; DWORD primary_mixpos, buf_mixpos;
BOOL need_remix; BOOL need_remix;
/* IDirectSoundNotifyImpl fields */ /* IDirectSoundNotifyImpl fields */
IDirectSoundNotifyImpl *notify; IDirectSoundNotifyImpl* notify;
/* DirectSound3DBuffer fields */
DS3DBUFFER ds3db_ds3db;
LONG ds3db_lVolume;
BOOL ds3db_need_recalc;
}; };
HRESULT WINAPI SecondaryBuffer_Create( HRESULT WINAPI SecondaryBuffer_Create(
...@@ -126,10 +144,9 @@ HRESULT WINAPI SecondaryBuffer_Create( ...@@ -126,10 +144,9 @@ HRESULT WINAPI SecondaryBuffer_Create(
LPDSBUFFERDESC dsbd); LPDSBUFFERDESC dsbd);
struct PrimaryBufferImpl { struct PrimaryBufferImpl {
ICOM_VFIELD(IDirectSoundBuffer8); ICOM_VFIELD(IDirectSoundBuffer8);
DWORD ref; DWORD ref;
IDirectSoundImpl* dsound; IDirectSoundImpl* dsound;
DSBUFFERDESC dsbd;
}; };
HRESULT WINAPI PrimaryBuffer_Create( HRESULT WINAPI PrimaryBuffer_Create(
...@@ -182,15 +199,15 @@ struct IDirectSoundCaptureBufferImpl ...@@ -182,15 +199,15 @@ struct IDirectSoundCaptureBufferImpl
{ {
/* IUnknown fields */ /* IUnknown fields */
ICOM_VFIELD(IDirectSoundCaptureBuffer8); ICOM_VFIELD(IDirectSoundCaptureBuffer8);
DWORD ref; DWORD ref;
/* IDirectSoundCaptureBufferImpl fields */ /* IDirectSoundCaptureBufferImpl fields */
IDirectSoundCaptureImpl* dsound; IDirectSoundCaptureImpl* dsound;
/* FIXME: don't need this */ /* FIXME: don't need this */
LPDSCBUFFERDESC pdscbd; LPDSCBUFFERDESC pdscbd;
DWORD flags; DWORD flags;
/* IDirectSoundNotifyImpl fields */ /* IDirectSoundNotifyImpl fields */
IDirectSoundNotifyImpl *notify; IDirectSoundNotifyImpl* notify;
}; };
/***************************************************************************** /*****************************************************************************
...@@ -200,10 +217,10 @@ struct IDirectSoundFullDuplexImpl ...@@ -200,10 +217,10 @@ struct IDirectSoundFullDuplexImpl
{ {
/* IUnknown fields */ /* IUnknown fields */
ICOM_VFIELD(IDirectSoundFullDuplex); ICOM_VFIELD(IDirectSoundFullDuplex);
DWORD ref; DWORD ref;
/* IDirectSoundFullDuplexImpl fields */ /* IDirectSoundFullDuplexImpl fields */
CRITICAL_SECTION lock; CRITICAL_SECTION lock;
}; };
/***************************************************************************** /*****************************************************************************
...@@ -213,12 +230,12 @@ struct IDirectSoundNotifyImpl ...@@ -213,12 +230,12 @@ struct IDirectSoundNotifyImpl
{ {
/* IUnknown fields */ /* IUnknown fields */
ICOM_VFIELD(IDirectSoundNotify); ICOM_VFIELD(IDirectSoundNotify);
DWORD ref; DWORD ref;
/* IDirectSoundNotifyImpl fields */ /* IDirectSoundNotifyImpl fields */
LPDSBPOSITIONNOTIFY notifies; LPDSBPOSITIONNOTIFY notifies;
int nrofnotifies; int nrofnotifies;
PIDSDRIVERNOTIFY hwnotify; PIDSDRIVERNOTIFY hwnotify;
}; };
/***************************************************************************** /*****************************************************************************
...@@ -228,12 +245,9 @@ struct IDirectSound3DListenerImpl ...@@ -228,12 +245,9 @@ struct IDirectSound3DListenerImpl
{ {
/* IUnknown fields */ /* IUnknown fields */
ICOM_VFIELD(IDirectSound3DListener); ICOM_VFIELD(IDirectSound3DListener);
DWORD ref; DWORD ref;
/* IDirectSound3DListenerImpl fields */ /* IDirectSound3DListenerImpl fields */
PrimaryBufferImpl* dsb; IDirectSoundImpl* dsound;
DS3DLISTENER ds3dl;
CRITICAL_SECTION lock;
BOOL need_recalc;
}; };
HRESULT WINAPI IDirectSound3DListenerImpl_Create( HRESULT WINAPI IDirectSound3DListenerImpl_Create(
...@@ -263,13 +277,10 @@ struct IDirectSound3DBufferImpl ...@@ -263,13 +277,10 @@ struct IDirectSound3DBufferImpl
{ {
/* IUnknown fields */ /* IUnknown fields */
ICOM_VFIELD(IDirectSound3DBuffer); ICOM_VFIELD(IDirectSound3DBuffer);
DWORD ref; DWORD ref;
/* IDirectSound3DBufferImpl fields */ /* IDirectSound3DBufferImpl fields */
IDirectSoundBufferImpl* dsb; IDirectSoundBufferImpl* dsb;
DS3DBUFFER ds3db; CRITICAL_SECTION lock;
LONG lVolume;
CRITICAL_SECTION lock;
BOOL need_recalc;
}; };
HRESULT WINAPI IDirectSound3DBufferImpl_Create( HRESULT WINAPI IDirectSound3DBufferImpl_Create(
...@@ -302,6 +313,10 @@ void DSOUND_PerformMix(void); ...@@ -302,6 +313,10 @@ void DSOUND_PerformMix(void);
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2); void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2); void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2);
/* sound3d.c */
void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb);
#define STATE_STOPPED 0 #define STATE_STOPPED 0
#define STATE_STARTING 1 #define STATE_STARTING 1
#define STATE_PLAYING 2 #define STATE_PLAYING 2
...@@ -313,12 +328,6 @@ void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, D ...@@ -313,12 +328,6 @@ void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, D
extern IDirectSoundImpl* dsound; extern IDirectSoundImpl* dsound;
extern IDirectSoundCaptureImpl* dsound_capture; extern IDirectSoundCaptureImpl* dsound_capture;
struct PrimaryBuffer {
DWORD ref;
PIDSDRIVERBUFFER hwbuf;
DWORD state;
};
extern ICOM_VTABLE(IDirectSoundNotify) dsnvt; extern ICOM_VTABLE(IDirectSoundNotify) dsnvt;
extern HRESULT mmErr(UINT err); extern HRESULT mmErr(UINT err);
extern void setup_dsound_options(void); extern void setup_dsound_options(void);
...@@ -50,6 +50,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); ...@@ -50,6 +50,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound);
void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan) void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan)
{ {
double temp; double temp;
TRACE("(%p)\n",volpan);
/* the AmpFactors are expressed in 16.16 fixed point */ /* the AmpFactors are expressed in 16.16 fixed point */
volpan->dwVolAmpFactor = (ULONG) (pow(2.0, volpan->lVolume / 600.0) * 65536); volpan->dwVolAmpFactor = (ULONG) (pow(2.0, volpan->lVolume / 600.0) * 65536);
...@@ -190,7 +191,7 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len) ...@@ -190,7 +191,7 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
INT iAdvance = dsb->wfx.nBlockAlign; INT iAdvance = dsb->wfx.nBlockAlign;
INT oAdvance = dsb->dsound->wfx.nBlockAlign; INT oAdvance = dsb->dsound->wfx.nBlockAlign;
ibp = dsb->buffer + dsb->buf_mixpos; ibp = dsb->buffer->memory + dsb->buf_mixpos;
obp = buf; obp = buf;
TRACE("(%p, %p, %p), buf_mixpos=%ld\n", dsb, ibp, obp, dsb->buf_mixpos); TRACE("(%p, %p, %p), buf_mixpos=%ld\n", dsb, ibp, obp, dsb->buf_mixpos);
...@@ -204,7 +205,7 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len) ...@@ -204,7 +205,7 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
memcpy(obp, ibp, len); memcpy(obp, ibp, len);
else { /* wrap */ else { /* wrap */
memcpy(obp, ibp, bytesleft ); memcpy(obp, ibp, bytesleft );
memcpy(obp + bytesleft, dsb->buffer, len - bytesleft); memcpy(obp + bytesleft, dsb->buffer->memory, len - bytesleft);
} }
return len; return len;
} }
...@@ -219,8 +220,8 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len) ...@@ -219,8 +220,8 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
ibp += iAdvance; ibp += iAdvance;
ilen += iAdvance; ilen += iAdvance;
obp += oAdvance; obp += oAdvance;
if (ibp >= (BYTE *)(dsb->buffer + dsb->buflen)) if (ibp >= (BYTE *)(dsb->buffer->memory + dsb->buflen))
ibp = dsb->buffer; /* wrap */ ibp = dsb->buffer->memory; /* wrap */
} }
return (ilen); return (ilen);
} }
...@@ -240,7 +241,7 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len) ...@@ -240,7 +241,7 @@ static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len)
ilen = 0; ilen = 0;
ipos = dsb->buf_mixpos; ipos = dsb->buf_mixpos;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
cp_fields(dsb, (dsb->buffer + ipos), obp); cp_fields(dsb, (dsb->buffer->memory + ipos), obp);
obp += oAdvance; obp += oAdvance;
dsb->freqAcc += dsb->freqAdjust; dsb->freqAcc += dsb->freqAdjust;
if (dsb->freqAcc >= (1<<DSOUND_FREQSHIFT)) { if (dsb->freqAcc >= (1<<DSOUND_FREQSHIFT)) {
...@@ -380,7 +381,8 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO ...@@ -380,7 +381,8 @@ static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWO
ilen = DSOUND_MixerNorm(dsb, ibuf, len); ilen = DSOUND_MixerNorm(dsb, ibuf, len);
if ((dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || if ((dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
(dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) (dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) ||
(dsb->dsbd.dwFlags & DSBCAPS_CTRL3D))
DSOUND_MixerVol(dsb, ibuf, len); DSOUND_MixerVol(dsb, ibuf, len);
obuf = dsb->dsound->buffer + writepos; obuf = dsb->dsound->buffer + writepos;
...@@ -450,7 +452,8 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR ...@@ -450,7 +452,8 @@ static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWOR
ilen = DSOUND_MixerNorm(dsb, ibuf, len); ilen = DSOUND_MixerNorm(dsb, ibuf, len);
if ((dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || if ((dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) ||
(dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) (dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) ||
(dsb->dsbd.dwFlags & DSBCAPS_CTRL3D))
DSOUND_MixerVol(dsb, ibuf, len); DSOUND_MixerVol(dsb, ibuf, len);
/* subtract instead of add, to phase out premixed data */ /* subtract instead of add, to phase out premixed data */
...@@ -844,21 +847,12 @@ void DSOUND_PerformMix(void) ...@@ -844,21 +847,12 @@ void DSOUND_PerformMix(void)
TRACE("()\n"); TRACE("()\n");
RtlAcquireResourceShared(&(dsound->lock), TRUE);
if (!dsound || !dsound->ref) {
/* seems the dsound object is currently being released */
RtlReleaseResource(&(dsound->lock));
return;
}
/* the sound of silence */ /* the sound of silence */
nfiller = dsound->wfx.wBitsPerSample == 8 ? 128 : 0; nfiller = dsound->wfx.wBitsPerSample == 8 ? 128 : 0;
/* whether the primary is forced to play even without secondary buffers */ /* whether the primary is forced to play even without secondary buffers */
forced = ((dsound->state == STATE_PLAYING) || (dsound->state == STATE_STARTING)); forced = ((dsound->state == STATE_PLAYING) || (dsound->state == STATE_STARTING));
TRACE("entering at %ld\n", GetTickCount());
if (dsound->priolevel != DSSCL_WRITEPRIMARY) { if (dsound->priolevel != DSSCL_WRITEPRIMARY) {
BOOL paused = ((dsound->state == STATE_STOPPED) || (dsound->state == STATE_STARTING)); BOOL paused = ((dsound->state == STATE_STOPPED) || (dsound->state == STATE_STARTING));
/* FIXME: document variables */ /* FIXME: document variables */
...@@ -866,7 +860,7 @@ void DSOUND_PerformMix(void) ...@@ -866,7 +860,7 @@ void DSOUND_PerformMix(void)
if (dsound->hwbuf) { if (dsound->hwbuf) {
hres = IDsDriverBuffer_GetPosition(dsound->hwbuf, &playpos, &writepos); hres = IDsDriverBuffer_GetPosition(dsound->hwbuf, &playpos, &writepos);
if (hres) { if (hres) {
RtlReleaseResource(&(dsound->lock)); WARN("IDsDriverBuffer_GetPosition failed\n");
return; return;
} }
/* Well, we *could* do Just-In-Time mixing using the writepos, /* Well, we *could* do Just-In-Time mixing using the writepos,
...@@ -954,7 +948,7 @@ void DSOUND_PerformMix(void) ...@@ -954,7 +948,7 @@ void DSOUND_PerformMix(void)
hres = IDsDriverBuffer_GetPosition(dsound->hwbuf, &playpos, NULL); hres = IDsDriverBuffer_GetPosition(dsound->hwbuf, &playpos, NULL);
if (hres) { if (hres) {
LeaveCriticalSection(&(dsound->mixlock)); LeaveCriticalSection(&(dsound->mixlock));
RtlReleaseResource(&(dsound->lock)); WARN("IDsDriverBuffer_GetPosition failed\n");
return; return;
} }
} else { } else {
...@@ -1012,12 +1006,13 @@ void DSOUND_PerformMix(void) ...@@ -1012,12 +1006,13 @@ void DSOUND_PerformMix(void)
dsound->state = STATE_STOPPED; dsound->state = STATE_STOPPED;
} }
} }
TRACE("completed processing at %ld\n", GetTickCount());
RtlReleaseResource(&(dsound->lock));
} }
void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
{ {
TRACE("(%d,%d,0x%lx,0x%lx,0x%lx)\n",timerID,msg,dwUser,dw1,dw2);
TRACE("entering at %ld\n", GetTickCount());
if (!dsound) { if (!dsound) {
ERR("dsound died without killing us?\n"); ERR("dsound died without killing us?\n");
timeKillEvent(timerID); timeKillEvent(timerID);
...@@ -1025,8 +1020,15 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWOR ...@@ -1025,8 +1020,15 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWOR
return; return;
} }
TRACE("entered\n"); RtlAcquireResourceShared(&(dsound->lock), TRUE);
DSOUND_PerformMix();
if (dsound->ref) {
DSOUND_PerformMix();
}
RtlReleaseResource(&(dsound->lock));
TRACE("completed processing at %ld\n", GetTickCount());
} }
void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2)
......
...@@ -430,7 +430,7 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume( ...@@ -430,7 +430,7 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume(
TRACE("(%p,%ld)\n",This,vol); TRACE("(%p,%ld)\n",This,vol);
/* I'm not sure if we need this for primary buffer */ /* I'm not sure if we need this for primary buffer */
if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
WARN("control unavailable\n"); WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL; return DSERR_CONTROLUNAVAIL;
} }
...@@ -480,6 +480,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume( ...@@ -480,6 +480,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume(
ICOM_THIS(PrimaryBufferImpl,iface); ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%p)\n",This,vol); TRACE("(%p,%p)\n",This,vol);
if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) {
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
if (vol == NULL) { if (vol == NULL) {
WARN("invalid parameter: vol = NULL\n"); WARN("invalid parameter: vol = NULL\n");
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
...@@ -555,29 +560,21 @@ static DWORD WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) { ...@@ -555,29 +560,21 @@ static DWORD WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) {
ICOM_THIS(PrimaryBufferImpl,iface); ICOM_THIS(PrimaryBufferImpl,iface);
DWORD ref; DWORD ref;
TRACE("(%p) ref was %ld, thread is %lx\n",This, This->ref, GetCurrentThreadId()); TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedIncrement(&(This->ref)); ref = InterlockedIncrement(&(This->ref));
if (!ref) {
FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
}
return ref; return ref;
} }
static DWORD WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) { static DWORD WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) {
ICOM_THIS(PrimaryBufferImpl,iface); ICOM_THIS(PrimaryBufferImpl,iface);
DWORD ref; DWORD ref;
TRACE("(%p) ref was %ld, thread is %lx\n",This, This->ref, GetCurrentThreadId()); TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedDecrement(&(This->ref)); ref = InterlockedDecrement(&(This->ref));
if (ref == 0) { if (ref == -1) {
IDirectSound_Release((LPDIRECTSOUND)This->dsound); This->dsound->primary = NULL;
if (This->dsound->listener) {
IDirectSound3DListener_Release((LPDIRECTSOUND3DLISTENER)This->dsound->listener);
This->dsound->listener = NULL;
}
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
} }
...@@ -611,7 +608,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetStatus( ...@@ -611,7 +608,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetStatus(
LPDIRECTSOUNDBUFFER8 iface,LPDWORD status LPDIRECTSOUNDBUFFER8 iface,LPDWORD status
) { ) {
ICOM_THIS(PrimaryBufferImpl,iface); ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%p), thread is %lx\n",This,status,GetCurrentThreadId()); TRACE("(%p,%p), thread is %04lx\n",This,status,GetCurrentThreadId());
if (status == NULL) { if (status == NULL) {
WARN("invalid parameter: status == NULL\n"); WARN("invalid parameter: status == NULL\n");
...@@ -812,6 +809,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFrequency( ...@@ -812,6 +809,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFrequency(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
if (!(This->dsound->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) {
WARN("control unavailable\n");
return DSERR_CONTROLUNAVAIL;
}
*freq = This->dsound->wfx.nSamplesPerSec; *freq = This->dsound->wfx.nSamplesPerSec;
TRACE("-> %ld\n", *freq); TRACE("-> %ld\n", *freq);
...@@ -885,7 +887,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetCaps( ...@@ -885,7 +887,7 @@ static HRESULT WINAPI PrimaryBufferImpl_GetCaps(
return DSERR_INVALIDPARAM; return DSERR_INVALIDPARAM;
} }
caps->dwFlags = This->dsbd.dwFlags; caps->dwFlags = This->dsound->dsbd.dwFlags;
if (This->dsound->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE; if (This->dsound->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE;
else caps->dwFlags |= DSBCAPS_LOCSOFTWARE; else caps->dwFlags |= DSBCAPS_LOCSOFTWARE;
...@@ -905,56 +907,58 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface( ...@@ -905,56 +907,58 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface(
LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj
) { ) {
ICOM_THIS(PrimaryBufferImpl,iface); ICOM_THIS(PrimaryBufferImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
*ppobj = NULL; /* assume failure */
if ( IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)This);
*ppobj = This;
return S_OK;
}
/* DirectSoundBuffer and DirectSoundBuffer8 are different and */
/* a primary buffer can't have a DirectSoundBuffer8 interface */
if ( IsEqualGUID( &IID_IDirectSoundBuffer8, riid ) ) {
WARN("app requested DirectSoundBuffer8 on primary buffer\n");
return E_NOINTERFACE;
}
if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) { if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) {
ERR("app requested IDirectSoundNotify on primary buffer\n"); ERR("app requested IDirectSoundNotify on primary buffer\n");
/* FIXME: should we support this? */ /* FIXME: should we support this? */
*ppobj = NULL; return E_NOINTERFACE;
return E_FAIL;
} }
if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) { if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) {
ERR("app requested IDirectSound3DBuffer on primary buffer\n"); ERR("app requested IDirectSound3DBuffer on primary buffer\n");
*ppobj = NULL;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) { if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) {
if (!This->dsound->listener) if (This->dsound->dsbd.dwFlags & DSBCAPS_CTRL3D) {
IDirectSound3DListenerImpl_Create(This, &This->dsound->listener); if (!This->dsound->listener)
*ppobj = This->dsound->listener; IDirectSound3DListenerImpl_Create(This, &This->dsound->listener);
if (This->dsound->listener) {
IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj); *ppobj = This->dsound->listener;
return DS_OK;
if (This->dsound->listener) {
IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj);
return S_OK;
}
} }
WARN("IID_IDirectSound3DListener failed\n"); WARN("IID_IDirectSound3DListener failed\n");
*ppobj = NULL; return E_NOINTERFACE;
return E_FAIL;
} }
if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) { if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) {
#if 0
if (!This->iks)
IKsPropertySetImpl_Create(This, &This->iks);
*ppobj = This->iks;
if (*ppobj) {
IKsPropertySet_AddRef((LPKSPROPERTYSET)*ppobj);
return S_OK;
}
return E_FAIL;
#else
FIXME("app requested IKsPropertySet on primary buffer\n"); FIXME("app requested IKsPropertySet on primary buffer\n");
*ppobj = NULL; return E_NOINTERFACE;
return E_FAIL;
#endif
} }
FIXME( "Unknown IID %s\n", debugstr_guid( riid ) ); FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
*ppobj = NULL;
return E_NOINTERFACE; return E_NOINTERFACE;
} }
...@@ -1010,11 +1014,11 @@ HRESULT WINAPI PrimaryBuffer_Create( ...@@ -1010,11 +1014,11 @@ HRESULT WINAPI PrimaryBuffer_Create(
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
} }
dsb->ref = 1; dsb->ref = -1;
dsb->dsound = This; dsb->dsound = This;
dsb->lpVtbl = &dspbvt; dsb->lpVtbl = &dspbvt;
memcpy(&dsb->dsbd, dsbd, sizeof(*dsbd)); memcpy(&This->dsbd, dsbd, sizeof(*dsbd));
TRACE("Created primary buffer at %p\n", dsb); TRACE("Created primary buffer at %p\n", dsb);
TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld," TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld,"
...@@ -1023,18 +1027,6 @@ HRESULT WINAPI PrimaryBuffer_Create( ...@@ -1023,18 +1027,6 @@ HRESULT WINAPI PrimaryBuffer_Create(
This->wfx.nAvgBytesPerSec, This->wfx.nBlockAlign, This->wfx.nAvgBytesPerSec, This->wfx.nBlockAlign,
This->wfx.wBitsPerSample, This->wfx.cbSize); This->wfx.wBitsPerSample, This->wfx.cbSize);
if (dsbd->dwFlags & DSBCAPS_CTRL3D) {
HRESULT hres;
hres = IDirectSound3DListenerImpl_Create(dsb, &This->listener);
if (hres != DS_OK) {
WARN("IDirectSound3DListenerImpl_Create failed\n");
} else {
IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)This->listener);
}
}
IDirectSound8_AddRef((LPDIRECTSOUND8)This);
*pdsb = dsb; *pdsb = dsb;
return S_OK; return S_OK;
} }
...@@ -169,7 +169,7 @@ static inline D3DVECTOR VectorBetweenTwoPoints (LPD3DVECTOR a, LPD3DVECTOR b) ...@@ -169,7 +169,7 @@ static inline D3DVECTOR VectorBetweenTwoPoints (LPD3DVECTOR a, LPD3DVECTOR b)
return c; return c;
} }
/* calculates the lenght of vector's projection on another vector */ /* calculates the length of vector's projection on another vector */
static inline D3DVALUE ProjectVector (LPD3DVECTOR a, LPD3DVECTOR p) static inline D3DVALUE ProjectVector (LPD3DVECTOR a, LPD3DVECTOR p)
{ {
D3DVALUE prod, result; D3DVALUE prod, result;
...@@ -184,10 +184,8 @@ static inline D3DVALUE ProjectVector (LPD3DVECTOR a, LPD3DVECTOR p) ...@@ -184,10 +184,8 @@ static inline D3DVALUE ProjectVector (LPD3DVECTOR a, LPD3DVECTOR p)
* 3D Buffer and Listener mixing * 3D Buffer and Listener mixing
*/ */
static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db) void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb)
{ {
IDirectSound3DListenerImpl *dsl;
/* volume, at which the sound will be played after all calcs. */ /* volume, at which the sound will be played after all calcs. */
D3DVALUE lVolume = 0; D3DVALUE lVolume = 0;
/* intensity (used for distance related stuff) */ /* intensity (used for distance related stuff) */
...@@ -204,79 +202,77 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db) ...@@ -204,79 +202,77 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db)
D3DVALUE flFreq, flBufferVel, flListenerVel; D3DVALUE flFreq, flBufferVel, flListenerVel;
#endif #endif
TRACE("(%p)\n",ds3db); TRACE("(%p)\n",dsb);
if (ds3db->dsb->dsound->listener == NULL)
return;
dsl = ds3db->dsb->dsound->listener;
/* initial buffer volume */ /* initial buffer volume */
lVolume = ds3db->lVolume; lVolume = dsb->ds3db_lVolume;
switch (ds3db->ds3db.dwMode) switch (dsb->ds3db_ds3db.dwMode)
{ {
case DS3DMODE_DISABLE: case DS3DMODE_DISABLE:
TRACE("3D processing disabled\n"); TRACE("3D processing disabled\n");
/* this one is here only to eliminate annoying warning message */ /* this one is here only to eliminate annoying warning message */
DSOUND_RecalcVolPan (&ds3db->dsb->volpan); DSOUND_RecalcVolPan (&dsb->volpan);
DSOUND_ForceRemix (ds3db->dsb); DSOUND_ForceRemix (dsb);
break; break;
case DS3DMODE_NORMAL: case DS3DMODE_NORMAL:
TRACE("Normal 3D processing mode\n"); TRACE("Normal 3D processing mode\n");
/* we need to calculate distance between buffer and listener*/ /* we need to calculate distance between buffer and listener*/
vDistance = VectorBetweenTwoPoints(&ds3db->ds3db.vPosition, &dsl->ds3dl.vPosition); vDistance = VectorBetweenTwoPoints(&dsb->ds3db_ds3db.vPosition, &dsb->dsound->ds3dl.vPosition);
flDistance = VectorMagnitude (&vDistance); flDistance = VectorMagnitude (&vDistance);
break; break;
case DS3DMODE_HEADRELATIVE: case DS3DMODE_HEADRELATIVE:
TRACE("Head-relative 3D processing mode\n"); TRACE("Head-relative 3D processing mode\n");
/* distance between buffer and listener is same as buffer's position */ /* distance between buffer and listener is same as buffer's position */
flDistance = VectorMagnitude (&ds3db->ds3db.vPosition); flDistance = VectorMagnitude (&dsb->ds3db_ds3db.vPosition);
break; break;
} }
if (flDistance > ds3db->ds3db.flMaxDistance) if (flDistance > dsb->ds3db_ds3db.flMaxDistance)
{ {
/* some apps don't want you to hear too distant sounds... */ /* some apps don't want you to hear too distant sounds... */
if (ds3db->dsb->dsbd.dwFlags & DSBCAPS_MUTE3DATMAXDISTANCE) if (dsb->dsbd.dwFlags & DSBCAPS_MUTE3DATMAXDISTANCE)
{ {
ds3db->dsb->volpan.lVolume = DSBVOLUME_MIN; dsb->volpan.lVolume = DSBVOLUME_MIN;
DSOUND_RecalcVolPan (&ds3db->dsb->volpan); DSOUND_RecalcVolPan (&dsb->volpan);
/* i guess mixing here would be a waste of power */ /* i guess mixing here would be a waste of power */
return; return;
} }
else else
flDistance = ds3db->ds3db.flMaxDistance; flDistance = dsb->ds3db_ds3db.flMaxDistance;
} }
if (flDistance < ds3db->ds3db.flMinDistance)
flDistance = ds3db->ds3db.flMinDistance; if (flDistance < dsb->ds3db_ds3db.flMinDistance)
flDistance = dsb->ds3db_ds3db.flMinDistance;
/* the following formula is taken from my physics book. I think it's ok for the *real* world...i hope m$ does it that way */ /* the following formula is taken from my physics book. I think it's ok for the *real* world...i hope m$ does it that way */
lVolume += 10000; /* ms likes working with negative volume...i don't */ lVolume += 10000; /* ms likes working with negative volume...i don't */
lVolume /= 1000; /* convert hundreths of dB into B */ lVolume /= 1000; /* convert hundreths of dB into B */
/* intensity level (loudness) = log10(Intensity/DefaultIntensity)...therefore */ /* intensity level (loudness) = log10(Intensity/DefaultIntensity)...therefore */
flIntensity = pow(10,lVolume)*DEFAULT_INTENSITY; flIntensity = pow(10,lVolume)*DEFAULT_INTENSITY;
flTemp = (flDistance/ds3db->ds3db.flMinDistance)*(flDistance/ds3db->ds3db.flMinDistance); flTemp = (flDistance/dsb->ds3db_ds3db.flMinDistance)*(flDistance/dsb->ds3db_ds3db.flMinDistance);
flIntensity /= flTemp; flIntensity /= flTemp;
lVolume = log10(flIntensity/DEFAULT_INTENSITY); lVolume = log10(flIntensity/DEFAULT_INTENSITY);
lVolume *= 1000; /* convert back to hundreths of dB */ lVolume *= 1000; /* convert back to hundreths of dB */
lVolume -= 10000; /* we need to do it in ms way */ lVolume -= 10000; /* we need to do it in ms way */
TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %ld to %f\n", flDistance, ds3db->ds3db.flMinDistance, ds3db->lVolume, lVolume); TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %ld to %f\n", flDistance, dsb->ds3db_ds3db.flMinDistance, dsb->ds3db_lVolume, lVolume);
/* conning */ /* conning */
/* sometimes it happens that vConeOrientation vector = (0,0,0); in this case angle is "nan" and it's useless*/ /* sometimes it happens that vConeOrientation vector = (0,0,0); in this case angle is "nan" and it's useless*/
if (ds3db->ds3db.vConeOrientation.u1.x == 0 && ds3db->ds3db.vConeOrientation.u2.y == 0 && ds3db->ds3db.vConeOrientation.u3.z == 0) if (dsb->ds3db_ds3db.vConeOrientation.u1.x == 0 && dsb->ds3db_ds3db.vConeOrientation.u2.y == 0 && dsb->ds3db_ds3db.vConeOrientation.u3.z == 0)
{ {
TRACE("conning: cones not set\n"); TRACE("conning: cones not set\n");
} }
else else
{ {
/* calculate angle */ /* calculate angle */
flAngle = AngleBetweenVectorsDeg(&ds3db->ds3db.vConeOrientation, &vDistance); flAngle = AngleBetweenVectorsDeg(&dsb->ds3db_ds3db.vConeOrientation, &vDistance);
/* if by any chance it happens that OutsideConeAngle = InsideConeAngle (that means that conning has no effect) */ /* if by any chance it happens that OutsideConeAngle = InsideConeAngle (that means that conning has no effect) */
if (ds3db->ds3db.dwInsideConeAngle != ds3db->ds3db.dwOutsideConeAngle) if (dsb->ds3db_ds3db.dwInsideConeAngle != dsb->ds3db_ds3db.dwOutsideConeAngle)
{ {
/* my test show that for my way of calc., we need only half of angles */ /* my test show that for my way of calc., we need only half of angles */
DWORD dwInsideConeAngle = ds3db->ds3db.dwInsideConeAngle/2; DWORD dwInsideConeAngle = dsb->ds3db_ds3db.dwInsideConeAngle/2;
DWORD dwOutsideConeAngle = ds3db->ds3db.dwOutsideConeAngle/2; DWORD dwOutsideConeAngle = dsb->ds3db_ds3db.dwOutsideConeAngle/2;
/* full volume */ /* full volume */
if (flAngle < dwInsideConeAngle) if (flAngle < dwInsideConeAngle)
flAngle = dwInsideConeAngle; flAngle = dwInsideConeAngle;
...@@ -284,25 +280,34 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db) ...@@ -284,25 +280,34 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db)
if (flAngle > dwOutsideConeAngle) if (flAngle > dwOutsideConeAngle)
flAngle = dwOutsideConeAngle; flAngle = dwOutsideConeAngle;
/* this probably isn't the right thing, but it's ok for the time being */ /* this probably isn't the right thing, but it's ok for the time being */
lVolume += ((ds3db->ds3db.lConeOutsideVolume)/((dwOutsideConeAngle) - (dwInsideConeAngle))) * flAngle; lVolume += ((dsb->ds3db_ds3db.lConeOutsideVolume)/((dwOutsideConeAngle) - (dwInsideConeAngle))) * flAngle;
} }
TRACE("conning: Angle = %f deg; InsideConeAngle(/2) = %ld deg; OutsideConeAngle(/2) = %ld deg; ConeOutsideVolume = %ld => adjusting volume to %f\n", TRACE("conning: Angle = %f deg; InsideConeAngle(/2) = %ld deg; OutsideConeAngle(/2) = %ld deg; ConeOutsideVolume = %ld => adjusting volume to %f\n",
flAngle, ds3db->ds3db.dwInsideConeAngle/2, ds3db->ds3db.dwOutsideConeAngle/2, ds3db->ds3db.lConeOutsideVolume, lVolume); flAngle, dsb->ds3db_ds3db.dwInsideConeAngle/2, dsb->ds3db_ds3db.dwOutsideConeAngle/2, dsb->ds3db_ds3db.lConeOutsideVolume, lVolume);
} }
ds3db->dsb->volpan.lVolume = lVolume; dsb->volpan.lVolume = lVolume;
/* panning */ /* panning */
vDistance = VectorBetweenTwoPoints(&dsl->ds3dl.vPosition, &ds3db->ds3db.vPosition); if (dsb->dsound->ds3dl.vPosition.u1.x == dsb->ds3db_ds3db.vPosition.u1.x &&
vLeft = VectorProduct(&dsl->ds3dl.vOrientFront, &dsl->ds3dl.vOrientTop); dsb->dsound->ds3dl.vPosition.u2.y == dsb->ds3db_ds3db.vPosition.u2.y &&
flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance); dsb->dsound->ds3dl.vPosition.u3.z == dsb->ds3db_ds3db.vPosition.u3.z) {
/* for now, we'll use "linear formula" (which is probably incorrect); if someone has it in book, correct it */ dsb->volpan.lPan = 0;
ds3db->dsb->volpan.lPan = 10000*2*flAngle/M_PI - 10000; flAngle = 0.0;
TRACE("panning: Angle = %f rad, lPan = %ld\n", flAngle, ds3db->dsb->volpan.lPan); }
else
{
vDistance = VectorBetweenTwoPoints(&dsb->dsound->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition);
vLeft = VectorProduct(&dsb->dsound->ds3dl.vOrientFront, &dsb->dsound->ds3dl.vOrientTop);
flAngle = AngleBetweenVectorsRad(&vLeft, &vDistance);
/* for now, we'll use "linear formula" (which is probably incorrect); if someone has it in book, correct it */
dsb->volpan.lPan = 10000*2*flAngle/M_PI - 10000;
}
TRACE("panning: Angle = %f rad, lPan = %ld\n", flAngle, dsb->volpan.lPan);
/* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */ /* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */
#if 0 #if 0
/* doppler shift*/ /* doppler shift*/
if ((VectorMagnitude(&ds3db->ds3db.vVelocity) == 0) && (VectorMagnitude(&dsl->ds3dl.vVelocity) == 0)) if ((VectorMagnitude(&ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->dsound->ds3dl.vVelocity) == 0))
{ {
TRACE("doppler: Buffer and Listener don't have velocities\n"); TRACE("doppler: Buffer and Listener don't have velocities\n");
} }
...@@ -311,41 +316,47 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db) ...@@ -311,41 +316,47 @@ static void WINAPI DSOUND_Mix3DBuffer(IDirectSound3DBufferImpl *ds3db)
/* calculate lenght of ds3db.vVelocity component which causes Doppler Effect /* calculate lenght of ds3db.vVelocity component which causes Doppler Effect
NOTE: if buffer moves TOWARDS the listener, it's velocity component is NEGATIVE NOTE: if buffer moves TOWARDS the listener, it's velocity component is NEGATIVE
if buffer moves AWAY from listener, it's velocity component is POSITIVE */ if buffer moves AWAY from listener, it's velocity component is POSITIVE */
flBufferVel = ProjectVector(&ds3db->ds3db.vVelocity, &vDistance); flBufferVel = ProjectVector(&dsb->ds3db_ds3db.vVelocity, &vDistance);
/* calculate lenght of ds3dl.vVelocity component which causes Doppler Effect /* calculate lenght of ds3dl.vVelocity component which causes Doppler Effect
NOTE: if listener moves TOWARDS the buffer, it's velocity component is POSITIVE NOTE: if listener moves TOWARDS the buffer, it's velocity component is POSITIVE
if listener moves AWAY from buffer, it's velocity component is NEGATIVE */ if listener moves AWAY from buffer, it's velocity component is NEGATIVE */
flListenerVel = ProjectVector(&dsl->ds3dl.vVelocity, &vDistance); flListenerVel = ProjectVector(&dsb->dsound->ds3dl.vVelocity, &vDistance);
/* formula taken from Gianicoli D.: Physics, 4th edition: */ /* formula taken from Gianicoli D.: Physics, 4th edition: */
/* FIXME: replace ds3db->dsb->freq with appropriate frequency ! */ /* FIXME: replace dsb->freq with appropriate frequency ! */
flFreq = ds3db->dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel)); flFreq = dsb->freq * ((DEFAULT_VELOCITY + flListenerVel)/(DEFAULT_VELOCITY + flBufferVel));
TRACE("doppler: Buffer velocity (component) = %lf, Listener velocity (component) = %lf => Doppler shift: %ld Hz -> %lf Hz\n", flBufferVel, flListenerVel, \ TRACE("doppler: Buffer velocity (component) = %lf, Listener velocity (component) = %lf => Doppler shift: %ld Hz -> %lf Hz\n", flBufferVel, flListenerVel, \
ds3db->dsb->freq, flFreq); dsb->freq, flFreq);
/* FIXME: replace following line with correct frequency setting ! */ /* FIXME: replace following line with correct frequency setting ! */
ds3db->dsb->freq = flFreq; dsb->freq = flFreq;
} }
#endif #endif
/* time for remix */ /* time for remix */
DSOUND_RecalcVolPan (&ds3db->dsb->volpan); DSOUND_RecalcVolPan(&dsb->volpan);
DSOUND_ForceRemix (ds3db->dsb); }
static void DSOUND_Mix3DBuffer(IDirectSoundBufferImpl *dsb)
{
TRACE("(%p)\n",dsb);
DSOUND_Calc3DBuffer(dsb);
DSOUND_ForceRemix(dsb);
} }
static void WINAPI DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl) static void WINAPI DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl)
{ {
int i; int i;
TRACE("(%p)\n",ds3dl); TRACE("(%p)\n",ds3dl);
for (i = 0; i < ds3dl->dsb->dsound->nrofbuffers; i++) for (i = 0; i < ds3dl->dsound->nrofbuffers; i++)
{ {
/* some buffers don't have 3d buffer (Ultima IX seems to /* some buffers don't have 3d buffer (Ultima IX seems to
crash without the following line) */ crash without the following line) */
if (ds3dl->dsb->dsound->buffers[i]->ds3db == NULL) if (ds3dl->dsound->buffers[i]->ds3db == NULL)
continue; continue;
if (ds3dl->dsb->dsound->buffers[i]->ds3db->need_recalc == TRUE) if (ds3dl->dsound->buffers[i]->ds3db_need_recalc == TRUE)
{ {
DSOUND_Mix3DBuffer(ds3dl->dsb->dsound->buffers[i]->ds3db); DSOUND_Mix3DBuffer(ds3dl->dsound->buffers[i]);
} }
} }
} }
...@@ -366,13 +377,14 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface( ...@@ -366,13 +377,14 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_QueryInterface(
static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface) static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
ULONG ulReturn; ULONG ref;
TRACE("(%p) ref was %ld\n", This, This->ref); TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
ulReturn = InterlockedIncrement(&This->ref); ref = InterlockedIncrement(&This->ref);
if (ulReturn == 1) if (!ref) {
IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb); FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
return ulReturn; }
return ref;
} }
static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface) static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface)
...@@ -380,28 +392,16 @@ static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface ...@@ -380,28 +392,16 @@ static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
ULONG ulReturn; ULONG ulReturn;
TRACE("(%p) ref was %ld\n", This, This->ref); TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
ulReturn = InterlockedDecrement(&This->ref); ulReturn = InterlockedDecrement(&This->ref);
if(ulReturn) if (!ulReturn) {
return ulReturn; IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This);
This->dsb->ds3db = NULL;
if (This->dsb) { DeleteCriticalSection(&(This->lock));
BOOL std = (This->dsb->dsbd.dwFlags & DSBCAPS_CTRL3D); HeapFree(GetProcessHeap(),0,This);
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb);
if (std)
return 0; /* leave it to IDirectSoundBufferImpl_Release */
} }
if (This->dsb->ds3db == This) This->dsb->ds3db = NULL; return ulReturn;
DeleteCriticalSection(&This->lock);
HeapFree(GetProcessHeap(),0,This);
return 0;
} }
/* IDirectSound3DBuffer methods */ /* IDirectSound3DBuffer methods */
...@@ -410,8 +410,22 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters( ...@@ -410,8 +410,22 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters(
LPDS3DBUFFER lpDs3dBuffer) LPDS3DBUFFER lpDs3dBuffer)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: all parameters\n"); TRACE("(%p,%p)\n",This,lpDs3dBuffer);
*lpDs3dBuffer = This->ds3db;
if (lpDs3dBuffer == NULL) {
WARN("invalid paramater: lpDs3dBuffer == NULL\n");
return DSERR_INVALIDPARAM;
}
if (lpDs3dBuffer->dwSize < sizeof(*lpDs3dBuffer)) {
WARN("invalid paramater: lpDs3dBuffer->dwSize = %ld < %d\n",lpDs3dBuffer->dwSize, sizeof(*lpDs3dBuffer));
return DSERR_INVALIDPARAM;
}
if (This->dsb) {
TRACE("returning: all parameters\n");
*lpDs3dBuffer = This->dsb->ds3db_ds3db;
}
return DS_OK; return DS_OK;
} }
...@@ -421,9 +435,12 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles( ...@@ -421,9 +435,12 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles(
LPDWORD lpdwOutsideConeAngle) LPDWORD lpdwOutsideConeAngle)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: Inside Cone Angle = %ld degrees; Outside Cone Angle = %ld degrees\n", This->ds3db.dwInsideConeAngle, This->ds3db.dwOutsideConeAngle); if (This->dsb) {
*lpdwInsideConeAngle = This->ds3db.dwInsideConeAngle; TRACE("returning: Inside Cone Angle = %ld degrees; Outside Cone Angle = %ld degrees\n",
*lpdwOutsideConeAngle = This->ds3db.dwOutsideConeAngle; This->dsb->ds3db_ds3db.dwInsideConeAngle, This->dsb->ds3db_ds3db.dwOutsideConeAngle);
*lpdwInsideConeAngle = This->dsb->ds3db_ds3db.dwInsideConeAngle;
*lpdwOutsideConeAngle = This->dsb->ds3db_ds3db.dwOutsideConeAngle;
}
return DS_OK; return DS_OK;
} }
...@@ -432,8 +449,13 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation( ...@@ -432,8 +449,13 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOrientation(
LPD3DVECTOR lpvConeOrientation) LPD3DVECTOR lpvConeOrientation)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: Cone Orientation vector = (%f,%f,%f)\n", This->ds3db.vConeOrientation.u1.x, This->ds3db.vConeOrientation.u2.y, This->ds3db.vConeOrientation.u3.z); if (This->dsb) {
*lpvConeOrientation = This->ds3db.vConeOrientation; TRACE("returning: Cone Orientation vector = (%f,%f,%f)\n",
This->dsb->ds3db_ds3db.vConeOrientation.u1.x,
This->dsb->ds3db_ds3db.vConeOrientation.u2.y,
This->dsb->ds3db_ds3db.vConeOrientation.u3.z);
*lpvConeOrientation = This->dsb->ds3db_ds3db.vConeOrientation;
}
return DS_OK; return DS_OK;
} }
...@@ -442,8 +464,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume( ...@@ -442,8 +464,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume(
LPLONG lplConeOutsideVolume) LPLONG lplConeOutsideVolume)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: Cone Outside Volume = %ld\n", This->ds3db.lConeOutsideVolume); if (This->dsb) {
*lplConeOutsideVolume = This->ds3db.lConeOutsideVolume; TRACE("returning: Cone Outside Volume = %ld\n", This->dsb->ds3db_ds3db.lConeOutsideVolume);
*lplConeOutsideVolume = This->dsb->ds3db_ds3db.lConeOutsideVolume;
}
return DS_OK; return DS_OK;
} }
...@@ -452,8 +476,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance( ...@@ -452,8 +476,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetMaxDistance(
LPD3DVALUE lpfMaxDistance) LPD3DVALUE lpfMaxDistance)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: Max Distance = %f\n", This->ds3db.flMaxDistance); if (This->dsb) {
*lpfMaxDistance = This->ds3db.flMaxDistance; TRACE("returning: Max Distance = %f\n", This->dsb->ds3db_ds3db.flMaxDistance);
*lpfMaxDistance = This->dsb->ds3db_ds3db.flMaxDistance;
}
return DS_OK; return DS_OK;
} }
...@@ -462,8 +488,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance( ...@@ -462,8 +488,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetMinDistance(
LPD3DVALUE lpfMinDistance) LPD3DVALUE lpfMinDistance)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: Min Distance = %f\n", This->ds3db.flMinDistance); if (This->dsb) {
*lpfMinDistance = This->ds3db.flMinDistance; TRACE("returning: Min Distance = %f\n", This->dsb->ds3db_ds3db.flMinDistance);
*lpfMinDistance = This->dsb->ds3db_ds3db.flMinDistance;
}
return DS_OK; return DS_OK;
} }
...@@ -472,8 +500,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode( ...@@ -472,8 +500,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode(
LPDWORD lpdwMode) LPDWORD lpdwMode)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: Mode = %ld\n", This->ds3db.dwMode); if (This->dsb) {
*lpdwMode = This->ds3db.dwMode; TRACE("returning: Mode = %ld\n", This->dsb->ds3db_ds3db.dwMode);
*lpdwMode = This->dsb->ds3db_ds3db.dwMode;
}
return DS_OK; return DS_OK;
} }
...@@ -482,8 +512,13 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition( ...@@ -482,8 +512,13 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetPosition(
LPD3DVECTOR lpvPosition) LPD3DVECTOR lpvPosition)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: Position vector = (%f,%f,%f)\n", This->ds3db.vPosition.u1.x, This->ds3db.vPosition.u2.y, This->ds3db.vPosition.u1.x); if (This->dsb) {
*lpvPosition = This->ds3db.vPosition; TRACE("returning: Position vector = (%f,%f,%f)\n",
This->dsb->ds3db_ds3db.vPosition.u1.x,
This->dsb->ds3db_ds3db.vPosition.u2.y,
This->dsb->ds3db_ds3db.vPosition.u3.z);
*lpvPosition = This->dsb->ds3db_ds3db.vPosition;
}
return DS_OK; return DS_OK;
} }
...@@ -492,8 +527,13 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity( ...@@ -492,8 +527,13 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetVelocity(
LPD3DVECTOR lpvVelocity) LPD3DVECTOR lpvVelocity)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->ds3db.vVelocity.u1.x, This->ds3db.vVelocity.u2.y, This->ds3db.vVelocity.u3.z); if (This->dsb) {
*lpvVelocity = This->ds3db.vVelocity; TRACE("returning: Velocity vector = (%f,%f,%f)\n",
This->dsb->ds3db_ds3db.vVelocity.u1.x,
This->dsb->ds3db_ds3db.vVelocity.u2.y,
This->dsb->ds3db_ds3db.vVelocity.u3.z);
*lpvVelocity = This->dsb->ds3db_ds3db.vVelocity;
}
return DS_OK; return DS_OK;
} }
...@@ -503,14 +543,38 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters( ...@@ -503,14 +543,38 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters(
DWORD dwApply) DWORD dwApply)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: all parameters; dwApply = %ld\n", dwApply); DWORD status = DSERR_INVALIDPARAM;
This->ds3db = *lpcDs3dBuffer; TRACE("(%p,%p,%lx)\n",iface,lpcDs3dBuffer,dwApply);
if (dwApply == DS3D_IMMEDIATE)
{ if (lpcDs3dBuffer == NULL) {
DSOUND_Mix3DBuffer(This); WARN("invalid parameter: lpcDs3dBuffer == NULL\n");
return status;
} }
This->need_recalc = TRUE;
return DS_OK; if (lpcDs3dBuffer->dwSize != sizeof(DS3DBUFFER)) {
WARN("invalid parameter: lpcDs3dBuffer->dwSize = %ld != %d\n",
lpcDs3dBuffer->dwSize, sizeof(DS3DBUFFER));
return status;
}
EnterCriticalSection(&This->lock);
if (This->dsb) {
TRACE("setting: all parameters; dwApply = %ld\n", dwApply);
This->dsb->ds3db_ds3db = *lpcDs3dBuffer;
if (dwApply == DS3D_IMMEDIATE)
{
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
status = DS_OK;
} else
WARN("pointer no longer valid\n");
LeaveCriticalSection(&This->lock);
return status;
} }
static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles( static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
...@@ -520,14 +584,17 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles( ...@@ -520,14 +584,17 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles(
DWORD dwApply) DWORD dwApply)
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: Inside Cone Angle = %ld; Outside Cone Angle = %ld; dwApply = %ld\n", dwInsideConeAngle, dwOutsideConeAngle, dwApply); TRACE("setting: Inside Cone Angle = %ld; Outside Cone Angle = %ld; dwApply = %ld\n",
This->ds3db.dwInsideConeAngle = dwInsideConeAngle; dwInsideConeAngle, dwOutsideConeAngle, dwApply);
This->ds3db.dwOutsideConeAngle = dwOutsideConeAngle; if (This->dsb) {
if (dwApply == DS3D_IMMEDIATE) This->dsb->ds3db_ds3db.dwInsideConeAngle = dwInsideConeAngle;
{ This->dsb->ds3db_ds3db.dwOutsideConeAngle = dwOutsideConeAngle;
DSOUND_Mix3DBuffer(This); if (dwApply == DS3D_IMMEDIATE)
{
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
} }
This->need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -538,15 +605,17 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation( ...@@ -538,15 +605,17 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation(
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: Cone Orientation vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); TRACE("setting: Cone Orientation vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->ds3db.vConeOrientation.u1.x = x; if (This->dsb) {
This->ds3db.vConeOrientation.u2.y = y; This->dsb->ds3db_ds3db.vConeOrientation.u1.x = x;
This->ds3db.vConeOrientation.u3.z = z; This->dsb->ds3db_ds3db.vConeOrientation.u2.y = y;
if (dwApply == DS3D_IMMEDIATE) This->dsb->ds3db_ds3db.vConeOrientation.u3.z = z;
{ if (dwApply == DS3D_IMMEDIATE)
This->need_recalc = FALSE; {
DSOUND_Mix3DBuffer(This); This->dsb->ds3db_need_recalc = FALSE;
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
} }
This->need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -557,13 +626,15 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume( ...@@ -557,13 +626,15 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume(
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: ConeOutsideVolume = %ld; dwApply = %ld\n", lConeOutsideVolume, dwApply); TRACE("setting: ConeOutsideVolume = %ld; dwApply = %ld\n", lConeOutsideVolume, dwApply);
This->ds3db.lConeOutsideVolume = lConeOutsideVolume; if (This->dsb) {
if (dwApply == DS3D_IMMEDIATE) This->dsb->ds3db_ds3db.lConeOutsideVolume = lConeOutsideVolume;
{ if (dwApply == DS3D_IMMEDIATE)
This->need_recalc = FALSE; {
DSOUND_Mix3DBuffer(This); This->dsb->ds3db_need_recalc = FALSE;
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
} }
This->need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -574,13 +645,15 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance( ...@@ -574,13 +645,15 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance(
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: MaxDistance = %f; dwApply = %ld\n", fMaxDistance, dwApply); TRACE("setting: MaxDistance = %f; dwApply = %ld\n", fMaxDistance, dwApply);
This->ds3db.flMaxDistance = fMaxDistance; if (This->dsb) {
if (dwApply == DS3D_IMMEDIATE) This->dsb->ds3db_ds3db.flMaxDistance = fMaxDistance;
{ if (dwApply == DS3D_IMMEDIATE)
This->need_recalc = FALSE; {
DSOUND_Mix3DBuffer(This); This->dsb->ds3db_need_recalc = FALSE;
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
} }
This->need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -591,13 +664,15 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance( ...@@ -591,13 +664,15 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance(
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: MinDistance = %f; dwApply = %ld\n", fMinDistance, dwApply); TRACE("setting: MinDistance = %f; dwApply = %ld\n", fMinDistance, dwApply);
This->ds3db.flMinDistance = fMinDistance; if (This->dsb) {
if (dwApply == DS3D_IMMEDIATE) This->dsb->ds3db_ds3db.flMinDistance = fMinDistance;
{ if (dwApply == DS3D_IMMEDIATE)
This->need_recalc = FALSE; {
DSOUND_Mix3DBuffer(This); This->dsb->ds3db_need_recalc = FALSE;
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
} }
This->need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -608,13 +683,15 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode( ...@@ -608,13 +683,15 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode(
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: Mode = %ld; dwApply = %ld\n", dwMode, dwApply); TRACE("setting: Mode = %ld; dwApply = %ld\n", dwMode, dwApply);
This->ds3db.dwMode = dwMode; if (This->dsb) {
if (dwApply == DS3D_IMMEDIATE) This->dsb->ds3db_ds3db.dwMode = dwMode;
{ if (dwApply == DS3D_IMMEDIATE)
This->need_recalc = FALSE; {
DSOUND_Mix3DBuffer(This); This->dsb->ds3db_need_recalc = FALSE;
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
} }
This->need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -625,15 +702,17 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition( ...@@ -625,15 +702,17 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition(
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->ds3db.vPosition.u1.x = x; if (This->dsb) {
This->ds3db.vPosition.u2.y = y; This->dsb->ds3db_ds3db.vPosition.u1.x = x;
This->ds3db.vPosition.u3.z = z; This->dsb->ds3db_ds3db.vPosition.u2.y = y;
if (dwApply == DS3D_IMMEDIATE) This->dsb->ds3db_ds3db.vPosition.u3.z = z;
{ if (dwApply == DS3D_IMMEDIATE)
This->need_recalc = FALSE; {
DSOUND_Mix3DBuffer(This); This->dsb->ds3db_need_recalc = FALSE;
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
} }
This->need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -644,15 +723,17 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity( ...@@ -644,15 +723,17 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity(
{ {
ICOM_THIS(IDirectSound3DBufferImpl,iface); ICOM_THIS(IDirectSound3DBufferImpl,iface);
TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->ds3db.vVelocity.u1.x = x; if (This->dsb) {
This->ds3db.vVelocity.u2.y = y; This->dsb->ds3db_ds3db.vVelocity.u1.x = x;
This->ds3db.vVelocity.u3.z = z; This->dsb->ds3db_ds3db.vVelocity.u2.y = y;
if (dwApply == DS3D_IMMEDIATE) This->dsb->ds3db_ds3db.vVelocity.u3.z = z;
{ if (dwApply == DS3D_IMMEDIATE)
This->need_recalc = FALSE; {
DSOUND_Mix3DBuffer(This); This->dsb->ds3db_need_recalc = FALSE;
DSOUND_Mix3DBuffer(This->dsb);
}
This->dsb->ds3db_need_recalc = TRUE;
} }
This->need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -695,30 +776,34 @@ HRESULT WINAPI IDirectSound3DBufferImpl_Create( ...@@ -695,30 +776,34 @@ HRESULT WINAPI IDirectSound3DBufferImpl_Create(
if (ds3db == NULL) { if (ds3db == NULL) {
WARN("out of memory\n"); WARN("out of memory\n");
*pds3db = 0;
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
} }
ds3db->ref = 0; ds3db->ref = 0;
ds3db->dsb = This; ds3db->dsb = This;
ds3db->lpVtbl = &ds3dbvt; ds3db->lpVtbl = &ds3dbvt;
InitializeCriticalSection(&ds3db->lock);
ds3db->dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER);
ds3db->ds3db.dwSize = sizeof(DS3DBUFFER); ds3db->dsb->ds3db_ds3db.vPosition.u1.x = 0.0;
ds3db->ds3db.vPosition.u1.x = 0.0; ds3db->dsb->ds3db_ds3db.vPosition.u2.y = 0.0;
ds3db->ds3db.vPosition.u2.y = 0.0; ds3db->dsb->ds3db_ds3db.vPosition.u3.z = 0.0;
ds3db->ds3db.vPosition.u3.z = 0.0; ds3db->dsb->ds3db_ds3db.vVelocity.u1.x = 0.0;
ds3db->ds3db.vVelocity.u1.x = 0.0; ds3db->dsb->ds3db_ds3db.vVelocity.u2.y = 0.0;
ds3db->ds3db.vVelocity.u2.y = 0.0; ds3db->dsb->ds3db_ds3db.vVelocity.u3.z = 0.0;
ds3db->ds3db.vVelocity.u3.z = 0.0; ds3db->dsb->ds3db_ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE;
ds3db->ds3db.dwInsideConeAngle = DS3D_DEFAULTCONEANGLE; ds3db->dsb->ds3db_ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE;
ds3db->ds3db.dwOutsideConeAngle = DS3D_DEFAULTCONEANGLE; ds3db->dsb->ds3db_ds3db.vConeOrientation.u1.x = 0.0;
ds3db->ds3db.vConeOrientation.u1.x = 0.0; ds3db->dsb->ds3db_ds3db.vConeOrientation.u2.y = 0.0;
ds3db->ds3db.vConeOrientation.u2.y = 0.0; ds3db->dsb->ds3db_ds3db.vConeOrientation.u3.z = 0.0;
ds3db->ds3db.vConeOrientation.u3.z = 0.0; ds3db->dsb->ds3db_ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME;
ds3db->ds3db.lConeOutsideVolume = DS3D_DEFAULTCONEOUTSIDEVOLUME; ds3db->dsb->ds3db_ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE;
ds3db->ds3db.flMinDistance = DS3D_DEFAULTMINDISTANCE; ds3db->dsb->ds3db_ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE;
ds3db->ds3db.flMaxDistance = DS3D_DEFAULTMAXDISTANCE; ds3db->dsb->ds3db_ds3db.dwMode = DS3DMODE_NORMAL;
ds3db->ds3db.dwMode = DS3DMODE_NORMAL;
ds3db->dsb->ds3db_need_recalc = TRUE;
InitializeCriticalSection(&(ds3db->lock));
*pds3db = ds3db; *pds3db = ds3db;
return S_OK; return S_OK;
...@@ -735,14 +820,38 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface( ...@@ -735,14 +820,38 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface(
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj);
return IDirectSoundBuffer_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj);
if ( IsEqualGUID(riid, &IID_IUnknown) ||
IsEqualGUID(riid, &IID_IDirectSound3DListener ) ) {
IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)This);
*ppobj = This;
return S_OK;
}
if ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) {
*ppobj = This->dsound->primary;
IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj);
return S_OK;
}
FIXME( "Unknown IID %s\n", debugstr_guid( riid ) );
*ppobj = NULL;
return E_NOINTERFACE;
} }
static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface) static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER iface)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("(%p) ref was %ld\n", This, This->ref); ULONG ref;
return InterlockedIncrement(&This->ref); TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
ref = InterlockedIncrement(&This->ref);
if (!ref) {
FIXME("thread-safety alert! AddRef-ing with a zero refcount!\n");
}
return ref;
} }
static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface) static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER iface)
...@@ -750,15 +859,13 @@ static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER i ...@@ -750,15 +859,13 @@ static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER i
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
ULONG ulReturn; ULONG ulReturn;
TRACE("(%p) ref was %ld\n", This, This->ref); TRACE("(%p) ref was %ld, thread is %04lx\n",This, This->ref, GetCurrentThreadId());
ulReturn = InterlockedDecrement(&This->ref); ulReturn = InterlockedDecrement(&This->ref);
/* Free all resources */ /* Free all resources */
if( ulReturn == 0 ) { if( ulReturn == 0 ) {
if(This->dsb) IDirectSound8_Release((LPDIRECTSOUND8)This->dsound);
IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb); This->dsound->listener = 0;
DeleteCriticalSection(&This->lock);
HeapFree(GetProcessHeap(),0,This); HeapFree(GetProcessHeap(),0,This);
} }
...@@ -771,8 +878,20 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter( ...@@ -771,8 +878,20 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter(
LPDS3DLISTENER lpDS3DL) LPDS3DLISTENER lpDS3DL)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("(%p,%p)\n",This,lpDS3DL);
if (lpDS3DL == NULL) {
WARN("invalid paramater: lpDS3DL == NULL\n");
return DSERR_INVALIDPARAM;
}
if (lpDS3DL->dwSize < sizeof(*lpDS3DL)) {
WARN("invalid paramater: lpDS3DL->dwSize = %ld < %d\n",lpDS3DL->dwSize, sizeof(*lpDS3DL));
return DSERR_INVALIDPARAM;
}
TRACE("returning: all parameters\n"); TRACE("returning: all parameters\n");
*lpDS3DL = This->ds3dl; *lpDS3DL = This->dsound->ds3dl;
return DS_OK; return DS_OK;
} }
...@@ -781,8 +900,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor( ...@@ -781,8 +900,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor(
LPD3DVALUE lpfDistanceFactor) LPD3DVALUE lpfDistanceFactor)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("returning: Distance Factor = %f\n", This->ds3dl.flDistanceFactor); TRACE("returning: Distance Factor = %f\n", This->dsound->ds3dl.flDistanceFactor);
*lpfDistanceFactor = This->ds3dl.flDistanceFactor; *lpfDistanceFactor = This->dsound->ds3dl.flDistanceFactor;
return DS_OK; return DS_OK;
} }
...@@ -791,8 +910,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor( ...@@ -791,8 +910,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor(
LPD3DVALUE lpfDopplerFactor) LPD3DVALUE lpfDopplerFactor)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("returning: Doppler Factor = %f\n", This->ds3dl.flDopplerFactor); TRACE("returning: Doppler Factor = %f\n", This->dsound->ds3dl.flDopplerFactor);
*lpfDopplerFactor = This->ds3dl.flDopplerFactor; *lpfDopplerFactor = This->dsound->ds3dl.flDopplerFactor;
return DS_OK; return DS_OK;
} }
...@@ -802,11 +921,11 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation( ...@@ -802,11 +921,11 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation(
LPD3DVECTOR lpvOrientTop) LPD3DVECTOR lpvOrientTop)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->ds3dl.vOrientFront.u1.x, \ TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->dsound->ds3dl.vOrientFront.u1.x, \
This->ds3dl.vOrientFront.u2.y, This->ds3dl.vOrientFront.u3.z, This->ds3dl.vOrientTop.u1.x, This->ds3dl.vOrientTop.u2.y, \ This->dsound->ds3dl.vOrientFront.u2.y, This->dsound->ds3dl.vOrientFront.u3.z, This->dsound->ds3dl.vOrientTop.u1.x, This->dsound->ds3dl.vOrientTop.u2.y, \
This->ds3dl.vOrientTop.u3.z); This->dsound->ds3dl.vOrientTop.u3.z);
*lpvOrientFront = This->ds3dl.vOrientFront; *lpvOrientFront = This->dsound->ds3dl.vOrientFront;
*lpvOrientTop = This->ds3dl.vOrientTop; *lpvOrientTop = This->dsound->ds3dl.vOrientTop;
return DS_OK; return DS_OK;
} }
...@@ -815,8 +934,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition( ...@@ -815,8 +934,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition(
LPD3DVECTOR lpvPosition) LPD3DVECTOR lpvPosition)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("returning: Position vector = (%f,%f,%f)\n", This->ds3dl.vPosition.u1.x, This->ds3dl.vPosition.u2.y, This->ds3dl.vPosition.u3.z); TRACE("returning: Position vector = (%f,%f,%f)\n", This->dsound->ds3dl.vPosition.u1.x, This->dsound->ds3dl.vPosition.u2.y, This->dsound->ds3dl.vPosition.u3.z);
*lpvPosition = This->ds3dl.vPosition; *lpvPosition = This->dsound->ds3dl.vPosition;
return DS_OK; return DS_OK;
} }
...@@ -825,8 +944,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor( ...@@ -825,8 +944,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor(
LPD3DVALUE lpfRolloffFactor) LPD3DVALUE lpfRolloffFactor)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("returning: RolloffFactor = %f\n", This->ds3dl.flRolloffFactor); TRACE("returning: RolloffFactor = %f\n", This->dsound->ds3dl.flRolloffFactor);
*lpfRolloffFactor = This->ds3dl.flRolloffFactor; *lpfRolloffFactor = This->dsound->ds3dl.flRolloffFactor;
return DS_OK; return DS_OK;
} }
...@@ -835,8 +954,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity( ...@@ -835,8 +954,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity(
LPD3DVECTOR lpvVelocity) LPD3DVECTOR lpvVelocity)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->ds3dl.vVelocity.u1.x, This->ds3dl.vVelocity.u2.y, This->ds3dl.vVelocity.u3.z); TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->dsound->ds3dl.vVelocity.u1.x, This->dsound->ds3dl.vVelocity.u2.y, This->dsound->ds3dl.vVelocity.u3.z);
*lpvVelocity = This->ds3dl.vVelocity; *lpvVelocity = This->dsound->ds3dl.vVelocity;
return DS_OK; return DS_OK;
} }
...@@ -847,13 +966,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters( ...@@ -847,13 +966,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters(
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("setting: all parameters; dwApply = %ld\n", dwApply); TRACE("setting: all parameters; dwApply = %ld\n", dwApply);
This->ds3dl = *lpcDS3DL; This->dsound->ds3dl = *lpcDS3DL;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->need_recalc = FALSE; This->dsound->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->need_recalc = TRUE; This->dsound->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -864,13 +983,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor( ...@@ -864,13 +983,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor(
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("setting: Distance Factor = %f; dwApply = %ld\n", fDistanceFactor, dwApply); TRACE("setting: Distance Factor = %f; dwApply = %ld\n", fDistanceFactor, dwApply);
This->ds3dl.flDistanceFactor = fDistanceFactor; This->dsound->ds3dl.flDistanceFactor = fDistanceFactor;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->need_recalc = FALSE; This->dsound->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->need_recalc = TRUE; This->dsound->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -881,13 +1000,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor( ...@@ -881,13 +1000,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor(
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("setting: Doppler Factor = %f; dwApply = %ld\n", fDopplerFactor, dwApply); TRACE("setting: Doppler Factor = %f; dwApply = %ld\n", fDopplerFactor, dwApply);
This->ds3dl.flDopplerFactor = fDopplerFactor; This->dsound->ds3dl.flDopplerFactor = fDopplerFactor;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->need_recalc = FALSE; This->dsound->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->need_recalc = TRUE; This->dsound->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -900,18 +1019,18 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation( ...@@ -900,18 +1019,18 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation(
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %ld\n", \ TRACE("setting: Front vector = (%f,%f,%f); Top vector = (%f,%f,%f); dwApply = %ld\n", \
xFront, yFront, zFront, xTop, yTop, zTop, dwApply); xFront, yFront, zFront, xTop, yTop, zTop, dwApply);
This->ds3dl.vOrientFront.u1.x = xFront; This->dsound->ds3dl.vOrientFront.u1.x = xFront;
This->ds3dl.vOrientFront.u2.y = yFront; This->dsound->ds3dl.vOrientFront.u2.y = yFront;
This->ds3dl.vOrientFront.u3.z = zFront; This->dsound->ds3dl.vOrientFront.u3.z = zFront;
This->ds3dl.vOrientTop.u1.x = xTop; This->dsound->ds3dl.vOrientTop.u1.x = xTop;
This->ds3dl.vOrientTop.u2.y = yTop; This->dsound->ds3dl.vOrientTop.u2.y = yTop;
This->ds3dl.vOrientTop.u3.z = zTop; This->dsound->ds3dl.vOrientTop.u3.z = zTop;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->need_recalc = FALSE; This->dsound->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->need_recalc = TRUE; This->dsound->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -922,15 +1041,15 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition( ...@@ -922,15 +1041,15 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition(
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->ds3dl.vPosition.u1.x = x; This->dsound->ds3dl.vPosition.u1.x = x;
This->ds3dl.vPosition.u2.y = y; This->dsound->ds3dl.vPosition.u2.y = y;
This->ds3dl.vPosition.u3.z = z; This->dsound->ds3dl.vPosition.u3.z = z;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->need_recalc = FALSE; This->dsound->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->need_recalc = TRUE; This->dsound->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -941,13 +1060,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor( ...@@ -941,13 +1060,13 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor(
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("setting: Rolloff Factor = %f; dwApply = %ld\n", fRolloffFactor, dwApply); TRACE("setting: Rolloff Factor = %f; dwApply = %ld\n", fRolloffFactor, dwApply);
This->ds3dl.flRolloffFactor = fRolloffFactor; This->dsound->ds3dl.flRolloffFactor = fRolloffFactor;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->need_recalc = FALSE; This->dsound->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->need_recalc = TRUE; This->dsound->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
...@@ -958,21 +1077,20 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity( ...@@ -958,21 +1077,20 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity(
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply);
This->ds3dl.vVelocity.u1.x = x; This->dsound->ds3dl.vVelocity.u1.x = x;
This->ds3dl.vVelocity.u2.y = y; This->dsound->ds3dl.vVelocity.u2.y = y;
This->ds3dl.vVelocity.u3.z = z; This->dsound->ds3dl.vVelocity.u3.z = z;
if (dwApply == DS3D_IMMEDIATE) if (dwApply == DS3D_IMMEDIATE)
{ {
This->need_recalc = FALSE; This->dsound->ds3dl_need_recalc = FALSE;
DSOUND_ChangeListener(This); DSOUND_ChangeListener(This);
} }
This->need_recalc = TRUE; This->dsound->ds3dl_need_recalc = TRUE;
return DS_OK; return DS_OK;
} }
static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings( static HRESULT WINAPI IDirectSound3DListenerImpl_CommitDeferredSettings(
LPDIRECTSOUND3DLISTENER iface) LPDIRECTSOUND3DLISTENER iface)
{ {
ICOM_THIS(IDirectSound3DListenerImpl,iface); ICOM_THIS(IDirectSound3DListenerImpl,iface);
TRACE("\n"); TRACE("\n");
...@@ -1016,34 +1134,37 @@ HRESULT WINAPI IDirectSound3DListenerImpl_Create( ...@@ -1016,34 +1134,37 @@ HRESULT WINAPI IDirectSound3DListenerImpl_Create(
if (dsl == NULL) { if (dsl == NULL) {
WARN("out of memory\n"); WARN("out of memory\n");
*pdsl = 0;
return DSERR_OUTOFMEMORY; return DSERR_OUTOFMEMORY;
} }
dsl->ref = 1; dsl->ref = 0;
dsl->lpVtbl = &ds3dlvt; dsl->lpVtbl = &ds3dlvt;
dsl->ds3dl.dwSize = sizeof(DS3DLISTENER); dsl->dsound = This->dsound;
dsl->ds3dl.vPosition.u1.x = 0.0;
dsl->ds3dl.vPosition.u2.y = 0.0; dsl->dsound->ds3dl.dwSize = sizeof(DS3DLISTENER);
dsl->ds3dl.vPosition.u3.z = 0.0; dsl->dsound->ds3dl.vPosition.u1.x = 0.0;
dsl->ds3dl.vVelocity.u1.x = 0.0; dsl->dsound->ds3dl.vPosition.u2.y = 0.0;
dsl->ds3dl.vVelocity.u2.y = 0.0; dsl->dsound->ds3dl.vPosition.u3.z = 0.0;
dsl->ds3dl.vVelocity.u3.z = 0.0; dsl->dsound->ds3dl.vVelocity.u1.x = 0.0;
dsl->ds3dl.vOrientFront.u1.x = 0.0; dsl->dsound->ds3dl.vVelocity.u2.y = 0.0;
dsl->ds3dl.vOrientFront.u2.y = 0.0; dsl->dsound->ds3dl.vVelocity.u3.z = 0.0;
dsl->ds3dl.vOrientFront.u3.z = 1.0; dsl->dsound->ds3dl.vOrientFront.u1.x = 0.0;
dsl->ds3dl.vOrientTop.u1.x = 0.0; dsl->dsound->ds3dl.vOrientFront.u2.y = 0.0;
dsl->ds3dl.vOrientTop.u2.y = 1.0; dsl->dsound->ds3dl.vOrientFront.u3.z = 1.0;
dsl->ds3dl.vOrientTop.u3.z = 0.0; dsl->dsound->ds3dl.vOrientTop.u1.x = 0.0;
dsl->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; dsl->dsound->ds3dl.vOrientTop.u2.y = 1.0;
dsl->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; dsl->dsound->ds3dl.vOrientTop.u3.z = 0.0;
dsl->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR; dsl->dsound->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR;
dsl->dsound->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR;
InitializeCriticalSection(&dsl->lock); dsl->dsound->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR;
dsl->dsb = This; dsl->dsound->ds3dl_need_recalc = TRUE;
/* NOTE: don't add a reference because it would cause a circular reference */
/* IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This); */ InitializeCriticalSection(&dsl->dsound->ds3dl_lock);
IDirectSound8_AddRef((LPDIRECTSOUND8)This->dsound);
*pdsl = dsl; *pdsl = dsl;
return S_OK; return S_OK;
......
...@@ -18,6 +18,10 @@ ...@@ -18,6 +18,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#define NONAMELESSSTRUCT
#define NONAMELESSUNION
#include <windows.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -26,6 +30,10 @@ ...@@ -26,6 +30,10 @@
#include "initguid.h" #include "initguid.h"
#include "dsound.h" #include "dsound.h"
#ifndef DSBCAPS_CTRLDEFAULT
#define DSBCAPS_CTRLDEFAULT 0x000000E0
#endif
static const unsigned int formats[][3]={ static const unsigned int formats[][3]={
{ 8000, 8, 1}, { 8000, 8, 1},
{ 8000, 8, 2}, { 8000, 8, 2},
...@@ -78,23 +86,23 @@ static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size) ...@@ -78,23 +86,23 @@ static char* wave_generate_la(WAVEFORMATEX* wfx, double duration, DWORD* size)
*size=nb_samples*wfx->nBlockAlign; *size=nb_samples*wfx->nBlockAlign;
b=buf=malloc(*size); b=buf=malloc(*size);
for (i=0;i<nb_samples;i++) { for (i=0;i<nb_samples;i++) {
double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec); double y=sin(440.0*2*PI*i/wfx->nSamplesPerSec);
if (wfx->wBitsPerSample==8) { if (wfx->wBitsPerSample==8) {
unsigned char sample=(unsigned char)((double)127.5*(y+1.0)); unsigned char sample=(unsigned char)((double)127.5*(y+1.0));
*b++=sample; *b++=sample;
if (wfx->nChannels==2) if (wfx->nChannels==2)
*b++=sample; *b++=sample;
} else { } else {
signed short sample=(signed short)((double)32767.5*y-0.5); signed short sample=(signed short)((double)32767.5*y-0.5);
b[0]=sample & 0xff; b[0]=sample & 0xff;
b[1]=sample >> 8; b[1]=sample >> 8;
b+=2; b+=2;
if (wfx->nChannels==2) { if (wfx->nChannels==2) {
b[0]=sample & 0xff; b[0]=sample & 0xff;
b[1]=sample >> 8; b[1]=sample >> 8;
b+=2; b+=2;
} }
} }
} }
return buf; return buf;
} }
...@@ -103,7 +111,7 @@ static HWND get_hwnd() ...@@ -103,7 +111,7 @@ static HWND get_hwnd()
{ {
HWND hwnd=GetForegroundWindow(); HWND hwnd=GetForegroundWindow();
if (!hwnd) if (!hwnd)
hwnd=GetDesktopWindow(); hwnd=GetDesktopWindow();
return hwnd; return hwnd;
} }
...@@ -138,25 +146,25 @@ static int buffer_refill(play_state_t* state, DWORD size) ...@@ -138,25 +146,25 @@ static int buffer_refill(play_state_t* state, DWORD size)
HRESULT rc; HRESULT rc;
if (size>state->wave_len-state->written) if (size>state->wave_len-state->written)
size=state->wave_len-state->written; size=state->wave_len-state->written;
rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size, rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
&ptr1,&len1,&ptr2,&len2,0); &ptr1,&len1,&ptr2,&len2,0);
ok(rc==DS_OK,"Lock: 0x%lx",rc); ok(rc==DS_OK,"Lock: 0x%lx",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return -1; return -1;
memcpy(ptr1,state->wave+state->written,len1); memcpy(ptr1,state->wave+state->written,len1);
state->written+=len1; state->written+=len1;
if (ptr2!=NULL) { if (ptr2!=NULL) {
memcpy(ptr2,state->wave+state->written,len2); memcpy(ptr2,state->wave+state->written,len2);
state->written+=len2; state->written+=len2;
} }
state->offset=state->written % state->buffer_size; state->offset=state->written % state->buffer_size;
rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2); rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
ok(rc==DS_OK,"Unlock: 0x%lx",rc); ok(rc==DS_OK,"Unlock: 0x%lx",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return -1; return -1;
return size; return size;
} }
...@@ -168,21 +176,21 @@ static int buffer_silence(play_state_t* state, DWORD size) ...@@ -168,21 +176,21 @@ static int buffer_silence(play_state_t* state, DWORD size)
BYTE s; BYTE s;
rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size, rc=IDirectSoundBuffer_Lock(state->dsbo,state->offset,size,
&ptr1,&len1,&ptr2,&len2,0); &ptr1,&len1,&ptr2,&len2,0);
ok(rc==DS_OK,"Lock: 0x%lx",rc); ok(rc==DS_OK,"Lock: 0x%lx",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return -1; return -1;
s=(state->wfx->wBitsPerSample==8?0x80:0); s=(state->wfx->wBitsPerSample==8?0x80:0);
memset(ptr1,s,len1); memset(ptr1,s,len1);
if (ptr2!=NULL) { if (ptr2!=NULL) {
memset(ptr2,s,len2); memset(ptr2,s,len2);
} }
state->offset=(state->offset+size) % state->buffer_size; state->offset=(state->offset+size) % state->buffer_size;
rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2); rc=IDirectSoundBuffer_Unlock(state->dsbo,ptr1,len1,ptr2,len2);
ok(rc==DS_OK,"Unlock: 0x%lx",rc); ok(rc==DS_OK,"Unlock: 0x%lx",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return -1; return -1;
return size; return size;
} }
...@@ -194,70 +202,79 @@ static int buffer_service(play_state_t* state) ...@@ -194,70 +202,79 @@ static int buffer_service(play_state_t* state)
rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,&write_pos); rc=IDirectSoundBuffer_GetCurrentPosition(state->dsbo,&play_pos,&write_pos);
ok(rc==DS_OK,"GetCurrentPosition: %lx",rc); ok(rc==DS_OK,"GetCurrentPosition: %lx",rc);
if (rc!=DS_OK) { if (rc!=DS_OK) {
goto STOP; goto STOP;
} }
/* Refill the buffer */ /* Refill the buffer */
if (state->offset<=play_pos) { if (state->offset<=play_pos) {
buf_free=play_pos-state->offset; buf_free=play_pos-state->offset;
} else { } else {
buf_free=state->buffer_size-state->offset+play_pos; buf_free=state->buffer_size-state->offset+play_pos;
} }
if (winetest_debug > 1) if (winetest_debug > 1)
trace("buf pos=%ld free=%ld written=%ld / %ld\n", trace("buf pos=%ld free=%ld written=%ld / %ld\n",
play_pos,buf_free,state->written,state->wave_len); play_pos,buf_free,state->written,state->wave_len);
if (buf_free==0) if (buf_free==0)
return 1; return 1;
if (state->written<state->wave_len) { if (state->written<state->wave_len) {
int w=buffer_refill(state,buf_free); int w=buffer_refill(state,buf_free);
if (w==-1) if (w==-1)
goto STOP; goto STOP;
buf_free-=w; buf_free-=w;
if (state->written==state->wave_len) { if (state->written==state->wave_len) {
state->last_pos=(state->offset<play_pos)?play_pos:0; state->last_pos=(state->offset<play_pos)?play_pos:0;
if (winetest_debug > 1) if (winetest_debug > 1)
trace("last sound byte at %ld\n", trace("last sound byte at %ld\n",
(state->written % state->buffer_size)); (state->written % state->buffer_size));
} }
} else { } else {
if (state->last_pos!=0 && play_pos<state->last_pos) { if (state->last_pos!=0 && play_pos<state->last_pos) {
/* We wrapped around the end of the buffer */ /* We wrapped around the end of the buffer */
state->last_pos=0; state->last_pos=0;
} }
if (state->last_pos==0 && if (state->last_pos==0 &&
play_pos>(state->written % state->buffer_size)) { play_pos>(state->written % state->buffer_size)) {
/* Now everything has been played */ /* Now everything has been played */
goto STOP; goto STOP;
} }
} }
if (buf_free>0) { if (buf_free>0) {
/* Fill with silence */ /* Fill with silence */
if (winetest_debug > 1) if (winetest_debug > 1)
trace("writing %ld bytes of silence\n",buf_free); trace("writing %ld bytes of silence\n",buf_free);
if (buffer_silence(state,buf_free)==-1) if (buffer_silence(state,buf_free)==-1)
goto STOP; goto STOP;
} }
return 1; return 1;
STOP: STOP:
if (winetest_debug > 1) if (winetest_debug > 1)
trace("stopping playback\n"); trace("stopping playback\n");
rc=IDirectSoundBuffer_Stop(state->dsbo); rc=IDirectSoundBuffer_Stop(state->dsbo);
ok(rc==DS_OK,"Stop failed: rc=%ld",rc); ok(rc==DS_OK,"Stop failed: rc=%ld",rc);
return 0; return 0;
} }
static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo, static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
int primary, int play) int is_primary, int play, int buffer3d,
LPDIRECTSOUND3DLISTENER listener,
int move_listener, int move_sound)
{ {
HRESULT rc; HRESULT rc;
DSBCAPS dsbcaps; DSBCAPS dsbcaps;
WAVEFORMATEX wfx,wfx2; WAVEFORMATEX wfx,wfx2;
DWORD size,status,freq; DWORD size,status,freq;
int ref;
dsbcaps.dwSize=0; /* DSOUND: Error: Invalid caps pointer */
rc=IDirectSoundBuffer_GetCaps(dsbo,0);
ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
ZeroMemory(&dsbcaps, sizeof(dsbcaps));
/* DSOUND: Error: Invalid caps pointer */
rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps); rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc); ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
...@@ -265,8 +282,8 @@ static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo, ...@@ -265,8 +282,8 @@ static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps); rc=IDirectSoundBuffer_GetCaps(dsbo,&dsbcaps);
ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
trace(" Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags, trace(" Caps: flags=0x%08lx size=%ld\n",dsbcaps.dwFlags,
dsbcaps.dwBufferBytes); dsbcaps.dwBufferBytes);
} }
/* Query the format size. Note that it may not match sizeof(wfx) */ /* Query the format size. Note that it may not match sizeof(wfx) */
...@@ -279,206 +296,583 @@ static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo, ...@@ -279,206 +296,583 @@ static void test_buffer(LPDIRECTSOUND dso, LPDIRECTSOUNDBUFFER dsbo,
rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL); rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n", trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample, wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign); wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
} }
/* DSOUND: Error: Invalid frequency buffer */
rc=IDirectSoundBuffer_GetFrequency(dsbo,0);
ok(rc==DSERR_INVALIDPARAM,"GetFrequency should have failed: 0x%lx\n",rc);
/* DSOUND: Error: Primary buffers don't support CTRLFREQUENCY */
rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq); rc=IDirectSoundBuffer_GetFrequency(dsbo,&freq);
ok(rc==DS_OK || rc==DSERR_CONTROLUNAVAIL,"GetFrequency failed: 0x%lx\n",rc); ok((rc==DS_OK&&!is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary),
"GetFrequency failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
ok(freq==wfx.nSamplesPerSec, ok(freq==wfx.nSamplesPerSec,
"The frequency returned by GetFrequency %ld does not match the format %ld\n", "The frequency returned by GetFrequency %ld does not match the format %ld\n",
freq,wfx.nSamplesPerSec); freq,wfx.nSamplesPerSec);
} }
/* DSOUND: Error: Invalid status pointer */
rc=IDirectSoundBuffer_GetStatus(dsbo,0);
ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_GetStatus(dsbo,&status); rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
trace(" status=0x%04lx\n",status); trace(" status=0x%04lx\n",status);
}
if (primary) {
init_format(&wfx2,11025,16,2);
rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
/* There is no garantee that SetFormat will actually change the
* format to what we asked for. It depends on what the soundcard
* supports. So we must re-query the format.
*/
rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
if (rc==DS_OK) {
trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
}
} }
if (play) { if (is_primary) {
play_state_t state; /* We must call SetCooperativeLevel to be allowed to call SetFormat */
LONG volume; /* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
if(rc!=DS_OK)
return;
/* DSOUND: Error: Invalid format pointer */
rc=IDirectSoundBuffer_SetFormat(dsbo,0);
ok(rc==DSERR_INVALIDPARAM,"SetFormat should have failed: 0x%lx\n",rc);
init_format(&wfx2,11025,16,2);
rc=IDirectSoundBuffer_SetFormat(dsbo,&wfx2);
ok(rc==DS_OK,"SetFormat failed: 0x%lx\n",rc);
/* There is no garantee that SetFormat will actually change the
* format to what we asked for. It depends on what the soundcard
* supports. So we must re-query the format.
*/
rc=IDirectSoundBuffer_GetFormat(dsbo,&wfx,sizeof(wfx),NULL);
ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
if (rc==DS_OK) {
trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
}
trace(" Playing 440Hz LA at %ldx%2dx%d\n", /* Set the CooperativeLevel back to normal */
wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels); /* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
}
if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) { if (play) {
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume); play_state_t state;
ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc); LONG volume;
LPDIRECTSOUND3DBUFFER buffer=NULL;
DS3DBUFFER buffer_param;
DS3DLISTENER listener_param;
trace(" Playing 440Hz LA at %ldx%dx%d\n",
wfx.nSamplesPerSec, wfx.wBitsPerSample,wfx.nChannels);
if (is_primary) {
/* We must call SetCooperativeLevel to be allowed to call Lock */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_WRITEPRIMARY */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_WRITEPRIMARY);
ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
if (rc!=DS_OK)
return;
}
if (buffer3d) {
LPDIRECTSOUNDBUFFER temp_buffer;
rc=IDirectSoundBuffer_QueryInterface(dsbo,&IID_IDirectSound3DBuffer,(LPVOID *)&buffer);
ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
if(rc!=DS_OK)
return;
/* check the COM interface */
rc=IDirectSoundBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
ok(rc==DS_OK&&temp_buffer!=NULL,"QueryInterface failed: 0x%lx\n",rc);
ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
ref=IDirectSoundBuffer_Release(temp_buffer);
ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
temp_buffer=NULL;
rc=IDirectSound3DBuffer_QueryInterface(dsbo, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSound3DBuffer_QueryInterface failed: 0x%lx\n",rc);
ok(temp_buffer==dsbo,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)dsbo);
ref=IDirectSoundBuffer_Release(temp_buffer);
ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
/* DSOUND: Error: Invalid buffer */
rc=IDirectSound3DBuffer_GetAllParameters(buffer,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
ZeroMemory(&buffer_param, sizeof(buffer_param));
/* DSOUND: Error: Invalid buffer */
rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
buffer_param.dwSize=sizeof(buffer_param);
rc=IDirectSound3DBuffer_GetAllParameters(buffer,&buffer_param);
ok(rc==DS_OK,"IDirectSound3DBuffer_GetAllParameters failed: 0x%lx\n",rc);
}
if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
rc=IDirectSoundBuffer_SetVolume(dsbo,-300); rc=IDirectSoundBuffer_SetVolume(dsbo,-300);
ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc); ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
} }
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
ok(rc==DS_OK,"GetVolume failed: 0x%lx\n",rc);
if (rc==DS_OK) {
trace(" volume=%ld\n",volume);
}
state.wave=wave_generate_la(&wfx,((double)TONE_DURATION)/1000,&state.wave_len); /* DSOUND: Error: Buffer does not have CTRLVOLUME */
rc=IDirectSoundBuffer_GetVolume(dsbo,&volume);
ok((rc==DS_OK&&!is_primary) || (rc==DSERR_CONTROLUNAVAIL&&is_primary),"GetVolume failed: 0x%lx\n",rc);
if (rc==DS_OK) {
trace(" volume=%ld\n",volume);
}
state.dsbo=dsbo; state.wave=wave_generate_la(&wfx,((double)TONE_DURATION)/1000,&state.wave_len);
state.wfx=&wfx;
state.buffer_size=dsbcaps.dwBufferBytes; state.dsbo=dsbo;
state.written=state.offset=0; state.wfx=&wfx;
buffer_refill(&state,state.buffer_size); state.buffer_size=dsbcaps.dwBufferBytes;
state.written=state.offset=0;
buffer_refill(&state,state.buffer_size);
rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING);
ok(rc==DS_OK,"Play: 0x%lx\n",rc);
rc=IDirectSoundBuffer_GetStatus(dsbo,&status);
ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING),
"GetStatus: bad status: %lx",status);
/* FIXME: set position here someday */
if (listener) {
ZeroMemory(&listener_param,sizeof(listener_param));
listener_param.dwSize=sizeof(listener_param);
rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
if (move_listener)
listener_param.vPosition.u1.x = -5.0;
else
listener_param.vPosition.u1.x = 0.0;
listener_param.vPosition.u2.y = 0.0;
listener_param.vPosition.u3.z = 0.0;
rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.u1.x,listener_param.vPosition.u2.y,listener_param.vPosition.u3.z,DS3D_IMMEDIATE);
ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
}
if (buffer3d) {
if (move_sound)
buffer_param.vPosition.u1.x = 5.0;
else
buffer_param.vPosition.u1.x = 0.0;
buffer_param.vPosition.u2.y = 0.0;
buffer_param.vPosition.u3.z = 0.0;
rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.u1.x,buffer_param.vPosition.u2.y,buffer_param.vPosition.u3.z,DS3D_IMMEDIATE);
ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
}
rc=IDirectSoundBuffer_Play(dsbo,0,0,DSBPLAY_LOOPING); while (buffer_service(&state)) {
ok(rc==DS_OK,"Play: 0x%lx\n",rc); WaitForSingleObject(GetCurrentProcess(),TIME_SLICE/2);
/* FIXME: move positions here someday */
if (listener&&move_listener) {
listener_param.vPosition.u1.x += 0.5;
rc=IDirectSound3DListener_SetPosition(listener,listener_param.vPosition.u1.x,listener_param.vPosition.u2.y,listener_param.vPosition.u3.z,DS3D_IMMEDIATE);
ok(rc==DS_OK,"IDirectSound3dListener_SetPosition failed 0x%lx\n",rc);
}
if (buffer3d&&move_sound) {
buffer_param.vPosition.u1.x -= 0.5;
rc=IDirectSound3DBuffer_SetPosition(buffer,buffer_param.vPosition.u1.x,buffer_param.vPosition.u2.y,buffer_param.vPosition.u3.z,DS3D_IMMEDIATE);
ok(rc==DS_OK,"IDirectSound3dBuffer_SetPosition failed 0x%lx\n",rc);
}
}
rc=IDirectSoundBuffer_GetStatus(dsbo,&status); if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) {
ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc); rc=IDirectSoundBuffer_SetVolume(dsbo,volume);
ok(status==(DSBSTATUS_PLAYING|DSBSTATUS_LOOPING), ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc);
"GetStatus: bad status: %lx",status); }
while (buffer_service(&state)) { free(state.wave);
WaitForSingleObject(GetCurrentProcess(),TIME_SLICE/2); if (is_primary) {
} /* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%0lx\n",rc);
}
if (buffer3d) {
ref=IDirectSound3DBuffer_Release(buffer);
ok(ref==0,"IDirectSound3DBuffer_Release has %d references, should have 0\n",ref);
}
}
}
if (dsbcaps.dwFlags & DSBCAPS_CTRLVOLUME) { static void test_secondary(LPDIRECTSOUND dso,
rc=IDirectSoundBuffer_SetVolume(dsbo,volume); int play, int has_3dbuffer,
ok(rc==DS_OK,"SetVolume failed: 0x%lx\n",rc); int has_listener, int has_duplicate,
} int move_listener, int move_sound)
{
HRESULT rc;
LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL;
LPDIRECTSOUND3DLISTENER listener=NULL;
DSBUFFERDESC bufdesc;
WAVEFORMATEX wfx;
int f,ref;
free(state.wave); ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
if (rc==DS_OK&&primary!=NULL) {
if (has_listener) {
rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
if(rc==DS_OK&&listener!=NULL) {
DS3DLISTENER listener_param;
ZeroMemory(&listener_param,sizeof(listener_param));
/* DSOUND: Error: Invalid buffer */
rc=IDirectSound3DListener_GetAllParameters(listener,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
/* DSOUND: Error: Invalid buffer */
rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
listener_param.dwSize=sizeof(listener_param);
rc=IDirectSound3DListener_GetAllParameters(listener,&listener_param);
ok(rc==DS_OK,"IDirectSound3dListener_GetAllParameters failed 0x%lx\n",rc);
} else
return;
}
for (f=0;f<NB_FORMATS;f++) {
init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRL3D;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.lpwfxFormat=&wfx;
trace(" Testing a %s%ssecondary buffer %s%s%s%sat %ldx%dx%d\n",
has_3dbuffer?"3D ":"",
has_duplicate?"duplicated ":"",
listener!=NULL||move_sound?"with ":"",
move_listener?"moving ":"",
listener!=NULL?"listener ":"",
listener&&move_sound?"and moving sound ":move_sound?"moving sound ":"",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK&&secondary!=NULL,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc);
if (rc==DS_OK&&secondary!=NULL) {
if (has_duplicate) {
LPDIRECTSOUNDBUFFER duplicated=NULL;
/* DSOUND: Error: Invalid source buffer */
rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
/* DSOUND: Error: Invalid dest buffer */
rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
/* DSOUND: Error: Invalid source buffer */
rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
duplicated=NULL;
rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
ok(rc==DS_OK&&duplicated!=NULL,"IDirectSound_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
if (rc==DS_OK&&duplicated!=NULL) {
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref);
secondary=duplicated;
}
}
if (rc==DS_OK&&secondary!=NULL) {
test_buffer(dso,secondary,0,winetest_interactive,has_3dbuffer,listener,move_listener,move_sound);
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release %s has %d references, should have 0\n",has_duplicate?"duplicated":"secondary",ref);
}
}
}
if (has_listener) {
ref=IDirectSound3DListener_Release(listener);
ok(ref==0,"IDirectSound3dListener_Release listener has %d references, should have 0\n",ref);
} else {
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
}
} }
} }
static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, static BOOL WINAPI dsenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
LPCSTR lpcstrModule, LPVOID lpContext) LPCSTR lpcstrModule, LPVOID lpContext)
{ {
HRESULT rc; HRESULT rc;
LPDIRECTSOUND dso=NULL; LPDIRECTSOUND dso=NULL;
LPDIRECTSOUNDBUFFER dsbo=NULL; LPDIRECTSOUNDBUFFER primary=NULL,secondary=NULL,duplicated=NULL;
DSBUFFERDESC bufdesc; DSBUFFERDESC bufdesc;
WAVEFORMATEX wfx; WAVEFORMATEX wfx;
DSCAPS dscaps; DSCAPS dscaps;
int f,ref; int f,ref;
trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule); trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule);
/* DSOUND: Error: Invalid interface buffer */
rc=DirectSoundCreate(lpGuid,0,NULL);
ok(rc==DSERR_INVALIDPARAM,"DirectSoundCreate should have failed: 0x%lx\n",rc);
rc=DirectSoundCreate(lpGuid,&dso,NULL); rc=DirectSoundCreate(lpGuid,&dso,NULL);
ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc); ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
goto EXIT; goto EXIT;
dscaps.dwSize=0; /* DSOUND: Error: Invalid caps buffer */
rc=IDirectSound_GetCaps(dso,0);
ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
ZeroMemory(&dscaps, sizeof(dscaps));
/* DSOUND: Error: Invalid caps buffer */
rc=IDirectSound_GetCaps(dso,&dscaps); rc=IDirectSound_GetCaps(dso,&dscaps);
ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc); ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc);
dscaps.dwSize=sizeof(dscaps); dscaps.dwSize=sizeof(dscaps);
/* DSOUND: Running on a certified driver */
rc=IDirectSound_GetCaps(dso,&dscaps); rc=IDirectSound_GetCaps(dso,&dscaps);
ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
trace(" DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n", trace(" DirectSound Caps: flags=0x%08lx secondary min=%ld max=%ld\n",
dscaps.dwFlags,dscaps.dwMinSecondarySampleRate, dscaps.dwFlags,dscaps.dwMinSecondarySampleRate,
dscaps.dwMaxSecondarySampleRate); dscaps.dwMaxSecondarySampleRate);
} }
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound_CreateSoundBuffer(dso,0,0,NULL);
ok(rc==DSERR_INVALIDPARAM,"CreateSoundBuffer should have failed: 0x%lx\n",rc);
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound_CreateSoundBuffer(dso,0,&primary,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
/* DSOUND: Error: Invalid buffer description pointer */
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,0,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,dsbo=0x%lx\n",rc,(DWORD)primary);
ZeroMemory(&bufdesc, sizeof(bufdesc));
/* DSOUND: Error: Invalid size */
/* DSOUND: Error: Invalid buffer description */
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DSERR_INVALIDPARAM && primary==0,"CreateSoundBuffer should have failed: rc=0x%lx,primary=0x%lx\n",rc,(DWORD)primary);
/* We must call SetCooperativeLevel before calling CreateSoundBuffer */ /* We must call SetCooperativeLevel before calling CreateSoundBuffer */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_PRIORITY */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY);
ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc); ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
goto EXIT; goto EXIT;
/* Testing the primary buffer */ /* Testing the primary buffer */
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
bufdesc.dwBufferBytes=0;
bufdesc.dwReserved=0;
bufdesc.lpwfxFormat=NULL;
trace(" Testing the primary buffer\n"); trace(" Testing the primary buffer\n");
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&dsbo,NULL); rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK,"CreateSoundBuffer failed to create a primary buffer 0x%lx\n",rc); ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a primary buffer: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK&&primary!=NULL) {
test_buffer(dso,dsbo,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER)); test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
ref=IDirectSoundBuffer_Release(dsbo); ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release has %d references\n",ref); ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
} }
/* Testing 3D primary buffer */ /* Testing 3D primary buffer */
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D; bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
bufdesc.dwBufferBytes=0;
bufdesc.dwReserved=0;
bufdesc.lpwfxFormat=NULL;
trace(" Testing 3D primary buffer\n"); trace(" Testing 3D primary buffer\n");
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&dsbo,NULL); rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc); ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK&&primary!=NULL) {
test_buffer(dso,dsbo,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER)); ref=IDirectSoundBuffer_Release(primary);
ref=IDirectSoundBuffer_Release(dsbo); ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
ok(ref==0,"IDirectSoundBuffer_Release has %d references\n",ref); primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
if (rc==DS_OK&&primary!=NULL) {
test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,0,0,0);
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
}
} }
/* Testing the primary buffer with listener */
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER;
trace(" Testing 3D primary buffer\n");
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
if (rc==DS_OK&&primary!=NULL) {
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer: 0x%lx\n",rc);
if (rc==DS_OK&&primary!=NULL) {
LPDIRECTSOUND3DLISTENER listener=NULL;
rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
if (rc==DS_OK&&listener) {
test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0);
ref=IDirectSound3DListener_Release(listener);
ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
}
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
}
}
/* Testing 3D primary buffer with listener */
primary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D;
trace(" Testing 3D primary buffer with listener\n");
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&primary,NULL);
ok(rc==DS_OK&&primary!=NULL,"CreateSoundBuffer failed to create a 3D primary buffer 0x%lx\n",rc);
if (rc==DS_OK&&primary!=NULL) {
LPDIRECTSOUND3DLISTENER listener=NULL;
rc=IDirectSoundBuffer_QueryInterface(primary,&IID_IDirectSound3DListener,(void **)&listener);
ok(rc==DS_OK&&listener!=NULL,"IDirectSoundBuffer_QueryInterface failed to get a 3D listener 0x%lx\n",rc);
if (rc==DS_OK&&listener!=NULL) {
LPDIRECTSOUNDBUFFER temp_buffer=NULL;
/* Checking the COM interface */
rc=IDirectSoundBuffer_QueryInterface(primary, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
if(rc==DS_OK&&temp_buffer!=NULL) {
ref=IDirectSoundBuffer_Release(temp_buffer);
ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
temp_buffer=NULL;
rc=IDirectSound3DListener_QueryInterface(listener, &IID_IDirectSoundBuffer,(LPVOID *)&temp_buffer);
ok(rc==DS_OK&&temp_buffer!=NULL,"IDirectSoundBuffer_QueryInterface failed: 0x%lx\n",rc);
ok(temp_buffer==primary,"COM interface broken: 0x%08lx != 0x%08lx\n",(DWORD)temp_buffer,(DWORD)primary);
ref=IDirectSoundBuffer_Release(temp_buffer);
ok(ref==1,"IDirectSoundBuffer_Release has %d references, should have 1\n",ref);
/* Testing the buffer */
test_buffer(dso,primary,1,winetest_interactive && !(dscaps.dwFlags & DSCAPS_EMULDRIVER),0,listener,0,0);
}
/* Testing the reference counting */
ref=IDirectSound3DListener_Release(listener);
ok(ref==0,"IDirectSound3DListener_Release listener has %d references, should have 0\n",ref);
}
/* Testing the reference counting */
ref=IDirectSoundBuffer_Release(primary);
ok(ref==0,"IDirectSoundBuffer_Release primary has %d references, should have 0\n",ref);
}
/* Set the CooperativeLevel back to normal */ /* Set the CooperativeLevel back to normal */
/* DSOUND: Setting DirectSound cooperative level to DSSCL_NORMAL */
rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL);
ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc); ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
goto EXIT; goto EXIT;
/* Testing secondary buffers */ /* Testing secondary buffers */
for (f=0;f<NB_FORMATS;f++) { for (f=0;f<NB_FORMATS;f++) {
init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]); init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2; bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.dwReserved=0;
bufdesc.lpwfxFormat=&wfx; bufdesc.lpwfxFormat=&wfx;
trace(" Testing a secondary buffer at %ldx%dx%d\n", trace(" Testing a secondary buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&dsbo,NULL); rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n",rc); ok(rc==DS_OK&&secondary!=NULL,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK&&secondary!=NULL) {
test_buffer(dso,dsbo,0,winetest_interactive); test_buffer(dso,secondary,0,winetest_interactive,0,0,0,0);
ref=IDirectSoundBuffer_Release(dsbo); ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release has %d references\n",ref); ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref);
} }
} }
/* Testing 3D secondary buffers */ /* Testing duplicated secondary buffers */
for (f=0;f<NB_FORMATS;f++) { for (f=0;f<NB_FORMATS;f++) {
init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]); init_format(&wfx,formats[f][0],formats[f][1],formats[f][2]);
secondary=NULL;
ZeroMemory(&bufdesc, sizeof(bufdesc));
bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwSize=sizeof(bufdesc);
bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2|DSBCAPS_CTRL3D; bufdesc.dwFlags=DSBCAPS_CTRLDEFAULT|DSBCAPS_GETCURRENTPOSITION2;
bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000; bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec*BUFFER_LEN/1000;
bufdesc.dwReserved=0;
bufdesc.lpwfxFormat=&wfx; bufdesc.lpwfxFormat=&wfx;
trace(" Testing a 3D secondary buffer at %ldx%dx%d\n", trace(" Testing a duplicated secondary buffer at %ldx%dx%d\n",
wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels);
rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&dsbo,NULL); rc=IDirectSound_CreateSoundBuffer(dso,&bufdesc,&secondary,NULL);
ok(rc==DS_OK,"CreateSoundBuffer failed to create a 3D secondary buffer 0x%lx\n",rc); ok(rc==DS_OK&&secondary!=NULL,"CreateSoundBuffer failed to create a secondary buffer 0x%lx\n",rc);
if (rc==DS_OK) { if(rc==DS_OK&&secondary!=NULL) {
test_buffer(dso,dsbo,0,winetest_interactive); /* DSOUND: Error: Invalid source buffer */
ref=IDirectSoundBuffer_Release(dsbo); rc=IDirectSound_DuplicateSoundBuffer(dso,0,0);
ok(ref==0,"IDirectSoundBuffer_Release has %d references\n",ref); ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
/* DSOUND: Error: Invalid dest buffer */
rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,0);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
/* DSOUND: Error: Invalid source buffer */
rc=IDirectSound_DuplicateSoundBuffer(dso,0,&duplicated);
ok(rc==DSERR_INVALIDPARAM,"IDirectSound_DuplicateSoundBuffer should have failed 0x%lx\n",rc);
duplicated=NULL;
rc=IDirectSound_DuplicateSoundBuffer(dso,secondary,&duplicated);
ok(rc==DS_OK&&duplicated!=NULL,"IDirectSound_DuplicateSoundBuffer failed to duplicate a secondary buffer 0x%lx\n",rc);
ref=IDirectSoundBuffer_Release(secondary);
ok(ref==0,"IDirectSoundBuffer_Release secondary has %d references, should have 0\n",ref);
if (rc==DS_OK&&duplicated!=NULL) {
test_buffer(dso,duplicated,0,winetest_interactive,0,0,0,0);
ref=IDirectSoundBuffer_Release(duplicated);
ok(ref==0,"IDirectSoundBuffer_Release duplicated has %d references, should have 0\n",ref);
}
} }
} }
/* Testing 3D secondary buffers */
test_secondary(dso,winetest_interactive,0,0,0,0,0);
test_secondary(dso,winetest_interactive,1,0,0,0,0);
test_secondary(dso,winetest_interactive,1,0,1,0,0);
test_secondary(dso,winetest_interactive,0,1,0,0,0);
test_secondary(dso,winetest_interactive,0,1,1,0,0);
test_secondary(dso,winetest_interactive,1,1,0,0,0);
test_secondary(dso,winetest_interactive,1,1,1,0,0);
test_secondary(dso,winetest_interactive,1,1,0,1,0);
test_secondary(dso,winetest_interactive,1,1,0,0,1);
test_secondary(dso,winetest_interactive,1,1,0,1,1);
EXIT: EXIT:
if (dso!=NULL) { if (dso!=NULL) {
ref=IDirectSound_Release(dso); ref=IDirectSound_Release(dso);
ok(ref==0,"IDirectSound_Release has %d references\n",ref); ok(ref==0,"IDirectSound_Release has %d references, should have 0\n",ref);
} }
return 1; return 1;
} }
...@@ -520,24 +914,25 @@ static int capture_buffer_service(capture_state_t* state) ...@@ -520,24 +914,25 @@ static int capture_buffer_service(capture_state_t* state)
rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos); rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos);
ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return 0; return 0;
rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,&ptr1,&len1,&ptr2,&len2,0); rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,state->size,&ptr1,&len1,&ptr2,&len2,0);
ok(rc==DS_OK,"Lock failed: 0x%lx\n",rc); ok(rc==DS_OK,"Lock failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return 0; return 0;
rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2); rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2);
ok(rc==DS_OK,"Unlock failed: 0x%lx\n",rc); ok(rc==DS_OK,"Unlock failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return 0; return 0;
state->offset = (state->offset + state->size) % state->buffer_size; state->offset = (state->offset + state->size) % state->buffer_size;
return 1; return 1;
} }
static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREBUFFER dscbo) static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco,
LPDIRECTSOUNDCAPTUREBUFFER dscbo, int record)
{ {
HRESULT rc; HRESULT rc;
DSCBCAPS dscbcaps; DSCBCAPS dscbcaps;
...@@ -559,8 +954,8 @@ static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREB ...@@ -559,8 +954,8 @@ static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREB
rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps); rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps);
ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\n", trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\n",
dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes); dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes);
} }
/* Query the format size. Note that it may not match sizeof(wfx) */ /* Query the format size. Note that it may not match sizeof(wfx) */
...@@ -578,9 +973,9 @@ static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREB ...@@ -578,9 +973,9 @@ static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREB
rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL); rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL);
ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n", trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n",
wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample, wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample,
wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign); wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign);
} }
/* Private dsound.dll: Error: Invalid status pointer */ /* Private dsound.dll: Error: Invalid status pointer */
...@@ -590,7 +985,7 @@ static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREB ...@@ -590,7 +985,7 @@ static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREB
rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status); rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
trace(" status=0x%04lx\n",status); trace(" status=0x%04lx\n",status);
} }
ZeroMemory(&state, sizeof(state)); ZeroMemory(&state, sizeof(state));
...@@ -603,53 +998,55 @@ static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREB ...@@ -603,53 +998,55 @@ static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREB
rc=IDirectSoundCapture_QueryInterface(dscbo,&IID_IDirectSoundNotify,(void **)&(state.notify)); rc=IDirectSoundCapture_QueryInterface(dscbo,&IID_IDirectSoundNotify,(void **)&(state.notify));
ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc); ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return; return;
for (i = 0; i < NOTIFICATIONS; i++) { for (i = 0; i < NOTIFICATIONS; i++) {
state.posnotify[i].dwOffset = (i * state.size) + state.size - 1; state.posnotify[i].dwOffset = (i * state.size) + state.size - 1;
state.posnotify[i].hEventNotify = state.event; state.posnotify[i].hEventNotify = state.event;
} }
rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify); rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify);
ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx\n",rc); ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
return; return;
rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING); if (record) {
ok(rc==DS_OK,"Start: 0x%lx\n",rc); rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING);
if (rc!=DS_OK) ok(rc==DS_OK,"Start: 0x%lx\n",rc);
return; if (rc!=DS_OK)
return;
rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc); rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status);
ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING), ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc);
"GetStatus: bad status: %lx",status); ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING),
if (rc!=DS_OK) "GetStatus: bad status: %lx",status);
return; if (rc!=DS_OK)
return;
/* wait for the notifications */
for (i = 0; i < (NOTIFICATIONS * 2); i++) {
rc=MsgWaitForMultipleObjects( 1, &(state.event), FALSE, 3000, QS_ALLEVENTS );
ok(rc==WAIT_OBJECT_0,"MsgWaitForMultipleObjects failed: 0x%lx\n",rc);
if (rc!=WAIT_OBJECT_0)
break;
if (!capture_buffer_service(&state))
break;
}
/* wait for the notifications */ rc=IDirectSoundCaptureBuffer_Stop(dscbo);
for (i = 0; i < (NOTIFICATIONS * 2); i++) { ok(rc==DS_OK,"Stop: 0x%lx\n",rc);
rc=MsgWaitForMultipleObjects( 1, &(state.event), FALSE, 3000, QS_ALLEVENTS ); if (rc!=DS_OK)
ok(rc==WAIT_OBJECT_0,"MsgWaitForMultipleObjects failed: 0x%lx\n",rc); return;
if (rc!=WAIT_OBJECT_0)
break;
if (!capture_buffer_service(&state))
break;
} }
rc=IDirectSoundCaptureBuffer_Stop(dscbo);
ok(rc==DS_OK,"Stop: 0x%lx\n",rc);
if (rc!=DS_OK)
return;
rc=IDirectSoundNotify_Release(state.notify); rc=IDirectSoundNotify_Release(state.notify);
ok(rc==0,"Release: 0x%lx\n",rc); ok(rc==0,"Release: 0x%lx\n",rc);
if (rc!=0) if (rc!=0)
return; return;
} }
static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
LPCSTR lpcstrModule, LPVOID lpContext) LPCSTR lpcstrModule, LPVOID lpContext)
{ {
HRESULT rc; HRESULT rc;
LPDIRECTSOUNDCAPTURE dsco=NULL; LPDIRECTSOUNDCAPTURE dsco=NULL;
...@@ -665,13 +1062,13 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, ...@@ -665,13 +1062,13 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx\n",rc); ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
ref=IDirectSoundCapture_Release(dsco); ref=IDirectSoundCapture_Release(dsco);
ok(ref==0,"IDirectSoundCapture_Release has %d references\n",ref); ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
} }
rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL); rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL);
ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate failed: 0x%lx\n",rc); ok((rc==DS_OK)||(rc==DSERR_NODRIVER),"DirectSoundCaptureCreate failed: 0x%lx\n",rc);
if (rc!=DS_OK) if (rc!=DS_OK)
goto EXIT; goto EXIT;
/* Private dsound.dll: Error: Invalid caps buffer */ /* Private dsound.dll: Error: Invalid caps buffer */
rc=IDirectSoundCapture_GetCaps(dsco,NULL); rc=IDirectSoundCapture_GetCaps(dsco,NULL);
...@@ -686,8 +1083,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, ...@@ -686,8 +1083,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps); rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps);
ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc); ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
trace(" DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n", trace(" DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%05lx channels=%ld\n",
dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels); dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels);
} }
/* Private dsound.dll: Error: Invalid size */ /* Private dsound.dll: Error: Invalid size */
...@@ -701,8 +1098,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, ...@@ -701,8 +1098,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc); ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
ref=IDirectSoundCaptureBuffer_Release(dscbo); ref=IDirectSoundCaptureBuffer_Release(dscbo);
ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references\n",ref); ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
} }
/* Private dsound.dll: Error: Invalid buffer size */ /* Private dsound.dll: Error: Invalid buffer size */
...@@ -716,8 +1113,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, ...@@ -716,8 +1113,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc); ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
ref=IDirectSoundCaptureBuffer_Release(dscbo); ref=IDirectSoundCaptureBuffer_Release(dscbo);
ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references\n",ref); ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
} }
/* Private dsound.dll: Error: Invalid buffer size */ /* Private dsound.dll: Error: Invalid buffer size */
...@@ -732,8 +1129,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, ...@@ -732,8 +1129,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc); ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
ref=IDirectSoundCaptureBuffer_Release(dscbo); ref=IDirectSoundCaptureBuffer_Release(dscbo);
ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references\n",ref); ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
} }
/* Private dsound.dll: Error: Invalid buffer size */ /* Private dsound.dll: Error: Invalid buffer size */
...@@ -748,8 +1145,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, ...@@ -748,8 +1145,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc); ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
ref=IDirectSoundCaptureBuffer_Release(dscbo); ref=IDirectSoundCaptureBuffer_Release(dscbo);
ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references\n",ref); ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
} }
for (f=0;f<NB_FORMATS;f++) { for (f=0;f<NB_FORMATS;f++) {
...@@ -765,9 +1162,9 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, ...@@ -765,9 +1162,9 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL);
ok(rc==DS_OK,"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc); ok(rc==DS_OK,"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc);
if (rc==DS_OK) { if (rc==DS_OK) {
test_capture_buffer(dsco, dscbo); test_capture_buffer(dsco, dscbo, winetest_interactive);
ref=IDirectSoundCaptureBuffer_Release(dscbo); ref=IDirectSoundCaptureBuffer_Release(dscbo);
ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references\n",ref); ok(ref==0,"IDirectSoundCaptureBuffer_Release has %d references, should have 0\n",ref);
} }
} }
...@@ -788,8 +1185,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, ...@@ -788,8 +1185,8 @@ static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription,
EXIT: EXIT:
if (dsco!=NULL) { if (dsco!=NULL) {
ref=IDirectSoundCapture_Release(dsco); ref=IDirectSoundCapture_Release(dsco);
ok(ref==0,"IDirectSoundCapture_Release has %d references\n",ref); ok(ref==0,"IDirectSoundCapture_Release has %d references, should have 0\n",ref);
} }
return TRUE; return TRUE;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment