From abde7d0acf5c3c581ef009b2c300cdb0dd8f3868 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Fri, 2 May 2003 20:16:48 +0000 Subject: [PATCH] Reversed relationship between buffers and notifies. Fixed notify reuse bug. Minor documentation and error message cleanup. --- dlls/dsound/buffer.c | 103 +++++++++++++++++------------- dlls/dsound/capture.c | 120 +++++++++++++++++++++++++---------- dlls/dsound/dsound_main.c | 40 ++++++++++-- dlls/dsound/dsound_private.h | 13 ++-- dlls/dsound/mixer.c | 6 +- dlls/dsound/propset.c | 2 + 6 files changed, 194 insertions(+), 90 deletions(-) diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c index 7c49c059b01..11c0adaae1c 100644 --- a/dlls/dsound/buffer.c +++ b/dlls/dsound/buffer.c @@ -54,13 +54,21 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_QueryInterface( LPDIRECTSOUNDNOTIFY iface,REFIID riid,LPVOID *ppobj ) { ICOM_THIS(IDirectSoundNotifyImpl,iface); - TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - if (This->dsb) - return IDirectSoundBuffer8_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, riid, ppobj); - else if (This->dscb) - return IDirectSoundCaptureBuffer8_QueryInterface((LPDIRECTSOUNDCAPTUREBUFFER8)This->dscb, riid, ppobj); - return DSERR_GENERIC; + + if ( IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_IDirectSoundNotify) || + IsEqualGUID(riid, &IID_IDirectSoundNotify8) ) { + IDirectSoundNotify_AddRef(iface); + *ppobj = This; + return DS_OK; + } + + FIXME( "Unknown IID %s\n", debugstr_guid( riid ) ); + + *ppobj = 0; + + return E_NOINTERFACE; } static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) { @@ -80,11 +88,12 @@ static ULONG WINAPI IDirectSoundNotifyImpl_Release(LPDIRECTSOUNDNOTIFY iface) { TRACE("(%p) ref was %ld\n", This, This->ref); ref = InterlockedDecrement(&(This->ref)); - if (!ref) { - if (This->dsb) - IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb); - else if (This->dscb) - IDirectSoundCaptureBuffer8_Release((LPDIRECTSOUNDCAPTUREBUFFER8)This->dscb); + /* FIXME: A notification should be a part of a buffer rather than pointed + * to from a buffer. Hence the -1 ref count */ + if (ref == -1) { + if (This->notifies != NULL) + HeapFree(GetProcessHeap(), 0, This->notifies); + HeapFree(GetProcessHeap(),0,This); return 0; } @@ -95,33 +104,31 @@ static HRESULT WINAPI IDirectSoundNotifyImpl_SetNotificationPositions( LPDIRECTSOUNDNOTIFY iface,DWORD howmuch,LPCDSBPOSITIONNOTIFY notify ) { ICOM_THIS(IDirectSoundNotifyImpl,iface); - int i; + TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify); + + if (!notify) { + WARN("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } if (TRACE_ON(dsound)) { - TRACE("(%p,0x%08lx,%p)\n",This,howmuch,notify); + int i; for (i=0;idsb) { - This->dsb->notifies = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->dsb->notifies,(This->dsb->nrofnotifies+howmuch)*sizeof(DSBPOSITIONNOTIFY)); - memcpy( This->dsb->notifies+This->dsb->nrofnotifies, - notify, - howmuch*sizeof(DSBPOSITIONNOTIFY) - ); - This->dsb->nrofnotifies+=howmuch; - } else if (This->dscb) { - TRACE("notifies = %p, nrofnotifies = %d\n", This->dscb->notifies, This->dscb->nrofnotifies); - This->dscb->notifies = HeapReAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,This->dscb->notifies,(This->dscb->nrofnotifies+howmuch)*sizeof(DSBPOSITIONNOTIFY)); - memcpy( This->dscb->notifies+This->dscb->nrofnotifies, - notify, - howmuch*sizeof(DSBPOSITIONNOTIFY) - ); - This->dscb->nrofnotifies+=howmuch; - TRACE("notifies = %p, nrofnotifies = %d\n", This->dscb->notifies, This->dscb->nrofnotifies); + + if (This->hwnotify) { + return IDsDriverNotify_SetNotificationPositions(This->hwnotify, howmuch, notify); + } + else { + /* Make an internal copy of the caller-supplied array. + * Replace the existing copy if one is already present. */ + This->notifies = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + This->notifies, howmuch * sizeof(DSBPOSITIONNOTIFY)); + memcpy(This->notifies, notify, howmuch * sizeof(DSBPOSITIONNOTIFY)); + This->nrofnotifies = howmuch; } - else - return DSERR_INVALIDPARAM; return S_OK; } @@ -816,17 +823,23 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) { - IDirectSoundNotifyImpl *dsn; - - dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn)); - dsn->ref = 1; - dsn->dsb = This; - dsn->dscb = 0; - IDirectSoundBuffer8_AddRef(iface); - dsn->lpVtbl = &dsnvt; - *ppobj = (LPVOID)dsn; - return S_OK; + if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) || + IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) { + if (!This->notify) { + This->notify = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY,sizeof(*This->notify)); + if (This->notify) { + This->notify->ref = 0; /* release when ref == -1 */ + This->notify->lpVtbl = &dsnvt; + } + } + if (This->notify) { + IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify); + *ppobj = (LPVOID)This->notify; + return S_OK; + } + *ppobj = NULL; + return E_FAIL; } if ( IsEqualGUID( &IID_IDirectSound3DBuffer, riid ) ) { @@ -837,6 +850,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( IDirectSound3DBuffer_AddRef((LPDIRECTSOUND3DBUFFER)*ppobj); return S_OK; } + *ppobj = NULL; return E_FAIL; } @@ -854,6 +868,7 @@ static HRESULT WINAPI IDirectSoundBufferImpl_QueryInterface( IKsPropertySet_AddRef((LPKSPROPERTYSET)*ppobj); return S_OK; } + *ppobj = NULL; return E_FAIL; } diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c index 8901549ec75..7b4bbe6bdb4 100644 --- a/dlls/dsound/capture.c +++ b/dlls/dsound/capture.c @@ -82,12 +82,24 @@ IDirectSoundCaptureImpl* dsound_capture = NULL; /*************************************************************************** * DirectSoundCaptureCreate [DSOUND.6] * - * Create and initialize a DirectSoundCapture interface + * Create and initialize a DirectSoundCapture interface. + * + * PARAMS + * lpcGUID [I] Address of the GUID that identifies the sound capture device. + * lplpDSC [O] Address of a variable to receive the interface pointer. + * pUnkOuter [I] Must be NULL. * * RETURNS * Success: DS_OK * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM, * DSERR_OUTOFMEMORY + * + * NOTES + * lpcGUID must be one of the values returned from DirectSoundCaptureEnumerate + * or NULL for the default device or DSDEVID_DefaultCapture or + * DSDEVID_DefaultVoiceCapture. + * + * DSERR_ALLOCATED is returned for sound devices that do not support full duplex. */ HRESULT WINAPI DirectSoundCaptureCreate8( @@ -99,7 +111,7 @@ DirectSoundCaptureCreate8( TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter); if ( pUnkOuter ) { - WARN("pUnkOuter != 0\n"); + WARN("invalid parameter: pUnkOuter != NULL\n"); return DSERR_NOAGGREGATION; } @@ -141,7 +153,11 @@ DirectSoundCaptureCreate8( /*************************************************************************** * DirectSoundCaptureEnumerateA [DSOUND.7] * - * Enumerate all DirectSound drivers installed in the system + * Enumerate all DirectSound drivers installed in the system. + * + * PARAMS + * lpDSEnumCallback [I] Address of callback function. + * lpContext [I] Address of user defined context passed to callback function. * * RETURNS * Success: DS_OK @@ -160,7 +176,7 @@ DirectSoundCaptureEnumerateA( TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext ); if (lpDSEnumCallback == NULL) { - WARN("invalid parameter\n"); + WARN("invalid parameter: lpDSEnumCallback == NULL\n"); return DSERR_INVALIDPARAM; } @@ -204,7 +220,11 @@ DirectSoundCaptureEnumerateA( /*************************************************************************** * DirectSoundCaptureEnumerateW [DSOUND.8] * - * Enumerate all DirectSound drivers installed in the system + * Enumerate all DirectSound drivers installed in the system. + * + * PARAMS + * lpDSEnumCallback [I] Address of callback function. + * lpContext [I] Address of user defined context passed to callback function. * * RETURNS * Success: DS_OK @@ -225,7 +245,7 @@ DirectSoundCaptureEnumerateW( TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext ); if (lpDSEnumCallback == NULL) { - WARN("invalid parameter\n"); + WARN("invalid parameter: lpDSEnumCallback == NULL\n"); return DSERR_INVALIDPARAM; } @@ -283,7 +303,9 @@ DSOUND_capture_callback( DWORD dw2 ) { IDirectSoundCaptureImpl* This = (IDirectSoundCaptureImpl*)dwUser; - TRACE("entering at %ld, msg=%08x\n", GetTickCount(), msg); + TRACE("(%p,%08x(%s),%08lx,%08lx,%08lx) entering at %ld\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) { EnterCriticalSection( &(This->lock) ); @@ -300,8 +322,8 @@ DSOUND_capture_callback( } This->index = (This->index + 1) % This->nrofpwaves; waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR)); - if (This->capture_buffer->nrofnotifies) - SetEvent(This->capture_buffer->notifies[This->index].hEventNotify); + if (This->capture_buffer->notify && This->capture_buffer->notify->nrofnotifies) + SetEvent(This->capture_buffer->notify->notifies[This->index].hEventNotify); if ( (This->index == 0) && !(This->capture_buffer->flags & DSCBSTART_LOOPING) ) { TRACE("end of buffer\n"); This->state = STATE_STOPPED; @@ -698,22 +720,40 @@ IDirectSoundCaptureBufferImpl_QueryInterface( ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj ); - if (IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) { - IDirectSoundNotifyImpl *dsn; + if ( IsEqualGUID( &IID_IDirectSoundNotify, riid ) || + IsEqualGUID( &IID_IDirectSoundNotify8, riid ) ) { + if (!This->notify) { + This->notify = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(*This->notify)); + if (This->notify) { + This->notify->ref = 0; /* release when ref = -1 */ + This->notify->lpVtbl = &dsnvt; + } + } + if (This->notify) { + if (This->dsound->hwbuf) { + HRESULT err; + + err = IDsCaptureDriverBuffer_QueryInterface(This->dsound->hwbuf, + &IID_IDsDriverNotify, (LPVOID*)&(This->notify->hwnotify)); + if (err != DS_OK) { + WARN("IDsCaptureDriverBuffer_QueryInterface failed\n"); + *ppobj = 0; + return err; + } + } - dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0, - sizeof(*dsn)); - dsn->ref = 1; - dsn->dsb = 0; - dsn->dscb = This; - /* FIXME: get this right someday */ - IDirectSoundCaptureBuffer8_AddRef(iface); - dsn->lpVtbl = &dsnvt; - *ppobj = (LPVOID)dsn; - return DS_OK; + IDirectSoundNotify_AddRef((LPDIRECTSOUNDNOTIFY)This->notify); + *ppobj = (LPVOID)This->notify; + return DS_OK; + } + + *ppobj = 0; + return E_FAIL; } - if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) { + if ( IsEqualGUID( &IID_IDirectSoundCaptureBuffer, riid ) || + IsEqualGUID( &IID_IDirectSoundCaptureBuffer8, riid ) ) { IDirectSoundCaptureBuffer8_AddRef(iface); *ppobj = This; return NO_ERROR; @@ -721,7 +761,9 @@ IDirectSoundCaptureBufferImpl_QueryInterface( FIXME("(%p,%s,%p) unsupported GUID\n", This, debugstr_guid(riid), ppobj); - return E_FAIL; + *ppobj = 0; + + return E_NOINTERFACE; } static ULONG WINAPI @@ -783,8 +825,8 @@ IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) else ERR("does not reference dsound\n"); - if (This->notifies) - HeapFree(GetProcessHeap(),0, This->notifies); + if (This->notify) + IDirectSoundNotify_Release((LPDIRECTSOUNDNOTIFY)This->notify); HeapFree( GetProcessHeap(), 0, This ); } @@ -1042,10 +1084,10 @@ IDirectSoundCaptureBufferImpl_Start( IDirectSoundCaptureImpl* ipDSC = This->dsound; if (ipDSC->buffer) { - if (This->nrofnotifies) { + if (This->notify && This->notify->nrofnotifies) { unsigned c; - ipDSC->nrofpwaves = This->nrofnotifies; + ipDSC->nrofpwaves = This->notify->nrofnotifies; /* prepare headers */ ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave, @@ -1055,13 +1097,13 @@ IDirectSoundCaptureBufferImpl_Start( if (c == 0) { ipDSC->pwave[0].lpData = ipDSC->buffer; ipDSC->pwave[0].dwBufferLength = - This->notifies[0].dwOffset + 1; + This->notify->notifies[0].dwOffset + 1; } else { ipDSC->pwave[c].lpData = ipDSC->buffer + - This->notifies[c-1].dwOffset + 1; + This->notify->notifies[c-1].dwOffset + 1; ipDSC->pwave[c].dwBufferLength = - This->notifies[c].dwOffset - - This->notifies[c-1].dwOffset; + This->notify->notifies[c].dwOffset - + This->notify->notifies[c-1].dwOffset; } ipDSC->pwave[c].dwUser = (DWORD)ipDSC; ipDSC->pwave[c].dwFlags = 0; @@ -1256,9 +1298,21 @@ static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt = }; /*************************************************************************** - * DirectSoundFullDuplexCreate8 [DSOUND.8] + * DirectSoundFullDuplexCreate8 [DSOUND.10] * - * Create and initialize a DirectSoundFullDuplex interface + * 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 diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c index 02caf316330..f839750dfcc 100644 --- a/dlls/dsound/dsound_main.c +++ b/dlls/dsound/dsound_main.c @@ -231,13 +231,24 @@ void setup_dsound_options(void) /*************************************************************************** - * GetDeviceId [DSOUND.2] + * GetDeviceID [DSOUND.9] * * Retrieves unique identifier of default device specified * + * PARAMS + * pGuidSrc [I] Address of device GUID. + * pGuidDest [O] Address to receive unique device GUID. + * * RETURNS * Success: DS_OK * Failure: DSERR_INVALIDPARAM + * + * NOTES + * pGuidSrc is a valid device GUID or DSDEVID_DefaultPlayback, + * DSDEVID_DefaultCapture, DSDEVID_DefaultVoicePlayback, or + * DSDEVID_DefaultVoiceCapture. + * Returns pGuidSrc if pGuidSrc is a valid device or the device + * GUID for the specified constants. */ HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest) { @@ -277,6 +288,10 @@ HRESULT WINAPI GetDeviceID(LPCGUID pGuidSrc, LPGUID pGuidDest) * * Enumerate all DirectSound drivers installed in the system * + * PARAMS + * lpDSEnumCallback [I] Address of callback function. + * lpContext [I] Address of user defined context passed to callback function. + * * RETURNS * Success: DS_OK * Failure: DSERR_INVALIDPARAM @@ -294,7 +309,7 @@ HRESULT WINAPI DirectSoundEnumerateA( lpDSEnumCallback, lpContext); if (lpDSEnumCallback == NULL) { - WARN("invalid parameter\n"); + WARN("invalid parameter: lpDSEnumCallback == NULL\n"); return DSERR_INVALIDPARAM; } @@ -339,6 +354,10 @@ HRESULT WINAPI DirectSoundEnumerateA( * * Enumerate all DirectSound drivers installed in the system * + * PARAMS + * lpDSEnumCallback [I] Address of callback function. + * lpContext [I] Address of user defined context passed to callback function. + * * RETURNS * Success: DS_OK * Failure: DSERR_INVALIDPARAM @@ -358,7 +377,7 @@ HRESULT WINAPI DirectSoundEnumerateW( lpDSEnumCallback, lpContext); if (lpDSEnumCallback == NULL) { - WARN("invalid parameter\n"); + WARN("invalid parameter: lpDSEnumCallback == NULL\n"); return DSERR_INVALIDPARAM; } @@ -708,6 +727,18 @@ static ICOM_VTABLE(IDirectSound8) dsvt = /******************************************************************************* * 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 DirectSoundCreate8(LPCGUID lpcGUID,LPDIRECTSOUND8 *ppDS,IUnknown *pUnkOuter ) { @@ -976,7 +1007,8 @@ DWORD WINAPI DSOUND_DllGetClassObject(REFCLSID rclsid,REFIID riid,LPVOID *ppv) /******************************************************************************* - * DllCanUnloadNow [DSOUND.4] Determines whether the DLL is in use. + * DllCanUnloadNow [DSOUND.4] + * Determines whether the DLL is in use. * * RETURNS * Success: S_OK diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index 356a770e1dd..5f6c928823b 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h @@ -117,8 +117,7 @@ struct IDirectSoundBufferImpl DWORD primary_mixpos, buf_mixpos; BOOL need_remix; /* IDirectSoundNotifyImpl fields */ - LPDSBPOSITIONNOTIFY notifies; - int nrofnotifies; + IDirectSoundNotifyImpl *notify; }; HRESULT WINAPI SecondaryBuffer_Create( @@ -189,9 +188,9 @@ struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureImpl* dsound; /* FIXME: don't need this */ LPDSCBUFFERDESC pdscbd; - LPDSBPOSITIONNOTIFY notifies; - int nrofnotifies; DWORD flags; + /* IDirectSoundNotifyImpl fields */ + IDirectSoundNotifyImpl *notify; }; /***************************************************************************** @@ -216,8 +215,10 @@ struct IDirectSoundNotifyImpl ICOM_VFIELD(IDirectSoundNotify); DWORD ref; /* IDirectSoundNotifyImpl fields */ - IDirectSoundBufferImpl* dsb; - IDirectSoundCaptureBufferImpl* dscb; + LPDSBPOSITIONNOTIFY notifies; + int nrofnotifies; + + PIDSDRIVERNOTIFY hwnotify; }; /***************************************************************************** diff --git a/dlls/dsound/mixer.c b/dlls/dsound/mixer.c index 471b3233de5..27bcc57294f 100644 --- a/dlls/dsound/mixer.c +++ b/dlls/dsound/mixer.c @@ -79,13 +79,13 @@ void DSOUND_CheckEvent(IDirectSoundBufferImpl *dsb, int len) DWORD offset; LPDSBPOSITIONNOTIFY event; - if (dsb->nrofnotifies == 0) + if (!dsb->notify || dsb->notify->nrofnotifies == 0) return; TRACE("(%p) buflen = %ld, playpos = %ld, len = %d\n", dsb, dsb->buflen, dsb->playpos, len); - for (i = 0; i < dsb->nrofnotifies ; i++) { - event = dsb->notifies + i; + for (i = 0; i < dsb->notify->nrofnotifies ; i++) { + event = dsb->notify->notifies + i; offset = event->dwOffset; TRACE("checking %d, position %ld, event = %p\n", i, offset, event->hEventNotify); diff --git a/dlls/dsound/propset.c b/dlls/dsound/propset.c index c050c1d4171..a1c316c4914 100644 --- a/dlls/dsound/propset.c +++ b/dlls/dsound/propset.c @@ -388,10 +388,12 @@ static HRESULT WINAPI DSPROPERTY_DescriptionW( } ppd->Type = DIRECTSOUNDDEVICE_TYPE_EMULATED; + if (pcbReturned) { *pcbReturned = cbPropData; TRACE("*pcbReturned=%ld\n", *pcbReturned); } + return S_OK; }