From 3ec78e9525c945edd83d323cf9814a00f4b073be Mon Sep 17 00:00:00 2001 From: Kamil Hornicek Date: Mon, 9 Mar 2009 19:46:37 +0000 Subject: [PATCH 1/1] - fix some prototypes, remove dxroslayer from dsound - sync dsound with wine head, it now works again (tested on win xp and reactos) svn path=/trunk/; revision=39921 --- reactos/dll/directx/dsound/buffer.c | 625 ++-- reactos/dll/directx/dsound/capture.c | 1379 ++++----- reactos/dll/directx/dsound/dsound.c | 2660 ++++++++--------- reactos/dll/directx/dsound/dsound.rbuild | 7 +- reactos/dll/directx/dsound/dsound_convert.c | 435 +++ reactos/dll/directx/dsound/dsound_main.c | 375 +-- reactos/dll/directx/dsound/dsound_private.h | 377 ++- reactos/dll/directx/dsound/duplex.c | 935 +++++- .../directx/dsound/dxroslayer/dxros_layer.h | 62 - .../dxroslayer/dxrosdrv_querydsounddesc.c | 163 - .../dxroslayer/dxrosdrv_querydsoundiface.c | 72 - .../directx/dsound/dxroslayer/dxroslayer.c | 115 - .../dsound/dxroslayer/getguidfromstring.c | 176 -- reactos/dll/directx/dsound/mixer.c | 1634 +++++----- reactos/dll/directx/dsound/primary.c | 884 +++--- reactos/dll/directx/dsound/propset.c | 801 +++-- reactos/dll/directx/dsound/regsvr.c | 104 +- reactos/dll/directx/dsound/sound3d.c | 372 ++- reactos/dll/directx/dsound/version.rc | 10 +- reactos/include/psdk/dsdriver.h | 1 + reactos/include/psdk/dsound.h | 4 +- reactos/include/reactos/wine/mmsystem.h | 6 + reactos/lib/sdk/dxguid/dxguid-mingw.c | 14 +- 23 files changed, 5670 insertions(+), 5541 deletions(-) create mode 100644 reactos/dll/directx/dsound/dsound_convert.c delete mode 100644 reactos/dll/directx/dsound/dxroslayer/dxros_layer.h delete mode 100644 reactos/dll/directx/dsound/dxroslayer/dxrosdrv_querydsounddesc.c delete mode 100644 reactos/dll/directx/dsound/dxroslayer/dxrosdrv_querydsoundiface.c delete mode 100644 reactos/dll/directx/dsound/dxroslayer/dxroslayer.c delete mode 100644 reactos/dll/directx/dsound/dxroslayer/getguidfromstring.c diff --git a/reactos/dll/directx/dsound/buffer.c b/reactos/dll/directx/dsound/buffer.c index 2541b9938df..251c436d14a 100644 --- a/reactos/dll/directx/dsound/buffer.c +++ b/reactos/dll/directx/dsound/buffer.c @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -25,8 +25,8 @@ #define NONAMELESSUNION #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "mmsystem.h" -#include "winreg.h" #include "winternl.h" #include "wine/debug.h" #include "dsound.h" @@ -35,9 +35,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); +static HRESULT SecondaryBufferImpl_Destroy(SecondaryBufferImpl *pdsb); + /******************************************************************************* * IDirectSoundNotify */ + +struct IDirectSoundNotifyImpl +{ + /* IUnknown fields */ + const IDirectSoundNotifyVtbl *lpVtbl; + LONG ref; + IDirectSoundBufferImpl* dsb; +}; + +static HRESULT IDirectSoundNotifyImpl_Create(IDirectSoundBufferImpl *dsb, + IDirectSoundNotifyImpl **pdsn); +static HRESULT IDirectSoundNotifyImpl_Destroy(IDirectSoundNotifyImpl *pdsn); + static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface( LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj ) { @@ -56,7 +71,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) { IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -64,7 +79,7 @@ static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) { IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER)This->dsb); @@ -79,7 +94,7 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions( LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify ) { IDirectSoundNotifyImpl *This = (IDirectSoundNotifyImpl *)iface; - TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify); + TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify); if (howmuch > 0 && notify == NULL) { WARN("invalid parameter: notify == NULL\n"); @@ -89,7 +104,7 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions( if (TRACE_ON(dsound)) { unsigned int i; for (i=0;i 0) { /* Make an internal copy of the caller-supplied array. * Replace the existing copy if one is already present. */ - if (This->dsb->notifies) - This->dsb->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, - This->dsb->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY)); - else - This->dsb->notifies = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + HeapFree(GetProcessHeap(), 0, This->dsb->notifies); + This->dsb->notifies = HeapAlloc(GetProcessHeap(), 0, howmuch * sizeof(DSBPOSITIONNOTIFY)); if (This->dsb->notifies == NULL) { @@ -132,14 +144,14 @@ static const IDirectSoundNotifyVtbl dsnvt = IDirectSoundNotifyImpl_SetNotificationPositions, }; -HRESULT WINAPI IDirectSoundNotifyImpl_Create( +static HRESULT IDirectSoundNotifyImpl_Create( IDirectSoundBufferImpl * dsb, IDirectSoundNotifyImpl **pdsn) { IDirectSoundNotifyImpl * dsn; TRACE("(%p,%p)\n",dsb,pdsn); - dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(dsn)); + dsn = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*dsn)); if (dsn == NULL) { WARN("out of memory\n"); @@ -156,7 +168,7 @@ HRESULT WINAPI IDirectSoundNotifyImpl_Create( return DS_OK; } -HRESULT WINAPI IDirectSoundNotifyImpl_Destroy( +static HRESULT IDirectSoundNotifyImpl_Destroy( IDirectSoundNotifyImpl *pdsn) { TRACE("(%p)\n",pdsn); @@ -188,24 +200,27 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume( LONG oldVol; HRESULT hres = DS_OK; - TRACE("(%p,%ld)\n",This,vol); + TRACE("(%p,%d)\n",This,vol); if (!(This->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { - WARN("control unavailable: This->dsbd.dwFlags = 0x%08lx\n", This->dsbd.dwFlags); + WARN("control unavailable: This->dsbd.dwFlags = 0x%08x\n", This->dsbd.dwFlags); return DSERR_CONTROLUNAVAIL; } if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) { - WARN("invalid parameter: vol = %ld\n", vol); + WARN("invalid parameter: vol = %d\n", vol); return DSERR_INVALIDPARAM; } /* **** */ - EnterCriticalSection(&(This->lock)); + RtlAcquireResourceExclusive(&This->lock, TRUE); if (This->dsbd.dwFlags & DSBCAPS_CTRL3D) { oldVol = This->ds3db_lVolume; This->ds3db_lVolume = vol; + if (vol != oldVol) + /* recalc 3d volume, which in turn recalcs the pans */ + DSOUND_Calc3DBuffer(This); } else { oldVol = This->volpan.lVolume; This->volpan.lVolume = vol; @@ -218,11 +233,10 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetVolume( hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan)); if (hres != DS_OK) WARN("IDsDriverBuffer_SetVolumePan failed\n"); - } else - DSOUND_ForceRemix(This); + } } - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); /* **** */ return hres; @@ -255,7 +269,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency( IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; DWORD oldFreq; - TRACE("(%p,%ld)\n",This,freq); + TRACE("(%p,%d)\n",This,freq); if (!(This->dsbd.dwFlags & DSBCAPS_CTRLFREQUENCY)) { WARN("control unavailable\n"); @@ -266,24 +280,23 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFrequency( freq = This->pwfx->nSamplesPerSec; if ((freq < DSBFREQUENCY_MIN) || (freq > DSBFREQUENCY_MAX)) { - WARN("invalid parameter: freq = %ld\n", freq); + WARN("invalid parameter: freq = %d\n", freq); return DSERR_INVALIDPARAM; } /* **** */ - EnterCriticalSection(&(This->lock)); + RtlAcquireResourceExclusive(&This->lock, TRUE); oldFreq = This->freq; This->freq = freq; if (freq != oldFreq) { - This->freqAdjust = (freq << DSOUND_FREQSHIFT) / This->dsound->device->pwfx->nSamplesPerSec; + This->freqAdjust = ((DWORD64)This->freq << DSOUND_FREQSHIFT) / This->device->pwfx->nSamplesPerSec; This->nAvgBytesPerSec = freq * This->pwfx->nBlockAlign; DSOUND_RecalcFormat(This); - if (!This->hwbuf) - DSOUND_ForceRemix(This); + DSOUND_MixToTemporary(This, 0, This->buflen, FALSE); } - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); /* **** */ return DS_OK; @@ -294,15 +307,14 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Play( ) { HRESULT hres = DS_OK; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - TRACE("(%p,%08lx,%08lx,%08lx)\n",This,reserved1,reserved2,flags); + TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags); /* **** */ - EnterCriticalSection(&(This->lock)); + RtlAcquireResourceExclusive(&This->lock, TRUE); This->playflags = flags; - if (This->state == STATE_STOPPED) { + if (This->state == STATE_STOPPED && !This->hwbuf) { This->leadin = TRUE; - This->startpos = This->buf_mixpos; This->state = STATE_STARTING; } else if (This->state == STATE_STOPPING) This->state = STATE_PLAYING; @@ -314,7 +326,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Play( This->state = STATE_PLAYING; } - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); /* **** */ return hres; @@ -327,12 +339,15 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface) TRACE("(%p)\n",This); /* **** */ - EnterCriticalSection(&(This->lock)); + RtlAcquireResourceExclusive(&This->lock, TRUE); if (This->state == STATE_PLAYING) This->state = STATE_STOPPING; else if (This->state == STATE_STARTING) + { This->state = STATE_STOPPED; + DSOUND_CheckEvent(This, 0, 0); + } if (This->hwbuf) { hres = IDsDriverBuffer_Stop(This->hwbuf); if (hres != DS_OK) @@ -340,9 +355,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface) else This->state = STATE_STOPPED; } - DSOUND_CheckEvent(This, 0); - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); /* **** */ return hres; @@ -352,7 +366,7 @@ static ULONG WINAPI IDirectSoundBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -360,31 +374,24 @@ static ULONG WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { - DSOUND_RemoveBuffer(This->dsound, This); + DirectSoundDevice_RemoveBuffer(This->device, This); + RtlDeleteResource(&This->lock); - This->lock.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&(This->lock)); - - if (This->hwbuf) { + if (This->hwbuf) IDsDriverBuffer_Release(This->hwbuf); - if (This->dsound->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { - This->buffer->ref--; - if (This->buffer->ref==0) { - HeapFree(GetProcessHeap(),0,This->buffer->memory); - HeapFree(GetProcessHeap(),0,This->buffer); - } - } - } else { + if (!This->hwbuf || (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)) { This->buffer->ref--; + list_remove(&This->entry); if (This->buffer->ref==0) { HeapFree(GetProcessHeap(),0,This->buffer->memory); HeapFree(GetProcessHeap(),0,This->buffer); } } + HeapFree(GetProcessHeap(), 0, This->tmp_buffer); HeapFree(GetProcessHeap(), 0, This->notifies); HeapFree(GetProcessHeap(), 0, This->pwfx); HeapFree(GetProcessHeap(), 0, This); @@ -394,50 +401,14 @@ static ULONG WINAPI IDirectSoundBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) return ref; } -DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This, DWORD pplay, DWORD pwrite) -{ - DWORD bplay = This->buf_mixpos; - DWORD pmix = This->primary_mixpos; - TRACE("(%p, pplay=%lu, pwrite=%lu)\n", This, pplay, pwrite); - - /* the actual primary play position (pplay) is always behind last mixed (pmix), - * unless the computer is too slow or something */ - /* we need to know how far away we are from there */ - if (pmix < pplay) pmix += This->dsound->device->buflen; /* wraparound */ - pmix -= pplay; - /* detect buffer underrun */ - if (pwrite < pplay) pwrite += This->dsound->device->buflen; /* wraparound */ - pwrite -= pplay; - if (pmix > (ds_snd_queue_max * This->dsound->device->fraglen + pwrite + This->dsound->device->writelead)) { - WARN("detected an underrun: primary queue was %ld\n",pmix); - pmix = 0; - } - /* divide the offset by its sample size */ - pmix /= This->dsound->device->pwfx->nBlockAlign; - TRACE("primary back-samples=%ld\n",pmix); - /* adjust for our frequency */ - pmix = (pmix * This->freqAdjust) >> DSOUND_FREQSHIFT; - /* multiply by our own sample size */ - pmix *= This->pwfx->nBlockAlign; - TRACE("this back-offset=%ld\n", pmix); - /* subtract from our last mixed position */ - while (bplay < pmix) bplay += This->buflen; /* wraparound */ - bplay -= pmix; - if (This->leadin && ((bplay < This->startpos) || (bplay > This->buf_mixpos))) { - /* seems we haven't started playing yet */ - TRACE("this still in lead-in phase\n"); - bplay = This->startpos; - } - /* return the result */ - return bplay; -} - static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition( LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos ) { HRESULT hres; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; TRACE("(%p,%p,%p)\n",This,playpos,writepos); + + RtlAcquireResourceShared(&This->lock, TRUE); if (This->hwbuf) { hres=IDsDriverBuffer_GetPosition(This->hwbuf,playpos,writepos); if (hres != DS_OK) { @@ -445,47 +416,29 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCurrentPosition( return hres; } } else { - if (playpos && (This->state != STATE_PLAYING)) { - /* we haven't been merged into the primary buffer (yet) */ - *playpos = This->buf_mixpos; - } else if (playpos) { - DWORD pplay, pwrite; - /* let's get this exact; first, recursively call GetPosition on the primary */ - EnterCriticalSection(&(This->dsound->device->mixlock)); - if (DSOUND_PrimaryGetPosition(This->dsound->device, &pplay, &pwrite) != DS_OK) - WARN("DSOUND_PrimaryGetPosition failed\n"); - /* detect HEL mode underrun */ - if (!(This->dsound->device->hwbuf || This->dsound->device->pwqueue)) - TRACE("detected an underrun\n"); - if ((This->dsbd.dwFlags & DSBCAPS_GETCURRENTPOSITION2) || This->dsound->device->hwbuf) { - /* calculate play position using this */ - *playpos = DSOUND_CalcPlayPosition(This, pplay, pwrite); - } else { - /* (unless the app isn't using GETCURRENTPOSITION2) */ - /* don't know exactly how this should be handled... - * the docs says that play cursor is reported as directly - * behind write cursor, hmm... */ - /* let's just do what might work for Half-Life */ - DWORD wp; - wp = (This->dsound->device->pwplay + ds_hel_margin) * This->dsound->device->fraglen; - wp %= This->dsound->device->buflen; - *playpos = DSOUND_CalcPlayPosition(This, wp, pwrite); - } - LeaveCriticalSection(&(This->dsound->device->mixlock)); + DWORD pos = This->sec_mixpos; + + /* sanity */ + if (pos >= This->buflen){ + FIXME("Bad play position. playpos: %d, buflen: %d\n", pos, This->buflen); + pos %= This->buflen; } + + if (playpos) + *playpos = pos; if (writepos) - *writepos = This->buf_mixpos; + *writepos = pos; } - if (writepos) { - if (This->state != STATE_STOPPED) { - /* apply the documented 10ms lead to writepos */ - *writepos += This->writelead; - } + if (writepos && This->state != STATE_STOPPED && (!This->hwbuf || !(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD))) { + /* apply the documented 10ms lead to writepos */ + *writepos += This->writelead; *writepos %= This->buflen; } - if (playpos) - This->last_playpos = *playpos; - TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, This, GetTickCount()); + RtlReleaseResource(&This->lock); + + TRACE("playpos = %d, writepos = %d, buflen=%d (%p, time=%d)\n", + playpos?*playpos:-1, writepos?*writepos:-1, This->buflen, This, GetTickCount()); + return DS_OK; } @@ -493,7 +446,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus( LPDIRECTSOUNDBUFFER8 iface,LPDWORD status ) { IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - TRACE("(%p,%p), thread is %04lx\n",This,status,GetCurrentThreadId()); + TRACE("(%p,%p), thread is %04x\n",This,status,GetCurrentThreadId()); if (status == NULL) { WARN("invalid parameter: status = NULL\n"); @@ -501,13 +454,15 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetStatus( } *status = 0; + RtlAcquireResourceShared(&This->lock, TRUE); if ((This->state == STATE_STARTING) || (This->state == STATE_PLAYING)) { *status |= DSBSTATUS_PLAYING; if (This->playflags & DSBPLAY_LOOPING) *status |= DSBSTATUS_LOOPING; } + RtlReleaseResource(&This->lock); - TRACE("status=%lx\n", *status); + TRACE("status=%x\n", *status); return DS_OK; } @@ -520,7 +475,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat( { DWORD size; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten); + TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten); size = sizeof(WAVEFORMATEX) + This->pwfx->cbSize; @@ -531,8 +486,9 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat( *wfwritten = size; } else { WARN("invalid parameter: wfsize too small\n"); + CopyMemory(lpwf,This->pwfx,wfsize); if (wfwritten) - *wfwritten = 0; + *wfwritten = wfsize; return DSERR_INVALIDPARAM; } } else { @@ -548,12 +504,12 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetFormat( } static HRESULT WINAPI IDirectSoundBufferImpl_Lock( - LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags + LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID *lplpaudioptr1,LPDWORD audiobytes1,LPVOID *lplpaudioptr2,LPDWORD audiobytes2,DWORD flags ) { HRESULT hres = DS_OK; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n", + TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n", This, writecursor, writebytes, @@ -565,36 +521,39 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock( GetTickCount() ); + if (!audiobytes1) + return DSERR_INVALIDPARAM; + + /* when this flag is set, writecursor is meaningless and must be calculated */ if (flags & DSBLOCK_FROMWRITECURSOR) { - DWORD writepos; /* GetCurrentPosition does too much magic to duplicate here */ - hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writepos); + hres = IDirectSoundBufferImpl_GetCurrentPosition(iface, NULL, &writecursor); if (hres != DS_OK) { WARN("IDirectSoundBufferImpl_GetCurrentPosition failed\n"); return hres; } - writecursor += writepos; } - writecursor %= This->buflen; + + /* when this flag is set, writebytes is meaningless and must be set */ if (flags & DSBLOCK_ENTIREBUFFER) writebytes = This->buflen; - if (writebytes > This->buflen) - writebytes = This->buflen; - EnterCriticalSection(&(This->lock)); + if (writecursor >= This->buflen) { + WARN("Invalid parameter, writecursor: %u >= buflen: %u\n", + writecursor, This->buflen); + return DSERR_INVALIDPARAM; + } - if ((writebytes == This->buflen) && - ((This->state == STATE_STARTING) || - (This->state == STATE_PLAYING))) - /* some games, like Half-Life, try to be clever (not) and - * keep one secondary buffer, and mix sounds into it itself, - * locking the entire buffer every time... so we can just forget - * about tracking the last-written-to-position... */ - This->probably_valid_to = (DWORD)-1; - else - This->probably_valid_to = writecursor; + if (writebytes > This->buflen) { + WARN("Invalid parameter, writebytes: %u > buflen: %u\n", + writebytes, This->buflen); + return DSERR_INVALIDPARAM; + } + + /* **** */ + RtlAcquireResourceShared(&This->lock, TRUE); - if (!(This->dsound->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { + if (!(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { hres = IDsDriverBuffer_Lock(This->hwbuf, lplpaudioptr1, audiobytes1, lplpaudioptr2, audiobytes2, @@ -602,50 +561,41 @@ static HRESULT WINAPI IDirectSoundBufferImpl_Lock( 0); if (hres != DS_OK) { WARN("IDsDriverBuffer_Lock failed\n"); - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); return hres; } } else { - BOOL remix = FALSE; if (writecursor+writebytes <= This->buflen) { *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor; + if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING) + WARN("Overwriting mixing position, case 1\n"); *audiobytes1 = writebytes; if (lplpaudioptr2) *(LPBYTE*)lplpaudioptr2 = NULL; if (audiobytes2) *audiobytes2 = 0; - TRACE("->%ld.0\n",writebytes); + TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", + *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor); + TRACE("->%d.0\n",writebytes); } else { + DWORD remainder = writebytes + writecursor - This->buflen; *(LPBYTE*)lplpaudioptr1 = This->buffer->memory+writecursor; *audiobytes1 = This->buflen-writecursor; + if (This->sec_mixpos >= writecursor && This->sec_mixpos < writecursor + writebytes && This->state == STATE_PLAYING) + WARN("Overwriting mixing position, case 2\n"); if (lplpaudioptr2) *(LPBYTE*)lplpaudioptr2 = This->buffer->memory; if (audiobytes2) *audiobytes2 = writebytes-(This->buflen-writecursor); - TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0); - } - if (This->state == STATE_PLAYING) { - /* if the segment between playpos and buf_mixpos is touched, - * we need to cancel some mixing */ - /* we'll assume that the app always calls GetCurrentPosition before - * locking a playing buffer, so that last_playpos is up-to-date */ - if (This->buf_mixpos >= This->last_playpos) { - if (This->buf_mixpos > writecursor && - This->last_playpos < writecursor+writebytes) - remix = TRUE; - } else { - if (This->buf_mixpos > writecursor || - This->last_playpos < writecursor+writebytes) - remix = TRUE; - } - if (remix) { - TRACE("locking prebuffered region, ouch\n"); - DSOUND_MixCancelAt(This, writecursor); - } + if (audiobytes2 && This->sec_mixpos < remainder && This->state == STATE_PLAYING) + WARN("Overwriting mixing position, case 3\n"); + TRACE("Locked %p(%i bytes) and %p(%i bytes) writecursor=%d\n", *(LPBYTE*)lplpaudioptr1, *audiobytes1, lplpaudioptr2 ? *(LPBYTE*)lplpaudioptr2 : NULL, audiobytes2 ? *audiobytes2: 0, writecursor); } } - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); + /* **** */ + return DS_OK; } @@ -654,20 +604,33 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetCurrentPosition( ) { HRESULT hres = DS_OK; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - TRACE("(%p,%ld)\n",This,newpos); + DWORD oldpos; + TRACE("(%p,%d)\n",This,newpos); /* **** */ - EnterCriticalSection(&(This->lock)); + RtlAcquireResourceExclusive(&This->lock, TRUE); + + oldpos = This->sec_mixpos; + /* start mixing from this new location instead */ newpos %= This->buflen; - This->buf_mixpos = newpos; + newpos -= newpos%This->pwfx->nBlockAlign; + This->sec_mixpos = newpos; + + /* at this point, do not attempt to reset buffers, mess with primary mix position, + or anything like that to reduce latancy. The data already prebuffered cannot be changed */ + + /* position HW buffer if applicable, else just start mixing from new location instead */ if (This->hwbuf) { hres = IDsDriverBuffer_SetPosition(This->hwbuf, This->buf_mixpos); if (hres != DS_OK) WARN("IDsDriverBuffer_SetPosition failed\n"); } + else if (oldpos != newpos) + /* FIXME: Perhaps add a call to DSOUND_MixToTemporary here? Not sure it's needed */ + This->buf_mixpos = DSOUND_secpos_to_bufpos(This, newpos, 0, NULL); - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); /* **** */ return hres; @@ -679,10 +642,10 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetPan( HRESULT hres = DS_OK; IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - TRACE("(%p,%ld)\n",This,pan); + TRACE("(%p,%d)\n",This,pan); if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) { - WARN("invalid parameter: pan = %ld\n", pan); + WARN("invalid parameter: pan = %d\n", pan); return DSERR_INVALIDPARAM; } @@ -694,7 +657,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetPan( } /* **** */ - EnterCriticalSection(&(This->lock)); + RtlAcquireResourceExclusive(&This->lock, TRUE); if (This->volpan.lPan != pan) { This->volpan.lPan = pan; @@ -704,11 +667,10 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetPan( hres = IDsDriverBuffer_SetVolumePan(This->hwbuf, &(This->volpan)); if (hres != DS_OK) WARN("IDsDriverBuffer_SetVolumePan failed\n"); - } else - DSOUND_ForceRemix(This); + } } - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); /* **** */ return hres; @@ -738,37 +700,46 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetPan( static HRESULT WINAPI IDirectSoundBufferImpl_Unlock( LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2 ) { - IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - DWORD probably_valid_to; + IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface, *iter; HRESULT hres = DS_OK; - TRACE("(%p,%p,%ld,%p,%ld)\n", This,p1,x1,p2,x2); + TRACE("(%p,%p,%d,%p,%d)\n", This,p1,x1,p2,x2); /* **** */ - EnterCriticalSection(&(This->lock)); + RtlAcquireResourceShared(&This->lock, TRUE); - if (!(This->dsound->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { + if (!(This->device->drvdesc.dwFlags & DSDDESC_DONTNEEDSECONDARYLOCK) && This->hwbuf) { hres = IDsDriverBuffer_Unlock(This->hwbuf, p1, x1, p2, x2); if (hres != DS_OK) WARN("IDsDriverBuffer_Unlock failed\n"); } - if (hres == DS_OK) { - if (p2) probably_valid_to = (((LPBYTE)p2)-This->buffer->memory) + x2; - else probably_valid_to = (((LPBYTE)p1)-This->buffer->memory) + x1; - probably_valid_to %= This->buflen; - if ((probably_valid_to == 0) && ((x1+x2) == This->buflen) && - ((This->state == STATE_STARTING) || - (This->state == STATE_PLAYING))) - /* see IDirectSoundBufferImpl_Lock */ - probably_valid_to = (DWORD)-1; - This->probably_valid_to = probably_valid_to; - } - - LeaveCriticalSection(&(This->lock)); + RtlReleaseResource(&This->lock); /* **** */ - TRACE("probably_valid_to=%ld\n", This->probably_valid_to); + if (!p2) + x2 = 0; + + if (!This->hwbuf && (x1 || x2)) + { + RtlAcquireResourceShared(&This->device->buffer_list_lock, TRUE); + LIST_FOR_EACH_ENTRY(iter, &This->buffer->buffers, IDirectSoundBufferImpl, entry ) + { + RtlAcquireResourceShared(&iter->lock, TRUE); + if (x1) + { + if(x1 + (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory > iter->buflen) + hres = DSERR_INVALIDPARAM; + else + DSOUND_MixToTemporary(iter, (DWORD_PTR)p1 - (DWORD_PTR)iter->buffer->memory, x1, FALSE); + } + if (x2) + DSOUND_MixToTemporary(iter, 0, x2, FALSE); + RtlReleaseResource(&iter->lock); + } + RtlReleaseResource(&This->device->buffer_list_lock); + } + return hres; } @@ -792,7 +763,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetFrequency( } *freq = This->freq; - TRACE("-> %ld\n", *freq); + TRACE("-> %d\n", *freq); return DS_OK; } @@ -803,7 +774,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_SetFX( IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; DWORD u; - FIXME("(%p,%lu,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes); + FIXME("(%p,%u,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes); if (pdwResultCodes) for (u=0; udwSize < sizeof(*caps)) { - WARN("invalid parameter: caps->dwSize = %ld < %d\n",caps->dwSize, sizeof(*caps)); + WARN("invalid parameter: caps->dwSize = %d\n",caps->dwSize); return DSERR_INVALIDPARAM; } @@ -870,11 +839,8 @@ static HRESULT WINAPI IDirectSoundBufferImpl_GetCaps( caps->dwBufferBytes = This->buflen; - /* This value represents the speed of the "unlock" command. - As unlock is quite fast (it does not do anything), I put - 4096 ko/s = 4 Mo / s */ - /* FIXME: hwbuf speed */ - caps->dwUnlockTransferRate = 4096; + /* According to windows, this is zero*/ + caps->dwUnlockTransferRate = 0; caps->dwPlayCpuOverhead = 0; return DS_OK; @@ -897,11 +863,11 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( if ( IsEqualGUID(riid, &IID_IUnknown) || IsEqualGUID(riid, &IID_IDirectSoundBuffer) || IsEqualGUID(riid, &IID_IDirectSoundBuffer8) ) { - if (!This->dsb) - SecondaryBufferImpl_Create(This, &(This->dsb)); - if (This->dsb) { - IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->dsb); - *ppobj = This->dsb; + if (!This->secondary) + SecondaryBufferImpl_Create(This, &(This->secondary)); + if (This->secondary) { + IDirectSoundBuffer8_AddRef((LPDIRECTSOUNDBUFFER8)This->secondary); + *ppobj = This->secondary; return S_OK; } WARN("IID_IDirectSoundBuffer\n"); @@ -982,8 +948,8 @@ static const IDirectSoundBuffer8Vtbl dsbvt = IDirectSoundBufferImpl_GetObjectInPath }; -HRESULT WINAPI IDirectSoundBufferImpl_Create( - IDirectSoundImpl *ds, +HRESULT IDirectSoundBufferImpl_Create( + DirectSoundDevice * device, IDirectSoundBufferImpl **pdsb, LPCDSBUFFERDESC dsbd) { @@ -992,10 +958,10 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( HRESULT err = DS_OK; DWORD capf = 0; int use_hw, alloc_size, cp_size; - TRACE("(%p,%p,%p)\n",ds,pdsb,dsbd); + TRACE("(%p,%p,%p)\n",device,pdsb,dsbd); if (dsbd->dwBufferBytes < DSBSIZE_MIN || dsbd->dwBufferBytes > DSBSIZE_MAX) { - WARN("invalid parameter: dsbd->dwBufferBytes = %ld\n", dsbd->dwBufferBytes); + WARN("invalid parameter: dsbd->dwBufferBytes = %d\n", dsbd->dwBufferBytes); *pdsb = NULL; return DSERR_INVALIDPARAM; /* FIXME: which error? */ } @@ -1011,8 +977,8 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( TRACE("Created buffer at %p\n", dsb); dsb->ref = 0; - dsb->dsb = 0; - dsb->dsound = ds; + dsb->secondary = 0; + dsb->device = device; dsb->lpVtbl = &dsbvt; dsb->iks = NULL; @@ -1023,7 +989,7 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( if (wfex->wFormatTag == WAVE_FORMAT_PCM) { alloc_size = sizeof(WAVEFORMATEX); cp_size = sizeof(PCMWAVEFORMAT); - } else + } else alloc_size = cp_size = sizeof(WAVEFORMATEX) + wfex->cbSize; dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,alloc_size); @@ -1037,8 +1003,8 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( CopyMemory(dsb->pwfx, wfex, cp_size); if (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign) - dsb->buflen = dsbd->dwBufferBytes + - (dsbd->lpwfxFormat->nBlockAlign - + dsb->buflen = dsbd->dwBufferBytes + + (dsbd->lpwfxFormat->nBlockAlign - (dsbd->dwBufferBytes % dsbd->lpwfxFormat->nBlockAlign)); else dsb->buflen = dsbd->dwBufferBytes; @@ -1055,8 +1021,19 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( if (wfex->wBitsPerSample==16) capf |= DSCAPS_SECONDARY16BIT; else capf |= DSCAPS_SECONDARY8BIT; - use_hw = (ds->device->drvcaps.dwFlags & capf) == capf; - TRACE("use_hw = 0x%08x, capf = 0x%08lx, ds->drvcaps.dwFlags = 0x%08lx\n", use_hw, capf, ds->device->drvcaps.dwFlags); + use_hw = !!(dsbd->dwFlags & DSBCAPS_LOCHARDWARE); + TRACE("use_hw = %d, capf = 0x%08x, device->drvcaps.dwFlags = 0x%08x\n", use_hw, capf, device->drvcaps.dwFlags); + if (use_hw && ((device->drvcaps.dwFlags & capf) != capf || !device->driver)) + { + if (device->driver) + WARN("Format not supported for hardware buffer\n"); + HeapFree(GetProcessHeap(),0,dsb->pwfx); + HeapFree(GetProcessHeap(),0,dsb); + *pdsb = NULL; + if ((device->drvcaps.dwFlags & capf) != capf) + return DSERR_BADFORMAT; + return DSERR_GENERIC; + } /* FIXME: check hardware sample rate mixing capabilities */ /* FIXME: check app hints for software/hardware buffer (STATIC, LOCHARDWARE, etc) */ @@ -1074,7 +1051,7 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( } /* Allocate system memory for buffer if applicable */ - if ((ds->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) { + if ((device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) || !use_hw) { dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen); if (dsb->buffer->memory == NULL) { WARN("out of memory\n"); @@ -1084,50 +1061,43 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( *pdsb = NULL; return DSERR_OUTOFMEMORY; } - dsb->buffer->ref = 1; - FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0); } /* Allocate the hardware buffer */ if (use_hw) { - err = IDsDriver_CreateSoundBuffer(ds->device->driver,wfex,dsbd->dwFlags,0, + err = IDsDriver_CreateSoundBuffer(device->driver,wfex,dsbd->dwFlags,0, &(dsb->buflen),&(dsb->buffer->memory), (LPVOID*)&(dsb->hwbuf)); - /* fall back to software buffer on failure */ - if (err != DS_OK) { - TRACE("IDsDriver_CreateSoundBuffer failed, falling back to software buffer\n"); - use_hw = 0; - if (ds->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { - dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen); - if (dsb->buffer->memory == NULL) { - WARN("out of memory\n"); - HeapFree(GetProcessHeap(),0,dsb->buffer); - HeapFree(GetProcessHeap(),0,dsb->pwfx); - HeapFree(GetProcessHeap(),0,dsb); - *pdsb = NULL; - return DSERR_OUTOFMEMORY; - } - dsb->buffer->ref = 1; - FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0); - } - err = DS_OK; + if (FAILED(err)) + { + WARN("Failed to create hardware secondary buffer: %08x\n", err); + if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) + HeapFree(GetProcessHeap(),0,dsb->buffer->memory); + HeapFree(GetProcessHeap(),0,dsb->buffer); + HeapFree(GetProcessHeap(),0,dsb->pwfx); + HeapFree(GetProcessHeap(),0,dsb); + *pdsb = NULL; + return DSERR_GENERIC; } } - /* calculate fragment size and write lead */ - DSOUND_RecalcFormat(dsb); + dsb->buffer->ref = 1; + list_init(&dsb->buffer->buffers); + list_add_head(&dsb->buffer->buffers, &dsb->entry); + FillMemory(dsb->buffer->memory, dsb->buflen, dsbd->lpwfxFormat->wBitsPerSample == 8 ? 128 : 0); /* It's not necessary to initialize values to zero since */ /* we allocated this structure with HEAP_ZERO_MEMORY... */ - dsb->playpos = 0; - dsb->buf_mixpos = 0; + dsb->buf_mixpos = dsb->sec_mixpos = 0; dsb->state = STATE_STOPPED; - dsb->freqAdjust = (dsb->freq << DSOUND_FREQSHIFT) / - ds->device->pwfx->nSamplesPerSec; + dsb->freqAdjust = ((DWORD64)dsb->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec; dsb->nAvgBytesPerSec = dsb->freq * dsbd->lpwfxFormat->nBlockAlign; + /* calculate fragment size and write lead */ + DSOUND_RecalcFormat(dsb); + if (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D) { dsb->ds3db_ds3db.dwSize = sizeof(DS3DBUFFER); dsb->ds3db_ds3db.vPosition.x = 0.0; @@ -1151,17 +1121,15 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( } else DSOUND_RecalcVolPan(&(dsb->volpan)); - InitializeCriticalSection(&(dsb->lock)); - dsb->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUNDBUFFER_lock"; + RtlInitializeResource(&dsb->lock); /* register buffer if not primary */ if (!(dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER)) { - err = DSOUND_AddBuffer(ds, dsb); + err = DirectSoundDevice_AddBuffer(device, dsb); if (err != DS_OK) { HeapFree(GetProcessHeap(),0,dsb->buffer->memory); HeapFree(GetProcessHeap(),0,dsb->buffer); - dsb->lock.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&(dsb->lock)); + RtlDeleteResource(&dsb->lock); HeapFree(GetProcessHeap(),0,dsb->pwfx); HeapFree(GetProcessHeap(),0,dsb); dsb = NULL; @@ -1172,7 +1140,7 @@ HRESULT WINAPI IDirectSoundBufferImpl_Create( return err; } -HRESULT WINAPI IDirectSoundBufferImpl_Destroy( +HRESULT IDirectSoundBufferImpl_Destroy( IDirectSoundBufferImpl *pdsb) { TRACE("(%p)\n",pdsb); @@ -1199,10 +1167,10 @@ HRESULT WINAPI IDirectSoundBufferImpl_Destroy( pdsb->notify = NULL; } - if (pdsb->dsb) { + if (pdsb->secondary) { WARN("dsb not NULL\n"); - SecondaryBufferImpl_Destroy(pdsb->dsb); - pdsb->dsb = NULL; + SecondaryBufferImpl_Destroy(pdsb->secondary); + pdsb->secondary = NULL; } while (IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)pdsb) > 0); @@ -1210,6 +1178,83 @@ HRESULT WINAPI IDirectSoundBufferImpl_Destroy( return S_OK; } +HRESULT IDirectSoundBufferImpl_Duplicate( + DirectSoundDevice *device, + IDirectSoundBufferImpl **ppdsb, + IDirectSoundBufferImpl *pdsb) +{ + IDirectSoundBufferImpl *dsb; + HRESULT hres = DS_OK; + int size; + TRACE("(%p,%p,%p)\n", device, pdsb, pdsb); + + dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb)); + + if (dsb == NULL) { + WARN("out of memory\n"); + *ppdsb = NULL; + return DSERR_OUTOFMEMORY; + } + + CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl)); + + if (pdsb->hwbuf) { + TRACE("duplicating hardware buffer\n"); + + hres = IDsDriver_DuplicateSoundBuffer(device->driver, pdsb->hwbuf, + (LPVOID *)&dsb->hwbuf); + if (FAILED(hres)) { + WARN("IDsDriver_DuplicateSoundBuffer failed (%08x)\n", hres); + HeapFree(GetProcessHeap(),0,dsb); + *ppdsb = NULL; + return hres; + } + } + + dsb->buffer->ref++; + list_add_head(&dsb->buffer->buffers, &dsb->entry); + dsb->ref = 0; + dsb->state = STATE_STOPPED; + dsb->buf_mixpos = dsb->sec_mixpos = 0; + dsb->device = device; + dsb->ds3db = NULL; + dsb->iks = NULL; /* FIXME? */ + dsb->secondary = NULL; + dsb->tmp_buffer = NULL; + DSOUND_RecalcFormat(dsb); + DSOUND_MixToTemporary(dsb, 0, dsb->buflen, FALSE); + + /* variable sized struct so calculate size based on format */ + size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize; + + dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size); + if (dsb->pwfx == NULL) { + WARN("out of memory\n"); + HeapFree(GetProcessHeap(),0,dsb->buffer); + HeapFree(GetProcessHeap(),0,dsb); + *ppdsb = NULL; + return DSERR_OUTOFMEMORY; + } + + CopyMemory(dsb->pwfx, pdsb->pwfx, size); + + RtlInitializeResource(&dsb->lock); + + /* register buffer */ + hres = DirectSoundDevice_AddBuffer(device, dsb); + if (hres != DS_OK) { + RtlDeleteResource(&dsb->lock); + HeapFree(GetProcessHeap(),0,dsb->tmp_buffer); + HeapFree(GetProcessHeap(),0,dsb->buffer); + HeapFree(GetProcessHeap(),0,dsb->pwfx); + HeapFree(GetProcessHeap(),0,dsb); + *ppdsb = 0; + } + + *ppdsb = dsb; + return hres; +} + /******************************************************************************* * SecondaryBuffer */ @@ -1225,20 +1270,22 @@ static HRESULT WINAPI SecondaryBufferImpl_QueryInterface( static ULONG WINAPI SecondaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) { - IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; + SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } static ULONG WINAPI SecondaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) { - IDirectSoundBufferImpl *This = (IDirectSoundBufferImpl *)iface; - ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; + ULONG ref; + TRACE("(%p)\n", This); + ref = InterlockedDecrement(&(This->ref)); + TRACE("ref was %d\n", ref + 1); if (!ref) { - This->dsb->dsb = NULL; + This->dsb->secondary = NULL; IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)This->dsb); HeapFree(GetProcessHeap(), 0, This); TRACE("(%p) released\n", This); @@ -1268,7 +1315,7 @@ static HRESULT WINAPI SecondaryBufferImpl_GetFormat( LPDIRECTSOUNDBUFFER8 iface,LPWAVEFORMATEX lpwf,DWORD wfsize,LPDWORD wfwritten) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%p,%ld,%p)\n",This,lpwf,wfsize,wfwritten); + TRACE("(%p,%p,%d,%p)\n",This,lpwf,wfsize,wfwritten); return IDirectSoundBufferImpl_GetFormat((LPDIRECTSOUNDBUFFER8)This->dsb,lpwf,wfsize,wfwritten); } @@ -1322,14 +1369,14 @@ static HRESULT WINAPI SecondaryBufferImpl_Lock( LPDIRECTSOUNDBUFFER8 iface, DWORD writecursor, DWORD writebytes, - LPVOID lplpaudioptr1, + LPVOID *lplpaudioptr1, LPDWORD audiobytes1, - LPVOID lplpaudioptr2, + LPVOID *lplpaudioptr2, LPDWORD audiobytes2, DWORD dwFlags) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx)\n", + TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x)\n", This,writecursor,writebytes,lplpaudioptr1,audiobytes1,lplpaudioptr2,audiobytes2,dwFlags); return IDirectSoundBufferImpl_Lock((LPDIRECTSOUNDBUFFER8)This->dsb, @@ -1340,7 +1387,7 @@ static HRESULT WINAPI SecondaryBufferImpl_Play( LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%08lx,%08lx,%08lx)\n",This,reserved1,reserved2,flags); + TRACE("(%p,%08x,%08x,%08x)\n",This,reserved1,reserved2,flags); return IDirectSoundBufferImpl_Play((LPDIRECTSOUNDBUFFER8)This->dsb,reserved1,reserved2,flags); } @@ -1349,7 +1396,7 @@ static HRESULT WINAPI SecondaryBufferImpl_SetCurrentPosition( LPDIRECTSOUNDBUFFER8 iface,DWORD newpos) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%ld)\n",This,newpos); + TRACE("(%p,%d)\n",This,newpos); return IDirectSoundBufferImpl_SetCurrentPosition((LPDIRECTSOUNDBUFFER8)This->dsb,newpos); } @@ -1367,7 +1414,7 @@ static HRESULT WINAPI SecondaryBufferImpl_SetVolume( LPDIRECTSOUNDBUFFER8 iface,LONG vol) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%ld)\n",This,vol); + TRACE("(%p,%d)\n",This,vol); return IDirectSoundBufferImpl_SetVolume((LPDIRECTSOUNDBUFFER8)This->dsb,vol); } @@ -1376,7 +1423,7 @@ static HRESULT WINAPI SecondaryBufferImpl_SetPan( LPDIRECTSOUNDBUFFER8 iface,LONG pan) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%ld)\n",This,pan); + TRACE("(%p,%d)\n",This,pan); return IDirectSoundBufferImpl_SetPan((LPDIRECTSOUNDBUFFER8)This->dsb,pan); } @@ -1385,7 +1432,7 @@ static HRESULT WINAPI SecondaryBufferImpl_SetFrequency( LPDIRECTSOUNDBUFFER8 iface,DWORD freq) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%ld)\n",This,freq); + TRACE("(%p,%d)\n",This,freq); return IDirectSoundBufferImpl_SetFrequency((LPDIRECTSOUNDBUFFER8)This->dsb,freq); } @@ -1406,7 +1453,7 @@ static HRESULT WINAPI SecondaryBufferImpl_Unlock( DWORD dwAudioBytes2) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%p,%ld,%p,%ld)\n", + TRACE("(%p,%p,%d,%p,%d)\n", This, lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2); return IDirectSoundBufferImpl_Unlock((LPDIRECTSOUNDBUFFER8)This->dsb, @@ -1426,7 +1473,7 @@ static HRESULT WINAPI SecondaryBufferImpl_SetFX( LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%lu,%p,%p)\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes); + TRACE("(%p,%u,%p,%p)\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes); return IDirectSoundBufferImpl_SetFX((LPDIRECTSOUNDBUFFER8)This->dsb,dwEffectsCount,pDSFXDesc,pdwResultCodes); } @@ -1435,7 +1482,7 @@ static HRESULT WINAPI SecondaryBufferImpl_AcquireResources( LPDIRECTSOUNDBUFFER8 iface,DWORD dwFlags,DWORD dwEffectsCount,LPDWORD pdwResultCodes) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%08lu,%lu,%p)\n",This,dwFlags,dwEffectsCount,pdwResultCodes); + TRACE("(%p,%08u,%u,%p)\n",This,dwFlags,dwEffectsCount,pdwResultCodes); return IDirectSoundBufferImpl_AcquireResources((LPDIRECTSOUNDBUFFER8)This->dsb,dwFlags,dwEffectsCount,pdwResultCodes); } @@ -1444,7 +1491,7 @@ static HRESULT WINAPI SecondaryBufferImpl_GetObjectInPath( LPDIRECTSOUNDBUFFER8 iface,REFGUID rguidObject,DWORD dwIndex,REFGUID rguidInterface,LPVOID* ppObject) { SecondaryBufferImpl *This = (SecondaryBufferImpl *)iface; - TRACE("(%p,%s,%lu,%s,%p)\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject); + TRACE("(%p,%s,%u,%s,%p)\n",This,debugstr_guid(rguidObject),dwIndex,debugstr_guid(rguidInterface),ppObject); return IDirectSoundBufferImpl_GetObjectInPath((LPDIRECTSOUNDBUFFER8)This->dsb,rguidObject,dwIndex,rguidInterface,ppObject); } @@ -1477,7 +1524,7 @@ static const IDirectSoundBuffer8Vtbl sbvt = SecondaryBufferImpl_GetObjectInPath }; -HRESULT WINAPI SecondaryBufferImpl_Create( +HRESULT SecondaryBufferImpl_Create( IDirectSoundBufferImpl *dsb, SecondaryBufferImpl **psb) { @@ -1500,7 +1547,7 @@ HRESULT WINAPI SecondaryBufferImpl_Create( return S_OK; } -HRESULT WINAPI SecondaryBufferImpl_Destroy( +static HRESULT SecondaryBufferImpl_Destroy( SecondaryBufferImpl *pdsb) { TRACE("(%p)\n",pdsb); diff --git a/reactos/dll/directx/dsound/capture.c b/reactos/dll/directx/dsound/capture.c index 35dbeffae67..2a8252f9c0f 100644 --- a/reactos/dll/directx/dsound/capture.c +++ b/reactos/dll/directx/dsound/capture.c @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ /* * TODO: @@ -31,9 +31,9 @@ #define NONAMELESSUNION #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "mmsystem.h" #include "mmddk.h" -#include "winreg.h" #include "winternl.h" #include "winnls.h" #include "wine/debug.h" @@ -43,60 +43,60 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); -static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize( - LPDIRECTSOUNDCAPTURE iface, - LPCGUID lpcGUID ); -static ULONG WINAPI IDirectSoundCaptureImpl_Release( - LPDIRECTSOUNDCAPTURE iface ); -static ULONG WINAPI IDirectSoundCaptureBufferImpl_Release( - LPDIRECTSOUNDCAPTUREBUFFER8 iface ); -static HRESULT DSOUND_CreateDirectSoundCaptureBuffer( - IDirectSoundCaptureImpl *ipDSC, - LPCDSCBUFFERDESC lpcDSCBufferDesc, - LPVOID* ppobj ); +/***************************************************************************** + * IDirectSoundCapture implementation structure + */ +struct IDirectSoundCaptureImpl +{ + /* IUnknown fields */ + const IDirectSoundCaptureVtbl *lpVtbl; + LONG ref; -static const IDirectSoundCaptureVtbl dscvt; -static const IDirectSoundCaptureBuffer8Vtbl dscbvt; + DirectSoundCaptureDevice *device; +}; -DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS]; +static HRESULT IDirectSoundCaptureImpl_Create(LPDIRECTSOUNDCAPTURE8 * ppds); -static const char * captureStateString[] = { - "STATE_STOPPED", - "STATE_STARTING", - "STATE_CAPTURING", - "STATE_STOPPING" -}; -HRESULT WINAPI IDirectSoundCaptureImpl_Create( - LPDIRECTSOUNDCAPTURE8 * ppDSC) +/***************************************************************************** + * IDirectSoundCaptureNotify implementation structure + */ +struct IDirectSoundCaptureNotifyImpl { - IDirectSoundCaptureImpl *pDSC; - TRACE("(%p)\n", ppDSC); + /* IUnknown fields */ + const IDirectSoundNotifyVtbl *lpVtbl; + LONG ref; + IDirectSoundCaptureBufferImpl* dscb; +}; - /* Allocate memory */ - pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl)); - if (pDSC == NULL) { - WARN("out of memory\n"); - *ppDSC = NULL; - return DSERR_OUTOFMEMORY; - } +static HRESULT IDirectSoundCaptureNotifyImpl_Create(IDirectSoundCaptureBufferImpl *dscb, + IDirectSoundCaptureNotifyImpl ** pdscn); - pDSC->lpVtbl = &dscvt; - pDSC->ref = 0; - pDSC->device = NULL; - *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC; +DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS]; - return DS_OK; -} +static HRESULT DirectSoundCaptureDevice_Create(DirectSoundCaptureDevice ** ppDevice); -HRESULT WINAPI DSOUND_CaptureCreate( - LPDIRECTSOUNDCAPTURE *ppDSC, - IUnknown *pUnkOuter) +static const char * const captureStateString[] = { + "STATE_STOPPED", + "STATE_STARTING", + "STATE_CAPTURING", + "STATE_STOPPING" +}; + +HRESULT DSOUND_CaptureCreate( + REFIID riid, + LPDIRECTSOUNDCAPTURE *ppDSC) { LPDIRECTSOUNDCAPTURE pDSC; HRESULT hr; - TRACE("(%p,%p)\n",ppDSC,pUnkOuter); + TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC); + + if (!IsEqualIID(riid, &IID_IUnknown) && + !IsEqualIID(riid, &IID_IDirectSoundCapture)) { + *ppDSC = 0; + return E_NOINTERFACE; + } /* Get dsound configuration */ setup_dsound_options(); @@ -113,13 +113,19 @@ HRESULT WINAPI DSOUND_CaptureCreate( return hr; } -HRESULT WINAPI DSOUND_CaptureCreate8( - LPDIRECTSOUNDCAPTURE8 *ppDSC8, - IUnknown *pUnkOuter) +HRESULT DSOUND_CaptureCreate8( + REFIID riid, + LPDIRECTSOUNDCAPTURE8 *ppDSC8) { LPDIRECTSOUNDCAPTURE8 pDSC8; HRESULT hr; - TRACE("(%p,%p)\n",ppDSC8,pUnkOuter); + TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSC8); + + if (!IsEqualIID(riid, &IID_IUnknown) && + !IsEqualIID(riid, &IID_IDirectSoundCapture8)) { + *ppDSC8 = 0; + return E_NOINTERFACE; + } /* Get dsound configuration */ setup_dsound_options(); @@ -178,7 +184,7 @@ HRESULT WINAPI DirectSoundCaptureCreate( return DSERR_NOAGGREGATION; } - hr = DSOUND_CaptureCreate(&pDSC, (IUnknown *)pUnkOuter); + hr = DSOUND_CaptureCreate(&IID_IDirectSoundCapture, &pDSC); if (hr == DS_OK) { hr = IDirectSoundCapture_Initialize(pDSC, lpcGUID); if (hr != DS_OK) { @@ -234,7 +240,7 @@ HRESULT WINAPI DirectSoundCaptureCreate8( return DSERR_NOAGGREGATION; } - hr = DSOUND_CaptureCreate8(&pDSC8, (IUnknown *)pUnkOuter); + hr = DSOUND_CaptureCreate8(&IID_IDirectSoundCapture8, &pDSC8); if (hr == DS_OK) { hr = IDirectSoundCapture_Initialize(pDSC8, lpcGUID); if (hr != DS_OK) { @@ -248,31 +254,6 @@ HRESULT WINAPI DirectSoundCaptureCreate8( return hr; } -static HRESULT DirectSoundCaptureDevice_Create( - DirectSoundCaptureDevice ** ppDevice) -{ - DirectSoundCaptureDevice * device; - TRACE("(%p)\n", ppDevice); - - /* Allocate memory */ - device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice)); - - if (device == NULL) { - WARN("out of memory\n"); - return DSERR_OUTOFMEMORY; - } - - device->ref = 1; - device->state = STATE_STOPPED; - - InitializeCriticalSection( &(device->lock) ); - device->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSCAPTURE_lock"; - - *ppDevice = device; - - return DS_OK; -} - /*************************************************************************** * DirectSoundCaptureEnumerateA [DSOUND.7] * @@ -308,7 +289,7 @@ DirectSoundCaptureEnumerateA( if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) { for (wid = 0; wid < devs; ++wid) { if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", "Primary Sound Capture Driver",desc.szDrvname,lpContext); @@ -321,7 +302,7 @@ DirectSoundCaptureEnumerateA( } for (wid = 0; wid < devs; ++wid) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext); @@ -370,7 +351,7 @@ DirectSoundCaptureEnumerateW( if (GetDeviceID(&DSDEVID_DefaultCapture, &guid) == DS_OK) { for (wid = 0; wid < devs; ++wid) { if (IsEqualGUID( &guid, &DSOUND_capture_guids[wid] ) ) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", "Primary Sound Capture Driver",desc.szDrvname,lpContext); @@ -387,7 +368,7 @@ DirectSoundCaptureEnumerateW( } for (wid = 0; wid < devs; ++wid) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", debugstr_guid(&DSOUND_capture_guids[wid]),desc.szDesc,desc.szDrvname,lpContext); @@ -395,7 +376,7 @@ DirectSoundCaptureEnumerateW( wDesc, sizeof(wDesc)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wName, sizeof(wName)/sizeof(WCHAR) ); - if (lpDSEnumCallback((LPGUID)&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE) + if (lpDSEnumCallback(&DSOUND_capture_guids[wid], wDesc, wName, lpContext) == FALSE) return DS_OK; } } @@ -403,38 +384,59 @@ DirectSoundCaptureEnumerateW( return DS_OK; } +static void capture_CheckNotify(IDirectSoundCaptureBufferImpl *This, DWORD from, DWORD len) +{ + int i; + for (i = 0; i < This->nrofnotifies; ++i) { + LPDSBPOSITIONNOTIFY event = This->notifies + i; + DWORD offset = event->dwOffset; + TRACE("checking %d, position %d, event = %p\n", i, offset, event->hEventNotify); + + if (offset == DSBPN_OFFSETSTOP) { + if (!from && !len) { + SetEvent(event->hEventNotify); + TRACE("signalled event %p (%d)\n", event->hEventNotify, i); + return; + } + else return; + } + + if (offset >= from && offset < (from + len)) + { + TRACE("signalled event %p (%d)\n", event->hEventNotify, i); + SetEvent(event->hEventNotify); + } + } +} + static void CALLBACK -DSOUND_capture_callback( - HWAVEIN hwi, - UINT msg, - DWORD dwUser, - DWORD dw1, - DWORD dw2 ) +DSOUND_capture_callback(HWAVEIN hwi, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, + DWORD_PTR dw2) { DirectSoundCaptureDevice * This = (DirectSoundCaptureDevice*)dwUser; - TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\n",hwi,msg, + IDirectSoundCaptureBufferImpl * Moi = This->capture_buffer; + TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %d\n",hwi,msg, msg == MM_WIM_OPEN ? "MM_WIM_OPEN" : msg == MM_WIM_CLOSE ? "MM_WIM_CLOSE" : msg == MM_WIM_DATA ? "MM_WIM_DATA" : "UNKNOWN",dwUser,dw1,dw2,GetTickCount()); if (msg == MM_WIM_DATA) { - LPWAVEHDR pHdr = (LPWAVEHDR)dw1; EnterCriticalSection( &(This->lock) ); TRACE("DirectSoundCapture msg=MM_WIM_DATA, old This->state=%s, old This->index=%d\n", captureStateString[This->state],This->index); if (This->state != STATE_STOPPED) { int index = This->index; - if (This->state == STATE_STARTING) { - This->read_position = pHdr->dwBytesRecorded; + if (This->state == STATE_STARTING) This->state = STATE_CAPTURING; - } - if (This->capture_buffer->nrofnotifies) - SetEvent(This->capture_buffer->notifies[This->index].hEventNotify); - This->index = (This->index + 1) % This->nrofpwaves; + capture_CheckNotify(Moi, (DWORD_PTR)This->pwave[index].lpData - (DWORD_PTR)This->buffer, This->pwave[index].dwBufferLength); + This->index = (++This->index) % This->nrofpwaves; if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) { TRACE("end of buffer\n"); This->state = STATE_STOPPED; + capture_CheckNotify(Moi, 0, 0); } else { if (This->state == STATE_CAPTURING) { + waveInUnprepareHeader(hwi, &(This->pwave[index]), sizeof(WAVEHDR)); + waveInPrepareHeader(hwi, &(This->pwave[index]), sizeof(WAVEHDR)); waveInAddBuffer(hwi, &(This->pwave[index]), sizeof(WAVEHDR)); } else if (This->state == STATE_STOPPING) { TRACE("stopping\n"); @@ -450,6 +452,9 @@ DSOUND_capture_callback( TRACE("completed\n"); } +/*************************************************************************** + * IDirectSoundCaptureImpl + */ static HRESULT WINAPI IDirectSoundCaptureImpl_QueryInterface( LPDIRECTSOUNDCAPTURE iface, @@ -485,36 +490,7 @@ IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface ) { IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); - return ref; -} - -static ULONG DirectSoundCaptureDevice_Release( - DirectSoundCaptureDevice * device) -{ - ULONG ref; - TRACE("(%p) ref was %lu\n", device, device->ref); - - device->ref--; - ref=device->ref; - if (device->ref == 0) { - TRACE("deleting object\n"); - if (device->capture_buffer) - IDirectSoundCaptureBufferImpl_Release( - (LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer); - - if (device->driver) { - IDsCaptureDriver_Close(device->driver); - IDsCaptureDriver_Release(device->driver); - } - - HeapFree(GetProcessHeap(), 0, device->pwfx); - device->lock.DebugInfo->Spare[0] = 0; - DeleteCriticalSection( &(device->lock) ); - DSOUND_capture[device->drvdesc.dnDevNode] = NULL; - HeapFree(GetProcessHeap(), 0, device); - TRACE("(%p) released\n", device); - } + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -523,20 +499,19 @@ IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface ) { IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { if (This->device) DirectSoundCaptureDevice_Release(This->device); HeapFree( GetProcessHeap(), 0, This ); - TRACE("(%p) released\n", This); + TRACE("(%p) released\n", This); } return ref; } -static HRESULT WINAPI -IDirectSoundCaptureImpl_CreateCaptureBuffer( +HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer( LPDIRECTSOUNDCAPTURE iface, LPCDSCBUFFERDESC lpcDSCBufferDesc, LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer, @@ -547,11 +522,6 @@ IDirectSoundCaptureImpl_CreateCaptureBuffer( TRACE( "(%p,%p,%p,%p)\n",iface,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk); - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } - if (lpcDSCBufferDesc == NULL) { WARN("invalid parameter: lpcDSCBufferDesc == NULL)\n"); return DSERR_INVALIDPARAM; @@ -573,17 +543,16 @@ IDirectSoundCaptureImpl_CreateCaptureBuffer( return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */ } - hr = DSOUND_CreateDirectSoundCaptureBuffer(This, lpcDSCBufferDesc, - (LPVOID*)lplpDSCaptureBuffer ); + hr = IDirectSoundCaptureBufferImpl_Create(This->device, + (IDirectSoundCaptureBufferImpl **)lplpDSCaptureBuffer, lpcDSCBufferDesc); if (hr != DS_OK) - WARN("DSOUND_CreateDirectSoundCaptureBuffer failed\n"); + WARN("IDirectSoundCaptureBufferImpl_Create failed\n"); return hr; } -static HRESULT WINAPI -IDirectSoundCaptureImpl_GetCaps( +HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps( LPDIRECTSOUNDCAPTURE iface, LPDSCCAPS lpDSCCaps ) { @@ -601,8 +570,7 @@ IDirectSoundCaptureImpl_GetCaps( } if (lpDSCCaps->dwSize < sizeof(*lpDSCCaps)) { - WARN("invalid parameter: lpDSCCaps->dwSize = %ld < %d\n", - lpDSCCaps->dwSize, sizeof(*lpDSCCaps)); + WARN("invalid parameter: lpDSCCaps->dwSize = %d\n", lpDSCCaps->dwSize); return DSERR_INVALIDPARAM; } @@ -610,137 +578,24 @@ IDirectSoundCaptureImpl_GetCaps( lpDSCCaps->dwFormats = This->device->drvcaps.dwFormats; lpDSCCaps->dwChannels = This->device->drvcaps.dwChannels; - TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags, + TRACE("(flags=0x%08x,format=0x%08x,channels=%d)\n",lpDSCCaps->dwFlags, lpDSCCaps->dwFormats, lpDSCCaps->dwChannels); return DS_OK; } -static HRESULT WINAPI -IDirectSoundCaptureImpl_Initialize( +HRESULT WINAPI IDirectSoundCaptureImpl_Initialize( LPDIRECTSOUNDCAPTURE iface, LPCGUID lpcGUID ) { - HRESULT err = DSERR_INVALIDPARAM; - unsigned wid, widn; - BOOLEAN found = FALSE; - GUID devGUID; IDirectSoundCaptureImpl *This = (IDirectSoundCaptureImpl *)iface; - DirectSoundCaptureDevice *device = This->device; - TRACE("(%p)\n", This); - - if (!This) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } + TRACE("(%p,%s)\n", This, debugstr_guid(lpcGUID)); - if (device != NULL) { + if (This->device != NULL) { WARN("already initialized\n"); return DSERR_ALREADYINITIALIZED; } - - /* Default device? */ - if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) ) - lpcGUID = &DSDEVID_DefaultCapture; - - if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) { - WARN("invalid parameter: lpcGUID\n"); - return DSERR_INVALIDPARAM; - } - - widn = waveInGetNumDevs(); - if (!widn) { - WARN("no audio devices found\n"); - return DSERR_NODRIVER; - } - - /* enumerate WINMM audio devices and find the one we want */ - for (wid=0; widdevice = device; - device->guid = devGUID; - - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&(This->device->driver),0)); - if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) { - WARN("WineWaveInMessage failed; err=%lx\n",err); - return err; - } - err = DS_OK; - - /* Disable the direct sound driver to force emulation if requested. */ - if (ds_hw_accel == DS_HW_ACCEL_EMULATION) - This->device->driver = NULL; - - /* Get driver description */ - if (This->device->driver) { - TRACE("using DirectSound driver\n"); - err = IDsCaptureDriver_GetDriverDesc(This->device->driver, &(This->device->drvdesc)); - if (err != DS_OK) { - WARN("IDsCaptureDriver_GetDriverDesc failed\n"); - return err; - } - } else { - TRACE("using WINMM\n"); - /* if no DirectSound interface available, use WINMM API instead */ - This->device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | - DSDDESC_DOMMSYSTEMSETFORMAT; - } - - This->device->drvdesc.dnDevNode = wid; - - /* open the DirectSound driver if available */ - if (This->device->driver && (err == DS_OK)) - err = IDsCaptureDriver_Open(This->device->driver); - - if (err == DS_OK) { - This->device = device; - - /* the driver is now open, so it's now allowed to call GetCaps */ - if (This->device->driver) { - This->device->drvcaps.dwSize = sizeof(This->device->drvcaps); - err = IDsCaptureDriver_GetCaps(This->device->driver,&(This->device->drvcaps)); - if (err != DS_OK) { - WARN("IDsCaptureDriver_GetCaps failed\n"); - return err; - } - } else /*if (This->hwi)*/ { - WAVEINCAPSA wic; - err = mmErr(waveInGetDevCapsA((UINT)This->device->drvdesc.dnDevNode, &wic, sizeof(wic))); - - if (err == DS_OK) { - This->device->drvcaps.dwFlags = 0; - lstrcpynA(This->device->drvdesc.szDrvname, wic.szPname, - sizeof(This->device->drvdesc.szDrvname)); - - This->device->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER; - This->device->drvcaps.dwFormats = wic.dwFormats; - This->device->drvcaps.dwChannels = wic.wChannels; - } - } - } - - return err; + return DirectSoundCaptureDevice_Initialize(&This->device, lpcGUID); } static const IDirectSoundCaptureVtbl dscvt = @@ -756,200 +611,53 @@ static const IDirectSoundCaptureVtbl dscvt = IDirectSoundCaptureImpl_Initialize }; -static HRESULT -DSOUND_CreateDirectSoundCaptureBuffer( - IDirectSoundCaptureImpl *ipDSC, - LPCDSCBUFFERDESC lpcDSCBufferDesc, - LPVOID* ppobj ) +static HRESULT IDirectSoundCaptureImpl_Create( + LPDIRECTSOUNDCAPTURE8 * ppDSC) { - LPWAVEFORMATEX wfex; - TRACE( "(%p,%p)\n", lpcDSCBufferDesc, ppobj ); + IDirectSoundCaptureImpl *pDSC; + TRACE("(%p)\n", ppDSC); - if (ipDSC == NULL) { - WARN("invalid parameter: ipDSC == NULL\n"); - return DSERR_INVALIDPARAM; + /* Allocate memory */ + pDSC = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundCaptureImpl)); + if (pDSC == NULL) { + WARN("out of memory\n"); + *ppDSC = NULL; + return DSERR_OUTOFMEMORY; } - if (lpcDSCBufferDesc == NULL) { - WARN("invalid parameter: lpcDSCBufferDesc == NULL\n"); - return DSERR_INVALIDPARAM; - } + pDSC->lpVtbl = &dscvt; + pDSC->ref = 0; + pDSC->device = NULL; - if (ppobj == NULL) { - WARN("invalid parameter: ppobj == NULL\n"); - return DSERR_INVALIDPARAM; - } + *ppDSC = (LPDIRECTSOUNDCAPTURE8)pDSC; - if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) && - (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) || - (lpcDSCBufferDesc->dwBufferBytes == 0) || - (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { - WARN("invalid lpcDSCBufferDesc\n"); - *ppobj = NULL; - return DSERR_INVALIDPARAM; - } + return DS_OK; +} - if ( !ipDSC->device) { - WARN("not initialized\n"); - *ppobj = NULL; - return DSERR_UNINITIALIZED; +/******************************************************************************* + * IDirectSoundCaptureNotify + */ +static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface( + LPDIRECTSOUNDNOTIFY iface, + REFIID riid, + LPVOID *ppobj) +{ + IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + + if (This->dscb == NULL) { + WARN("invalid parameter\n"); + return E_INVALIDARG; } - wfex = lpcDSCBufferDesc->lpwfxFormat; - - if (wfex) { - TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld," - "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", - wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, - wfex->nAvgBytesPerSec, wfex->nBlockAlign, - wfex->wBitsPerSample, wfex->cbSize); - - if (wfex->wFormatTag == WAVE_FORMAT_PCM) { - ipDSC->device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)); - CopyMemory(ipDSC->device->pwfx, wfex, sizeof(WAVEFORMATEX)); - ipDSC->device->pwfx->cbSize = 0; - } else { - ipDSC->device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize); - CopyMemory(ipDSC->device->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize); - } - } else { - WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n"); - *ppobj = NULL; - return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */ - } - - *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, - sizeof(IDirectSoundCaptureBufferImpl)); - - if ( *ppobj == NULL ) { - WARN("out of memory\n"); - *ppobj = NULL; - return DSERR_OUTOFMEMORY; - } else { - HRESULT err = DS_OK; - LPBYTE newbuf; - DWORD buflen; - IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)*ppobj; - - This->ref = 1; - This->dsound = ipDSC; - This->dsound->device->capture_buffer = This; - This->notify = NULL; - This->nrofnotifies = 0; - This->hwnotify = NULL; - - This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, - lpcDSCBufferDesc->dwSize); - if (This->pdscbd) - CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize); - else { - WARN("no memory\n"); - This->dsound->device->capture_buffer = 0; - HeapFree( GetProcessHeap(), 0, This ); - *ppobj = NULL; - return DSERR_OUTOFMEMORY; - } - - This->lpVtbl = &dscbvt; - - if (ipDSC->device->driver) { - if (This->dsound->device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) - FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n"); - - if (This->dsound->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { - /* allocate buffer from system memory */ - buflen = lpcDSCBufferDesc->dwBufferBytes; - TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->device->buffer); - if (ipDSC->device->buffer) - newbuf = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->buffer,buflen); - else - newbuf = HeapAlloc(GetProcessHeap(),0,buflen); - - if (newbuf == NULL) { - WARN("failed to allocate capture buffer\n"); - err = DSERR_OUTOFMEMORY; - /* but the old buffer might still exist and must be re-prepared */ - } else { - ipDSC->device->buffer = newbuf; - ipDSC->device->buflen = buflen; - } - } else { - /* let driver allocate memory */ - ipDSC->device->buflen = lpcDSCBufferDesc->dwBufferBytes; - /* FIXME: */ - HeapFree( GetProcessHeap(), 0, ipDSC->device->buffer); - ipDSC->device->buffer = NULL; - } - - err = IDsCaptureDriver_CreateCaptureBuffer(ipDSC->device->driver, - ipDSC->device->pwfx,0,0,&(ipDSC->device->buflen),&(ipDSC->device->buffer),(LPVOID*)&(ipDSC->device->hwbuf)); - if (err != DS_OK) { - WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n"); - This->dsound->device->capture_buffer = 0; - HeapFree( GetProcessHeap(), 0, This ); - *ppobj = NULL; - return err; - } - } else { - DWORD flags = CALLBACK_FUNCTION; - if (ds_hw_accel != DS_HW_ACCEL_EMULATION) - flags |= WAVE_DIRECTSOUND; - err = mmErr(waveInOpen(&(ipDSC->device->hwi), - ipDSC->device->drvdesc.dnDevNode, ipDSC->device->pwfx, - (DWORD_PTR)DSOUND_capture_callback, (DWORD)ipDSC->device, flags)); - if (err != DS_OK) { - WARN("waveInOpen failed\n"); - This->dsound->device->capture_buffer = 0; - HeapFree( GetProcessHeap(), 0, This ); - *ppobj = NULL; - return err; - } - - buflen = lpcDSCBufferDesc->dwBufferBytes; - TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->device->buffer); - if (ipDSC->device->buffer) - newbuf = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->buffer,buflen); - else - newbuf = HeapAlloc(GetProcessHeap(),0,buflen); - if (newbuf == NULL) { - WARN("failed to allocate capture buffer\n"); - err = DSERR_OUTOFMEMORY; - /* but the old buffer might still exist and must be re-prepared */ - } else { - ipDSC->device->buffer = newbuf; - ipDSC->device->buflen = buflen; - } - } - } - - TRACE("returning DS_OK\n"); - return DS_OK; -} - -/******************************************************************************* - * IDirectSoundCaptureNotify - */ -static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_QueryInterface( - LPDIRECTSOUNDNOTIFY iface, - REFIID riid, - LPVOID *ppobj) -{ - IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface; - TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - - if (This->dscb == NULL) { - WARN("invalid parameter\n"); - return E_INVALIDARG; - } - - return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj); -} + return IDirectSoundCaptureBuffer_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER)This->dscb, riid, ppobj); +} static ULONG WINAPI IDirectSoundCaptureNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) { IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -957,7 +665,7 @@ static ULONG WINAPI IDirectSoundCaptureNotifyImpl_Release(LPDIRECTSOUNDNOTIFY if { IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { if (This->dscb->hwnotify) @@ -976,7 +684,7 @@ static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions( LPCDSBPOSITIONNOTIFY notify) { IDirectSoundCaptureNotifyImpl *This = (IDirectSoundCaptureNotifyImpl *)iface; - TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify); + TRACE("(%p,0x%08x,%p)\n",This,howmuch,notify); if (howmuch > 0 && notify == NULL) { WARN("invalid parameter: notify == NULL\n"); @@ -986,7 +694,7 @@ static HRESULT WINAPI IDirectSoundCaptureNotifyImpl_SetNotificationPositions( if (TRACE_ON(dsound)) { unsigned int i; for (i=0;inotify) hres = IDirectSoundCaptureNotifyImpl_Create(This, &This->notify); if (This->notify) { - if (This->dsound->device->hwbuf) { - hres = IDsCaptureDriverBuffer_QueryInterface(This->dsound->device->hwbuf, + IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify); + if (This->device->hwbuf && !This->hwnotify) { + hres = IDsCaptureDriverBuffer_QueryInterface(This->device->hwbuf, &IID_IDsDriverNotify, (LPVOID*)&(This->hwnotify)); if (hres != DS_OK) { WARN("IDsCaptureDriverBuffer_QueryInterface failed\n"); + IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify); *ppobj = 0; return hres; } } - IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify); - *ppobj = (LPVOID)This->notify; + *ppobj = This->notify; return DS_OK; } @@ -1112,7 +821,7 @@ IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) { IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -1121,35 +830,38 @@ IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) { IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { TRACE("deleting object\n"); - if (This->dsound->device->state == STATE_CAPTURING) - This->dsound->device->state = STATE_STOPPING; + if (This->device->state == STATE_CAPTURING) + This->device->state = STATE_STOPPING; HeapFree(GetProcessHeap(),0, This->pdscbd); - if (This->dsound->device->hwi) { - waveInReset(This->dsound->device->hwi); - waveInClose(This->dsound->device->hwi); - HeapFree(GetProcessHeap(),0, This->dsound->device->pwave); - This->dsound->device->pwave = 0; - This->dsound->device->hwi = 0; + if (This->device->hwi) { + waveInReset(This->device->hwi); + waveInClose(This->device->hwi); + HeapFree(GetProcessHeap(),0, This->device->pwave); + This->device->pwave = 0; + This->device->hwi = 0; } - if (This->dsound->device->hwbuf) - IDsCaptureDriverBuffer_Release(This->dsound->device->hwbuf); + if (This->device->hwbuf) + IDsCaptureDriverBuffer_Release(This->device->hwbuf); - /* remove from IDirectSoundCaptureImpl */ - if (This->dsound) - This->dsound->device->capture_buffer = NULL; - else - ERR("does not reference dsound\n"); + /* remove from DirectSoundCaptureDevice */ + This->device->capture_buffer = NULL; if (This->notify) IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify); + /* If driver manages its own buffer, IDsCaptureDriverBuffer_Release + should have freed the buffer. Prevent freeing it again in + IDirectSoundCaptureBufferImpl_Create */ + if (!(This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY)) + This->device->buffer = NULL; + HeapFree(GetProcessHeap(), 0, This->notifies); HeapFree( GetProcessHeap(), 0, This ); TRACE("(%p) released\n", This); @@ -1165,24 +877,18 @@ IDirectSoundCaptureBufferImpl_GetCaps( IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; TRACE( "(%p,%p)\n", This, lpDSCBCaps ); - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } - if (lpDSCBCaps == NULL) { WARN("invalid parameter: lpDSCBCaps == NULL\n"); return DSERR_INVALIDPARAM; } if (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) { - WARN("invalid parameter: lpDSCBCaps->dwSize = %ld < %d\n", - lpDSCBCaps->dwSize, sizeof(DSCBCAPS)); + WARN("invalid parameter: lpDSCBCaps->dwSize = %d\n", lpDSCBCaps->dwSize); return DSERR_INVALIDPARAM; } - if (This->dsound == NULL) { - WARN("invalid parameter: This->dsound == NULL\n"); + if (This->device == NULL) { + WARN("invalid parameter: This->device == NULL\n"); return DSERR_INVALIDPARAM; } @@ -1205,51 +911,33 @@ IDirectSoundCaptureBufferImpl_GetCurrentPosition( HRESULT hres = DS_OK; TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition ); - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } - - if (This->dsound == NULL) { - WARN("invalid parameter: This->dsound == NULL\n"); + if (This->device == NULL) { + WARN("invalid parameter: This->device == NULL\n"); return DSERR_INVALIDPARAM; } - if (This->dsound->device->driver) { - hres = IDsCaptureDriverBuffer_GetPosition(This->dsound->device->hwbuf, lpdwCapturePosition, lpdwReadPosition ); + if (This->device->driver) { + hres = IDsCaptureDriverBuffer_GetPosition(This->device->hwbuf, lpdwCapturePosition, lpdwReadPosition ); if (hres != DS_OK) WARN("IDsCaptureDriverBuffer_GetPosition failed\n"); - } else if (This->dsound->device->hwi) { - EnterCriticalSection(&(This->dsound->device->lock)); - TRACE("old This->dsound->device->state=%s\n",captureStateString[This->dsound->device->state]); - if (lpdwCapturePosition) { - MMTIME mtime; - mtime.wType = TIME_BYTES; - waveInGetPosition(This->dsound->device->hwi, &mtime, sizeof(mtime)); - TRACE("mtime.u.cb=%ld,This->dsound->device->buflen=%ld\n", mtime.u.cb, - This->dsound->device->buflen); - mtime.u.cb = mtime.u.cb % This->dsound->device->buflen; - *lpdwCapturePosition = mtime.u.cb; - } + } else if (This->device->hwi) { + DWORD pos; + + EnterCriticalSection(&This->device->lock); + pos = (DWORD_PTR)This->device->pwave[This->device->index].lpData - (DWORD_PTR)This->device->buffer; + if (lpdwCapturePosition) + *lpdwCapturePosition = (This->device->pwave[This->device->index].dwBufferLength + pos) % This->device->buflen; + if (lpdwReadPosition) + *lpdwReadPosition = pos; + LeaveCriticalSection(&This->device->lock); - if (lpdwReadPosition) { - if (This->dsound->device->state == STATE_STARTING) { - if (lpdwCapturePosition) - This->dsound->device->read_position = *lpdwCapturePosition; - This->dsound->device->state = STATE_CAPTURING; - } - *lpdwReadPosition = This->dsound->device->read_position; - } - TRACE("new This->dsound->device->state=%s\n",captureStateString[This->dsound->device->state]); - LeaveCriticalSection(&(This->dsound->device->lock)); - if (lpdwCapturePosition) TRACE("*lpdwCapturePosition=%ld\n",*lpdwCapturePosition); - if (lpdwReadPosition) TRACE("*lpdwReadPosition=%ld\n",*lpdwReadPosition); } else { WARN("no driver\n"); hres = DSERR_NODRIVER; } - TRACE("returning %08lx\n", hres); + TRACE("cappos=%d readpos=%d\n", (lpdwCapturePosition?*lpdwCapturePosition:-1), (lpdwReadPosition?*lpdwReadPosition:-1)); + TRACE("returning %08x\n", hres); return hres; } @@ -1262,36 +950,31 @@ IDirectSoundCaptureBufferImpl_GetFormat( { IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; HRESULT hres = DS_OK; - TRACE( "(%p,%p,0x%08lx,%p)\n", This, lpwfxFormat, dwSizeAllocated, + TRACE( "(%p,%p,0x%08x,%p)\n", This, lpwfxFormat, dwSizeAllocated, lpdwSizeWritten ); - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } - - if (This->dsound == NULL) { - WARN("invalid parameter: This->dsound == NULL\n"); + if (This->device == NULL) { + WARN("invalid parameter: This->device == NULL\n"); return DSERR_INVALIDPARAM; } - if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->dsound->device->pwfx->cbSize)) - dwSizeAllocated = sizeof(WAVEFORMATEX) + This->dsound->device->pwfx->cbSize; + if (dwSizeAllocated > (sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize)) + dwSizeAllocated = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize; if (lpwfxFormat) { /* NULL is valid (just want size) */ - CopyMemory(lpwfxFormat, This->dsound->device->pwfx, dwSizeAllocated); + CopyMemory(lpwfxFormat, This->device->pwfx, dwSizeAllocated); if (lpdwSizeWritten) *lpdwSizeWritten = dwSizeAllocated; } else { if (lpdwSizeWritten) - *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->dsound->device->pwfx->cbSize; + *lpdwSizeWritten = sizeof(WAVEFORMATEX) + This->device->pwfx->cbSize; else { TRACE("invalid parameter: lpdwSizeWritten = NULL\n"); hres = DSERR_INVALIDPARAM; } } - TRACE("returning %08lx\n", hres); + TRACE("returning %08x\n", hres); return hres; } @@ -1301,15 +984,10 @@ IDirectSoundCaptureBufferImpl_GetStatus( LPDWORD lpdwStatus ) { IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; - TRACE( "(%p, %p), thread is %04lx\n", This, lpdwStatus, GetCurrentThreadId() ); - - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } + TRACE( "(%p, %p), thread is %04x\n", This, lpdwStatus, GetCurrentThreadId() ); - if (This->dsound == NULL) { - WARN("invalid parameter: This->dsound == NULL\n"); + if (This->device == NULL) { + WARN("invalid parameter: This->device == NULL\n"); return DSERR_INVALIDPARAM; } @@ -1319,21 +997,21 @@ IDirectSoundCaptureBufferImpl_GetStatus( } *lpdwStatus = 0; - EnterCriticalSection(&(This->dsound->device->lock)); + EnterCriticalSection(&(This->device->lock)); - TRACE("old This->dsound->state=%s, old lpdwStatus=%08lx\n", - captureStateString[This->dsound->device->state],*lpdwStatus); - if ((This->dsound->device->state == STATE_STARTING) || - (This->dsound->device->state == STATE_CAPTURING)) { + TRACE("old This->device->state=%s, old lpdwStatus=%08x\n", + captureStateString[This->device->state],*lpdwStatus); + if ((This->device->state == STATE_STARTING) || + (This->device->state == STATE_CAPTURING)) { *lpdwStatus |= DSCBSTATUS_CAPTURING; if (This->flags & DSCBSTART_LOOPING) *lpdwStatus |= DSCBSTATUS_LOOPING; } - TRACE("new This->dsound->state=%s, new lpdwStatus=%08lx\n", - captureStateString[This->dsound->device->state],*lpdwStatus); - LeaveCriticalSection(&(This->dsound->device->lock)); + TRACE("new This->device->state=%s, new lpdwStatus=%08x\n", + captureStateString[This->device->state],*lpdwStatus); + LeaveCriticalSection(&(This->device->lock)); - TRACE("status=%lx\n", *lpdwStatus); + TRACE("status=%x\n", *lpdwStatus); TRACE("returning DS_OK\n"); return DS_OK; } @@ -1364,17 +1042,12 @@ IDirectSoundCaptureBufferImpl_Lock( { HRESULT hres = DS_OK; IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; - TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx) at %ld\n", This, dwReadCusor, + TRACE( "(%p,%08u,%08u,%p,%p,%p,%p,0x%08x) at %d\n", This, dwReadCusor, dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2, dwFlags, GetTickCount() ); - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } - - if (This->dsound == NULL) { - WARN("invalid parameter: This->dsound == NULL\n"); + if (This->device == NULL) { + WARN("invalid parameter: This->device == NULL\n"); return DSERR_INVALIDPARAM; } @@ -1388,21 +1061,21 @@ IDirectSoundCaptureBufferImpl_Lock( return DSERR_INVALIDPARAM; } - EnterCriticalSection(&(This->dsound->device->lock)); + EnterCriticalSection(&(This->device->lock)); - if (This->dsound->device->driver) { - hres = IDsCaptureDriverBuffer_Lock(This->dsound->device->hwbuf, lplpvAudioPtr1, + if (This->device->driver) { + hres = IDsCaptureDriverBuffer_Lock(This->device->hwbuf, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2, dwReadCusor, dwReadBytes, dwFlags); if (hres != DS_OK) WARN("IDsCaptureDriverBuffer_Lock failed\n"); - } else if (This->dsound->device->hwi) { - *lplpvAudioPtr1 = This->dsound->device->buffer + dwReadCusor; - if ( (dwReadCusor + dwReadBytes) > This->dsound->device->buflen) { - *lpdwAudioBytes1 = This->dsound->device->buflen - dwReadCusor; + } else if (This->device->hwi) { + *lplpvAudioPtr1 = This->device->buffer + dwReadCusor; + if ( (dwReadCusor + dwReadBytes) > This->device->buflen) { + *lpdwAudioBytes1 = This->device->buflen - dwReadCusor; if (lplpvAudioPtr2) - *lplpvAudioPtr2 = This->dsound->device->buffer; + *lplpvAudioPtr2 = This->device->buffer; if (lpdwAudioBytes2) *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1; } else { @@ -1417,9 +1090,9 @@ IDirectSoundCaptureBufferImpl_Lock( hres = DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */ } - LeaveCriticalSection(&(This->dsound->device->lock)); + LeaveCriticalSection(&(This->device->lock)); - TRACE("returning %08lx\n", hres); + TRACE("returning %08x\n", hres); return hres; } @@ -1430,155 +1103,99 @@ IDirectSoundCaptureBufferImpl_Start( { HRESULT hres = DS_OK; IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; - TRACE( "(%p,0x%08lx)\n", This, dwFlags ); - - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } + TRACE( "(%p,0x%08x)\n", This, dwFlags ); - if (This->dsound == NULL) { - WARN("invalid parameter: This->dsound == NULL\n"); + if (This->device == NULL) { + WARN("invalid parameter: This->device == NULL\n"); return DSERR_INVALIDPARAM; } - if ( (This->dsound->device->driver == 0) && (This->dsound->device->hwi == 0) ) { + if ( (This->device->driver == 0) && (This->device->hwi == 0) ) { WARN("no driver\n"); return DSERR_NODRIVER; } - EnterCriticalSection(&(This->dsound->device->lock)); + EnterCriticalSection(&(This->device->lock)); This->flags = dwFlags; - TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->device->state]); - if (This->dsound->device->state == STATE_STOPPED) - This->dsound->device->state = STATE_STARTING; - else if (This->dsound->device->state == STATE_STOPPING) - This->dsound->device->state = STATE_CAPTURING; - TRACE("new This->dsound->device->state=%s\n",captureStateString[This->dsound->device->state]); + TRACE("old This->state=%s\n",captureStateString[This->device->state]); + if (This->device->state == STATE_STOPPED) + This->device->state = STATE_STARTING; + else if (This->device->state == STATE_STOPPING) + This->device->state = STATE_CAPTURING; + TRACE("new This->device->state=%s\n",captureStateString[This->device->state]); - LeaveCriticalSection(&(This->dsound->device->lock)); + LeaveCriticalSection(&(This->device->lock)); - if (This->dsound->device->driver) { - hres = IDsCaptureDriverBuffer_Start(This->dsound->device->hwbuf, dwFlags); + if (This->device->driver) { + hres = IDsCaptureDriverBuffer_Start(This->device->hwbuf, dwFlags); if (hres != DS_OK) WARN("IDsCaptureDriverBuffer_Start failed\n"); - } else if (This->dsound->device->hwi) { - IDirectSoundCaptureImpl* ipDSC = This->dsound; - - if (ipDSC->device->buffer) { - if (This->nrofnotifies) { - int c; - - ipDSC->device->nrofpwaves = This->nrofnotifies; - TRACE("nrofnotifies=%d\n", This->nrofnotifies); - - /* prepare headers */ - if (ipDSC->device->pwave) - ipDSC->device->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->pwave, - ipDSC->device->nrofpwaves*sizeof(WAVEHDR)); - else - ipDSC->device->pwave = HeapAlloc(GetProcessHeap(),0, - ipDSC->device->nrofpwaves*sizeof(WAVEHDR)); - - for (c = 0; c < ipDSC->device->nrofpwaves; c++) { - if (This->notifies[c].dwOffset == DSBPN_OFFSETSTOP) { - TRACE("got DSBPN_OFFSETSTOP\n"); - ipDSC->device->nrofpwaves = c; - break; - } - if (c == 0) { - ipDSC->device->pwave[0].lpData = (LPSTR)ipDSC->device->buffer; - ipDSC->device->pwave[0].dwBufferLength = - This->notifies[0].dwOffset + 1; - } else { - ipDSC->device->pwave[c].lpData = (LPSTR)ipDSC->device->buffer + - This->notifies[c-1].dwOffset + 1; - ipDSC->device->pwave[c].dwBufferLength = - This->notifies[c].dwOffset - - This->notifies[c-1].dwOffset; - } - ipDSC->device->pwave[c].dwBytesRecorded = 0; - ipDSC->device->pwave[c].dwUser = (DWORD)ipDSC; - ipDSC->device->pwave[c].dwFlags = 0; - ipDSC->device->pwave[c].dwLoops = 0; - hres = mmErr(waveInPrepareHeader(ipDSC->device->hwi, - &(ipDSC->device->pwave[c]),sizeof(WAVEHDR))); - if (hres != DS_OK) { - WARN("waveInPrepareHeader failed\n"); - while (c--) - waveInUnprepareHeader(ipDSC->device->hwi, - &(ipDSC->device->pwave[c]),sizeof(WAVEHDR)); - break; - } - - hres = mmErr(waveInAddBuffer(ipDSC->device->hwi, - &(ipDSC->device->pwave[c]), sizeof(WAVEHDR))); - if (hres != DS_OK) { - WARN("waveInAddBuffer failed\n"); - while (c--) - waveInUnprepareHeader(ipDSC->device->hwi, - &(ipDSC->device->pwave[c]),sizeof(WAVEHDR)); - break; - } + } else if (This->device->hwi) { + DirectSoundCaptureDevice *device = This->device; + + if (device->buffer) { + int c; + DWORD blocksize = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign); + device->nrofpwaves = device->buflen / blocksize + !!(device->buflen % blocksize); + TRACE("nrofpwaves=%d\n", device->nrofpwaves); + + /* prepare headers */ + if (device->pwave) + device->pwave = HeapReAlloc(GetProcessHeap(), 0,device->pwave, device->nrofpwaves*sizeof(WAVEHDR)); + else + device->pwave = HeapAlloc(GetProcessHeap(), 0, device->nrofpwaves*sizeof(WAVEHDR)); + + for (c = 0; c < device->nrofpwaves; ++c) { + device->pwave[c].lpData = (char *)device->buffer + c * blocksize; + if (c + 1 == device->nrofpwaves) + device->pwave[c].dwBufferLength = device->buflen - c * blocksize; + else + device->pwave[c].dwBufferLength = blocksize; + device->pwave[c].dwBytesRecorded = 0; + device->pwave[c].dwUser = (DWORD_PTR)device; + device->pwave[c].dwFlags = 0; + device->pwave[c].dwLoops = 0; + hres = mmErr(waveInPrepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR))); + if (hres != DS_OK) { + WARN("waveInPrepareHeader failed\n"); + while (c--) + waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR)); + break; } - FillMemory(ipDSC->device->buffer, ipDSC->device->buflen, - (ipDSC->device->pwfx->wBitsPerSample == 8) ? 128 : 0); - } else { - TRACE("no notifiers specified\n"); - /* no notifiers specified so just create a single default header */ - ipDSC->device->nrofpwaves = 1; - if (ipDSC->device->pwave) - ipDSC->device->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->device->pwave,sizeof(WAVEHDR)); - else - ipDSC->device->pwave = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEHDR)); - - ipDSC->device->pwave[0].lpData = (LPSTR)ipDSC->device->buffer; - ipDSC->device->pwave[0].dwBufferLength = ipDSC->device->buflen; - ipDSC->device->pwave[0].dwBytesRecorded = 0; - ipDSC->device->pwave[0].dwUser = (DWORD)ipDSC; - ipDSC->device->pwave[0].dwFlags = 0; - ipDSC->device->pwave[0].dwLoops = 0; - - hres = mmErr(waveInPrepareHeader(ipDSC->device->hwi, - &(ipDSC->device->pwave[0]),sizeof(WAVEHDR))); + hres = mmErr(waveInAddBuffer(device->hwi, &(device->pwave[c]), sizeof(WAVEHDR))); if (hres != DS_OK) { - WARN("waveInPrepareHeader failed\n"); - waveInUnprepareHeader(ipDSC->device->hwi, - &(ipDSC->device->pwave[0]),sizeof(WAVEHDR)); - } - hres = mmErr(waveInAddBuffer(ipDSC->device->hwi, - &(ipDSC->device->pwave[0]), sizeof(WAVEHDR))); - if (hres != DS_OK) { - WARN("waveInAddBuffer failed\n"); - waveInUnprepareHeader(ipDSC->device->hwi, - &(ipDSC->device->pwave[0]),sizeof(WAVEHDR)); - } - } + WARN("waveInAddBuffer failed\n"); + while (c--) + waveInUnprepareHeader(device->hwi, &(device->pwave[c]),sizeof(WAVEHDR)); + break; + } + } + + FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0); } - ipDSC->device->index = 0; - ipDSC->device->read_position = 0; + device->index = 0; if (hres == DS_OK) { /* start filling the first buffer */ - hres = mmErr(waveInStart(ipDSC->device->hwi)); + hres = mmErr(waveInStart(device->hwi)); if (hres != DS_OK) WARN("waveInStart failed\n"); } if (hres != DS_OK) { WARN("calling waveInClose because of error\n"); - waveInClose(This->dsound->device->hwi); - This->dsound->device->hwi = 0; + waveInClose(device->hwi); + device->hwi = 0; } } else { WARN("no driver\n"); hres = DSERR_NODRIVER; } - TRACE("returning %08lx\n", hres); + TRACE("returning %08x\n", hres); return hres; } @@ -1589,33 +1206,28 @@ IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; TRACE( "(%p)\n", This ); - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } - - if (This->dsound == NULL) { - WARN("invalid parameter: This->dsound == NULL\n"); + if (This->device == NULL) { + WARN("invalid parameter: This->device == NULL\n"); return DSERR_INVALIDPARAM; } - EnterCriticalSection(&(This->dsound->device->lock)); + EnterCriticalSection(&(This->device->lock)); - TRACE("old This->dsound->state=%s\n",captureStateString[This->dsound->device->state]); - if (This->dsound->device->state == STATE_CAPTURING) - This->dsound->device->state = STATE_STOPPING; - else if (This->dsound->device->state == STATE_STARTING) - This->dsound->device->state = STATE_STOPPED; - TRACE("new This->dsound->device->state=%s\n",captureStateString[This->dsound->device->state]); + TRACE("old This->device->state=%s\n",captureStateString[This->device->state]); + if (This->device->state == STATE_CAPTURING) + This->device->state = STATE_STOPPING; + else if (This->device->state == STATE_STARTING) + This->device->state = STATE_STOPPED; + TRACE("new This->device->state=%s\n",captureStateString[This->device->state]); - LeaveCriticalSection(&(This->dsound->device->lock)); + LeaveCriticalSection(&(This->device->lock)); - if (This->dsound->device->driver) { - hres = IDsCaptureDriverBuffer_Stop(This->dsound->device->hwbuf); + if (This->device->driver) { + hres = IDsCaptureDriverBuffer_Stop(This->device->hwbuf); if (hres != DS_OK) WARN("IDsCaptureDriverBuffer_Stop() failed\n"); - } else if (This->dsound->device->hwi) { - hres = mmErr(waveInReset(This->dsound->device->hwi)); + } else if (This->device->hwi) { + hres = mmErr(waveInReset(This->device->hwi)); if (hres != DS_OK) WARN("waveInReset() failed\n"); } else { @@ -1623,7 +1235,7 @@ IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) hres = DSERR_NODRIVER; } - TRACE("returning %08lx\n", hres); + TRACE("returning %08x\n", hres); return hres; } @@ -1637,33 +1249,25 @@ IDirectSoundCaptureBufferImpl_Unlock( { HRESULT hres = DS_OK; IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; - TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This, lpvAudioPtr1, dwAudioBytes1, + TRACE( "(%p,%p,%08u,%p,%08u)\n", This, lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2 ); - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } - if (lpvAudioPtr1 == NULL) { WARN("invalid parameter: lpvAudioPtr1 == NULL\n"); return DSERR_INVALIDPARAM; } - if (This->dsound->device->driver) { - hres = IDsCaptureDriverBuffer_Unlock(This->dsound->device->hwbuf, lpvAudioPtr1, + if (This->device->driver) { + hres = IDsCaptureDriverBuffer_Unlock(This->device->hwbuf, lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2); if (hres != DS_OK) WARN("IDsCaptureDriverBuffer_Unlock failed\n"); - } else if (This->dsound->device->hwi) { - This->dsound->device->read_position = (This->dsound->device->read_position + - (dwAudioBytes1 + dwAudioBytes2)) % This->dsound->device->buflen; - } else { + } else if (!This->device->hwi) { WARN("invalid call\n"); hres = DSERR_INVALIDCALL; } - TRACE("returning %08lx\n", hres); + TRACE("returning %08x\n", hres); return hres; } @@ -1677,7 +1281,7 @@ IDirectSoundCaptureBufferImpl_GetObjectInPath( { IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; - FIXME( "(%p,%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject), + FIXME( "(%p,%s,%u,%s,%p): stub\n", This, debugstr_guid(rguidObject), dwIndex, debugstr_guid(rguidInterface), ppObject ); return DS_OK; @@ -1691,7 +1295,7 @@ IDirectSoundCaptureBufferImpl_GetFXStatus( { IDirectSoundCaptureBufferImpl *This = (IDirectSoundCaptureBufferImpl *)iface; - FIXME( "(%p,%lu,%p): stub\n", This, dwFXCount, pdwFXStatus ); + FIXME( "(%p,%u,%p): stub\n", This, dwFXCount, pdwFXStatus ); return DS_OK; } @@ -1719,79 +1323,336 @@ static const IDirectSoundCaptureBuffer8Vtbl dscbvt = IDirectSoundCaptureBufferImpl_GetFXStatus }; -/******************************************************************************* - * DirectSoundCapture ClassFactory - */ - -static HRESULT WINAPI -DSCCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) +HRESULT IDirectSoundCaptureBufferImpl_Create( + DirectSoundCaptureDevice *device, + IDirectSoundCaptureBufferImpl ** ppobj, + LPCDSCBUFFERDESC lpcDSCBufferDesc) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + LPWAVEFORMATEX wfex; + TRACE( "(%p,%p,%p)\n", device, ppobj, lpcDSCBufferDesc); - FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj); - return E_NOINTERFACE; -} + if (ppobj == NULL) { + WARN("invalid parameter: ppobj == NULL\n"); + return DSERR_INVALIDPARAM; + } -static ULONG WINAPI -DSCCF_AddRef(LPCLASSFACTORY iface) -{ - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); - return ref; -} + if (!device) { + WARN("not initialized\n"); + *ppobj = NULL; + return DSERR_UNINITIALIZED; + } -static ULONG WINAPI -DSCCF_Release(LPCLASSFACTORY iface) -{ - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); - /* static class, won't be freed */ - return ref; + if (lpcDSCBufferDesc == NULL) { + WARN("invalid parameter: lpcDSCBufferDesc == NULL\n"); + *ppobj = NULL; + return DSERR_INVALIDPARAM; + } + + if ( ((lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC)) && + (lpcDSCBufferDesc->dwSize != sizeof(DSCBUFFERDESC1))) || + (lpcDSCBufferDesc->dwBufferBytes == 0) || + (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { + WARN("invalid lpcDSCBufferDesc\n"); + *ppobj = NULL; + return DSERR_INVALIDPARAM; + } + + wfex = lpcDSCBufferDesc->lpwfxFormat; + + if (wfex) { + TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," + "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", + wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, + wfex->nAvgBytesPerSec, wfex->nBlockAlign, + wfex->wBitsPerSample, wfex->cbSize); + + if (wfex->wFormatTag == WAVE_FORMAT_PCM) { + device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)); + *device->pwfx = *wfex; + device->pwfx->cbSize = 0; + } else { + device->pwfx = HeapAlloc(GetProcessHeap(),0,sizeof(WAVEFORMATEX)+wfex->cbSize); + CopyMemory(device->pwfx, wfex, sizeof(WAVEFORMATEX)+wfex->cbSize); + } + } else { + WARN("lpcDSCBufferDesc->lpwfxFormat == 0\n"); + *ppobj = NULL; + return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */ + } + + *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, + sizeof(IDirectSoundCaptureBufferImpl)); + + if ( *ppobj == NULL ) { + WARN("out of memory\n"); + *ppobj = NULL; + return DSERR_OUTOFMEMORY; + } else { + HRESULT err = DS_OK; + LPBYTE newbuf; + DWORD buflen; + IDirectSoundCaptureBufferImpl *This = *ppobj; + + This->ref = 1; + This->device = device; + This->device->capture_buffer = This; + This->notify = NULL; + This->nrofnotifies = 0; + This->hwnotify = NULL; + + This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, + lpcDSCBufferDesc->dwSize); + if (This->pdscbd) + CopyMemory(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize); + else { + WARN("no memory\n"); + This->device->capture_buffer = 0; + HeapFree( GetProcessHeap(), 0, This ); + *ppobj = NULL; + return DSERR_OUTOFMEMORY; + } + + This->lpVtbl = &dscbvt; + + if (device->driver) { + if (This->device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) + FIXME("DSDDESC_DOMMSYSTEMOPEN not supported\n"); + + if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { + /* allocate buffer from system memory */ + buflen = lpcDSCBufferDesc->dwBufferBytes; + TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer); + if (device->buffer) + newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen); + else + newbuf = HeapAlloc(GetProcessHeap(),0,buflen); + + if (newbuf == NULL) { + WARN("failed to allocate capture buffer\n"); + err = DSERR_OUTOFMEMORY; + /* but the old buffer might still exist and must be re-prepared */ + } else { + device->buffer = newbuf; + device->buflen = buflen; + } + } else { + /* let driver allocate memory */ + device->buflen = lpcDSCBufferDesc->dwBufferBytes; + /* FIXME: */ + HeapFree( GetProcessHeap(), 0, device->buffer); + device->buffer = NULL; + } + + err = IDsCaptureDriver_CreateCaptureBuffer(device->driver, + device->pwfx,0,0,&(device->buflen),&(device->buffer),(LPVOID*)&(device->hwbuf)); + if (err != DS_OK) { + WARN("IDsCaptureDriver_CreateCaptureBuffer failed\n"); + This->device->capture_buffer = 0; + HeapFree( GetProcessHeap(), 0, This ); + *ppobj = NULL; + return err; + } + } else { + DWORD flags = CALLBACK_FUNCTION; + err = mmErr(waveInOpen(&(device->hwi), + device->drvdesc.dnDevNode, device->pwfx, + (DWORD_PTR)DSOUND_capture_callback, (DWORD_PTR)device, flags)); + if (err != DS_OK) { + WARN("waveInOpen failed\n"); + This->device->capture_buffer = 0; + HeapFree( GetProcessHeap(), 0, This ); + *ppobj = NULL; + return err; + } + + buflen = lpcDSCBufferDesc->dwBufferBytes; + TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer); + if (device->buffer) + newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen); + else + newbuf = HeapAlloc(GetProcessHeap(),0,buflen); + if (newbuf == NULL) { + WARN("failed to allocate capture buffer\n"); + err = DSERR_OUTOFMEMORY; + /* but the old buffer might still exist and must be re-prepared */ + } else { + device->buffer = newbuf; + device->buflen = buflen; + } + } + } + + TRACE("returning DS_OK\n"); + return DS_OK; } -static HRESULT WINAPI -DSCCF_CreateInstance( - LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj ) +/******************************************************************************* + * DirectSoundCaptureDevice + */ +HRESULT DirectSoundCaptureDevice_Initialize( + DirectSoundCaptureDevice ** ppDevice, + LPCGUID lpcGUID) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); + HRESULT err = DSERR_INVALIDPARAM; + unsigned wid, widn; + BOOLEAN found = FALSE; + GUID devGUID; + DirectSoundCaptureDevice *device = *ppDevice; + TRACE("(%p, %s)\n", ppDevice, debugstr_guid(lpcGUID)); + + /* Default device? */ + if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) ) + lpcGUID = &DSDEVID_DefaultCapture; - if (pOuter) { - WARN("aggregation not supported\n"); - return CLASS_E_NOAGGREGATION; + if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) { + WARN("invalid parameter: lpcGUID\n"); + return DSERR_INVALIDPARAM; } - if (ppobj == NULL) { - WARN("invalid parameter\n"); - return E_INVALIDARG; + widn = waveInGetNumDevs(); + if (!widn) { + WARN("no audio devices found\n"); + return DSERR_NODRIVER; } - *ppobj = NULL; + /* enumerate WINMM audio devices and find the one we want */ + for (wid=0; widguid = devGUID; + + /* Disable the direct sound driver to force emulation if requested. */ + device->driver = NULL; + if (ds_hw_accel != DS_HW_ACCEL_EMULATION) + { + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&device->driver,0)); + if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) { + WARN("waveInMessage failed; err=%x\n",err); + return err; + } + } + err = DS_OK; + + /* Get driver description */ + if (device->driver) { + TRACE("using DirectSound driver\n"); + err = IDsCaptureDriver_GetDriverDesc(device->driver, &(device->drvdesc)); + if (err != DS_OK) { + WARN("IDsCaptureDriver_GetDriverDesc failed\n"); + return err; + } + } else { + TRACE("using WINMM\n"); + /* if no DirectSound interface available, use WINMM API instead */ + device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | + DSDDESC_DOMMSYSTEMSETFORMAT; + } + + device->drvdesc.dnDevNode = wid; + + /* open the DirectSound driver if available */ + if (device->driver && (err == DS_OK)) + err = IDsCaptureDriver_Open(device->driver); + + if (err == DS_OK) { + *ppDevice = device; + + /* the driver is now open, so it's now allowed to call GetCaps */ + if (device->driver) { + device->drvcaps.dwSize = sizeof(device->drvcaps); + err = IDsCaptureDriver_GetCaps(device->driver,&(device->drvcaps)); + if (err != DS_OK) { + WARN("IDsCaptureDriver_GetCaps failed\n"); + return err; + } + } else /*if (device->hwi)*/ { + WAVEINCAPSA wic; + err = mmErr(waveInGetDevCapsA((UINT)device->drvdesc.dnDevNode, &wic, sizeof(wic))); + + if (err == DS_OK) { + device->drvcaps.dwFlags = 0; + lstrcpynA(device->drvdesc.szDrvname, wic.szPname, + sizeof(device->drvdesc.szDrvname)); + + device->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER; + device->drvcaps.dwFormats = wic.dwFormats; + device->drvcaps.dwChannels = wic.wChannels; + } + } + } + + return err; } -static HRESULT WINAPI -DSCCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) +static HRESULT DirectSoundCaptureDevice_Create( + DirectSoundCaptureDevice ** ppDevice) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p)->(%d),stub!\n",This,dolock); - return S_OK; + DirectSoundCaptureDevice * device; + TRACE("(%p)\n", ppDevice); + + /* Allocate memory */ + device = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DirectSoundCaptureDevice)); + + if (device == NULL) { + WARN("out of memory\n"); + return DSERR_OUTOFMEMORY; + } + + device->ref = 1; + device->state = STATE_STOPPED; + + InitializeCriticalSection( &(device->lock) ); + device->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundCaptureDevice.lock"); + + *ppDevice = device; + + return DS_OK; } -static const IClassFactoryVtbl DSCCF_Vtbl = +ULONG DirectSoundCaptureDevice_Release( + DirectSoundCaptureDevice * device) { - DSCCF_QueryInterface, - DSCCF_AddRef, - DSCCF_Release, - DSCCF_CreateInstance, - DSCCF_LockServer -}; + ULONG ref = InterlockedDecrement(&(device->ref)); + TRACE("(%p) ref was %d\n", device, ref + 1); + + if (!ref) { + TRACE("deleting object\n"); + if (device->capture_buffer) + IDirectSoundCaptureBufferImpl_Release( + (LPDIRECTSOUNDCAPTUREBUFFER8) device->capture_buffer); + + if (device->driver) { + IDsCaptureDriver_Close(device->driver); + IDsCaptureDriver_Release(device->driver); + } -IClassFactoryImpl DSOUND_CAPTURE_CF = { &DSCCF_Vtbl, 1 }; + HeapFree(GetProcessHeap(), 0, device->pwfx); + device->lock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection( &(device->lock) ); + DSOUND_capture[device->drvdesc.dnDevNode] = NULL; + HeapFree(GetProcessHeap(), 0, device); + TRACE("(%p) released\n", device); + } + return ref; +} diff --git a/reactos/dll/directx/dsound/dsound.c b/reactos/dll/directx/dsound/dsound.c index 08f6e48d4a1..1f60f37be6f 100644 --- a/reactos/dll/directx/dsound/dsound.c +++ b/reactos/dll/directx/dsound/dsound.c @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -27,10 +27,14 @@ #define NONAMELESSUNION #include "windef.h" #include "winbase.h" -#include "winreg.h" +#include "winuser.h" #include "mmsystem.h" #include "winternl.h" #include "mmddk.h" +#include "wingdi.h" +#include "mmreg.h" +#include "ks.h" +#include "ksmedia.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" @@ -38,16 +42,76 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); -static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface); -static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface); +/***************************************************************************** + * IDirectSound COM components + */ +struct IDirectSound_IUnknown { + const IUnknownVtbl *lpVtbl; + LONG ref; + LPDIRECTSOUND8 pds; +}; + +static HRESULT IDirectSound_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk); + +struct IDirectSound_IDirectSound { + const IDirectSoundVtbl *lpVtbl; + LONG ref; + LPDIRECTSOUND8 pds; +}; + +static HRESULT IDirectSound_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds); + +/***************************************************************************** + * IDirectSound8 COM components + */ +struct IDirectSound8_IUnknown { + const IUnknownVtbl *lpVtbl; + LONG ref; + LPDIRECTSOUND8 pds; +}; + +static HRESULT IDirectSound8_IUnknown_Create(LPDIRECTSOUND8 pds, LPUNKNOWN * ppunk); static ULONG WINAPI IDirectSound8_IUnknown_AddRef(LPUNKNOWN iface); + +struct IDirectSound8_IDirectSound { + const IDirectSoundVtbl *lpVtbl; + LONG ref; + LPDIRECTSOUND8 pds; +}; + +static HRESULT IDirectSound8_IDirectSound_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND * ppds); static ULONG WINAPI IDirectSound8_IDirectSound_AddRef(LPDIRECTSOUND iface); + +struct IDirectSound8_IDirectSound8 { + const IDirectSound8Vtbl *lpVtbl; + LONG ref; + LPDIRECTSOUND8 pds; +}; + +static HRESULT IDirectSound8_IDirectSound8_Create(LPDIRECTSOUND8 pds, LPDIRECTSOUND8 * ppds); static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef(LPDIRECTSOUND8 iface); -static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice); -static ULONG DirectSoundDevice_Release(DirectSoundDevice * device); +/***************************************************************************** + * IDirectSound implementation structure + */ +struct IDirectSoundImpl +{ + LONG ref; + + DirectSoundDevice *device; + LPUNKNOWN pUnknown; + LPDIRECTSOUND pDS; + LPDIRECTSOUND8 pDS8; +}; + +static HRESULT IDirectSoundImpl_Create(LPDIRECTSOUND8 * ppds); + +static ULONG WINAPI IDirectSound_IUnknown_AddRef(LPUNKNOWN iface); +static ULONG WINAPI IDirectSound_IDirectSound_AddRef(LPDIRECTSOUND iface); -static const char * dumpCooperativeLevel(DWORD level) +static HRESULT DirectSoundDevice_VerifyCertification(DirectSoundDevice * device, LPDWORD pdwCertified); + +const char * dumpCooperativeLevel(DWORD level) { static char unknown[32]; #define LE(x) case x: return #x @@ -58,7 +122,7 @@ static const char * dumpCooperativeLevel(DWORD level) LE(DSSCL_WRITEPRIMARY); } #undef LE - sprintf(unknown, "Unknown(%08lx)", level); + sprintf(unknown, "Unknown(%08x)", (UINT)level); return unknown; } @@ -85,7 +149,7 @@ static void _dump_DSCAPS(DWORD xmask) { for (i=0;iref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } -static ULONG WINAPI IDirectSoundImpl_Release( +static ULONG IDirectSoundImpl_Release( LPDIRECTSOUND8 iface) { IDirectSoundImpl *This = (IDirectSoundImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { if (This->device) DirectSoundDevice_Release(This->device); - HeapFree(GetProcessHeap(),0,This); TRACE("(%p) released\n", This); } return ref; } -static HRESULT WINAPI IDirectSoundImpl_CreateSoundBuffer( - LPDIRECTSOUND8 iface, - LPCDSBUFFERDESC dsbd, - LPLPDIRECTSOUNDBUFFER ppdsb, - LPUNKNOWN lpunk) +static HRESULT IDirectSoundImpl_Create( + LPDIRECTSOUND8 * ppDS) { - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); - FIXME("shouldn't be called directly\n"); - return DSERR_GENERIC; + IDirectSoundImpl* pDS; + TRACE("(%p)\n",ppDS); + + /* Allocate memory */ + pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl)); + if (pDS == NULL) { + WARN("out of memory\n"); + *ppDS = NULL; + return DSERR_OUTOFMEMORY; + } + + pDS->ref = 0; + pDS->device = NULL; + + *ppDS = (LPDIRECTSOUND8)pDS; + + return DS_OK; } -static HRESULT WINAPI DSOUND_CreateSoundBuffer( - LPDIRECTSOUND8 iface, - LPCDSBUFFERDESC dsbd, - LPLPDIRECTSOUNDBUFFER ppdsb, - LPUNKNOWN lpunk, - BOOL from8) +/******************************************************************************* + * IDirectSound_IUnknown + */ +static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface( + LPUNKNOWN iface, + REFIID riid, + LPVOID * ppobj) { - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - HRESULT hres = DS_OK; - TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); + IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + return DSOUND_QueryInterface(This->pds, riid, ppobj); +} - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } +static ULONG WINAPI IDirectSound_IUnknown_AddRef( + LPUNKNOWN iface) +{ + IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; +} - if (This->device == NULL) { - WARN("not initialized\n"); - return DSERR_UNINITIALIZED; +static ULONG WINAPI IDirectSound_IUnknown_Release( + LPUNKNOWN iface) +{ + IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref + 1); + if (!ref) { + ((IDirectSoundImpl*)This->pds)->pUnknown = NULL; + IDirectSoundImpl_Release(This->pds); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } + return ref; +} - if (dsbd == NULL) { - WARN("invalid parameter: dsbd == NULL\n"); - return DSERR_INVALIDPARAM; - } +static const IUnknownVtbl DirectSound_Unknown_Vtbl = +{ + IDirectSound_IUnknown_QueryInterface, + IDirectSound_IUnknown_AddRef, + IDirectSound_IUnknown_Release +}; - if (dsbd->dwSize != sizeof(DSBUFFERDESC) && - dsbd->dwSize != sizeof(DSBUFFERDESC1)) { - WARN("invalid parameter: dsbd\n"); +static HRESULT IDirectSound_IUnknown_Create( + LPDIRECTSOUND8 pds, + LPUNKNOWN * ppunk) +{ + IDirectSound_IUnknown * pdsunk; + TRACE("(%p,%p)\n",pds,ppunk); + + if (ppunk == NULL) { + ERR("invalid parameter: ppunk == NULL\n"); return DSERR_INVALIDPARAM; } - if (ppdsb == NULL) { - WARN("invalid parameter: ppdsb == NULL\n"); + if (pds == NULL) { + ERR("invalid parameter: pds == NULL\n"); + *ppunk = NULL; return DSERR_INVALIDPARAM; } - if (TRACE_ON(dsound)) { - TRACE("(structsize=%ld)\n",dsbd->dwSize); - TRACE("(flags=0x%08lx:\n",dsbd->dwFlags); - _dump_DSBCAPS(dsbd->dwFlags); - DPRINTF(")\n"); - TRACE("(bufferbytes=%ld)\n",dsbd->dwBufferBytes); - TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat); + pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk)); + if (pdsunk == NULL) { + WARN("out of memory\n"); + *ppunk = NULL; + return DSERR_OUTOFMEMORY; } - if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) { - if (dsbd->lpwfxFormat != NULL) { - WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for " - "primary buffer\n"); - return DSERR_INVALIDPARAM; - } + pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl; + pdsunk->ref = 0; + pdsunk->pds = pds; - if (This->device->primary) { - WARN("Primary Buffer already created\n"); - IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary)); - *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary); - } else { - This->device->dsbd = *dsbd; - hres = PrimaryBufferImpl_Create(This, (PrimaryBufferImpl**)&(This->device->primary), &(This->device->dsbd)); - if (This->device->primary) { - IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(This->device->primary)); - *ppdsb = (LPDIRECTSOUNDBUFFER)(This->device->primary); - } else - WARN("PrimaryBufferImpl_Create failed\n"); - } - } else { - IDirectSoundBufferImpl * dsb; + IDirectSoundImpl_AddRef(pds); + *ppunk = (LPUNKNOWN)pdsunk; - if (dsbd->lpwfxFormat == NULL) { - WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for " - "secondary buffer\n"); - return DSERR_INVALIDPARAM; - } + return DS_OK; +} - TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld," - "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", - dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels, - dsbd->lpwfxFormat->nSamplesPerSec, - dsbd->lpwfxFormat->nAvgBytesPerSec, - dsbd->lpwfxFormat->nBlockAlign, - dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize); +/******************************************************************************* + * IDirectSound_IDirectSound + */ +static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface( + LPDIRECTSOUND iface, + REFIID riid, + LPVOID * ppobj) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + return DSOUND_QueryInterface(This->pds, riid, ppobj); +} - if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) { - WARN("invalid parameter: 3D buffer format must be mono\n"); - return DSERR_INVALIDPARAM; - } +static ULONG WINAPI IDirectSound_IDirectSound_AddRef( + LPDIRECTSOUND iface) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; +} - hres = IDirectSoundBufferImpl_Create(This, (IDirectSoundBufferImpl**)&dsb, dsbd); - if (dsb) { - hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb); - if (*ppdsb) { - dsb->dsb = (SecondaryBufferImpl*)*ppdsb; - IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppdsb); - } else - WARN("SecondaryBufferImpl_Create failed\n"); - } else - WARN("IDirectSoundBufferImpl_Create failed\n"); - } +static ULONG WINAPI IDirectSound_IDirectSound_Release( + LPDIRECTSOUND iface) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref + 1); + if (!ref) { + ((IDirectSoundImpl*)This->pds)->pDS = NULL; + IDirectSoundImpl_Release(This->pds); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; +} - return hres; +static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer( + LPDIRECTSOUND iface, + LPCDSBUFFERDESC dsbd, + LPLPDIRECTSOUNDBUFFER ppdsb, + LPUNKNOWN lpunk) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); + return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,FALSE); } -static HRESULT WINAPI IDirectSoundImpl_GetCaps( - LPDIRECTSOUND8 iface, +static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps( + LPDIRECTSOUND iface, LPDSCAPS lpDSCaps) { - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - DirectSoundDevice *device; + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; TRACE("(%p,%p)\n",This,lpDSCaps); + return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps); +} - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } - - device = This->device; +static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer( + LPDIRECTSOUND iface, + LPDIRECTSOUNDBUFFER psb, + LPLPDIRECTSOUNDBUFFER ppdsb) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + TRACE("(%p,%p,%p)\n",This,psb,ppdsb); + return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb); +} - if (device == NULL) { - WARN("not initialized\n"); - return DSERR_UNINITIALIZED; - } +static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel( + LPDIRECTSOUND iface, + HWND hwnd, + DWORD level) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); + return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level); +} - if (lpDSCaps == NULL) { - WARN("invalid parameter: lpDSCaps = NULL\n"); - return DSERR_INVALIDPARAM; - } +static HRESULT WINAPI IDirectSound_IDirectSound_Compact( + LPDIRECTSOUND iface) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + TRACE("(%p)\n", This); + return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device); +} - /* check if there is enough room */ - if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) { - WARN("invalid parameter: lpDSCaps->dwSize = %ld < %d\n", - lpDSCaps->dwSize, sizeof(*lpDSCaps)); - return DSERR_INVALIDPARAM; - } - - lpDSCaps->dwFlags = device->drvcaps.dwFlags; - if (TRACE_ON(dsound)) { - TRACE("(flags=0x%08lx:\n",lpDSCaps->dwFlags); - _dump_DSCAPS(lpDSCaps->dwFlags); - DPRINTF(")\n"); - } - lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate; - lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate; - lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers; - lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers; - lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers; - lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers; - lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers; - lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers; - lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers; - lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers; - lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers; - lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers; - lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers; - lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers; - lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers; - lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes; - lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes; - lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes; - - /* driver doesn't have these */ - lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */ - lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */ - - return DS_OK; +static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig( + LPDIRECTSOUND iface, + LPDWORD lpdwSpeakerConfig) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); + return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig); } -static HRESULT WINAPI IDirectSoundImpl_DuplicateSoundBuffer( - LPDIRECTSOUND8 iface, - LPDIRECTSOUNDBUFFER psb, - LPLPDIRECTSOUNDBUFFER ppdsb) +static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig( + LPDIRECTSOUND iface, + DWORD config) { - IDirectSoundBufferImpl* pdsb; - IDirectSoundBufferImpl* dsb; - HRESULT hres = DS_OK; - int size; - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + TRACE("(%p,0x%08x)\n",This,config); + return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config); +} - TRACE("(%p,%p,%p)\n",This,psb,ppdsb); +static HRESULT WINAPI IDirectSound_IDirectSound_Initialize( + LPDIRECTSOUND iface, + LPCGUID lpcGuid) +{ + IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; + TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); + return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid); +} - if (This == NULL) { - WARN("invalid parameter: This == NULL\n"); - return DSERR_INVALIDPARAM; - } +static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl = +{ + IDirectSound_IDirectSound_QueryInterface, + IDirectSound_IDirectSound_AddRef, + IDirectSound_IDirectSound_Release, + IDirectSound_IDirectSound_CreateSoundBuffer, + IDirectSound_IDirectSound_GetCaps, + IDirectSound_IDirectSound_DuplicateSoundBuffer, + IDirectSound_IDirectSound_SetCooperativeLevel, + IDirectSound_IDirectSound_Compact, + IDirectSound_IDirectSound_GetSpeakerConfig, + IDirectSound_IDirectSound_SetSpeakerConfig, + IDirectSound_IDirectSound_Initialize +}; - if (This->device == NULL) { - WARN("not initialized\n"); - return DSERR_UNINITIALIZED; - } +static HRESULT IDirectSound_IDirectSound_Create( + LPDIRECTSOUND8 pds, + LPDIRECTSOUND * ppds) +{ + IDirectSound_IDirectSound * pdsds; + TRACE("(%p,%p)\n",pds,ppds); - if (psb == NULL) { - WARN("invalid parameter: psb == NULL\n"); + if (ppds == NULL) { + ERR("invalid parameter: ppds == NULL\n"); return DSERR_INVALIDPARAM; } - if (ppdsb == NULL) { - WARN("invalid parameter: ppdsb == NULL\n"); + if (pds == NULL) { + ERR("invalid parameter: pds == NULL\n"); + *ppds = NULL; return DSERR_INVALIDPARAM; } - /* FIXME: hack to make sure we have a secondary buffer */ - if ((IDirectSoundImpl *)((SecondaryBufferImpl *)psb)->dsb == This) { - WARN("trying to duplicate primary buffer\n"); - *ppdsb = NULL; - return DSERR_INVALIDCALL; - } - - pdsb = ((SecondaryBufferImpl *)psb)->dsb; - - dsb = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsb)); - - if (dsb == NULL) { + pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); + if (pdsds == NULL) { WARN("out of memory\n"); - *ppdsb = NULL; + *ppds = NULL; return DSERR_OUTOFMEMORY; } - CopyMemory(dsb, pdsb, sizeof(IDirectSoundBufferImpl)); - - if (pdsb->hwbuf) { - TRACE("duplicating hardware buffer\n"); - - hres = IDsDriver_DuplicateSoundBuffer(This->device->driver, pdsb->hwbuf, (LPVOID *)&dsb->hwbuf); - if (hres != DS_OK) { - TRACE("IDsDriver_DuplicateSoundBuffer failed, falling back to software buffer\n"); - dsb->hwbuf = NULL; - /* allocate buffer */ - if (This->device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) { - dsb->buffer = HeapAlloc(GetProcessHeap(),0,sizeof(*(dsb->buffer))); - if (dsb->buffer == NULL) { - WARN("out of memory\n"); - HeapFree(GetProcessHeap(),0,dsb); - *ppdsb = NULL; - return DSERR_OUTOFMEMORY; - } - - dsb->buffer->memory = HeapAlloc(GetProcessHeap(),0,dsb->buflen); - if (dsb->buffer->memory == NULL) { - WARN("out of memory\n"); - HeapFree(GetProcessHeap(),0,dsb->buffer); - HeapFree(GetProcessHeap(),0,dsb); - *ppdsb = NULL; - return DSERR_OUTOFMEMORY; - } - dsb->buffer->ref = 1; - - /* FIXME: copy buffer ? */ - } - } - } else { - dsb->hwbuf = NULL; - dsb->buffer->ref++; - } - - dsb->ref = 0; - dsb->state = STATE_STOPPED; - dsb->playpos = 0; - dsb->buf_mixpos = 0; - dsb->dsound = This; - dsb->ds3db = NULL; - dsb->iks = NULL; /* FIXME? */ - dsb->dsb = NULL; - - /* variable sized struct so calculate size based on format */ - size = sizeof(WAVEFORMATEX) + pdsb->pwfx->cbSize; - - dsb->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size); - if (dsb->pwfx == NULL) { - WARN("out of memory\n"); - HeapFree(GetProcessHeap(),0,dsb->buffer); - HeapFree(GetProcessHeap(),0,dsb); - *ppdsb = NULL; - return DSERR_OUTOFMEMORY; - } - - CopyMemory(dsb->pwfx, pdsb->pwfx, size); - - InitializeCriticalSection(&(dsb->lock)); - dsb->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUNDBUFFER_lock"; - - /* register buffer */ - hres = DSOUND_AddBuffer(This, dsb); - if (hres != DS_OK) { - IDirectSoundBuffer8_Release(psb); - dsb->lock.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&(dsb->lock)); - HeapFree(GetProcessHeap(),0,dsb->buffer); - HeapFree(GetProcessHeap(),0,dsb->pwfx); - HeapFree(GetProcessHeap(),0,dsb); - *ppdsb = 0; - } else { - hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb); - if (*ppdsb) { - dsb->dsb = (SecondaryBufferImpl*)*ppdsb; - IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb); - } else - WARN("SecondaryBufferImpl_Create failed\n"); - } - - return hres; -} - -static HRESULT WINAPI IDirectSoundImpl_SetCooperativeLevel( - LPDIRECTSOUND8 iface, - HWND hwnd, - DWORD level) -{ - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); + pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl; + pdsds->ref = 0; + pdsds->pds = pds; - if (This->device == NULL) { - WARN("not initialized\n"); - return DSERR_UNINITIALIZED; - } + IDirectSoundImpl_AddRef(pds); + *ppds = (LPDIRECTSOUND)pdsds; - if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) { - WARN("level=%s not fully supported\n", - level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE"); - } - This->device->priolevel = level; return DS_OK; } -static HRESULT WINAPI IDirectSoundImpl_Compact( - LPDIRECTSOUND8 iface) +/******************************************************************************* + * IDirectSound8_IUnknown + */ +static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface( + LPUNKNOWN iface, + REFIID riid, + LPVOID * ppobj) { - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - TRACE("(%p)\n",This); + IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + return DSOUND_QueryInterface8(This->pds, riid, ppobj); +} - if (This->device == NULL) { - WARN("not initialized\n"); - return DSERR_UNINITIALIZED; - } +static ULONG WINAPI IDirectSound8_IUnknown_AddRef( + LPUNKNOWN iface) +{ + IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; +} - if (This->device->priolevel != DSSCL_PRIORITY) { - WARN("incorrect priority level\n"); - return DSERR_PRIOLEVELNEEDED; +static ULONG WINAPI IDirectSound8_IUnknown_Release( + LPUNKNOWN iface) +{ + IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref + 1); + if (!ref) { + ((IDirectSoundImpl*)This->pds)->pUnknown = NULL; + IDirectSoundImpl_Release(This->pds); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } - - return DS_OK; + return ref; } -static HRESULT WINAPI IDirectSoundImpl_GetSpeakerConfig( - LPDIRECTSOUND8 iface, - LPDWORD lpdwSpeakerConfig) +static const IUnknownVtbl DirectSound8_Unknown_Vtbl = { - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - TRACE("(%p, %p)\n",This,lpdwSpeakerConfig); + IDirectSound8_IUnknown_QueryInterface, + IDirectSound8_IUnknown_AddRef, + IDirectSound8_IUnknown_Release +}; - if (This->device == NULL) { - WARN("not initialized\n"); - return DSERR_UNINITIALIZED; +static HRESULT IDirectSound8_IUnknown_Create( + LPDIRECTSOUND8 pds, + LPUNKNOWN * ppunk) +{ + IDirectSound8_IUnknown * pdsunk; + TRACE("(%p,%p)\n",pds,ppunk); + + if (ppunk == NULL) { + ERR("invalid parameter: ppunk == NULL\n"); + return DSERR_INVALIDPARAM; } - if (lpdwSpeakerConfig == NULL) { - WARN("invalid parameter: lpdwSpeakerConfig == NULL\n"); + if (pds == NULL) { + ERR("invalid parameter: pds == NULL\n"); + *ppunk = NULL; return DSERR_INVALIDPARAM; } - WARN("not fully functional\n"); - *lpdwSpeakerConfig = This->device->speaker_config; - return DS_OK; -} + pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk)); + if (pdsunk == NULL) { + WARN("out of memory\n"); + *ppunk = NULL; + return DSERR_OUTOFMEMORY; + } -static HRESULT WINAPI IDirectSoundImpl_SetSpeakerConfig( - LPDIRECTSOUND8 iface, - DWORD config) -{ - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - TRACE("(%p,0x%08lx)\n",This,config); + pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl; + pdsunk->ref = 0; + pdsunk->pds = pds; - if (This->device == NULL) { - WARN("not initialized\n"); - return DSERR_UNINITIALIZED; - } + IDirectSoundImpl_AddRef(pds); + *ppunk = (LPUNKNOWN)pdsunk; - This->device->speaker_config = config; - WARN("not fully functional\n"); return DS_OK; } -static HRESULT WINAPI IDirectSoundImpl_Initialize( - LPDIRECTSOUND8 iface, - LPCGUID lpcGUID) +/******************************************************************************* + * IDirectSound8_IDirectSound + */ +static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface( + LPDIRECTSOUND iface, + REFIID riid, + LPVOID * ppobj) { - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - DirectSoundDevice *device = This->device; - HRESULT hr = DS_OK; - unsigned wod, wodn; - BOOLEAN found = FALSE; - GUID devGUID; - TRACE("(%p,%s)\n",This,debugstr_guid(lpcGUID)); + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + return DSOUND_QueryInterface8(This->pds, riid, ppobj); +} - if (device != NULL) { - WARN("already initialized\n"); - return DSERR_ALREADYINITIALIZED; +static ULONG WINAPI IDirectSound8_IDirectSound_AddRef( + LPDIRECTSOUND iface) +{ + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; +} + +static ULONG WINAPI IDirectSound8_IDirectSound_Release( + LPDIRECTSOUND iface) +{ + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref + 1); + if (!ref) { + ((IDirectSoundImpl*)This->pds)->pDS = NULL; + IDirectSoundImpl_Release(This->pds); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); } + return ref; +} - /* Default device? */ - if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL)) - lpcGUID = &DSDEVID_DefaultPlayback; - - if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) { - WARN("invalid parameter: lpcGUID\n"); - return DSERR_INVALIDPARAM; - } - - /* Enumerate WINMM audio devices and find the one we want */ - wodn = waveOutGetNumDevs(); - if (!wodn) { - WARN("no driver\n"); - return DSERR_NODRIVER; - } - - for (wod=0; wodguid)) { - device = DSOUND_renderer[wod]; - device->ref++; - This->device = device; - return DS_OK; - } else { - ERR("device GUID doesn't match\n"); - hr = DSERR_GENERIC; - return hr; - } - } else { - hr = DirectSoundDevice_Create(&(device)); - if (hr != DS_OK) { - WARN("DirectSoundDevice_Create failed\n"); - return hr; - } - } - - This->device = device; - device->guid = devGUID; - - /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */ - WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0); - - /* Disable the direct sound driver to force emulation if requested. */ - if (ds_hw_accel == DS_HW_ACCEL_EMULATION) - device->driver = NULL; - - /* Get driver description */ - if (device->driver) { - hr = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc)); - if (hr != DS_OK) { - WARN("IDsDriver_GetDriverDesc failed\n"); - return hr; - } - } else { - /* if no DirectSound interface available, use WINMM API instead */ - device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT; - } - - device->drvdesc.dnDevNode = wod; - - /* If the driver requests being opened through MMSYSTEM - * (which is recommended by the DDK), it is supposed to happen - * before the DirectSound interface is opened */ - if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) - { - DWORD flags = CALLBACK_FUNCTION; - - /* disable direct sound if requested */ - if (ds_hw_accel != DS_HW_ACCEL_EMULATION) - flags |= WAVE_DIRECTSOUND; - - hr = mmErr(waveOutOpen(&(device->hwo), - device->drvdesc.dnDevNode, device->pwfx, - (DWORD_PTR)DSOUND_callback, (DWORD)device, - flags)); - if (hr != DS_OK) { - WARN("waveOutOpen failed\n"); - return hr; - } - } - - if (device->driver) { - hr = IDsDriver_Open(device->driver); - if (hr != DS_OK) { - WARN("IDsDriver_Open failed\n"); - return hr; - } - - /* the driver is now open, so it's now allowed to call GetCaps */ - hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps)); - if (hr != DS_OK) { - WARN("IDsDriver_GetCaps failed\n"); - return hr; - } - } else { - WAVEOUTCAPSA woc; - hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc))); - if (hr != DS_OK) { - WARN("waveOutGetDevCaps failed\n"); - return hr; - } - ZeroMemory(&device->drvcaps, sizeof(device->drvcaps)); - if ((woc.dwFormats & WAVE_FORMAT_1M08) || - (woc.dwFormats & WAVE_FORMAT_2M08) || - (woc.dwFormats & WAVE_FORMAT_4M08) || - (woc.dwFormats & WAVE_FORMAT_48M08) || - (woc.dwFormats & WAVE_FORMAT_96M08)) { - device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; - device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; - } - if ((woc.dwFormats & WAVE_FORMAT_1M16) || - (woc.dwFormats & WAVE_FORMAT_2M16) || - (woc.dwFormats & WAVE_FORMAT_4M16) || - (woc.dwFormats & WAVE_FORMAT_48M16) || - (woc.dwFormats & WAVE_FORMAT_96M16)) { - device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; - device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; - } - if ((woc.dwFormats & WAVE_FORMAT_1S08) || - (woc.dwFormats & WAVE_FORMAT_2S08) || - (woc.dwFormats & WAVE_FORMAT_4S08) || - (woc.dwFormats & WAVE_FORMAT_48S08) || - (woc.dwFormats & WAVE_FORMAT_96S08)) { - device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; - device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; - } - if ((woc.dwFormats & WAVE_FORMAT_1S16) || - (woc.dwFormats & WAVE_FORMAT_2S16) || - (woc.dwFormats & WAVE_FORMAT_4S16) || - (woc.dwFormats & WAVE_FORMAT_48S16) || - (woc.dwFormats & WAVE_FORMAT_96S16)) { - device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; - device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; - } - if (ds_emuldriver) - device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER; - device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN; - device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX; - device->drvcaps.dwPrimaryBuffers = 1; - } - - hr = DSOUND_PrimaryCreate(device); - if (hr == DS_OK) { - DSOUND_renderer[device->drvdesc.dnDevNode] = device; - timeBeginPeriod(DS_TIME_RES); - DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = timeSetEvent(DS_TIME_DEL, DS_TIME_RES, DSOUND_timer, - (DWORD_PTR)DSOUND_renderer[device->drvdesc.dnDevNode], TIME_PERIODIC | TIME_CALLBACK_FUNCTION); - } else { - WARN("DSOUND_PrimaryCreate failed\n"); - } - - return hr; +static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer( + LPDIRECTSOUND iface, + LPCDSBUFFERDESC dsbd, + LPLPDIRECTSOUNDBUFFER ppdsb, + LPUNKNOWN lpunk) +{ + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); + return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE); } -static HRESULT WINAPI IDirectSoundImpl_VerifyCertification( - LPDIRECTSOUND8 iface, - LPDWORD pdwCertified) +static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps( + LPDIRECTSOUND iface, + LPDSCAPS lpDSCaps) { - IDirectSoundImpl *This = (IDirectSoundImpl *)iface; - TRACE("(%p, %p)\n",This,pdwCertified); - - if (This->device == NULL) { - WARN("not initialized\n"); - return DSERR_UNINITIALIZED; - } - - if (This->device->drvcaps.dwFlags & DSCAPS_CERTIFIED) - *pdwCertified = DS_CERTIFIED; - else - *pdwCertified = DS_UNCERTIFIED; - return DS_OK; + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p,%p)\n",This,lpDSCaps); + return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps); } -static const IDirectSound8Vtbl IDirectSoundImpl_Vtbl = -{ - IDirectSoundImpl_QueryInterface, - IDirectSoundImpl_AddRef, - IDirectSoundImpl_Release, - IDirectSoundImpl_CreateSoundBuffer, - IDirectSoundImpl_GetCaps, - IDirectSoundImpl_DuplicateSoundBuffer, - IDirectSoundImpl_SetCooperativeLevel, - IDirectSoundImpl_Compact, - IDirectSoundImpl_GetSpeakerConfig, - IDirectSoundImpl_SetSpeakerConfig, - IDirectSoundImpl_Initialize, - IDirectSoundImpl_VerifyCertification -}; - -static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice) +static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer( + LPDIRECTSOUND iface, + LPDIRECTSOUNDBUFFER psb, + LPLPDIRECTSOUNDBUFFER ppdsb) { - DirectSoundDevice * device; - TRACE("(%p)\n", ppDevice); - - /* Allocate memory */ - device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice)); - if (device == NULL) { - WARN("out of memory\n"); - return DSERR_OUTOFMEMORY; - } - - device->ref = 1; - device->driver = NULL; - device->priolevel = DSSCL_NORMAL; - device->fraglen = 0; - device->hwbuf = NULL; - device->buffer = NULL; - device->buflen = 0; - device->writelead = 0; - device->state = STATE_STOPPED; - device->nrofbuffers = 0; - device->buffers = NULL; - device->primary = NULL; - device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16); - device->tmp_buffer = NULL; - device->tmp_buffer_len = 0; - - /* 3D listener initial parameters */ - device->listener = NULL; - device->ds3dl.dwSize = sizeof(DS3DLISTENER); - device->ds3dl.vPosition.x = 0.0; - device->ds3dl.vPosition.y = 0.0; - device->ds3dl.vPosition.z = 0.0; - device->ds3dl.vVelocity.x = 0.0; - device->ds3dl.vVelocity.y = 0.0; - device->ds3dl.vVelocity.z = 0.0; - device->ds3dl.vOrientFront.x = 0.0; - device->ds3dl.vOrientFront.y = 0.0; - device->ds3dl.vOrientFront.z = 1.0; - device->ds3dl.vOrientTop.x = 0.0; - device->ds3dl.vOrientTop.y = 1.0; - device->ds3dl.vOrientTop.z = 0.0; - device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; - device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; - device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR; - - device->prebuf = ds_snd_queue_max; - device->guid = GUID_NULL; - - /* Set default wave format (may need it for waveOutOpen) */ - device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX)); - if (device->pwfx == NULL) { - WARN("out of memory\n"); - HeapFree(GetProcessHeap(),0,device); - return DSERR_OUTOFMEMORY; - } - - /* We rely on the sound driver to return the actual sound format of - * the device if it does not support 22050x8x2 and is given the - * WAVE_DIRECTSOUND flag. - */ - device->pwfx->wFormatTag = WAVE_FORMAT_PCM; - device->pwfx->nSamplesPerSec = 22050; - device->pwfx->wBitsPerSample = 8; - device->pwfx->nChannels = 2; - device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8; - device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign; - device->pwfx->cbSize = 0; - - InitializeCriticalSection(&(device->mixlock)); - device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)"DSOUND_mixlock"; - - RtlInitializeResource(&(device->buffer_list_lock)); - - *ppDevice = device; - - return DS_OK; + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p,%p,%p)\n",This,psb,ppdsb); + return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb); } -static ULONG DirectSoundDevice_Release(DirectSoundDevice * device) +static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel( + LPDIRECTSOUND iface, + HWND hwnd, + DWORD level) { - int i; - HRESULT hr; - TRACE("(%p) ref was %lu\n", device, device->ref); - - device->ref--; - if (device->ref == 0) { - timeKillEvent(device->timerID); - timeEndPeriod(DS_TIME_RES); - /* wait for timer to expire */ - Sleep(DS_TIME_RES+1); - - /* The sleep above should have allowed the timer process to expire - * but try to grab the lock just in case. Can't hold lock because - * IDirectSoundBufferImpl_Destroy also grabs the lock */ - RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE); - RtlReleaseResource(&(device->buffer_list_lock)); - - /* It is allowed to release this object even when buffers are playing */ - if (device->buffers) { - WARN("%d secondary buffers not released\n", device->nrofbuffers); - for( i=0;inrofbuffers;i++) - IDirectSoundBufferImpl_Destroy(device->buffers[i]); - } + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); + return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level); +} - if (device->primary) { - WARN("primary buffer not released\n"); - IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary); - } +static HRESULT WINAPI IDirectSound8_IDirectSound_Compact( + LPDIRECTSOUND iface) +{ + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p)\n", This); + return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device); +} - hr = DSOUND_PrimaryDestroy(device); - if (hr != DS_OK) - WARN("DSOUND_PrimaryDestroy failed\n"); +static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig( + LPDIRECTSOUND iface, + LPDWORD lpdwSpeakerConfig) +{ + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); + return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig); +} - if (device->driver) - IDsDriver_Close(device->driver); +static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig( + LPDIRECTSOUND iface, + DWORD config) +{ + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p,0x%08x)\n",This,config); + return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config); +} - if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) - waveOutClose(device->hwo); +static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize( + LPDIRECTSOUND iface, + LPCGUID lpcGuid) +{ + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); + return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid); +} - if (device->driver) - IDsDriver_Release(device->driver); +static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl = +{ + IDirectSound8_IDirectSound_QueryInterface, + IDirectSound8_IDirectSound_AddRef, + IDirectSound8_IDirectSound_Release, + IDirectSound8_IDirectSound_CreateSoundBuffer, + IDirectSound8_IDirectSound_GetCaps, + IDirectSound8_IDirectSound_DuplicateSoundBuffer, + IDirectSound8_IDirectSound_SetCooperativeLevel, + IDirectSound8_IDirectSound_Compact, + IDirectSound8_IDirectSound_GetSpeakerConfig, + IDirectSound8_IDirectSound_SetSpeakerConfig, + IDirectSound8_IDirectSound_Initialize +}; - DSOUND_renderer[device->drvdesc.dnDevNode] = NULL; +static HRESULT IDirectSound8_IDirectSound_Create( + LPDIRECTSOUND8 pds, + LPDIRECTSOUND * ppds) +{ + IDirectSound8_IDirectSound * pdsds; + TRACE("(%p,%p)\n",pds,ppds); - HeapFree(GetProcessHeap(),0,device->tmp_buffer); - HeapFree(GetProcessHeap(),0,device->buffer); - RtlDeleteResource(&device->buffer_list_lock); - device->mixlock.DebugInfo->Spare[0] = 0; - DeleteCriticalSection(&device->mixlock); - HeapFree(GetProcessHeap(),0,device); - TRACE("(%p) released\n", device); + if (ppds == NULL) { + ERR("invalid parameter: ppds == NULL\n"); + return DSERR_INVALIDPARAM; } - return device->ref; -} -HRESULT WINAPI IDirectSoundImpl_Create( - LPDIRECTSOUND8 * ppDS) -{ - IDirectSoundImpl* pDS; - TRACE("(%p)\n",ppDS); + if (pds == NULL) { + ERR("invalid parameter: pds == NULL\n"); + *ppds = NULL; + return DSERR_INVALIDPARAM; + } - /* Allocate memory */ - pDS = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(IDirectSoundImpl)); - if (pDS == NULL) { + pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); + if (pdsds == NULL) { WARN("out of memory\n"); - *ppDS = NULL; + *ppds = NULL; return DSERR_OUTOFMEMORY; } - pDS->lpVtbl = &IDirectSoundImpl_Vtbl; - pDS->ref = 0; - pDS->device = NULL; + pdsds->lpVtbl = &DirectSound8_DirectSound_Vtbl; + pdsds->ref = 0; + pdsds->pds = pds; - *ppDS = (LPDIRECTSOUND8)pDS; + IDirectSoundImpl_AddRef(pds); + *ppds = (LPDIRECTSOUND)pdsds; return DS_OK; } /******************************************************************************* - * IDirectSound_IUnknown + * IDirectSound8_IDirectSound8 */ -static HRESULT WINAPI IDirectSound_IUnknown_QueryInterface( - LPUNKNOWN iface, +static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface( + LPDIRECTSOUND8 iface, REFIID riid, LPVOID * ppobj) { - IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - return DSOUND_QueryInterface(This->pds, riid, ppobj); + return DSOUND_QueryInterface8(This->pds, riid, ppobj); } -static ULONG WINAPI IDirectSound_IUnknown_AddRef( - LPUNKNOWN iface) +static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef( + LPDIRECTSOUND8 iface) { - IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } -static ULONG WINAPI IDirectSound_IUnknown_Release( - LPUNKNOWN iface) +static ULONG WINAPI IDirectSound8_IDirectSound8_Release( + LPDIRECTSOUND8 iface) { - IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { + ((IDirectSoundImpl*)This->pds)->pDS8 = NULL; IDirectSoundImpl_Release(This->pds); HeapFree(GetProcessHeap(), 0, This); TRACE("(%p) released\n", This); @@ -1061,812 +849,978 @@ static ULONG WINAPI IDirectSound_IUnknown_Release( return ref; } -static const IUnknownVtbl DirectSound_Unknown_Vtbl = +static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer( + LPDIRECTSOUND8 iface, + LPCDSBUFFERDESC dsbd, + LPLPDIRECTSOUNDBUFFER ppdsb, + LPUNKNOWN lpunk) { - IDirectSound_IUnknown_QueryInterface, - IDirectSound_IUnknown_AddRef, - IDirectSound_IUnknown_Release + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; + TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); + return DirectSoundDevice_CreateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,dsbd,ppdsb,lpunk,TRUE); +} + +static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps( + LPDIRECTSOUND8 iface, + LPDSCAPS lpDSCaps) +{ + IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; + TRACE("(%p,%p)\n",This,lpDSCaps); + return DirectSoundDevice_GetCaps(((IDirectSoundImpl *)This->pds)->device, lpDSCaps); +} + +static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer( + LPDIRECTSOUND8 iface, + LPDIRECTSOUNDBUFFER psb, + LPLPDIRECTSOUNDBUFFER ppdsb) +{ + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; + TRACE("(%p,%p,%p)\n",This,psb,ppdsb); + return DirectSoundDevice_DuplicateSoundBuffer(((IDirectSoundImpl *)This->pds)->device,psb,ppdsb); +} + +static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel( + LPDIRECTSOUND8 iface, + HWND hwnd, + DWORD level) +{ + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; + TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); + return DirectSoundDevice_SetCooperativeLevel(((IDirectSoundImpl *)This->pds)->device, hwnd, level); +} + +static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact( + LPDIRECTSOUND8 iface) +{ + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; + TRACE("(%p)\n", This); + return DirectSoundDevice_Compact(((IDirectSoundImpl *)This->pds)->device); +} + +static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig( + LPDIRECTSOUND8 iface, + LPDWORD lpdwSpeakerConfig) +{ + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; + TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); + return DirectSoundDevice_GetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,lpdwSpeakerConfig); +} + +static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig( + LPDIRECTSOUND8 iface, + DWORD config) +{ + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; + TRACE("(%p,0x%08x)\n",This,config); + return DirectSoundDevice_SetSpeakerConfig(((IDirectSoundImpl *)This->pds)->device,config); +} + +static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize( + LPDIRECTSOUND8 iface, + LPCGUID lpcGuid) +{ + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; + TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); + return DirectSoundDevice_Initialize(&((IDirectSoundImpl *)This->pds)->device,lpcGuid); +} + +static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification( + LPDIRECTSOUND8 iface, + LPDWORD pdwCertified) +{ + IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; + TRACE("(%p, %p)\n", This, pdwCertified); + return DirectSoundDevice_VerifyCertification(((IDirectSoundImpl *)This->pds)->device,pdwCertified); +} + +static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl = +{ + IDirectSound8_IDirectSound8_QueryInterface, + IDirectSound8_IDirectSound8_AddRef, + IDirectSound8_IDirectSound8_Release, + IDirectSound8_IDirectSound8_CreateSoundBuffer, + IDirectSound8_IDirectSound8_GetCaps, + IDirectSound8_IDirectSound8_DuplicateSoundBuffer, + IDirectSound8_IDirectSound8_SetCooperativeLevel, + IDirectSound8_IDirectSound8_Compact, + IDirectSound8_IDirectSound8_GetSpeakerConfig, + IDirectSound8_IDirectSound8_SetSpeakerConfig, + IDirectSound8_IDirectSound8_Initialize, + IDirectSound8_IDirectSound8_VerifyCertification }; -HRESULT WINAPI IDirectSound_IUnknown_Create( +static HRESULT IDirectSound8_IDirectSound8_Create( LPDIRECTSOUND8 pds, - LPUNKNOWN * ppunk) + LPDIRECTSOUND8 * ppds) +{ + IDirectSound8_IDirectSound8 * pdsds; + TRACE("(%p,%p)\n",pds,ppds); + + if (ppds == NULL) { + ERR("invalid parameter: ppds == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (pds == NULL) { + ERR("invalid parameter: pds == NULL\n"); + *ppds = NULL; + return DSERR_INVALIDPARAM; + } + + pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); + if (pdsds == NULL) { + WARN("out of memory\n"); + *ppds = NULL; + return DSERR_OUTOFMEMORY; + } + + pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl; + pdsds->ref = 0; + pdsds->pds = pds; + + IDirectSoundImpl_AddRef(pds); + *ppds = (LPDIRECTSOUND8)pdsds; + + return DS_OK; +} + +HRESULT DSOUND_Create( + REFIID riid, + LPDIRECTSOUND *ppDS) +{ + LPDIRECTSOUND8 pDS; + HRESULT hr; + TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS); + + if (!IsEqualIID(riid, &IID_IUnknown) && + !IsEqualIID(riid, &IID_IDirectSound)) { + *ppDS = 0; + return E_NOINTERFACE; + } + + /* Get dsound configuration */ + setup_dsound_options(); + + hr = IDirectSoundImpl_Create(&pDS); + if (hr == DS_OK) { + hr = IDirectSound_IDirectSound_Create(pDS, ppDS); + if (*ppDS) + IDirectSound_IDirectSound_AddRef(*ppDS); + else { + WARN("IDirectSound_IDirectSound_Create failed\n"); + IDirectSound8_Release(pDS); + } + } else { + WARN("IDirectSoundImpl_Create failed\n"); + *ppDS = 0; + } + + return hr; +} + +/******************************************************************************* + * DirectSoundCreate (DSOUND.1) + * + * Creates and initializes a DirectSound interface. + * + * PARAMS + * lpcGUID [I] Address of the GUID that identifies the sound device. + * ppDS [O] Address of a variable to receive the interface pointer. + * pUnkOuter [I] Must be NULL. + * + * RETURNS + * Success: DS_OK + * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION, + * DSERR_NODRIVER, DSERR_OUTOFMEMORY + */ +HRESULT WINAPI DirectSoundCreate( + LPCGUID lpcGUID, + LPDIRECTSOUND *ppDS, + IUnknown *pUnkOuter) { - IDirectSound_IUnknown * pdsunk; - TRACE("(%p,%p)\n",pds,ppunk); + HRESULT hr; + LPDIRECTSOUND pDS; - if (ppunk == NULL) { - ERR("invalid parameter: ppunk == NULL\n"); + TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter); + + if (ppDS == NULL) { + WARN("invalid parameter: ppDS == NULL\n"); return DSERR_INVALIDPARAM; } - if (pds == NULL) { - ERR("invalid parameter: pds == NULL\n"); - *ppunk = NULL; + if (pUnkOuter != NULL) { + WARN("invalid parameter: pUnkOuter != NULL\n"); + *ppDS = 0; return DSERR_INVALIDPARAM; } - pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk)); - if (pdsunk == NULL) { - WARN("out of memory\n"); - *ppunk = NULL; - return DSERR_OUTOFMEMORY; + hr = DSOUND_Create(&IID_IDirectSound, &pDS); + if (hr == DS_OK) { + hr = IDirectSound_Initialize(pDS, lpcGUID); + if (hr != DS_OK) { + if (hr != DSERR_ALREADYINITIALIZED) { + IDirectSound_Release(pDS); + pDS = 0; + } else + hr = DS_OK; + } } - pdsunk->lpVtbl = &DirectSound_Unknown_Vtbl; - pdsunk->ref = 0; - pdsunk->pds = pds; - - IDirectSoundImpl_AddRef(pds); - *ppunk = (LPUNKNOWN)pdsunk; + *ppDS = pDS; - return DS_OK; + return hr; } -/******************************************************************************* - * IDirectSound_IDirectSound - */ -static HRESULT WINAPI IDirectSound_IDirectSound_QueryInterface( - LPDIRECTSOUND iface, +HRESULT DSOUND_Create8( REFIID riid, - LPVOID * ppobj) + LPDIRECTSOUND8 *ppDS) { - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - return DSOUND_QueryInterface(This->pds, riid, ppobj); -} + LPDIRECTSOUND8 pDS; + HRESULT hr; + TRACE("(%s, %p)\n", debugstr_guid(riid), ppDS); -static ULONG WINAPI IDirectSound_IDirectSound_AddRef( - LPDIRECTSOUND iface) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); - return ref; -} + if (!IsEqualIID(riid, &IID_IUnknown) && + !IsEqualIID(riid, &IID_IDirectSound) && + !IsEqualIID(riid, &IID_IDirectSound8)) { + *ppDS = 0; + return E_NOINTERFACE; + } -static ULONG WINAPI IDirectSound_IDirectSound_Release( - LPDIRECTSOUND iface) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); - if (!ref) { - IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(), 0, This); - TRACE("(%p) released\n", This); + /* Get dsound configuration */ + setup_dsound_options(); + + hr = IDirectSoundImpl_Create(&pDS); + if (hr == DS_OK) { + hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS); + if (*ppDS) + IDirectSound8_IDirectSound8_AddRef(*ppDS); + else { + WARN("IDirectSound8_IDirectSound8_Create failed\n"); + IDirectSound8_Release(pDS); + } + } else { + WARN("IDirectSoundImpl_Create failed\n"); + *ppDS = 0; } - return ref; -} -static HRESULT WINAPI IDirectSound_IDirectSound_CreateSoundBuffer( - LPDIRECTSOUND iface, - LPCDSBUFFERDESC dsbd, - LPLPDIRECTSOUNDBUFFER ppdsb, - LPUNKNOWN lpunk) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); - return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,FALSE); + return hr; } -static HRESULT WINAPI IDirectSound_IDirectSound_GetCaps( - LPDIRECTSOUND iface, - LPDSCAPS lpDSCaps) +/******************************************************************************* + * DirectSoundCreate8 (DSOUND.11) + * + * Creates and initializes a DirectSound8 interface. + * + * PARAMS + * lpcGUID [I] Address of the GUID that identifies the sound device. + * ppDS [O] Address of a variable to receive the interface pointer. + * pUnkOuter [I] Must be NULL. + * + * RETURNS + * Success: DS_OK + * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION, + * DSERR_NODRIVER, DSERR_OUTOFMEMORY + */ +HRESULT WINAPI DirectSoundCreate8( + LPCGUID lpcGUID, + LPDIRECTSOUND8 *ppDS, + IUnknown *pUnkOuter) { - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p,%p)\n",This,lpDSCaps); - return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps); -} + HRESULT hr; + LPDIRECTSOUND8 pDS; -static HRESULT WINAPI IDirectSound_IDirectSound_DuplicateSoundBuffer( - LPDIRECTSOUND iface, - LPDIRECTSOUNDBUFFER psb, - LPLPDIRECTSOUNDBUFFER ppdsb) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p,%p,%p)\n",This,psb,ppdsb); - return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb); -} + TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter); -static HRESULT WINAPI IDirectSound_IDirectSound_SetCooperativeLevel( - LPDIRECTSOUND iface, - HWND hwnd, - DWORD level) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); - return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level); -} + if (ppDS == NULL) { + WARN("invalid parameter: ppDS == NULL\n"); + return DSERR_INVALIDPARAM; + } -static HRESULT WINAPI IDirectSound_IDirectSound_Compact( - LPDIRECTSOUND iface) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p)\n", This); - return IDirectSoundImpl_Compact(This->pds); -} + if (pUnkOuter != NULL) { + WARN("invalid parameter: pUnkOuter != NULL\n"); + *ppDS = 0; + return DSERR_INVALIDPARAM; + } -static HRESULT WINAPI IDirectSound_IDirectSound_GetSpeakerConfig( - LPDIRECTSOUND iface, - LPDWORD lpdwSpeakerConfig) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); - return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig); -} + hr = DSOUND_Create8(&IID_IDirectSound8, &pDS); + if (hr == DS_OK) { + hr = IDirectSound8_Initialize(pDS, lpcGUID); + if (hr != DS_OK) { + if (hr != DSERR_ALREADYINITIALIZED) { + IDirectSound8_Release(pDS); + pDS = 0; + } else + hr = DS_OK; + } + } -static HRESULT WINAPI IDirectSound_IDirectSound_SetSpeakerConfig( - LPDIRECTSOUND iface, - DWORD config) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p,0x%08lx)\n",This,config); - return IDirectSoundImpl_SetSpeakerConfig(This->pds,config); -} + *ppDS = pDS; -static HRESULT WINAPI IDirectSound_IDirectSound_Initialize( - LPDIRECTSOUND iface, - LPCGUID lpcGuid) -{ - IDirectSound_IDirectSound *This = (IDirectSound_IDirectSound *)iface; - TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); - return IDirectSoundImpl_Initialize(This->pds,lpcGuid); + return hr; } -static const IDirectSoundVtbl DirectSound_DirectSound_Vtbl = -{ - IDirectSound_IDirectSound_QueryInterface, - IDirectSound_IDirectSound_AddRef, - IDirectSound_IDirectSound_Release, - IDirectSound_IDirectSound_CreateSoundBuffer, - IDirectSound_IDirectSound_GetCaps, - IDirectSound_IDirectSound_DuplicateSoundBuffer, - IDirectSound_IDirectSound_SetCooperativeLevel, - IDirectSound_IDirectSound_Compact, - IDirectSound_IDirectSound_GetSpeakerConfig, - IDirectSound_IDirectSound_SetSpeakerConfig, - IDirectSound_IDirectSound_Initialize -}; - -HRESULT WINAPI IDirectSound_IDirectSound_Create( - LPDIRECTSOUND8 pds, - LPDIRECTSOUND * ppds) +/******************************************************************************* + * DirectSoundDevice + */ +static HRESULT DirectSoundDevice_Create(DirectSoundDevice ** ppDevice) { - IDirectSound_IDirectSound * pdsds; - TRACE("(%p,%p)\n",pds,ppds); + DirectSoundDevice * device; + TRACE("(%p)\n", ppDevice); - if (ppds == NULL) { - ERR("invalid parameter: ppds == NULL\n"); - return DSERR_INVALIDPARAM; + /* Allocate memory */ + device = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DirectSoundDevice)); + if (device == NULL) { + WARN("out of memory\n"); + return DSERR_OUTOFMEMORY; } - if (pds == NULL) { - ERR("invalid parameter: pds == NULL\n"); - *ppds = NULL; - return DSERR_INVALIDPARAM; - } + device->ref = 1; + device->priolevel = DSSCL_NORMAL; + device->state = STATE_STOPPED; + device->speaker_config = DSSPEAKER_STEREO | (DSSPEAKER_GEOMETRY_NARROW << 16); - pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); - if (pdsds == NULL) { + /* 3D listener initial parameters */ + device->ds3dl.dwSize = sizeof(DS3DLISTENER); + device->ds3dl.vPosition.x = 0.0; + device->ds3dl.vPosition.y = 0.0; + device->ds3dl.vPosition.z = 0.0; + device->ds3dl.vVelocity.x = 0.0; + device->ds3dl.vVelocity.y = 0.0; + device->ds3dl.vVelocity.z = 0.0; + device->ds3dl.vOrientFront.x = 0.0; + device->ds3dl.vOrientFront.y = 0.0; + device->ds3dl.vOrientFront.z = 1.0; + device->ds3dl.vOrientTop.x = 0.0; + device->ds3dl.vOrientTop.y = 1.0; + device->ds3dl.vOrientTop.z = 0.0; + device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; + device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; + device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR; + + device->prebuf = ds_snd_queue_max; + device->guid = GUID_NULL; + + /* Set default wave format (may need it for waveOutOpen) */ + device->pwfx = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEFORMATEX)); + if (device->pwfx == NULL) { WARN("out of memory\n"); - *ppds = NULL; + HeapFree(GetProcessHeap(),0,device); return DSERR_OUTOFMEMORY; } - pdsds->lpVtbl = &DirectSound_DirectSound_Vtbl; - pdsds->ref = 0; - pdsds->pds = pds; + /* We rely on the sound driver to return the actual sound format of + * the device if it does not support 22050x8x2 and is given the + * WAVE_DIRECTSOUND flag. + */ + device->pwfx->wFormatTag = WAVE_FORMAT_PCM; + device->pwfx->nSamplesPerSec = ds_default_sample_rate; + device->pwfx->wBitsPerSample = ds_default_bits_per_sample; + device->pwfx->nChannels = 2; + device->pwfx->nBlockAlign = device->pwfx->wBitsPerSample * device->pwfx->nChannels / 8; + device->pwfx->nAvgBytesPerSec = device->pwfx->nSamplesPerSec * device->pwfx->nBlockAlign; + device->pwfx->cbSize = 0; - IDirectSoundImpl_AddRef(pds); - *ppds = (LPDIRECTSOUND)pdsds; + InitializeCriticalSection(&(device->mixlock)); + device->mixlock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": DirectSoundDevice.mixlock"); - return DS_OK; -} + RtlInitializeResource(&(device->buffer_list_lock)); -/******************************************************************************* - * IDirectSound8_IUnknown - */ -static HRESULT WINAPI IDirectSound8_IUnknown_QueryInterface( - LPUNKNOWN iface, - REFIID riid, - LPVOID * ppobj) -{ - IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; - TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - return DSOUND_QueryInterface8(This->pds, riid, ppobj); -} + *ppDevice = device; -static ULONG WINAPI IDirectSound8_IUnknown_AddRef( - LPUNKNOWN iface) -{ - IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; - ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); - return ref; + return DS_OK; } -static ULONG WINAPI IDirectSound8_IUnknown_Release( - LPUNKNOWN iface) +static ULONG DirectSoundDevice_AddRef(DirectSoundDevice * device) { - IDirectSound_IUnknown *This = (IDirectSound_IUnknown *)iface; - ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); - if (!ref) { - IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(), 0, This); - TRACE("(%p) released\n", This); - } + ULONG ref = InterlockedIncrement(&(device->ref)); + TRACE("(%p) ref was %d\n", device, ref - 1); return ref; } -static const IUnknownVtbl DirectSound8_Unknown_Vtbl = -{ - IDirectSound8_IUnknown_QueryInterface, - IDirectSound8_IUnknown_AddRef, - IDirectSound8_IUnknown_Release -}; - -HRESULT WINAPI IDirectSound8_IUnknown_Create( - LPDIRECTSOUND8 pds, - LPUNKNOWN * ppunk) +ULONG DirectSoundDevice_Release(DirectSoundDevice * device) { - IDirectSound8_IUnknown * pdsunk; - TRACE("(%p,%p)\n",pds,ppunk); + HRESULT hr; + ULONG ref = InterlockedDecrement(&(device->ref)); + TRACE("(%p) ref was %u\n", device, ref + 1); + if (!ref) { + int i; + timeKillEvent(device->timerID); + timeEndPeriod(DS_TIME_RES); - if (ppunk == NULL) { - ERR("invalid parameter: ppunk == NULL\n"); - return DSERR_INVALIDPARAM; - } + /* The kill event should have allowed the timer process to expire + * but try to grab the lock just in case. Can't hold lock because + * IDirectSoundBufferImpl_Destroy also grabs the lock */ + RtlAcquireResourceShared(&(device->buffer_list_lock), TRUE); + RtlReleaseResource(&(device->buffer_list_lock)); - if (pds == NULL) { - ERR("invalid parameter: pds == NULL\n"); - *ppunk = NULL; - return DSERR_INVALIDPARAM; - } + /* It is allowed to release this object even when buffers are playing */ + if (device->buffers) { + WARN("%d secondary buffers not released\n", device->nrofbuffers); + for( i=0;inrofbuffers;i++) + IDirectSoundBufferImpl_Destroy(device->buffers[i]); + } - pdsunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsunk)); - if (pdsunk == NULL) { - WARN("out of memory\n"); - *ppunk = NULL; - return DSERR_OUTOFMEMORY; - } + if (device->primary) { + WARN("primary buffer not released\n"); + IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)device->primary); + } - pdsunk->lpVtbl = &DirectSound8_Unknown_Vtbl; - pdsunk->ref = 0; - pdsunk->pds = pds; + hr = DSOUND_PrimaryDestroy(device); + if (hr != DS_OK) + WARN("DSOUND_PrimaryDestroy failed\n"); - IDirectSoundImpl_AddRef(pds); - *ppunk = (LPUNKNOWN)pdsunk; + if (device->driver) + IDsDriver_Close(device->driver); - return DS_OK; -} + if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) + waveOutClose(device->hwo); -/******************************************************************************* - * IDirectSound8_IDirectSound - */ -static HRESULT WINAPI IDirectSound8_IDirectSound_QueryInterface( - LPDIRECTSOUND iface, - REFIID riid, - LPVOID * ppobj) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - return DSOUND_QueryInterface8(This->pds, riid, ppobj); -} + if (device->driver) + IDsDriver_Release(device->driver); -static ULONG WINAPI IDirectSound8_IDirectSound_AddRef( - LPDIRECTSOUND iface) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); - return ref; -} + DSOUND_renderer[device->drvdesc.dnDevNode] = NULL; -static ULONG WINAPI IDirectSound8_IDirectSound_Release( - LPDIRECTSOUND iface) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); - if (!ref) { - IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(), 0, This); - TRACE("(%p) released\n", This); + HeapFree(GetProcessHeap(), 0, device->tmp_buffer); + HeapFree(GetProcessHeap(), 0, device->mix_buffer); + if (device->drvdesc.dwFlags & DSDDESC_USESYSTEMMEMORY) + HeapFree(GetProcessHeap(), 0, device->buffer); + RtlDeleteResource(&device->buffer_list_lock); + device->mixlock.DebugInfo->Spare[0] = 0; + DeleteCriticalSection(&device->mixlock); + HeapFree(GetProcessHeap(),0,device); + TRACE("(%p) released\n", device); } return ref; } -static HRESULT WINAPI IDirectSound8_IDirectSound_CreateSoundBuffer( - LPDIRECTSOUND iface, - LPCDSBUFFERDESC dsbd, - LPLPDIRECTSOUNDBUFFER ppdsb, - LPUNKNOWN lpunk) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); - return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE); -} - -static HRESULT WINAPI IDirectSound8_IDirectSound_GetCaps( - LPDIRECTSOUND iface, +HRESULT DirectSoundDevice_GetCaps( + DirectSoundDevice * device, LPDSCAPS lpDSCaps) { - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p,%p)\n",This,lpDSCaps); - return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps); -} + TRACE("(%p,%p)\n",device,lpDSCaps); -static HRESULT WINAPI IDirectSound8_IDirectSound_DuplicateSoundBuffer( - LPDIRECTSOUND iface, - LPDIRECTSOUNDBUFFER psb, - LPLPDIRECTSOUNDBUFFER ppdsb) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p,%p,%p)\n",This,psb,ppdsb); - return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb); -} + if (device == NULL) { + WARN("not initialized\n"); + return DSERR_UNINITIALIZED; + } -static HRESULT WINAPI IDirectSound8_IDirectSound_SetCooperativeLevel( - LPDIRECTSOUND iface, - HWND hwnd, - DWORD level) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); - return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level); -} + if (lpDSCaps == NULL) { + WARN("invalid parameter: lpDSCaps = NULL\n"); + return DSERR_INVALIDPARAM; + } -static HRESULT WINAPI IDirectSound8_IDirectSound_Compact( - LPDIRECTSOUND iface) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p)\n", This); - return IDirectSoundImpl_Compact(This->pds); -} + /* check if there is enough room */ + if (lpDSCaps->dwSize < sizeof(*lpDSCaps)) { + WARN("invalid parameter: lpDSCaps->dwSize = %d\n", lpDSCaps->dwSize); + return DSERR_INVALIDPARAM; + } -static HRESULT WINAPI IDirectSound8_IDirectSound_GetSpeakerConfig( - LPDIRECTSOUND iface, - LPDWORD lpdwSpeakerConfig) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); - return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig); -} + lpDSCaps->dwFlags = device->drvcaps.dwFlags; + if (TRACE_ON(dsound)) { + TRACE("(flags=0x%08x:\n",lpDSCaps->dwFlags); + _dump_DSCAPS(lpDSCaps->dwFlags); + TRACE(")\n"); + } + lpDSCaps->dwMinSecondarySampleRate = device->drvcaps.dwMinSecondarySampleRate; + lpDSCaps->dwMaxSecondarySampleRate = device->drvcaps.dwMaxSecondarySampleRate; + lpDSCaps->dwPrimaryBuffers = device->drvcaps.dwPrimaryBuffers; + lpDSCaps->dwMaxHwMixingAllBuffers = device->drvcaps.dwMaxHwMixingAllBuffers; + lpDSCaps->dwMaxHwMixingStaticBuffers = device->drvcaps.dwMaxHwMixingStaticBuffers; + lpDSCaps->dwMaxHwMixingStreamingBuffers = device->drvcaps.dwMaxHwMixingStreamingBuffers; + lpDSCaps->dwFreeHwMixingAllBuffers = device->drvcaps.dwFreeHwMixingAllBuffers; + lpDSCaps->dwFreeHwMixingStaticBuffers = device->drvcaps.dwFreeHwMixingStaticBuffers; + lpDSCaps->dwFreeHwMixingStreamingBuffers = device->drvcaps.dwFreeHwMixingStreamingBuffers; + lpDSCaps->dwMaxHw3DAllBuffers = device->drvcaps.dwMaxHw3DAllBuffers; + lpDSCaps->dwMaxHw3DStaticBuffers = device->drvcaps.dwMaxHw3DStaticBuffers; + lpDSCaps->dwMaxHw3DStreamingBuffers = device->drvcaps.dwMaxHw3DStreamingBuffers; + lpDSCaps->dwFreeHw3DAllBuffers = device->drvcaps.dwFreeHw3DAllBuffers; + lpDSCaps->dwFreeHw3DStaticBuffers = device->drvcaps.dwFreeHw3DStaticBuffers; + lpDSCaps->dwFreeHw3DStreamingBuffers = device->drvcaps.dwFreeHw3DStreamingBuffers; + lpDSCaps->dwTotalHwMemBytes = device->drvcaps.dwTotalHwMemBytes; + lpDSCaps->dwFreeHwMemBytes = device->drvcaps.dwFreeHwMemBytes; + lpDSCaps->dwMaxContigFreeHwMemBytes = device->drvcaps.dwMaxContigFreeHwMemBytes; -static HRESULT WINAPI IDirectSound8_IDirectSound_SetSpeakerConfig( - LPDIRECTSOUND iface, - DWORD config) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p,0x%08lx)\n",This,config); - return IDirectSoundImpl_SetSpeakerConfig(This->pds,config); -} + /* driver doesn't have these */ + lpDSCaps->dwUnlockTransferRateHwBuffers = 4096; /* But we have none... */ + lpDSCaps->dwPlayCpuOverheadSwBuffers = 1; /* 1% */ -static HRESULT WINAPI IDirectSound8_IDirectSound_Initialize( - LPDIRECTSOUND iface, - LPCGUID lpcGuid) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); - return IDirectSoundImpl_Initialize(This->pds,lpcGuid); + return DS_OK; } -static const IDirectSoundVtbl DirectSound8_DirectSound_Vtbl = +HRESULT DirectSoundDevice_Initialize(DirectSoundDevice ** ppDevice, LPCGUID lpcGUID) { - IDirectSound8_IDirectSound_QueryInterface, - IDirectSound8_IDirectSound_AddRef, - IDirectSound8_IDirectSound_Release, - IDirectSound8_IDirectSound_CreateSoundBuffer, - IDirectSound8_IDirectSound_GetCaps, - IDirectSound8_IDirectSound_DuplicateSoundBuffer, - IDirectSound8_IDirectSound_SetCooperativeLevel, - IDirectSound8_IDirectSound_Compact, - IDirectSound8_IDirectSound_GetSpeakerConfig, - IDirectSound8_IDirectSound_SetSpeakerConfig, - IDirectSound8_IDirectSound_Initialize -}; + HRESULT hr = DS_OK; + unsigned wod, wodn; + BOOLEAN found = FALSE; + GUID devGUID; + DirectSoundDevice * device = *ppDevice; + TRACE("(%p,%s)\n",ppDevice,debugstr_guid(lpcGUID)); + + if (*ppDevice != NULL) { + WARN("already initialized\n"); + return DSERR_ALREADYINITIALIZED; + } -HRESULT WINAPI IDirectSound8_IDirectSound_Create( - LPDIRECTSOUND8 pds, - LPDIRECTSOUND * ppds) -{ - IDirectSound8_IDirectSound * pdsds; - TRACE("(%p,%p)\n",pds,ppds); + /* Default device? */ + if (!lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL)) + lpcGUID = &DSDEVID_DefaultPlayback; - if (ppds == NULL) { - ERR("invalid parameter: ppds == NULL\n"); + if (GetDeviceID(lpcGUID, &devGUID) != DS_OK) { + WARN("invalid parameter: lpcGUID\n"); return DSERR_INVALIDPARAM; } - if (pds == NULL) { - ERR("invalid parameter: pds == NULL\n"); - *ppds = NULL; - return DSERR_INVALIDPARAM; + /* Enumerate WINMM audio devices and find the one we want */ + wodn = waveOutGetNumDevs(); + if (!wodn) { + WARN("no driver\n"); + return DSERR_NODRIVER; } - pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); - if (pdsds == NULL) { - WARN("out of memory\n"); - *ppds = NULL; - return DSERR_OUTOFMEMORY; + for (wod=0; wodlpVtbl = &DirectSound8_DirectSound_Vtbl; - pdsds->ref = 0; - pdsds->pds = pds; + if (found == FALSE) { + WARN("No device found matching given ID!\n"); + return DSERR_NODRIVER; + } - IDirectSoundImpl_AddRef(pds); - *ppds = (LPDIRECTSOUND)pdsds; + if (DSOUND_renderer[wod]) { + if (IsEqualGUID(&devGUID, &DSOUND_renderer[wod]->guid)) { + device = DSOUND_renderer[wod]; + DirectSoundDevice_AddRef(device); + *ppDevice = device; + return DS_OK; + } else { + ERR("device GUID doesn't match\n"); + hr = DSERR_GENERIC; + return hr; + } + } else { + hr = DirectSoundDevice_Create(&device); + if (hr != DS_OK) { + WARN("DirectSoundDevice_Create failed\n"); + return hr; + } + } - return DS_OK; -} + *ppDevice = device; + device->guid = devGUID; + device->driver = NULL; -/******************************************************************************* - * IDirectSound8_IDirectSound8 - */ -static HRESULT WINAPI IDirectSound8_IDirectSound8_QueryInterface( - LPDIRECTSOUND8 iface, - REFIID riid, - LPVOID * ppobj) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - return DSOUND_QueryInterface8(This->pds, riid, ppobj); -} + device->drvdesc.dnDevNode = wod; + hr = DSOUND_ReopenDevice(device, FALSE); + if (FAILED(hr)) + { + WARN("DSOUND_ReopenDevice failed: %08x\n", hr); + return hr; + } -static ULONG WINAPI IDirectSound8_IDirectSound8_AddRef( - LPDIRECTSOUND8 iface) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); - return ref; -} + if (device->driver) { + /* the driver is now open, so it's now allowed to call GetCaps */ + hr = IDsDriver_GetCaps(device->driver,&(device->drvcaps)); + if (hr != DS_OK) { + WARN("IDsDriver_GetCaps failed\n"); + return hr; + } + } else { + WAVEOUTCAPSA woc; + hr = mmErr(waveOutGetDevCapsA(device->drvdesc.dnDevNode, &woc, sizeof(woc))); + if (hr != DS_OK) { + WARN("waveOutGetDevCaps failed\n"); + return hr; + } + ZeroMemory(&device->drvcaps, sizeof(device->drvcaps)); + if ((woc.dwFormats & WAVE_FORMAT_1M08) || + (woc.dwFormats & WAVE_FORMAT_2M08) || + (woc.dwFormats & WAVE_FORMAT_4M08) || + (woc.dwFormats & WAVE_FORMAT_48M08) || + (woc.dwFormats & WAVE_FORMAT_96M08)) { + device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; + device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; + } + if ((woc.dwFormats & WAVE_FORMAT_1M16) || + (woc.dwFormats & WAVE_FORMAT_2M16) || + (woc.dwFormats & WAVE_FORMAT_4M16) || + (woc.dwFormats & WAVE_FORMAT_48M16) || + (woc.dwFormats & WAVE_FORMAT_96M16)) { + device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; + device->drvcaps.dwFlags |= DSCAPS_PRIMARYMONO; + } + if ((woc.dwFormats & WAVE_FORMAT_1S08) || + (woc.dwFormats & WAVE_FORMAT_2S08) || + (woc.dwFormats & WAVE_FORMAT_4S08) || + (woc.dwFormats & WAVE_FORMAT_48S08) || + (woc.dwFormats & WAVE_FORMAT_96S08)) { + device->drvcaps.dwFlags |= DSCAPS_PRIMARY8BIT; + device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; + } + if ((woc.dwFormats & WAVE_FORMAT_1S16) || + (woc.dwFormats & WAVE_FORMAT_2S16) || + (woc.dwFormats & WAVE_FORMAT_4S16) || + (woc.dwFormats & WAVE_FORMAT_48S16) || + (woc.dwFormats & WAVE_FORMAT_96S16)) { + device->drvcaps.dwFlags |= DSCAPS_PRIMARY16BIT; + device->drvcaps.dwFlags |= DSCAPS_PRIMARYSTEREO; + } + if (ds_emuldriver) + device->drvcaps.dwFlags |= DSCAPS_EMULDRIVER; + device->drvcaps.dwMinSecondarySampleRate = DSBFREQUENCY_MIN; + device->drvcaps.dwMaxSecondarySampleRate = DSBFREQUENCY_MAX; + ZeroMemory(&device->volpan, sizeof(device->volpan)); + } -static ULONG WINAPI IDirectSound8_IDirectSound8_Release( - LPDIRECTSOUND8 iface) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); - if (!ref) { - IDirectSoundImpl_Release(This->pds); - HeapFree(GetProcessHeap(), 0, This); - TRACE("(%p) released\n", This); + hr = DSOUND_PrimaryCreate(device); + if (hr == DS_OK) { + UINT triggertime = DS_TIME_DEL, res = DS_TIME_RES, id; + TIMECAPS time; + + DSOUND_renderer[device->drvdesc.dnDevNode] = device; + timeGetDevCaps(&time, sizeof(TIMECAPS)); + TRACE("Minimum timer resolution: %u, max timer: %u\n", time.wPeriodMin, time.wPeriodMax); + if (triggertime < time.wPeriodMin) + triggertime = time.wPeriodMin; + if (res < time.wPeriodMin) + res = time.wPeriodMin; + if (timeBeginPeriod(res) == TIMERR_NOCANDO) + WARN("Could not set minimum resolution, don't expect sound\n"); + id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC | TIME_KILL_SYNCHRONOUS); + if (!id) + { + WARN("Timer not created! Retrying without TIME_KILL_SYNCHRONOUS\n"); + id = timeSetEvent(triggertime, res, DSOUND_timer, (DWORD_PTR)device, TIME_PERIODIC); + if (!id) ERR("Could not create timer, sound playback will not occur\n"); + } + DSOUND_renderer[device->drvdesc.dnDevNode]->timerID = id; + } else { + WARN("DSOUND_PrimaryCreate failed\n"); } - return ref; + + return hr; } -static HRESULT WINAPI IDirectSound8_IDirectSound8_CreateSoundBuffer( - LPDIRECTSOUND8 iface, +HRESULT DirectSoundDevice_CreateSoundBuffer( + DirectSoundDevice * device, LPCDSBUFFERDESC dsbd, LPLPDIRECTSOUNDBUFFER ppdsb, - LPUNKNOWN lpunk) + LPUNKNOWN lpunk, + BOOL from8) { - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); - return DSOUND_CreateSoundBuffer(This->pds,dsbd,ppdsb,lpunk,TRUE); -} + HRESULT hres = DS_OK; + TRACE("(%p,%p,%p,%p)\n",device,dsbd,ppdsb,lpunk); -static HRESULT WINAPI IDirectSound8_IDirectSound8_GetCaps( - LPDIRECTSOUND8 iface, - LPDSCAPS lpDSCaps) -{ - IDirectSound8_IDirectSound *This = (IDirectSound8_IDirectSound *)iface; - TRACE("(%p,%p)\n",This,lpDSCaps); - return IDirectSoundImpl_GetCaps(This->pds, lpDSCaps); -} + if (device == NULL) { + WARN("not initialized\n"); + return DSERR_UNINITIALIZED; + } -static HRESULT WINAPI IDirectSound8_IDirectSound8_DuplicateSoundBuffer( - LPDIRECTSOUND8 iface, - LPDIRECTSOUNDBUFFER psb, - LPLPDIRECTSOUNDBUFFER ppdsb) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p,%p,%p)\n",This,psb,ppdsb); - return IDirectSoundImpl_DuplicateSoundBuffer(This->pds,psb,ppdsb); -} + if (dsbd == NULL) { + WARN("invalid parameter: dsbd == NULL\n"); + return DSERR_INVALIDPARAM; + } -static HRESULT WINAPI IDirectSound8_IDirectSound8_SetCooperativeLevel( - LPDIRECTSOUND8 iface, - HWND hwnd, - DWORD level) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); - return IDirectSoundImpl_SetCooperativeLevel(This->pds,hwnd,level); -} + if (dsbd->dwSize != sizeof(DSBUFFERDESC) && + dsbd->dwSize != sizeof(DSBUFFERDESC1)) { + WARN("invalid parameter: dsbd\n"); + return DSERR_INVALIDPARAM; + } -static HRESULT WINAPI IDirectSound8_IDirectSound8_Compact( - LPDIRECTSOUND8 iface) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p)\n", This); - return IDirectSoundImpl_Compact(This->pds); -} + if (ppdsb == NULL) { + WARN("invalid parameter: ppdsb == NULL\n"); + return DSERR_INVALIDPARAM; + } + *ppdsb = NULL; -static HRESULT WINAPI IDirectSound8_IDirectSound8_GetSpeakerConfig( - LPDIRECTSOUND8 iface, - LPDWORD lpdwSpeakerConfig) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); - return IDirectSoundImpl_GetSpeakerConfig(This->pds,lpdwSpeakerConfig); -} + if (TRACE_ON(dsound)) { + TRACE("(structsize=%d)\n",dsbd->dwSize); + TRACE("(flags=0x%08x:\n",dsbd->dwFlags); + _dump_DSBCAPS(dsbd->dwFlags); + TRACE(")\n"); + TRACE("(bufferbytes=%d)\n",dsbd->dwBufferBytes); + TRACE("(lpwfxFormat=%p)\n",dsbd->lpwfxFormat); + } -static HRESULT WINAPI IDirectSound8_IDirectSound8_SetSpeakerConfig( - LPDIRECTSOUND8 iface, - DWORD config) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p,0x%08lx)\n",This,config); - return IDirectSoundImpl_SetSpeakerConfig(This->pds,config); -} + if (dsbd->dwFlags & DSBCAPS_PRIMARYBUFFER) { + if (dsbd->lpwfxFormat != NULL) { + WARN("invalid parameter: dsbd->lpwfxFormat must be NULL for " + "primary buffer\n"); + return DSERR_INVALIDPARAM; + } + + if (device->primary) { + WARN("Primary Buffer already created\n"); + IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary)); + *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary); + } else { + device->dsbd = *dsbd; + device->dsbd.dwFlags &= ~(DSBCAPS_LOCHARDWARE | DSBCAPS_LOCSOFTWARE); + if (device->hwbuf) + device->dsbd.dwFlags |= DSBCAPS_LOCHARDWARE; + else device->dsbd.dwFlags |= DSBCAPS_LOCSOFTWARE; + hres = PrimaryBufferImpl_Create(device, &(device->primary), &(device->dsbd)); + if (device->primary) { + IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)(device->primary)); + *ppdsb = (LPDIRECTSOUNDBUFFER)(device->primary); + } else + WARN("PrimaryBufferImpl_Create failed\n"); + } + } else { + IDirectSoundBufferImpl * dsb; + WAVEFORMATEXTENSIBLE *pwfxe; + + if (dsbd->lpwfxFormat == NULL) { + WARN("invalid parameter: dsbd->lpwfxFormat can't be NULL for " + "secondary buffer\n"); + return DSERR_INVALIDPARAM; + } + pwfxe = (WAVEFORMATEXTENSIBLE*)dsbd->lpwfxFormat; + + if (pwfxe->Format.wBitsPerSample != 16 && pwfxe->Format.wBitsPerSample != 8 && pwfxe->Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) + { + WARN("wBitsPerSample=%d needs a WAVEFORMATEXTENSIBLE\n", dsbd->lpwfxFormat->wBitsPerSample); + return DSERR_CONTROLUNAVAIL; + } + if (pwfxe->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + if (pwfxe->Format.cbSize < (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))) + { + WARN("Too small a cbSize %u\n", pwfxe->Format.cbSize); + return DSERR_INVALIDPARAM; + } + + if (pwfxe->Format.cbSize > (sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX))) + { + WARN("Too big a cbSize %u\n", pwfxe->Format.cbSize); + return DSERR_CONTROLUNAVAIL; + } + + if (!IsEqualGUID(&pwfxe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)) + { + if (!IsEqualGUID(&pwfxe->SubFormat, &GUID_NULL)) + FIXME("SubFormat %s not supported right now.\n", debugstr_guid(&pwfxe->SubFormat)); + return DSERR_INVALIDPARAM; + } + if (pwfxe->Samples.wValidBitsPerSample > dsbd->lpwfxFormat->wBitsPerSample) + { + WARN("Samples.wValidBitsPerSample(%d) > Format.wBitsPerSample (%d)\n", pwfxe->Samples.wValidBitsPerSample, pwfxe->Format.wBitsPerSample); + return DSERR_INVALIDPARAM; + } + if (pwfxe->Samples.wValidBitsPerSample && pwfxe->Samples.wValidBitsPerSample < dsbd->lpwfxFormat->wBitsPerSample) + { + FIXME("Non-packed formats not supported right now: %d/%d\n", pwfxe->Samples.wValidBitsPerSample, dsbd->lpwfxFormat->wBitsPerSample); + return DSERR_CONTROLUNAVAIL; + } + } + + TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," + "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", + dsbd->lpwfxFormat->wFormatTag, dsbd->lpwfxFormat->nChannels, + dsbd->lpwfxFormat->nSamplesPerSec, + dsbd->lpwfxFormat->nAvgBytesPerSec, + dsbd->lpwfxFormat->nBlockAlign, + dsbd->lpwfxFormat->wBitsPerSample, dsbd->lpwfxFormat->cbSize); -static HRESULT WINAPI IDirectSound8_IDirectSound8_Initialize( - LPDIRECTSOUND8 iface, - LPCGUID lpcGuid) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); - return IDirectSoundImpl_Initialize(This->pds,lpcGuid); -} + if (from8 && (dsbd->dwFlags & DSBCAPS_CTRL3D) && (dsbd->lpwfxFormat->nChannels != 1)) { + WARN("invalid parameter: 3D buffer format must be mono\n"); + return DSERR_INVALIDPARAM; + } -static HRESULT WINAPI IDirectSound8_IDirectSound8_VerifyCertification( - LPDIRECTSOUND8 iface, - LPDWORD pdwCertified) -{ - IDirectSound8_IDirectSound8 *This = (IDirectSound8_IDirectSound8 *)iface; - TRACE("(%p, %p)\n", This, pdwCertified); - return IDirectSoundImpl_VerifyCertification(This->pds,pdwCertified); + hres = IDirectSoundBufferImpl_Create(device, &dsb, dsbd); + if (dsb) { + hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb); + if (*ppdsb) { + dsb->secondary = (SecondaryBufferImpl*)*ppdsb; + IDirectSoundBuffer_AddRef(*ppdsb); + } else + WARN("SecondaryBufferImpl_Create failed\n"); + } else + WARN("IDirectSoundBufferImpl_Create failed\n"); + } + + return hres; } -static const IDirectSound8Vtbl DirectSound8_DirectSound8_Vtbl = +HRESULT DirectSoundDevice_DuplicateSoundBuffer( + DirectSoundDevice * device, + LPDIRECTSOUNDBUFFER psb, + LPLPDIRECTSOUNDBUFFER ppdsb) { - IDirectSound8_IDirectSound8_QueryInterface, - IDirectSound8_IDirectSound8_AddRef, - IDirectSound8_IDirectSound8_Release, - IDirectSound8_IDirectSound8_CreateSoundBuffer, - IDirectSound8_IDirectSound8_GetCaps, - IDirectSound8_IDirectSound8_DuplicateSoundBuffer, - IDirectSound8_IDirectSound8_SetCooperativeLevel, - IDirectSound8_IDirectSound8_Compact, - IDirectSound8_IDirectSound8_GetSpeakerConfig, - IDirectSound8_IDirectSound8_SetSpeakerConfig, - IDirectSound8_IDirectSound8_Initialize, - IDirectSound8_IDirectSound8_VerifyCertification -}; + HRESULT hres = DS_OK; + IDirectSoundBufferImpl* dsb; + TRACE("(%p,%p,%p)\n",device,psb,ppdsb); -HRESULT WINAPI IDirectSound8_IDirectSound8_Create( - LPDIRECTSOUND8 pds, - LPDIRECTSOUND8 * ppds) -{ - IDirectSound8_IDirectSound8 * pdsds; - TRACE("(%p,%p)\n",pds,ppds); + if (device == NULL) { + WARN("not initialized\n"); + return DSERR_UNINITIALIZED; + } - if (ppds == NULL) { - ERR("invalid parameter: ppds == NULL\n"); + if (psb == NULL) { + WARN("invalid parameter: psb == NULL\n"); return DSERR_INVALIDPARAM; } - if (pds == NULL) { - ERR("invalid parameter: pds == NULL\n"); - *ppds = NULL; + if (ppdsb == NULL) { + WARN("invalid parameter: ppdsb == NULL\n"); return DSERR_INVALIDPARAM; } - pdsds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsds)); - if (pdsds == NULL) { - WARN("out of memory\n"); - *ppds = NULL; - return DSERR_OUTOFMEMORY; + /* make sure we have a secondary buffer */ + if ((PrimaryBufferImpl *)psb == device->primary) { + WARN("trying to duplicate primary buffer\n"); + *ppdsb = NULL; + return DSERR_INVALIDCALL; } - pdsds->lpVtbl = &DirectSound8_DirectSound8_Vtbl; - pdsds->ref = 0; - pdsds->pds = pds; + /* duplicate the actual buffer implementation */ + hres = IDirectSoundBufferImpl_Duplicate(device, &dsb, + ((SecondaryBufferImpl *)psb)->dsb); - IDirectSoundImpl_AddRef(pds); - *ppds = (LPDIRECTSOUND8)pdsds; + if (hres == DS_OK) { + /* create a new secondary buffer using the new implementation */ + hres = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl**)ppdsb); + if (*ppdsb) { + dsb->secondary = (SecondaryBufferImpl*)*ppdsb; + IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)*ppdsb); + } else { + WARN("SecondaryBufferImpl_Create failed\n"); + IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER8)dsb); + IDirectSoundBuffer_Release((LPDIRECTSOUNDBUFFER8)dsb); + } + } - return DS_OK; + return hres; } -HRESULT WINAPI DSOUND_Create( - LPDIRECTSOUND *ppDS, - IUnknown *pUnkOuter) +HRESULT DirectSoundDevice_SetCooperativeLevel( + DirectSoundDevice * device, + HWND hwnd, + DWORD level) { - LPDIRECTSOUND8 pDS; - HRESULT hr; - TRACE("(%p,%p)\n",ppDS,pUnkOuter); + TRACE("(%p,%p,%s)\n",device,hwnd,dumpCooperativeLevel(level)); - /* Get dsound configuration */ - setup_dsound_options(); + if (device == NULL) { + WARN("not initialized\n"); + return DSERR_UNINITIALIZED; + } - hr = IDirectSoundImpl_Create(&pDS); - if (hr == DS_OK) { - hr = IDirectSound_IDirectSound_Create(pDS, ppDS); - if (*ppDS) - IDirectSound_IDirectSound_AddRef(*ppDS); - else { - WARN("IDirectSound_IDirectSound_Create failed\n"); - IDirectSound8_Release(pDS); - } - } else { - WARN("IDirectSoundImpl_Create failed\n"); - *ppDS = 0; + if (level==DSSCL_PRIORITY || level==DSSCL_EXCLUSIVE) { + WARN("level=%s not fully supported\n", + level==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE"); } - return hr; + device->priolevel = level; + return DS_OK; } -/******************************************************************************* - * DirectSoundCreate (DSOUND.1) - * - * Creates and initializes a DirectSound interface. - * - * PARAMS - * lpcGUID [I] Address of the GUID that identifies the sound device. - * ppDS [O] Address of a variable to receive the interface pointer. - * pUnkOuter [I] Must be NULL. - * - * RETURNS - * Success: DS_OK - * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION, - * DSERR_NODRIVER, DSERR_OUTOFMEMORY - */ -HRESULT WINAPI DirectSoundCreate( - LPCGUID lpcGUID, - LPDIRECTSOUND *ppDS, - IUnknown *pUnkOuter) +HRESULT DirectSoundDevice_Compact( + DirectSoundDevice * device) { - HRESULT hr; - LPDIRECTSOUND pDS; - - TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter); - - if (ppDS == NULL) { - WARN("invalid parameter: ppDS == NULL\n"); - return DSERR_INVALIDPARAM; - } + TRACE("(%p)\n", device); - if (pUnkOuter != NULL) { - WARN("invalid parameter: pUnkOuter != NULL\n"); - *ppDS = 0; - return DSERR_INVALIDPARAM; + if (device == NULL) { + WARN("not initialized\n"); + return DSERR_UNINITIALIZED; } - hr = DSOUND_Create(&pDS, pUnkOuter); - if (hr == DS_OK) { - hr = IDirectSound_Initialize(pDS, lpcGUID); - if (hr != DS_OK) { - if (hr != DSERR_ALREADYINITIALIZED) { - IDirectSound_Release(pDS); - pDS = 0; - } else - hr = DS_OK; - } + if (device->priolevel < DSSCL_PRIORITY) { + WARN("incorrect priority level\n"); + return DSERR_PRIOLEVELNEEDED; } - *ppDS = pDS; - - return hr; + return DS_OK; } -HRESULT WINAPI DSOUND_Create8( - LPDIRECTSOUND8 *ppDS, - IUnknown *pUnkOuter) +HRESULT DirectSoundDevice_GetSpeakerConfig( + DirectSoundDevice * device, + LPDWORD lpdwSpeakerConfig) { - LPDIRECTSOUND8 pDS; - HRESULT hr; - TRACE("(%p,%p)\n",ppDS,pUnkOuter); + TRACE("(%p, %p)\n", device, lpdwSpeakerConfig); - /* Get dsound configuration */ - setup_dsound_options(); + if (device == NULL) { + WARN("not initialized\n"); + return DSERR_UNINITIALIZED; + } - hr = IDirectSoundImpl_Create(&pDS); - if (hr == DS_OK) { - hr = IDirectSound8_IDirectSound8_Create(pDS, ppDS); - if (*ppDS) - IDirectSound8_IDirectSound8_AddRef(*ppDS); - else { - WARN("IDirectSound8_IDirectSound8_Create failed\n"); - IDirectSound8_Release(pDS); - } - } else { - WARN("IDirectSoundImpl_Create failed\n"); - *ppDS = 0; + if (lpdwSpeakerConfig == NULL) { + WARN("invalid parameter: lpdwSpeakerConfig == NULL\n"); + return DSERR_INVALIDPARAM; } - return hr; + WARN("not fully functional\n"); + *lpdwSpeakerConfig = device->speaker_config; + return DS_OK; } -/******************************************************************************* - * DirectSoundCreate8 (DSOUND.11) - * - * Creates and initializes a DirectSound8 interface. - * - * PARAMS - * lpcGUID [I] Address of the GUID that identifies the sound device. - * ppDS [O] Address of a variable to receive the interface pointer. - * pUnkOuter [I] Must be NULL. - * - * RETURNS - * Success: DS_OK - * Failure: DSERR_ALLOCATED, DSERR_INVALIDPARAM, DSERR_NOAGGREGATION, - * DSERR_NODRIVER, DSERR_OUTOFMEMORY - */ -HRESULT WINAPI DirectSoundCreate8( - LPCGUID lpcGUID, - LPDIRECTSOUND8 *ppDS, - IUnknown *pUnkOuter) +HRESULT DirectSoundDevice_SetSpeakerConfig( + DirectSoundDevice * device, + DWORD config) { - HRESULT hr; - LPDIRECTSOUND8 pDS; - - TRACE("(%s,%p,%p)\n",debugstr_guid(lpcGUID),ppDS,pUnkOuter); + TRACE("(%p,0x%08x)\n",device,config); - if (ppDS == NULL) { - WARN("invalid parameter: ppDS == NULL\n"); - return DSERR_INVALIDPARAM; + if (device == NULL) { + WARN("not initialized\n"); + return DSERR_UNINITIALIZED; } - if (pUnkOuter != NULL) { - WARN("invalid parameter: pUnkOuter != NULL\n"); - *ppDS = 0; - return DSERR_INVALIDPARAM; - } + device->speaker_config = config; + WARN("not fully functional\n"); + return DS_OK; +} - hr = DSOUND_Create8(&pDS, pUnkOuter); - if (hr == DS_OK) { - hr = IDirectSound8_Initialize(pDS, lpcGUID); - if (hr != DS_OK) { - if (hr != DSERR_ALREADYINITIALIZED) { - IDirectSound8_Release(pDS); - pDS = 0; - } else - hr = DS_OK; - } +static HRESULT DirectSoundDevice_VerifyCertification( + DirectSoundDevice * device, + LPDWORD pdwCertified) +{ + TRACE("(%p, %p)\n",device,pdwCertified); + + if (device == NULL) { + WARN("not initialized\n"); + return DSERR_UNINITIALIZED; } - *ppDS = pDS; + if (device->drvcaps.dwFlags & DSCAPS_CERTIFIED) + *pdwCertified = DS_CERTIFIED; + else + *pdwCertified = DS_UNCERTIFIED; - return hr; + return DS_OK; } /* * Add secondary buffer to buffer list. * Gets exclusive access to buffer for writing. */ -HRESULT DSOUND_AddBuffer( - IDirectSoundImpl * pDS, +HRESULT DirectSoundDevice_AddBuffer( + DirectSoundDevice * device, IDirectSoundBufferImpl * pDSB) { IDirectSoundBufferImpl **newbuffers; HRESULT hr = DS_OK; - TRACE("(%p, %p)\n", pDS, pDSB); + TRACE("(%p, %p)\n", device, pDSB); - RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE); + RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); - if (pDS->device->buffers) - newbuffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1)); + if (device->buffers) + newbuffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1)); else - newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(pDS->device->nrofbuffers+1)); + newbuffers = HeapAlloc(GetProcessHeap(),0,sizeof(IDirectSoundBufferImpl*)*(device->nrofbuffers+1)); if (newbuffers) { - pDS->device->buffers = newbuffers; - pDS->device->buffers[pDS->device->nrofbuffers] = pDSB; - pDS->device->nrofbuffers++; - TRACE("buffer count is now %d\n", pDS->device->nrofbuffers); + device->buffers = newbuffers; + device->buffers[device->nrofbuffers] = pDSB; + device->nrofbuffers++; + TRACE("buffer count is now %d\n", device->nrofbuffers); } else { - ERR("out of memory for buffer list! Current buffer count is %d\n", pDS->device->nrofbuffers); + ERR("out of memory for buffer list! Current buffer count is %d\n", device->nrofbuffers); hr = DSERR_OUTOFMEMORY; } - RtlReleaseResource(&(pDS->device->buffer_list_lock)); + RtlReleaseResource(&(device->buffer_list_lock)); return hr; } @@ -1875,35 +1829,35 @@ HRESULT DSOUND_AddBuffer( * Remove secondary buffer from buffer list. * Gets exclusive access to buffer for writing. */ -HRESULT DSOUND_RemoveBuffer( - IDirectSoundImpl * pDS, +HRESULT DirectSoundDevice_RemoveBuffer( + DirectSoundDevice * device, IDirectSoundBufferImpl * pDSB) { int i; HRESULT hr = DS_OK; - TRACE("(%p, %p)\n", pDS, pDSB); + TRACE("(%p, %p)\n", device, pDSB); - RtlAcquireResourceExclusive(&(pDS->device->buffer_list_lock), TRUE); + RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); - for (i = 0; i < pDS->device->nrofbuffers; i++) - if (pDS->device->buffers[i] == pDSB) + for (i = 0; i < device->nrofbuffers; i++) + if (device->buffers[i] == pDSB) break; - if (i < pDS->device->nrofbuffers) { + if (i < device->nrofbuffers) { /* Put the last buffer of the list in the (now empty) position */ - pDS->device->buffers[i] = pDS->device->buffers[pDS->device->nrofbuffers - 1]; - pDS->device->nrofbuffers--; - pDS->device->buffers = HeapReAlloc(GetProcessHeap(),0,pDS->device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*pDS->device->nrofbuffers); - TRACE("buffer count is now %d\n", pDS->device->nrofbuffers); + device->buffers[i] = device->buffers[device->nrofbuffers - 1]; + device->nrofbuffers--; + device->buffers = HeapReAlloc(GetProcessHeap(),0,device->buffers,sizeof(LPDIRECTSOUNDBUFFER8)*device->nrofbuffers); + TRACE("buffer count is now %d\n", device->nrofbuffers); } - if (pDS->device->nrofbuffers == 0) { - HeapFree(GetProcessHeap(),0,pDS->device->buffers); - pDS->device->buffers = NULL; + if (device->nrofbuffers == 0) { + HeapFree(GetProcessHeap(),0,device->buffers); + device->buffers = NULL; } - RtlReleaseResource(&(pDS->device->buffer_list_lock)); + RtlReleaseResource(&(device->buffer_list_lock)); return hr; } diff --git a/reactos/dll/directx/dsound/dsound.rbuild b/reactos/dll/directx/dsound/dsound.rbuild index 6123c420c1b..c76e412d415 100644 --- a/reactos/dll/directx/dsound/dsound.rbuild +++ b/reactos/dll/directx/dsound/dsound.rbuild @@ -18,6 +18,7 @@ buffer.c capture.c dsound.c + dsound_convert.c dsound_main.c duplex.c mixer.c @@ -25,10 +26,4 @@ propset.c regsvr.c sound3d.c - - dxrosdrv_querydsounddesc.c - dxrosdrv_querydsoundiface.c - dxroslayer.c - getguidfromstring.c - diff --git a/reactos/dll/directx/dsound/dsound_convert.c b/reactos/dll/directx/dsound/dsound_convert.c new file mode 100644 index 00000000000..0a6e474d09d --- /dev/null +++ b/reactos/dll/directx/dsound/dsound_convert.c @@ -0,0 +1,435 @@ +/* DirectSound format conversion and mixing routines + * + * Copyright 2007 Maarten Lankhorst + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* 8 bits is unsigned, the rest is signed. + * First I tried to reuse existing stuff from alsa-lib, after that + * didn't work, I gave up and just went for individual hacks. + * + * 24 bit is expensive to do, due to unaligned access. + * In dlls/winex11.drv/dib_convert.c convert_888_to_0888_asis there is a way + * around it, but I'm happy current code works, maybe something for later. + * + * The ^ 0x80 flips the signed bit, this is the conversion from + * signed (-128.. 0.. 127) to unsigned (0...255) + * This is only temporary: All 8 bit data should be converted to signed. + * then when fed to the sound card, it should be converted to unsigned again. + * + * Sound is LITTLE endian + */ + +#include "config.h" + +#include + +#define NONAMELESSSTRUCT +#define NONAMELESSUNION +#include "windef.h" +#include "winbase.h" +#include "mmsystem.h" +#include "winternl.h" +#include "wine/debug.h" +#include "dsound.h" +#include "dsdriver.h" +#include "dsound_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(dsound); + +#ifdef WORDS_BIGENDIAN +#define le16(x) RtlUshortByteSwap((x)) +#define le32(x) RtlUlongByteSwap((x)) +#else +#define le16(x) (x) +#define le32(x) (x) +#endif + +static inline void src_advance(const void **src, UINT stride, INT *count, UINT *freqAcc, UINT adj) +{ + *freqAcc += adj; + if (*freqAcc >= (1 << DSOUND_FREQSHIFT)) + { + ULONG adv = (*freqAcc >> DSOUND_FREQSHIFT); + *freqAcc &= (1 << DSOUND_FREQSHIFT) - 1; + *(const char **)src += adv * stride; + *count -= adv; + } +} + +static void convert_8_to_8 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + *(BYTE *)dst = *(const BYTE *)src; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_8_to_16 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + WORD dest = *(const BYTE *)src, *dest16 = dst; + *dest16 = le16(dest * 257 - 32768); + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_8_to_24 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + BYTE dest = *(const BYTE *)src; + BYTE *dest24 = dst; + dest24[0] = dest; + dest24[1] = dest; + dest24[2] = dest - 0x80; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_8_to_32 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + DWORD dest = *(const BYTE *)src, *dest32 = dst; + *dest32 = le32(dest * 16843009 - 2147483648U); + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_16_to_8 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + BYTE *dst8 = dst; + *dst8 = (le16(*(const WORD *)src)) / 256; + *dst8 -= 0x80; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_16_to_16 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + *(WORD *)dst = *(const WORD *)src; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_16_to_24 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + WORD dest = le16(*(const WORD *)src); + BYTE *dest24 = dst; + + dest24[0] = dest / 256; + dest24[1] = dest; + dest24[2] = dest / 256; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_16_to_32 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + DWORD dest = *(const WORD *)src, *dest32 = dst; + *dest32 = dest * 65537; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_24_to_8 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + BYTE *dst8 = dst; + *dst8 = ((const BYTE *)src)[2]; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_24_to_16 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + WORD *dest16 = dst; + const BYTE *source = src; + *dest16 = le16(source[2] * 256 + source[1]); + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_24_to_24 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + BYTE *dest24 = dst; + const BYTE *src24 = src; + + dest24[0] = src24[0]; + dest24[1] = src24[1]; + dest24[2] = src24[2]; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_24_to_32 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + DWORD *dest32 = dst; + const BYTE *source = src; + *dest32 = le32(source[2] * 16777217 + source[1] * 65536 + source[0] * 256); + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_32_to_8 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + BYTE *dst8 = dst; + *dst8 = (le32(*(const DWORD *)src) / 16777216); + *dst8 -= 0x80; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_32_to_16 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + WORD *dest16 = dst; + *dest16 = le16(le32(*(const DWORD *)src) / 65536); + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_32_to_24 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + DWORD dest = le32(*(const DWORD *)src); + BYTE *dest24 = dst; + + dest24[0] = dest / 256; + dest24[1] = dest / 65536; + dest24[2] = dest / 16777216; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +static void convert_32_to_32 (const void *src, void *dst, UINT src_stride, + UINT dst_stride, INT count, UINT freqAcc, UINT adj) +{ + while (count > 0) + { + DWORD *dest = dst; + *dest = *(const DWORD *)src; + + dst = (char *)dst + dst_stride; + src_advance(&src, src_stride, &count, &freqAcc, adj); + } +} + +const bitsconvertfunc convertbpp[4][4] = { + { convert_8_to_8, convert_8_to_16, convert_8_to_24, convert_8_to_32 }, + { convert_16_to_8, convert_16_to_16, convert_16_to_24, convert_16_to_32 }, + { convert_24_to_8, convert_24_to_16, convert_24_to_24, convert_24_to_32 }, + { convert_32_to_8, convert_32_to_16, convert_32_to_24, convert_32_to_32 }, +}; + +static void mix8(signed char *src, INT *dst, unsigned len) +{ + TRACE("%p - %p %d\n", src, dst, len); + while (len--) + /* 8-bit WAV is unsigned, it's here converted to signed, normalize function will convert it back again */ + *(dst++) += (signed char)((BYTE)*(src++) - (BYTE)0x80); +} + +static void mix16(SHORT *src, INT *dst, unsigned len) +{ + TRACE("%p - %p %d\n", src, dst, len); + len /= 2; + while (len--) + { + *dst += le16(*src); + ++dst; ++src; + } +} + +static void mix24(BYTE *src, INT *dst, unsigned len) +{ + TRACE("%p - %p %d\n", src, dst, len); + len /= 3; + while (len--) + { + DWORD field; + field = ((DWORD)src[2] << 16) + ((DWORD)src[1] << 8) + (DWORD)src[0]; + if (src[2] & 0x80) + field |= 0xFF000000U; + *(dst++) += field; + ++src; + } +} + +static void mix32(INT *src, LONGLONG *dst, unsigned len) +{ + TRACE("%p - %p %d\n", src, dst, len); + len /= 4; + while (len--) + *(dst++) += le32(*(src++)); +} + +const mixfunc mixfunctions[4] = { + (mixfunc)mix8, + (mixfunc)mix16, + (mixfunc)mix24, + (mixfunc)mix32 +}; + +static void norm8(INT *src, signed char *dst, unsigned len) +{ + TRACE("%p - %p %d\n", src, dst, len); + while (len--) + { + *dst = (*src) + 0x80; + if (*src < -0x80) + *dst = 0; + else if (*src > 0x7f) + *dst = 0xff; + ++dst; + ++src; + } +} + +static void norm16(INT *src, SHORT *dst, unsigned len) +{ + TRACE("%p - %p %d\n", src, dst, len); + len /= 2; + while (len--) + { + *dst = le16(*src); + if (*src <= -0x8000) + *dst = le16(0x8000); + else if (*src > 0x7fff) + *dst = le16(0x7fff); + ++dst; + ++src; + } +} + +static void norm24(INT *src, BYTE *dst, unsigned len) +{ + TRACE("%p - %p %d\n", src, dst, len); + len /= 3; + while (len--) + { + if (*src <= -0x800000) + { + dst[0] = 0; + dst[1] = 0; + dst[2] = 0x80; + } + else if (*src > 0x7fffff) + { + dst[0] = 0xff; + dst[1] = 0xff; + dst[2] = 0x7f; + } + else + { + dst[0] = *src; + dst[1] = *src >> 8; + dst[2] = *src >> 16; + } + ++dst; + ++src; + } +} + +static void norm32(LONGLONG *src, INT *dst, unsigned len) +{ + TRACE("%p - %p %d\n", src, dst, len); + len /= 4; + while (len--) + { + *dst = le32(*src); + if (*src <= -(LONGLONG)0x80000000) + *dst = le32(0x80000000); + else if (*src > 0x7fffffff) + *dst = le32(0x7fffffff); + ++dst; + ++src; + } +} + +const normfunc normfunctions[4] = { + (normfunc)norm8, + (normfunc)norm16, + (normfunc)norm24, + (normfunc)norm32, +}; diff --git a/reactos/dll/directx/dsound/dsound_main.c b/reactos/dll/directx/dsound/dsound_main.c index f8b763f9b9f..44897bc9946 100644 --- a/reactos/dll/directx/dsound/dsound_main.c +++ b/reactos/dll/directx/dsound/dsound_main.c @@ -16,15 +16,11 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + * * Most thread locking is complete. There may be a few race * conditions still lurking. * - * Tested with a Soundblaster clone, a Gravis UltraSound Classic, - * and a Turtle Beach Tropez+. - * * TODO: * Implement SetCooperativeLevel properly (need to address focus issues) * Implement DirectSound3DBuffers (stubs in place) @@ -32,8 +28,8 @@ * Add critical section locking inside Release and AddRef methods * Handle static buffers - put those in hardware, non-static not in hardware * Hardware DuplicateSoundBuffer - * Proper volume calculation, and setting volume in HEL primary buffer - * Optimize WINMM and negotiate fragment size, decrease DS_HEL_MARGIN + * Proper volume calculation for 3d buffers + * Remove DS_HEL_FRAGS and use mixer fragment length for it */ #include @@ -43,6 +39,7 @@ #define NONAMELESSUNION #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "winnls.h" #include "winreg.h" #include "mmsystem.h" @@ -50,24 +47,16 @@ #include "mmddk.h" #include "wine/debug.h" #include "dsound.h" +#include "dsconf.h" +#include "ks.h" +#include "initguid.h" +#include "ksmedia.h" #include "dsdriver.h" + #include "dsound_private.h" -#include "dsconf.h" WINE_DEFAULT_DEBUG_CHANNEL(dsound); -/* these are eligible for tuning... they must be high on slow machines... */ -/* some stuff may get more responsive with lower values though... */ -#define DS_EMULDRIVER 0 /* some games (Quake 2, UT) refuse to accept - emulated dsound devices. set to 0 ! */ -#define DS_HEL_MARGIN 5 /* HEL only: number of waveOut fragments ahead to mix in new buffers - * (keep this close or equal to DS_HEL_QUEUE for best results) */ -#define DS_HEL_QUEUE 5 /* HEL only: number of waveOut fragments ahead to queue to driver - * (this will affect HEL sound reliability and latency) */ - -#define DS_SND_QUEUE_MAX 28 /* max number of fragments to prebuffer */ -#define DS_SND_QUEUE_MIN 12 /* min number of fragments to prebuffer */ - DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS]; GUID DSOUND_renderer_guids[MAXWAVEDRIVERS]; GUID DSOUND_capture_guids[MAXWAVEDRIVERS]; @@ -99,20 +88,23 @@ HRESULT mmErr(UINT err) } } -int ds_emuldriver = DS_EMULDRIVER; -int ds_hel_margin = DS_HEL_MARGIN; -int ds_hel_queue = DS_HEL_QUEUE; -int ds_snd_queue_max = DS_SND_QUEUE_MAX; -int ds_snd_queue_min = DS_SND_QUEUE_MIN; +/* All default settings, you most likely don't want to touch these, see wiki on UsefulRegistryKeys */ +int ds_emuldriver = 0; +int ds_hel_buflen = 32768 * 2; +int ds_snd_queue_max = 10; +int ds_snd_queue_min = 6; +int ds_snd_shadow_maxsize = 2; int ds_hw_accel = DS_HW_ACCEL_FULL; -int ds_default_playback = 0; -int ds_default_capture = 0; +int ds_default_sample_rate = 44100; +int ds_default_bits_per_sample = 16; +static int ds_default_playback; +static int ds_default_capture; /* * Get a config key from either the app-specific or the default config */ -inline static DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name, +static inline DWORD get_config_key( HKEY defkey, HKEY appkey, const char *name, char *buffer, DWORD size ) { if (appkey && !RegQueryValueExA( appkey, name, 0, NULL, (LPBYTE)buffer, &size )) return 0; @@ -147,7 +139,7 @@ void setup_dsound_options(void) if ((p = strrchr( appname, '/' ))) appname = p + 1; if ((p = strrchr( appname, '\\' ))) appname = p + 1; strcat( appname, "\\DirectSound" ); - TRACE("appname = [%s] \n",appname); + TRACE("appname = [%s]\n", appname); if (RegOpenKeyA( tmpkey, appname, &appkey )) appkey = 0; RegCloseKey( tmpkey ); } @@ -158,11 +150,8 @@ void setup_dsound_options(void) if (!get_config_key( hkey, appkey, "EmulDriver", buffer, MAX_PATH )) ds_emuldriver = strcmp(buffer, "N"); - if (!get_config_key( hkey, appkey, "HELmargin", buffer, MAX_PATH )) - ds_hel_margin = atoi(buffer); - - if (!get_config_key( hkey, appkey, "HELqueue", buffer, MAX_PATH )) - ds_hel_queue = atoi(buffer); + if (!get_config_key( hkey, appkey, "HelBuflen", buffer, MAX_PATH )) + ds_hel_buflen = atoi(buffer); if (!get_config_key( hkey, appkey, "SndQueueMax", buffer, MAX_PATH )) ds_snd_queue_max = atoi(buffer); @@ -180,42 +169,43 @@ void setup_dsound_options(void) else if (strcmp(buffer, "Emulation") == 0) ds_hw_accel = DS_HW_ACCEL_EMULATION; } - FIXME("dsound is hardcoded to software emulation until we fix it in ros\n"); - ds_hw_accel = DS_HW_ACCEL_EMULATION; if (!get_config_key( hkey, appkey, "DefaultPlayback", buffer, MAX_PATH )) - ds_default_playback = atoi(buffer); + ds_default_playback = atoi(buffer); + + if (!get_config_key( hkey, appkey, "MaxShadowSize", buffer, MAX_PATH )) + ds_snd_shadow_maxsize = atoi(buffer); if (!get_config_key( hkey, appkey, "DefaultCapture", buffer, MAX_PATH )) - ds_default_capture = atoi(buffer); + ds_default_capture = atoi(buffer); + + if (!get_config_key( hkey, appkey, "DefaultSampleRate", buffer, MAX_PATH )) + ds_default_sample_rate = atoi(buffer); + + if (!get_config_key( hkey, appkey, "DefaultBitsPerSample", buffer, MAX_PATH )) + ds_default_bits_per_sample = atoi(buffer); if (appkey) RegCloseKey( appkey ); if (hkey) RegCloseKey( hkey ); - if (ds_emuldriver != DS_EMULDRIVER ) - WARN("ds_emuldriver = %d (default=%d)\n",ds_emuldriver, DS_EMULDRIVER); - if (ds_hel_margin != DS_HEL_MARGIN ) - WARN("ds_hel_margin = %d (default=%d)\n",ds_hel_margin, DS_HEL_MARGIN ); - if (ds_hel_queue != DS_HEL_QUEUE ) - WARN("ds_hel_queue = %d (default=%d)\n",ds_hel_queue, DS_HEL_QUEUE ); - if (ds_snd_queue_max != DS_SND_QUEUE_MAX) - WARN("ds_snd_queue_max = %d (default=%d)\n",ds_snd_queue_max ,DS_SND_QUEUE_MAX); - if (ds_snd_queue_min != DS_SND_QUEUE_MIN) - WARN("ds_snd_queue_min = %d (default=%d)\n",ds_snd_queue_min ,DS_SND_QUEUE_MIN); - if (ds_hw_accel != DS_HW_ACCEL_FULL) - WARN("ds_hw_accel = %s (default=Full)\n", - ds_hw_accel==DS_HW_ACCEL_FULL ? "Full" : - ds_hw_accel==DS_HW_ACCEL_STANDARD ? "Standard" : - ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" : - ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" : - "Unknown"); - if (ds_default_playback != 0) - WARN("ds_default_playback = %d (default=0)\n",ds_default_playback); - if (ds_default_capture != 0) - WARN("ds_default_capture = %d (default=0)\n",ds_default_playback); + TRACE("ds_emuldriver = %d\n", ds_emuldriver); + TRACE("ds_hel_buflen = %d\n", ds_hel_buflen); + TRACE("ds_snd_queue_max = %d\n", ds_snd_queue_max); + TRACE("ds_snd_queue_min = %d\n", ds_snd_queue_min); + TRACE("ds_hw_accel = %s\n", + ds_hw_accel==DS_HW_ACCEL_FULL ? "Full" : + ds_hw_accel==DS_HW_ACCEL_STANDARD ? "Standard" : + ds_hw_accel==DS_HW_ACCEL_BASIC ? "Basic" : + ds_hw_accel==DS_HW_ACCEL_EMULATION ? "Emulation" : + "Unknown"); + TRACE("ds_default_playback = %d\n", ds_default_playback); + TRACE("ds_default_capture = %d\n", ds_default_playback); + TRACE("ds_default_sample_rate = %d\n", ds_default_sample_rate); + TRACE("ds_default_bits_per_sample = %d\n", ds_default_bits_per_sample); + TRACE("ds_snd_shadow_maxsize = %d\n", ds_snd_shadow_maxsize); } -const char * get_device_id(LPCGUID pGuid) +static const char * get_device_id(LPCGUID pGuid) { if (IsEqualGUID(&DSDEVID_DefaultPlayback, pGuid)) return "DSDEVID_DefaultPlayback"; @@ -264,19 +254,19 @@ HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest) if ( IsEqualGUID( &DSDEVID_DefaultPlayback, pGuidSrc ) || IsEqualGUID( &DSDEVID_DefaultVoicePlayback, pGuidSrc ) ) { - CopyMemory(pGuidDest, &DSOUND_renderer_guids[ds_default_playback], sizeof(GUID)); + *pGuidDest = DSOUND_renderer_guids[ds_default_playback]; TRACE("returns %s\n", get_device_id(pGuidDest)); return DS_OK; } if ( IsEqualGUID( &DSDEVID_DefaultCapture, pGuidSrc ) || IsEqualGUID( &DSDEVID_DefaultVoiceCapture, pGuidSrc ) ) { - CopyMemory(pGuidDest, &DSOUND_capture_guids[ds_default_capture], sizeof(GUID)); + *pGuidDest = DSOUND_capture_guids[ds_default_capture]; TRACE("returns %s\n", get_device_id(pGuidDest)); return DS_OK; } - CopyMemory(pGuidDest, pGuidSrc, sizeof(GUID)); + *pGuidDest = *pGuidSrc; TRACE("returns %s\n", get_device_id(pGuidDest)); return DS_OK; @@ -318,11 +308,11 @@ HRESULT WINAPI DirectSoundEnumerateA( if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) { for (wod = 0; wod < devs; ++wod) { if (IsEqualGUID( &guid, &DSOUND_renderer_guids[wod]) ) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", - "Primary Sound Driver",desc.szDrvname,lpContext); - if (lpDSEnumCallback(NULL, "Primary Sound Driver", desc.szDrvname, lpContext) == FALSE) + "Primary Sound Driver","",lpContext); + if (lpDSEnumCallback(NULL, "Primary Sound Driver", "", lpContext) == FALSE) return DS_OK; } } @@ -331,7 +321,7 @@ HRESULT WINAPI DirectSoundEnumerateA( } for (wod = 0; wod < devs; ++wod) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", debugstr_guid(&DSOUND_renderer_guids[wod]),desc.szDesc,desc.szDrvname,lpContext); @@ -377,17 +367,16 @@ HRESULT WINAPI DirectSoundEnumerateW( devs = waveOutGetNumDevs(); if (devs > 0) { if (GetDeviceID(&DSDEVID_DefaultPlayback, &guid) == DS_OK) { + static const WCHAR empty[] = { 0 }; for (wod = 0; wod < devs; ++wod) { if (IsEqualGUID( &guid, &DSOUND_renderer_guids[wod] ) ) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(NULL,\"%s\",\"%s\",%p)\n", "Primary Sound Driver",desc.szDrvname,lpContext); MultiByteToWideChar( CP_ACP, 0, "Primary Sound Driver", -1, wDesc, sizeof(wDesc)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, - wName, sizeof(wName)/sizeof(WCHAR) ); - if (lpDSEnumCallback(NULL, wDesc, wName, lpContext) == FALSE) + if (lpDSEnumCallback(NULL, wDesc, empty, lpContext) == FALSE) return DS_OK; } } @@ -396,7 +385,7 @@ HRESULT WINAPI DirectSoundEnumerateW( } for (wod = 0; wod < devs; ++wod) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { TRACE("calling lpDSEnumCallback(%s,\"%s\",\"%s\",%p)\n", debugstr_guid(&DSOUND_renderer_guids[wod]),desc.szDesc,desc.szDrvname,lpContext); @@ -415,19 +404,38 @@ HRESULT WINAPI DirectSoundEnumerateW( * DirectSound ClassFactory */ -static HRESULT WINAPI -DSCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; +typedef HRESULT (*FnCreateInstance)(REFIID riid, LPVOID *ppobj); + +typedef struct { + const IClassFactoryVtbl *lpVtbl; + LONG ref; + REFCLSID rclsid; + FnCreateInstance pfnCreateInstance; +} IClassFactoryImpl; - FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj); - return E_NOINTERFACE; +static HRESULT WINAPI +DSCF_QueryInterface(LPCLASSFACTORY iface, REFIID riid, LPVOID *ppobj) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + TRACE("(%p, %s, %p)\n", This, debugstr_guid(riid), ppobj); + if (ppobj == NULL) + return E_POINTER; + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IClassFactory)) + { + *ppobj = iface; + IUnknown_AddRef(iface); + return S_OK; + } + *ppobj = NULL; + return E_NOINTERFACE; } static ULONG WINAPI DSCF_AddRef(LPCLASSFACTORY iface) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -435,120 +443,55 @@ static ULONG WINAPI DSCF_Release(LPCLASSFACTORY iface) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); /* static class, won't be freed */ return ref; } static HRESULT WINAPI DSCF_CreateInstance( - LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj -) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); - - if (pOuter) - return CLASS_E_NOAGGREGATION; - - if (ppobj == NULL) { - WARN("invalid parameter\n"); - return DSERR_INVALIDPARAM; - } - - *ppobj = NULL; - - if ( IsEqualIID( &IID_IDirectSound, riid ) ) - return DSOUND_Create((LPDIRECTSOUND*)ppobj,pOuter); - - if ( IsEqualIID( &IID_IDirectSound8, riid ) ) - return DSOUND_Create8((LPDIRECTSOUND8*)ppobj,pOuter); - - WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj); - return E_NOINTERFACE; -} - -static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p)->(%d),stub!\n",This,dolock); - return S_OK; -} - -static const IClassFactoryVtbl DSCF_Vtbl = { - DSCF_QueryInterface, - DSCF_AddRef, - DSCF_Release, - DSCF_CreateInstance, - DSCF_LockServer -}; - -static IClassFactoryImpl DSOUND_CF = { &DSCF_Vtbl, 1 }; - -/******************************************************************************* - * DirectSoundPrivate ClassFactory - */ - -static HRESULT WINAPI -DSPCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - - FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj); - return E_NOINTERFACE; -} - -static ULONG WINAPI DSPCF_AddRef(LPCLASSFACTORY iface) -{ - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); - return ref; -} - -static ULONG WINAPI DSPCF_Release(LPCLASSFACTORY iface) + LPCLASSFACTORY iface, + LPUNKNOWN pOuter, + REFIID riid, + LPVOID *ppobj) { IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); - /* static class, won't be freed */ - return ref; -} - -static HRESULT WINAPI -DSPCF_CreateInstance( - LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj -) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); - - if (ppobj == NULL) { - WARN("invalid parameter\n"); - return DSERR_INVALIDPARAM; - } - - *ppobj = NULL; + TRACE("(%p, %p, %s, %p)\n", This, pOuter, debugstr_guid(riid), ppobj); - if ( IsEqualGUID( &IID_IKsPropertySet, riid ) ) { - return IKsPrivatePropertySetImpl_Create((IKsPrivatePropertySetImpl**)ppobj); - } + if (pOuter) + return CLASS_E_NOAGGREGATION; - WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj); - return E_NOINTERFACE; + if (ppobj == NULL) { + WARN("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } + *ppobj = NULL; + return This->pfnCreateInstance(riid, ppobj); } - -static HRESULT WINAPI -DSPCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p)->(%d),stub!\n",This,dolock); - return S_OK; + +static HRESULT WINAPI DSCF_LockServer(LPCLASSFACTORY iface, BOOL dolock) +{ + IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + FIXME("(%p, %d) stub!\n", This, dolock); + return S_OK; } -static const IClassFactoryVtbl DSPCF_Vtbl = { - DSPCF_QueryInterface, - DSPCF_AddRef, - DSPCF_Release, - DSPCF_CreateInstance, - DSPCF_LockServer +static const IClassFactoryVtbl DSCF_Vtbl = { + DSCF_QueryInterface, + DSCF_AddRef, + DSCF_Release, + DSCF_CreateInstance, + DSCF_LockServer }; -static IClassFactoryImpl DSOUND_PRIVATE_CF = { &DSPCF_Vtbl, 1 }; +static IClassFactoryImpl DSOUND_CF[] = { + { &DSCF_Vtbl, 1, &CLSID_DirectSound, (FnCreateInstance)DSOUND_Create }, + { &DSCF_Vtbl, 1, &CLSID_DirectSound8, (FnCreateInstance)DSOUND_Create8 }, + { &DSCF_Vtbl, 1, &CLSID_DirectSoundCapture, (FnCreateInstance)DSOUND_CaptureCreate }, + { &DSCF_Vtbl, 1, &CLSID_DirectSoundCapture8, (FnCreateInstance)DSOUND_CaptureCreate8 }, + { &DSCF_Vtbl, 1, &CLSID_DirectSoundFullDuplex, (FnCreateInstance)DSOUND_FullDuplexCreate }, + { &DSCF_Vtbl, 1, &CLSID_DirectSoundPrivate, (FnCreateInstance)IKsPrivatePropertySetImpl_Create }, + { NULL, 0, NULL, NULL } +}; /******************************************************************************* * DllGetClassObject [DSOUND.@] @@ -569,62 +512,33 @@ static IClassFactoryImpl DSOUND_PRIVATE_CF = { &DSPCF_Vtbl, 1 }; */ HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID *ppv) { - TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + int i = 0; + TRACE("(%s, %s, %p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); if (ppv == NULL) { - WARN("invalid parameter\n"); - return E_INVALIDARG; + WARN("invalid parameter\n"); + return E_INVALIDARG; } *ppv = NULL; - if ( IsEqualCLSID( &CLSID_DirectSound, rclsid ) || - IsEqualCLSID( &CLSID_DirectSound8, rclsid ) ) { - if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) { - *ppv = (LPVOID)&DSOUND_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } - WARN("(%s,%s,%p): no interface found.\n", - debugstr_guid(rclsid), debugstr_guid(riid), ppv); - return S_FALSE; + if (!IsEqualIID(riid, &IID_IClassFactory) && + !IsEqualIID(riid, &IID_IUnknown)) { + WARN("no interface for %s\n", debugstr_guid(riid)); + return E_NOINTERFACE; } - if ( IsEqualCLSID( &CLSID_DirectSoundCapture, rclsid ) || - IsEqualCLSID( &CLSID_DirectSoundCapture8, rclsid ) ) { - if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) { - *ppv = (LPVOID)&DSOUND_CAPTURE_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } - WARN("(%s,%s,%p): no interface found.\n", - debugstr_guid(rclsid), debugstr_guid(riid), ppv); - return S_FALSE; - } - - if ( IsEqualCLSID( &CLSID_DirectSoundFullDuplex, rclsid ) ) { - if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) { - *ppv = (LPVOID)&DSOUND_FULLDUPLEX_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } - WARN("(%s,%s,%p): no interface found.\n", - debugstr_guid(rclsid), debugstr_guid(riid), ppv); - return S_FALSE; - } - - if ( IsEqualCLSID( &CLSID_DirectSoundPrivate, rclsid ) ) { - if ( IsEqualCLSID( &IID_IClassFactory, riid ) ) { - *ppv = (LPVOID)&DSOUND_PRIVATE_CF; - IClassFactory_AddRef((IClassFactory*)*ppv); - return S_OK; - } - WARN("(%s,%s,%p): no interface found.\n", - debugstr_guid(rclsid), debugstr_guid(riid), ppv); - return S_FALSE; + while (NULL != DSOUND_CF[i].rclsid) { + if (IsEqualGUID(rclsid, DSOUND_CF[i].rclsid)) { + DSCF_AddRef((IClassFactory*) &DSOUND_CF[i]); + *ppv = &DSOUND_CF[i]; + return S_OK; + } + i++; } - WARN("(%s,%s,%p): no class found.\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv); + WARN("(%s, %s, %p): no class found.\n", debugstr_guid(rclsid), + debugstr_guid(riid), ppv); return CLASS_E_CLASSNOTAVAILABLE; } @@ -655,7 +569,7 @@ HRESULT WINAPI DllCanUnloadNow(void) BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) { int i; - TRACE("(%p %ld %p)\n", hInstDLL, fdwReason, lpvReserved); + TRACE("(%p %d %p)\n", hInstDLL, fdwReason, lpvReserved); switch (fdwReason) { case DLL_PROCESS_ATTACH: @@ -666,16 +580,13 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved) INIT_GUID(DSOUND_renderer_guids[i], 0xbd6dd71a, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i); INIT_GUID(DSOUND_capture_guids[i], 0xbd6dd71b, 0x3deb, 0x11d1, 0xb1, 0x71, 0x00, 0xc0, 0x4f, 0xc2, 0x00, 0x00 + i); } + DisableThreadLibraryCalls(hInstDLL); + /* Increase refcount on dsound by 1 */ + GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR)hInstDLL, &hInstDLL); break; case DLL_PROCESS_DETACH: TRACE("DLL_PROCESS_DETACH\n"); break; - case DLL_THREAD_ATTACH: - TRACE("DLL_THREAD_ATTACH\n"); - break; - case DLL_THREAD_DETACH: - TRACE("DLL_THREAD_DETACH\n"); - break; default: TRACE("UNKNOWN REASON\n"); break; diff --git a/reactos/dll/directx/dsound/dsound_private.h b/reactos/dll/directx/dsound/dsound_private.h index 8772e09b350..221433f24cb 100644 --- a/reactos/dll/directx/dsound/dsound_private.h +++ b/reactos/dll/directx/dsound/dsound_private.h @@ -16,20 +16,15 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ -#include "dxroslayer/dxros_layer.h" - /* Linux does not support better timing than 10ms */ -#define DS_TIME_RES 10 /* Resolution of multimedia timer */ +#define DS_TIME_RES 2 /* Resolution of multimedia timer */ #define DS_TIME_DEL 10 /* Delay of multimedia timer callback, and duration of HEL fragment */ -#define DS_HEL_FRAGS 48 /* HEL only: number of waveOut fragments in primary buffer - * (changing this won't help you) */ +#include "wine/list.h" -/* wine spec */ -#include "dxroslayer/dxros_layer.h" /* direct sound hardware acceleration levels */ #define DS_HW_ACCEL_FULL 0 /* default on Windows 98 */ #define DS_HW_ACCEL_STANDARD 1 /* default on Windows 2000 */ @@ -37,13 +32,13 @@ #define DS_HW_ACCEL_EMULATION 3 extern int ds_emuldriver; -extern int ds_hel_margin; -extern int ds_hel_queue; +extern int ds_hel_buflen; extern int ds_snd_queue_max; extern int ds_snd_queue_min; +extern int ds_snd_shadow_maxsize; extern int ds_hw_accel; -extern int ds_default_playback; -extern int ds_default_capture; +extern int ds_default_sample_rate; +extern int ds_default_bits_per_sample; /***************************************************************************** * Predeclare the interface implementation structures @@ -58,6 +53,10 @@ typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl; typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl; typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl; typedef struct IDirectSoundFullDuplexImpl IDirectSoundFullDuplexImpl; +typedef struct IDirectSoundFullDuplex_IUnknown IDirectSoundFullDuplex_IUnknown; +typedef struct IDirectSoundFullDuplex_IDirectSound IDirectSoundFullDuplex_IDirectSound; +typedef struct IDirectSoundFullDuplex_IDirectSound8 IDirectSoundFullDuplex_IDirectSound8; +typedef struct IDirectSoundFullDuplex_IDirectSoundCapture IDirectSoundFullDuplex_IDirectSoundCapture; typedef struct IDirectSoundNotifyImpl IDirectSoundNotifyImpl; typedef struct IDirectSoundCaptureNotifyImpl IDirectSoundCaptureNotifyImpl; typedef struct IDirectSound3DListenerImpl IDirectSound3DListenerImpl; @@ -66,25 +65,20 @@ typedef struct IKsBufferPropertySetImpl IKsBufferPropertySetImpl; typedef struct IKsPrivatePropertySetImpl IKsPrivatePropertySetImpl; typedef struct PrimaryBufferImpl PrimaryBufferImpl; typedef struct SecondaryBufferImpl SecondaryBufferImpl; -typedef struct IClassFactoryImpl IClassFactoryImpl; typedef struct DirectSoundDevice DirectSoundDevice; typedef struct DirectSoundCaptureDevice DirectSoundCaptureDevice; +/* dsound_convert.h */ +typedef void (*bitsconvertfunc)(const void *, void *, UINT, UINT, INT, UINT, UINT); +extern const bitsconvertfunc convertbpp[4][4]; +typedef void (*mixfunc)(const void *, void *, unsigned); +extern const mixfunc mixfunctions[4]; +typedef void (*normfunc)(const void *, void *, unsigned); +extern const normfunc normfunctions[4]; + /***************************************************************************** - * IDirectSound implementation structure + * IDirectSoundDevice implementation structure */ -struct IDirectSoundImpl -{ - /* IUnknown fields */ - const IDirectSound8Vtbl *lpVtbl; - LONG ref; - - DirectSoundDevice *device; - LPUNKNOWN pUnknown; - LPDIRECTSOUND pDS; - LPDIRECTSOUND8 pDS8; -}; - struct DirectSoundDevice { LONG ref; @@ -96,13 +90,12 @@ struct DirectSoundDevice DWORD priolevel; PWAVEFORMATEX pwfx; HWAVEOUT hwo; - LPWAVEHDR pwave[DS_HEL_FRAGS]; - UINT timerID, pwplay, pwwrite, pwqueue, prebuf, precount; + LPWAVEHDR pwave; + UINT timerID, pwplay, pwqueue, prebuf, helfrags; DWORD fraglen; PIDSDRIVERBUFFER hwbuf; LPBYTE buffer; DWORD writelead, buflen, state, playpos, mixpos; - BOOL need_remix; int nrofbuffers; IDirectSoundBufferImpl** buffers; RTL_RWLOCK buffer_list_lock; @@ -110,8 +103,13 @@ struct DirectSoundDevice PrimaryBufferImpl* primary; DSBUFFERDESC dsbd; DWORD speaker_config; - LPBYTE tmp_buffer; - DWORD tmp_buffer_len; + LPBYTE tmp_buffer, mix_buffer; + DWORD tmp_buffer_len, mix_buffer_len; + + DSVOLUMEPAN volpan; + + mixfunc mixfunction; + normfunc normfunction; /* DirectSound3DListener fields */ IDirectSound3DListenerImpl* listener; @@ -124,74 +122,41 @@ typedef struct BufferMemory { LONG ref; LPBYTE memory; + struct list buffers; } BufferMemory; -HRESULT WINAPI IDirectSoundImpl_Create( - LPDIRECTSOUND8 * ppds); - -HRESULT WINAPI DSOUND_Create( - LPDIRECTSOUND *ppDS, - IUnknown *pUnkOuter); - -HRESULT WINAPI DSOUND_Create8( - LPDIRECTSOUND8 *ppDS, - IUnknown *pUnkOuter); - -/***************************************************************************** - * IDirectSound COM components - */ -struct IDirectSound_IUnknown { - const IUnknownVtbl *lpVtbl; - LONG ref; - LPDIRECTSOUND8 pds; -}; - -HRESULT WINAPI IDirectSound_IUnknown_Create( - LPDIRECTSOUND8 pds, - LPUNKNOWN * ppunk); - -struct IDirectSound_IDirectSound { - const IDirectSoundVtbl *lpVtbl; - LONG ref; - LPDIRECTSOUND8 pds; -}; - -HRESULT WINAPI IDirectSound_IDirectSound_Create( - LPDIRECTSOUND8 pds, - LPDIRECTSOUND * ppds); - -/***************************************************************************** - * IDirectSound8 COM components - */ -struct IDirectSound8_IUnknown { - const IUnknownVtbl *lpVtbl; - LONG ref; - LPDIRECTSOUND8 pds; -}; - -HRESULT WINAPI IDirectSound8_IUnknown_Create( - LPDIRECTSOUND8 pds, - LPUNKNOWN * ppunk); - -struct IDirectSound8_IDirectSound { - const IDirectSoundVtbl *lpVtbl; - LONG ref; - LPDIRECTSOUND8 pds; -}; - -HRESULT WINAPI IDirectSound8_IDirectSound_Create( - LPDIRECTSOUND8 pds, - LPDIRECTSOUND * ppds); - -struct IDirectSound8_IDirectSound8 { - const IDirectSound8Vtbl *lpVtbl; - LONG ref; - LPDIRECTSOUND8 pds; -}; - -HRESULT WINAPI IDirectSound8_IDirectSound8_Create( - LPDIRECTSOUND8 pds, - LPDIRECTSOUND8 * ppds); +ULONG DirectSoundDevice_Release(DirectSoundDevice * device); +HRESULT DirectSoundDevice_Initialize( + DirectSoundDevice ** ppDevice, + LPCGUID lpcGUID); +HRESULT DirectSoundDevice_AddBuffer( + DirectSoundDevice * device, + IDirectSoundBufferImpl * pDSB); +HRESULT DirectSoundDevice_RemoveBuffer( + DirectSoundDevice * device, + IDirectSoundBufferImpl * pDSB); +HRESULT DirectSoundDevice_GetCaps(DirectSoundDevice * device, LPDSCAPS lpDSCaps); +HRESULT DirectSoundDevice_CreateSoundBuffer( + DirectSoundDevice * device, + LPCDSBUFFERDESC dsbd, + LPLPDIRECTSOUNDBUFFER ppdsb, + LPUNKNOWN lpunk, + BOOL from8); +HRESULT DirectSoundDevice_DuplicateSoundBuffer( + DirectSoundDevice * device, + LPDIRECTSOUNDBUFFER psb, + LPLPDIRECTSOUNDBUFFER ppdsb); +HRESULT DirectSoundDevice_SetCooperativeLevel( + DirectSoundDevice * devcie, + HWND hwnd, + DWORD level); +HRESULT DirectSoundDevice_Compact(DirectSoundDevice * device); +HRESULT DirectSoundDevice_GetSpeakerConfig( + DirectSoundDevice * device, + LPDWORD lpdwSpeakerConfig); +HRESULT DirectSoundDevice_SetSpeakerConfig( + DirectSoundDevice * device, + DWORD config); /***************************************************************************** * IDirectSoundBuffer implementation structure @@ -203,24 +168,23 @@ struct IDirectSoundBufferImpl const IDirectSoundBuffer8Vtbl *lpVtbl; LONG ref; /* IDirectSoundBufferImpl fields */ - SecondaryBufferImpl* dsb; - IDirectSoundImpl* dsound; - CRITICAL_SECTION lock; + SecondaryBufferImpl* secondary; + DirectSoundDevice* device; + RTL_RWLOCK lock; PIDSDRIVERBUFFER hwbuf; PWAVEFORMATEX pwfx; BufferMemory* buffer; + LPBYTE tmp_buffer; DWORD playflags,state,leadin; - DWORD playpos,startpos,writelead,buflen; + DWORD writelead,buflen; DWORD nAvgBytesPerSec; - DWORD freq; - DSVOLUMEPAN volpan, cvolpan; + DWORD freq, tmp_buffer_len, max_buffer_len; + DSVOLUMEPAN volpan; DSBUFFERDESC dsbd; /* used for frequency conversion (PerfectPitch) */ - ULONG freqAdjust, freqAcc; - /* used for intelligent (well, sort of) prebuffering */ - DWORD probably_valid_to, last_playpos; - DWORD primary_mixpos, buf_mixpos; - BOOL need_remix; + ULONG freqneeded, freqAdjust, freqAcc, freqAccNext, resampleinmixer; + /* used for mixing */ + DWORD primary_mixpos, buf_mixpos, sec_mixpos; /* IDirectSoundNotifyImpl fields */ IDirectSoundNotifyImpl* notify; @@ -236,13 +200,19 @@ struct IDirectSoundBufferImpl /* IKsPropertySet fields */ IKsBufferPropertySetImpl* iks; + bitsconvertfunc convert; + struct list entry; }; -HRESULT WINAPI IDirectSoundBufferImpl_Create( - IDirectSoundImpl *ds, - IDirectSoundBufferImpl **pdsb, +HRESULT IDirectSoundBufferImpl_Create( + DirectSoundDevice *device, + IDirectSoundBufferImpl **ppdsb, LPCDSBUFFERDESC dsbd); -HRESULT WINAPI IDirectSoundBufferImpl_Destroy( +HRESULT IDirectSoundBufferImpl_Destroy( + IDirectSoundBufferImpl *pdsb); +HRESULT IDirectSoundBufferImpl_Duplicate( + DirectSoundDevice *device, + IDirectSoundBufferImpl **ppdsb, IDirectSoundBufferImpl *pdsb); /***************************************************************************** @@ -255,39 +225,28 @@ struct SecondaryBufferImpl IDirectSoundBufferImpl* dsb; }; -HRESULT WINAPI SecondaryBufferImpl_Create( +HRESULT SecondaryBufferImpl_Create( IDirectSoundBufferImpl *dsb, SecondaryBufferImpl **pdsb); -HRESULT WINAPI SecondaryBufferImpl_Destroy( - SecondaryBufferImpl *pdsb); /***************************************************************************** * PrimaryBuffer implementation structure */ struct PrimaryBufferImpl { - const IDirectSoundBuffer8Vtbl *lpVtbl; + const IDirectSoundBufferVtbl *lpVtbl; LONG ref; - IDirectSoundImpl* dsound; + DirectSoundDevice* device; }; -HRESULT WINAPI PrimaryBufferImpl_Create( - IDirectSoundImpl *ds, - PrimaryBufferImpl **pdsb, +HRESULT PrimaryBufferImpl_Create( + DirectSoundDevice * device, + PrimaryBufferImpl **ppdsb, LPCDSBUFFERDESC dsbd); /***************************************************************************** - * IDirectSoundCapture implementation structure + * DirectSoundCaptureDevice implementation structure */ -struct IDirectSoundCaptureImpl -{ - /* IUnknown fields */ - const IDirectSoundCaptureVtbl *lpVtbl; - LONG ref; - - DirectSoundCaptureDevice *device; -}; - struct DirectSoundCaptureDevice { /* IDirectSoundCaptureImpl fields */ @@ -306,7 +265,6 @@ struct DirectSoundCaptureDevice /* more stuff */ LPBYTE buffer; DWORD buflen; - DWORD read_position; PWAVEFORMATEX pwfx; @@ -318,16 +276,11 @@ struct DirectSoundCaptureDevice CRITICAL_SECTION lock; }; -HRESULT WINAPI IDirectSoundCaptureImpl_Create( - LPDIRECTSOUNDCAPTURE8 * ppds); - -HRESULT WINAPI DSOUND_CaptureCreate( - LPDIRECTSOUNDCAPTURE *ppDSC, - IUnknown *pUnkOuter); - -HRESULT WINAPI DSOUND_CaptureCreate8( - LPDIRECTSOUNDCAPTURE8 *ppDSC8, - IUnknown *pUnkOuter); +HRESULT DirectSoundCaptureDevice_Initialize( + DirectSoundCaptureDevice ** ppDevice, + LPCGUID lpcGUID); +ULONG DirectSoundCaptureDevice_Release( + DirectSoundCaptureDevice * device); /***************************************************************************** * IDirectSoundCaptureBuffer implementation structure @@ -339,7 +292,7 @@ struct IDirectSoundCaptureBufferImpl LONG ref; /* IDirectSoundCaptureBufferImpl fields */ - IDirectSoundCaptureImpl* dsound; + DirectSoundCaptureDevice* device; /* FIXME: don't need this */ LPDSCBUFFERDESC pdscbd; DWORD flags; @@ -351,6 +304,11 @@ struct IDirectSoundCaptureBufferImpl PIDSDRIVERNOTIFY hwnotify; }; +HRESULT IDirectSoundCaptureBufferImpl_Create( + DirectSoundCaptureDevice *device, + IDirectSoundCaptureBufferImpl ** ppobj, + LPCDSCBUFFERDESC lpcDSCBufferDesc); + /***************************************************************************** * IDirectSoundFullDuplex implementation structure */ @@ -358,43 +316,44 @@ struct IDirectSoundFullDuplexImpl { /* IUnknown fields */ const IDirectSoundFullDuplexVtbl *lpVtbl; - LONG ref; + LONG ref; /* IDirectSoundFullDuplexImpl fields */ - CRITICAL_SECTION lock; + DirectSoundDevice *renderer_device; + DirectSoundCaptureDevice *capture_device; + + LPUNKNOWN pUnknown; + LPDIRECTSOUND pDS; + LPDIRECTSOUND8 pDS8; + LPDIRECTSOUNDCAPTURE pDSC; }; /***************************************************************************** - * IDirectSoundNotify implementation structure + * IDirectSoundFullDuplex COM components */ -struct IDirectSoundNotifyImpl -{ - /* IUnknown fields */ - const IDirectSoundNotifyVtbl *lpVtbl; +struct IDirectSoundFullDuplex_IUnknown { + const IUnknownVtbl *lpVtbl; LONG ref; - IDirectSoundBufferImpl* dsb; + IDirectSoundFullDuplexImpl *pdsfd; }; -HRESULT WINAPI IDirectSoundNotifyImpl_Create( - IDirectSoundBufferImpl *dsb, - IDirectSoundNotifyImpl **pdsn); -HRESULT WINAPI IDirectSoundNotifyImpl_Destroy( - IDirectSoundNotifyImpl *pdsn); +struct IDirectSoundFullDuplex_IDirectSound { + const IDirectSoundVtbl *lpVtbl; + LONG ref; + IDirectSoundFullDuplexImpl *pdsfd; +}; -/***************************************************************************** - * IDirectSoundCaptureNotify implementation structure - */ -struct IDirectSoundCaptureNotifyImpl -{ - /* IUnknown fields */ - const IDirectSoundNotifyVtbl *lpVtbl; - LONG ref; - IDirectSoundCaptureBufferImpl* dscb; +struct IDirectSoundFullDuplex_IDirectSound8 { + const IDirectSound8Vtbl *lpVtbl; + LONG ref; + IDirectSoundFullDuplexImpl *pdsfd; }; -HRESULT WINAPI IDirectSoundCaptureNotifyImpl_Create( - IDirectSoundCaptureBufferImpl *dscb, - IDirectSoundCaptureNotifyImpl ** pdscn); +struct IDirectSoundFullDuplex_IDirectSoundCapture { + const IDirectSoundCaptureVtbl *lpVtbl; + LONG ref; + IDirectSoundFullDuplexImpl *pdsfd; +}; /***************************************************************************** * IDirectSound3DListener implementation structure @@ -405,11 +364,11 @@ struct IDirectSound3DListenerImpl const IDirectSound3DListenerVtbl *lpVtbl; LONG ref; /* IDirectSound3DListenerImpl fields */ - IDirectSoundImpl* dsound; + DirectSoundDevice* device; }; -HRESULT WINAPI IDirectSound3DListenerImpl_Create( - PrimaryBufferImpl *pb, +HRESULT IDirectSound3DListenerImpl_Create( + DirectSoundDevice *device, IDirectSound3DListenerImpl **pdsl); /***************************************************************************** @@ -424,10 +383,10 @@ struct IKsBufferPropertySetImpl IDirectSoundBufferImpl* dsb; }; -HRESULT WINAPI IKsBufferPropertySetImpl_Create( +HRESULT IKsBufferPropertySetImpl_Create( IDirectSoundBufferImpl *dsb, IKsBufferPropertySetImpl **piks); -HRESULT WINAPI IKsBufferPropertySetImpl_Destroy( +HRESULT IKsBufferPropertySetImpl_Destroy( IKsBufferPropertySetImpl *piks); /***************************************************************************** @@ -440,7 +399,8 @@ struct IKsPrivatePropertySetImpl LONG ref; }; -HRESULT WINAPI IKsPrivatePropertySetImpl_Create( +HRESULT IKsPrivatePropertySetImpl_Create( + REFIID riid, IKsPrivatePropertySetImpl **piks); /***************************************************************************** @@ -455,67 +415,74 @@ struct IDirectSound3DBufferImpl IDirectSoundBufferImpl* dsb; }; -HRESULT WINAPI IDirectSound3DBufferImpl_Create( +HRESULT IDirectSound3DBufferImpl_Create( IDirectSoundBufferImpl *dsb, IDirectSound3DBufferImpl **pds3db); -HRESULT WINAPI IDirectSound3DBufferImpl_Destroy( +HRESULT IDirectSound3DBufferImpl_Destroy( IDirectSound3DBufferImpl *pds3db); /******************************************************************************* - * DirectSound ClassFactory implementation structure */ -struct IClassFactoryImpl -{ - /* IUnknown fields */ - const IClassFactoryVtbl *lpVtbl; - LONG ref; -}; - -extern IClassFactoryImpl DSOUND_CAPTURE_CF; -extern IClassFactoryImpl DSOUND_FULLDUPLEX_CF; - -void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan); -void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan); -void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb); /* dsound.c */ -HRESULT DSOUND_AddBuffer(IDirectSoundImpl * pDS, IDirectSoundBufferImpl * pDSB); -HRESULT DSOUND_RemoveBuffer(IDirectSoundImpl * pDS, IDirectSoundBufferImpl * pDSB); +HRESULT DSOUND_Create(REFIID riid, LPDIRECTSOUND *ppDS); +HRESULT DSOUND_Create8(REFIID riid, LPDIRECTSOUND8 *ppDS); /* primary.c */ +DWORD DSOUND_fraglen(DWORD nSamplesPerSec, DWORD nBlockAlign); HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device); HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device); HRESULT DSOUND_PrimaryPlay(DirectSoundDevice *device); HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device); HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LPDWORD writepos); +HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, BOOL forced); +HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave); -/* buffer.c */ - -DWORD DSOUND_CalcPlayPosition(IDirectSoundBufferImpl *This, DWORD pplay, DWORD pwrite); +/* duplex.c */ + +HRESULT DSOUND_FullDuplexCreate(REFIID riid, LPDIRECTSOUNDFULLDUPLEX* ppDSFD); /* mixer.c */ +DWORD DSOUND_bufpos_to_mixpos(const DirectSoundDevice* device, DWORD pos); +void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len); +void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan); +void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan); +void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb); +void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen, BOOL inmixer); +DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD* overshot); -void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len); -void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb); -void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos); -void DSOUND_WaveQueue(DirectSoundDevice *device, DWORD mixq); -void DSOUND_PerformMix(DirectSoundDevice *device); -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_timer(UINT timerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2); +void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2); /* sound3d.c */ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb); +/* capture.c */ + +HRESULT DSOUND_CaptureCreate(REFIID riid, LPDIRECTSOUNDCAPTURE *ppDSC); +HRESULT DSOUND_CaptureCreate8(REFIID riid, LPDIRECTSOUNDCAPTURE8 *ppDSC8); +HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer( + LPDIRECTSOUNDCAPTURE iface, + LPCDSCBUFFERDESC lpcDSCBufferDesc, + LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer, + LPUNKNOWN pUnk); +HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps( + LPDIRECTSOUNDCAPTURE iface, + LPDSCCAPS lpDSCCaps); +HRESULT WINAPI IDirectSoundCaptureImpl_Initialize( + LPDIRECTSOUNDCAPTURE iface, + LPCGUID lpcGUID); + #define STATE_STOPPED 0 #define STATE_STARTING 1 #define STATE_PLAYING 2 #define STATE_CAPTURING 2 #define STATE_STOPPING 3 -#define DSOUND_FREQSHIFT (14) +#define DSOUND_FREQSHIFT (20) extern DirectSoundDevice* DSOUND_renderer[MAXWAVEDRIVERS]; extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS]; @@ -523,6 +490,6 @@ extern GUID DSOUND_renderer_guids[MAXWAVEDRIVERS]; extern DirectSoundCaptureDevice * DSOUND_capture[MAXWAVEDRIVERS]; extern GUID DSOUND_capture_guids[MAXWAVEDRIVERS]; -extern HRESULT mmErr(UINT err); -extern void setup_dsound_options(void); -extern const char * get_device_id(LPCGUID pGuid); +HRESULT mmErr(UINT err); +void setup_dsound_options(void); +const char * dumpCooperativeLevel(DWORD level); diff --git a/reactos/dll/directx/dsound/duplex.c b/reactos/dll/directx/dsound/duplex.c index 8c732c52a79..1fe6bbc67da 100644 --- a/reactos/dll/directx/dsound/duplex.c +++ b/reactos/dll/directx/dsound/duplex.c @@ -17,11 +17,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/* - * TODO: - * Implement DirectSoundFullDuplex support. + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -30,11 +26,10 @@ #define NONAMELESSUNION #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "mmsystem.h" #include "mmddk.h" -#include "winreg.h" #include "winternl.h" -#include "winnls.h" #include "wine/debug.h" #include "dsound.h" #include "dsdriver.h" @@ -42,88 +37,536 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); -static HRESULT WINAPI IDirectSoundFullDuplexImpl_Initialize( - LPDIRECTSOUNDFULLDUPLEX iface, - LPCGUID pCaptureGuid, - LPCGUID pRendererGuid, - LPCDSCBUFFERDESC lpDscBufferDesc, - LPCDSBUFFERDESC lpDsBufferDesc, - HWND hWnd, - DWORD dwLevel, - LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8, - LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 ); +/******************************************************************************* + * IUnknown + */ +static HRESULT WINAPI IDirectSoundFullDuplex_IUnknown_QueryInterface( + LPUNKNOWN iface, + REFIID riid, + LPVOID * ppobj) +{ + IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj); +} -static const IDirectSoundFullDuplexVtbl dsfdvt; +static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_AddRef( + LPUNKNOWN iface) +{ + IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; +} -/*************************************************************************** - * DirectSoundFullDuplexCreate [DSOUND.10] - * - * Create and initialize a DirectSoundFullDuplex interface. - * - * PARAMS - * pcGuidCaptureDevice [I] Address of sound capture device GUID. - * pcGuidRenderDevice [I] Address of sound render device GUID. - * pcDSCBufferDesc [I] Address of capture buffer description. - * pcDSBufferDesc [I] Address of render buffer description. - * hWnd [I] Handle to application window. - * dwLevel [I] Cooperative level. - * ppDSFD [O] Address where full duplex interface returned. - * ppDSCBuffer8 [0] Address where capture buffer interface returned. - * ppDSBuffer8 [0] Address where render buffer interface returned. - * pUnkOuter [I] Must be NULL. - * - * RETURNS - * Success: DS_OK - * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM, - * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER +static ULONG WINAPI IDirectSoundFullDuplex_IUnknown_Release( + LPUNKNOWN iface) +{ + IDirectSoundFullDuplex_IUnknown *This = (IDirectSoundFullDuplex_IUnknown *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref + 1); + if (!ref) { + IDirectSound_Release(This->pdsfd->pUnknown); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; +} + +static const IUnknownVtbl DirectSoundFullDuplex_Unknown_Vtbl = +{ + IDirectSoundFullDuplex_IUnknown_QueryInterface, + IDirectSoundFullDuplex_IUnknown_AddRef, + IDirectSoundFullDuplex_IUnknown_Release +}; + +static HRESULT IDirectSoundFullDuplex_IUnknown_Create( + LPDIRECTSOUNDFULLDUPLEX pdsfd, + LPUNKNOWN * ppunk) +{ + IDirectSoundFullDuplex_IUnknown * pdsfdunk; + TRACE("(%p,%p)\n",pdsfd,ppunk); + + if (pdsfd == NULL) { + ERR("invalid parameter: pdsfd == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (ppunk == NULL) { + ERR("invalid parameter: ppunk == NULL\n"); + return DSERR_INVALIDPARAM; + } + + pdsfdunk = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdunk)); + if (pdsfdunk == NULL) { + WARN("out of memory\n"); + *ppunk = NULL; + return DSERR_OUTOFMEMORY; + } + + pdsfdunk->lpVtbl = &DirectSoundFullDuplex_Unknown_Vtbl; + pdsfdunk->ref = 0; + pdsfdunk->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd; + + *ppunk = (LPUNKNOWN)pdsfdunk; + + return DS_OK; +} + +/******************************************************************************* + * IDirectSoundFullDuplex_IDirectSound */ -HRESULT WINAPI -DirectSoundFullDuplexCreate( - LPCGUID pcGuidCaptureDevice, - LPCGUID pcGuidRenderDevice, - LPCDSCBUFFERDESC pcDSCBufferDesc, - LPCDSBUFFERDESC pcDSBufferDesc, - HWND hWnd, - DWORD dwLevel, - LPDIRECTSOUNDFULLDUPLEX *ppDSFD, - LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8, - LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, - LPUNKNOWN pUnkOuter) +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_QueryInterface( + LPDIRECTSOUND iface, + REFIID riid, + LPVOID * ppobj) { - IDirectSoundFullDuplexImpl** ippDSFD=(IDirectSoundFullDuplexImpl**)ppDSFD; - TRACE("(%s,%s,%p,%p,%p,%lx,%p,%p,%p,%p)\n", debugstr_guid(pcGuidCaptureDevice), - debugstr_guid(pcGuidRenderDevice), pcDSCBufferDesc, pcDSBufferDesc, - hWnd, dwLevel, ppDSFD, ppDSCBuffer8, ppDSBuffer8, pUnkOuter); + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj); +} - if ( pUnkOuter ) { - WARN("pUnkOuter != 0\n"); - return DSERR_NOAGGREGATION; +static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound_AddRef( + LPDIRECTSOUND iface) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; +} + +static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound_Release( + LPDIRECTSOUND iface) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref + 1); + if (!ref) { + IDirectSound_Release(This->pdsfd->pDS); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_CreateSoundBuffer( + LPDIRECTSOUND iface, + LPCDSBUFFERDESC dsbd, + LPLPDIRECTSOUNDBUFFER ppdsb, + LPUNKNOWN lpunk) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); + return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,FALSE); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_GetCaps( + LPDIRECTSOUND iface, + LPDSCAPS lpDSCaps) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p,%p)\n",This,lpDSCaps); + return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer( + LPDIRECTSOUND iface, + LPDIRECTSOUNDBUFFER psb, + LPLPDIRECTSOUNDBUFFER ppdsb) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p,%p,%p)\n",This,psb,ppdsb); + return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_SetCooperativeLevel( + LPDIRECTSOUND iface, + HWND hwnd, + DWORD level) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); + return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_Compact( + LPDIRECTSOUND iface) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p)\n", This); + return DirectSoundDevice_Compact(This->pdsfd->renderer_device); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_GetSpeakerConfig( + LPDIRECTSOUND iface, + LPDWORD lpdwSpeakerConfig) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); + return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_SetSpeakerConfig( + LPDIRECTSOUND iface, + DWORD config) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p,0x%08x)\n",This,config); + return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound_Initialize( + LPDIRECTSOUND iface, + LPCGUID lpcGuid) +{ + IDirectSoundFullDuplex_IDirectSound *This = (IDirectSoundFullDuplex_IDirectSound *)iface; + TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); + return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid); +} + +static const IDirectSoundVtbl DirectSoundFullDuplex_DirectSound_Vtbl = +{ + IDirectSoundFullDuplex_IDirectSound_QueryInterface, + IDirectSoundFullDuplex_IDirectSound_AddRef, + IDirectSoundFullDuplex_IDirectSound_Release, + IDirectSoundFullDuplex_IDirectSound_CreateSoundBuffer, + IDirectSoundFullDuplex_IDirectSound_GetCaps, + IDirectSoundFullDuplex_IDirectSound_DuplicateSoundBuffer, + IDirectSoundFullDuplex_IDirectSound_SetCooperativeLevel, + IDirectSoundFullDuplex_IDirectSound_Compact, + IDirectSoundFullDuplex_IDirectSound_GetSpeakerConfig, + IDirectSoundFullDuplex_IDirectSound_SetSpeakerConfig, + IDirectSoundFullDuplex_IDirectSound_Initialize +}; + +static HRESULT IDirectSoundFullDuplex_IDirectSound_Create( + LPDIRECTSOUNDFULLDUPLEX pdsfd, + LPDIRECTSOUND * ppds) +{ + IDirectSoundFullDuplex_IDirectSound * pdsfdds; + TRACE("(%p,%p)\n",pdsfd,ppds); + + if (pdsfd == NULL) { + ERR("invalid parameter: pdsfd == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (ppds == NULL) { + ERR("invalid parameter: ppds == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) { + WARN("not initialized\n"); + *ppds = NULL; + return DSERR_UNINITIALIZED; + } + + pdsfdds = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds)); + if (pdsfdds == NULL) { + WARN("out of memory\n"); + *ppds = NULL; + return DSERR_OUTOFMEMORY; + } + + pdsfdds->lpVtbl = &DirectSoundFullDuplex_DirectSound_Vtbl; + pdsfdds->ref = 0; + pdsfdds->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd; + + *ppds = (LPDIRECTSOUND)pdsfdds; + + return DS_OK; +} + +/******************************************************************************* + * IDirectSoundFullDuplex_IDirectSound8 + */ +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_QueryInterface( + LPDIRECTSOUND8 iface, + REFIID riid, + LPVOID * ppobj) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj); +} + +static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_AddRef( + LPDIRECTSOUND8 iface) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; +} + +static ULONG WINAPI IDirectSoundFullDuplex_IDirectSound8_Release( + LPDIRECTSOUND8 iface) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref + 1); + if (!ref) { + IDirectSound_Release(This->pdsfd->pDS8); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer( + LPDIRECTSOUND8 iface, + LPCDSBUFFERDESC dsbd, + LPLPDIRECTSOUNDBUFFER ppdsb, + LPUNKNOWN lpunk) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p,%p,%p,%p)\n",This,dsbd,ppdsb,lpunk); + return DirectSoundDevice_CreateSoundBuffer(This->pdsfd->renderer_device,dsbd,ppdsb,lpunk,TRUE); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetCaps( + LPDIRECTSOUND8 iface, + LPDSCAPS lpDSCaps) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p,%p)\n",This,lpDSCaps); + return DirectSoundDevice_GetCaps(This->pdsfd->renderer_device, lpDSCaps); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer( + LPDIRECTSOUND8 iface, + LPDIRECTSOUNDBUFFER psb, + LPLPDIRECTSOUNDBUFFER ppdsb) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p,%p,%p)\n",This,psb,ppdsb); + return DirectSoundDevice_DuplicateSoundBuffer(This->pdsfd->renderer_device,psb,ppdsb); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel( + LPDIRECTSOUND8 iface, + HWND hwnd, + DWORD level) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p,%p,%s)\n",This,hwnd,dumpCooperativeLevel(level)); + return DirectSoundDevice_SetCooperativeLevel(This->pdsfd->renderer_device,hwnd,level); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Compact( + LPDIRECTSOUND8 iface) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p)\n", This); + return DirectSoundDevice_Compact(This->pdsfd->renderer_device); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig( + LPDIRECTSOUND8 iface, + LPDWORD lpdwSpeakerConfig) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p, %p)\n", This, lpdwSpeakerConfig); + return DirectSoundDevice_GetSpeakerConfig(This->pdsfd->renderer_device,lpdwSpeakerConfig); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig( + LPDIRECTSOUND8 iface, + DWORD config) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p,0x%08x)\n",This,config); + return DirectSoundDevice_SetSpeakerConfig(This->pdsfd->renderer_device,config); +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSound8_Initialize( + LPDIRECTSOUND8 iface, + LPCGUID lpcGuid) +{ + IDirectSoundFullDuplex_IDirectSound8 *This = (IDirectSoundFullDuplex_IDirectSound8 *)iface; + TRACE("(%p, %s)\n", This, debugstr_guid(lpcGuid)); + return DirectSoundDevice_Initialize(&This->pdsfd->renderer_device,lpcGuid); +} + +static const IDirectSound8Vtbl DirectSoundFullDuplex_DirectSound8_Vtbl = +{ + IDirectSoundFullDuplex_IDirectSound8_QueryInterface, + IDirectSoundFullDuplex_IDirectSound8_AddRef, + IDirectSoundFullDuplex_IDirectSound8_Release, + IDirectSoundFullDuplex_IDirectSound8_CreateSoundBuffer, + IDirectSoundFullDuplex_IDirectSound8_GetCaps, + IDirectSoundFullDuplex_IDirectSound8_DuplicateSoundBuffer, + IDirectSoundFullDuplex_IDirectSound8_SetCooperativeLevel, + IDirectSoundFullDuplex_IDirectSound8_Compact, + IDirectSoundFullDuplex_IDirectSound8_GetSpeakerConfig, + IDirectSoundFullDuplex_IDirectSound8_SetSpeakerConfig, + IDirectSoundFullDuplex_IDirectSound8_Initialize +}; + +static HRESULT IDirectSoundFullDuplex_IDirectSound8_Create( + LPDIRECTSOUNDFULLDUPLEX pdsfd, + LPDIRECTSOUND8 * ppds8) +{ + IDirectSoundFullDuplex_IDirectSound8 * pdsfdds8; + TRACE("(%p,%p)\n",pdsfd,ppds8); + + if (pdsfd == NULL) { + ERR("invalid parameter: pdsfd == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (ppds8 == NULL) { + ERR("invalid parameter: ppds8 == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (((IDirectSoundFullDuplexImpl*)pdsfd)->renderer_device == NULL) { + WARN("not initialized\n"); + *ppds8 = NULL; + return DSERR_UNINITIALIZED; + } + + pdsfdds8 = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfdds8)); + if (pdsfdds8 == NULL) { + WARN("out of memory\n"); + *ppds8 = NULL; + return DSERR_OUTOFMEMORY; } - *ippDSFD = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl)); + pdsfdds8->lpVtbl = &DirectSoundFullDuplex_DirectSound8_Vtbl; + pdsfdds8->ref = 0; + pdsfdds8->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd; + + *ppds8 = (LPDIRECTSOUND8)pdsfdds8; + + return DS_OK; +} + +/******************************************************************************* + * IDirectSoundFullDuplex_IDirectSoundCapture + */ +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface( + LPDIRECTSOUNDCAPTURE iface, + REFIID riid, + LPVOID * ppobj) +{ + IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; + TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + return IDirectSoundFullDuplex_QueryInterface((LPDIRECTSOUNDFULLDUPLEX)This->pdsfd, riid, ppobj); +} + +static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_AddRef( + LPDIRECTSOUNDCAPTURE iface) +{ + IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; +} + +static ULONG WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Release( + LPDIRECTSOUNDCAPTURE iface) +{ + IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; + ULONG ref = InterlockedDecrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref + 1); + if (!ref) { + IDirectSoundCapture_Release(This->pdsfd->pDSC); + HeapFree(GetProcessHeap(), 0, This); + TRACE("(%p) released\n", This); + } + return ref; +} + +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer( + LPDIRECTSOUNDCAPTURE iface, + LPCDSCBUFFERDESC lpcDSCBufferDesc, + LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer, + LPUNKNOWN pUnk) +{ + IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; + TRACE("(%p,%p,%p,%p)\n",This,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk); + return IDirectSoundCaptureImpl_CreateCaptureBuffer(This->pdsfd->pDSC,lpcDSCBufferDesc,lplpDSCaptureBuffer,pUnk); +} - if (*ippDSFD == NULL) { - WARN("out of memory\n"); - return DSERR_OUTOFMEMORY; - } else { - HRESULT hres; - IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)*ippDSFD; +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps( + LPDIRECTSOUNDCAPTURE iface, + LPDSCCAPS lpDSCCaps) +{ + IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; + TRACE("(%p,%p)\n",This,lpDSCCaps); + return IDirectSoundCaptureImpl_GetCaps(This->pdsfd->pDSC, lpDSCCaps); +} - This->ref = 1; - This->lpVtbl = &dsfdvt; +static HRESULT WINAPI IDirectSoundFullDuplex_IDirectSoundCapture_Initialize( + LPDIRECTSOUNDCAPTURE iface, + LPCGUID lpcGUID) +{ + IDirectSoundFullDuplex_IDirectSoundCapture *This = (IDirectSoundFullDuplex_IDirectSoundCapture *)iface; + TRACE("(%p, %s)\n", This, debugstr_guid(lpcGUID)); + return IDirectSoundCaptureImpl_Initialize(This->pdsfd->pDSC,lpcGUID); +} - InitializeCriticalSection( &(This->lock) ); - This->lock.DebugInfo->Spare[0] = (DWORD_PTR)"DSDUPLEX_lock"; +static const IDirectSoundCaptureVtbl DirectSoundFullDuplex_DirectSoundCapture_Vtbl = +{ + IDirectSoundFullDuplex_IDirectSoundCapture_QueryInterface, + IDirectSoundFullDuplex_IDirectSoundCapture_AddRef, + IDirectSoundFullDuplex_IDirectSoundCapture_Release, + IDirectSoundFullDuplex_IDirectSoundCapture_CreateCaptureBuffer, + IDirectSoundFullDuplex_IDirectSoundCapture_GetCaps, + IDirectSoundFullDuplex_IDirectSoundCapture_Initialize +}; - hres = IDirectSoundFullDuplexImpl_Initialize( (LPDIRECTSOUNDFULLDUPLEX)This, - pcGuidCaptureDevice, pcGuidRenderDevice, - pcDSCBufferDesc, pcDSBufferDesc, - hWnd, dwLevel, ppDSCBuffer8, ppDSBuffer8); - if (hres != DS_OK) - WARN("IDirectSoundFullDuplexImpl_Initialize failed\n"); - return hres; +static HRESULT IDirectSoundFullDuplex_IDirectSoundCapture_Create( + LPDIRECTSOUNDFULLDUPLEX pdsfd, + LPDIRECTSOUNDCAPTURE8 * ppdsc8) +{ + IDirectSoundFullDuplex_IDirectSoundCapture * pdsfddsc; + TRACE("(%p,%p)\n",pdsfd,ppdsc8); + + if (pdsfd == NULL) { + ERR("invalid parameter: pdsfd == NULL\n"); + return DSERR_INVALIDPARAM; } + + if (ppdsc8 == NULL) { + ERR("invalid parameter: ppdsc8 == NULL\n"); + return DSERR_INVALIDPARAM; + } + + if (((IDirectSoundFullDuplexImpl*)pdsfd)->capture_device == NULL) { + WARN("not initialized\n"); + *ppdsc8 = NULL; + return DSERR_UNINITIALIZED; + } + + pdsfddsc = HeapAlloc(GetProcessHeap(),0,sizeof(*pdsfddsc)); + if (pdsfddsc == NULL) { + WARN("out of memory\n"); + *ppdsc8 = NULL; + return DSERR_OUTOFMEMORY; + } + + pdsfddsc->lpVtbl = &DirectSoundFullDuplex_DirectSoundCapture_Vtbl; + pdsfddsc->ref = 0; + pdsfddsc->pdsfd = (IDirectSoundFullDuplexImpl *)pdsfd; + + *ppdsc8 = (LPDIRECTSOUNDCAPTURE)pdsfddsc; + + return DS_OK; +} + +/*************************************************************************** + * IDirectSoundFullDuplexImpl + */ +static ULONG WINAPI +IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface ) +{ + IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; + ULONG ref = InterlockedIncrement(&(This->ref)); + TRACE("(%p) ref was %d\n", This, ref - 1); + return ref; } static HRESULT WINAPI @@ -141,16 +584,62 @@ IDirectSoundFullDuplexImpl_QueryInterface( } *ppobj = NULL; - return E_NOINTERFACE; -} -static ULONG WINAPI -IDirectSoundFullDuplexImpl_AddRef( LPDIRECTSOUNDFULLDUPLEX iface ) -{ - IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; - ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); - return ref; + if (IsEqualIID(riid, &IID_IUnknown)) { + if (!This->pUnknown) { + IDirectSoundFullDuplex_IUnknown_Create(iface, &This->pUnknown); + if (!This->pUnknown) { + WARN("IDirectSoundFullDuplex_IUnknown_Create() failed\n"); + *ppobj = NULL; + return E_NOINTERFACE; + } + } + IDirectSoundFullDuplex_IUnknown_AddRef(This->pUnknown); + *ppobj = This->pUnknown; + return S_OK; + } else if (IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) { + IDirectSoundFullDuplexImpl_AddRef(iface); + *ppobj = This; + return S_OK; + } else if (IsEqualIID(riid, &IID_IDirectSound)) { + if (!This->pDS) { + IDirectSoundFullDuplex_IDirectSound_Create(iface, &This->pDS); + if (!This->pDS) { + WARN("IDirectSoundFullDuplex_IDirectSound_Create() failed\n"); + *ppobj = NULL; + return E_NOINTERFACE; + } + } + IDirectSoundFullDuplex_IDirectSound_AddRef(This->pDS); + *ppobj = This->pDS; + return S_OK; + } else if (IsEqualIID(riid, &IID_IDirectSound8)) { + if (!This->pDS8) { + IDirectSoundFullDuplex_IDirectSound8_Create(iface, &This->pDS8); + if (!This->pDS8) { + WARN("IDirectSoundFullDuplex_IDirectSound8_Create() failed\n"); + *ppobj = NULL; + return E_NOINTERFACE; + } + } + IDirectSoundFullDuplex_IDirectSound8_AddRef(This->pDS8); + *ppobj = This->pDS8; + return S_OK; + } else if (IsEqualIID(riid, &IID_IDirectSoundCapture)) { + if (!This->pDSC) { + IDirectSoundFullDuplex_IDirectSoundCapture_Create(iface, &This->pDSC); + if (!This->pDSC) { + WARN("IDirectSoundFullDuplex_IDirectSoundCapture_Create() failed\n"); + *ppobj = NULL; + return E_NOINTERFACE; + } + } + IDirectSoundFullDuplex_IDirectSoundCapture_AddRef(This->pDSC); + *ppobj = This->pDSC; + return S_OK; + } + + return E_NOINTERFACE; } static ULONG WINAPI @@ -158,11 +647,13 @@ IDirectSoundFullDuplexImpl_Release( LPDIRECTSOUNDFULLDUPLEX iface ) { IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); if (!ref) { - This->lock.DebugInfo->Spare[0] = 0; - DeleteCriticalSection( &(This->lock) ); + if (This->capture_device) + DirectSoundCaptureDevice_Release(This->capture_device); + if (This->renderer_device) + DirectSoundDevice_Release(This->renderer_device); HeapFree( GetProcessHeap(), 0, This ); TRACE("(%p) released\n", This); } @@ -181,15 +672,79 @@ IDirectSoundFullDuplexImpl_Initialize( LPLPDIRECTSOUNDCAPTUREBUFFER8 lplpDirectSoundCaptureBuffer8, LPLPDIRECTSOUNDBUFFER8 lplpDirectSoundBuffer8 ) { + HRESULT hr; IDirectSoundFullDuplexImpl *This = (IDirectSoundFullDuplexImpl *)iface; - IDirectSoundCaptureBufferImpl** ippdscb=(IDirectSoundCaptureBufferImpl**)lplpDirectSoundCaptureBuffer8; - IDirectSoundBufferImpl** ippdsc=(IDirectSoundBufferImpl**)lplpDirectSoundBuffer8; + IDirectSoundBufferImpl * dsb; + + TRACE("(%p,%s,%s,%p,%p,%p,%x,%p,%p)\n", This, + debugstr_guid(pCaptureGuid), debugstr_guid(pRendererGuid), + lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel, + lplpDirectSoundCaptureBuffer8, lplpDirectSoundBuffer8); + + if (This->renderer_device != NULL || This->capture_device != NULL) { + WARN("already initialized\n"); + *lplpDirectSoundCaptureBuffer8 = NULL; + *lplpDirectSoundBuffer8 = NULL; + return DSERR_ALREADYINITIALIZED; + } - FIXME( "(%p,%s,%s,%p,%p,%p,%lx,%p,%p) stub!\n", This, debugstr_guid(pCaptureGuid), - debugstr_guid(pRendererGuid), lpDscBufferDesc, lpDsBufferDesc, hWnd, dwLevel, - ippdscb, ippdsc); + hr = DirectSoundDevice_Initialize(&This->renderer_device, pRendererGuid); + if (hr != DS_OK) { + WARN("DirectSoundDevice_Initialize() failed\n"); + *lplpDirectSoundCaptureBuffer8 = NULL; + *lplpDirectSoundBuffer8 = NULL; + return hr; + } + + if (dwLevel==DSSCL_PRIORITY || dwLevel==DSSCL_EXCLUSIVE) { + WARN("level=%s not fully supported\n", + dwLevel==DSSCL_PRIORITY ? "DSSCL_PRIORITY" : "DSSCL_EXCLUSIVE"); + } + This->renderer_device->priolevel = dwLevel; + + hr = DSOUND_PrimarySetFormat(This->renderer_device, lpDsBufferDesc->lpwfxFormat, dwLevel == DSSCL_EXCLUSIVE); + if (hr != DS_OK) { + WARN("DSOUND_PrimarySetFormat() failed\n"); + *lplpDirectSoundCaptureBuffer8 = NULL; + *lplpDirectSoundBuffer8 = NULL; + return hr; + } + hr = IDirectSoundBufferImpl_Create(This->renderer_device, &dsb, lpDsBufferDesc); + if (hr != DS_OK) { + WARN("IDirectSoundBufferImpl_Create() failed\n"); + *lplpDirectSoundCaptureBuffer8 = NULL; + *lplpDirectSoundBuffer8 = NULL; + return hr; + } - return E_FAIL; + hr = SecondaryBufferImpl_Create(dsb, (SecondaryBufferImpl **)lplpDirectSoundBuffer8); + if (hr != DS_OK) { + WARN("SecondaryBufferImpl_Create() failed\n"); + *lplpDirectSoundCaptureBuffer8 = NULL; + *lplpDirectSoundBuffer8 = NULL; + return hr; + } + IDirectSoundBuffer8_AddRef(*lplpDirectSoundBuffer8); + + hr = DirectSoundCaptureDevice_Initialize(&This->capture_device, pCaptureGuid); + if (hr != DS_OK) { + WARN("DirectSoundCaptureDevice_Initialize() failed\n"); + *lplpDirectSoundCaptureBuffer8 = NULL; + *lplpDirectSoundBuffer8 = NULL; + return hr; + } + + hr = IDirectSoundCaptureBufferImpl_Create(This->capture_device, + (IDirectSoundCaptureBufferImpl **)lplpDirectSoundCaptureBuffer8, + lpDscBufferDesc); + if (hr != DS_OK) { + WARN("IDirectSoundCaptureBufferImpl_Create() failed\n"); + *lplpDirectSoundCaptureBuffer8 = NULL; + *lplpDirectSoundBuffer8 = NULL; + return hr; + } + + return hr; } static const IDirectSoundFullDuplexVtbl dsfdvt = @@ -203,81 +758,153 @@ static const IDirectSoundFullDuplexVtbl dsfdvt = IDirectSoundFullDuplexImpl_Initialize }; -/******************************************************************************* - * DirectSoundFullDuplex ClassFactory - */ - -static HRESULT WINAPI -DSFDCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid,LPVOID *ppobj) +HRESULT DSOUND_FullDuplexCreate( + REFIID riid, + LPDIRECTSOUNDFULLDUPLEX* ppDSFD) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + IDirectSoundFullDuplexImpl *This = NULL; + TRACE("(%s, %p)\n", debugstr_guid(riid), ppDSFD); - FIXME("(%p)->(%s,%p),stub!\n",This,debugstr_guid(riid),ppobj); - return E_NOINTERFACE; -} + if (ppDSFD == NULL) { + WARN("invalid parameter: ppDSFD == NULL\n"); + return DSERR_INVALIDPARAM; + } -static ULONG WINAPI -DSFDCF_AddRef(LPCLASSFACTORY iface) -{ - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedIncrement(&(This->ref)); -} + if (!IsEqualIID(riid, &IID_IUnknown) && + !IsEqualIID(riid, &IID_IDirectSoundFullDuplex)) { + *ppDSFD = 0; + return E_NOINTERFACE; + } -static ULONG WINAPI -DSFDCF_Release(LPCLASSFACTORY iface) -{ - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - /* static class, won't be freed */ - TRACE("(%p) ref was %ld\n", This, This->ref); - return InterlockedDecrement(&(This->ref)); + /* Get dsound configuration */ + setup_dsound_options(); + + This = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl)); + + if (This == NULL) { + WARN("out of memory\n"); + *ppDSFD = NULL; + return DSERR_OUTOFMEMORY; + } + + This->lpVtbl = &dsfdvt; + This->ref = 1; + This->capture_device = NULL; + This->renderer_device = NULL; + + *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This; + + return DS_OK; } -static HRESULT WINAPI -DSFDCF_CreateInstance( - LPCLASSFACTORY iface,LPUNKNOWN pOuter,REFIID riid,LPVOID *ppobj ) +/*************************************************************************** + * DirectSoundFullDuplexCreate [DSOUND.10] + * + * Create and initialize a DirectSoundFullDuplex interface. + * + * PARAMS + * pcGuidCaptureDevice [I] Address of sound capture device GUID. + * pcGuidRenderDevice [I] Address of sound render device GUID. + * pcDSCBufferDesc [I] Address of capture buffer description. + * pcDSBufferDesc [I] Address of render buffer description. + * hWnd [I] Handle to application window. + * dwLevel [I] Cooperative level. + * ppDSFD [O] Address where full duplex interface returned. + * ppDSCBuffer8 [0] Address where capture buffer interface returned. + * ppDSBuffer8 [0] Address where render buffer interface returned. + * pUnkOuter [I] Must be NULL. + * + * RETURNS + * Success: DS_OK + * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM, + * DSERR_OUTOFMEMORY DSERR_INVALIDCALL DSERR_NODRIVER + */ +HRESULT WINAPI +DirectSoundFullDuplexCreate( + LPCGUID pcGuidCaptureDevice, + LPCGUID pcGuidRenderDevice, + LPCDSCBUFFERDESC pcDSCBufferDesc, + LPCDSBUFFERDESC pcDSBufferDesc, + HWND hWnd, + DWORD dwLevel, + LPDIRECTSOUNDFULLDUPLEX *ppDSFD, + LPDIRECTSOUNDCAPTUREBUFFER8 *ppDSCBuffer8, + LPDIRECTSOUNDBUFFER8 *ppDSBuffer8, + LPUNKNOWN pUnkOuter) { - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; + HRESULT hres; + IDirectSoundFullDuplexImpl *This = NULL; + TRACE("(%s,%s,%p,%p,%p,%x,%p,%p,%p,%p)\n", + debugstr_guid(pcGuidCaptureDevice), debugstr_guid(pcGuidRenderDevice), + pcDSCBufferDesc, pcDSBufferDesc, hWnd, dwLevel, ppDSFD, ppDSCBuffer8, + ppDSBuffer8, pUnkOuter); + + if (pUnkOuter) { + WARN("pUnkOuter != 0\n"); + *ppDSFD = NULL; + return DSERR_NOAGGREGATION; + } - TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj); + if (pcDSCBufferDesc == NULL) { + WARN("invalid parameter: pcDSCBufferDesc == NULL\n"); + *ppDSFD = NULL; + return DSERR_INVALIDPARAM; + } - if (pOuter) { - WARN("aggregation not supported\n"); - return CLASS_E_NOAGGREGATION; + if (pcDSBufferDesc == NULL) { + WARN("invalid parameter: pcDSBufferDesc == NULL\n"); + *ppDSFD = NULL; + return DSERR_INVALIDPARAM; } - if (ppobj == NULL) { - WARN("invalid parameter\n"); - return E_INVALIDARG; + if (ppDSFD == NULL) { + WARN("invalid parameter: ppDSFD == NULL\n"); + return DSERR_INVALIDPARAM; } - *ppobj = NULL; + if (ppDSCBuffer8 == NULL) { + WARN("invalid parameter: ppDSCBuffer8 == NULL\n"); + *ppDSFD = NULL; + return DSERR_INVALIDPARAM; + } - if ( IsEqualGUID( &IID_IDirectSoundFullDuplex, riid ) ) { - /* FIXME: how do we do this one ? */ - FIXME("not implemented\n"); - return E_NOINTERFACE; + if (ppDSBuffer8 == NULL) { + WARN("invalid parameter: ppDSBuffer8 == NULL\n"); + *ppDSFD = NULL; + return DSERR_INVALIDPARAM; } - WARN("(%p,%p,%s,%p) Interface not found!\n",This,pOuter,debugstr_guid(riid),ppobj); - return E_NOINTERFACE; -} + /* Get dsound configuration */ + setup_dsound_options(); -static HRESULT WINAPI -DSFDCF_LockServer(LPCLASSFACTORY iface,BOOL dolock) -{ - IClassFactoryImpl *This = (IClassFactoryImpl *)iface; - FIXME("(%p)->(%d),stub!\n",This,dolock); - return S_OK; -} + This = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(IDirectSoundFullDuplexImpl)); -static const IClassFactoryVtbl DSFDCF_Vtbl = -{ - DSFDCF_QueryInterface, - DSFDCF_AddRef, - DSFDCF_Release, - DSFDCF_CreateInstance, - DSFDCF_LockServer -}; + if (This == NULL) { + WARN("out of memory\n"); + *ppDSFD = NULL; + return DSERR_OUTOFMEMORY; + } -IClassFactoryImpl DSOUND_FULLDUPLEX_CF = { &DSFDCF_Vtbl, 1 }; + This->lpVtbl = &dsfdvt; + This->ref = 1; + This->capture_device = NULL; + This->renderer_device = NULL; + + hres = IDirectSoundFullDuplexImpl_Initialize((LPDIRECTSOUNDFULLDUPLEX)This, + pcGuidCaptureDevice, + pcGuidRenderDevice, + pcDSCBufferDesc, + pcDSBufferDesc, + hWnd, dwLevel, ppDSCBuffer8, + ppDSBuffer8); + if (hres != DS_OK) { + HeapFree(GetProcessHeap(), 0, This); + WARN("IDirectSoundFullDuplexImpl_Initialize failed\n"); + *ppDSFD = NULL; + } else + *ppDSFD = (LPDIRECTSOUNDFULLDUPLEX)This; + + return hres; +} diff --git a/reactos/dll/directx/dsound/dxroslayer/dxros_layer.h b/reactos/dll/directx/dsound/dxroslayer/dxros_layer.h deleted file mode 100644 index 4ab5a5162a1..00000000000 --- a/reactos/dll/directx/dsound/dxroslayer/dxros_layer.h +++ /dev/null @@ -1,62 +0,0 @@ - /* - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ReactOS emulation layer betwin wine and windows api for directx - * This transform wine specfiy api to native reactos/windows api - * wine have done some hack to geting dsound working. But does - * hack does not work on windows or reactos. It need to warp thuse - * api hack to true native api. - * - * this include file really need to be clean up. - * - * copyright 2004 by magnus olsen - */ - -#ifdef __REACTOS__ -#include - -// wine spec -#define MAXWAVEDRIVERS 10 -#define MAXMIDIDRIVERS 10 -#define MAXAUXDRIVERS 10 -#define MAXMCIDRIVERS 32 -#define MAXMIXERDRIVERS 10 - -/* where */ -#ifdef RC_INVOKED -#define _HRESULT_TYPEDEF_(x) (x) -#else -#define _HRESULT_TYPEDEF_(x) ((HRESULT)x) -#endif - -/* wine own api */ -#define DRV_QUERYDSOUNDIFACE (DRV_RESERVED + 20) -#define DRV_QUERYDSOUNDDESC (DRV_RESERVED + 21) - -#define WineWaveOutMessage RosWineWaveOutMessage -#define WineWaveInMessage RosWineWaveInMessage - -#else -#define WineWaveOutMessage WaveOutMessage -#define WineWaveInMessage WaveInMessage -#endif - - -/* dxroslayers prototypes */ -void dxGetGuidFromString( char *in_str, GUID *guid ); - -DWORD dxrosdrv_drv_querydsounddescss(int type, HWAVEOUT hwo_out,HWAVEIN hwo_in, PDSDRIVERDESC pDESC); -DWORD dxrosdrv_drv_querydsoundiface(HWAVEIN wDevID, PIDSDRIVER* drv); - -DWORD RosWineWaveOutMessage(HWAVEOUT hwo, UINT, DWORD_PTR, DWORD_PTR); -DWORD RosWineWaveInMessage(HWAVEIN, UINT, DWORD_PTR, DWORD_PTR); diff --git a/reactos/dll/directx/dsound/dxroslayer/dxrosdrv_querydsounddesc.c b/reactos/dll/directx/dsound/dxroslayer/dxrosdrv_querydsounddesc.c deleted file mode 100644 index caf62018f00..00000000000 --- a/reactos/dll/directx/dsound/dxroslayer/dxrosdrv_querydsounddesc.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * reactos emulation layer betwin wine and windows api for directx - * get hardware dec - * Copyright 2004 Magnus Olsen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO: - * soucre clean - * need to rewrite almost everthing so it get all info from the hardware instead - * see todo.rtf - * - * put it in own library that call dxroslayer.a - * - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include - -#define NONAMELESSSTRUCT -#define NONAMELESSUNION -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winuser.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" -#include "mmsystem.h" -#include "winternl.h" -#include "mmddk.h" -#include "wine/windef16.h" -#include "wine/winbase16.h" -#include "wine/debug.h" -#include "dsound.h" -#include "dsdriver.h" -#include "dxros_layer.h" -#include "dsconf.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dsound); - -DWORD dxrosdrv_drv_querydsounddescss(int type, HWAVEOUT hwo_out,HWAVEIN hwo_in, PDSDRIVERDESC pDESC) -{ - WAVEOUTCAPSA ac_play; - WAVEINCAPSA ac_rec; - DWORD msg; - - - - // type 0 = out - // clear data - memset(pDESC,0,sizeof(DSDRIVERDESC)); - memset((char *)pDESC->szDrvname,0,255); - if (type==0) memset(&ac_play,0,sizeof(WAVEOUTCAPSA)); - else memset(&ac_rec,0,sizeof(WAVEINCAPSA)); - - // get some data - if (type==0) { - msg = waveOutGetDevCapsA((UINT)hwo_out,&ac_play,sizeof(WAVEOUTCAPSA)); - if (ac_play.szPname==NULL) return MMSYSERR_NOTSUPPORTED; - } - - else { - msg = waveInGetDevCapsA((UINT)hwo_in,&ac_rec,sizeof(WAVEINCAPSA)); - if (ac_rec.szPname==NULL) return MMSYSERR_NOTSUPPORTED; - } - - if (msg!=MMSYSERR_NOERROR) return msg; - - - - // setting up value - //pDESC->wReserved = NULL; - - - if (type==0) { - pDESC->ulDeviceNum = (ULONG)hwo_out; - memcpy((char *)pDESC->szDesc,ac_play.szPname,strlen(ac_play.szPname)); - } - else { - pDESC->ulDeviceNum = (ULONG)hwo_in; - memcpy((char *)pDESC->szDesc,ac_rec.szPname,strlen(ac_rec.szPname)); - } - - // FIXME - /* how to fill these - pDESC->dwFlags |= DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT | - DSDDESC_USESYSTEMMEMORY | DSDDESC_DONTNEEDPRIMARYLOCK | - DSDDESC_DONTNEEDSECONDARYLOCK; - //pDesc->dnDevNode = WOutDev[This->wDevID].waveDesc.dnDevNode; - pDESC->wVxdId = 0; - pDESC->wReserved = 0; - pDESC->dwHeapType = DSDHEAP_NOHEAP; - pDESC->pvDirectDrawHeap = NULL; - pDESC->dwMemStartAddress = 0; - pDESC->dwMemEndAddress = 0; - pDESC->dwMemAllocExtra = 0; - pDESC->pvReserved1 = NULL; - pDESC->pvReserved2 = NULL; - -*/ - - pDESC->pvReserved1 = NULL; - pDESC->pvReserved2 = NULL; - - // we need to fill it right so we do not need ddraw.dll - pDESC->pvDirectDrawHeap = NULL; // wine dsound does not use ddraw.dll - - - // need to write dective for it - pDESC->dwHeapType = DSDHEAP_NOHEAP; - - // have take the value from wine audio drv - pDESC->dwFlags = DSDDESC_DOMMSYSTEMOPEN | - DSDDESC_DOMMSYSTEMSETFORMAT | - DSDDESC_USESYSTEMMEMORY | - DSDDESC_DONTNEEDPRIMARYLOCK | - DSDDESC_DONTNEEDSECONDARYLOCK; - - - //WAVEOPENDESC->DevNode need to fig. how to get it from mmdrv - pDESC->dnDevNode = 0; // wine dsound are using this value - - // need to fill the rest also - - // must contain the audio drv name - // but how to get it ? - //memcpy((char *)pDESC->szDrvname,(char *)&"kx.sys",6); - - - - pDESC->dwMemStartAddress = 0; - pDESC->dwMemAllocExtra = 0; - pDESC->wVxdId = 0; - - - return MMSYSERR_NOERROR; -} - diff --git a/reactos/dll/directx/dsound/dxroslayer/dxrosdrv_querydsoundiface.c b/reactos/dll/directx/dsound/dxroslayer/dxrosdrv_querydsoundiface.c deleted file mode 100644 index 93b0a663590..00000000000 --- a/reactos/dll/directx/dsound/dxroslayer/dxrosdrv_querydsoundiface.c +++ /dev/null @@ -1,72 +0,0 @@ -/* - * reactos emulation layer betwin wine and windows api for directx - * - * Copyright 2004 Magnus Olsen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * TODO: - * write hardware support for windows nt 4.0 and higher - * put it in own library that call dxroslayer.a - * - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include - -#define NONAMELESSSTRUCT -#define NONAMELESSUNION -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winuser.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" -#include "mmsystem.h" -#include "winternl.h" -#include "mmddk.h" -#include "wine/windef16.h" -#include "wine/winbase16.h" -#include "wine/debug.h" -#include "dsound.h" -#include "dsdriver.h" -#include "dsconf.h" -#include "windows.h" -#include "dxros_layer.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dsound); - - -DWORD dxrosdrv_drv_querydsoundiface(HWAVEIN wDevID, PIDSDRIVER* drv) -{ - // no hardware support for dsound NT 4.0 does not support it - // but win 2000/xp drv does support hardware support of direct sound - drv = NULL; - // drv should be fild with hardware pointers see PIDSDRIVER struct - return MMSYSERR_NOERROR; -} diff --git a/reactos/dll/directx/dsound/dxroslayer/dxroslayer.c b/reactos/dll/directx/dsound/dxroslayer/dxroslayer.c deleted file mode 100644 index 7ddfdf2bb56..00000000000 --- a/reactos/dll/directx/dsound/dxroslayer/dxroslayer.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * ReactOS emulation layer betwin wine and windows api for directx - * This transform wine specfiy api to native reactos/windows api - * wine have done some hack to geting dsound working. But does - * hack does not work on windows or reactos. It need to warp thuse - * api hack to true native api. - * - * This layer have some weekness - * it does not support hardware accleration of the sound card. - * it need complete implant of it here, and we need also wdm - * in reactos to complete dsound. for monet it is not posibile - * to get all value and fill them. eg the soundcard drv name. - * - * Wine does get almost everthing from there sound drv, then - * pass it thurg winmm, then to dsound. but windows drv does - * not pass this info to the winmm. it send it on wdm instead. - * - * Do rember this dsound is hardcode to software mode only. - * the program will not notice it. it will think it is hardware. - * for the flag never report back it is in software mode. - * - * - * Copyright 2004 Magnus Olsen - * - */ -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include - -#define NONAMELESSSTRUCT -#define NONAMELESSUNION -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winuser.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" -#include "mmsystem.h" -#include "winternl.h" -#include "mmddk.h" -#include "wine/windef16.h" -#include "wine/winbase16.h" -#include "wine/debug.h" -#include "dsound.h" -#include "dsdriver.h" -#include "dxros_layer.h" -#include "dsconf.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dsound); - - -DWORD RosWineWaveOutMessage(HWAVEOUT hwo, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) -{ - DWORD msg; - switch (uMsg) { - case DRV_QUERYDSOUNDDESC: - msg = dxrosdrv_drv_querydsounddescss(0, (HWAVEOUT)((ULONG)hwo),(HWAVEIN) 0, (PDSDRIVERDESC) dwParam1); - break; - - case DRV_QUERYDSOUNDIFACE: - msg = dxrosdrv_drv_querydsoundiface((HWAVEIN)hwo, (PIDSDRIVER*)dwParam1); - break; - - default : - msg = waveOutMessage(hwo, uMsg, dwParam1, dwParam2); - break; - } -return msg; -} - -DWORD RosWineWaveInMessage(HWAVEIN hwo, UINT uMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2) -{ - DWORD msg; - switch (uMsg) { - case DRV_QUERYDSOUNDDESC: - msg = dxrosdrv_drv_querydsounddescss(1, (HWAVEOUT)((ULONG)0),(HWAVEIN)((ULONG)hwo), (PDSDRIVERDESC) dwParam1); - break; - - case DRV_QUERYDSOUNDIFACE: - msg = dxrosdrv_drv_querydsoundiface(hwo, (PIDSDRIVER*)dwParam1); - break; - - default : - msg = waveInMessage(hwo, uMsg, dwParam1, dwParam2); - break; - } -return msg; -} diff --git a/reactos/dll/directx/dsound/dxroslayer/getguidfromstring.c b/reactos/dll/directx/dsound/dxroslayer/getguidfromstring.c deleted file mode 100644 index 40b5f9389d6..00000000000 --- a/reactos/dll/directx/dsound/dxroslayer/getguidfromstring.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * ReactOS emulation layer betwin wine and windows api for directx - * convort string to GUID - * - * Copyright 2004 Magnus Olsen - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * - * TODO: - * soucre clean - * Rewrite so it use unicode instead for asc or find how windows convert it - */ - -#include "config.h" -#include "wine/port.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif -#include -#include -#include - -#define NONAMELESSSTRUCT -#define NONAMELESSUNION -#include "windef.h" -#include "winbase.h" -#include "winreg.h" -#include "winuser.h" -#include "wingdi.h" -#include "winuser.h" -#include "winerror.h" -#include "mmsystem.h" -#include "winternl.h" -#include "mmddk.h" -#include "wine/windef16.h" -#include "wine/winbase16.h" -#include "wine/debug.h" -#include "dsound.h" -#include "dsdriver.h" -#include "dxros_layer.h" -#include "dsconf.h" -#include "windows.h" - -WINE_DEFAULT_DEBUG_CHANNEL(dsound); - - - -void dxGetGuidFromString( char *in_str, GUID *guid ) -{ - unsigned long c=0; - int i; - - // this string hex converter need to be rewrite or find uhow windows convort a string - // to GUID - - for (i=1;i<9;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') - { - c=c * 16 + (in_str[i] - 48); - } - else if (in_str[i]>='A' && in_str[i]<='F') - { - c=c * 16 + (in_str[i] - 55); - } - } - guid->Data1 = c; - c=0; - - for (i=9;i<14;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') - { - c=c * 16 + (in_str[i] - 48); - } - else if (in_str[i]>='A' && in_str[i]<='F') - { - c=c * 16 + (in_str[i] - 55); - } - } - - guid->Data2 = (short) c; - c=0; - - for (i=14;i<19;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data3 = (short) c; - c=0; - - for (i=20;i<22;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data4[0] = (BYTE) c; - c=0; - - for (i=22;i<24;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data4[1] = (BYTE) c; - c=0; - - - for (i=25;i<27;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data4[2] = (BYTE) c; - c=0; - - for (i=27;i<29;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data4[3] = (BYTE) c; - c=0; - - for (i=29;i<31;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data4[4] = (BYTE) c; - c=0; - - for (i=31;i<33;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data4[5] = (BYTE) c; - c=0; - - for (i=33;i<35;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data4[6] = (BYTE) c; - c=0; - - for (i=35;i<37;i++) - { - if (in_str[i]>='0' && in_str[i]<='9') c=c * 16 + (in_str[i] - 48); - else if (in_str[i]>='A' && in_str[i]<='F') c=c * 16 + (in_str[i] - 55); - } - guid->Data4[7] = (BYTE) c; - c=0; - } diff --git a/reactos/dll/directx/dsound/mixer.c b/reactos/dll/directx/dsound/mixer.c index 49c8b37e210..d014c4b8655 100644 --- a/reactos/dll/directx/dsound/mixer.c +++ b/reactos/dll/directx/dsound/mixer.c @@ -3,6 +3,8 @@ * Copyright 1998 Marcus Meissner * Copyright 1998 Rob Riggs * Copyright 2000-2002 TransGaming Technologies, Inc. + * Copyright 2007 Peter Dons Tychsen + * Copyright 2007 Maarten Lankhorst * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -16,7 +18,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -28,7 +30,6 @@ #include "windef.h" #include "winbase.h" #include "mmsystem.h" -#include "winreg.h" #include "winternl.h" #include "wine/debug.h" #include "dsound.h" @@ -42,7 +43,7 @@ void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan) double temp; TRACE("(%p)\n",volpan); - TRACE("Vol=%ld Pan=%ld\n", volpan->lVolume, volpan->lPan); + TRACE("Vol=%d Pan=%d\n", volpan->lVolume, volpan->lPan); /* the AmpFactors are expressed in 16.16 fixed point */ volpan->dwVolAmpFactor = (ULONG) (pow(2.0, volpan->lVolume / 600.0) * 0xffff); /* FIXME: dwPan{Left|Right}AmpFactor */ @@ -53,7 +54,7 @@ void DSOUND_RecalcVolPan(PDSVOLUMEPAN volpan) temp = (double) (volpan->lVolume + (volpan->lPan < 0 ? volpan->lPan : 0)); volpan->dwTotalRightAmpFactor = (ULONG) (pow(2.0, temp / 600.0) * 0xffff); - TRACE("left = %lx, right = %lx\n", volpan->dwTotalLeftAmpFactor, volpan->dwTotalRightAmpFactor); + TRACE("left = %x, right = %x\n", volpan->dwTotalLeftAmpFactor, volpan->dwTotalRightAmpFactor); } void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan) @@ -61,7 +62,7 @@ void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan) double left,right; TRACE("(%p)\n",volpan); - TRACE("left=%lx, right=%lx\n",volpan->dwTotalLeftAmpFactor,volpan->dwTotalRightAmpFactor); + TRACE("left=%x, right=%x\n",volpan->dwTotalLeftAmpFactor,volpan->dwTotalRightAmpFactor); if (volpan->dwTotalLeftAmpFactor==0) left=-10000; else @@ -86,18 +87,141 @@ void DSOUND_AmpFactorToVolPan(PDSVOLUMEPAN volpan) if (volpan->lPan < -10000) volpan->lPan=-10000; - TRACE("Vol=%ld Pan=%ld\n", volpan->lVolume, volpan->lPan); + TRACE("Vol=%d Pan=%d\n", volpan->lVolume, volpan->lPan); } +/** Convert a primary buffer position to a pointer position for device->mix_buffer + * device: DirectSoundDevice for which to calculate + * pos: Primary buffer position to converts + * Returns: Offset for mix_buffer + */ +DWORD DSOUND_bufpos_to_mixpos(const DirectSoundDevice* device, DWORD pos) +{ + DWORD ret = pos * 32 / device->pwfx->wBitsPerSample; + if (device->pwfx->wBitsPerSample == 32) + ret *= 2; + return ret; +} + +/* NOTE: Not all secpos have to always be mapped to a bufpos, other way around is always the case + * DWORD64 is used here because a single DWORD wouldn't be big enough to fit the freqAcc for big buffers + */ +/** This function converts a 'native' sample pointer to a resampled pointer that fits for primary + * secmixpos is used to decide which freqAcc is needed + * overshot tells what the 'actual' secpos is now (optional) + */ +DWORD DSOUND_secpos_to_bufpos(const IDirectSoundBufferImpl *dsb, DWORD secpos, DWORD secmixpos, DWORD* overshot) +{ + DWORD64 framelen = secpos / dsb->pwfx->nBlockAlign; + DWORD64 freqAdjust = dsb->freqAdjust; + DWORD64 acc, freqAcc; + + if (secpos < secmixpos) + freqAcc = dsb->freqAccNext; + else freqAcc = dsb->freqAcc; + acc = (framelen << DSOUND_FREQSHIFT) + (freqAdjust - 1 - freqAcc); + acc /= freqAdjust; + if (overshot) + { + DWORD64 oshot = acc * freqAdjust + freqAcc; + assert(oshot >= framelen << DSOUND_FREQSHIFT); + oshot -= framelen << DSOUND_FREQSHIFT; + *overshot = (DWORD)oshot; + assert(*overshot < dsb->freqAdjust); + } + return (DWORD)acc * dsb->device->pwfx->nBlockAlign; +} + +/** Convert a resampled pointer that fits for primary to a 'native' sample pointer + * freqAccNext is used here rather than freqAcc: In case the app wants to fill up to + * the play position it won't overwrite it + */ +static DWORD DSOUND_bufpos_to_secpos(const IDirectSoundBufferImpl *dsb, DWORD bufpos) +{ + DWORD oAdv = dsb->device->pwfx->nBlockAlign, iAdv = dsb->pwfx->nBlockAlign, pos; + DWORD64 framelen; + DWORD64 acc; + + framelen = bufpos/oAdv; + acc = framelen * (DWORD64)dsb->freqAdjust + (DWORD64)dsb->freqAccNext; + acc = acc >> DSOUND_FREQSHIFT; + pos = (DWORD)acc * iAdv; + if (pos >= dsb->buflen) + /* Because of differences between freqAcc and freqAccNext, this might happen */ + pos = dsb->buflen - iAdv; + TRACE("Converted %d/%d to %d/%d\n", bufpos, dsb->tmp_buffer_len, pos, dsb->buflen); + return pos; +} + +/** + * Move freqAccNext to freqAcc, and find new values for buffer length and freqAccNext + */ +static void DSOUND_RecalcFreqAcc(IDirectSoundBufferImpl *dsb) +{ + if (!dsb->freqneeded) return; + dsb->freqAcc = dsb->freqAccNext; + dsb->tmp_buffer_len = DSOUND_secpos_to_bufpos(dsb, dsb->buflen, 0, &dsb->freqAccNext); + TRACE("New freqadjust: %04x, new buflen: %d\n", dsb->freqAccNext, dsb->tmp_buffer_len); +} + +/** + * Recalculate the size for temporary buffer, and new writelead + * Should be called when one of the following things occur: + * - Primary buffer format is changed + * - This buffer format (frequency) is changed + * + * After this, DSOUND_MixToTemporary(dsb, 0, dsb->buflen) should + * be called to refill the temporary buffer with data. + */ void DSOUND_RecalcFormat(IDirectSoundBufferImpl *dsb) { + BOOL needremix = TRUE, needresample = (dsb->freq != dsb->device->pwfx->nSamplesPerSec); + DWORD bAlign = dsb->pwfx->nBlockAlign, pAlign = dsb->device->pwfx->nBlockAlign; + TRACE("(%p)\n",dsb); /* calculate the 10ms write lead */ dsb->writelead = (dsb->freq / 100) * dsb->pwfx->nBlockAlign; + + if ((dsb->pwfx->wBitsPerSample == dsb->device->pwfx->wBitsPerSample) && + (dsb->pwfx->nChannels == dsb->device->pwfx->nChannels) && !needresample) + needremix = FALSE; + HeapFree(GetProcessHeap(), 0, dsb->tmp_buffer); + dsb->tmp_buffer = NULL; + dsb->max_buffer_len = dsb->freqAcc = dsb->freqAccNext = 0; + dsb->freqneeded = needresample; + + dsb->convert = convertbpp[dsb->pwfx->wBitsPerSample/8 - 1][dsb->device->pwfx->wBitsPerSample/8 - 1]; + + dsb->resampleinmixer = FALSE; + + if (needremix) + { + if (needresample) + DSOUND_RecalcFreqAcc(dsb); + else + dsb->tmp_buffer_len = dsb->buflen / bAlign * pAlign; + dsb->max_buffer_len = dsb->tmp_buffer_len; + if ((dsb->max_buffer_len <= dsb->device->buflen || dsb->max_buffer_len < ds_snd_shadow_maxsize * 1024 * 1024) && ds_snd_shadow_maxsize >= 0) + dsb->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, dsb->max_buffer_len); + if (dsb->tmp_buffer) + FillMemory(dsb->tmp_buffer, dsb->tmp_buffer_len, dsb->device->pwfx->wBitsPerSample == 8 ? 128 : 0); + else + dsb->resampleinmixer = TRUE; + } + else dsb->max_buffer_len = dsb->tmp_buffer_len = dsb->buflen; + dsb->buf_mixpos = DSOUND_secpos_to_bufpos(dsb, dsb->sec_mixpos, 0, NULL); } -void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len) +/** + * Check for application callback requests for when the play position + * reaches certain points. + * + * The offsets that will be triggered will be those between the recorded + * "last played" position for the buffer (i.e. dsb->playpos) and "len" bytes + * beyond that position. + */ +void DSOUND_CheckEvent(const IDirectSoundBufferImpl *dsb, DWORD playpos, int len) { int i; DWORD offset; @@ -107,15 +231,17 @@ void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len) if (dsb->nrofnotifies == 0) return; - TRACE("(%p) buflen = %ld, playpos = %ld, len = %d\n", - dsb, dsb->buflen, dsb->playpos, len); + TRACE("(%p) buflen = %d, playpos = %d, len = %d\n", + dsb, dsb->buflen, playpos, len); for (i = 0; i < dsb->nrofnotifies ; i++) { event = dsb->notifies + i; offset = event->dwOffset; - TRACE("checking %d, position %ld, event = %p\n", + TRACE("checking %d, position %d, event = %p\n", i, offset, event->hEventNotify); /* DSBPN_OFFSETSTOP has to be the last element. So this is */ /* OK. [Inside DirectX, p274] */ + /* Windows does not seem to enforce this, and some apps rely */ + /* on that, so we can't stop there. */ /* */ /* This also means we can't sort the entries by offset, */ /* because DSBPN_OFFSETSTOP == -1 */ @@ -123,18 +249,17 @@ void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len) if (dsb->state == STATE_STOPPED) { SetEvent(event->hEventNotify); TRACE("signalled event %p (%d)\n", event->hEventNotify, i); - return; - } else - return; + } + continue; } - if ((dsb->playpos + len) >= dsb->buflen) { - if ((offset < ((dsb->playpos + len) % dsb->buflen)) || - (offset >= dsb->playpos)) { + if ((playpos + len) >= dsb->buflen) { + if ((offset < ((playpos + len) % dsb->buflen)) || + (offset >= playpos)) { TRACE("signalled event %p (%d)\n", event->hEventNotify, i); SetEvent(event->hEventNotify); } } else { - if ((offset >= dsb->playpos) && (offset < (dsb->playpos + len))) { + if ((offset >= playpos) && (offset < (playpos + len))) { TRACE("signalled event %p (%d)\n", event->hEventNotify, i); SetEvent(event->hEventNotify); } @@ -142,954 +267,705 @@ void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len) } } -/* WAV format info can be found at: - * - * http://www.cwi.nl/ftp/audio/AudioFormats.part2 - * ftp://ftp.cwi.nl/pub/audio/RIFF-format - * - * Import points to remember: - * 8-bit WAV is unsigned - * 16-bit WAV is signed +/** + * Copy a single frame from the given input buffer to the given output buffer. + * Translate 8 <-> 16 bits and mono <-> stereo */ - /* Use the same formulas as pcmconverter.c */ -static inline INT16 cvtU8toS16(BYTE b) +static inline void cp_fields(const IDirectSoundBufferImpl *dsb, const BYTE *ibuf, BYTE *obuf, + UINT istride, UINT ostride, UINT count, UINT freqAcc, UINT adj) { - return (short)((b+(b << 8))-32768); -} + DirectSoundDevice *device = dsb->device; + INT istep = dsb->pwfx->wBitsPerSample / 8, ostep = device->pwfx->wBitsPerSample / 8; -static inline BYTE cvtS16toU8(INT16 s) -{ - return (s >> 8) ^ (unsigned char)0x80; + if (device->pwfx->nChannels == dsb->pwfx->nChannels) { + dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj); + if (device->pwfx->nChannels == 2) + dsb->convert(ibuf + istep, obuf + ostep, istride, ostride, count, freqAcc, adj); + } + + if (device->pwfx->nChannels == 1 && dsb->pwfx->nChannels == 2) + { + dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj); + } + + if (device->pwfx->nChannels == 2 && dsb->pwfx->nChannels == 1) + { + dsb->convert(ibuf, obuf, istride, ostride, count, freqAcc, adj); + dsb->convert(ibuf, obuf + ostep, istride, ostride, count, freqAcc, adj); + } } -static inline void cp_fields(const IDirectSoundBufferImpl *dsb, BYTE *ibuf, BYTE *obuf ) +/** + * Calculate the distance between two buffer offsets, taking wraparound + * into account. + */ +static inline DWORD DSOUND_BufPtrDiff(DWORD buflen, DWORD ptr1, DWORD ptr2) { - DirectSoundDevice * device = dsb->dsound->device; - INT fl,fr; - - if (dsb->pwfx->wBitsPerSample == 8) { - if (device->pwfx->wBitsPerSample == 8 && - device->pwfx->nChannels == dsb->pwfx->nChannels) { - /* avoid needless 8->16->8 conversion */ - *obuf=*ibuf; - if (dsb->pwfx->nChannels==2) - *(obuf+1)=*(ibuf+1); - return; - } - fl = cvtU8toS16(*ibuf); - fr = (dsb->pwfx->nChannels==2 ? cvtU8toS16(*(ibuf + 1)) : fl); - } else { - fl = *((INT16 *)ibuf); - fr = (dsb->pwfx->nChannels==2 ? *(((INT16 *)ibuf) + 1) : fl); - } - - if (device->pwfx->nChannels == 2) { - if (device->pwfx->wBitsPerSample == 8) { - *obuf = cvtS16toU8(fl); - *(obuf + 1) = cvtS16toU8(fr); - return; - } - if (device->pwfx->wBitsPerSample == 16) { - *((INT16 *)obuf) = fl; - *(((INT16 *)obuf) + 1) = fr; - return; - } - } - if (device->pwfx->nChannels == 1) { - fl = (fl + fr) >> 1; - if (device->pwfx->wBitsPerSample == 8) { - *obuf = cvtS16toU8(fl); - return; - } - if (device->pwfx->wBitsPerSample == 16) { - *((INT16 *)obuf) = fl; - return; - } - } +/* If these asserts fail, the problem is not here, but in the underlying code */ + assert(ptr1 < buflen); + assert(ptr2 < buflen); + if (ptr1 >= ptr2) { + return ptr1 - ptr2; + } else { + return buflen + ptr1 - ptr2; + } } - -/* Now with PerfectPitch (tm) technology */ -static INT DSOUND_MixerNorm(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len) +/** + * Mix at most the given amount of data into the allocated temporary buffer + * of the given secondary buffer, starting from the dsb's first currently + * unsampled frame (writepos), translating frequency (pitch), stereo/mono + * and bits-per-sample so that it is ideal for the primary buffer. + * Doesn't perform any mixing - this is a straight copy/convert operation. + * + * dsb = the secondary buffer + * writepos = Starting position of changed buffer + * len = number of bytes to resample from writepos + * + * NOTE: writepos + len <= buflen. When called by mixer, MixOne makes sure of this. + */ +void DSOUND_MixToTemporary(const IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len, BOOL inmixer) { - INT i, size, ipos, ilen; - BYTE *ibp, *obp; + INT size; + BYTE *ibp, *obp, *obp_begin; INT iAdvance = dsb->pwfx->nBlockAlign; - INT oAdvance = dsb->dsound->device->pwfx->nBlockAlign; - - ibp = dsb->buffer->memory + dsb->buf_mixpos; - obp = buf; - - TRACE("(%p, %p, %p), buf_mixpos=%ld\n", dsb, ibp, obp, dsb->buf_mixpos); - /* Check for the best case */ - if ((dsb->freq == dsb->dsound->device->pwfx->nSamplesPerSec) && - (dsb->pwfx->wBitsPerSample == dsb->dsound->device->pwfx->wBitsPerSample) && - (dsb->pwfx->nChannels == dsb->dsound->device->pwfx->nChannels)) { - INT bytesleft = dsb->buflen - dsb->buf_mixpos; - TRACE("(%p) Best case\n", dsb); - if (len <= bytesleft ) - CopyMemory(obp, ibp, len); - else { /* wrap */ - CopyMemory(obp, ibp, bytesleft); - CopyMemory(obp + bytesleft, dsb->buffer->memory, len - bytesleft); - } - return len; + INT oAdvance = dsb->device->pwfx->nBlockAlign; + DWORD freqAcc, target_writepos = 0, overshot, maxlen; + + /* We resample only when needed */ + if ((dsb->tmp_buffer && inmixer) || (!dsb->tmp_buffer && !inmixer) || dsb->resampleinmixer != inmixer) + return; + + assert(writepos + len <= dsb->buflen); + if (inmixer && writepos + len < dsb->buflen) + len += dsb->pwfx->nBlockAlign; + + maxlen = DSOUND_secpos_to_bufpos(dsb, len, 0, NULL); + + ibp = dsb->buffer->memory + writepos; + if (!inmixer) + obp_begin = dsb->tmp_buffer; + else if (dsb->device->tmp_buffer_len < maxlen || !dsb->device->tmp_buffer) + { + dsb->device->tmp_buffer_len = maxlen; + if (dsb->device->tmp_buffer) + dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, maxlen); + else + dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, maxlen); + obp_begin = dsb->device->tmp_buffer; } + else + obp_begin = dsb->device->tmp_buffer; + + TRACE("(%p, %p)\n", dsb, ibp); + size = len / iAdvance; /* Check for same sample rate */ - if (dsb->freq == dsb->dsound->device->pwfx->nSamplesPerSec) { - TRACE("(%p) Same sample rate %ld = primary %ld\n", dsb, - dsb->freq, dsb->dsound->device->pwfx->nSamplesPerSec); - ilen = 0; - for (i = 0; i < len; i += oAdvance) { - cp_fields(dsb, ibp, obp ); - ibp += iAdvance; - ilen += iAdvance; - obp += oAdvance; - if (ibp >= (BYTE *)(dsb->buffer->memory + dsb->buflen)) - ibp = dsb->buffer->memory; /* wrap */ - } - return (ilen); + if (dsb->freq == dsb->device->pwfx->nSamplesPerSec) { + TRACE("(%p) Same sample rate %d = primary %d\n", dsb, + dsb->freq, dsb->device->pwfx->nSamplesPerSec); + obp = obp_begin; + if (!inmixer) + obp += writepos/iAdvance*oAdvance; + + cp_fields(dsb, ibp, obp, iAdvance, oAdvance, size, 0, 1 << DSOUND_FREQSHIFT); + return; } /* Mix in different sample rates */ - /* */ - /* New PerfectPitch(tm) Technology (c) 1998 Rob Riggs */ - /* Patent Pending :-] */ - - /* Patent enhancements (c) 2000 Ove KÃ¥ven, - * TransGaming Technologies Inc. */ - - /* FIXME("(%p) Adjusting frequency: %ld -> %ld (need optimization)\n", - dsb, dsb->freq, dsb->dsound->device->pwfx->nSamplesPerSec); */ - - size = len / oAdvance; - ilen = 0; - ipos = dsb->buf_mixpos; - for (i = 0; i < size; i++) { - cp_fields(dsb, (dsb->buffer->memory + ipos), obp); - obp += oAdvance; - dsb->freqAcc += dsb->freqAdjust; - if (dsb->freqAcc >= (1<freqAcc>>DSOUND_FREQSHIFT) * iAdvance; - dsb->freqAcc &= (1<buflen; - } + TRACE("(%p) Adjusting frequency: %d -> %d\n", dsb, dsb->freq, dsb->device->pwfx->nSamplesPerSec); + + target_writepos = DSOUND_secpos_to_bufpos(dsb, writepos, dsb->sec_mixpos, &freqAcc); + overshot = freqAcc >> DSOUND_FREQSHIFT; + if (overshot) + { + if (overshot >= size) + return; + size -= overshot; + writepos += overshot * iAdvance; + if (writepos >= dsb->buflen) + return; + ibp = dsb->buffer->memory + writepos; + freqAcc &= (1 << DSOUND_FREQSHIFT) - 1; + TRACE("Overshot: %d, freqAcc: %04x\n", overshot, freqAcc); } - return ilen; + + if (!inmixer) + obp = obp_begin + target_writepos; + else obp = obp_begin; + + /* FIXME: Small problem here when we're overwriting buf_mixpos, it then STILL uses old freqAcc, not sure if it matters or not */ + cp_fields(dsb, ibp, obp, iAdvance, oAdvance, size, freqAcc, dsb->freqAdjust); } -static void DSOUND_MixerVol(IDirectSoundBufferImpl *dsb, BYTE *buf, INT len) +/** Apply volume to the given soundbuffer from (primary) position writepos and length len + * Returns: NULL if no volume needs to be applied + * or else a memory handle that holds 'len' volume adjusted buffer */ +static LPBYTE DSOUND_MixerVol(const IDirectSoundBufferImpl *dsb, INT len) { INT i; - BYTE *bpc = buf; - INT16 *bps = (INT16 *) buf; + BYTE *bpc; + INT16 *bps, *mems; + DWORD vLeft, vRight; + INT nChannels = dsb->device->pwfx->nChannels; + LPBYTE mem = (dsb->tmp_buffer ? dsb->tmp_buffer : dsb->buffer->memory) + dsb->buf_mixpos; - TRACE("(%p,%p,%d)\n",dsb,buf,len); - TRACE("left = %lx, right = %lx\n", dsb->cvolpan.dwTotalLeftAmpFactor, - dsb->cvolpan.dwTotalRightAmpFactor); + if (dsb->resampleinmixer) + mem = dsb->device->tmp_buffer; - if ((!(dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || (dsb->cvolpan.lPan == 0)) && - (!(dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) || (dsb->cvolpan.lVolume == 0)) && - !(dsb->dsbd.dwFlags & DSBCAPS_CTRL3D)) - return; /* Nothing to do */ + TRACE("(%p,%d)\n",dsb,len); + TRACE("left = %x, right = %x\n", dsb->volpan.dwTotalLeftAmpFactor, + dsb->volpan.dwTotalRightAmpFactor); + + if ((!(dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || (dsb->volpan.lPan == 0)) && + (!(dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) || (dsb->volpan.lVolume == 0)) && + !(dsb->dsbd.dwFlags & DSBCAPS_CTRL3D)) + return NULL; /* Nothing to do */ + + if (nChannels != 1 && nChannels != 2) + { + FIXME("There is no support for %d channels\n", nChannels); + return NULL; + } - /* If we end up with some bozo coder using panning or 3D sound */ - /* with a mono primary buffer, it could sound very weird using */ - /* this method. Oh well, tough patooties. */ + if (dsb->device->pwfx->wBitsPerSample != 8 && dsb->device->pwfx->wBitsPerSample != 16) + { + FIXME("There is no support for %d bpp\n", dsb->device->pwfx->wBitsPerSample); + return NULL; + } - switch (dsb->dsound->device->pwfx->wBitsPerSample) { + if (dsb->device->tmp_buffer_len < len || !dsb->device->tmp_buffer) + { + /* If we just resampled in DSOUND_MixToTemporary, we shouldn't need to resize here */ + assert(!dsb->resampleinmixer); + dsb->device->tmp_buffer_len = len; + if (dsb->device->tmp_buffer) + dsb->device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, dsb->device->tmp_buffer, len); + else + dsb->device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, len); + } + + bpc = dsb->device->tmp_buffer; + bps = (INT16 *)bpc; + mems = (INT16 *)mem; + vLeft = dsb->volpan.dwTotalLeftAmpFactor; + if (nChannels > 1) + vRight = dsb->volpan.dwTotalRightAmpFactor; + else + vRight = vLeft; + + switch (dsb->device->pwfx->wBitsPerSample) { case 8: /* 8-bit WAV is unsigned, but we need to operate */ /* on signed data for this to work properly */ - switch (dsb->dsound->device->pwfx->nChannels) { - case 1: - for (i = 0; i < len; i++) { - INT val = *bpc - 128; - val = (val * dsb->cvolpan.dwTotalLeftAmpFactor) >> 16; - *bpc = val + 128; - bpc++; - } - break; - case 2: - for (i = 0; i < len; i+=2) { - INT val = *bpc - 128; - val = (val * dsb->cvolpan.dwTotalLeftAmpFactor) >> 16; - *bpc++ = val + 128; - val = *bpc - 128; - val = (val * dsb->cvolpan.dwTotalRightAmpFactor) >> 16; - *bpc = val + 128; - bpc++; - } - break; - default: - FIXME("doesn't support %d channels\n", dsb->dsound->device->pwfx->nChannels); - break; + for (i = 0; i < len-1; i+=2) { + *(bpc++) = (((*(mem++) - 128) * vLeft) >> 16) + 128; + *(bpc++) = (((*(mem++) - 128) * vRight) >> 16) + 128; } + if (len % 2 == 1 && nChannels == 1) + *(bpc++) = (((*(mem++) - 128) * vLeft) >> 16) + 128; break; case 16: /* 16-bit WAV is signed -- much better */ - switch (dsb->dsound->device->pwfx->nChannels) { - case 1: - for (i = 0; i < len; i += 2) { - *bps = (*bps * dsb->cvolpan.dwTotalLeftAmpFactor) >> 16; - bps++; - } - break; - case 2: - for (i = 0; i < len; i += 4) { - *bps = (*bps * dsb->cvolpan.dwTotalLeftAmpFactor) >> 16; - bps++; - *bps = (*bps * dsb->cvolpan.dwTotalRightAmpFactor) >> 16; - bps++; - } - break; - default: - FIXME("doesn't support %d channels\n", dsb->dsound->device->pwfx->nChannels); - break; + for (i = 0; i < len-3; i += 4) { + *(bps++) = (*(mems++) * vLeft) >> 16; + *(bps++) = (*(mems++) * vRight) >> 16; } - break; - default: - FIXME("doesn't support %d bit samples\n", dsb->dsound->device->pwfx->wBitsPerSample); + if (len % 4 == 2 && nChannels == 1) + *(bps++) = ((INT)*(mems++) * vLeft) >> 16; break; } + return dsb->device->tmp_buffer; } -static LPBYTE DSOUND_tmpbuffer(DirectSoundDevice *device, DWORD len) +/** + * Mix (at most) the given number of bytes into the given position of the + * device buffer, from the secondary buffer "dsb" (starting at the current + * mix position for that buffer). + * + * Returns the number of bytes actually mixed into the device buffer. This + * will match fraglen unless the end of the secondary buffer is reached + * (and it is not looping). + * + * dsb = the secondary buffer to mix from + * writepos = position (offset) in device buffer to write at + * fraglen = number of bytes to mix + */ +static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen) { - TRACE("(%p,%ld)\n", device, len); + INT len = fraglen, ilen; + BYTE *ibuf = (dsb->tmp_buffer ? dsb->tmp_buffer : dsb->buffer->memory) + dsb->buf_mixpos, *volbuf; + DWORD oldpos, mixbufpos; - if (len > device->tmp_buffer_len) { - if (device->tmp_buffer) - device->tmp_buffer = HeapReAlloc(GetProcessHeap(), 0, device->tmp_buffer, len); - else - device->tmp_buffer = HeapAlloc(GetProcessHeap(), 0, len); + TRACE("buf_mixpos=%d/%d sec_mixpos=%d/%d\n", dsb->buf_mixpos, dsb->tmp_buffer_len, dsb->sec_mixpos, dsb->buflen); + TRACE("(%p,%d,%d)\n",dsb,writepos,fraglen); - device->tmp_buffer_len = len; - } - - return device->tmp_buffer; -} + assert(dsb->buf_mixpos + len <= dsb->tmp_buffer_len); -static DWORD DSOUND_MixInBuffer(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD fraglen) -{ - INT i, len, ilen, field, todo; - BYTE *buf, *ibuf; - - TRACE("(%p,%ld,%ld)\n",dsb,writepos,fraglen); - - len = fraglen; - if (!(dsb->playflags & DSBPLAY_LOOPING)) { - int secondary_remainder = dsb->buflen - dsb->buf_mixpos; - int adjusted_remainder = MulDiv(dsb->dsound->device->pwfx->nAvgBytesPerSec, secondary_remainder, dsb->nAvgBytesPerSec); - assert(adjusted_remainder >= 0); - TRACE("secondary_remainder = %d, adjusted_remainder = %d, len = %d\n", secondary_remainder, adjusted_remainder, len); - if (adjusted_remainder < len) { - TRACE("clipping len to remainder of secondary buffer\n"); - len = adjusted_remainder; - } - if (len == 0) - return 0; - } - - if (len % dsb->dsound->device->pwfx->nBlockAlign) { - INT nBlockAlign = dsb->dsound->device->pwfx->nBlockAlign; + if (len % dsb->device->pwfx->nBlockAlign) { + INT nBlockAlign = dsb->device->pwfx->nBlockAlign; ERR("length not a multiple of block size, len = %d, block size = %d\n", len, nBlockAlign); - len = (len / nBlockAlign) * nBlockAlign; /* data alignment */ + len -= len % nBlockAlign; /* data alignment */ } - if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound->device, len)) == NULL) - return 0; - - TRACE("MixInBuffer (%p) len = %d, dest = %ld\n", dsb, len, writepos); - - ilen = DSOUND_MixerNorm(dsb, ibuf, len); - if ((dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || - (dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) || - (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D)) - DSOUND_MixerVol(dsb, ibuf, len); - - if (dsb->dsound->device->pwfx->wBitsPerSample == 8) { - BYTE *obuf = dsb->dsound->device->buffer + writepos; - - if ((writepos + len) <= dsb->dsound->device->buflen) - todo = len; - else - todo = dsb->dsound->device->buflen - writepos; - - for (i = 0; i < todo; i++) { - /* 8-bit WAV is unsigned */ - field = (*ibuf++ - 128); - field += (*obuf - 128); - if (field > 127) field = 127; - else if (field < -128) field = -128; - *obuf++ = field + 128; - } - - if (todo < len) { - todo = len - todo; - obuf = dsb->dsound->device->buffer; - - for (i = 0; i < todo; i++) { - /* 8-bit WAV is unsigned */ - field = (*ibuf++ - 128); - field += (*obuf - 128); - if (field > 127) field = 127; - else if (field < -128) field = -128; - *obuf++ = field + 128; - } - } - } else { - INT16 *ibufs, *obufs; - - ibufs = (INT16 *) ibuf; - obufs = (INT16 *)(dsb->dsound->device->buffer + writepos); - - if ((writepos + len) <= dsb->dsound->device->buflen) - todo = len / 2; - else - todo = (dsb->dsound->device->buflen - writepos) / 2; - - for (i = 0; i < todo; i++) { - /* 16-bit WAV is signed */ - field = *ibufs++; - field += *obufs; - if (field > 32767) field = 32767; - else if (field < -32768) field = -32768; - *obufs++ = field; - } - - if (todo < (len / 2)) { - todo = (len / 2) - todo; - obufs = (INT16 *)dsb->dsound->device->buffer; - - for (i = 0; i < todo; i++) { - /* 16-bit WAV is signed */ - field = *ibufs++; - field += *obufs; - if (field > 32767) field = 32767; - else if (field < -32768) field = -32768; - *obufs++ = field; - } - } - } - - if (dsb->leadin && (dsb->startpos > dsb->buf_mixpos) && (dsb->startpos <= dsb->buf_mixpos + ilen)) { - /* HACK... leadin should be reset when the PLAY position reaches the startpos, - * not the MIX position... but if the sound buffer is bigger than our prebuffering - * (which must be the case for the streaming buffers that need this hack anyway) - * plus DS_HEL_MARGIN or equivalent, then this ought to work anyway. */ - dsb->leadin = FALSE; + /* Resample buffer to temporary buffer specifically allocated for this purpose, if needed */ + DSOUND_MixToTemporary(dsb, dsb->sec_mixpos, DSOUND_bufpos_to_secpos(dsb, dsb->buf_mixpos+len) - dsb->sec_mixpos, TRUE); + if (dsb->resampleinmixer) + ibuf = dsb->device->tmp_buffer; + + /* Apply volume if needed */ + volbuf = DSOUND_MixerVol(dsb, len); + if (volbuf) + ibuf = volbuf; + + mixbufpos = DSOUND_bufpos_to_mixpos(dsb->device, writepos); + /* Now mix the temporary buffer into the devices main buffer */ + if ((writepos + len) <= dsb->device->buflen) + dsb->device->mixfunction(ibuf, dsb->device->mix_buffer + mixbufpos, len); + else + { + DWORD todo = dsb->device->buflen - writepos; + dsb->device->mixfunction(ibuf, dsb->device->mix_buffer + mixbufpos, todo); + dsb->device->mixfunction(ibuf + todo, dsb->device->mix_buffer, len - todo); } - dsb->buf_mixpos += ilen; + oldpos = dsb->sec_mixpos; + dsb->buf_mixpos += len; - if (dsb->buf_mixpos >= dsb->buflen) { + if (dsb->buf_mixpos >= dsb->tmp_buffer_len) { + if (dsb->buf_mixpos > dsb->tmp_buffer_len) + ERR("Mixpos (%u) past buflen (%u), capping...\n", dsb->buf_mixpos, dsb->tmp_buffer_len); if (dsb->playflags & DSBPLAY_LOOPING) { - /* wrap */ - dsb->buf_mixpos %= dsb->buflen; - if (dsb->leadin && (dsb->startpos <= dsb->buf_mixpos)) - dsb->leadin = FALSE; /* HACK: see above */ - } else if (dsb->buf_mixpos > dsb->buflen) { - ERR("Mixpos (%lu) past buflen (%lu), capping...\n", dsb->buf_mixpos, dsb->buflen); - dsb->buf_mixpos = dsb->buflen; + dsb->buf_mixpos -= dsb->tmp_buffer_len; + } else if (dsb->buf_mixpos >= dsb->tmp_buffer_len) { + dsb->buf_mixpos = dsb->sec_mixpos = 0; + dsb->state = STATE_STOPPED; } + DSOUND_RecalcFreqAcc(dsb); } - return len; -} - -static void DSOUND_PhaseCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD len) -{ - INT ilen, field; - UINT i, todo; - BYTE *buf, *ibuf; - - TRACE("(%p,%ld,%ld)\n",dsb,writepos,len); - - if (len % dsb->dsound->device->pwfx->nBlockAlign) { - INT nBlockAlign = dsb->dsound->device->pwfx->nBlockAlign; - ERR("length not a multiple of block size, len = %ld, block size = %d\n", len, nBlockAlign); - len = (len / nBlockAlign) * nBlockAlign; /* data alignment */ + dsb->sec_mixpos = DSOUND_bufpos_to_secpos(dsb, dsb->buf_mixpos); + ilen = DSOUND_BufPtrDiff(dsb->buflen, dsb->sec_mixpos, oldpos); + /* check for notification positions */ + if (dsb->dsbd.dwFlags & DSBCAPS_CTRLPOSITIONNOTIFY && + dsb->state != STATE_STARTING) { + DSOUND_CheckEvent(dsb, oldpos, ilen); } - if ((buf = ibuf = DSOUND_tmpbuffer(dsb->dsound->device, len)) == NULL) - return; - - TRACE("PhaseCancel (%p) len = %ld, dest = %ld\n", dsb, len, writepos); - - ilen = DSOUND_MixerNorm(dsb, ibuf, len); - if ((dsb->dsbd.dwFlags & DSBCAPS_CTRLPAN) || - (dsb->dsbd.dwFlags & DSBCAPS_CTRLVOLUME) || - (dsb->dsbd.dwFlags & DSBCAPS_CTRL3D)) - DSOUND_MixerVol(dsb, ibuf, len); - - /* subtract instead of add, to phase out premixed data */ - if (dsb->dsound->device->pwfx->wBitsPerSample == 8) { - BYTE *obuf = dsb->dsound->device->buffer + writepos; - - if ((writepos + len) <= dsb->dsound->device->buflen) - todo = len; - else - todo = dsb->dsound->device->buflen - writepos; - - for (i = 0; i < todo; i++) { - /* 8-bit WAV is unsigned */ - field = (*ibuf++ - 128); - field -= (*obuf - 128); - if (field > 127) field = 127; - else if (field < -128) field = -128; - *obuf++ = field + 128; - } - - if (todo < len) { - todo = len - todo; - obuf = dsb->dsound->device->buffer; - - for (i = 0; i < todo; i++) { - /* 8-bit WAV is unsigned */ - field = (*ibuf++ - 128); - field -= (*obuf - 128); - if (field > 127) field = 127; - else if (field < -128) field = -128; - *obuf++ = field + 128; - } - } - } else { - INT16 *ibufs, *obufs; - - ibufs = (INT16 *) ibuf; - obufs = (INT16 *)(dsb->dsound->device->buffer + writepos); - - if ((writepos + len) <= dsb->dsound->device->buflen) - todo = len / 2; - else - todo = (dsb->dsound->device->buflen - writepos) / 2; - - for (i = 0; i < todo; i++) { - /* 16-bit WAV is signed */ - field = *ibufs++; - field -= *obufs; - if (field > 32767) field = 32767; - else if (field < -32768) field = -32768; - *obufs++ = field; - } - - if (todo < (len / 2)) { - todo = (len / 2) - todo; - obufs = (INT16 *)dsb->dsound->device->buffer; - - for (i = 0; i < todo; i++) { - /* 16-bit WAV is signed */ - field = *ibufs++; - field -= *obufs; - if (field > 32767) field = 32767; - else if (field < -32768) field = -32768; - *obufs++ = field; - } - } - } + /* increase mix position */ + dsb->primary_mixpos += len; + if (dsb->primary_mixpos >= dsb->device->buflen) + dsb->primary_mixpos -= dsb->device->buflen; + return len; } -static void DSOUND_MixCancel(IDirectSoundBufferImpl *dsb, DWORD writepos, BOOL cancel) +/** + * Mix some frames from the given secondary buffer "dsb" into the device + * primary buffer. + * + * dsb = the secondary buffer + * playpos = the current play position in the device buffer (primary buffer) + * writepos = the current safe-to-write position in the device buffer + * mixlen = the maximum number of bytes in the primary buffer to mix, from the + * current writepos. + * + * Returns: the number of bytes beyond the writepos that were mixed. + */ +static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD writepos, DWORD mixlen) { - DWORD size, flen, len, npos, nlen; - INT iAdvance = dsb->pwfx->nBlockAlign; - INT oAdvance = dsb->dsound->device->pwfx->nBlockAlign; - /* determine amount of premixed data to cancel */ - DWORD primary_done = - ((dsb->primary_mixpos < writepos) ? dsb->dsound->device->buflen : 0) + - dsb->primary_mixpos - writepos; - - TRACE("(%p, %ld), buf_mixpos=%ld\n", dsb, writepos, dsb->buf_mixpos); - - /* backtrack the mix position */ - size = primary_done / oAdvance; - flen = size * dsb->freqAdjust; - len = (flen >> DSOUND_FREQSHIFT) * iAdvance; - flen &= (1<freqAcc < flen) { - len += iAdvance; - dsb->freqAcc += 1<buflen; - npos = ((dsb->buf_mixpos < len) ? dsb->buflen : 0) + - dsb->buf_mixpos - len; - if (dsb->leadin && (dsb->startpos > npos) && (dsb->startpos <= npos + len)) { - /* stop backtracking at startpos */ - npos = dsb->startpos; - len = ((dsb->buf_mixpos < npos) ? dsb->buflen : 0) + - dsb->buf_mixpos - npos; - flen = dsb->freqAcc; - nlen = len / dsb->pwfx->nBlockAlign; - nlen = ((nlen << DSOUND_FREQSHIFT) + flen) / dsb->freqAdjust; - nlen *= dsb->dsound->device->pwfx->nBlockAlign; - writepos = - ((dsb->primary_mixpos < nlen) ? dsb->dsound->device->buflen : 0) + - dsb->primary_mixpos - nlen; + /* The buffer's primary_mixpos may be before or after the device + * buffer's mixpos, but both must be ahead of writepos. */ + DWORD primary_done; + + TRACE("(%p,%d,%d)\n",dsb,writepos,mixlen); + TRACE("writepos=%d, buf_mixpos=%d, primary_mixpos=%d, mixlen=%d\n", writepos, dsb->buf_mixpos, dsb->primary_mixpos, mixlen); + TRACE("looping=%d, leadin=%d, buflen=%d\n", dsb->playflags, dsb->leadin, dsb->tmp_buffer_len); + + /* If leading in, only mix about 20 ms, and 'skip' mixing the rest, for more fluid pointer advancement */ + if (dsb->leadin && dsb->state == STATE_STARTING) + { + if (mixlen > 2 * dsb->device->fraglen) + { + dsb->primary_mixpos += mixlen - 2 * dsb->device->fraglen; + dsb->primary_mixpos %= dsb->device->buflen; + } } + dsb->leadin = FALSE; - dsb->freqAcc -= flen; - dsb->buf_mixpos = npos; - dsb->primary_mixpos = writepos; + /* calculate how much pre-buffering has already been done for this buffer */ + primary_done = DSOUND_BufPtrDiff(dsb->device->buflen, dsb->primary_mixpos, writepos); - TRACE("new buf_mixpos=%ld, primary_mixpos=%ld (len=%ld)\n", - dsb->buf_mixpos, dsb->primary_mixpos, len); - - if (cancel) DSOUND_PhaseCancel(dsb, writepos, len); -} - -void DSOUND_MixCancelAt(IDirectSoundBufferImpl *dsb, DWORD buf_writepos) -{ -#if 0 - DWORD i, size, flen, len, npos, nlen; - INT iAdvance = dsb->pwfx->nBlockAlign; - INT oAdvance = dsb->dsound->device->pwfx->nBlockAlign; - /* determine amount of premixed data to cancel */ - DWORD buf_done = - ((dsb->buf_mixpos < buf_writepos) ? dsb->buflen : 0) + - dsb->buf_mixpos - buf_writepos; -#endif - - WARN("(%p, %ld), buf_mixpos=%ld\n", dsb, buf_writepos, dsb->buf_mixpos); - /* since this is not implemented yet, just cancel *ALL* prebuffering for now - * (which is faster anyway when there's only a single secondary buffer) */ - dsb->dsound->device->need_remix = TRUE; -} - -void DSOUND_ForceRemix(IDirectSoundBufferImpl *dsb) -{ - TRACE("(%p)\n",dsb); - EnterCriticalSection(&dsb->lock); - if (dsb->state == STATE_PLAYING) - dsb->dsound->device->need_remix = TRUE; - LeaveCriticalSection(&dsb->lock); -} - -static DWORD DSOUND_MixOne(IDirectSoundBufferImpl *dsb, DWORD playpos, DWORD writepos, DWORD mixlen) -{ - DWORD len, slen; - /* determine this buffer's write position */ - DWORD buf_writepos = DSOUND_CalcPlayPosition(dsb, writepos, writepos); - /* determine how much already-mixed data exists */ - DWORD buf_done = - ((dsb->buf_mixpos < buf_writepos) ? dsb->buflen : 0) + - dsb->buf_mixpos - buf_writepos; - DWORD primary_done = - ((dsb->primary_mixpos < writepos) ? dsb->dsound->device->buflen : 0) + - dsb->primary_mixpos - writepos; - DWORD adv_done = - ((dsb->dsound->device->mixpos < writepos) ? dsb->dsound->device->buflen : 0) + - dsb->dsound->device->mixpos - writepos; - DWORD played = - ((buf_writepos < dsb->playpos) ? dsb->buflen : 0) + - buf_writepos - dsb->playpos; - DWORD buf_left = dsb->buflen - buf_writepos; - int still_behind; - - TRACE("(%p,%ld,%ld,%ld)\n",dsb,playpos,writepos,mixlen); - TRACE("buf_writepos=%ld, primary_writepos=%ld\n", buf_writepos, writepos); - TRACE("buf_done=%ld, primary_done=%ld\n", buf_done, primary_done); - TRACE("buf_mixpos=%ld, primary_mixpos=%ld, mixlen=%ld\n", dsb->buf_mixpos, dsb->primary_mixpos, - mixlen); - TRACE("looping=%ld, startpos=%ld, leadin=%ld\n", dsb->playflags, dsb->startpos, dsb->leadin); - - /* check for notification positions */ - if (dsb->dsbd.dwFlags & DSBCAPS_CTRLPOSITIONNOTIFY && - dsb->state != STATE_STARTING) { - DSOUND_CheckEvent(dsb, played); + /* sanity */ + if(mixlen < primary_done) + { + /* Should *NEVER* happen */ + ERR("Fatal error. Under/Overflow? primary_done=%d, mixpos=%d/%d (%d/%d), primary_mixpos=%d, writepos=%d, mixlen=%d\n", primary_done,dsb->buf_mixpos,dsb->tmp_buffer_len,dsb->sec_mixpos, dsb->buflen, dsb->primary_mixpos, writepos, mixlen); + return 0; } - /* save write position for non-GETCURRENTPOSITION2... */ - dsb->playpos = buf_writepos; - - /* check whether CalcPlayPosition detected a mixing underrun */ - if ((buf_done == 0) && (dsb->primary_mixpos != writepos)) { - /* it did, but did we have more to play? */ - if ((dsb->playflags & DSBPLAY_LOOPING) || - (dsb->buf_mixpos < dsb->buflen)) { - /* yes, have to recover */ - ERR("underrun on sound buffer %p\n", dsb); - TRACE("recovering from underrun: primary_mixpos=%ld\n", writepos); - } - dsb->primary_mixpos = writepos; - primary_done = 0; - } - /* determine how far ahead we should mix */ - if (((dsb->playflags & DSBPLAY_LOOPING) || - (dsb->leadin && (dsb->probably_valid_to != 0))) && - !(dsb->dsbd.dwFlags & DSBCAPS_STATIC)) { - /* if this is a streaming buffer, it typically means that - * we should defer mixing past probably_valid_to as long - * as we can, to avoid unnecessary remixing */ - /* the heavy-looking calculations shouldn't be that bad, - * as any game isn't likely to be have more than 1 or 2 - * streaming buffers in use at any time anyway... */ - DWORD probably_valid_left = - (dsb->probably_valid_to == (DWORD)-1) ? dsb->buflen : - ((dsb->probably_valid_to < buf_writepos) ? dsb->buflen : 0) + - dsb->probably_valid_to - buf_writepos; - /* check for leadin condition */ - if ((probably_valid_left == 0) && - (dsb->probably_valid_to == dsb->startpos) && - dsb->leadin) - probably_valid_left = dsb->buflen; - TRACE("streaming buffer probably_valid_to=%ld, probably_valid_left=%ld\n", - dsb->probably_valid_to, probably_valid_left); - /* check whether the app's time is already up */ - if (probably_valid_left < dsb->writelead) { - WARN("probably_valid_to now within writelead, possible streaming underrun\n"); - /* once we pass the point of no return, - * no reason to hold back anymore */ - dsb->probably_valid_to = (DWORD)-1; - /* we just have to go ahead and mix what we have, - * there's no telling what the app is thinking anyway */ - } else { - /* adjust for our frequency and our sample size */ - probably_valid_left = MulDiv(probably_valid_left, - 1 << DSOUND_FREQSHIFT, - dsb->pwfx->nBlockAlign * dsb->freqAdjust) * - dsb->dsound->device->pwfx->nBlockAlign; - /* check whether to clip mix_len */ - if (probably_valid_left < mixlen) { - TRACE("clipping to probably_valid_left=%ld\n", probably_valid_left); - mixlen = probably_valid_left; + /* take into account already mixed data */ + mixlen -= primary_done; + + TRACE("primary_done=%d, mixlen (primary) = %i\n", primary_done, mixlen); + + if (!mixlen) + return primary_done; + + /* First try to mix to the end of the buffer if possible + * Theoretically it would allow for better optimization + */ + if (mixlen + dsb->buf_mixpos >= dsb->tmp_buffer_len) + { + DWORD newmixed, mixfirst = dsb->tmp_buffer_len - dsb->buf_mixpos; + newmixed = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixfirst); + mixlen -= newmixed; + + if (dsb->playflags & DSBPLAY_LOOPING) + while (newmixed && mixlen) + { + mixfirst = (dsb->tmp_buffer_len < mixlen ? dsb->tmp_buffer_len : mixlen); + newmixed = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixfirst); + mixlen -= newmixed; } - } - } - /* cut mixlen with what's already been mixed */ - if (mixlen < primary_done) { - /* huh? and still CalcPlayPosition didn't - * detect an underrun? */ - FIXME("problem with underrun detection (mixlen=%ld < primary_done=%ld)\n", mixlen, primary_done); - return 0; } - len = mixlen - primary_done; - TRACE("remaining mixlen=%ld\n", len); - - if (len < dsb->dsound->device->fraglen) { - /* smaller than a fragment, wait until it gets larger - * before we take the mixing overhead */ - TRACE("mixlen not worth it, deferring mixing\n"); - still_behind = 1; - goto post_mix; - } - - /* ok, we know how much to mix, let's go */ - still_behind = (adv_done > primary_done); - while (len) { - slen = dsb->dsound->device->buflen - dsb->primary_mixpos; - if (slen > len) slen = len; - slen = DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, slen); + else DSOUND_MixInBuffer(dsb, dsb->primary_mixpos, mixlen); - if ((dsb->primary_mixpos < dsb->dsound->device->mixpos) && - (dsb->primary_mixpos + slen >= dsb->dsound->device->mixpos)) - still_behind = FALSE; + /* re-calculate the primary done */ + primary_done = DSOUND_BufPtrDiff(dsb->device->buflen, dsb->primary_mixpos, writepos); - dsb->primary_mixpos += slen; len -= slen; - dsb->primary_mixpos %= dsb->dsound->device->buflen; + TRACE("new primary_mixpos=%d, total mixed data=%d\n", dsb->primary_mixpos, primary_done); - if ((dsb->state == STATE_STOPPED) || !slen) break; - } - TRACE("new primary_mixpos=%ld, primary_advbase=%ld\n", dsb->primary_mixpos, dsb->dsound->device->mixpos); - TRACE("mixed data len=%ld, still_behind=%d\n", mixlen-len, still_behind); - -post_mix: - /* check if buffer should be considered complete */ - if (buf_left < dsb->writelead && - !(dsb->playflags & DSBPLAY_LOOPING)) { - dsb->state = STATE_STOPPED; - dsb->playpos = 0; - dsb->last_playpos = 0; - dsb->buf_mixpos = 0; - dsb->leadin = FALSE; - dsb->need_remix = FALSE; - DSOUND_CheckEvent(dsb, buf_left); - } - - /* return how far we think the primary buffer can - * advance its underrun detector...*/ - if (still_behind) return 0; - if ((mixlen - len) < primary_done) return 0; - slen = ((dsb->primary_mixpos < dsb->dsound->device->mixpos) ? - dsb->dsound->device->buflen : 0) + dsb->primary_mixpos - - dsb->dsound->device->mixpos; - if (slen > mixlen) { - /* the primary_done and still_behind checks above should have worked */ - FIXME("problem with advancement calculation (advlen=%ld > mixlen=%ld)\n", slen, mixlen); - slen = 0; - } - return slen; + /* Report back the total prebuffered amount for this buffer */ + return primary_done; } -static DWORD DSOUND_MixToPrimary(DirectSoundDevice *device, DWORD playpos, DWORD writepos, DWORD mixlen, BOOL recover) +/** + * For a DirectSoundDevice, go through all the currently playing buffers and + * mix them in to the device buffer. + * + * writepos = the current safe-to-write position in the primary buffer + * mixlen = the maximum amount to mix into the primary buffer + * (beyond the current writepos) + * mustlock = Do we have to fight for lock because we otherwise risk an underrun? + * recover = true if the sound device may have been reset and the write + * position in the device buffer changed + * all_stopped = reports back if all buffers have stopped + * + * Returns: the length beyond the writepos that was mixed to. + */ + +static DWORD DSOUND_MixToPrimary(const DirectSoundDevice *device, DWORD writepos, DWORD mixlen, BOOL mustlock, BOOL recover, BOOL *all_stopped) { - INT i, len, maxlen = 0; + INT i, len; + DWORD minlen = 0; IDirectSoundBufferImpl *dsb; + BOOL gotall = TRUE; - TRACE("(%ld,%ld,%ld,%d)\n", playpos, writepos, mixlen, recover); + /* unless we find a running buffer, all have stopped */ + *all_stopped = TRUE; + + TRACE("(%d,%d,%d)\n", writepos, mixlen, recover); for (i = 0; i < device->nrofbuffers; i++) { dsb = device->buffers[i]; + TRACE("MixToPrimary for %p, state=%d\n", dsb, dsb->state); + if (dsb->buflen && dsb->state && !dsb->hwbuf) { - TRACE("Checking %p, mixlen=%ld\n", dsb, mixlen); - EnterCriticalSection(&(dsb->lock)); + TRACE("Checking %p, mixlen=%d\n", dsb, mixlen); + if (!RtlAcquireResourceShared(&dsb->lock, mustlock)) + { + gotall = FALSE; + continue; + } + /* if buffer is stopping it is stopped now */ if (dsb->state == STATE_STOPPING) { - DSOUND_MixCancel(dsb, writepos, TRUE); dsb->state = STATE_STOPPED; - DSOUND_CheckEvent(dsb, 0); - } else { + DSOUND_CheckEvent(dsb, 0, 0); + } else if (dsb->state != STATE_STOPPED) { + + /* if recovering, reset the mix position */ if ((dsb->state == STATE_STARTING) || recover) { dsb->primary_mixpos = writepos; - dsb->cvolpan = dsb->volpan; - dsb->need_remix = FALSE; - } - else if (dsb->need_remix) { - DSOUND_MixCancel(dsb, writepos, TRUE); - dsb->cvolpan = dsb->volpan; - dsb->need_remix = FALSE; } - len = DSOUND_MixOne(dsb, playpos, writepos, mixlen); + + /* if the buffer was starting, it must be playing now */ if (dsb->state == STATE_STARTING) dsb->state = STATE_PLAYING; - maxlen = (len > maxlen) ? len : maxlen; + + /* mix next buffer into the main buffer */ + len = DSOUND_MixOne(dsb, writepos, mixlen); + + if (!minlen) minlen = len; + + /* record the minimum length mixed from all buffers */ + /* we only want to return the length which *all* buffers have mixed */ + else if (len) minlen = (len < minlen) ? len : minlen; + + *all_stopped = FALSE; } - LeaveCriticalSection(&(dsb->lock)); + RtlReleaseResource(&dsb->lock); } } - return maxlen; + TRACE("Mixed at least %d from all buffers\n", minlen); + if (!gotall) return 0; + return minlen; } -static void DSOUND_MixReset(DirectSoundDevice *device, DWORD writepos) +/** + * Add buffers to the emulated wave device system. + * + * device = The current dsound playback device + * force = If TRUE, the function will buffer up as many frags as possible, + * even though and will ignore the actual state of the primary buffer. + * + * Returns: None + */ + +static void DSOUND_WaveQueue(DirectSoundDevice *device, BOOL force) { - INT i; - IDirectSoundBufferImpl *dsb; - int nfiller; + DWORD prebuf_frags, wave_writepos, wave_fragpos, i; + TRACE("(%p)\n", device); - TRACE("(%p,%ld)\n", device, writepos); + /* calculate the current wave frag position */ + wave_fragpos = (device->pwplay + device->pwqueue) % device->helfrags; + + /* calculate the current wave write position */ + wave_writepos = wave_fragpos * device->fraglen; + + TRACE("wave_fragpos = %i, wave_writepos = %i, pwqueue = %i, prebuf = %i\n", + wave_fragpos, wave_writepos, device->pwqueue, device->prebuf); + + if (!force) + { + /* check remaining prebuffered frags */ + prebuf_frags = device->mixpos / device->fraglen; + if (prebuf_frags == device->helfrags) + --prebuf_frags; + TRACE("wave_fragpos = %d, mixpos_frags = %d\n", wave_fragpos, prebuf_frags); + if (prebuf_frags < wave_fragpos) + prebuf_frags += device->helfrags; + prebuf_frags -= wave_fragpos; + TRACE("wanted prebuf_frags = %d\n", prebuf_frags); + } + else + /* buffer the maximum amount of frags */ + prebuf_frags = device->prebuf; - /* the sound of silence */ - nfiller = device->pwfx->wBitsPerSample == 8 ? 128 : 0; + /* limit to the queue we have left */ + if ((prebuf_frags + device->pwqueue) > device->prebuf) + prebuf_frags = device->prebuf - device->pwqueue; - /* reset all buffer mix positions */ - for (i = 0; i < device->nrofbuffers; i++) { - dsb = device->buffers[i]; + TRACE("prebuf_frags = %i\n", prebuf_frags); - if (dsb->buflen && dsb->state && !dsb->hwbuf) { - TRACE("Resetting %p\n", dsb); - EnterCriticalSection(&(dsb->lock)); - if (dsb->state == STATE_STOPPING) { - dsb->state = STATE_STOPPED; - } - else if (dsb->state == STATE_STARTING) { - /* nothing */ - } else { - DSOUND_MixCancel(dsb, writepos, FALSE); - dsb->cvolpan = dsb->volpan; - dsb->need_remix = FALSE; - } - LeaveCriticalSection(&(dsb->lock)); - } - } + /* adjust queue */ + device->pwqueue += prebuf_frags; - /* wipe out premixed data */ - if (device->mixpos < writepos) { - FillMemory(device->buffer + writepos, device->buflen - writepos, nfiller); - FillMemory(device->buffer, device->mixpos, nfiller); - } else { - FillMemory(device->buffer + writepos, device->mixpos - writepos, nfiller); - } + /* get out of CS when calling the wave system */ + LeaveCriticalSection(&(device->mixlock)); + /* **** */ - /* reset primary mix position */ - device->mixpos = writepos; -} - -static void DSOUND_CheckReset(DirectSoundDevice *device, DWORD writepos) -{ - TRACE("(%p,%ld)\n",device,writepos); - if (device->need_remix) { - DSOUND_MixReset(device, writepos); - device->need_remix = FALSE; - /* maximize Half-Life performance */ - device->prebuf = ds_snd_queue_min; - device->precount = 0; - } else { - device->precount++; - if (device->precount >= 4) { - if (device->prebuf < ds_snd_queue_max) - device->prebuf++; - device->precount = 0; - } + /* queue up the new buffers */ + for(i=0; ihwo, &device->pwave[wave_fragpos], sizeof(WAVEHDR)); + wave_fragpos++; + wave_fragpos %= device->helfrags; } - TRACE("premix adjust: %d\n", device->prebuf); -} -void DSOUND_WaveQueue(DirectSoundDevice *device, DWORD mixq) -{ - TRACE("(%p,%ld)\n", device, mixq); - if (mixq + device->pwqueue > ds_hel_queue) mixq = ds_hel_queue - device->pwqueue; - TRACE("queueing %ld buffers, starting at %d\n", mixq, device->pwwrite); - for (; mixq; mixq--) { - waveOutWrite(device->hwo, device->pwave[device->pwwrite], sizeof(WAVEHDR)); - device->pwwrite++; - if (device->pwwrite >= DS_HEL_FRAGS) device->pwwrite = 0; - device->pwqueue++; - } -} + /* **** */ + EnterCriticalSection(&(device->mixlock)); -/* #define SYNC_CALLBACK */ + TRACE("queue now = %i\n", device->pwqueue); +} -void DSOUND_PerformMix(DirectSoundDevice *device) +/** + * Perform mixing for a Direct Sound device. That is, go through all the + * secondary buffers (the sound bites currently playing) and mix them in + * to the primary buffer (the device buffer). + */ +static void DSOUND_PerformMix(DirectSoundDevice *device) { - int nfiller; - BOOL forced; - HRESULT hres; - TRACE("(%p)\n", device); - /* the sound of silence */ - nfiller = device->pwfx->wBitsPerSample == 8 ? 128 : 0; - - /* whether the primary is forced to play even without secondary buffers */ - forced = ((device->state == STATE_PLAYING) || (device->state == STATE_STARTING)); + /* **** */ + EnterCriticalSection(&(device->mixlock)); if (device->priolevel != DSSCL_WRITEPRIMARY) { - BOOL paused = ((device->state == STATE_STOPPED) || (device->state == STATE_STARTING)); - /* FIXME: document variables */ - DWORD playpos, writepos, inq, maxq, frag; - if (device->hwbuf) { - hres = IDsDriverBuffer_GetPosition(device->hwbuf, &playpos, &writepos); - if (hres) { - WARN("IDsDriverBuffer_GetPosition failed\n"); - return; - } - /* Well, we *could* do Just-In-Time mixing using the writepos, - * but that's a little bit ambitious and unnecessary... */ - /* rather add our safety margin to the writepos, if we're playing */ - if (!paused) { - writepos += device->writelead; - writepos %= device->buflen; - } else writepos = playpos; - } else { - playpos = device->pwplay * device->fraglen; - writepos = playpos; - if (!paused) { - writepos += ds_hel_margin * device->fraglen; - writepos %= device->buflen; - } + BOOL recover = FALSE, all_stopped = FALSE; + DWORD playpos, writepos, writelead, maxq, frag, prebuff_max, prebuff_left, size1, size2, mixplaypos, mixplaypos2; + LPVOID buf1, buf2; + BOOL lock = (device->hwbuf && !(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK)); + BOOL mustlock = FALSE; + int nfiller; + + /* the sound of silence */ + nfiller = device->pwfx->wBitsPerSample == 8 ? 128 : 0; + + /* get the position in the primary buffer */ + if (DSOUND_PrimaryGetPosition(device, &playpos, &writepos) != 0){ + LeaveCriticalSection(&(device->mixlock)); + return; } - TRACE("primary playpos=%ld, writepos=%ld, clrpos=%ld, mixpos=%ld, buflen=%ld\n", + + TRACE("primary playpos=%d, writepos=%d, clrpos=%d, mixpos=%d, buflen=%d\n", playpos,writepos,device->playpos,device->mixpos,device->buflen); assert(device->playpos < device->buflen); - /* wipe out just-played sound data */ - if (playpos < device->playpos) { - FillMemory(device->buffer + device->playpos, device->buflen - device->playpos, nfiller); - FillMemory(device->buffer, playpos, nfiller); + + mixplaypos = DSOUND_bufpos_to_mixpos(device, device->playpos); + mixplaypos2 = DSOUND_bufpos_to_mixpos(device, playpos); + + /* calc maximum prebuff */ + prebuff_max = (device->prebuf * device->fraglen); + if (!device->hwbuf && playpos + prebuff_max >= device->helfrags * device->fraglen) + prebuff_max += device->buflen - device->helfrags * device->fraglen; + + /* check how close we are to an underrun. It occurs when the writepos overtakes the mixpos */ + prebuff_left = DSOUND_BufPtrDiff(device->buflen, device->mixpos, playpos); + writelead = DSOUND_BufPtrDiff(device->buflen, writepos, playpos); + + /* check for underrun. underrun occurs when the write position passes the mix position + * also wipe out just-played sound data */ + if((prebuff_left > prebuff_max) || (device->state == STATE_STOPPED) || (device->state == STATE_STARTING)){ + if (device->state == STATE_STOPPING || device->state == STATE_PLAYING) + WARN("Probable buffer underrun\n"); + else TRACE("Buffer starting or buffer underrun\n"); + + /* recover mixing for all buffers */ + recover = TRUE; + + /* reset mix position to write position */ + device->mixpos = writepos; + + ZeroMemory(device->mix_buffer, device->mix_buffer_len); + ZeroMemory(device->buffer, device->buflen); + } else if (playpos < device->playpos) { + buf1 = device->buffer + device->playpos; + buf2 = device->buffer; + size1 = device->buflen - device->playpos; + size2 = playpos; + FillMemory(device->mix_buffer + mixplaypos, device->mix_buffer_len - mixplaypos, 0); + FillMemory(device->mix_buffer, mixplaypos2, 0); + if (lock) + IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, device->playpos, size1+size2, 0); + FillMemory(buf1, size1, nfiller); + if (playpos && (!buf2 || !size2)) + FIXME("%d: (%d, %d)=>(%d, %d) There should be an additional buffer here!!\n", __LINE__, device->playpos, device->mixpos, playpos, writepos); + FillMemory(buf2, size2, nfiller); + if (lock) + IDsDriverBuffer_Unlock(device->hwbuf, buf1, size1, buf2, size2); } else { - FillMemory(device->buffer + device->playpos, playpos - device->playpos, nfiller); + buf1 = device->buffer + device->playpos; + buf2 = NULL; + size1 = playpos - device->playpos; + size2 = 0; + FillMemory(device->mix_buffer + mixplaypos, mixplaypos2 - mixplaypos, 0); + if (lock) + IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, device->playpos, size1+size2, 0); + FillMemory(buf1, size1, nfiller); + if (buf2 && size2) + { + FIXME("%d: There should be no additional buffer here!!\n", __LINE__); + FillMemory(buf2, size2, nfiller); + } + if (lock) + IDsDriverBuffer_Unlock(device->hwbuf, buf1, size1, buf2, size2); } device->playpos = playpos; - EnterCriticalSection(&(device->mixlock)); + /* find the maximum we can prebuffer from current write position */ + maxq = (writelead < prebuff_max) ? (prebuff_max - writelead) : 0; - /* reset mixing if necessary */ - DSOUND_CheckReset(device, writepos); - - /* check how much prebuffering is left */ - inq = device->mixpos; - if (inq < writepos) - inq += device->buflen; - inq -= writepos; - - /* find the maximum we can prebuffer */ - if (!paused) { - maxq = playpos; - if (maxq < writepos) - maxq += device->buflen; - maxq -= writepos; - } else maxq = device->buflen; - - /* clip maxq to device->prebuf */ - frag = device->prebuf * device->fraglen; - if (maxq > frag) maxq = frag; - - /* check for consistency */ - if (inq > maxq) { - /* the playback position must have passed our last - * mixed position, i.e. it's an underrun, or we have - * nothing more to play */ - TRACE("reached end of mixed data (inq=%ld, maxq=%ld)\n", inq, maxq); - inq = 0; - /* stop the playback now, to allow buffers to refill */ - if (device->state == STATE_PLAYING) { - device->state = STATE_STARTING; - } - else if (device->state == STATE_STOPPING) { - device->state = STATE_STOPPED; - } - else { - /* how can we have an underrun if we aren't playing? */ - WARN("unexpected primary state (%ld)\n", device->state); - } -#ifdef SYNC_CALLBACK - /* DSOUND_callback may need this lock */ - LeaveCriticalSection(&(device->mixlock)); -#endif - if (DSOUND_PrimaryStop(device) != DS_OK) - WARN("DSOUND_PrimaryStop failed\n"); -#ifdef SYNC_CALLBACK - EnterCriticalSection(&(device->mixlock)); -#endif - if (device->hwbuf) { - /* the Stop is supposed to reset play position to beginning of buffer */ - /* unfortunately, OSS is not able to do so, so get current pointer */ - hres = IDsDriverBuffer_GetPosition(device->hwbuf, &playpos, NULL); - if (hres) { - LeaveCriticalSection(&(device->mixlock)); - WARN("IDsDriverBuffer_GetPosition failed\n"); - return; - } - } else { - playpos = device->pwplay * device->fraglen; - } - writepos = playpos; - device->playpos = playpos; - device->mixpos = writepos; - inq = 0; - maxq = device->buflen; - if (maxq > frag) maxq = frag; - FillMemory(device->buffer, device->buflen, nfiller); - paused = TRUE; - } + TRACE("prebuff_left = %d, prebuff_max = %dx%d=%d, writelead=%d\n", + prebuff_left, device->prebuf, device->fraglen, prebuff_max, writelead); + + /* Do we risk an 'underrun' if we don't advance pointer? */ + if (writelead/device->fraglen <= ds_snd_queue_min || recover) + mustlock = TRUE; + + if (lock) + IDsDriverBuffer_Lock(device->hwbuf, &buf1, &size1, &buf2, &size2, writepos, maxq, 0); /* do the mixing */ - frag = DSOUND_MixToPrimary(device, playpos, writepos, maxq, paused); - if (forced) frag = maxq - inq; - device->mixpos += frag; + frag = DSOUND_MixToPrimary(device, writepos, maxq, mustlock, recover, &all_stopped); + + if (frag + writepos > device->buflen) + { + DWORD todo = device->buflen - writepos; + device->normfunction(device->mix_buffer + DSOUND_bufpos_to_mixpos(device, writepos), device->buffer + writepos, todo); + device->normfunction(device->mix_buffer, device->buffer, frag - todo); + } + else + device->normfunction(device->mix_buffer + DSOUND_bufpos_to_mixpos(device, writepos), device->buffer + writepos, frag); + + /* update the mix position, taking wrap-around into account */ + device->mixpos = writepos + frag; device->mixpos %= device->buflen; - if (frag) { - /* buffers have been filled, restart playback */ - if (device->state == STATE_STARTING) { - device->state = STATE_PLAYING; + if (lock) + { + DWORD frag2 = (frag > size1 ? frag - size1 : 0); + frag -= frag2; + if (frag2 > size2) + { + FIXME("Buffering too much! (%d, %d, %d, %d)\n", maxq, frag, size2, frag2 - size2); + frag2 = size2; } - else if (device->state == STATE_STOPPED) { - /* the dsound is supposed to play if there's something to play - * even if it is reported as stopped, so don't let this confuse you */ - device->state = STATE_STOPPING; + IDsDriverBuffer_Unlock(device->hwbuf, buf1, frag, buf2, frag2); + } + + /* update prebuff left */ + prebuff_left = DSOUND_BufPtrDiff(device->buflen, device->mixpos, playpos); + + /* check if have a whole fragment */ + if (prebuff_left >= device->fraglen){ + + /* update the wave queue if using wave system */ + if (!device->hwbuf) + DSOUND_WaveQueue(device, FALSE); + + /* buffers are full. start playing if applicable */ + if(device->state == STATE_STARTING){ + TRACE("started primary buffer\n"); + if(DSOUND_PrimaryPlay(device) != DS_OK){ + WARN("DSOUND_PrimaryPlay failed\n"); + } + else{ + /* we are playing now */ + device->state = STATE_PLAYING; + } } - LeaveCriticalSection(&(device->mixlock)); - if (paused) { - if (DSOUND_PrimaryPlay(device) != DS_OK) + + /* buffers are full. start stopping if applicable */ + if(device->state == STATE_STOPPED){ + TRACE("restarting primary buffer\n"); + if(DSOUND_PrimaryPlay(device) != DS_OK){ WARN("DSOUND_PrimaryPlay failed\n"); - else - TRACE("starting playback\n"); + } + else{ + /* start stopping again. as soon as there is no more data, it will stop */ + device->state = STATE_STOPPING; + } } } - else - LeaveCriticalSection(&(device->mixlock)); + + /* if device was stopping, its for sure stopped when all buffers have stopped */ + else if((all_stopped == TRUE) && (device->state == STATE_STOPPING)){ + TRACE("All buffers have stopped. Stopping primary buffer\n"); + device->state = STATE_STOPPED; + + /* stop the primary buffer now */ + DSOUND_PrimaryStop(device); + } + } else { + + /* update the wave queue if using wave system */ + if (!device->hwbuf) + DSOUND_WaveQueue(device, TRUE); + else + /* Keep alsa happy, which needs GetPosition called once every 10 ms */ + IDsDriverBuffer_GetPosition(device->hwbuf, NULL, NULL); + /* in the DSSCL_WRITEPRIMARY mode, the app is totally in charge... */ if (device->state == STATE_STARTING) { if (DSOUND_PrimaryPlay(device) != DS_OK) @@ -1104,15 +980,19 @@ void DSOUND_PerformMix(DirectSoundDevice *device) device->state = STATE_STOPPED; } } + + LeaveCriticalSection(&(device->mixlock)); + /* **** */ } -void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) +void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD_PTR dwUser, + DWORD_PTR dw1, DWORD_PTR dw2) { - DirectSoundDevice * device = (DirectSoundDevice*)dwUser; + DirectSoundDevice * device = (DirectSoundDevice*)dwUser; DWORD start_time = GetTickCount(); - DWORD end_time; + DWORD end_time; TRACE("(%d,%d,0x%lx,0x%lx,0x%lx)\n",timerID,msg,dwUser,dw1,dw2); - TRACE("entering at %ld\n", start_time); + TRACE("entering at %d\n", start_time); if (DSOUND_renderer[device->drvdesc.dnDevNode] != device) { ERR("dsound died without killing us?\n"); @@ -1129,49 +1009,39 @@ void CALLBACK DSOUND_timer(UINT timerID, UINT msg, DWORD dwUser, DWORD dw1, DWOR RtlReleaseResource(&(device->buffer_list_lock)); end_time = GetTickCount(); - TRACE("completed processing at %ld, duration = %ld\n", end_time, end_time - start_time); + TRACE("completed processing at %d, duration = %d\n", end_time, end_time - start_time); } -void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) +void CALLBACK DSOUND_callback(HWAVEOUT hwo, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { - DirectSoundDevice * device = (DirectSoundDevice*)dwUser; + DirectSoundDevice * device = (DirectSoundDevice*)dwUser; TRACE("(%p,%x,%lx,%lx,%lx)\n",hwo,msg,dwUser,dw1,dw2); - TRACE("entering at %ld, msg=%08x(%s)\n", GetTickCount(), msg, - msg==MM_WOM_DONE ? "MM_WOM_DONE" : msg==MM_WOM_CLOSE ? "MM_WOM_CLOSE" : + TRACE("entering at %d, msg=%08x(%s)\n", GetTickCount(), msg, + msg==MM_WOM_DONE ? "MM_WOM_DONE" : msg==MM_WOM_CLOSE ? "MM_WOM_CLOSE" : msg==MM_WOM_OPEN ? "MM_WOM_OPEN" : "UNKNOWN"); + + /* check if packet completed from wave driver */ if (msg == MM_WOM_DONE) { - DWORD inq, mixq, fraglen, buflen, pwplay, playpos, mixpos; - if (device->pwqueue == (DWORD)-1) { - TRACE("completed due to reset\n"); - return; - } -/* it could be a bad idea to enter critical section here... if there's lock contention, - * the resulting scheduling delays might obstruct the winmm player thread */ -#ifdef SYNC_CALLBACK + + /* **** */ EnterCriticalSection(&(device->mixlock)); -#endif - /* retrieve current values */ - fraglen = device->fraglen; - buflen = device->buflen; - pwplay = device->pwplay; - playpos = pwplay * fraglen; - mixpos = device->mixpos; - /* check remaining mixed data */ - inq = ((mixpos < playpos) ? buflen : 0) + mixpos - playpos; - mixq = inq / fraglen; - if ((inq - (mixq * fraglen)) > 0) mixq++; - /* complete the playing buffer */ - TRACE("done playing primary pos=%ld\n", playpos); - pwplay++; - if (pwplay >= DS_HEL_FRAGS) pwplay = 0; - /* write new values */ - device->pwplay = pwplay; + + TRACE("done playing primary pos=%d\n", device->pwplay * device->fraglen); + + /* update playpos */ + device->pwplay++; + device->pwplay %= device->helfrags; + + /* sanity */ + if(device->pwqueue == 0){ + ERR("Wave queue corrupted!\n"); + } + + /* update queue */ device->pwqueue--; - /* queue new buffer if we have data for it */ - if (inq>1) DSOUND_WaveQueue(device, inq-1); -#ifdef SYNC_CALLBACK + LeaveCriticalSection(&(device->mixlock)); -#endif + /* **** */ } TRACE("completed\n"); } diff --git a/reactos/dll/directx/dsound/primary.c b/reactos/dll/directx/dsound/primary.c index 3ea9fb06db5..a57a5afaba6 100644 --- a/reactos/dll/directx/dsound/primary.c +++ b/reactos/dll/directx/dsound/primary.c @@ -16,7 +16,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include @@ -25,8 +25,8 @@ #define NONAMELESSUNION #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "mmsystem.h" -#include "winreg.h" #include "winternl.h" #include "mmddk.h" #include "wine/debug.h" @@ -36,107 +36,249 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); -void DSOUND_RecalcPrimary(DirectSoundDevice *device) +/** Calculate how long a fragment length of about 10 ms should be in frames + * + * nSamplesPerSec: Frequency rate in samples per second + * nBlockAlign: Size of a single blockalign + * + * Returns: + * Size in bytes of a single fragment + */ +DWORD DSOUND_fraglen(DWORD nSamplesPerSec, DWORD nBlockAlign) { - DWORD nBlockAlign; - TRACE("(%p)\n", device); + /* Given a timer delay of 10ms, the fragment size is approximately: + * fraglen = (nSamplesPerSec * 10 / 1000) * nBlockAlign + * ==> fraglen = (nSamplesPerSec / 100) * nBlockSize + * + * ALSA uses buffers that are powers of 2. Because of this, fraglen + * is rounded up to the nearest power of 2: + */ - nBlockAlign = device->pwfx->nBlockAlign; - if (device->hwbuf) { - DWORD fraglen; - /* let fragment size approximate the timer delay */ - fraglen = (device->pwfx->nSamplesPerSec * DS_TIME_DEL / 1000) * nBlockAlign; - /* reduce fragment size until an integer number of them fits in the buffer */ - /* (FIXME: this may or may not be a good idea) */ - while (device->buflen % fraglen) fraglen -= nBlockAlign; - device->fraglen = fraglen; - TRACE("fraglen=%ld\n", device->fraglen); + if (nSamplesPerSec <= 12800) + return 128 * nBlockAlign; + + if (nSamplesPerSec <= 25600) + return 256 * nBlockAlign; + + if (nSamplesPerSec <= 51200) + return 512 * nBlockAlign; + + return 1024 * nBlockAlign; +} + +static void DSOUND_RecalcPrimary(DirectSoundDevice *device) +{ + TRACE("(%p)\n", device); + + device->fraglen = DSOUND_fraglen(device->pwfx->nSamplesPerSec, device->pwfx->nBlockAlign); + device->helfrags = device->buflen / device->fraglen; + TRACE("fraglen=%d helfrags=%d\n", device->fraglen, device->helfrags); + + if (device->hwbuf && device->drvdesc.dwFlags & DSDDESC_DONTNEEDWRITELEAD) + device->writelead = 0; + else + /* calculate the 10ms write lead */ + device->writelead = (device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign; +} + +HRESULT DSOUND_ReopenDevice(DirectSoundDevice *device, BOOL forcewave) +{ + HRESULT hres = DS_OK; + TRACE("(%p, %d)\n", device, forcewave); + + if (device->driver) + { + IDsDriver_Close(device->driver); + if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) + waveOutClose(device->hwo); + IDsDriver_Release(device->driver); + device->driver = NULL; + device->buffer = NULL; + device->hwo = 0; } - /* calculate the 10ms write lead */ - device->writelead = (device->pwfx->nSamplesPerSec / 100) * nBlockAlign; + else if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) + waveOutClose(device->hwo); + + /* DRV_QUERYDSOUNDIFACE is a "Wine extension" to get the DSound interface */ + if (ds_hw_accel != DS_HW_ACCEL_EMULATION && !forcewave) + waveOutMessage((HWAVEOUT)device->drvdesc.dnDevNode, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&device->driver, 0); + + /* Get driver description */ + if (device->driver) { + DWORD wod = device->drvdesc.dnDevNode; + hres = IDsDriver_GetDriverDesc(device->driver,&(device->drvdesc)); + device->drvdesc.dnDevNode = wod; + if (FAILED(hres)) { + WARN("IDsDriver_GetDriverDesc failed: %08x\n", hres); + IDsDriver_Release(device->driver); + device->driver = NULL; + } + } + + /* if no DirectSound interface available, use WINMM API instead */ + if (!device->driver) + device->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | DSDDESC_DOMMSYSTEMSETFORMAT; + + if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) + { + DWORD flags = CALLBACK_FUNCTION; + + if (device->driver) + flags |= WAVE_DIRECTSOUND; + + hres = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD)device, flags)); + if (FAILED(hres)) { + WARN("waveOutOpen failed\n"); + if (device->driver) + { + IDsDriver_Release(device->driver); + device->driver = NULL; + } + return hres; + } + } + + if (device->driver) + hres = IDsDriver_Open(device->driver); + + return hres; } static HRESULT DSOUND_PrimaryOpen(DirectSoundDevice *device) { + DWORD buflen; HRESULT err = DS_OK; TRACE("(%p)\n", device); + /* on original windows, the buffer it set to a fixed size, no matter what the settings are. + on windows this size is always fixed (tested on win-xp) */ + if (!device->buflen) + device->buflen = ds_hel_buflen; + buflen = device->buflen; + buflen -= buflen % device->pwfx->nBlockAlign; + device->buflen = buflen; + + if (device->driver) + { + err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx, + DSBCAPS_PRIMARYBUFFER,0, + &(device->buflen),&(device->buffer), + (LPVOID*)&(device->hwbuf)); + + if (err != DS_OK) { + WARN("IDsDriver_CreateSoundBuffer failed (%08x), falling back to waveout\n", err); + err = DSOUND_ReopenDevice(device, TRUE); + if (FAILED(err)) + { + WARN("Falling back to waveout failed too! Giving up\n"); + return err; + } + } + if (device->hwbuf) + IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan); + + DSOUND_RecalcPrimary(device); + device->prebuf = ds_snd_queue_max; + if (device->helfrags < ds_snd_queue_min) + { + WARN("Too little sound buffer to be effective (%d/%d) falling back to waveout\n", device->buflen, ds_snd_queue_min * device->fraglen); + device->buflen = buflen; + IDsDriverBuffer_Release(device->hwbuf); + device->hwbuf = NULL; + err = DSOUND_ReopenDevice(device, TRUE); + if (FAILED(err)) + { + WARN("Falling back to waveout failed too! Giving up\n"); + return err; + } + } + else if (device->helfrags < ds_snd_queue_max) + device->prebuf = device->helfrags; + } + + device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen); + device->mix_buffer = HeapAlloc(GetProcessHeap(), 0, device->mix_buffer_len); + if (!device->mix_buffer) + { + if (device->hwbuf) + IDsDriverBuffer_Release(device->hwbuf); + device->hwbuf = NULL; + return DSERR_OUTOFMEMORY; + } + + if (device->state == STATE_PLAYING) device->state = STATE_STARTING; + else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED; + /* are we using waveOut stuff? */ if (!device->driver) { LPBYTE newbuf; - DWORD buflen; - HRESULT merr = DS_OK; + LPWAVEHDR headers = NULL; + DWORD overshot; + unsigned int c; + /* Start in pause mode, to allow buffers to get filled */ waveOutPause(device->hwo); - if (device->state == STATE_PLAYING) device->state = STATE_STARTING; - else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED; - /* use fragments of 10ms (1/100s) each (which should get us within - * the documented write cursor lead of 10-15ms) */ - buflen = ((device->pwfx->nSamplesPerSec / 100) * device->pwfx->nBlockAlign) * DS_HEL_FRAGS; - TRACE("desired buflen=%ld, old buffer=%p\n", buflen, device->buffer); - /* reallocate emulated primary buffer */ + TRACE("desired buflen=%d, old buffer=%p\n", buflen, device->buffer); + + /* reallocate emulated primary buffer */ if (device->buffer) - newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer,buflen); + newbuf = HeapReAlloc(GetProcessHeap(),0,device->buffer, buflen); else - newbuf = HeapAlloc(GetProcessHeap(),0,buflen); + newbuf = HeapAlloc(GetProcessHeap(),0, buflen); - if (newbuf == NULL) { + if (!newbuf) { ERR("failed to allocate primary buffer\n"); - merr = DSERR_OUTOFMEMORY; + return DSERR_OUTOFMEMORY; /* but the old buffer might still exist and must be re-prepared */ - } else { - device->buffer = newbuf; - device->buflen = buflen; } - if (device->buffer) { - unsigned c; - - device->fraglen = device->buflen / DS_HEL_FRAGS; - - /* prepare fragment headers */ - for (c=0; cpwave[c]->lpData = (char*)device->buffer + c*device->fraglen; - device->pwave[c]->dwBufferLength = device->fraglen; - device->pwave[c]->dwUser = (DWORD)device; - device->pwave[c]->dwFlags = 0; - device->pwave[c]->dwLoops = 0; - err = mmErr(waveOutPrepareHeader(device->hwo,device->pwave[c],sizeof(WAVEHDR))); - if (err != DS_OK) { - while (c--) - waveOutUnprepareHeader(device->hwo,device->pwave[c],sizeof(WAVEHDR)); - break; - } - } - device->pwplay = 0; - device->pwwrite = 0; - device->pwqueue = 0; - device->playpos = 0; - device->mixpos = 0; - FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0); - TRACE("fraglen=%ld\n", device->fraglen); - DSOUND_WaveQueue(device, (DWORD)-1); + DSOUND_RecalcPrimary(device); + if (device->pwave) + headers = HeapReAlloc(GetProcessHeap(),0,device->pwave, device->helfrags * sizeof(WAVEHDR)); + else + headers = HeapAlloc(GetProcessHeap(),0,device->helfrags * sizeof(WAVEHDR)); + + if (!headers) { + ERR("failed to allocate wave headers\n"); + HeapFree(GetProcessHeap(), 0, newbuf); + DSOUND_RecalcPrimary(device); + return DSERR_OUTOFMEMORY; } - if ((err == DS_OK) && (merr != DS_OK)) - err = merr; - } else if (!device->hwbuf) { - err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx, - DSBCAPS_PRIMARYBUFFER,0, - &(device->buflen),&(device->buffer), - (LPVOID*)&(device->hwbuf)); - if (err != DS_OK) { - WARN("IDsDriver_CreateSoundBuffer failed\n"); - return err; + + device->buffer = newbuf; + device->pwave = headers; + + /* prepare fragment headers */ + for (c=0; chelfrags; c++) { + device->pwave[c].lpData = (char*)device->buffer + c*device->fraglen; + device->pwave[c].dwBufferLength = device->fraglen; + device->pwave[c].dwUser = (DWORD_PTR)device; + device->pwave[c].dwFlags = 0; + device->pwave[c].dwLoops = 0; + err = mmErr(waveOutPrepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR))); + if (err != DS_OK) { + while (c--) + waveOutUnprepareHeader(device->hwo,&device->pwave[c],sizeof(WAVEHDR)); + break; + } } - if (device->state == STATE_PLAYING) device->state = STATE_STARTING; - else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED; - device->playpos = 0; - device->mixpos = 0; - FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0); - } + overshot = device->buflen % device->fraglen; + /* sanity */ + if(overshot) + { + overshot -= overshot % device->pwfx->nBlockAlign; + device->pwave[device->helfrags - 1].dwBufferLength += overshot; + } + TRACE("fraglen=%d, overshot=%d\n", device->fraglen, overshot); + } + device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1]; + device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1]; + FillMemory(device->buffer, device->buflen, (device->pwfx->wBitsPerSample == 8) ? 128 : 0); + FillMemory(device->mix_buffer, device->mix_buffer_len, 0); + device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0; return err; } @@ -149,14 +291,24 @@ static void DSOUND_PrimaryClose(DirectSoundDevice *device) if (!device->hwbuf) { unsigned c; + /* get out of CS when calling the wave system */ + LeaveCriticalSection(&(device->mixlock)); + /* **** */ device->pwqueue = (DWORD)-1; /* resetting queues */ waveOutReset(device->hwo); - for (c=0; chwo, device->pwave[c], sizeof(WAVEHDR)); + for (c=0; chelfrags; c++) + waveOutUnprepareHeader(device->hwo, &device->pwave[c], sizeof(WAVEHDR)); + /* **** */ + EnterCriticalSection(&(device->mixlock)); + + /* clear the queue */ device->pwqueue = 0; } else { - if (IDsDriverBuffer_Release(device->hwbuf) == 0) + ULONG ref = IDsDriverBuffer_Release(device->hwbuf); + if (!ref) device->hwbuf = 0; + else + ERR("Still %d references on primary buffer, refcount leak?\n", ref); } } @@ -165,36 +317,7 @@ HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device) HRESULT err = DS_OK; TRACE("(%p)\n", device); - device->buflen = device->pwfx->nAvgBytesPerSec; - - /* FIXME: verify that hardware capabilities (DSCAPS_PRIMARY flags) match */ - - if (device->driver) { - err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx, - DSBCAPS_PRIMARYBUFFER,0, - &(device->buflen),&(device->buffer), - (LPVOID*)&(device->hwbuf)); - if (err != DS_OK) { - WARN("IDsDriver_CreateSoundBuffer failed\n"); - return err; - } - } - if (!device->hwbuf) { - /* Allocate memory for HEL buffer headers */ - unsigned c; - for (c=0; cpwave[c] = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(WAVEHDR)); - if (!device->pwave[c]) { - /* Argh, out of memory */ - while (c--) { - HeapFree(GetProcessHeap(),0,device->pwave[c]); - } - WARN("out of memory\n"); - return DSERR_OUTOFMEMORY; - } - } - } - + device->buflen = ds_hel_buflen; err = DSOUND_PrimaryOpen(device); if (err != DS_OK) { @@ -202,8 +325,6 @@ HRESULT DSOUND_PrimaryCreate(DirectSoundDevice *device) return err; } - /* calculate fragment size and write lead */ - DSOUND_RecalcPrimary(device); device->state = STATE_STOPPED; return DS_OK; } @@ -212,20 +333,23 @@ HRESULT DSOUND_PrimaryDestroy(DirectSoundDevice *device) { TRACE("(%p)\n", device); + /* **** */ + EnterCriticalSection(&(device->mixlock)); + DSOUND_PrimaryClose(device); if (device->driver) { if (device->hwbuf) { if (IDsDriverBuffer_Release(device->hwbuf) == 0) device->hwbuf = 0; } - } else { - unsigned c; - for (c=0; cpwave[c]); - } - } + } else + HeapFree(GetProcessHeap(),0,device->pwave); HeapFree(GetProcessHeap(),0,device->pwfx); device->pwfx=NULL; + + LeaveCriticalSection(&(device->mixlock)); + /* **** */ + return DS_OK; } @@ -255,35 +379,34 @@ HRESULT DSOUND_PrimaryStop(DirectSoundDevice *device) if (device->hwbuf) { err = IDsDriverBuffer_Stop(device->hwbuf); if (err == DSERR_BUFFERLOST) { - DWORD flags = CALLBACK_FUNCTION; - if (ds_hw_accel != DS_HW_ACCEL_EMULATION) - flags |= WAVE_DIRECTSOUND; - /* Wine-only: the driver wants us to reopen the device */ - /* FIXME: check for errors */ - IDsDriverBuffer_Release(device->hwbuf); - waveOutClose(device->hwo); - device->hwo = 0; - err = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, - device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD)device, - flags)); - if (err == DS_OK) { - err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx, - DSBCAPS_PRIMARYBUFFER,0, - &(device->buflen),&(device->buffer), - (LPVOID)&(device->hwbuf)); - if (err != DS_OK) - WARN("IDsDriver_CreateSoundBuffer failed\n"); - } else { - WARN("waveOutOpen failed\n"); + DSOUND_PrimaryClose(device); + err = DSOUND_ReopenDevice(device, FALSE); + if (FAILED(err)) + ERR("DSOUND_ReopenDevice failed\n"); + else + { + err = DSOUND_PrimaryOpen(device); + if (FAILED(err)) + WARN("DSOUND_PrimaryOpen failed\n"); } } else if (err != DS_OK) { WARN("IDsDriverBuffer_Stop failed\n"); } } else { + + /* don't call the wave system with the lock set */ + LeaveCriticalSection(&(device->mixlock)); + /* **** */ + err = mmErr(waveOutPause(device->hwo)); + + /* **** */ + EnterCriticalSection(&(device->mixlock)); + if (err != DS_OK) WARN("waveOutPause failed\n"); } + return err; } @@ -293,43 +416,33 @@ HRESULT DSOUND_PrimaryGetPosition(DirectSoundDevice *device, LPDWORD playpos, LP if (device->hwbuf) { HRESULT err=IDsDriverBuffer_GetPosition(device->hwbuf,playpos,writepos); - if (err) { + if (err != S_OK) { WARN("IDsDriverBuffer_GetPosition failed\n"); return err; } } else { - if (playpos) { - MMTIME mtime; - mtime.wType = TIME_BYTES; - waveOutGetPosition(device->hwo, &mtime, sizeof(mtime)); - mtime.u.cb = mtime.u.cb % device->buflen; - *playpos = mtime.u.cb; - } - if (writepos) { - /* the writepos should only be used by apps with WRITEPRIMARY priority, - * in which case our software mixer is disabled anyway */ - *writepos = (device->pwplay + ds_hel_margin) * device->fraglen; - while (*writepos >= device->buflen) - *writepos -= device->buflen; - } + TRACE("pwplay=%i, pwqueue=%i\n", device->pwplay, device->pwqueue); + + /* check if playpos was requested */ + if (playpos) + /* use the cached play position */ + *playpos = device->pwplay * device->fraglen; + + /* check if writepos was requested */ + if (writepos) + /* the writepos is the first non-queued position */ + *writepos = ((device->pwplay + device->pwqueue) % device->helfrags) * device->fraglen; } - TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, device, GetTickCount()); + TRACE("playpos = %d, writepos = %d (%p, time=%d)\n", playpos?*playpos:-1, writepos?*writepos:-1, device, GetTickCount()); return DS_OK; } -/******************************************************************************* - * PrimaryBuffer - */ -/* This sets this format for the Primary Buffer Only */ -/* See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 120 */ -static HRESULT WINAPI PrimaryBufferImpl_SetFormat( - LPDIRECTSOUNDBUFFER8 iface,LPCWAVEFORMATEX wfex -) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; - HRESULT err = DS_OK; +HRESULT DSOUND_PrimarySetFormat(DirectSoundDevice *device, LPCWAVEFORMATEX wfex, BOOL forced) +{ + HRESULT err = DSERR_BUFFERLOST; int i, alloc_size, cp_size; - DWORD nSamplesPerSec; - TRACE("(%p,%p)\n", iface, wfex); + DWORD nSamplesPerSec, bpp, chans; + TRACE("(%p,%p)\n", device, wfex); if (device->priolevel == DSSCL_NORMAL) { WARN("failed priority check!\n"); @@ -341,8 +454,8 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFormat( WARN("invalid parameter: wfex==NULL!\n"); return DSERR_INVALIDPARAM; } - TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld," - "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", + TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," + "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", wfex->wFormatTag, wfex->nChannels, wfex->nSamplesPerSec, wfex->nAvgBytesPerSec, wfex->nBlockAlign, wfex->wBitsPerSample, wfex->cbSize); @@ -351,7 +464,7 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFormat( RtlAcquireResourceExclusive(&(device->buffer_list_lock), TRUE); EnterCriticalSection(&(device->mixlock)); - if (wfex->wFormatTag == WAVE_FORMAT_PCM) { + if (wfex->wFormatTag == WAVE_FORMAT_PCM) { alloc_size = sizeof(WAVEFORMATEX); cp_size = sizeof(PCMWAVEFORMAT); } else @@ -360,63 +473,92 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFormat( device->pwfx = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,device->pwfx,alloc_size); nSamplesPerSec = device->pwfx->nSamplesPerSec; + bpp = device->pwfx->wBitsPerSample; + chans = device->pwfx->nChannels; CopyMemory(device->pwfx, wfex, cp_size); - if (device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) { - DWORD flags = CALLBACK_FUNCTION; - if (ds_hw_accel != DS_HW_ACCEL_EMULATION) - flags |= WAVE_DIRECTSOUND; - /* FIXME: check for errors */ - DSOUND_PrimaryClose(device); - waveOutClose(device->hwo); - device->hwo = 0; - err = mmErr(waveOutOpen(&(device->hwo), device->drvdesc.dnDevNode, - device->pwfx, (DWORD_PTR)DSOUND_callback, (DWORD)device, - flags)); - if (err == DS_OK) { - err = DSOUND_PrimaryOpen(device); - if (err != DS_OK) { - WARN("DSOUND_PrimaryOpen failed\n"); - goto done; - } - } else { - WARN("waveOutOpen failed\n"); + if (!(device->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMSETFORMAT) && device->hwbuf) { + err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx); + + /* On bad format, try to re-create, big chance it will work then, only do this if we to */ + if (forced && (device->pwfx->nSamplesPerSec/100 != wfex->nSamplesPerSec/100 || err == DSERR_BADFORMAT)) + { + err = DSERR_BUFFERLOST; + CopyMemory(device->pwfx, wfex, cp_size); + } + + if (err != DSERR_BUFFERLOST && FAILED(err)) { + WARN("IDsDriverBuffer_SetFormat failed\n"); + if (!forced) + err = DS_OK; goto done; } - } else if (device->hwbuf) { - err = IDsDriverBuffer_SetFormat(device->hwbuf, device->pwfx); - if (err == DSERR_BUFFERLOST) { - /* Wine-only: the driver wants us to recreate the HW buffer */ - IDsDriverBuffer_Release(device->hwbuf); - err = IDsDriver_CreateSoundBuffer(device->driver,device->pwfx, - DSBCAPS_PRIMARYBUFFER,0, - &(device->buflen),&(device->buffer), - (LPVOID)&(device->hwbuf)); - if (err != DS_OK) { - WARN("IDsDriver_CreateSoundBuffer failed\n"); - goto done; - } + + if (err == S_FALSE) + { + /* ALSA specific: S_FALSE tells that recreation was successful, + * but size and location may be changed, and buffer has to be restarted + * I put it here, so if frequency doesn't match the error will be changed to DSERR_BUFFERLOST + * and the entire re-initialization will occur anyway + */ + IDsDriverBuffer_Lock(device->hwbuf, (LPVOID *)&device->buffer, &device->buflen, NULL, NULL, 0, 0, DSBLOCK_ENTIREBUFFER); + IDsDriverBuffer_Unlock(device->hwbuf, device->buffer, 0, NULL, 0); + if (device->state == STATE_PLAYING) device->state = STATE_STARTING; else if (device->state == STATE_STOPPING) device->state = STATE_STOPPED; - } else { - WARN("IDsDriverBuffer_SetFormat failed\n"); + device->pwplay = device->pwqueue = device->playpos = device->mixpos = 0; + err = DS_OK; + } + DSOUND_RecalcPrimary(device); + } + + if (err == DSERR_BUFFERLOST) + { + DSOUND_PrimaryClose(device); + + err = DSOUND_ReopenDevice(device, FALSE); + if (FAILED(err)) + { + WARN("DSOUND_ReopenDevice failed: %08x\n", err); goto done; } - /* FIXME: should we set err back to DS_OK in all cases ? */ + err = DSOUND_PrimaryOpen(device); + if (err != DS_OK) { + WARN("DSOUND_PrimaryOpen failed\n"); + goto done; + } + + if (wfex->nSamplesPerSec/100 != device->pwfx->nSamplesPerSec/100 && forced && device->buffer) + { + DSOUND_PrimaryClose(device); + device->pwfx->nSamplesPerSec = wfex->nSamplesPerSec; + err = DSOUND_ReopenDevice(device, TRUE); + if (FAILED(err)) + WARN("DSOUND_ReopenDevice(2) failed: %08x\n", err); + else if (FAILED((err = DSOUND_PrimaryOpen(device)))) + WARN("DSOUND_PrimaryOpen(2) failed: %08x\n", err); + } } - DSOUND_RecalcPrimary(device); - if (nSamplesPerSec != device->pwfx->nSamplesPerSec) { + device->mix_buffer_len = DSOUND_bufpos_to_mixpos(device, device->buflen); + device->mix_buffer = HeapReAlloc(GetProcessHeap(), 0, device->mix_buffer, device->mix_buffer_len); + FillMemory(device->mix_buffer, device->mix_buffer_len, 0); + device->mixfunction = mixfunctions[device->pwfx->wBitsPerSample/8 - 1]; + device->normfunction = normfunctions[device->pwfx->wBitsPerSample/8 - 1]; + + if (nSamplesPerSec != device->pwfx->nSamplesPerSec || bpp != device->pwfx->wBitsPerSample || chans != device->pwfx->nChannels) { IDirectSoundBufferImpl** dsb = device->buffers; for (i = 0; i < device->nrofbuffers; i++, dsb++) { /* **** */ - EnterCriticalSection(&((*dsb)->lock)); + RtlAcquireResourceExclusive(&(*dsb)->lock, TRUE); - (*dsb)->freqAdjust = ((*dsb)->freq << DSOUND_FREQSHIFT) / - wfex->nSamplesPerSec; + (*dsb)->freqAdjust = ((DWORD64)(*dsb)->freq << DSOUND_FREQSHIFT) / device->pwfx->nSamplesPerSec; + DSOUND_RecalcFormat((*dsb)); + DSOUND_MixToTemporary((*dsb), 0, (*dsb)->buflen, FALSE); + (*dsb)->primary_mixpos = 0; - LeaveCriticalSection(&((*dsb)->lock)); + RtlReleaseResource(&(*dsb)->lock); /* **** */ } } @@ -429,14 +571,27 @@ done: return err; } +/******************************************************************************* + * PrimaryBuffer + */ +/* This sets this format for the Primary Buffer Only */ +/* See file:///cdrom/sdk52/docs/worddoc/dsound.doc page 120 */ +static HRESULT WINAPI PrimaryBufferImpl_SetFormat( + LPDIRECTSOUNDBUFFER iface, + LPCWAVEFORMATEX wfex) +{ + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; + TRACE("(%p,%p)\n", iface, wfex); + return DSOUND_PrimarySetFormat(device, wfex, device->priolevel == DSSCL_WRITEPRIMARY); +} + static HRESULT WINAPI PrimaryBufferImpl_SetVolume( - LPDIRECTSOUNDBUFFER8 iface,LONG vol + LPDIRECTSOUNDBUFFER iface,LONG vol ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; DWORD ampfactors; - DSVOLUMEPAN volpan; HRESULT hres = DS_OK; - TRACE("(%p,%ld)\n", iface, vol); + TRACE("(%p,%d)\n", iface, vol); if (!(device->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { WARN("control unavailable\n"); @@ -444,7 +599,7 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume( } if ((vol > DSBVOLUME_MAX) || (vol < DSBVOLUME_MIN)) { - WARN("invalid parameter: vol = %ld\n", vol); + WARN("invalid parameter: vol = %d\n", vol); return DSERR_INVALIDPARAM; } @@ -452,18 +607,18 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume( EnterCriticalSection(&(device->mixlock)); waveOutGetVolume(device->hwo, &factors); - volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; - volpan.dwTotalRightAmpFactor=ampfactors >> 16; - DSOUND_AmpFactorToVolPan(&volpan); - if (vol != volpan.lVolume) { - volpan.lVolume=vol; - DSOUND_RecalcVolPan(&volpan); + device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; + device->volpan.dwTotalRightAmpFactor=ampfactors >> 16; + DSOUND_AmpFactorToVolPan(&device->volpan); + if (vol != device->volpan.lVolume) { + device->volpan.lVolume=vol; + DSOUND_RecalcVolPan(&device->volpan); if (device->hwbuf) { - hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &volpan); + hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan); if (hres != DS_OK) WARN("IDsDriverBuffer_SetVolumePan failed\n"); } else { - ampfactors = (volpan.dwTotalLeftAmpFactor & 0xffff) | (volpan.dwTotalRightAmpFactor << 16); + ampfactors = (device->volpan.dwTotalLeftAmpFactor & 0xffff) | (device->volpan.dwTotalRightAmpFactor << 16); waveOutSetVolume(device->hwo, ampfactors); } } @@ -475,11 +630,10 @@ static HRESULT WINAPI PrimaryBufferImpl_SetVolume( } static HRESULT WINAPI PrimaryBufferImpl_GetVolume( - LPDIRECTSOUNDBUFFER8 iface,LPLONG vol + LPDIRECTSOUNDBUFFER iface,LPLONG vol ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; DWORD ampfactors; - DSVOLUMEPAN volpan; TRACE("(%p,%p)\n", iface, vol); if (!(device->dsbd.dwFlags & DSBCAPS_CTRLVOLUME)) { @@ -492,19 +646,22 @@ static HRESULT WINAPI PrimaryBufferImpl_GetVolume( return DSERR_INVALIDPARAM; } - waveOutGetVolume(device->hwo, &factors); - volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; - volpan.dwTotalRightAmpFactor=ampfactors >> 16; - DSOUND_AmpFactorToVolPan(&volpan); - *vol = volpan.lVolume; + if (!device->hwbuf) + { + waveOutGetVolume(device->hwo, &factors); + device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; + device->volpan.dwTotalRightAmpFactor=ampfactors >> 16; + DSOUND_AmpFactorToVolPan(&device->volpan); + } + *vol = device->volpan.lVolume; return DS_OK; } static HRESULT WINAPI PrimaryBufferImpl_SetFrequency( - LPDIRECTSOUNDBUFFER8 iface,DWORD freq + LPDIRECTSOUNDBUFFER iface,DWORD freq ) { PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; - TRACE("(%p,%ld)\n",This,freq); + TRACE("(%p,%d)\n",This,freq); /* You cannot set the frequency of the primary buffer */ WARN("control unavailable\n"); @@ -512,13 +669,13 @@ static HRESULT WINAPI PrimaryBufferImpl_SetFrequency( } static HRESULT WINAPI PrimaryBufferImpl_Play( - LPDIRECTSOUNDBUFFER8 iface,DWORD reserved1,DWORD reserved2,DWORD flags + LPDIRECTSOUNDBUFFER iface,DWORD reserved1,DWORD reserved2,DWORD flags ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; - TRACE("(%p,%08lx,%08lx,%08lx)\n", iface, reserved1, reserved2, flags); + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; + TRACE("(%p,%08x,%08x,%08x)\n", iface, reserved1, reserved2, flags); if (!(flags & DSBPLAY_LOOPING)) { - WARN("invalid parameter: flags = %08lx\n", flags); + WARN("invalid parameter: flags = %08x\n", flags); return DSERR_INVALIDPARAM; } @@ -536,9 +693,9 @@ static HRESULT WINAPI PrimaryBufferImpl_Play( return DS_OK; } -static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface) +static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER iface) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; TRACE("(%p)\n", iface); /* **** */ @@ -555,22 +712,22 @@ static HRESULT WINAPI PrimaryBufferImpl_Stop(LPDIRECTSOUNDBUFFER8 iface) return DS_OK; } -static ULONG WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER8 iface) +static ULONG WINAPI PrimaryBufferImpl_AddRef(LPDIRECTSOUNDBUFFER iface) { PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } -static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) +static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER iface) { PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; DWORD ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { - This->dsound->device->primary = NULL; + This->device->primary = NULL; HeapFree(GetProcessHeap(), 0, This); TRACE("(%p) released\n", This); } @@ -578,15 +735,19 @@ static ULONG WINAPI PrimaryBufferImpl_Release(LPDIRECTSOUNDBUFFER8 iface) } static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition( - LPDIRECTSOUNDBUFFER8 iface,LPDWORD playpos,LPDWORD writepos + LPDIRECTSOUNDBUFFER iface,LPDWORD playpos,LPDWORD writepos ) { HRESULT hres; - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; TRACE("(%p,%p,%p)\n", iface, playpos, writepos); + /* **** */ + EnterCriticalSection(&(device->mixlock)); + hres = DSOUND_PrimaryGetPosition(device, playpos, writepos); if (hres != DS_OK) { WARN("DSOUND_PrimaryGetPosition failed\n"); + LeaveCriticalSection(&(device->mixlock)); return hres; } if (writepos) { @@ -595,14 +756,18 @@ static HRESULT WINAPI PrimaryBufferImpl_GetCurrentPosition( *writepos += device->writelead; while (*writepos >= device->buflen) *writepos -= device->buflen; } - TRACE("playpos = %ld, writepos = %ld (%p, time=%ld)\n", playpos?*playpos:0, writepos?*writepos:0, device, GetTickCount()); + + LeaveCriticalSection(&(device->mixlock)); + /* **** */ + + TRACE("playpos = %d, writepos = %d (%p, time=%d)\n", playpos?*playpos:0, writepos?*writepos:0, device, GetTickCount()); return DS_OK; } static HRESULT WINAPI PrimaryBufferImpl_GetStatus( - LPDIRECTSOUNDBUFFER8 iface,LPDWORD status + LPDIRECTSOUNDBUFFER iface,LPDWORD status ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; TRACE("(%p,%p)\n", iface, status); if (status == NULL) { @@ -615,20 +780,20 @@ static HRESULT WINAPI PrimaryBufferImpl_GetStatus( (device->state == STATE_PLAYING)) *status |= DSBSTATUS_PLAYING | DSBSTATUS_LOOPING; - TRACE("status=%lx\n", *status); + TRACE("status=%x\n", *status); return DS_OK; } static HRESULT WINAPI PrimaryBufferImpl_GetFormat( - LPDIRECTSOUNDBUFFER8 iface, + LPDIRECTSOUNDBUFFER iface, LPWAVEFORMATEX lpwf, DWORD wfsize, LPDWORD wfwritten) { DWORD size; - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; - TRACE("(%p,%p,%ld,%p)\n", iface, lpwf, wfsize, wfwritten); + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; + TRACE("(%p,%p,%d,%p)\n", iface, lpwf, wfsize, wfwritten); size = sizeof(WAVEFORMATEX) + device->pwfx->cbSize; @@ -656,10 +821,11 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFormat( } static HRESULT WINAPI PrimaryBufferImpl_Lock( - LPDIRECTSOUNDBUFFER8 iface,DWORD writecursor,DWORD writebytes,LPVOID lplpaudioptr1,LPDWORD audiobytes1,LPVOID lplpaudioptr2,LPDWORD audiobytes2,DWORD flags + LPDIRECTSOUNDBUFFER iface,DWORD writecursor,DWORD writebytes,LPVOID *lplpaudioptr1,LPDWORD audiobytes1,LPVOID *lplpaudioptr2,LPDWORD audiobytes2,DWORD flags ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; - TRACE("(%p,%ld,%ld,%p,%p,%p,%p,0x%08lx) at %ld\n", + HRESULT hres; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; + TRACE("(%p,%d,%d,%p,%p,%p,%p,0x%08x) at %d\n", iface, writecursor, writebytes, @@ -671,31 +837,41 @@ static HRESULT WINAPI PrimaryBufferImpl_Lock( GetTickCount() ); + if (!audiobytes1) + return DSERR_INVALIDPARAM; + if (device->priolevel != DSSCL_WRITEPRIMARY) { WARN("failed priority check!\n"); return DSERR_PRIOLEVELNEEDED; } + /* when this flag is set, writecursor is meaningless and must be calculated */ if (flags & DSBLOCK_FROMWRITECURSOR) { - DWORD writepos; - HRESULT hres; /* GetCurrentPosition does too much magic to duplicate here */ - hres = IDirectSoundBuffer_GetCurrentPosition(iface, NULL, &writepos); + hres = IDirectSoundBuffer_GetCurrentPosition(iface, NULL, &writecursor); if (hres != DS_OK) { WARN("IDirectSoundBuffer_GetCurrentPosition failed\n"); return hres; } - writecursor += writepos; } - while (writecursor >= device->buflen) - writecursor -= device->buflen; + + /* when this flag is set, writebytes is meaningless and must be set */ if (flags & DSBLOCK_ENTIREBUFFER) writebytes = device->buflen; - if (writebytes > device->buflen) - writebytes = device->buflen; + + if (writecursor >= device->buflen) { + WARN("Invalid parameter, writecursor: %u >= buflen: %u\n", + writecursor, device->buflen); + return DSERR_INVALIDPARAM; + } + + if (writebytes > device->buflen) { + WARN("Invalid parameter, writebytes: %u > buflen: %u\n", + writebytes, device->buflen); + return DSERR_INVALIDPARAM; + } if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) { - HRESULT hres; hres = IDsDriverBuffer_Lock(device->hwbuf, lplpaudioptr1, audiobytes1, lplpaudioptr2, audiobytes2, @@ -713,7 +889,7 @@ static HRESULT WINAPI PrimaryBufferImpl_Lock( *(LPBYTE*)lplpaudioptr2 = NULL; if (audiobytes2) *audiobytes2 = 0; - TRACE("->%ld.0\n",writebytes); + TRACE("->%d.0\n",writebytes); } else { *(LPBYTE*)lplpaudioptr1 = device->buffer+writecursor; *audiobytes1 = device->buflen-writecursor; @@ -721,17 +897,17 @@ static HRESULT WINAPI PrimaryBufferImpl_Lock( *(LPBYTE*)lplpaudioptr2 = device->buffer; if (audiobytes2) *audiobytes2 = writebytes-(device->buflen-writecursor); - TRACE("->%ld.%ld\n",*audiobytes1,audiobytes2?*audiobytes2:0); + TRACE("->%d.%d\n",*audiobytes1,audiobytes2?*audiobytes2:0); } } return DS_OK; } static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition( - LPDIRECTSOUNDBUFFER8 iface,DWORD newpos + LPDIRECTSOUNDBUFFER iface,DWORD newpos ) { PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; - TRACE("(%p,%ld)\n",This,newpos); + TRACE("(%p,%d)\n",This,newpos); /* You cannot set the position of the primary buffer */ WARN("invalid call\n"); @@ -739,13 +915,12 @@ static HRESULT WINAPI PrimaryBufferImpl_SetCurrentPosition( } static HRESULT WINAPI PrimaryBufferImpl_SetPan( - LPDIRECTSOUNDBUFFER8 iface,LONG pan + LPDIRECTSOUNDBUFFER iface,LONG pan ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; DWORD ampfactors; - DSVOLUMEPAN volpan; HRESULT hres = DS_OK; - TRACE("(%p,%ld)\n", iface, pan); + TRACE("(%p,%d)\n", iface, pan); if (!(device->dsbd.dwFlags & DSBCAPS_CTRLPAN)) { WARN("control unavailable\n"); @@ -753,26 +928,29 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan( } if ((pan > DSBPAN_RIGHT) || (pan < DSBPAN_LEFT)) { - WARN("invalid parameter: pan = %ld\n", pan); + WARN("invalid parameter: pan = %d\n", pan); return DSERR_INVALIDPARAM; } /* **** */ EnterCriticalSection(&(device->mixlock)); - waveOutGetVolume(device->hwo, &factors); - volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; - volpan.dwTotalRightAmpFactor=ampfactors >> 16; - DSOUND_AmpFactorToVolPan(&volpan); - if (pan != volpan.lPan) { - volpan.lPan=pan; - DSOUND_RecalcVolPan(&volpan); + if (!device->hwbuf) + { + waveOutGetVolume(device->hwo, &factors); + device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; + device->volpan.dwTotalRightAmpFactor=ampfactors >> 16; + DSOUND_AmpFactorToVolPan(&device->volpan); + } + if (pan != device->volpan.lPan) { + device->volpan.lPan=pan; + DSOUND_RecalcVolPan(&device->volpan); if (device->hwbuf) { - hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &volpan); + hres = IDsDriverBuffer_SetVolumePan(device->hwbuf, &device->volpan); if (hres != DS_OK) WARN("IDsDriverBuffer_SetVolumePan failed\n"); } else { - ampfactors = (volpan.dwTotalLeftAmpFactor & 0xffff) | (volpan.dwTotalRightAmpFactor << 16); + ampfactors = (device->volpan.dwTotalLeftAmpFactor & 0xffff) | (device->volpan.dwTotalRightAmpFactor << 16); waveOutSetVolume(device->hwo, ampfactors); } } @@ -784,11 +962,10 @@ static HRESULT WINAPI PrimaryBufferImpl_SetPan( } static HRESULT WINAPI PrimaryBufferImpl_GetPan( - LPDIRECTSOUNDBUFFER8 iface,LPLONG pan + LPDIRECTSOUNDBUFFER iface,LPLONG pan ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; DWORD ampfactors; - DSVOLUMEPAN volpan; TRACE("(%p,%p)\n", iface, pan); if (!(device->dsbd.dwFlags & DSBCAPS_CTRLPAN)) { @@ -801,19 +978,22 @@ static HRESULT WINAPI PrimaryBufferImpl_GetPan( return DSERR_INVALIDPARAM; } - waveOutGetVolume(device->hwo, &factors); - volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; - volpan.dwTotalRightAmpFactor=ampfactors >> 16; - DSOUND_AmpFactorToVolPan(&volpan); - *pan = volpan.lPan; + if (!device->hwbuf) + { + waveOutGetVolume(device->hwo, &factors); + device->volpan.dwTotalLeftAmpFactor=ampfactors & 0xffff; + device->volpan.dwTotalRightAmpFactor=ampfactors >> 16; + DSOUND_AmpFactorToVolPan(&device->volpan); + } + *pan = device->volpan.lPan; return DS_OK; } static HRESULT WINAPI PrimaryBufferImpl_Unlock( - LPDIRECTSOUNDBUFFER8 iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2 + LPDIRECTSOUNDBUFFER iface,LPVOID p1,DWORD x1,LPVOID p2,DWORD x2 ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; - TRACE("(%p,%p,%ld,%p,%ld)\n", iface, p1, x1, p2, x2); + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; + TRACE("(%p,%p,%d,%p,%d)\n", iface, p1, x1, p2, x2); if (device->priolevel != DSSCL_WRITEPRIMARY) { WARN("failed priority check!\n"); @@ -823,7 +1003,11 @@ static HRESULT WINAPI PrimaryBufferImpl_Unlock( if (!(device->drvdesc.dwFlags & DSDDESC_DONTNEEDPRIMARYLOCK) && device->hwbuf) { HRESULT hres; - hres = IDsDriverBuffer_Unlock(device->hwbuf, p1, x1, p2, x2); + if ((char *)p1 - (char *)device->buffer + x1 > device->buflen) + hres = DSERR_INVALIDPARAM; + else + hres = IDsDriverBuffer_Unlock(device->hwbuf, p1, x1, p2, x2); + if (hres != DS_OK) { WARN("IDsDriverBuffer_Unlock failed\n"); return hres; @@ -834,7 +1018,7 @@ static HRESULT WINAPI PrimaryBufferImpl_Unlock( } static HRESULT WINAPI PrimaryBufferImpl_Restore( - LPDIRECTSOUNDBUFFER8 iface + LPDIRECTSOUNDBUFFER iface ) { PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; FIXME("(%p):stub\n",This); @@ -842,9 +1026,9 @@ static HRESULT WINAPI PrimaryBufferImpl_Restore( } static HRESULT WINAPI PrimaryBufferImpl_GetFrequency( - LPDIRECTSOUNDBUFFER8 iface,LPDWORD freq + LPDIRECTSOUNDBUFFER iface,LPDWORD freq ) { - DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->dsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; TRACE("(%p,%p)\n", iface, freq); if (freq == NULL) { @@ -858,63 +1042,23 @@ static HRESULT WINAPI PrimaryBufferImpl_GetFrequency( } *freq = device->pwfx->nSamplesPerSec; - TRACE("-> %ld\n", *freq); + TRACE("-> %d\n", *freq); return DS_OK; } -static HRESULT WINAPI PrimaryBufferImpl_SetFX( - LPDIRECTSOUNDBUFFER8 iface,DWORD dwEffectsCount,LPDSEFFECTDESC pDSFXDesc,LPDWORD pdwResultCodes -) { - PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; - DWORD u; - FIXME("(%p,%lu,%p,%p): stub\n",This,dwEffectsCount,pDSFXDesc,pdwResultCodes); - - if (pdwResultCodes) - for (u=0; udsound->device; + DirectSoundDevice *device = ((PrimaryBufferImpl *)iface)->device; TRACE("(%p,%p)\n", iface, caps); if (caps == NULL) { @@ -923,31 +1067,25 @@ static HRESULT WINAPI PrimaryBufferImpl_GetCaps( } if (caps->dwSize < sizeof(*caps)) { - WARN("invalid parameter: caps->dwSize = %ld: < %d\n", caps->dwSize, sizeof(*caps)); + WARN("invalid parameter: caps->dwSize = %d\n", caps->dwSize); return DSERR_INVALIDPARAM; } caps->dwFlags = device->dsbd.dwFlags; - if (device->hwbuf) caps->dwFlags |= DSBCAPS_LOCHARDWARE; - else caps->dwFlags |= DSBCAPS_LOCSOFTWARE; - caps->dwBufferBytes = device->buflen; - /* This value represents the speed of the "unlock" command. - As unlock is quite fast (it does not do anything), I put - 4096 ko/s = 4 Mo / s */ - /* FIXME: hwbuf speed */ - caps->dwUnlockTransferRate = 4096; + /* Windows reports these as zero */ + caps->dwUnlockTransferRate = 0; caps->dwPlayCpuOverhead = 0; return DS_OK; } static HRESULT WINAPI PrimaryBufferImpl_QueryInterface( - LPDIRECTSOUNDBUFFER8 iface,REFIID riid,LPVOID *ppobj + LPDIRECTSOUNDBUFFER iface,REFIID riid,LPVOID *ppobj ) { PrimaryBufferImpl *This = (PrimaryBufferImpl *)iface; - DirectSoundDevice *device = This->dsound->device; + DirectSoundDevice *device = This->device; TRACE("(%p,%s,%p)\n", iface, debugstr_guid(riid), ppobj); if (ppobj == NULL) { @@ -984,7 +1122,7 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface( if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) { if (!device->listener) - IDirectSound3DListenerImpl_Create(This, &device->listener); + IDirectSound3DListenerImpl_Create(device, &device->listener); if (device->listener) { *ppobj = device->listener; IDirectSound3DListener_AddRef((LPDIRECTSOUND3DLISTENER)*ppobj); @@ -1004,7 +1142,7 @@ static HRESULT WINAPI PrimaryBufferImpl_QueryInterface( return E_NOINTERFACE; } -static const IDirectSoundBuffer8Vtbl dspbvt = +static const IDirectSoundBufferVtbl dspbvt = { PrimaryBufferImpl_QueryInterface, PrimaryBufferImpl_AddRef, @@ -1026,23 +1164,20 @@ static const IDirectSoundBuffer8Vtbl dspbvt = PrimaryBufferImpl_SetFrequency, PrimaryBufferImpl_Stop, PrimaryBufferImpl_Unlock, - PrimaryBufferImpl_Restore, - PrimaryBufferImpl_SetFX, - PrimaryBufferImpl_AcquireResources, - PrimaryBufferImpl_GetObjectInPath + PrimaryBufferImpl_Restore }; -HRESULT WINAPI PrimaryBufferImpl_Create( - IDirectSoundImpl *ds, - PrimaryBufferImpl **pdsb, +HRESULT PrimaryBufferImpl_Create( + DirectSoundDevice * device, + PrimaryBufferImpl ** ppdsb, LPCDSBUFFERDESC dsbd) { PrimaryBufferImpl *dsb; - TRACE("%p,%p,%p)\n",ds,pdsb,dsbd); + TRACE("%p,%p,%p)\n",device,ppdsb,dsbd); if (dsbd->lpwfxFormat) { WARN("invalid parameter: dsbd->lpwfxFormat != NULL\n"); - *pdsb = NULL; + *ppdsb = NULL; return DSERR_INVALIDPARAM; } @@ -1050,23 +1185,24 @@ HRESULT WINAPI PrimaryBufferImpl_Create( if (dsb == NULL) { WARN("out of memory\n"); - *pdsb = NULL; + *ppdsb = NULL; return DSERR_OUTOFMEMORY; } dsb->ref = 0; - dsb->dsound = ds; + dsb->device = device; dsb->lpVtbl = &dspbvt; - CopyMemory(&ds->device->dsbd, dsbd, sizeof(*dsbd)); + device->dsbd = *dsbd; TRACE("Created primary buffer at %p\n", dsb); - TRACE("(formattag=0x%04x,chans=%d,samplerate=%ld," - "bytespersec=%ld,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", - ds->device->pwfx->wFormatTag, ds->device->pwfx->nChannels, ds->device->pwfx->nSamplesPerSec, - ds->device->pwfx->nAvgBytesPerSec, ds->device->pwfx->nBlockAlign, - ds->device->pwfx->wBitsPerSample, ds->device->pwfx->cbSize); - - *pdsb = dsb; + TRACE("(formattag=0x%04x,chans=%d,samplerate=%d," + "bytespersec=%d,blockalign=%d,bitspersamp=%d,cbSize=%d)\n", + device->pwfx->wFormatTag, device->pwfx->nChannels, + device->pwfx->nSamplesPerSec, device->pwfx->nAvgBytesPerSec, + device->pwfx->nBlockAlign, device->pwfx->wBitsPerSample, + device->pwfx->cbSize); + + *ppdsb = dsb; return S_OK; } diff --git a/reactos/dll/directx/dsound/propset.c b/reactos/dll/directx/dsound/propset.c index 0309b81ebcc..4b6d77e76b2 100644 --- a/reactos/dll/directx/dsound/propset.c +++ b/reactos/dll/directx/dsound/propset.c @@ -16,15 +16,16 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ +#define COBJMACROS #include #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "mmsystem.h" -#include "winreg.h" #include "winternl.h" #include "winnls.h" #include "vfwmsgs.h" @@ -33,7 +34,6 @@ #include "dsound.h" #include "dsdriver.h" #include "dsound_private.h" -#include "initguid.h" #include "dsconf.h" #ifdef NONAMELESSSTRUCT @@ -65,7 +65,7 @@ static ULONG WINAPI IKsBufferPropertySetImpl_AddRef(LPKSPROPERTYSET iface) { IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -73,7 +73,7 @@ static ULONG WINAPI IKsBufferPropertySetImpl_Release(LPKSPROPERTYSET iface) { IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { This->dsb->iks = 0; @@ -96,7 +96,7 @@ static HRESULT WINAPI IKsBufferPropertySetImpl_Get( { IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface; PIDSDRIVERPROPERTYSET ps; - TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", + TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned); if (This->dsb->hwbuf) { @@ -109,7 +109,7 @@ static HRESULT WINAPI IKsBufferPropertySetImpl_Get( S(prop).Set = *guidPropSet; S(prop).Id = dwPropID; S(prop).Flags = 0; /* unused */ - S(prop).InstanceId = (ULONG)This->dsb->dsound; + S(prop).InstanceId = (ULONG)This->dsb->device; hres = IDsDriverPropertySet_Get(ps, &prop, pInstanceData, cbInstanceData, pPropData, cbPropData, pcbReturned); @@ -133,7 +133,7 @@ static HRESULT WINAPI IKsBufferPropertySetImpl_Set( { IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface; PIDSDRIVERPROPERTYSET ps; - TRACE("(%p,%s,%ld,%p,%ld,%p,%ld)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData); + TRACE("(%p,%s,%d,%p,%d,%p,%d)\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData); if (This->dsb->hwbuf) { IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps); @@ -145,7 +145,7 @@ static HRESULT WINAPI IKsBufferPropertySetImpl_Set( S(prop).Set = *guidPropSet; S(prop).Id = dwPropID; S(prop).Flags = 0; /* unused */ - S(prop).InstanceId = (ULONG)This->dsb->dsound; + S(prop).InstanceId = (ULONG)This->dsb->device; hres = IDsDriverPropertySet_Set(ps,&prop,pInstanceData,cbInstanceData,pPropData,cbPropData); IDsDriverPropertySet_Release(ps); @@ -165,7 +165,7 @@ static HRESULT WINAPI IKsBufferPropertySetImpl_QuerySupport( { IKsBufferPropertySetImpl *This = (IKsBufferPropertySetImpl *)iface; PIDSDRIVERPROPERTYSET ps; - TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport); + TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport); if (This->dsb->hwbuf) { IDsDriver_QueryInterface(This->dsb->hwbuf, &IID_IDsDriverPropertySet, (void **)&ps); @@ -193,12 +193,13 @@ static const IKsPropertySetVtbl iksbvt = { IKsBufferPropertySetImpl_QuerySupport }; -HRESULT WINAPI IKsBufferPropertySetImpl_Create( +HRESULT IKsBufferPropertySetImpl_Create( IDirectSoundBufferImpl *dsb, IKsBufferPropertySetImpl **piks) { IKsBufferPropertySetImpl *iks; TRACE("(%p,%p)\n",dsb,piks); + *piks = NULL; iks = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*iks)); if (iks == 0) { @@ -218,7 +219,7 @@ HRESULT WINAPI IKsBufferPropertySetImpl_Create( return S_OK; } -HRESULT WINAPI IKsBufferPropertySetImpl_Destroy( +HRESULT IKsBufferPropertySetImpl_Destroy( IKsBufferPropertySetImpl *piks) { TRACE("(%p)\n",piks); @@ -241,15 +242,21 @@ static HRESULT WINAPI IKsPrivatePropertySetImpl_QueryInterface( IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); + if (IsEqualIID(riid, &IID_IUnknown) || + IsEqualIID(riid, &IID_IKsPropertySet)) { + *ppobj = iface; + IUnknown_AddRef(iface); + return S_OK; + } *ppobj = NULL; - return DSERR_INVALIDPARAM; + return E_NOINTERFACE; } static ULONG WINAPI IKsPrivatePropertySetImpl_AddRef(LPKSPROPERTYSET iface) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -257,7 +264,7 @@ static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { HeapFree(GetProcessHeap(), 0, This); @@ -266,18 +273,17 @@ static ULONG WINAPI IKsPrivatePropertySetImpl_Release(LPKSPROPERTYSET iface) return ref; } -static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingA( - REFGUID guidPropSet, +static HRESULT DSPROPERTY_WaveDeviceMappingA( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { HRESULT hr = DSERR_INVALIDPARAM; PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA ppd; - TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) not implemented!\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); + TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + pPropData,cbPropData,pcbReturned); - ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A_DATA) pPropData; + ppd = pPropData; if (!ppd) { WARN("invalid parameter: pPropData\n"); @@ -330,18 +336,17 @@ static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingA( return hr; } -static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingW( - REFGUID guidPropSet, +static HRESULT DSPROPERTY_WaveDeviceMappingW( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { HRESULT hr = DSERR_INVALIDPARAM; PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA ppd; - TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); + TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + pPropData,cbPropData,pcbReturned); - ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W_DATA) pPropData; + ppd = pPropData; if (!ppd) { WARN("invalid parameter: pPropData\n"); @@ -394,8 +399,7 @@ static HRESULT WINAPI DSPROPERTY_WaveDeviceMappingW( return hr; } -static HRESULT WINAPI DSPROPERTY_Description1( - REFGUID guidPropSet, +static HRESULT DSPROPERTY_Description1( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) @@ -403,8 +407,8 @@ static HRESULT WINAPI DSPROPERTY_Description1( HRESULT err; GUID guid, dev_guid; PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA ppd; - TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); + TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + pPropData,cbPropData,pcbReturned); ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA) pPropData; @@ -423,8 +427,8 @@ static HRESULT WINAPI DSPROPERTY_Description1( } else { TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow); } - FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); + FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n", + pPropData,cbPropData,pcbReturned); return E_PROP_ID_UNSUPPORTED; } @@ -443,21 +447,21 @@ static HRESULT WINAPI DSPROPERTY_Description1( DSDRIVERDESC desc; ppd->WaveDeviceId = wod; ppd->Devnode = wod; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSDRIVER drv = NULL; lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA)); lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA)); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); break; } else { - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -474,21 +478,21 @@ static HRESULT WINAPI DSPROPERTY_Description1( DSDRIVERDESC desc; ppd->WaveDeviceId = wid; ppd->Devnode = wid; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSCDRIVER drv; lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA)); lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA)); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); break; } else { - WARN("WineWaveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -506,22 +510,22 @@ static HRESULT WINAPI DSPROPERTY_Description1( ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; ppd->WaveDeviceId = wod; ppd->Devnode = wod; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSDRIVER drv = NULL; lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA)); lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA)); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); found = TRUE; break; } else { - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -539,22 +543,22 @@ static HRESULT WINAPI DSPROPERTY_Description1( ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; ppd->WaveDeviceId = wid; ppd->Devnode = wid; - err = mmErr(WineWaveInMessage((HWAVEIN)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSDRIVER drv = NULL; lstrcpynA(ppd->DescriptionA, desc.szDesc, sizeof(ppd->DescriptionA)); lstrcpynA(ppd->ModuleA, desc.szDrvname, sizeof(ppd->ModuleA)); MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, ppd->DescriptionW, sizeof(ppd->DescriptionW)/sizeof(WCHAR) ); MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, ppd->ModuleW, sizeof(ppd->ModuleW)/sizeof(WCHAR) ); - err = mmErr(WineWaveInMessage((HWAVEIN)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + err = mmErr(waveInMessage(UlongToHandle(wid), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); found = TRUE; break; } else { - WARN("WineWaveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -569,23 +573,22 @@ static HRESULT WINAPI DSPROPERTY_Description1( if (pcbReturned) { *pcbReturned = cbPropData; - TRACE("*pcbReturned=%ld\n", *pcbReturned); + TRACE("*pcbReturned=%d\n", *pcbReturned); } return S_OK; } -static HRESULT WINAPI DSPROPERTY_DescriptionA( - REFGUID guidPropSet, +static HRESULT DSPROPERTY_DescriptionA( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { - PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA) pPropData; + PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA ppd = pPropData; HRESULT err; GUID dev_guid; - TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); + TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + pPropData,cbPropData,pcbReturned); TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId)); if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) { @@ -597,8 +600,8 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( } else { TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow); } - FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); + FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n", + pPropData,cbPropData,pcbReturned); return E_PROP_ID_UNSUPPORTED; } @@ -619,7 +622,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( if (IsEqualGUID( &dev_guid, &DSOUND_renderer_guids[wod] ) ) { DSDRIVERDESC desc; ppd->WaveDeviceId = wod; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSDRIVER drv = NULL; /* FIXME: this is a memory leak */ @@ -635,11 +638,11 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( ppd->Description = szDescription; ppd->Module = szModule; ppd->Interface = szInterface; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); break; } else { WARN("no memory\n"); @@ -649,7 +652,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( return E_OUTOFMEMORY; } } else { - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -668,7 +671,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( if (IsEqualGUID( &dev_guid, &DSOUND_capture_guids[wid] ) ) { DSDRIVERDESC desc; ppd->WaveDeviceId = wid; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSCDRIVER drv; /* FIXME: this is a memory leak */ @@ -684,11 +687,11 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( ppd->Description = szDescription; ppd->Module = szModule; ppd->Interface = szInterface; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); break; } else { WARN("no memory\n"); @@ -698,7 +701,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( return E_OUTOFMEMORY; } } else { - WARN("WineWaveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -713,10 +716,10 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( for (wod = 0; wod < wodn; wod++) { if (IsEqualGUID( &ppd->DeviceId, &DSOUND_renderer_guids[wod] ) ) { DSDRIVERDESC desc; - TRACE("DSOUND_renderer_guids[%ld]\n", wod); + TRACE("DSOUND_renderer_guids[%d]\n", wod); ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; ppd->WaveDeviceId = wod; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSDRIVER drv = NULL; /* FIXME: this is a memory leak */ @@ -732,11 +735,11 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( ppd->Description = szDescription; ppd->Module = szModule; ppd->Interface = szInterface; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); found = TRUE; break; } else { @@ -747,7 +750,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( return E_OUTOFMEMORY; } } else { - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -762,9 +765,9 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( for (wid = 0; wid < widn; wid++) { if (IsEqualGUID( &ppd->DeviceId, &DSOUND_capture_guids[wid] ) ) { DSDRIVERDESC desc; - TRACE("DSOUND_capture_guids[%ld]\n", wid); + TRACE("DSOUND_capture_guids[%d]\n", wid); ppd->WaveDeviceId = wid; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSCDRIVER drv; /* FIXME: this is a memory leak */ @@ -780,11 +783,11 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( ppd->Description = szDescription; ppd->Module = szModule; ppd->Interface = szInterface; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); found = TRUE; break; } else { @@ -795,7 +798,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( return E_OUTOFMEMORY; } } else { - WARN("WineWaveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -810,23 +813,22 @@ static HRESULT WINAPI DSPROPERTY_DescriptionA( if (pcbReturned) { *pcbReturned = cbPropData; - TRACE("*pcbReturned=%ld\n", *pcbReturned); + TRACE("*pcbReturned=%d\n", *pcbReturned); } return S_OK; } -static HRESULT WINAPI DSPROPERTY_DescriptionW( - REFGUID guidPropSet, +static HRESULT DSPROPERTY_DescriptionW( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { - PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA) pPropData; + PDSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA ppd = pPropData; HRESULT err; GUID dev_guid; - TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); + TRACE("pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + pPropData,cbPropData,pcbReturned); TRACE("DeviceId=%s\n",debugstr_guid(&ppd->DeviceId)); if ( IsEqualGUID( &ppd->DeviceId , &GUID_NULL) ) { @@ -838,8 +840,8 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( } else { TRACE("DataFlow=Unknown(%d)\n", ppd->DataFlow); } - FIXME("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p) GUID_NULL not implemented!\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); + FIXME("(pPropData=%p,cbPropData=%d,pcbReturned=%p) GUID_NULL not implemented!\n", + pPropData,cbPropData,pcbReturned); return E_PROP_ID_UNSUPPORTED; } @@ -859,9 +861,9 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( for (wod = 0; wod < wodn; wod++) { if (IsEqualGUID( &dev_guid, &DSOUND_renderer_guids[wod] ) ) { DSDRIVERDESC desc; - TRACE("DSOUND_renderer_guids[%ld]\n", wod); + TRACE("DSOUND_renderer_guids[%d]\n", wod); ppd->WaveDeviceId = wod; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSDRIVER drv = NULL; /* FIXME: this is a memory leak */ @@ -877,11 +879,11 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( ppd->Description = wDescription; ppd->Module = wModule; ppd->Interface = wInterface; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); break; } else { WARN("no memory\n"); @@ -891,7 +893,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( return E_OUTOFMEMORY; } } else { - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -910,7 +912,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( if (IsEqualGUID( &dev_guid, &DSOUND_capture_guids[wid] ) ) { DSDRIVERDESC desc; ppd->WaveDeviceId = wid; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSCDRIVER drv; /* FIXME: this is a memory leak */ @@ -926,11 +928,11 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( ppd->Description = wDescription; ppd->Module = wModule; ppd->Interface = wInterface; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); break; } else { WARN("no memory\n"); @@ -940,7 +942,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( return E_OUTOFMEMORY; } } else { - WARN("WineWaveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -955,10 +957,10 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( for (wod = 0; wod < wodn; wod++) { if (IsEqualGUID( &ppd->DeviceId, &DSOUND_renderer_guids[wod] ) ) { DSDRIVERDESC desc; - TRACE("DSOUND_renderer_guids[%ld]\n", wod); + TRACE("DSOUND_renderer_guids[%d]\n", wod); ppd->DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; ppd->WaveDeviceId = wod; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSDRIVER drv = NULL; /* FIXME: this is a memory leak */ @@ -974,11 +976,11 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( ppd->Description = wDescription; ppd->Module = wModule; ppd->Interface = wInterface; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); found = TRUE; break; } else { @@ -989,7 +991,7 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( return E_OUTOFMEMORY; } } else { - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveOutMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } @@ -1004,9 +1006,9 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( for (wid = 0; wid < widn; wid++) { if (IsEqualGUID( &dev_guid, &DSOUND_capture_guids[wid] ) ) { DSDRIVERDESC desc; - TRACE("DSOUND_capture_guids[%ld]\n", wid); + TRACE("DSOUND_capture_guids[%d]\n", wid); ppd->WaveDeviceId = wid; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&(desc),0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); if (err == DS_OK) { PIDSCDRIVER drv; /* FIXME: this is a memory leak */ @@ -1022,11 +1024,11 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( ppd->Description = wDescription; ppd->Module = wModule; ppd->Interface = wInterface; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDIFACE,(DWORD_PTR)&drv,0)); if (err == DS_OK && drv) ppd->Type = DIRECTSOUNDDEVICE_TYPE_VXD; else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); found = TRUE; break; } else { @@ -1037,12 +1039,12 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( return E_OUTOFMEMORY; } } else { - WARN("WineWaveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); + WARN("waveInMessage(DRV_QUERYDSOUNDDESC) failed\n"); return E_PROP_ID_UNSUPPORTED; } } } - } + } if (found == FALSE) { WARN("device not found\n"); @@ -1052,333 +1054,318 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( if (pcbReturned) { *pcbReturned = cbPropData; - TRACE("*pcbReturned=%ld\n", *pcbReturned); + TRACE("*pcbReturned=%d\n", *pcbReturned); } return S_OK; } -static HRESULT WINAPI DSPROPERTY_Enumerate1( - REFGUID guidPropSet, +static HRESULT DSPROPERTY_Enumerate1( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1_DATA) pPropData; HRESULT err; - TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); - - if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) { - if (ppd) { - if (ppd->Callback) { - unsigned devs, wod, wid; - DSDRIVERDESC desc; - DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA data; - - devs = waveOutGetNumDevs(); - for (wod = 0; wod < devs; ++wod) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); - if (err == DS_OK) { - PIDSCDRIVER drv; - ZeroMemory(&data, sizeof(data)); - data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; - data.WaveDeviceId = wod; - data.DeviceId = DSOUND_renderer_guids[wod]; - lstrcpynA(data.DescriptionA, desc.szDesc, sizeof(data.DescriptionA)); - lstrcpynA(data.ModuleA, desc.szDrvname, sizeof(data.ModuleA)); - - MultiByteToWideChar( CP_ACP, 0, data.DescriptionA, -1, data.DescriptionW, sizeof(data.DescriptionW)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, data.ModuleA, -1, data.ModuleW, sizeof(data.ModuleW)/sizeof(WCHAR) ); - - data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); - if (err == DS_OK && drv) - data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; - else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + pPropData,cbPropData,pcbReturned); + + if (ppd) { + if (ppd->Callback) { + unsigned devs, wod, wid; + DSDRIVERDESC desc; + DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1_DATA data; + + devs = waveOutGetNumDevs(); + for (wod = 0; wod < devs; ++wod) { + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + if (err == DS_OK) { + PIDSCDRIVER drv; + ZeroMemory(&data, sizeof(data)); + data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; + data.WaveDeviceId = wod; + data.DeviceId = DSOUND_renderer_guids[wod]; + lstrcpynA(data.DescriptionA, desc.szDesc, sizeof(data.DescriptionA)); + lstrcpynA(data.ModuleA, desc.szDrvname, sizeof(data.ModuleA)); + + MultiByteToWideChar( CP_ACP, 0, data.DescriptionA, -1, data.DescriptionW, sizeof(data.DescriptionW)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, data.ModuleA, -1, data.ModuleW, sizeof(data.ModuleW)/sizeof(WCHAR) ); + + data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + if (err == DS_OK && drv) + data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; + else + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); - TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); - (ppd->Callback)(&data, ppd->Context); - } + TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); + (ppd->Callback)(&data, ppd->Context); } + } - devs = waveInGetNumDevs(); - for (wid = 0; wid < devs; ++wid) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); - if (err == DS_OK) { - PIDSCDRIVER drv; - ZeroMemory(&data, sizeof(data)); - data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; - data.WaveDeviceId = wid; - data.DeviceId = DSOUND_capture_guids[wid]; - lstrcpynA(data.DescriptionA, desc.szDesc, sizeof(data.DescriptionA)); - lstrcpynA(data.ModuleA, desc.szDrvname, sizeof(data.ModuleA)); - - MultiByteToWideChar( CP_ACP, 0, data.DescriptionA, -1, data.DescriptionW, sizeof(data.DescriptionW)/sizeof(WCHAR) ); - MultiByteToWideChar( CP_ACP, 0, data.ModuleA, -1, data.ModuleW, sizeof(data.ModuleW)/sizeof(WCHAR) ); - - data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; - err = mmErr(WineWaveInMessage((HWAVEIN)wid, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); - if (err == DS_OK && drv) - data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; - else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + devs = waveInGetNumDevs(); + for (wid = 0; wid < devs; ++wid) { + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + if (err == DS_OK) { + PIDSCDRIVER drv; + ZeroMemory(&data, sizeof(data)); + data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; + data.WaveDeviceId = wid; + data.DeviceId = DSOUND_capture_guids[wid]; + lstrcpynA(data.DescriptionA, desc.szDesc, sizeof(data.DescriptionA)); + lstrcpynA(data.ModuleA, desc.szDrvname, sizeof(data.ModuleA)); + + MultiByteToWideChar( CP_ACP, 0, data.DescriptionA, -1, data.DescriptionW, sizeof(data.DescriptionW)/sizeof(WCHAR) ); + MultiByteToWideChar( CP_ACP, 0, data.ModuleA, -1, data.ModuleW, sizeof(data.ModuleW)/sizeof(WCHAR) ); + + data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; + err = mmErr(waveInMessage(UlongToHandle(wid), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + if (err == DS_OK && drv) + data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; + else + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); - TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); - (ppd->Callback)(&data, ppd->Context); - } + TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); + (ppd->Callback)(&data, ppd->Context); } - - return S_OK; } + + return S_OK; } - } else { - FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet)); } if (pcbReturned) { *pcbReturned = 0; - FIXME("*pcbReturned=%ld\n", *pcbReturned); + FIXME("*pcbReturned=%d\n", *pcbReturned); } return E_PROP_ID_UNSUPPORTED; } -static HRESULT WINAPI DSPROPERTY_EnumerateA( - REFGUID guidPropSet, +static HRESULT DSPROPERTY_EnumerateA( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { - PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA) pPropData; + PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A_DATA ppd = pPropData; HRESULT err; - TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); - - if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) { - if (ppd) { - if (ppd->Callback) { - unsigned devs, wod, wid; - DSDRIVERDESC desc; - DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA data; - - devs = waveOutGetNumDevs(); - for (wod = 0; wod < devs; ++wod) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); - if (err == DS_OK) { - DWORD size; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0)); - if (err == DS_OK) { - WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size); - if (nameW) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size)); - if (err == DS_OK) { - CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR)); - if (szInterface) { - PIDSCDRIVER drv; - ZeroMemory(&data, sizeof(data)); - data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; - data.WaveDeviceId = wod; - data.DeviceId = DSOUND_renderer_guids[wod]; - data.Description = desc.szDesc; - data.Module = desc.szDrvname; - WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL ); - data.Interface = szInterface; - - data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); - if (err == DS_OK && drv) - data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; - else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); - - TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); - (ppd->Callback)(&data, ppd->Context); - } - HeapFree(GetProcessHeap(),0,szInterface); + TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + pPropData,cbPropData,pcbReturned); + + if (ppd) { + if (ppd->Callback) { + unsigned devs, wod, wid; + DSDRIVERDESC desc; + DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A_DATA data; + + devs = waveOutGetNumDevs(); + for (wod = 0; wod < devs; ++wod) { + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + if (err == DS_OK) { + DWORD size; + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0)); + if (err == DS_OK) { + WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size); + if (nameW) { + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size)); + if (err == DS_OK) { + CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR)); + if (szInterface) { + PIDSCDRIVER drv; + ZeroMemory(&data, sizeof(data)); + data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; + data.WaveDeviceId = wod; + data.DeviceId = DSOUND_renderer_guids[wod]; + data.Description = desc.szDesc; + data.Module = desc.szDrvname; + WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL ); + data.Interface = szInterface; + + data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + if (err == DS_OK && drv) + data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; + else + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + + TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); + (ppd->Callback)(&data, ppd->Context); } - } - HeapFree(GetProcessHeap(),0,nameW); - } - } - } + HeapFree(GetProcessHeap(),0,szInterface); + } + } + HeapFree(GetProcessHeap(),0,nameW); + } + } + } - devs = waveInGetNumDevs(); - for (wid = 0; wid < devs; ++wid) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); - if (err == DS_OK) { - DWORD size; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0)); - if (err == DS_OK) { - WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size); - if (nameW) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size)); - if (err == DS_OK) { - CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR)); - if (szInterface) { - PIDSCDRIVER drv; - ZeroMemory(&data, sizeof(data)); - data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; - data.WaveDeviceId = wid; - data.DeviceId = DSOUND_capture_guids[wid]; - data.Description = desc.szDesc; - data.Module = desc.szDrvname; - WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL ); - data.Interface = szInterface; - - data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; - err = mmErr(WineWaveInMessage((HWAVEIN)wid, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); - if (err == DS_OK && drv) - data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; - else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); - - TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); - (ppd->Callback)(&data, ppd->Context); - } - HeapFree(GetProcessHeap(),0,szInterface); + devs = waveInGetNumDevs(); + for (wid = 0; wid < devs; ++wid) { + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + if (err == DS_OK) { + DWORD size; + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDEVICEINTERFACESIZE,(DWORD_PTR)&size,0)); + if (err == DS_OK) { + WCHAR * nameW = HeapAlloc(GetProcessHeap(),0,size); + if (nameW) { + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDEVICEINTERFACE,(DWORD_PTR)nameW,size)); + if (err == DS_OK) { + CHAR * szInterface = HeapAlloc(GetProcessHeap(),0,size/sizeof(WCHAR)); + if (szInterface) { + PIDSCDRIVER drv; + ZeroMemory(&data, sizeof(data)); + data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; + data.WaveDeviceId = wid; + data.DeviceId = DSOUND_capture_guids[wid]; + data.Description = desc.szDesc; + data.Module = desc.szDrvname; + WideCharToMultiByte( CP_ACP, 0, nameW, size/sizeof(WCHAR), szInterface, size/sizeof(WCHAR), NULL, NULL ); + data.Interface = szInterface; + + data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; + err = mmErr(waveInMessage(UlongToHandle(wid), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + if (err == DS_OK && drv) + data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; + else + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + + TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); + (ppd->Callback)(&data, ppd->Context); } - } - HeapFree(GetProcessHeap(),0,nameW); - } - } - } + HeapFree(GetProcessHeap(),0,szInterface); + } + } + HeapFree(GetProcessHeap(),0,nameW); + } + } + } - return S_OK; - } - } - } else { - FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet)); + return S_OK; + } } if (pcbReturned) { - *pcbReturned = 0; - FIXME("*pcbReturned=%ld\n", *pcbReturned); + *pcbReturned = 0; + FIXME("*pcbReturned=%d\n", *pcbReturned); } return E_PROP_ID_UNSUPPORTED; } -static HRESULT WINAPI DSPROPERTY_EnumerateW( - REFGUID guidPropSet, +static HRESULT DSPROPERTY_EnumerateW( LPVOID pPropData, ULONG cbPropData, PULONG pcbReturned ) { - PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = (PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA) pPropData; + PDSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W_DATA ppd = pPropData; HRESULT err; - TRACE("(guidPropSet=%s,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", - debugstr_guid(guidPropSet),pPropData,cbPropData,pcbReturned); - - if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) { - if (ppd) { - if (ppd->Callback) { - unsigned devs, wod, wid; - DSDRIVERDESC desc; - DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data; - - devs = waveOutGetNumDevs(); - for (wod = 0; wod < devs; ++wod) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); - if (err == DS_OK) { - WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200); - WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200); - if (wDescription && wModule) { - DWORD size; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0)); - if (err == DS_OK) { - WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size); - if (wInterface) { - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size)); - if (err == DS_OK) { - PIDSCDRIVER drv; - ZeroMemory(&data, sizeof(data)); - data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; - data.WaveDeviceId = wod; - data.DeviceId = DSOUND_renderer_guids[wod]; - - MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); - - data.Description = wDescription; - data.Module = wModule; - data.Interface = wInterface; - - data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; - err = mmErr(WineWaveOutMessage((HWAVEOUT)wod, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); - if (err == DS_OK && drv) - data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; - else - WARN("WineWaveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); - - TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); - (ppd->Callback)(&data, ppd->Context); - } - } - HeapFree(GetProcessHeap(),0,wInterface); - } - } - HeapFree(GetProcessHeap(),0,wDescription); - HeapFree(GetProcessHeap(),0,wModule); - } - } - - devs = waveInGetNumDevs(); - for (wid = 0; wid < devs; ++wid) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); - if (err == DS_OK) { - WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200); - WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200); - if (wDescription && wModule) { - DWORD size; - err = mmErr(WineWaveInMessage((HWAVEIN)wid,DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0)); - if (err == DS_OK) { - WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size); - if (wInterface) { - err = mmErr(WineWaveInMessage((HWAVEIN)wid, DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size)); - if (err == DS_OK) { - PIDSCDRIVER drv; - ZeroMemory(&data, sizeof(data)); - data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; - data.WaveDeviceId = wid; - data.DeviceId = DSOUND_capture_guids[wid]; - - MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); - MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); - - data.Description = wDescription; - data.Module = wModule; - data.Interface = wInterface; - data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; - err = mmErr(WineWaveInMessage((HWAVEIN)wid, DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); - if (err == DS_OK && drv) - data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; - else - WARN("WineWaveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); - - TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); - (ppd->Callback)(&data, ppd->Context); + TRACE("(pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + pPropData,cbPropData,pcbReturned); + + if (ppd) { + if (ppd->Callback) { + unsigned devs, wod, wid; + DSDRIVERDESC desc; + DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W_DATA data; + + devs = waveOutGetNumDevs(); + for (wod = 0; wod < devs; ++wod) { + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + if (err == DS_OK) { + WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200); + WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200); + if (wDescription && wModule) { + DWORD size; + err = mmErr(waveOutMessage(UlongToHandle(wod),DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0)); + if (err == DS_OK) { + WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size); + if (wInterface) { + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size)); + if (err == DS_OK) { + PIDSCDRIVER drv; + ZeroMemory(&data, sizeof(data)); + data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_RENDER; + data.WaveDeviceId = wod; + data.DeviceId = DSOUND_renderer_guids[wod]; + + MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); + + data.Description = wDescription; + data.Module = wModule; + data.Interface = wInterface; + + data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; + err = mmErr(waveOutMessage(UlongToHandle(wod), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + if (err == DS_OK && drv) + data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; + else + WARN("waveOutMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + + TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); + (ppd->Callback)(&data, ppd->Context); } + } + HeapFree(GetProcessHeap(),0,wInterface); + } + } + HeapFree(GetProcessHeap(),0,wDescription); + HeapFree(GetProcessHeap(),0,wModule); + } + } + + devs = waveInGetNumDevs(); + for (wid = 0; wid < devs; ++wid) { + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDSOUNDDESC,(DWORD_PTR)&desc,0)); + if (err == DS_OK) { + WCHAR * wDescription = HeapAlloc(GetProcessHeap(),0,0x200); + WCHAR * wModule = HeapAlloc(GetProcessHeap(),0,0x200); + if (wDescription && wModule) { + DWORD size; + err = mmErr(waveInMessage(UlongToHandle(wid),DRV_QUERYDEVICEINTERFACESIZE, (DWORD_PTR)&size, 0)); + if (err == DS_OK) { + WCHAR * wInterface = HeapAlloc(GetProcessHeap(),0,size); + if (wInterface) { + err = mmErr(waveInMessage(UlongToHandle(wid), DRV_QUERYDEVICEINTERFACE, (DWORD_PTR)wInterface, size)); + if (err == DS_OK) { + PIDSCDRIVER drv; + ZeroMemory(&data, sizeof(data)); + data.DataFlow = DIRECTSOUNDDEVICE_DATAFLOW_CAPTURE; + data.WaveDeviceId = wid; + data.DeviceId = DSOUND_capture_guids[wid]; + + MultiByteToWideChar( CP_ACP, 0, desc.szDesc, -1, wDescription, 0x100 ); + MultiByteToWideChar( CP_ACP, 0, desc.szDrvname, -1, wModule, 0x100 ); + + data.Description = wDescription; + data.Module = wModule; + data.Interface = wInterface; + data.Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; + err = mmErr(waveInMessage(UlongToHandle(wid), DRV_QUERYDSOUNDIFACE, (DWORD_PTR)&drv, 0)); + if (err == DS_OK && drv) + data.Type = DIRECTSOUNDDEVICE_TYPE_VXD; + else + WARN("waveInMessage(DRV_QUERYDSOUNDIFACE) failed\n"); + + TRACE("calling Callback(%p,%p)\n", &data, ppd->Context); + (ppd->Callback)(&data, ppd->Context); } - HeapFree(GetProcessHeap(),0,wInterface); - } - } - HeapFree(GetProcessHeap(),0,wDescription); - HeapFree(GetProcessHeap(),0,wModule); - } - } + } + HeapFree(GetProcessHeap(),0,wInterface); + } + } + HeapFree(GetProcessHeap(),0,wDescription); + HeapFree(GetProcessHeap(),0,wModule); + } + } - return S_OK; - } - } - } else { - FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet)); + return S_OK; + } } if (pcbReturned) { - *pcbReturned = 0; - FIXME("*pcbReturned=%ld\n", *pcbReturned); + *pcbReturned = 0; + FIXME("*pcbReturned=%d\n", *pcbReturned); } return E_PROP_ID_UNSUPPORTED; @@ -1395,38 +1382,38 @@ static HRESULT WINAPI IKsPrivatePropertySetImpl_Get( PULONG pcbReturned ) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; - TRACE("(iface=%p,guidPropSet=%s,dwPropID=%ld,pInstanceData=%p,cbInstanceData=%ld,pPropData=%p,cbPropData=%ld,pcbReturned=%p)\n", - This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned); + TRACE("(iface=%p,guidPropSet=%s,dwPropID=%d,pInstanceData=%p,cbInstanceData=%d,pPropData=%p,cbPropData=%d,pcbReturned=%p)\n", + This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData,pcbReturned); if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) { - switch (dwPropID) { - case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A: - return DSPROPERTY_WaveDeviceMappingA(guidPropSet,pPropData,cbPropData,pcbReturned); - case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1: - return DSPROPERTY_Description1(guidPropSet,pPropData,cbPropData,pcbReturned); - case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1: - return DSPROPERTY_Enumerate1(guidPropSet,pPropData,cbPropData,pcbReturned); - case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W: - return DSPROPERTY_WaveDeviceMappingW(guidPropSet,pPropData,cbPropData,pcbReturned); - case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A: - return DSPROPERTY_DescriptionA(guidPropSet,pPropData,cbPropData,pcbReturned); - case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W: - return DSPROPERTY_DescriptionW(guidPropSet,pPropData,cbPropData,pcbReturned); - case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A: - return DSPROPERTY_EnumerateA(guidPropSet,pPropData,cbPropData,pcbReturned); - case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W: - return DSPROPERTY_EnumerateW(guidPropSet,pPropData,cbPropData,pcbReturned); - default: - FIXME("unsupported ID: %ld\n",dwPropID); - break; - } + switch (dwPropID) { + case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_A: + return DSPROPERTY_WaveDeviceMappingA(pPropData,cbPropData,pcbReturned); + case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_1: + return DSPROPERTY_Description1(pPropData,cbPropData,pcbReturned); + case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_1: + return DSPROPERTY_Enumerate1(pPropData,cbPropData,pcbReturned); + case DSPROPERTY_DIRECTSOUNDDEVICE_WAVEDEVICEMAPPING_W: + return DSPROPERTY_WaveDeviceMappingW(pPropData,cbPropData,pcbReturned); + case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_A: + return DSPROPERTY_DescriptionA(pPropData,cbPropData,pcbReturned); + case DSPROPERTY_DIRECTSOUNDDEVICE_DESCRIPTION_W: + return DSPROPERTY_DescriptionW(pPropData,cbPropData,pcbReturned); + case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_A: + return DSPROPERTY_EnumerateA(pPropData,cbPropData,pcbReturned); + case DSPROPERTY_DIRECTSOUNDDEVICE_ENUMERATE_W: + return DSPROPERTY_EnumerateW(pPropData,cbPropData,pcbReturned); + default: + FIXME("unsupported ID: %d\n",dwPropID); + break; + } } else { - FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet)); + FIXME("unsupported property: %s\n",debugstr_guid(guidPropSet)); } if (pcbReturned) { - *pcbReturned = 0; - FIXME("*pcbReturned=%ld\n", *pcbReturned); + *pcbReturned = 0; + FIXME("*pcbReturned=%d\n", *pcbReturned); } return E_PROP_ID_UNSUPPORTED; @@ -1443,7 +1430,7 @@ static HRESULT WINAPI IKsPrivatePropertySetImpl_Set( { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; - FIXME("(%p,%s,%ld,%p,%ld,%p,%ld), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData); + FIXME("(%p,%s,%d,%p,%d,%p,%d), stub!\n",This,debugstr_guid(guidPropSet),dwPropID,pInstanceData,cbInstanceData,pPropData,cbPropData); return E_PROP_ID_UNSUPPORTED; } @@ -1454,7 +1441,7 @@ static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport( PULONG pTypeSupport ) { IKsPrivatePropertySetImpl *This = (IKsPrivatePropertySetImpl *)iface; - TRACE("(%p,%s,%ld,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport); + TRACE("(%p,%s,%d,%p)\n",This,debugstr_guid(guidPropSet),dwPropID,pTypeSupport); if ( IsEqualGUID( &DSPROPSETID_DirectSoundDevice, guidPropSet) ) { switch (dwPropID) { @@ -1483,7 +1470,7 @@ static HRESULT WINAPI IKsPrivatePropertySetImpl_QuerySupport( *pTypeSupport = KSPROPERTY_SUPPORT_GET; return S_OK; default: - FIXME("unsupported ID: %ld\n",dwPropID); + FIXME("unsupported ID: %d\n",dwPropID); break; } } else { @@ -1502,10 +1489,18 @@ static const IKsPropertySetVtbl ikspvt = { IKsPrivatePropertySetImpl_QuerySupport }; -HRESULT WINAPI IKsPrivatePropertySetImpl_Create( +HRESULT IKsPrivatePropertySetImpl_Create( + REFIID riid, IKsPrivatePropertySetImpl **piks) { IKsPrivatePropertySetImpl *iks; + TRACE("(%s, %p)\n", debugstr_guid(riid), piks); + + if (!IsEqualIID(riid, &IID_IUnknown) && + !IsEqualIID(riid, &IID_IKsPropertySet)) { + *piks = 0; + return E_NOINTERFACE; + } iks = HeapAlloc(GetProcessHeap(),0,sizeof(*iks)); iks->ref = 1; diff --git a/reactos/dll/directx/dsound/regsvr.c b/reactos/dll/directx/dsound/regsvr.c index 263cd4455b2..49c648a9199 100644 --- a/reactos/dll/directx/dsound/regsvr.c +++ b/reactos/dll/directx/dsound/regsvr.c @@ -15,26 +15,29 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include -#include +#define NONAMELESSSTRUCT +#define NONAMELESSUNION #include "windef.h" #include "winbase.h" -#include "wingdi.h" #include "winuser.h" #include "winreg.h" -#include "winerror.h" #include "mmsystem.h" #include "dsound.h" #include "wine/debug.h" +#include "wine/unicode.h" WINE_DEFAULT_DEBUG_CHANNEL(dsound); +static LSTATUS (WINAPI *pRegDeleteTreeW)(HKEY,LPCWSTR); +static LSTATUS (WINAPI *pRegDeleteTreeA)(HKEY,LPCSTR); + /* * Near the bottom of this file are the exported DllRegisterServer and * DllUnregisterServer, which make all this worthwhile. @@ -116,9 +119,6 @@ static LONG register_key_defvalueA(HKEY base, WCHAR const *name, static LONG register_progid(WCHAR const *clsid, char const *progid, char const *curver_progid, char const *name, char const *extra); -static LONG recursive_delete_key(HKEY key); -static LONG recursive_delete_keyA(HKEY base, char const *name); -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name); /*********************************************************************** * register_interfaces @@ -149,7 +149,7 @@ static HRESULT register_interfaces(struct regsvr_interface const *list) } if (list->base_iid) { - register_key_guid(iid_key, base_ifa_keyname, list->base_iid); + res = register_key_guid(iid_key, base_ifa_keyname, list->base_iid); if (res != ERROR_SUCCESS) goto error_close_iid_key; } @@ -161,7 +161,7 @@ static HRESULT register_interfaces(struct regsvr_interface const *list) KEY_READ | KEY_WRITE, NULL, &key, NULL); if (res != ERROR_SUCCESS) goto error_close_iid_key; - wsprintfW(buf, fmt, list->num_methods); + sprintfW(buf, fmt, list->num_methods); res = RegSetValueExW(key, NULL, 0, REG_SZ, (CONST BYTE*)buf, (lstrlenW(buf) + 1) * sizeof(WCHAR)); @@ -171,12 +171,12 @@ static HRESULT register_interfaces(struct regsvr_interface const *list) } if (list->ps_clsid) { - register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid); + res = register_key_guid(iid_key, ps_clsid_keyname, list->ps_clsid); if (res != ERROR_SUCCESS) goto error_close_iid_key; } if (list->ps_clsid32) { - register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32); + res = register_key_guid(iid_key, ps_clsid32_keyname, list->ps_clsid32); if (res != ERROR_SUCCESS) goto error_close_iid_key; } @@ -207,7 +207,8 @@ static HRESULT unregister_interfaces(struct regsvr_interface const *list) WCHAR buf[39]; StringFromGUID2(list->iid, buf, 39); - res = recursive_delete_keyW(interface_key, buf); + res = pRegDeleteTreeW(interface_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; } RegCloseKey(interface_key); @@ -314,16 +315,19 @@ static HRESULT unregister_coclasses(struct regsvr_coclass const *list) WCHAR buf[39]; StringFromGUID2(list->clsid, buf, 39); - res = recursive_delete_keyW(coclass_key, buf); + res = pRegDeleteTreeW(coclass_key, buf); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; if (list->progid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->progid); + res = pRegDeleteTreeA(HKEY_CLASSES_ROOT, list->progid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } if (list->viprogid) { - res = recursive_delete_keyA(HKEY_CLASSES_ROOT, list->viprogid); + res = pRegDeleteTreeA(HKEY_CLASSES_ROOT, list->viprogid); + if (res == ERROR_FILE_NOT_FOUND) res = ERROR_SUCCESS; if (res != ERROR_SUCCESS) goto error_close_coclass_key; } } @@ -435,70 +439,6 @@ error_close_progid_key: return res; } -/*********************************************************************** - * recursive_delete_key - */ -static LONG recursive_delete_key(HKEY key) -{ - LONG res; - WCHAR subkey_name[MAX_PATH]; - DWORD cName; - HKEY subkey; - - for (;;) { - cName = sizeof(subkey_name) / sizeof(WCHAR); - res = RegEnumKeyExW(key, 0, subkey_name, &cName, - NULL, NULL, NULL, NULL); - if (res != ERROR_SUCCESS && res != ERROR_MORE_DATA) { - res = ERROR_SUCCESS; /* presumably we're done enumerating */ - break; - } - res = RegOpenKeyExW(key, subkey_name, 0, - KEY_READ | KEY_WRITE, &subkey); - if (res == ERROR_FILE_NOT_FOUND) continue; - if (res != ERROR_SUCCESS) break; - - res = recursive_delete_key(subkey); - RegCloseKey(subkey); - if (res != ERROR_SUCCESS) break; - } - - if (res == ERROR_SUCCESS) res = RegDeleteKeyW(key, 0); - return res; -} - -/*********************************************************************** - * recursive_delete_keyA - */ -static LONG recursive_delete_keyA(HKEY base, char const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExA(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - -/*********************************************************************** - * recursive_delete_keyW - */ -static LONG recursive_delete_keyW(HKEY base, WCHAR const *name) -{ - LONG res; - HKEY key; - - res = RegOpenKeyExW(base, name, 0, KEY_READ | KEY_WRITE, &key); - if (res == ERROR_FILE_NOT_FOUND) return ERROR_SUCCESS; - if (res != ERROR_SUCCESS) return res; - res = recursive_delete_key(key); - RegCloseKey(key); - return res; -} - /*********************************************************************** * coclass list */ @@ -575,6 +515,12 @@ HRESULT WINAPI DllUnregisterServer(void) { HRESULT hr; + HMODULE advapi32 = GetModuleHandleA("advapi32"); + if (!advapi32) return E_FAIL; + pRegDeleteTreeA = (void *) GetProcAddress(advapi32, "RegDeleteTreeA"); + pRegDeleteTreeW = (void *) GetProcAddress(advapi32, "RegDeleteTreeW"); + if (!pRegDeleteTreeA || !pRegDeleteTreeW) return E_FAIL; + TRACE("\n"); hr = unregister_coclasses(coclass_list); diff --git a/reactos/dll/directx/dsound/sound3d.c b/reactos/dll/directx/dsound/sound3d.c index 91879a3cb93..252c7632667 100644 --- a/reactos/dll/directx/dsound/sound3d.c +++ b/reactos/dll/directx/dsound/sound3d.c @@ -17,7 +17,7 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ /* * Most thread locking is complete. There may be a few race @@ -44,8 +44,8 @@ #define NONAMELESSSTRUCT #include "windef.h" #include "winbase.h" +#include "winuser.h" #include "mmsystem.h" -#include "winreg.h" #include "winternl.h" #include "mmddk.h" #include "wine/debug.h" @@ -53,8 +53,6 @@ #include "dsdriver.h" #include "dsound_private.h" -/* default intensity level for human ears */ -#define DEFAULT_INTENSITY 0.000000000001f /* default velocity of sound in the air */ #define DEFAULT_VELOCITY 340 @@ -65,29 +63,29 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound3d); */ /* scalar product (i believe it's called dot product in english) */ -static inline D3DVALUE ScalarProduct (LPD3DVECTOR a, LPD3DVECTOR b) +static inline D3DVALUE ScalarProduct (const D3DVECTOR *a, const D3DVECTOR *b) { D3DVALUE c; c = (a->x*b->x) + (a->y*b->y) + (a->z*b->z); - TRACE("(%f,%f,%f) * (%f,%f,%f) = %f)\n", a->x, a->y, a->z, b->x, b->y, \ + TRACE("(%f,%f,%f) * (%f,%f,%f) = %f)\n", a->x, a->y, a->z, b->x, b->y, b->z, c); return c; } /* vector product (i believe it's called cross product in english */ -static inline D3DVECTOR VectorProduct (LPD3DVECTOR a, LPD3DVECTOR b) +static inline D3DVECTOR VectorProduct (const D3DVECTOR *a, const D3DVECTOR *b) { D3DVECTOR c; c.x = (a->y*b->z) - (a->z*b->y); c.y = (a->z*b->x) - (a->x*b->z); c.z = (a->x*b->y) - (a->y*b->x); - TRACE("(%f,%f,%f) x (%f,%f,%f) = (%f,%f,%f)\n", a->x, a->y, a->z, b->x, b->y, \ + TRACE("(%f,%f,%f) x (%f,%f,%f) = (%f,%f,%f)\n", a->x, a->y, a->z, b->x, b->y, b->z, c.x, c.y, c.z); return c; } /* magnitude (length) of vector */ -static inline D3DVALUE VectorMagnitude (LPD3DVECTOR a) +static inline D3DVALUE VectorMagnitude (const D3DVECTOR *a) { D3DVALUE l; l = sqrt (ScalarProduct (a, a)); @@ -104,49 +102,31 @@ static inline D3DVALUE RadToDeg (D3DVALUE angle) return newangle; } -/* conversion between degrees and radians */ -static inline D3DVALUE DegToRad (D3DVALUE angle) -{ - D3DVALUE newangle; - newangle = angle * (2*M_PI/360); - TRACE("%f deg = %f rad\n", angle, newangle); - return newangle; -} - -/* angle between vectors - deg version */ -static inline D3DVALUE AngleBetweenVectorsDeg (LPD3DVECTOR a, LPD3DVECTOR b) +/* angle between vectors - rad version */ +static inline D3DVALUE AngleBetweenVectorsRad (const D3DVECTOR *a, const D3DVECTOR *b) { D3DVALUE la, lb, product, angle, cos; - /* definition of scalar product: a*b = |a|*|b|*cos...therefore: */ + /* definition of scalar product: a*b = |a|*|b|*cos... therefore: */ product = ScalarProduct (a,b); la = VectorMagnitude (a); lb = VectorMagnitude (b); + if (!la || !lb) + return 0; + cos = product/(la*lb); angle = acos(cos); - /* we now have angle in radians */ - angle = RadToDeg(angle); - TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f degrees\n", a->x, a->y, a->z, b->x, - b->y, b->z, angle); - return angle; + TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f radians (%f degrees)\n", a->x, a->y, a->z, b->x, + b->y, b->z, angle, RadToDeg(angle)); + return angle; } -/* angle between vectors - rad version */ -static inline D3DVALUE AngleBetweenVectorsRad (LPD3DVECTOR a, LPD3DVECTOR b) +static inline D3DVALUE AngleBetweenVectorsDeg (const D3DVECTOR *a, const D3DVECTOR *b) { - D3DVALUE la, lb, product, angle, cos; - /* definition of scalar product: a*b = |a|*|b|*cos...therefore: */ - product = ScalarProduct (a,b); - la = VectorMagnitude (a); - lb = VectorMagnitude (b); - cos = product/(la*lb); - angle = acos(cos); - TRACE("angle between (%f,%f,%f) and (%f,%f,%f) = %f radians\n", a->x, a->y, a->z, b->x, - b->y, b->z, angle); - return angle; + return RadToDeg(AngleBetweenVectorsRad(a, b)); } /* calculates vector between two points */ -static inline D3DVECTOR VectorBetweenTwoPoints (LPD3DVECTOR a, LPD3DVECTOR b) +static inline D3DVECTOR VectorBetweenTwoPoints (const D3DVECTOR *a, const D3DVECTOR *b) { D3DVECTOR c; c.x = b->x - a->x; @@ -158,7 +138,7 @@ static inline D3DVECTOR VectorBetweenTwoPoints (LPD3DVECTOR a, LPD3DVECTOR b) } /* calculates the length of vector's projection on another vector */ -static inline D3DVALUE ProjectVector (LPD3DVECTOR a, LPD3DVECTOR p) +static inline D3DVALUE ProjectVector (const D3DVECTOR *a, const D3DVECTOR *p) { D3DVALUE prod, result; prod = ScalarProduct(a, p); @@ -176,9 +156,6 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) { /* volume, at which the sound will be played after all calcs. */ D3DVALUE lVolume = 0; - /* intensity (used for distance related stuff) */ - double flIntensity; - double flTemp; /* stuff for distance related stuff calc. */ D3DVECTOR vDistance; D3DVALUE flDistance = 0; @@ -194,19 +171,18 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) /* initial buffer volume */ lVolume = dsb->ds3db_lVolume; - + switch (dsb->ds3db_ds3db.dwMode) { case DS3DMODE_DISABLE: TRACE("3D processing disabled\n"); /* this one is here only to eliminate annoying warning message */ DSOUND_RecalcVolPan (&dsb->volpan); - DSOUND_ForceRemix (dsb); break; case DS3DMODE_NORMAL: TRACE("Normal 3D processing mode\n"); /* we need to calculate distance between buffer and listener*/ - vDistance = VectorBetweenTwoPoints(&dsb->ds3db_ds3db.vPosition, &dsb->dsound->device->ds3dl.vPosition); + vDistance = VectorBetweenTwoPoints(&dsb->ds3db_ds3db.vPosition, &dsb->device->ds3dl.vPosition); flDistance = VectorMagnitude (&vDistance); break; case DS3DMODE_HEADRELATIVE: @@ -215,35 +191,27 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) flDistance = VectorMagnitude (&dsb->ds3db_ds3db.vPosition); break; } - + if (flDistance > dsb->ds3db_ds3db.flMaxDistance) { /* some apps don't want you to hear too distant sounds... */ if (dsb->dsbd.dwFlags & DSBCAPS_MUTE3DATMAXDISTANCE) { dsb->volpan.lVolume = DSBVOLUME_MIN; - DSOUND_RecalcVolPan (&dsb->volpan); + DSOUND_RecalcVolPan (&dsb->volpan); /* i guess mixing here would be a waste of power */ return; } else flDistance = dsb->ds3db_ds3db.flMaxDistance; - } + } 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 */ - lVolume += 10000; /* ms likes working with negative volume...i don't */ - lVolume /= 1000; /* convert hundreths of dB into B */ - /* intensity level (loudness) = log10(Intensity/DefaultIntensity)...therefore */ - flIntensity = pow(10,lVolume)*DEFAULT_INTENSITY; - flTemp = (flDistance/dsb->ds3db_ds3db.flMinDistance)*(flDistance/dsb->ds3db_ds3db.flMinDistance); - flIntensity /= flTemp; - lVolume = log10(flIntensity/DEFAULT_INTENSITY); - lVolume *= 1000; /* convert back to hundreths of dB */ - lVolume -= 10000; /* we need to do it in ms way */ - TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %ld to %f\n", flDistance, dsb->ds3db_ds3db.flMinDistance, dsb->ds3db_lVolume, lVolume); + + /* attenuation proportional to the distance squared, converted to millibels as in lVolume*/ + lVolume -= log10(flDistance/dsb->ds3db_ds3db.flMinDistance * flDistance/dsb->ds3db_ds3db.flMinDistance)*1000; + TRACE("dist. att: Distance = %f, MinDistance = %f => adjusting volume %d to %f\n", flDistance, dsb->ds3db_ds3db.flMinDistance, dsb->ds3db_lVolume, lVolume); /* conning */ /* sometimes it happens that vConeOrientation vector = (0,0,0); in this case angle is "nan" and it's useless*/ @@ -261,6 +229,9 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) /* my test show that for my way of calc., we need only half of angles */ DWORD dwInsideConeAngle = dsb->ds3db_ds3db.dwInsideConeAngle/2; DWORD dwOutsideConeAngle = dsb->ds3db_ds3db.dwOutsideConeAngle/2; + if (dwOutsideConeAngle == dwInsideConeAngle) + ++dwOutsideConeAngle; + /* full volume */ if (flAngle < dwInsideConeAngle) flAngle = dwInsideConeAngle; @@ -270,55 +241,57 @@ void DSOUND_Calc3DBuffer(IDirectSoundBufferImpl *dsb) /* this probably isn't the right thing, but it's ok for the time being */ 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) = %d deg; OutsideConeAngle(/2) = %d deg; ConeOutsideVolume = %d => adjusting volume to %f\n", flAngle, dsb->ds3db_ds3db.dwInsideConeAngle/2, dsb->ds3db_ds3db.dwOutsideConeAngle/2, dsb->ds3db_ds3db.lConeOutsideVolume, lVolume); } dsb->volpan.lVolume = lVolume; - + /* panning */ - if (dsb->dsound->device->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x && - dsb->dsound->device->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y && - dsb->dsound->device->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) { + if (dsb->device->ds3dl.vPosition.x == dsb->ds3db_ds3db.vPosition.x && + dsb->device->ds3dl.vPosition.y == dsb->ds3db_ds3db.vPosition.y && + dsb->device->ds3dl.vPosition.z == dsb->ds3db_ds3db.vPosition.z) { dsb->volpan.lPan = 0; flAngle = 0.0; } else { - vDistance = VectorBetweenTwoPoints(&dsb->dsound->device->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition); - vLeft = VectorProduct(&dsb->dsound->device->ds3dl.vOrientFront, &dsb->dsound->device->ds3dl.vOrientTop); + vDistance = VectorBetweenTwoPoints(&dsb->device->ds3dl.vPosition, &dsb->ds3db_ds3db.vPosition); + vLeft = VectorProduct(&dsb->device->ds3dl.vOrientFront, &dsb->device->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); + TRACE("panning: Angle = %f rad, lPan = %d\n", flAngle, dsb->volpan.lPan); /* FIXME: Doppler Effect disabled since i have no idea which frequency to change and how to do it */ -#if 0 +#if 0 /* doppler shift*/ - if ((VectorMagnitude(&ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->dsound->device->ds3dl.vVelocity) == 0)) + if ((VectorMagnitude(&ds3db_ds3db.vVelocity) == 0) && (VectorMagnitude(&dsb->device->ds3dl.vVelocity) == 0)) { TRACE("doppler: Buffer and Listener don't have velocities\n"); } - else + else if (ds3db_ds3db.vVelocity != dsb->device->ds3dl.vVelocity) { - /* calculate length of ds3db.vVelocity component which causes Doppler Effect + /* calculate length of ds3db_ds3db.vVelocity component which causes Doppler Effect 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 */ flBufferVel = ProjectVector(&dsb->ds3db_ds3db.vVelocity, &vDistance); /* calculate length of ds3dl.vVelocity component which causes Doppler Effect 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 */ - flListenerVel = ProjectVector(&dsb->dsound->device->ds3dl.vVelocity, &vDistance); + flListenerVel = ProjectVector(&dsb->device->ds3dl.vVelocity, &vDistance); /* formula taken from Gianicoli D.: Physics, 4th edition: */ /* FIXME: replace dsb->freq with appropriate frequency ! */ 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, dsb->freq, flFreq); /* FIXME: replace following line with correct frequency setting ! */ dsb->freq = flFreq; + DSOUND_RecalcFormat(dsb); + DSOUND_MixToTemporary(dsb, 0, dsb->buflen); } -#endif - +#endif + /* time for remix */ DSOUND_RecalcVolPan(&dsb->volpan); } @@ -328,22 +301,18 @@ 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 DSOUND_ChangeListener(IDirectSound3DListenerImpl *ds3dl) { int i; TRACE("(%p)\n",ds3dl); - for (i = 0; i < ds3dl->dsound->device->nrofbuffers; i++) + for (i = 0; i < ds3dl->device->nrofbuffers; i++) { - /* some buffers don't have 3d buffer (Ultima IX seems to - crash without the following line) */ - if (ds3dl->dsound->device->buffers[i]->ds3db == NULL) - continue; - if (ds3dl->dsound->device->buffers[i]->ds3db_need_recalc) + /* check if this buffer is waiting for recalculation */ + if (ds3dl->device->buffers[i]->ds3db_need_recalc) { - DSOUND_Mix3DBuffer(ds3dl->dsound->device->buffers[i]); + DSOUND_Mix3DBuffer(ds3dl->device->buffers[i]); } } } @@ -366,7 +335,7 @@ static ULONG WINAPI IDirectSound3DBufferImpl_AddRef(LPDIRECTSOUND3DBUFFER iface) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -374,7 +343,7 @@ static ULONG WINAPI IDirectSound3DBufferImpl_Release(LPDIRECTSOUND3DBUFFER iface { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { This->dsb->ds3db = NULL; @@ -399,10 +368,10 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetAllParameters( } if (lpDs3dBuffer->dwSize < sizeof(*lpDs3dBuffer)) { - WARN("invalid parameter: lpDs3dBuffer->dwSize = %ld < %d\n",lpDs3dBuffer->dwSize, sizeof(*lpDs3dBuffer)); + WARN("invalid parameter: lpDs3dBuffer->dwSize = %d\n",lpDs3dBuffer->dwSize); return DSERR_INVALIDPARAM; } - + TRACE("returning: all parameters\n"); *lpDs3dBuffer = This->dsb->ds3db_ds3db; return DS_OK; @@ -414,7 +383,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeAngles( LPDWORD lpdwOutsideConeAngle) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("returning: Inside Cone Angle = %ld degrees; Outside Cone Angle = %ld degrees\n", + TRACE("returning: Inside Cone Angle = %d degrees; Outside Cone Angle = %d degrees\n", This->dsb->ds3db_ds3db.dwInsideConeAngle, This->dsb->ds3db_ds3db.dwOutsideConeAngle); *lpdwInsideConeAngle = This->dsb->ds3db_ds3db.dwInsideConeAngle; *lpdwOutsideConeAngle = This->dsb->ds3db_ds3db.dwOutsideConeAngle; @@ -439,7 +408,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetConeOutsideVolume( LPLONG lplConeOutsideVolume) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("returning: Cone Outside Volume = %ld\n", This->dsb->ds3db_ds3db.lConeOutsideVolume); + TRACE("returning: Cone Outside Volume = %d\n", This->dsb->ds3db_ds3db.lConeOutsideVolume); *lplConeOutsideVolume = This->dsb->ds3db_ds3db.lConeOutsideVolume; return DS_OK; } @@ -469,7 +438,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_GetMode( LPDWORD lpdwMode) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("returning: Mode = %ld\n", This->dsb->ds3db_ds3db.dwMode); + TRACE("returning: Mode = %d\n", This->dsb->ds3db_ds3db.dwMode); *lpdwMode = This->dsb->ds3db_ds3db.dwMode; return DS_OK; } @@ -507,7 +476,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters( { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; DWORD status = DSERR_INVALIDPARAM; - TRACE("(%p,%p,%lx)\n",iface,lpcDs3dBuffer,dwApply); + TRACE("(%p,%p,%x)\n",iface,lpcDs3dBuffer,dwApply); if (lpcDs3dBuffer == NULL) { WARN("invalid parameter: lpcDs3dBuffer == NULL\n"); @@ -515,12 +484,11 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetAllParameters( } if (lpcDs3dBuffer->dwSize != sizeof(DS3DBUFFER)) { - WARN("invalid parameter: lpcDs3dBuffer->dwSize = %ld != %d\n", - lpcDs3dBuffer->dwSize, sizeof(DS3DBUFFER)); + WARN("invalid parameter: lpcDs3dBuffer->dwSize = %d\n", lpcDs3dBuffer->dwSize); return status; } - TRACE("setting: all parameters; dwApply = %ld\n", dwApply); + TRACE("setting: all parameters; dwApply = %d\n", dwApply); This->dsb->ds3db_ds3db = *lpcDs3dBuffer; if (dwApply == DS3D_IMMEDIATE) @@ -540,7 +508,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeAngles( DWORD dwApply) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("setting: Inside Cone Angle = %ld; Outside Cone Angle = %ld; dwApply = %ld\n", + TRACE("setting: Inside Cone Angle = %d; Outside Cone Angle = %d; dwApply = %d\n", dwInsideConeAngle, dwOutsideConeAngle, dwApply); This->dsb->ds3db_ds3db.dwInsideConeAngle = dwInsideConeAngle; This->dsb->ds3db_ds3db.dwOutsideConeAngle = dwOutsideConeAngle; @@ -558,7 +526,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOrientation( DWORD dwApply) { IDirectSound3DBufferImpl *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 = %d\n", x, y, z, dwApply); This->dsb->ds3db_ds3db.vConeOrientation.x = x; This->dsb->ds3db_ds3db.vConeOrientation.y = y; This->dsb->ds3db_ds3db.vConeOrientation.z = z; @@ -577,7 +545,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetConeOutsideVolume( DWORD dwApply) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("setting: ConeOutsideVolume = %ld; dwApply = %ld\n", lConeOutsideVolume, dwApply); + TRACE("setting: ConeOutsideVolume = %d; dwApply = %d\n", lConeOutsideVolume, dwApply); This->dsb->ds3db_ds3db.lConeOutsideVolume = lConeOutsideVolume; if (dwApply == DS3D_IMMEDIATE) { @@ -594,7 +562,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMaxDistance( DWORD dwApply) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("setting: MaxDistance = %f; dwApply = %ld\n", fMaxDistance, dwApply); + TRACE("setting: MaxDistance = %f; dwApply = %d\n", fMaxDistance, dwApply); This->dsb->ds3db_ds3db.flMaxDistance = fMaxDistance; if (dwApply == DS3D_IMMEDIATE) { @@ -611,7 +579,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMinDistance( DWORD dwApply) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("setting: MinDistance = %f; dwApply = %ld\n", fMinDistance, dwApply); + TRACE("setting: MinDistance = %f; dwApply = %d\n", fMinDistance, dwApply); This->dsb->ds3db_ds3db.flMinDistance = fMinDistance; if (dwApply == DS3D_IMMEDIATE) { @@ -628,7 +596,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetMode( DWORD dwApply) { IDirectSound3DBufferImpl *This = (IDirectSound3DBufferImpl *)iface; - TRACE("setting: Mode = %ld; dwApply = %ld\n", dwMode, dwApply); + TRACE("setting: Mode = %d; dwApply = %d\n", dwMode, dwApply); This->dsb->ds3db_ds3db.dwMode = dwMode; if (dwApply == DS3D_IMMEDIATE) { @@ -645,7 +613,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetPosition( DWORD dwApply) { IDirectSound3DBufferImpl *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 = %d\n", x, y, z, dwApply); This->dsb->ds3db_ds3db.vPosition.x = x; This->dsb->ds3db_ds3db.vPosition.y = y; This->dsb->ds3db_ds3db.vPosition.z = z; @@ -664,7 +632,7 @@ static HRESULT WINAPI IDirectSound3DBufferImpl_SetVelocity( DWORD dwApply) { IDirectSound3DBufferImpl *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 = %d\n", x, y, z, dwApply); This->dsb->ds3db_ds3db.vVelocity.x = x; This->dsb->ds3db_ds3db.vVelocity.y = y; This->dsb->ds3db_ds3db.vVelocity.z = z; @@ -704,7 +672,7 @@ static const IDirectSound3DBufferVtbl ds3dbvt = IDirectSound3DBufferImpl_SetVelocity, }; -HRESULT WINAPI IDirectSound3DBufferImpl_Create( +HRESULT IDirectSound3DBufferImpl_Create( IDirectSoundBufferImpl *dsb, IDirectSound3DBufferImpl **pds3db) { @@ -748,7 +716,7 @@ HRESULT WINAPI IDirectSound3DBufferImpl_Create( return S_OK; } -HRESULT WINAPI IDirectSound3DBufferImpl_Destroy( +HRESULT IDirectSound3DBufferImpl_Destroy( IDirectSound3DBufferImpl *pds3db) { TRACE("(%p)\n",pds3db); @@ -785,10 +753,10 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_QueryInterface( } if ( IsEqualGUID(riid, &IID_IDirectSoundBuffer) ) { - if (!This->dsound->device->primary) - PrimaryBufferImpl_Create(This->dsound, &(This->dsound->device->primary), &(This->dsound->device->dsbd)); - if (This->dsound->device->primary) { - *ppobj = This->dsound->device->primary; + if (!This->device->primary) + PrimaryBufferImpl_Create(This->device, &(This->device->primary), &(This->device->dsbd)); + if (This->device->primary) { + *ppobj = This->device->primary; IDirectSoundBuffer_AddRef((LPDIRECTSOUNDBUFFER)*ppobj); return S_OK; } @@ -802,7 +770,7 @@ static ULONG WINAPI IDirectSound3DListenerImpl_AddRef(LPDIRECTSOUND3DLISTENER if { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; ULONG ref = InterlockedIncrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref - 1); + TRACE("(%p) ref was %d\n", This, ref - 1); return ref; } @@ -810,10 +778,10 @@ static ULONG WINAPI IDirectSound3DListenerImpl_Release(LPDIRECTSOUND3DLISTENER i { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; ULONG ref = InterlockedDecrement(&(This->ref)); - TRACE("(%p) ref was %ld\n", This, ref + 1); + TRACE("(%p) ref was %d\n", This, ref + 1); if (!ref) { - This->dsound->device->listener = 0; + This->device->listener = 0; HeapFree(GetProcessHeap(), 0, This); TRACE("(%p) released\n", This); } @@ -834,12 +802,12 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetAllParameter( } if (lpDS3DL->dwSize < sizeof(*lpDS3DL)) { - WARN("invalid parameter: lpDS3DL->dwSize = %ld < %d\n",lpDS3DL->dwSize, sizeof(*lpDS3DL)); + WARN("invalid parameter: lpDS3DL->dwSize = %d\n",lpDS3DL->dwSize); return DSERR_INVALIDPARAM; } - + TRACE("returning: all parameters\n"); - *lpDS3DL = This->dsound->device->ds3dl; + *lpDS3DL = This->device->ds3dl; return DS_OK; } @@ -848,8 +816,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDistanceFactor( LPD3DVALUE lpfDistanceFactor) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("returning: Distance Factor = %f\n", This->dsound->device->ds3dl.flDistanceFactor); - *lpfDistanceFactor = This->dsound->device->ds3dl.flDistanceFactor; + TRACE("returning: Distance Factor = %f\n", This->device->ds3dl.flDistanceFactor); + *lpfDistanceFactor = This->device->ds3dl.flDistanceFactor; return DS_OK; } @@ -858,8 +826,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetDopplerFactor( LPD3DVALUE lpfDopplerFactor) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("returning: Doppler Factor = %f\n", This->dsound->device->ds3dl.flDopplerFactor); - *lpfDopplerFactor = This->dsound->device->ds3dl.flDopplerFactor; + TRACE("returning: Doppler Factor = %f\n", This->device->ds3dl.flDopplerFactor); + *lpfDopplerFactor = This->device->ds3dl.flDopplerFactor; return DS_OK; } @@ -869,11 +837,11 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetOrientation( LPD3DVECTOR lpvOrientTop) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->dsound->device->ds3dl.vOrientFront.x, \ - This->dsound->device->ds3dl.vOrientFront.y, This->dsound->device->ds3dl.vOrientFront.z, This->dsound->device->ds3dl.vOrientTop.x, This->dsound->device->ds3dl.vOrientTop.y, \ - This->dsound->device->ds3dl.vOrientTop.z); - *lpvOrientFront = This->dsound->device->ds3dl.vOrientFront; - *lpvOrientTop = This->dsound->device->ds3dl.vOrientTop; + TRACE("returning: OrientFront vector = (%f,%f,%f); OrientTop vector = (%f,%f,%f)\n", This->device->ds3dl.vOrientFront.x, + This->device->ds3dl.vOrientFront.y, This->device->ds3dl.vOrientFront.z, This->device->ds3dl.vOrientTop.x, This->device->ds3dl.vOrientTop.y, + This->device->ds3dl.vOrientTop.z); + *lpvOrientFront = This->device->ds3dl.vOrientFront; + *lpvOrientTop = This->device->ds3dl.vOrientTop; return DS_OK; } @@ -882,8 +850,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetPosition( LPD3DVECTOR lpvPosition) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("returning: Position vector = (%f,%f,%f)\n", This->dsound->device->ds3dl.vPosition.x, This->dsound->device->ds3dl.vPosition.y, This->dsound->device->ds3dl.vPosition.z); - *lpvPosition = This->dsound->device->ds3dl.vPosition; + TRACE("returning: Position vector = (%f,%f,%f)\n", This->device->ds3dl.vPosition.x, This->device->ds3dl.vPosition.y, This->device->ds3dl.vPosition.z); + *lpvPosition = This->device->ds3dl.vPosition; return DS_OK; } @@ -892,8 +860,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetRolloffFactor( LPD3DVALUE lpfRolloffFactor) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("returning: RolloffFactor = %f\n", This->dsound->device->ds3dl.flRolloffFactor); - *lpfRolloffFactor = This->dsound->device->ds3dl.flRolloffFactor; + TRACE("returning: RolloffFactor = %f\n", This->device->ds3dl.flRolloffFactor); + *lpfRolloffFactor = This->device->ds3dl.flRolloffFactor; return DS_OK; } @@ -902,8 +870,8 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_GetVelocity( LPD3DVECTOR lpvVelocity) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->dsound->device->ds3dl.vVelocity.x, This->dsound->device->ds3dl.vVelocity.y, This->dsound->device->ds3dl.vVelocity.z); - *lpvVelocity = This->dsound->device->ds3dl.vVelocity; + TRACE("returning: Velocity vector = (%f,%f,%f)\n", This->device->ds3dl.vVelocity.x, This->device->ds3dl.vVelocity.y, This->device->ds3dl.vVelocity.z); + *lpvVelocity = This->device->ds3dl.vVelocity; return DS_OK; } @@ -913,14 +881,14 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetAllParameters( DWORD dwApply) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("setting: all parameters; dwApply = %ld\n", dwApply); - This->dsound->device->ds3dl = *lpcDS3DL; + TRACE("setting: all parameters; dwApply = %d\n", dwApply); + This->device->ds3dl = *lpcDS3DL; if (dwApply == DS3D_IMMEDIATE) { - This->dsound->device->ds3dl_need_recalc = FALSE; + This->device->ds3dl_need_recalc = FALSE; DSOUND_ChangeListener(This); } - This->dsound->device->ds3dl_need_recalc = TRUE; + This->device->ds3dl_need_recalc = TRUE; return DS_OK; } @@ -930,14 +898,14 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDistanceFactor( DWORD dwApply) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("setting: Distance Factor = %f; dwApply = %ld\n", fDistanceFactor, dwApply); - This->dsound->device->ds3dl.flDistanceFactor = fDistanceFactor; + TRACE("setting: Distance Factor = %f; dwApply = %d\n", fDistanceFactor, dwApply); + This->device->ds3dl.flDistanceFactor = fDistanceFactor; if (dwApply == DS3D_IMMEDIATE) { - This->dsound->device->ds3dl_need_recalc = FALSE; + This->device->ds3dl_need_recalc = FALSE; DSOUND_ChangeListener(This); } - This->dsound->device->ds3dl_need_recalc = TRUE; + This->device->ds3dl_need_recalc = TRUE; return DS_OK; } @@ -947,14 +915,14 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetDopplerFactor( DWORD dwApply) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("setting: Doppler Factor = %f; dwApply = %ld\n", fDopplerFactor, dwApply); - This->dsound->device->ds3dl.flDopplerFactor = fDopplerFactor; + TRACE("setting: Doppler Factor = %f; dwApply = %d\n", fDopplerFactor, dwApply); + This->device->ds3dl.flDopplerFactor = fDopplerFactor; if (dwApply == DS3D_IMMEDIATE) { - This->dsound->device->ds3dl_need_recalc = FALSE; + This->device->ds3dl_need_recalc = FALSE; DSOUND_ChangeListener(This); } - This->dsound->device->ds3dl_need_recalc = TRUE; + This->device->ds3dl_need_recalc = TRUE; return DS_OK; } @@ -965,20 +933,20 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetOrientation( DWORD dwApply) { IDirectSound3DListenerImpl *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 = %d\n", xFront, yFront, zFront, xTop, yTop, zTop, dwApply); - This->dsound->device->ds3dl.vOrientFront.x = xFront; - This->dsound->device->ds3dl.vOrientFront.y = yFront; - This->dsound->device->ds3dl.vOrientFront.z = zFront; - This->dsound->device->ds3dl.vOrientTop.x = xTop; - This->dsound->device->ds3dl.vOrientTop.y = yTop; - This->dsound->device->ds3dl.vOrientTop.z = zTop; + This->device->ds3dl.vOrientFront.x = xFront; + This->device->ds3dl.vOrientFront.y = yFront; + This->device->ds3dl.vOrientFront.z = zFront; + This->device->ds3dl.vOrientTop.x = xTop; + This->device->ds3dl.vOrientTop.y = yTop; + This->device->ds3dl.vOrientTop.z = zTop; if (dwApply == DS3D_IMMEDIATE) { - This->dsound->device->ds3dl_need_recalc = FALSE; + This->device->ds3dl_need_recalc = FALSE; DSOUND_ChangeListener(This); } - This->dsound->device->ds3dl_need_recalc = TRUE; + This->device->ds3dl_need_recalc = TRUE; return DS_OK; } @@ -988,16 +956,16 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetPosition( DWORD dwApply) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("setting: Position vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); - This->dsound->device->ds3dl.vPosition.x = x; - This->dsound->device->ds3dl.vPosition.y = y; - This->dsound->device->ds3dl.vPosition.z = z; + TRACE("setting: Position vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply); + This->device->ds3dl.vPosition.x = x; + This->device->ds3dl.vPosition.y = y; + This->device->ds3dl.vPosition.z = z; if (dwApply == DS3D_IMMEDIATE) { - This->dsound->device->ds3dl_need_recalc = FALSE; + This->device->ds3dl_need_recalc = FALSE; DSOUND_ChangeListener(This); } - This->dsound->device->ds3dl_need_recalc = TRUE; + This->device->ds3dl_need_recalc = TRUE; return DS_OK; } @@ -1007,14 +975,14 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetRolloffFactor( DWORD dwApply) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("setting: Rolloff Factor = %f; dwApply = %ld\n", fRolloffFactor, dwApply); - This->dsound->device->ds3dl.flRolloffFactor = fRolloffFactor; + TRACE("setting: Rolloff Factor = %f; dwApply = %d\n", fRolloffFactor, dwApply); + This->device->ds3dl.flRolloffFactor = fRolloffFactor; if (dwApply == DS3D_IMMEDIATE) { - This->dsound->device->ds3dl_need_recalc = FALSE; + This->device->ds3dl_need_recalc = FALSE; DSOUND_ChangeListener(This); } - This->dsound->device->ds3dl_need_recalc = TRUE; + This->device->ds3dl_need_recalc = TRUE; return DS_OK; } @@ -1024,16 +992,16 @@ static HRESULT WINAPI IDirectSound3DListenerImpl_SetVelocity( DWORD dwApply) { IDirectSound3DListenerImpl *This = (IDirectSound3DListenerImpl *)iface; - TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %ld\n", x, y, z, dwApply); - This->dsound->device->ds3dl.vVelocity.x = x; - This->dsound->device->ds3dl.vVelocity.y = y; - This->dsound->device->ds3dl.vVelocity.z = z; + TRACE("setting: Velocity vector = (%f,%f,%f); dwApply = %d\n", x, y, z, dwApply); + This->device->ds3dl.vVelocity.x = x; + This->device->ds3dl.vVelocity.y = y; + This->device->ds3dl.vVelocity.z = z; if (dwApply == DS3D_IMMEDIATE) { - This->dsound->device->ds3dl_need_recalc = FALSE; + This->device->ds3dl_need_recalc = FALSE; DSOUND_ChangeListener(This); } - This->dsound->device->ds3dl_need_recalc = TRUE; + This->device->ds3dl_need_recalc = TRUE; return DS_OK; } @@ -1070,45 +1038,45 @@ static const IDirectSound3DListenerVtbl ds3dlvt = IDirectSound3DListenerImpl_CommitDeferredSettings, }; -HRESULT WINAPI IDirectSound3DListenerImpl_Create( - PrimaryBufferImpl *This, - IDirectSound3DListenerImpl **pdsl) +HRESULT IDirectSound3DListenerImpl_Create( + DirectSoundDevice * device, + IDirectSound3DListenerImpl ** ppdsl) { - IDirectSound3DListenerImpl *dsl; - TRACE("(%p,%p)\n",This,pdsl); + IDirectSound3DListenerImpl *pdsl; + TRACE("(%p,%p)\n",device,ppdsl); - dsl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*dsl)); + pdsl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(*pdsl)); - if (dsl == NULL) { + if (pdsl == NULL) { WARN("out of memory\n"); - *pdsl = 0; + *ppdsl = 0; return DSERR_OUTOFMEMORY; } - dsl->ref = 0; - dsl->lpVtbl = &ds3dlvt; - - dsl->dsound = This->dsound; - - dsl->dsound->device->ds3dl.dwSize = sizeof(DS3DLISTENER); - dsl->dsound->device->ds3dl.vPosition.x = 0.0; - dsl->dsound->device->ds3dl.vPosition.y = 0.0; - dsl->dsound->device->ds3dl.vPosition.z = 0.0; - dsl->dsound->device->ds3dl.vVelocity.x = 0.0; - dsl->dsound->device->ds3dl.vVelocity.y = 0.0; - dsl->dsound->device->ds3dl.vVelocity.z = 0.0; - dsl->dsound->device->ds3dl.vOrientFront.x = 0.0; - dsl->dsound->device->ds3dl.vOrientFront.y = 0.0; - dsl->dsound->device->ds3dl.vOrientFront.z = 1.0; - dsl->dsound->device->ds3dl.vOrientTop.x = 0.0; - dsl->dsound->device->ds3dl.vOrientTop.y = 1.0; - dsl->dsound->device->ds3dl.vOrientTop.z = 0.0; - dsl->dsound->device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; - dsl->dsound->device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; - dsl->dsound->device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR; - - dsl->dsound->device->ds3dl_need_recalc = TRUE; - - *pdsl = dsl; + pdsl->ref = 0; + pdsl->lpVtbl = &ds3dlvt; + + pdsl->device = device; + + pdsl->device->ds3dl.dwSize = sizeof(DS3DLISTENER); + pdsl->device->ds3dl.vPosition.x = 0.0; + pdsl->device->ds3dl.vPosition.y = 0.0; + pdsl->device->ds3dl.vPosition.z = 0.0; + pdsl->device->ds3dl.vVelocity.x = 0.0; + pdsl->device->ds3dl.vVelocity.y = 0.0; + pdsl->device->ds3dl.vVelocity.z = 0.0; + pdsl->device->ds3dl.vOrientFront.x = 0.0; + pdsl->device->ds3dl.vOrientFront.y = 0.0; + pdsl->device->ds3dl.vOrientFront.z = 1.0; + pdsl->device->ds3dl.vOrientTop.x = 0.0; + pdsl->device->ds3dl.vOrientTop.y = 1.0; + pdsl->device->ds3dl.vOrientTop.z = 0.0; + pdsl->device->ds3dl.flDistanceFactor = DS3D_DEFAULTDISTANCEFACTOR; + pdsl->device->ds3dl.flRolloffFactor = DS3D_DEFAULTROLLOFFFACTOR; + pdsl->device->ds3dl.flDopplerFactor = DS3D_DEFAULTDOPPLERFACTOR; + + pdsl->device->ds3dl_need_recalc = TRUE; + + *ppdsl = pdsl; return S_OK; } diff --git a/reactos/dll/directx/dsound/version.rc b/reactos/dll/directx/dsound/version.rc index a27e80c2f44..5ea532f2b04 100644 --- a/reactos/dll/directx/dsound/version.rc +++ b/reactos/dll/directx/dsound/version.rc @@ -13,15 +13,15 @@ * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #define WINE_OLESELFREGISTER #define WINE_FILEDESCRIPTION_STR "Wine DirectSound" #define WINE_FILENAME_STR "dsound.dll" -#define WINE_FILEVERSION 5,3,0,900 -#define WINE_FILEVERSION_STR "5.3.0.900" -#define WINE_PRODUCTVERSION 5,3,0,900 -#define WINE_PRODUCTVERSION_STR "5.3" +#define WINE_FILEVERSION 5,3,1,904 +#define WINE_FILEVERSION_STR "5.3.1.904" +#define WINE_PRODUCTVERSION 5,3,1,904 +#define WINE_PRODUCTVERSION_STR "5.3.1.904" #include "wine/wine_common_ver.rc" diff --git a/reactos/include/psdk/dsdriver.h b/reactos/include/psdk/dsdriver.h index 4e6fa13ab3d..ff89cb3777b 100644 --- a/reactos/include/psdk/dsdriver.h +++ b/reactos/include/psdk/dsdriver.h @@ -52,6 +52,7 @@ typedef struct IDsCaptureDriverBuffer *PIDSCDRIVERBUFFER; #define DSDDESC_USESYSTEMMEMORY 0x00000004 #define DSDDESC_DONTNEEDPRIMARYLOCK 0x00000008 #define DSDDESC_DONTNEEDSECONDARYLOCK 0x00000010 +#define DSDDESC_DONTNEEDWRITELEAD 0x00000020 #define DSDHEAP_NOHEAP 0 #define DSDHEAP_CREATEHEAP 1 diff --git a/reactos/include/psdk/dsound.h b/reactos/include/psdk/dsound.h index 191fa74cd87..e53e8df16f0 100644 --- a/reactos/include/psdk/dsound.h +++ b/reactos/include/psdk/dsound.h @@ -553,7 +553,7 @@ DECLARE_INTERFACE_(IDirectSoundBuffer,IUnknown) STDMETHOD(GetFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; STDMETHOD(GetStatus)(THIS_ LPDWORD lpdwStatus) PURE; STDMETHOD(Initialize)(THIS_ LPDIRECTSOUND lpDirectSound, LPCDSBUFFERDESC lpcDSBufferDesc) PURE; - STDMETHOD(Lock)(THIS_ DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID lplpvAudioPtr1, LPDWORD lpdwAudioBytes1, LPVOID lplpvAudioPtr2, LPDWORD lpdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Lock)(THIS_ DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID *lplpvAudioPtr1, LPDWORD lpdwAudioBytes1, LPVOID *lplpvAudioPtr2, LPDWORD lpdwAudioBytes2, DWORD dwFlags) PURE; STDMETHOD(Play)(THIS_ DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags) PURE; STDMETHOD(SetCurrentPosition)(THIS_ DWORD dwNewPosition) PURE; STDMETHOD(SetFormat)(THIS_ LPCWAVEFORMATEX lpcfxFormat) PURE; @@ -636,7 +636,7 @@ DECLARE_INTERFACE_(IDirectSoundBuffer8,IUnknown) STDMETHOD(GetFrequency)(THIS_ LPDWORD lpdwFrequency) PURE; STDMETHOD(GetStatus)(THIS_ LPDWORD lpdwStatus) PURE; STDMETHOD(Initialize)(THIS_ LPDIRECTSOUND lpDirectSound, LPCDSBUFFERDESC lpcDSBufferDesc) PURE; - STDMETHOD(Lock)(THIS_ DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID lplpvAudioPtr1, LPDWORD lpdwAudioBytes1, LPVOID lplpvAudioPtr2, LPDWORD lpdwAudioBytes2, DWORD dwFlags) PURE; + STDMETHOD(Lock)(THIS_ DWORD dwWriteCursor, DWORD dwWriteBytes, LPVOID *lplpvAudioPtr1, LPDWORD lpdwAudioBytes1, LPVOID *lplpvAudioPtr2, LPDWORD lpdwAudioBytes2, DWORD dwFlags) PURE; STDMETHOD(Play)(THIS_ DWORD dwReserved1, DWORD dwReserved2, DWORD dwFlags) PURE; STDMETHOD(SetCurrentPosition)(THIS_ DWORD dwNewPosition) PURE; STDMETHOD(SetFormat)(THIS_ LPCWAVEFORMATEX lpcfxFormat) PURE; diff --git a/reactos/include/reactos/wine/mmsystem.h b/reactos/include/reactos/wine/mmsystem.h index e068d16e12b..7475c9bfc84 100644 --- a/reactos/include/reactos/wine/mmsystem.h +++ b/reactos/include/reactos/wine/mmsystem.h @@ -27,6 +27,12 @@ #define DRV_FAILURE 0x0000 #define DRV_EXITAPPLICATION 0x000C +#define MAXWAVEDRIVERS 10 +#define MAXMIDIDRIVERS 10 +#define MAXAUXDRIVERS 10 +#define MAXMCIDRIVERS 32 +#define MAXMIXERDRIVERS 10 + #define MCI_OPEN_DRIVER 0x0801 #define MCI_CLOSE_DRIVER 0x0802 #define MCI_SOUND 0x0812 diff --git a/reactos/lib/sdk/dxguid/dxguid-mingw.c b/reactos/lib/sdk/dxguid/dxguid-mingw.c index 5aa61151abf..e7267c54774 100644 --- a/reactos/lib/sdk/dxguid/dxguid-mingw.c +++ b/reactos/lib/sdk/dxguid/dxguid-mingw.c @@ -15,18 +15,15 @@ #include #include -/* Hack letting wine dsound be happy, it should not be in this file */ - -DEFINE_GUID(IID_IDsDriver, 0x8C4233C0l, 0xB4CC, 0x11CE, 0x92, 0x94, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); -DEFINE_GUID(IID_IDsDriverNotify, 0x00363EF44, 0x3B57, 0x11D3, 0xAC, 0x79, 0x00, 0x10, 0x5A, 0x01, 0x7f, 0xe1); -DEFINE_GUID(IID_IDsDriverPropertySet, 0x0F6F2E8E0, 0xD842, 0x11D0, 0x8F, 0x75, 0x00, 0xC0, 0x4F, 0xC2, 0x8A, 0xCA); -DEFINE_GUID(IID_IDsDriverBuffer, 0x8C4233C1l, 0xB4CC, 0x11CE, 0x92, 0x94, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00); +/* FIXME - find a better place for these, needed for dsound */ +DEFINE_GUID(CLSID_DirectSoundPrivate, 0x11ab3ec0, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); +DEFINE_GUID(DSPROPSETID_DirectSoundDevice, 0x84624f82, 0x25ec, 0x11d1, 0xa4, 0xd8, 0x0, 0xc0, 0x4f, 0xc2, 0x8a, 0xca); /* Hack Getting ddraw to compile with kernel interface u can not mix dxguid and striims */ DEFINE_GUID(IID_IDirectDrawKernel, 0x8D56C120, 0x6A08, 0x11D0, 0x9B, 0x06, 0x00, 0xA0, 0xC9, 0x03, 0xA3, 0xB8); DEFINE_GUID(IID_IDirectDrawSurfaceKernel, 0x60755DA0, 0x6A40, 0x11D0, 0x9B, 0x06, 0x00, 0xA0, 0xC9, 0x03, 0xA3, 0xB8); -/* This GUIDs does not extists in ms dxsdk 2004 dec in dxguid, I have tested */ +/* These GUIDs do not exist in ms dxsdk 2004 dec in dxguid, tested by Magnus Olsen */ DEFINE_GUID(CLSID_DirectMusicMelodyFormulationTrack,0xb0684266,0xb57f,0x11d2,0x97,0xf9,0x0,0xc0,0x4f,0xa3,0x6e,0x58); DEFINE_GUID(CLSID_DirectMusicSong,0xaed5f0a5,0xd972,0x483d,0xa3,0x84,0x64,0x9d,0xfe,0xb9,0xc1,0x81); DEFINE_GUID(GUID_Clear_All_MelodyFragments,0x8509fee6,0xb617,0x11d2,0x97,0xfa,0x0,0xc0,0x4f,0xa3,0x6e,0x58); @@ -50,8 +47,9 @@ DEFINE_GUID(IID_ID3DXTechnique,0xa00f378d,0xaf79,0x4917,0x90,0x7e,0x4d,0x63,0x5e DEFINE_GUID(IID_IDirectDraw3, 0x618F8AD4,0x8b7A,0x11D0,0x8F,0xCC,0x00,0xC0,0x4F,0xd9,0x18,0x9D); DEFINE_GUID(IID_IDirectMusicSong,0xa862b2ec,0x3676,0x4982,0x85,0xa,0x78,0x42,0x77,0x5e,0x1d,0x86); DEFINE_GUID(IID_IKsFastClock,0xc9902485,0xc180,0x11d2,0x84,0x73,0xd4,0x23,0x94,0x45,0x9e,0x5e); +DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); -/* Match ms dxsdk 2004 dec this guids exists in dxguid, tested by Magnus Olsen */ +/* Match ms dxsdk 2004 dec these guids exist in dxguid, tested by Magnus Olsen */ DEFINE_GUID(CLSID_DirectMusicAudioPathConfig, 0xEE0B9CA0, 0xA81E, 0x11D3, 0x9B, 0xD1, 0x00, 0x80, 0xC7, 0x15, 0x0A, 0x74); DEFINE_GUID(CLSID_CDirect3DRM, 0x4516EC41, 0x8F20, 0x11D0, 0x9B, 0x6D, 0x00, 0x00, 0xC0, 0x78, 0x1B, 0xC3); DEFINE_GUID(CLSID_CDirect3DRMAnimation, 0x4FA35698, 0x623F, 0x11CF, 0xAC, 0x4A, 0x00, 0x00, 0xC0, 0x38, 0x25, 0xA1); -- 2.17.1