Added support for direct sound capture and a real direct sound capture driver. Capture now works with some skipping. Full duplex does not but I will be working on that next.
diff --git a/dlls/dsound/buffer.c b/dlls/dsound/buffer.c index 2891cc5..161efd5 100644 --- a/dlls/dsound/buffer.c +++ b/dlls/dsound/buffer.c
@@ -56,7 +56,11 @@ ICOM_THIS(IDirectSoundNotifyImpl,iface); TRACE("(%p,%s,%p)\n",This,debugstr_guid(riid),ppobj); - return IDirectSoundBuffer8_QueryInterface((LPDIRECTSOUNDBUFFER8)This->dsb, 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; } static ULONG WINAPI IDirectSoundNotifyImpl_AddRef(LPDIRECTSOUNDNOTIFY iface) { @@ -77,7 +81,10 @@ ref = InterlockedDecrement(&(This->ref)); if (!ref) { - IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb); + if (This->dsb) + IDirectSoundBuffer8_Release((LPDIRECTSOUNDBUFFER8)This->dsb); + else if (This->dscb) + IDirectSoundCaptureBuffer_Release((LPDIRECTSOUNDCAPTUREBUFFER8)This->dscb); HeapFree(GetProcessHeap(),0,This); return 0; } @@ -96,17 +103,30 @@ TRACE("notify at %ld to 0x%08lx\n", notify[i].dwOffset,(DWORD)notify[i].hEventNotify); } - 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; + if (This->dsb) { + 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); + } + else + return DSERR_INVALIDPARAM; return S_OK; } -static ICOM_VTABLE(IDirectSoundNotify) dsnvt = +ICOM_VTABLE(IDirectSoundNotify) dsnvt = { ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE IDirectSoundNotifyImpl_QueryInterface, @@ -798,6 +818,7 @@ dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0,sizeof(*dsn)); dsn->ref = 1; dsn->dsb = This; + dsn->dscb = 0; IDirectSoundBuffer8_AddRef(iface); ICOM_VTBL(dsn) = &dsnvt; *ppobj = (LPVOID)dsn; @@ -815,7 +836,7 @@ return E_FAIL; } - if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) { + if ( IsEqualGUID( &IID_IDirectSound3DListener, riid ) ) { ERR("app requested IDirectSound3DListener on secondary buffer\n"); *ppobj = NULL; return E_FAIL; @@ -850,7 +871,7 @@ IDirectSoundBufferImpl_GetFormat, IDirectSoundBufferImpl_GetVolume, IDirectSoundBufferImpl_GetPan, - IDirectSoundBufferImpl_GetFrequency, + IDirectSoundBufferImpl_GetFrequency, IDirectSoundBufferImpl_GetStatus, IDirectSoundBufferImpl_Initialize, IDirectSoundBufferImpl_Lock,
diff --git a/dlls/dsound/capture.c b/dlls/dsound/capture.c index e7fc835..9e4cb1a 100644 --- a/dlls/dsound/capture.c +++ b/dlls/dsound/capture.c
@@ -1,4 +1,4 @@ -/* DirectSoundCapture +/* DirectSoundCapture * * Copyright 1998 Marcus Meissner * Copyright 1998 Rob Riggs @@ -20,7 +20,7 @@ */ /* * TODO: - * Implement DirectSoundCapture API + * Implement DirectSoundCapture API */ #include "config.h" @@ -40,47 +40,23 @@ #include "winuser.h" #include "winerror.h" #include "mmsystem.h" +#include "mmddk.h" +#include "winternl.h" +#include "winnls.h" #include "wine/debug.h" #include "dsound.h" +#include "dsdriver.h" +#include "dsound_private.h" WINE_DEFAULT_DEBUG_CHANNEL(dsound); -/***************************************************************************** - * Predeclare the interface implementation structures - */ -typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl; -typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl; - - -/***************************************************************************** - * IDirectSoundCapture implementation structure - */ -struct IDirectSoundCaptureImpl -{ - /* IUnknown fields */ - ICOM_VFIELD(IDirectSoundCapture); - DWORD ref; - - /* IDirectSoundCaptureImpl fields */ - CRITICAL_SECTION lock; -}; - -/***************************************************************************** - * IDirectSoundCapture implementation structure - */ -struct IDirectSoundCaptureBufferImpl -{ - /* IUnknown fields */ - ICOM_VFIELD(IDirectSoundCaptureBuffer8); - DWORD ref; - - /* IDirectSoundCaptureBufferImpl fields */ - CRITICAL_SECTION lock; -}; - - -static HRESULT DSOUND_CreateDirectSoundCapture( LPVOID* ppobj ); -static HRESULT DSOUND_CreateDirectSoundCaptureBuffer( LPCDSCBUFFERDESC lpcDSCBufferDesc, LPVOID* ppobj ); +static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize( + LPDIRECTSOUNDCAPTURE iface, + LPCGUID lpcGUID ); +static HRESULT DSOUND_CreateDirectSoundCaptureBuffer( + IDirectSoundCaptureImpl *ipDSC, + LPCDSCBUFFERDESC lpcDSCBufferDesc, + LPVOID* ppobj ); static ICOM_VTABLE(IDirectSoundCapture) dscvt; static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt; @@ -96,28 +72,62 @@ * Failure: DSERR_NOAGGREGATION, DSERR_ALLOCATED, DSERR_INVALIDPARAM, * DSERR_OUTOFMEMORY */ -HRESULT WINAPI DirectSoundCaptureCreate8( - LPCGUID lpcGUID, - LPDIRECTSOUNDCAPTURE* lplpDSC, - LPUNKNOWN pUnkOuter ) +HRESULT WINAPI +DirectSoundCaptureCreate8( + LPCGUID lpcGUID, + LPDIRECTSOUNDCAPTURE* lplpDSC, + LPUNKNOWN pUnkOuter ) { - TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter); + TRACE("(%s,%p,%p)\n", debugstr_guid(lpcGUID), lplpDSC, pUnkOuter); - if( pUnkOuter ) { - return DSERR_NOAGGREGATION; - } + if ( pUnkOuter ) { + TRACE("pUnkOuter != 0\n"); + return DSERR_NOAGGREGATION; + } - /* Default device? */ - if ( !lpcGUID || - IsEqualGUID(lpcGUID, &DSDEVID_DefaultCapture) || - IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoiceCapture) ) { - return DSOUND_CreateDirectSoundCapture( (LPVOID*)lplpDSC ); - } + if ( !lplpDSC ) { + TRACE("invalid parameter: lplpDSC == NULL\n"); + return DSERR_INVALIDPARAM; + } - FIXME( "Unknown GUID %s\n", debugstr_guid(lpcGUID) ); - *lplpDSC = NULL; + /* Default device? */ + if ( !lpcGUID || IsEqualGUID(lpcGUID, &GUID_NULL) || + IsEqualGUID(lpcGUID, &DSDEVID_DefaultCapture) || + IsEqualGUID(lpcGUID, &DSDEVID_DefaultVoiceCapture) ) { + IDirectSoundCaptureImpl** ippDSC=(IDirectSoundCaptureImpl**)lplpDSC; - return DSERR_OUTOFMEMORY; + *ippDSC = (IDirectSoundCaptureImpl*)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, sizeof(IDirectSoundCaptureImpl)); + + if (*ippDSC == NULL) { + TRACE("couldn't allocate memory\n"); + return DSERR_OUTOFMEMORY; + } + else + { + ICOM_THIS(IDirectSoundCaptureImpl, *ippDSC); + + This->ref = 1; + This->state = STATE_STOPPED; + + if (lpcGUID) + This->guid = *lpcGUID; + else + This->guid = GUID_NULL; + + InitializeCriticalSection( &(This->lock) ); + + ICOM_VTBL(This) = &dscvt; + + /* FIXME: should this be defered because we can't return no driver ? */ + return IDirectSoundCaptureImpl_Initialize( (LPDIRECTSOUNDCAPTURE)This, lpcGUID ); + } + } + + FIXME( "Unknown GUID %s\n", debugstr_guid(lpcGUID) ); + *lplpDSC = NULL; + + return DSERR_OUTOFMEMORY; } /*************************************************************************** @@ -129,18 +139,32 @@ * Success: DS_OK * Failure: DSERR_INVALIDPARAM */ -HRESULT WINAPI DirectSoundCaptureEnumerateA( - LPDSENUMCALLBACKA lpDSEnumCallback, - LPVOID lpContext) +HRESULT WINAPI +DirectSoundCaptureEnumerateA( + LPDSENUMCALLBACKA lpDSEnumCallback, + LPVOID lpContext) { - TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext ); + WAVEINCAPSA wcaps; + unsigned devs, wid; - if ( lpDSEnumCallback ) - lpDSEnumCallback(NULL,"WINE Primary Sound Capture Driver", - "SoundCap",lpContext); + TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext ); + if (lpDSEnumCallback == NULL) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + devs = waveInGetNumDevs(); + for (wid = 0; wid < devs; ++wid) { + waveInGetDevCapsA(wid, &wcaps, sizeof(wcaps)); + if (lpDSEnumCallback) { + lpDSEnumCallback(NULL, "WINE Sound Capture Driver", + wcaps.szPname ,lpContext); + return DS_OK; + } + } + + return DS_OK; } /*************************************************************************** @@ -152,388 +176,918 @@ * Success: DS_OK * Failure: DSERR_INVALIDPARAM */ -HRESULT WINAPI DirectSoundCaptureEnumerateW( - LPDSENUMCALLBACKW lpDSEnumCallback, - LPVOID lpContext) +HRESULT WINAPI +DirectSoundCaptureEnumerateW( + LPDSENUMCALLBACKW lpDSEnumCallback, + LPVOID lpContext) { - FIXME("(%p,%p):stub\n", lpDSEnumCallback, lpContext ); - return DS_OK; + WAVEINCAPSW wcaps; + unsigned devs, wid; + WCHAR desc[MAXPNAMELEN]; + + TRACE("(%p,%p)\n", lpDSEnumCallback, lpContext ); + + if (lpDSEnumCallback == NULL) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } + + devs = waveInGetNumDevs(); + for (wid = 0; wid < devs; ++wid) { + waveInGetDevCapsW(wid, &wcaps, sizeof(wcaps)); + if (lpDSEnumCallback) { + MultiByteToWideChar( CP_ACP, 0, "WINE Sound Capture Driver", -1, + desc, sizeof(desc)/sizeof(WCHAR) ); + lpDSEnumCallback(NULL, desc, wcaps.szPname ,lpContext); + return DS_OK; + } + } + + return DS_OK; } -static HRESULT -DSOUND_CreateDirectSoundCapture( LPVOID* ppobj ) +static void CALLBACK +DSOUND_capture_callback( + HWAVEIN hwi, + UINT msg, + DWORD dwUser, + DWORD dw1, + DWORD dw2 ) { - *ppobj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( IDirectSoundCaptureImpl ) ); + IDirectSoundCaptureImpl* This = (IDirectSoundCaptureImpl*)dwUser; + TRACE("entering at %ld, msg=%08x\n", GetTickCount(), msg); - if ( *ppobj == NULL ) { - return DSERR_OUTOFMEMORY; - } + if (msg == MM_WIM_DATA) { + This->index = (This->index + 1) % This->capture_buffer->nrofnotifies; + waveInUnprepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR)); + SetEvent(This->capture_buffer->notifies[This->index].hEventNotify); + waveInPrepareHeader(hwi,&(This->pwave[This->index]),sizeof(WAVEHDR)); + waveInAddBuffer(hwi, &(This->pwave[This->index]), sizeof(WAVEHDR)); + } - { - ICOM_THIS(IDirectSoundCaptureImpl,*ppobj); - - This->ref = 1; - ICOM_VTBL(This) = &dscvt; - - InitializeCriticalSection( &This->lock ); - } - - return S_OK; + TRACE("completed\n"); } static HRESULT WINAPI IDirectSoundCaptureImpl_QueryInterface( - LPDIRECTSOUNDCAPTURE iface, - REFIID riid, - LPVOID* ppobj ) + LPDIRECTSOUNDCAPTURE iface, + REFIID riid, + LPVOID* ppobj ) { - ICOM_THIS(IDirectSoundCaptureImpl,iface); + ICOM_THIS(IDirectSoundCaptureImpl,iface); + TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj ); - FIXME( "(%p)->(%s,%p): stub\n", This, debugstr_guid(riid), ppobj ); + if (This->driver) + return IDsCaptureDriver_QueryInterface(This->driver, riid, ppobj); - return E_FAIL; + return E_FAIL; } static ULONG WINAPI IDirectSoundCaptureImpl_AddRef( LPDIRECTSOUNDCAPTURE iface ) { - ULONG uRef; - ICOM_THIS(IDirectSoundCaptureImpl,iface); + ULONG uRef; + ICOM_THIS(IDirectSoundCaptureImpl,iface); - EnterCriticalSection( &This->lock ); + EnterCriticalSection( &This->lock ); - TRACE( "(%p) was 0x%08lx\n", This, This->ref ); - uRef = ++(This->ref); + TRACE( "(%p) was 0x%08lx\n", This, This->ref ); + uRef = ++(This->ref); - LeaveCriticalSection( &This->lock ); + if (This->driver) + IDsCaptureDriver_AddRef(This->driver); - return uRef; + LeaveCriticalSection( &This->lock ); + + return uRef; } static ULONG WINAPI IDirectSoundCaptureImpl_Release( LPDIRECTSOUNDCAPTURE iface ) { - ULONG uRef; - ICOM_THIS(IDirectSoundCaptureImpl,iface); + ULONG uRef; + ICOM_THIS(IDirectSoundCaptureImpl,iface); - EnterCriticalSection( &This->lock ); + EnterCriticalSection( &This->lock ); - TRACE( "(%p) was 0x%08lx\n", This, This->ref ); - uRef = --(This->ref); + TRACE( "(%p) was 0x%08lx\n", This, This->ref ); + uRef = --(This->ref); - LeaveCriticalSection( &This->lock ); + LeaveCriticalSection( &This->lock ); - if ( uRef == 0 ) { - DeleteCriticalSection( &This->lock ); - HeapFree( GetProcessHeap(), 0, This ); - } + if ( uRef == 0 ) { + TRACE("deleting object\n"); + if (This->capture_buffer) + IDirectSoundCaptureBuffer8_Release( + (LPDIRECTSOUNDCAPTUREBUFFER8)This->capture_buffer); - return uRef; + if (This->driver) + IDsDriver_Close(This->driver); + + if (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) + waveInClose(This->hwi); + + if (This->driver) + IDsDriver_Release(This->driver); + + DeleteCriticalSection( &This->lock ); + HeapFree( GetProcessHeap(), 0, This ); + } + + return uRef; } static HRESULT WINAPI IDirectSoundCaptureImpl_CreateCaptureBuffer( - LPDIRECTSOUNDCAPTURE iface, - LPCDSCBUFFERDESC lpcDSCBufferDesc, - LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer, - LPUNKNOWN pUnk ) + LPDIRECTSOUNDCAPTURE iface, + LPCDSCBUFFERDESC lpcDSCBufferDesc, + LPDIRECTSOUNDCAPTUREBUFFER* lplpDSCaptureBuffer, + LPUNKNOWN pUnk ) { - HRESULT hr; - ICOM_THIS(IDirectSoundCaptureImpl,iface); + HRESULT hr; + ICOM_THIS(IDirectSoundCaptureImpl,iface); - TRACE( "(%p)->(%p,%p,%p)\n", This, lpcDSCBufferDesc, lplpDSCaptureBuffer, pUnk ); + TRACE( "(%p,%p,%p,%p)\n", This, lpcDSCBufferDesc, lplpDSCaptureBuffer, + pUnk ); - if ( pUnk ) { - return DSERR_INVALIDPARAM; - } + if ( (This == NULL) || (lpcDSCBufferDesc== NULL) || + (lplpDSCaptureBuffer == NULL) || pUnk ) { + TRACE("invalid parameters\n"); + return DSERR_INVALIDPARAM; + } - hr = DSOUND_CreateDirectSoundCaptureBuffer( lpcDSCBufferDesc, (LPVOID*)lplpDSCaptureBuffer ); + /* FIXME: We can only have one buffer so what do we do here? */ + if (This->capture_buffer) { + TRACE("already has buffer\n"); + return DSERR_INVALIDPARAM; /* DSERR_GENERIC ? */ + } - return hr; + hr = DSOUND_CreateDirectSoundCaptureBuffer( This, lpcDSCBufferDesc, + (LPVOID*)lplpDSCaptureBuffer ); + + return hr; } static HRESULT WINAPI IDirectSoundCaptureImpl_GetCaps( - LPDIRECTSOUNDCAPTURE iface, - LPDSCCAPS lpDSCCaps ) + LPDIRECTSOUNDCAPTURE iface, + LPDSCCAPS lpDSCCaps ) { - ICOM_THIS(IDirectSoundCaptureImpl,iface); + ICOM_THIS(IDirectSoundCaptureImpl,iface); + TRACE("(%p,%p)\n",This,lpDSCCaps); - FIXME( "(%p)->(%p): stub\n", This, lpDSCCaps ); + if ( (lpDSCCaps== NULL) || (lpDSCCaps->dwSize != sizeof(*lpDSCCaps)) ) { + TRACE("invalid parameters\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + if ( !(This->initialized) ) { + TRACE("not initialized\n"); + return DSERR_UNINITIALIZED; + } + + if ( (This->driver = 0) || (This->hwi == 0) ) { + TRACE("no driver\n"); + return DSERR_NODRIVER; + } + + lpDSCCaps->dwFlags = This->drvcaps.dwFlags; + lpDSCCaps->dwFormats = This->formats; + lpDSCCaps->dwChannels = This->channels; + + TRACE("(flags=0x%08lx,format=0x%08lx,channels=%ld)\n",lpDSCCaps->dwFlags, + lpDSCCaps->dwFormats, lpDSCCaps->dwChannels); + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureImpl_Initialize( - LPDIRECTSOUNDCAPTURE iface, - LPCGUID lpcGUID ) + LPDIRECTSOUNDCAPTURE iface, + LPCGUID lpcGUID ) { - ICOM_THIS(IDirectSoundCaptureImpl,iface); + HRESULT err = DS_OK; + unsigned wid, widn; + ICOM_THIS(IDirectSoundCaptureImpl,iface); + TRACE("(%p)\n", This); - FIXME( "(%p)->(%p): stub\n", This, lpcGUID ); + if (!This) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + if (This->initialized) { + TRACE("already initialized\n"); + return DSERR_ALREADYINITIALIZED; + } + + widn = waveInGetNumDevs(); + + if (!widn) { + TRACE("no audio devices found\n"); + return DSERR_NODRIVER; + } + + /* FIXME: should enumerate WINMM audio devices and find the one we want */ + wid = 0; + + err = mmErr(waveInMessage((HWAVEIN)wid,DRV_QUERYDSOUNDIFACE,(DWORD)&(This->driver),0)); + if ( (err != DS_OK) && (err != DSERR_UNSUPPORTED) ) { + TRACE("waveInMessage failed; err=%lx\n",err); + return err; + } + err = DS_OK; + + /* Get driver description */ + if (This->driver) { + TRACE("using DirectSound driver\n"); + IDsDriver_GetDriverDesc(This->driver, &(This->drvdesc)); + } else { + TRACE("using WINMM\n"); + /* if no DirectSound interface available, use WINMM API instead */ + This->drvdesc.dwFlags = DSDDESC_DOMMSYSTEMOPEN | + DSDDESC_DOMMSYSTEMSETFORMAT; + This->drvdesc.dnDevNode = wid; /* FIXME? */ + } + + /* 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 (This->drvdesc.dwFlags & DSDDESC_DOMMSYSTEMOPEN) + { + /* FIXME: is this right? */ + This->drvdesc.dnDevNode = 0; + +#if 0 /* this returns an uninitialized structure so don't use */ + /* query the wave format */ + err = mmErr(waveInOpen(NULL, This->drvdesc.dnDevNode, &(This->wfx), + 0, 0, WAVE_FORMAT_QUERY)); +#else + /* Set default wave format for waveInOpen */ + This->wfx.wFormatTag = WAVE_FORMAT_PCM; + /* 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. + */ + This->wfx.nSamplesPerSec = 22050; + This->wfx.wBitsPerSample = 8; + This->wfx.nChannels = 2; + This->wfx.nBlockAlign = This->wfx.wBitsPerSample * + This->wfx.nChannels / 8; + This->wfx.nAvgBytesPerSec = This->wfx.nSamplesPerSec * + This->wfx.nBlockAlign; + This->wfx.cbSize = 0; +#endif + err = mmErr(waveInOpen(&(This->hwi), + This->drvdesc.dnDevNode, &(This->wfx), + (DWORD)DSOUND_capture_callback, (DWORD)This, + CALLBACK_FUNCTION | WAVE_DIRECTSOUND)); + } + + /* open the DirectSound driver if available */ + if (This->driver && (err == DS_OK)) + err = IDsDriver_Open(This->driver); + + if (err == DS_OK) { + This->initialized = TRUE; + + /* the driver is now open, so it's now allowed to call GetCaps */ + if (This->driver) { + IDsDriver_GetCaps(This->driver,&(This->drvcaps)); + } else if (This->hwi) { + WAVEINCAPSA wic; + err = mmErr(waveInGetDevCapsA((UINT)This->hwi, &wic, sizeof(wic))); + + if (err == DS_OK) { + This->drvcaps.dwFlags = 0; + strncpy(This->drvdesc.szDrvName, wic.szPname, + sizeof(This->drvdesc.szDrvName)); + + This->formats = wic.dwFormats; + This->channels = wic.wChannels; + + if (ds_emuldriver) + This->drvcaps.dwFlags |= DSCCAPS_EMULDRIVER; + } + } else { + TRACE("no audio devices found\n"); + return DSERR_NODRIVER; + } + } + + return err; } - static ICOM_VTABLE(IDirectSoundCapture) dscvt = { - ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE - /* IUnknown methods */ - IDirectSoundCaptureImpl_QueryInterface, - IDirectSoundCaptureImpl_AddRef, - IDirectSoundCaptureImpl_Release, + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + /* IUnknown methods */ + IDirectSoundCaptureImpl_QueryInterface, + IDirectSoundCaptureImpl_AddRef, + IDirectSoundCaptureImpl_Release, - /* IDirectSoundCapture methods */ - IDirectSoundCaptureImpl_CreateCaptureBuffer, - IDirectSoundCaptureImpl_GetCaps, - IDirectSoundCaptureImpl_Initialize + /* IDirectSoundCapture methods */ + IDirectSoundCaptureImpl_CreateCaptureBuffer, + IDirectSoundCaptureImpl_GetCaps, + IDirectSoundCaptureImpl_Initialize }; static HRESULT -DSOUND_CreateDirectSoundCaptureBuffer( LPCDSCBUFFERDESC lpcDSCBufferDesc, LPVOID* ppobj ) +DSOUND_CreateDirectSoundCaptureBuffer( + IDirectSoundCaptureImpl *ipDSC, + LPCDSCBUFFERDESC lpcDSCBufferDesc, + LPVOID* ppobj ) { + LPWAVEFORMATEX wfex; + TRACE( "(%p,%p)\n", lpcDSCBufferDesc, ppobj ); - FIXME( "(%p,%p): ignoring lpcDSCBufferDesc\n", lpcDSCBufferDesc, ppobj ); + if ( (ipDSC == NULL) || (lpcDSCBufferDesc == NULL) || (ppobj == NULL) ) { + TRACE("invalid parameters\n"); + return DSERR_INVALIDPARAM; + } - *ppobj = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( IDirectSoundCaptureBufferImpl ) ); + if ( (lpcDSCBufferDesc->dwSize < sizeof(DSCBUFFERDESC)) || + (lpcDSCBufferDesc->dwBufferBytes == 0) || + (lpcDSCBufferDesc->lpwfxFormat == NULL) ) { + TRACE("invalid lpcDSCBufferDesc\n"); + return DSERR_INVALIDPARAM; + } - if ( *ppobj == NULL ) { - return DSERR_OUTOFMEMORY; - } + if ( !ipDSC->initialized ) { + TRACE("not initialized\n"); - { - ICOM_THIS(IDirectSoundCaptureBufferImpl,*ppobj); + return DSERR_UNINITIALIZED; + } - This->ref = 1; - ICOM_VTBL(This) = &dscbvt; + if ( (ipDSC->driver == 0) && (ipDSC->hwi == 0) ) { + TRACE("no driver\n"); + return DSERR_NODRIVER; + } - InitializeCriticalSection( &This->lock ); - } + wfex = lpcDSCBufferDesc->lpwfxFormat; - return S_OK; + 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->cbSize == 0) + memcpy(&(ipDSC->wfx), wfex, sizeof(*wfex) + wfex->cbSize); + else { + ERR("non PCM formats not supported\n"); + return DSERR_BADFORMAT; /* FIXME: DSERR_INVALIDPARAM ? */ + } + } else { + TRACE("lpcDSCBufferDesc->lpwfxFormat == 0\n"); + return DSERR_INVALIDPARAM; /* FIXME: DSERR_BADFORMAT ? */ + } + + *ppobj = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, + sizeof(IDirectSoundCaptureBufferImpl)); + + if ( *ppobj == NULL ) { + TRACE("out of memory\n"); + return DSERR_OUTOFMEMORY; + } else { + ICOM_THIS(IDirectSoundCaptureBufferImpl,*ppobj); + + This->ref = 1; + This->dsound = ipDSC; + This->dsound->capture_buffer = This; + + This->pdscbd = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY, + lpcDSCBufferDesc->dwSize); + if (This->pdscbd) + memcpy(This->pdscbd, lpcDSCBufferDesc, lpcDSCBufferDesc->dwSize); + else { + TRACE("no memory\n"); + This->dsound->capture_buffer = 0; + HeapFree( GetProcessHeap(), 0, This ); + *ppobj = NULL; + return DSERR_OUTOFMEMORY; + } + + ICOM_VTBL(This) = &dscbvt; + + InitializeCriticalSection( &This->lock ); + } + + return DS_OK; } - static HRESULT WINAPI IDirectSoundCaptureBufferImpl_QueryInterface( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - REFIID riid, - LPVOID* ppobj ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + REFIID riid, + LPVOID* ppobj ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj ); - FIXME( "(%p)->(%s,%p): stub\n", This, debugstr_guid(riid), ppobj ); + if (IsEqualGUID( &IID_IDirectSoundNotify, riid ) ) { + IDirectSoundNotifyImpl *dsn; - return E_FAIL; + dsn = (IDirectSoundNotifyImpl*)HeapAlloc(GetProcessHeap(),0, + sizeof(*dsn)); + dsn->ref = 1; + dsn->dsb = 0; + dsn->dscb = This; + IDirectSoundCaptureBuffer8_AddRef(iface); + ICOM_VTBL(dsn) = &dsnvt; + *ppobj = (LPVOID)dsn; + return DS_OK; + } + + FIXME("(%p,%s,%p)\n", This, debugstr_guid(riid), ppobj); + + return E_FAIL; } static ULONG WINAPI IDirectSoundCaptureBufferImpl_AddRef( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) { - ULONG uRef; - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ULONG uRef; + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p)\n", This ); - EnterCriticalSection( &This->lock ); + EnterCriticalSection( &This->lock ); - TRACE( "(%p) was 0x%08lx\n", This, This->ref ); - uRef = ++(This->ref); + TRACE( "(%p) was 0x%08lx\n", This, This->ref ); + uRef = ++(This->ref); - LeaveCriticalSection( &This->lock ); + LeaveCriticalSection( &This->lock ); - return uRef; + return uRef; } static ULONG WINAPI IDirectSoundCaptureBufferImpl_Release( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) { - ULONG uRef; - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ULONG uRef; + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p)\n", This ); - EnterCriticalSection( &This->lock ); + EnterCriticalSection( &This->lock ); - TRACE( "(%p) was 0x%08lx\n", This, This->ref ); - uRef = --(This->ref); + TRACE( "(%p) was 0x%08lx\n", This, This->ref ); + uRef = --(This->ref); - LeaveCriticalSection( &This->lock ); + LeaveCriticalSection( &This->lock ); - if ( uRef == 0 ) { - DeleteCriticalSection( &This->lock ); - HeapFree( GetProcessHeap(), 0, This ); - } + if ( uRef == 0 ) { + if (This->pdscbd) + HeapFree(GetProcessHeap(),0, This->pdscbd); - return uRef; + /* remove from IDirectSoundCaptureImpl */ + if (This->dsound) + This->dsound->capture_buffer = NULL; + else + ERR("does not reference dsound\n"); + + if (This->notifies) + HeapFree(GetProcessHeap(),0, This->notifies); + + DeleteCriticalSection( &This->lock ); + HeapFree( GetProcessHeap(), 0, This ); + } + + return uRef; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetCaps( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - LPDSCBCAPS lpDSCBCaps ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + LPDSCBCAPS lpDSCBCaps ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p,%p)\n", This, lpDSCBCaps ); - FIXME( "(%p)->(%p): stub\n", This, lpDSCBCaps ); + if ( (This == NULL) || (lpDSCBCaps == NULL) ) { + TRACE("invalid parameters\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + if ( (lpDSCBCaps->dwSize < sizeof(DSCBCAPS)) || (This->dsound == NULL) ) { + TRACE("invalid parameters\n"); + return DSERR_INVALIDPARAM; + } + + lpDSCBCaps->dwSize = sizeof(DSCBCAPS); + lpDSCBCaps->dwFlags = This->flags; + lpDSCBCaps->dwBufferBytes = This->pdscbd->dwBufferBytes; + lpDSCBCaps->dwReserved = 0; + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetCurrentPosition( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - LPDWORD lpdwCapturePosition, - LPDWORD lpdwReadPosition ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + LPDWORD lpdwCapturePosition, + LPDWORD lpdwReadPosition ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p,%p,%p)\n", This, lpdwCapturePosition, lpdwReadPosition ); - FIXME( "(%p)->(%p,%p): stub\n", This, lpdwCapturePosition, lpdwReadPosition ); + if ( (This == NULL) || (This->dsound == NULL) || + (lpdwReadPosition == NULL) ) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + if (This->dsound->driver) { + FIXME( "(%p,%p,%p): direct sound driver not supported\n", + This, lpdwCapturePosition, lpdwReadPosition ); + return DSERR_NODRIVER; + } else if (This->dsound->hwi) { + if (lpdwCapturePosition) { + MMTIME mtime; + mtime.wType = TIME_BYTES; + waveInGetPosition(This->dsound->hwi, &mtime, sizeof(mtime)); + mtime.u.cb = mtime.u.cb % This->dsound->buflen; + *lpdwCapturePosition = mtime.u.cb; + } + + if (lpdwReadPosition) { + if (This->dsound->state == STATE_STARTING) { + This->dsound->read_position = *lpdwCapturePosition; + This->dsound->state = STATE_CAPTURING; + } + *lpdwReadPosition = This->dsound->read_position; + } + } else { + TRACE("no driver\n"); + return DSERR_NODRIVER; + } + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetFormat( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - LPWAVEFORMATEX lpwfxFormat, - DWORD dwSizeAllocated, - LPDWORD lpdwSizeWritten ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + LPWAVEFORMATEX lpwfxFormat, + DWORD dwSizeAllocated, + LPDWORD lpdwSizeWritten ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p,%p,0x%08lx,%p)\n", This, lpwfxFormat, dwSizeAllocated, + lpdwSizeWritten ); - FIXME( "(%p)->(%p,0x%08lx,%p): stub\n", This, lpwfxFormat, dwSizeAllocated, lpdwSizeWritten ); + if ( (This == NULL) || (This->dsound == NULL) ) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + /* FIXME: use real size for extended formats someday */ + if (dwSizeAllocated > sizeof(This->dsound->wfx)) + dwSizeAllocated = sizeof(This->dsound->wfx); + if (lpwfxFormat) { /* NULL is valid (just want size) */ + memcpy(lpwfxFormat,&(This->dsound->wfx),dwSizeAllocated); + if (lpdwSizeWritten) + *lpdwSizeWritten = dwSizeAllocated; + } else { + if (lpdwSizeWritten) + *lpdwSizeWritten = sizeof(This->dsound->wfx); + else { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } + } + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetStatus( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - LPDWORD lpdwStatus ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + LPDWORD lpdwStatus ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p, %p)\n", This, lpdwStatus ); - FIXME( "(%p)->(%p): stub\n", This, lpdwStatus ); + if ( (This == NULL ) || (This->dsound == NULL) || (lpdwStatus == NULL) ) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + *lpdwStatus = 0; + if ((This->dsound->state == STATE_STARTING) || + (This->dsound->state == STATE_CAPTURING)) { + *lpdwStatus |= DSCBSTATUS_CAPTURING; + if (This->flags & DSCBSTART_LOOPING) + *lpdwStatus |= DSCBSTATUS_LOOPING; + } + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Initialize( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - LPDIRECTSOUNDCAPTURE lpDSC, - LPCDSCBUFFERDESC lpcDSCBDesc ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + LPDIRECTSOUNDCAPTURE lpDSC, + LPCDSCBUFFERDESC lpcDSCBDesc ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); - FIXME( "(%p)->(%p,%p): stub\n", This, lpDSC, lpcDSCBDesc ); + FIXME( "(%p,%p,%p): stub\n", This, lpDSC, lpcDSCBDesc ); - return DS_OK; + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Lock( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - DWORD dwReadCusor, - DWORD dwReadBytes, - LPVOID* lplpvAudioPtr1, - LPDWORD lpdwAudioBytes1, - LPVOID* lplpvAudioPtr2, - LPDWORD lpdwAudioBytes2, - DWORD dwFlags ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + DWORD dwReadCusor, + DWORD dwReadBytes, + LPVOID* lplpvAudioPtr1, + LPDWORD lpdwAudioBytes1, + LPVOID* lplpvAudioPtr2, + LPDWORD lpdwAudioBytes2, + DWORD dwFlags ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p,%08lu,%08lu,%p,%p,%p,%p,0x%08lx)\n", This, dwReadCusor, + dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2, + lpdwAudioBytes2, dwFlags ); - FIXME( "(%p)->(%08lu,%08lu,%p,%p,%p,%p,0x%08lx): stub\n", This, dwReadCusor, dwReadBytes, lplpvAudioPtr1, lpdwAudioBytes1, lplpvAudioPtr2, lpdwAudioBytes2, dwFlags ); + if ( (This == NULL) || (This->dsound == NULL) || (lplpvAudioPtr1 == NULL) || + (lpdwAudioBytes1 == NULL) || (lplpvAudioPtr2 == NULL) || + (lpdwAudioBytes2 == NULL) ) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + if (This->dsound->driver) { + FIXME("direct sound driver not supported\n"); + return DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */ + } else if (This->dsound->hwi) { + *lplpvAudioPtr1 = This->dsound->buffer + dwReadCusor; + if ( (dwReadCusor + dwReadBytes) > This->dsound->buflen) { + *lpdwAudioBytes1 = This->dsound->buflen - dwReadCusor; + *lplpvAudioPtr2 = This->dsound->buffer; + *lpdwAudioBytes2 = dwReadBytes - *lpdwAudioBytes1; + } else { + *lpdwAudioBytes1 = dwReadBytes; + *lplpvAudioPtr2 = 0; + *lpdwAudioBytes2 = 0; + } + } else { + TRACE("invalid call\n"); + return DSERR_INVALIDCALL; /* DSERR_NODRIVER ? */ + } + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Start( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - DWORD dwFlags ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + DWORD dwFlags ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + HRESULT err = DS_OK; + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p,0x%08lx)\n", This, dwFlags ); - FIXME( "(%p)->(0x%08lx): stub\n", This, dwFlags ); + if ( (This == NULL) || (dwFlags != DSCBSTART_LOOPING) || + (This->dsound == NULL) ) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + if ( (This->dsound->driver == 0) && (This->dsound->hwi == 0) ) { + TRACE("no driver\n"); + return DSERR_NODRIVER; + } + + EnterCriticalSection(&(This->lock)); + + This->flags = dwFlags; + if (This->dsound->state == STATE_STOPPED) + This->dsound->state = STATE_STARTING; + else if (This->dsound->state == STATE_STOPPING) + This->dsound->state = STATE_CAPTURING; + + if (This->dsound->driver) { + FIXME("direct sound driver not supported\n"); + LeaveCriticalSection(&(This->lock)); + return DSERR_NODRIVER; + } else { + LPBYTE newbuf; + DWORD buflen; + + IDirectSoundCaptureImpl* ipDSC = This->dsound; + + /* FIXME: do this only if formats different */ + err = mmErr(waveInClose(ipDSC->hwi)); + if (err != DS_OK) { + TRACE("waveInClose failed\n"); + return DSERR_GENERIC; + } + + err = mmErr(waveInOpen(&(ipDSC->hwi), + ipDSC->drvdesc.dnDevNode, &(ipDSC->wfx), + (DWORD)DSOUND_capture_callback, (DWORD)ipDSC, + CALLBACK_FUNCTION | WAVE_DIRECTSOUND)); + if (err != DS_OK) { + TRACE("waveInOpen failed\n"); + return DSERR_GENERIC; + } + + buflen = This->pdscbd->dwBufferBytes; + TRACE("desired buflen=%ld, old buffer=%p\n", buflen, ipDSC->buffer); + newbuf = (LPBYTE)HeapReAlloc(GetProcessHeap(),0,ipDSC->buffer,buflen); + + if (newbuf == NULL) { + ERR("failed to allocate capture buffer\n"); + err = DSERR_OUTOFMEMORY; + /* but the old buffer might still exist and must be re-prepared */ + } else { + ipDSC->buffer = newbuf; + ipDSC->buflen = buflen; + } + + if (ipDSC->buffer) { + unsigned c; + + if (This->nrofnotifies) + { + /* prepare headers */ + ipDSC->pwave = HeapReAlloc(GetProcessHeap(),0,ipDSC->pwave, + This->nrofnotifies*sizeof(WAVEHDR)); + + for (c = 0; c < This->nrofnotifies; c++) { + if (c == 0) { + ipDSC->pwave[0].lpData = ipDSC->buffer; + ipDSC->pwave[0].dwBufferLength = + This->notifies[0].dwOffset + 1; + } else { + ipDSC->pwave[c].lpData = ipDSC->buffer + + This->notifies[c-1].dwOffset + 1; + ipDSC->pwave[c].dwBufferLength = + This->notifies[c].dwOffset - + This->notifies[c-1].dwOffset; + } + ipDSC->pwave[c].dwUser = (DWORD)ipDSC; + ipDSC->pwave[c].dwFlags = 0; + ipDSC->pwave[c].dwLoops = 0; + err = mmErr(waveInPrepareHeader(ipDSC->hwi, + &(ipDSC->pwave[c]),sizeof(WAVEHDR))); + if (err != DS_OK) { + while (c--) + waveInUnprepareHeader(ipDSC->hwi, + &(ipDSC->pwave[c]),sizeof(WAVEHDR)); + break; + } +#if 0 + err = mmErr(waveInAddBuffer(ipDSC->hwi, &(ipDSC->pwave[c]), + sizeof(WAVEHDR))); + if (err != DS_OK) { + while (c--) + waveInUnprepareHeader(ipDSC->hwi,&(ipDSC->pwave[c]), + sizeof(WAVEHDR)); + break; + } +#endif + } + + memset(ipDSC->buffer, + (ipDSC->wfx.wBitsPerSample == 16) ? 0 : 128, ipDSC->buflen); + } + } + + ipDSC->index = 0; + ipDSC->read_position = 0; + err = mmErr(waveInAddBuffer(ipDSC->hwi, &(ipDSC->pwave[ipDSC->index]), + sizeof(WAVEHDR))); + if (err == DS_OK) + err = mmErr(waveInStart(ipDSC->hwi)); + } + + if (err != DS_OK) { + FIXME("cleanup\n"); + if (This->dsound->driver) { + FIXME("direct sound driver not supported\n"); + } + if (This->dsound->hwi) { + waveInClose(This->dsound->hwi); + } + LeaveCriticalSection(&(This->lock)); + return err; + } + + LeaveCriticalSection(&(This->lock)); + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Stop( LPDIRECTSOUNDCAPTUREBUFFER8 iface ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p)\n", This ); - FIXME( "(%p): stub\n", This ); + if ( (This == NULL) || (This->dsound == NULL) ) { + TRACE("invalid parameter\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + if (This->dsound->driver) { + FIXME("direct sound driver not supported\n"); + return DSERR_NODRIVER; + } else if (This->dsound->hwi) { + TRACE("stopping winmm\n"); + waveInStop(This->dsound->hwi); + } else { + TRACE("no driver\n"); + return DSERR_NODRIVER; + } + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_Unlock( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - LPVOID lpvAudioPtr1, - DWORD dwAudioBytes1, - LPVOID lpvAudioPtr2, - DWORD dwAudioBytes2 ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + LPVOID lpvAudioPtr1, + DWORD dwAudioBytes1, + LPVOID lpvAudioPtr2, + DWORD dwAudioBytes2 ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + TRACE( "(%p,%p,%08lu,%p,%08lu)\n", This, lpvAudioPtr1, dwAudioBytes1, + lpvAudioPtr2, dwAudioBytes2 ); - FIXME( "(%p)->(%p,%08lu,%p,%08lu): stub\n", This, lpvAudioPtr1, dwAudioBytes1, lpvAudioPtr2, dwAudioBytes2 ); + if ( (This == NULL) || (lpvAudioPtr1 == NULL) ) { + TRACE("invalid parameters\n"); + return DSERR_INVALIDPARAM; + } - return DS_OK; + if (This->dsound->driver) { + TRACE("direct sound driver not supported\n"); + return DSERR_INVALIDCALL; + } else if (This->dsound->hwi) { + This->dsound->read_position = (This->dsound->read_position + + (dwAudioBytes1 + dwAudioBytes2)) % This->dsound->buflen; + } else { + TRACE("invalid call\n"); + return DSERR_INVALIDCALL; + } + + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetObjectInPath( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - REFGUID rguidObject, - DWORD dwIndex, - REFGUID rguidInterface, - LPVOID* ppObject ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + REFGUID rguidObject, + DWORD dwIndex, + REFGUID rguidInterface, + LPVOID* ppObject ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); - FIXME( "(%p)->(%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject), dwIndex, debugstr_guid(rguidInterface), ppObject ); + FIXME( "(%p,%s,%lu,%s,%p): stub\n", This, debugstr_guid(rguidObject), + dwIndex, debugstr_guid(rguidInterface), ppObject ); - return DS_OK; + return DS_OK; } static HRESULT WINAPI IDirectSoundCaptureBufferImpl_GetFXStatus( - LPDIRECTSOUNDCAPTUREBUFFER8 iface, - DWORD dwFXCount, - LPDWORD pdwFXStatus ) + LPDIRECTSOUNDCAPTUREBUFFER8 iface, + DWORD dwFXCount, + LPDWORD pdwFXStatus ) { - ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); + ICOM_THIS(IDirectSoundCaptureBufferImpl,iface); - FIXME( "(%p)->(%lu,%p): stub\n", This, dwFXCount, pdwFXStatus ); + FIXME( "(%p,%lu,%p): stub\n", This, dwFXCount, pdwFXStatus ); - return DS_OK; + return DS_OK; } - static ICOM_VTABLE(IDirectSoundCaptureBuffer8) dscbvt = { - ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE - /* IUnknown methods */ - IDirectSoundCaptureBufferImpl_QueryInterface, - IDirectSoundCaptureBufferImpl_AddRef, - IDirectSoundCaptureBufferImpl_Release, + ICOM_MSVTABLE_COMPAT_DummyRTTIVALUE + /* IUnknown methods */ + IDirectSoundCaptureBufferImpl_QueryInterface, + IDirectSoundCaptureBufferImpl_AddRef, + IDirectSoundCaptureBufferImpl_Release, - /* IDirectSoundCaptureBuffer methods */ - IDirectSoundCaptureBufferImpl_GetCaps, - IDirectSoundCaptureBufferImpl_GetCurrentPosition, - IDirectSoundCaptureBufferImpl_GetFormat, - IDirectSoundCaptureBufferImpl_GetStatus, - IDirectSoundCaptureBufferImpl_Initialize, - IDirectSoundCaptureBufferImpl_Lock, - IDirectSoundCaptureBufferImpl_Start, - IDirectSoundCaptureBufferImpl_Stop, - IDirectSoundCaptureBufferImpl_Unlock, + /* IDirectSoundCaptureBuffer methods */ + IDirectSoundCaptureBufferImpl_GetCaps, + IDirectSoundCaptureBufferImpl_GetCurrentPosition, + IDirectSoundCaptureBufferImpl_GetFormat, + IDirectSoundCaptureBufferImpl_GetStatus, + IDirectSoundCaptureBufferImpl_Initialize, + IDirectSoundCaptureBufferImpl_Lock, + IDirectSoundCaptureBufferImpl_Start, + IDirectSoundCaptureBufferImpl_Stop, + IDirectSoundCaptureBufferImpl_Unlock, - /* IDirectSoundCaptureBuffer methods */ - IDirectSoundCaptureBufferImpl_GetObjectInPath, - IDirectSoundCaptureBufferImpl_GetFXStatus + /* IDirectSoundCaptureBuffer methods */ + IDirectSoundCaptureBufferImpl_GetObjectInPath, + IDirectSoundCaptureBufferImpl_GetFXStatus };
diff --git a/dlls/dsound/dsound_main.c b/dlls/dsound/dsound_main.c index ccb9ac8..50d174e 100644 --- a/dlls/dsound/dsound_main.c +++ b/dlls/dsound/dsound_main.c
@@ -83,7 +83,7 @@ IDirectSoundImpl* dsound = NULL; -static HRESULT mmErr(UINT err) +HRESULT mmErr(UINT err) { switch(err) { case MMSYSERR_NOERROR: @@ -91,13 +91,18 @@ case MMSYSERR_ALLOCATED: return DSERR_ALLOCATED; case MMSYSERR_INVALHANDLE: + case WAVERR_STILLPLAYING: return DSERR_GENERIC; /* FIXME */ case MMSYSERR_NODRIVER: return DSERR_NODRIVER; case MMSYSERR_NOMEM: return DSERR_OUTOFMEMORY; case MMSYSERR_INVALPARAM: + case WAVERR_BADFORMAT: + case WAVERR_UNPREPARED: return DSERR_INVALIDPARAM; + case MMSYSERR_NOTSUPPORTED: + return DSERR_UNSUPPORTED; default: FIXME("Unknown MMSYS error %d\n",err); return DSERR_GENERIC;
diff --git a/dlls/dsound/dsound_private.h b/dlls/dsound/dsound_private.h index ff91eec..f1ef984 100644 --- a/dlls/dsound/dsound_private.h +++ b/dlls/dsound/dsound_private.h
@@ -37,6 +37,8 @@ */ typedef struct IDirectSoundImpl IDirectSoundImpl; typedef struct IDirectSoundBufferImpl IDirectSoundBufferImpl; +typedef struct IDirectSoundCaptureImpl IDirectSoundCaptureImpl; +typedef struct IDirectSoundCaptureBufferImpl IDirectSoundCaptureBufferImpl; typedef struct IDirectSoundNotifyImpl IDirectSoundNotifyImpl; typedef struct IDirectSound3DListenerImpl IDirectSound3DListenerImpl; typedef struct IDirectSound3DBufferImpl IDirectSound3DBufferImpl; @@ -68,9 +70,9 @@ int nrofbuffers; IDirectSoundBufferImpl** buffers; IDirectSound3DListenerImpl* listener; - RTL_RWLOCK lock; - CRITICAL_SECTION mixlock; - DSVOLUMEPAN volpan; + RTL_RWLOCK lock; + CRITICAL_SECTION mixlock; + DSVOLUMEPAN volpan; }; /***************************************************************************** @@ -126,6 +128,64 @@ LPDSBUFFERDESC dsbd); /***************************************************************************** + * IDirectSoundCapture implementation structure + */ +struct IDirectSoundCaptureImpl +{ + /* IUnknown fields */ + ICOM_VFIELD(IDirectSoundCapture); + DWORD ref; + + /* IDirectSoundCaptureImpl fields */ + GUID guid; + BOOL initialized; + + /* DirectSound driver stuff */ + PIDSCDRIVER driver; + DSDRIVERDESC drvdesc; + DSDRIVERCAPS drvcaps; + PIDSDRIVERBUFFER hwbuf; + + /* wave driver info */ + HWAVEIN hwi; + + /* more stuff */ + LPBYTE buffer; + DWORD buflen; + DWORD read_position; + + /* FIXME: this should be a pointer because it can be bigger */ + WAVEFORMATEX wfx; + + DWORD formats; + DWORD channels; + IDirectSoundCaptureBufferImpl* capture_buffer; + DWORD state; + LPWAVEHDR pwave; + int index; + CRITICAL_SECTION lock; +}; + +/***************************************************************************** + * IDirectSoundCaptureBuffer implementation structure + */ +struct IDirectSoundCaptureBufferImpl +{ + /* IUnknown fields */ + ICOM_VFIELD(IDirectSoundCaptureBuffer8); + DWORD ref; + + /* IDirectSoundCaptureBufferImpl fields */ + IDirectSoundCaptureImpl* dsound; + CRITICAL_SECTION lock; + /* FIXME: don't need this */ + LPDSCBUFFERDESC pdscbd; + LPDSBPOSITIONNOTIFY notifies; + int nrofnotifies; + DWORD flags; +}; + +/***************************************************************************** * IDirectSoundNotify implementation structure */ struct IDirectSoundNotifyImpl @@ -134,7 +194,8 @@ ICOM_VFIELD(IDirectSoundNotify); DWORD ref; /* IDirectSoundNotifyImpl fields */ - IDirectSoundBufferImpl* dsb; + IDirectSoundBufferImpl* dsb; + IDirectSoundCaptureBufferImpl* dscb; }; /***************************************************************************** @@ -218,10 +279,11 @@ 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); -#define STATE_STOPPED 0 -#define STATE_STARTING 1 -#define STATE_PLAYING 2 -#define STATE_STOPPING 3 +#define STATE_STOPPED 0 +#define STATE_STARTING 1 +#define STATE_PLAYING 2 +#define STATE_CAPTURING 2 +#define STATE_STOPPING 3 #define DSOUND_FREQSHIFT (14) @@ -232,3 +294,6 @@ PIDSDRIVERBUFFER hwbuf; DWORD state; }; + +extern ICOM_VTABLE(IDirectSoundNotify) dsnvt; +extern HRESULT mmErr(UINT err);
diff --git a/dlls/dsound/primary.c b/dlls/dsound/primary.c index 570e7f2..887bf74 100644 --- a/dlls/dsound/primary.c +++ b/dlls/dsound/primary.c
@@ -47,27 +47,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(dsound); -static HRESULT mmErr(UINT err) -{ - switch(err) { - case MMSYSERR_NOERROR: - return DS_OK; - case MMSYSERR_ALLOCATED: - return DSERR_ALLOCATED; - case MMSYSERR_INVALHANDLE: - return DSERR_GENERIC; /* FIXME */ - case MMSYSERR_NODRIVER: - return DSERR_NODRIVER; - case MMSYSERR_NOMEM: - return DSERR_OUTOFMEMORY; - case MMSYSERR_INVALPARAM: - return DSERR_INVALIDPARAM; - default: - FIXME("Unknown MMSYS error %d\n",err); - return DSERR_GENERIC; - } -} - void DSOUND_RecalcPrimary(IDirectSoundImpl *This) { DWORD sw;
diff --git a/dlls/dsound/tests/dsound.c b/dlls/dsound/tests/dsound.c index 2be163a..dd54fce 100644 --- a/dlls/dsound/tests/dsound.c +++ b/dlls/dsound/tests/dsound.c
@@ -22,9 +22,9 @@ #include <stdlib.h> #include "wine/test.h" +#include "wine/debug.h" #include "dsound.h" - /* The time slice determines how often we will service the buffer and the * buffer will be four time slices long */ @@ -369,7 +369,7 @@ WAVEFORMATEX wfx; DSCAPS dscaps; - trace("Testing %s - %s\n",lpcstrDescription,lpcstrModule); + trace("Testing %s - %s : %s\n",lpcstrDescription,lpcstrModule,wine_dbgstr_guid(lpGuid)); rc=DirectSoundCreate(lpGuid,&dso,NULL); ok(rc==DS_OK,"DirectSoundCreate failed: 0x%lx\n",rc); if (rc!=DS_OK) @@ -388,6 +388,12 @@ dscaps.dwMaxSecondarySampleRate); } + /* We must call SetCooperativeLevel before calling CreateSoundBuffer */ + rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_PRIORITY); + ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc); + if (rc!=DS_OK) + goto EXIT; + /* Testing the primary buffer */ bufdesc.dwSize=sizeof(bufdesc); bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER; @@ -402,6 +408,12 @@ IDirectSoundBuffer_Release(dsbo); } + /* Set the CooperativeLevel back to normal */ + rc=IDirectSound_SetCooperativeLevel(dso,get_hwnd(),DSSCL_NORMAL); + ok(rc==DS_OK,"SetCooperativeLevel failed: 0x%lx\n",rc); + if (rc!=DS_OK) + goto EXIT; + /* Testing secondary buffers */ init_format(&wfx,11025,8,1); bufdesc.dwSize=sizeof(bufdesc); @@ -446,7 +458,344 @@ ok(rc==DS_OK,"DirectSoundEnumerate failed: %ld\n",rc); } +#define NOTIFICATIONS 5 + +typedef struct { + char* wave; + DWORD wave_len; + + LPDIRECTSOUNDCAPTUREBUFFER dscbo; + LPWAVEFORMATEX wfx; + DSBPOSITIONNOTIFY posnotify[NOTIFICATIONS]; + HANDLE event; + LPDIRECTSOUNDNOTIFY notify; + + DWORD buffer_size; + DWORD read; + DWORD offset; + + DWORD last_pos; +} capture_state_t; + +static int capture_buffer_service(capture_state_t* state) +{ + HRESULT rc; + LPVOID ptr1,ptr2; + DWORD len1,len2; + DWORD capture_pos,read_pos; + LONG size; + + rc=IDirectSoundCaptureBuffer_GetCurrentPosition(state->dscbo,&capture_pos,&read_pos); + ok(rc==DS_OK,"GetCurrentPosition failed: 0x%lx\n",rc); + if (rc!=DS_OK) + return 0; + + size = state->wfx->nAvgBytesPerSec/NOTIFICATIONS; + + rc=IDirectSoundCaptureBuffer_Lock(state->dscbo,state->offset,size,&ptr1,&len1,&ptr2,&len2,0); + ok(rc==DS_OK,"Lock failed: 0x%lx\n",rc); + if (rc!=DS_OK) + return 0; + + rc=IDirectSoundCaptureBuffer_Unlock(state->dscbo,ptr1,len1,ptr2,len2); + ok(rc==DS_OK,"Unlock failed: 0x%lx\n",rc); + if (rc!=DS_OK) + return 0; + + state->offset = (state->offset + size) % state->wfx->nAvgBytesPerSec; + + return 1; +} + +static void test_capture_buffer(LPDIRECTSOUNDCAPTURE dsco, LPDIRECTSOUNDCAPTUREBUFFER dscbo) +{ + HRESULT rc; + DSCBCAPS dscbcaps; + WAVEFORMATEX wfx; + DWORD size,status; + capture_state_t state; + int i; + + /* Private dsound.dll: Error: Invalid caps pointer */ + rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,0); + ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc); + + /* Private dsound.dll: Error: Invalid caps pointer */ + dscbcaps.dwSize=0; + rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps); + ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc); + + dscbcaps.dwSize=sizeof(dscbcaps); + rc=IDirectSoundCaptureBuffer_GetCaps(dscbo,&dscbcaps); + ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc); + if (rc==DS_OK) { + trace(" Caps: size = %ld flags=0x%08lx buffer size=%ld\n", + dscbcaps.dwSize,dscbcaps.dwFlags,dscbcaps.dwBufferBytes); + } + + /* Query the format size. Note that it may not match sizeof(wfx) */ + /* Private dsound.dll: Error: Either pwfxFormat or pdwSizeWritten must be non-NULL */ + rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,NULL); + ok(rc==DSERR_INVALIDPARAM, + "GetFormat should have returned an error: rc=0x%lx\n",rc); + + size=0; + rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,NULL,0,&size); + ok(rc==DS_OK && size!=0, + "GetFormat should have returned the needed size: rc=0x%lx size=%ld\n", + rc,size); + + rc=IDirectSoundCaptureBuffer_GetFormat(dscbo,&wfx,sizeof(wfx),NULL); + ok(rc==DS_OK,"GetFormat failed: 0x%lx\n",rc); + if (rc==DS_OK) { + trace(" tag=0x%04x %ldx%dx%d avg.B/s=%ld align=%d\n", + wfx.wFormatTag,wfx.nSamplesPerSec,wfx.wBitsPerSample, + wfx.nChannels,wfx.nAvgBytesPerSec,wfx.nBlockAlign); + } + + /* Private dsound.dll: Error: Invalid status pointer */ + rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,0); + ok(rc==DSERR_INVALIDPARAM,"GetStatus should have failed: 0x%lx\n",rc); + + rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status); + ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc); + if (rc==DS_OK) { + trace(" status=0x%04lx\n",status); + } + + ZeroMemory(&state, sizeof(state)); + state.dscbo=dscbo; + state.wfx=&wfx; + state.buffer_size=dscbcaps.dwBufferBytes; + state.event = CreateEvent( NULL, FALSE, FALSE, NULL ); + + /* FIXME: I couldn't get this to work in vc6. */ +{ + GUID IID_IDirectSoundNotifyX = { 0xb0210783, 0x89cd, 0x11d0,{ 0xaf, 0x8, 0x0, 0xa0, 0xc9, 0x25, 0xcd, 0x16 } }; + rc=IDirectSoundCapture_QueryInterface(dscbo,&IID_IDirectSoundNotifyX,(void **)&(state.notify)); +} + ok(rc==DS_OK,"QueryInterface failed: 0x%lx\n",rc); + if (rc!=DS_OK) + return; + + for (i = 0; i < NOTIFICATIONS; i++) { + state.posnotify[i].dwOffset = (i * (dscbcaps.dwBufferBytes / NOTIFICATIONS)) + (dscbcaps.dwBufferBytes / NOTIFICATIONS) - 1; + state.posnotify[i].hEventNotify = state.event; + } + + rc=IDirectSoundNotify_SetNotificationPositions(state.notify,NOTIFICATIONS,state.posnotify); + ok(rc==DS_OK,"SetNotificationPositions failed: 0x%lx\n",rc); + if (rc!=DS_OK) + return; + + rc=IDirectSoundCaptureBuffer_Start(dscbo,DSCBSTART_LOOPING); + ok(rc==DS_OK,"Start: 0x%lx\n",rc); + if (rc!=DS_OK) + return; + + rc=IDirectSoundCaptureBuffer_GetStatus(dscbo,&status); + ok(rc==DS_OK,"GetStatus failed: 0x%lx\n",rc); + ok(status==(DSCBSTATUS_CAPTURING|DSCBSTATUS_LOOPING), + "GetStatus: bad status: %lx",status); + if (rc!=DS_OK) + return; + + /* wait for the notifications */ + for (i = 0; i < (NOTIFICATIONS * 2); i++) { + rc=MsgWaitForMultipleObjects( 1, &(state.event), FALSE, 100, QS_ALLEVENTS ); + ok(rc==WAIT_OBJECT_0,"MsgWaitForMultipleObjects failed: 0x%lx\n",rc); + if (rc!=WAIT_OBJECT_0) + break; + if (!capture_buffer_service(&state)) + break; + } + + rc=IDirectSoundCaptureBuffer_Stop(dscbo); + ok(rc==DS_OK,"Stop: 0x%lx\n",rc); + if (rc!=DS_OK) + return; + rc=IDirectSoundCaptureBuffer_Release(dscbo); + ok(rc==DS_OK,"Release: 0x%lx\n",rc); + if (rc!=DS_OK) + return; +} + +static BOOL WINAPI dscenum_callback(LPGUID lpGuid, LPCSTR lpcstrDescription, + LPCSTR lpcstrModule, LPVOID lpContext) +{ + HRESULT rc; + LPDIRECTSOUNDCAPTURE dsco=NULL; + LPDIRECTSOUNDCAPTUREBUFFER dscbo=NULL; + DSCBUFFERDESC bufdesc; + WAVEFORMATEX wfx; + DSCCAPS dsccaps; + + /* Private dsound.dll: Error: Invalid interface buffer */ + trace("Testing %s - %s : %s\n",lpcstrDescription,lpcstrModule,wine_dbgstr_guid(lpGuid)); + rc=DirectSoundCaptureCreate(lpGuid,NULL,NULL); + ok(rc==DSERR_INVALIDPARAM,"DirectSoundCaptureCreate didn't fail: 0x%lx\n",rc); + if (rc==DS_OK) + IDirectSoundCapture_Release(dsco); + + rc=DirectSoundCaptureCreate(lpGuid,&dsco,NULL); + ok(rc==DS_OK,"DirectSoundCaptureCreate failed: 0x%lx\n",rc); + if (rc!=DS_OK) + goto EXIT; + + /* Private dsound.dll: Error: Invalid caps buffer */ + rc=IDirectSoundCapture_GetCaps(dsco,NULL); + ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc); + + /* Private dsound.dll: Error: Invalid caps buffer */ + dsccaps.dwSize=0; + rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps); + ok(rc==DSERR_INVALIDPARAM,"GetCaps should have failed: 0x%lx\n",rc); + + dsccaps.dwSize=sizeof(dsccaps); + rc=IDirectSoundCapture_GetCaps(dsco,&dsccaps); + ok(rc==DS_OK,"GetCaps failed: 0x%lx\n",rc); + if (rc==DS_OK) { + trace(" DirectSoundCapture Caps: size=%ld flags=0x%08lx formats=%ld channels=%ld\n", + dsccaps.dwSize,dsccaps.dwFlags,dsccaps.dwFormats,dsccaps.dwChannels); + } + + /* Private dsound.dll: Error: Invalid size */ + /* Private dsound.dll: Error: Invalid capture buffer description */ + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=0; + bufdesc.dwFlags=0; + bufdesc.dwBufferBytes=0; + bufdesc.dwReserved=0; + bufdesc.lpwfxFormat=NULL; + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); + ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc); + if (rc==DS_OK) { + IDirectSoundCaptureBuffer_Release(dscbo); + } + + /* Private dsound.dll: Error: Invalid buffer size */ + /* Private dsound.dll: Error: Invalid capture buffer description */ + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=0; + bufdesc.dwBufferBytes=0; + bufdesc.dwReserved=0; + bufdesc.lpwfxFormat=NULL; + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); + ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc); + if (rc==DS_OK) { + IDirectSoundCaptureBuffer_Release(dscbo); + } + + /* Private dsound.dll: Error: Invalid buffer size */ + /* Private dsound.dll: Error: Invalid capture buffer description */ + ZeroMemory(&bufdesc, sizeof(bufdesc)); + ZeroMemory(&wfx, sizeof(wfx)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=0; + bufdesc.dwBufferBytes=0; + bufdesc.dwReserved=0; + bufdesc.lpwfxFormat=&wfx; + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); + ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc); + if (rc==DS_OK) { + IDirectSoundCaptureBuffer_Release(dscbo); + } + + /* Private dsound.dll: Error: Invalid buffer size */ + /* Private dsound.dll: Error: Invalid capture buffer description */ + init_format(&wfx,11025,8,1); + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=0; + bufdesc.dwBufferBytes=0; + bufdesc.dwReserved=0; + bufdesc.lpwfxFormat=&wfx; + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); + ok(rc==DSERR_INVALIDPARAM,"CreateCaptureBuffer should have failed to create a capture buffer 0x%lx\n",rc); + if (rc==DS_OK) { + IDirectSoundCaptureBuffer_Release(dscbo); + } + + init_format(&wfx,11025,8,1); + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=0; + bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec; + bufdesc.dwReserved=0; + bufdesc.lpwfxFormat=&wfx; + trace(" Testing the capture buffer at %ldx%dx%d\n", + wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); + ok(rc==DS_OK,"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc); + if (rc==DS_OK) { + test_capture_buffer(dsco, dscbo); + IDirectSoundCaptureBuffer_Release(dscbo); + } + + init_format(&wfx,11025,8,1); + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED; + bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec; + bufdesc.dwReserved=0; + bufdesc.lpwfxFormat=&wfx; + trace(" Testing the capture buffer at %ldx%dx%d\n", + wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); + ok(rc==DS_OK,"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc); + if (rc==DS_OK) { + test_capture_buffer(dsco, dscbo); + IDirectSoundCaptureBuffer_Release(dscbo); + } + + init_format(&wfx,11025,16,2); + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=0; + bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec; + bufdesc.dwReserved=0; + bufdesc.lpwfxFormat=&wfx; + trace(" Testing the capture buffer at %ldx%dx%d\n", + wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); + ok(rc==DS_OK,"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc); + if (rc==DS_OK) { + test_capture_buffer(dsco, dscbo); + IDirectSoundCaptureBuffer_Release(dscbo); + } + + init_format(&wfx,11025,16,2); + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=DSCBCAPS_WAVEMAPPED; + bufdesc.dwBufferBytes=wfx.nAvgBytesPerSec; + bufdesc.dwReserved=0; + bufdesc.lpwfxFormat=&wfx; + trace(" Testing the capture buffer at %ldx%dx%d\n", + wfx.nSamplesPerSec,wfx.wBitsPerSample,wfx.nChannels); + rc=IDirectSoundCapture_CreateCaptureBuffer(dsco,&bufdesc,&dscbo,NULL); + ok(rc==DS_OK,"CreateCaptureBuffer failed to create a capture buffer 0x%lx\n",rc); + if (rc==DS_OK) { + test_capture_buffer(dsco, dscbo); + IDirectSoundCaptureBuffer_Release(dscbo); + } + +EXIT: + if (dsco!=NULL) + IDirectSoundCapture_Release(dsco); + return TRUE; +} + +static void dsound_in_tests() +{ + HRESULT rc; + rc=DirectSoundCaptureEnumerateA(&dscenum_callback,NULL); + ok(rc==DS_OK,"DirectSoundCaptureEnumerate failed: %ld\n",rc); +} + START_TEST(dsound) { dsound_out_tests(); + dsound_in_tests(); }