From 0abe48a1570bb6250f40bbf1b7b18ae2ce1a4c88 Mon Sep 17 00:00:00 2001 From: Johannes Anderwald Date: Sat, 7 Nov 2009 13:49:01 +0000 Subject: [PATCH 1/1] [DSOUND] - Add more checks IDirectSoundCapture::CreateCaptureBuffer - Implement IDirectSoundNotify interface - Needs work from ks / portcls to work on formats supported natively by the driver svn path=/trunk/; revision=43997 --- reactos/dll/directx/dsound_new/capture.c | 18 +- .../dll/directx/dsound_new/capturebuffer.c | 33 +++ .../dll/directx/dsound_new/dsound_new.rbuild | 1 + reactos/dll/directx/dsound_new/notify.c | 256 ++++++++++++++++++ reactos/dll/directx/dsound_new/precomp.h | 15 + 5 files changed, 311 insertions(+), 12 deletions(-) create mode 100644 reactos/dll/directx/dsound_new/notify.c diff --git a/reactos/dll/directx/dsound_new/capture.c b/reactos/dll/directx/dsound_new/capture.c index 62d93c5327c..4a86ef1b32c 100644 --- a/reactos/dll/directx/dsound_new/capture.c +++ b/reactos/dll/directx/dsound_new/capture.c @@ -18,7 +18,6 @@ typedef struct LPFILTERINFO Filter; }CDirectSoundCaptureImpl, *LPCDirectSoundCaptureImpl; - HRESULT WINAPI CDirectSoundCapture_fnQueryInterface( @@ -100,25 +99,20 @@ CDirectSoundCapture_fnCreateCaptureBuffer( if (!lpcDSBufferDesc || !ppDSCBuffer || pUnkOuter != NULL) { - DPRINT("Invalid parameter %p %p %p\n", lpcDSBufferDesc, ppDSCBuffer, pUnkOuter); + /* invalid param */ return DSERR_INVALIDPARAM; } /* check buffer description */ - if ((lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC) && lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC1)) || lpcDSBufferDesc->dwReserved != 0) + if ((lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC) && lpcDSBufferDesc->dwSize != sizeof(DSCBUFFERDESC1)) || + lpcDSBufferDesc->dwReserved != 0 || lpcDSBufferDesc->dwBufferBytes == 0 || lpcDSBufferDesc->lpwfxFormat == NULL) { - DPRINT("Invalid buffer description size %u expected %u or %u dwReserved %u\n", lpcDSBufferDesc->dwSize, sizeof(DSBUFFERDESC1), sizeof(DSBUFFERDESC), lpcDSBufferDesc->dwReserved); + /* invalid buffer description */ return DSERR_INVALIDPARAM; } - /* sanity check */ - ASSERT(lpcDSBufferDesc->lpwfxFormat); - - if (lpcDSBufferDesc->lpwfxFormat) - { - DPRINT("This %p wFormatTag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u NBlockAlign %u wBitsPerSample %u cbSize %u\n", - This, lpcDSBufferDesc->lpwfxFormat->wFormatTag, lpcDSBufferDesc->lpwfxFormat->nChannels, lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec, lpcDSBufferDesc->lpwfxFormat->nAvgBytesPerSec, lpcDSBufferDesc->lpwfxFormat->nBlockAlign, lpcDSBufferDesc->lpwfxFormat->wBitsPerSample, lpcDSBufferDesc->lpwfxFormat->cbSize); - } + DPRINT("This %p wFormatTag %x nChannels %u nSamplesPerSec %u nAvgBytesPerSec %u NBlockAlign %u wBitsPerSample %u cbSize %u\n", + This, lpcDSBufferDesc->lpwfxFormat->wFormatTag, lpcDSBufferDesc->lpwfxFormat->nChannels, lpcDSBufferDesc->lpwfxFormat->nSamplesPerSec, lpcDSBufferDesc->lpwfxFormat->nAvgBytesPerSec, lpcDSBufferDesc->lpwfxFormat->nBlockAlign, lpcDSBufferDesc->lpwfxFormat->wBitsPerSample, lpcDSBufferDesc->lpwfxFormat->cbSize); hResult = NewDirectSoundCaptureBuffer((LPDIRECTSOUNDCAPTUREBUFFER8*)ppDSCBuffer, This->Filter, lpcDSBufferDesc); return hResult; diff --git a/reactos/dll/directx/dsound_new/capturebuffer.c b/reactos/dll/directx/dsound_new/capturebuffer.c index df042a23e2c..c6ac772802b 100644 --- a/reactos/dll/directx/dsound_new/capturebuffer.c +++ b/reactos/dll/directx/dsound_new/capturebuffer.c @@ -15,11 +15,14 @@ const GUID KSMEDIUMSETID_Standard = {0x4747B320L, 0x62CE, 0x11CF, const GUID KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; const GUID KSDATAFORMAT_SPECIFIER_WAVEFORMATEX = {0x05589f81L, 0xc356, 0x11ce, {0xbf, 0x01, 0x00, 0xaa, 0x00, 0x55, 0x59, 0x5a}}; const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; +const GUID KSEVENTSETID_LoopedStreaming = {0x4682B940L, 0xC6EF, 0x11D0, {0x96, 0xD8, 0x00, 0xAA, 0x00, 0x51, 0xE5, 0x1D}}; + typedef struct { IDirectSoundCaptureBuffer8Vtbl *lpVtbl; + LONG ref; LPFILTERINFO Filter; HANDLE hPin; @@ -36,6 +39,8 @@ typedef struct volatile LONG StopMixerThread; volatile LONG CurrentMixPosition; + LPDIRECTSOUNDNOTIFY Notify; + }CDirectSoundCaptureBufferImpl, *LPCDirectSoundCaptureBufferImpl; DWORD @@ -108,6 +113,13 @@ MixerThreadRoutine( BufferPosition += BytesWritten; DPRINT("MixPosition %u BufferPosition %u BytesRead %u BytesWritten %u MixLength %u BufferLength %u\n", MixPosition, BufferPosition, BytesRead, BytesWritten, MixLength, BufferLength); } + + /* Notify Events */ + if (This->Notify) + { + DoNotifyPositionEvents(This->Notify, This->CurrentMixPosition, BufferPosition); + } + /* update offset */ InterlockedExchange(&This->CurrentMixPosition, (LONG)BufferPosition); @@ -146,6 +158,25 @@ IDirectSoundCaptureBufferImpl_QueryInterface( return S_OK; } + /* check if the interface is supported */ + if (IsEqualIID(riid, &IID_IDirectSoundNotify)) + { + if (!This->Notify) + { + HRESULT hr = NewDirectSoundNotify(&This->Notify, This->bLoop, This->bMix, This->hPin, This->BufferSize); + if (FAILED(hr)) + return hr; + + *ppobj = (LPVOID)This->Notify; + return S_OK; + } + + /* increment reference count on existing notify object */ + IDirectSoundNotify_AddRef(This->Notify); + *ppobj = (LPVOID)This->Notify; + return S_OK; + } + /* interface not supported */ if (SUCCEEDED(StringFromIID(riid, &pStr))) { @@ -650,6 +681,8 @@ static IDirectSoundCaptureBuffer8Vtbl vt_DirectSoundCaptureBuffer8 = }; + + HRESULT NewDirectSoundCaptureBuffer( LPDIRECTSOUNDCAPTUREBUFFER8 *OutBuffer, diff --git a/reactos/dll/directx/dsound_new/dsound_new.rbuild b/reactos/dll/directx/dsound_new/dsound_new.rbuild index a7f1646a8fe..762337b8599 100644 --- a/reactos/dll/directx/dsound_new/dsound_new.rbuild +++ b/reactos/dll/directx/dsound_new/dsound_new.rbuild @@ -22,6 +22,7 @@ dsound.c enum.c misc.c + notify.c primary.c property.c regsvr.c diff --git a/reactos/dll/directx/dsound_new/notify.c b/reactos/dll/directx/dsound_new/notify.c new file mode 100644 index 00000000000..e3e31da7855 --- /dev/null +++ b/reactos/dll/directx/dsound_new/notify.c @@ -0,0 +1,256 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS Configuration of network devices + * FILE: dll/directx/dsound_new/notify.c + * PURPOSE: IDirectSoundNotify implementation + * + * PROGRAMMERS: Johannes Anderwald (janderwald@reactos.org) + */ + + +#include "precomp.h" + +typedef struct tagNOTIFYEVENT +{ + DWORD NotifyCount; + PLOOPEDSTREAMING_POSITION_EVENT_DATA Notify; + struct tagNOTIFYEVENT *lpNext; +}NOTIFYEVENT, *LPNOTIFYEVENT; + +typedef struct +{ + IDirectSoundNotifyVtbl * lpVtbl; + LONG ref; + + LPNOTIFYEVENT EventListHead; + BOOL bLoop; + BOOL bMix; + HANDLE hPin; + DWORD BufferSize; + +}CDirectSoundNotifyImpl, *LPCDirectSoundNotifyImpl; + +static +ULONG +WINAPI +IDirectSoundNotify_fnAddRef( + LPDIRECTSOUNDNOTIFY iface) +{ + ULONG ref; + LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl); + + /* increment reference count */ + ref = InterlockedIncrement(&This->ref); + + return ref; +} + +static +ULONG +WINAPI +IDirectSoundNotify_fnRelease( + LPDIRECTSOUNDNOTIFY iface) +{ + ULONG ref; + LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl); + + ref = InterlockedDecrement(&(This->ref)); + + if (!ref) + { + HeapFree(GetProcessHeap(), 0, This); + } + + return ref; +} + +HRESULT +WINAPI +IDirectSoundNotify_fnQueryInterface( + LPDIRECTSOUNDNOTIFY iface, + IN REFIID riid, + LPVOID* ppobj) +{ + LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl); + + /* check if the interface is supported */ + if (IsEqualIID(riid, &IID_IDirectSoundNotify) || IsEqualIID(riid, &IID_IUnknown)) + { + *ppobj = (LPVOID)&This->lpVtbl; + InterlockedIncrement(&This->ref); + return S_OK; + } + + return E_NOINTERFACE; +} + +HRESULT +WINAPI +IDirectSoundNotify_fnSetNotificationPositions( + LPDIRECTSOUNDNOTIFY iface, + DWORD dwPositionNotifies, + LPCDSBPOSITIONNOTIFY pcPositionNotifies) +{ + DWORD Index; + LPNOTIFYEVENT Notify; + DWORD Result; + KSEVENT Request; + + LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl); + + if (dwPositionNotifies > DSBNOTIFICATIONS_MAX) + { + /* invalid param */ + return DSERR_INVALIDPARAM; + } + + /* verify notification event handles */ + for(Index = 0; Index < dwPositionNotifies; Index++) + { + ASSERT(pcPositionNotifies[Index].hEventNotify); + ASSERT(pcPositionNotifies[Index].dwOffset < This->BufferSize || pcPositionNotifies[Index].dwOffset != DSBPN_OFFSETSTOP); + + if (pcPositionNotifies[Index].hEventNotify == NULL) + return DSERR_INVALIDPARAM; + + if (pcPositionNotifies[Index].dwOffset > This->BufferSize && pcPositionNotifies[Index].dwOffset != DSBPN_OFFSETSTOP) + return DSERR_INVALIDPARAM; + } + + /* allocate new array */ + Notify = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(NOTIFYEVENT)); + if (!Notify) + { + /* not enough memory */ + return DSERR_OUTOFMEMORY; + } + + /* allocate new array */ + Notify->Notify = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwPositionNotifies * sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA)); + if (!Notify->Notify) + { + /* not enough memory */ + HeapFree(GetProcessHeap(), 0, Notify); + return DSERR_OUTOFMEMORY; + } + + /* FIXME support non-looped streaming */ + ASSERT(This->bLoop); + + /* prepare request */ + Request.Set = KSEVENTSETID_LoopedStreaming; + Request.Id = KSEVENT_LOOPEDSTREAMING_POSITION; + Request.Flags = KSEVENT_TYPE_ENABLE; + + for(Index = 0; Index < dwPositionNotifies; Index++) + { + /* initialize event entries */ + Notify->Notify[Index].Position = pcPositionNotifies[Index].dwOffset; + Notify->Notify[Index].KsEventData.EventHandle.Event = pcPositionNotifies[Index].hEventNotify; + Notify->Notify[Index].KsEventData.NotificationType = KSEVENTF_EVENT_HANDLE; + + if (This->bMix == FALSE) + { + /* format is supported natively */ + Result = SyncOverlappedDeviceIoControl(This->hPin, IOCTL_KS_ENABLE_EVENT, (PVOID)&Request, sizeof(KSEVENT), (PVOID)&Notify->Notify[Index], sizeof(LOOPEDSTREAMING_POSITION_EVENT_DATA), NULL); + + if (Result != ERROR_SUCCESS) + { + DPRINT1("Failed to enable event %p Position %u\n", pcPositionNotifies[Index].hEventNotify, pcPositionNotifies[Index].dwOffset); + return DSERR_GENERIC; + } + } + } + + /* enlarge notify count */ + Notify->NotifyCount = dwPositionNotifies; + + if (This->EventListHead) + { + Notify->lpNext = This->EventListHead; + } + + /* insert at front */ + (void)InterlockedExchangePointer((LPVOID*)&This->EventListHead, Notify); + + return DS_OK; +} + +static IDirectSoundNotifyVtbl vt_DirectSoundNotify = +{ + /* IUnknown methods */ + IDirectSoundNotify_fnQueryInterface, + IDirectSoundNotify_fnAddRef, + IDirectSoundNotify_fnRelease, + /* IDirectSoundNotify */ + IDirectSoundNotify_fnSetNotificationPositions +}; + + +VOID +DoNotifyPositionEvents( + LPDIRECTSOUNDNOTIFY iface, + DWORD OldPosition, + DWORD NewPosition) +{ + DWORD Index; + LPNOTIFYEVENT CurEventList; + + LPCDirectSoundNotifyImpl This = (LPCDirectSoundNotifyImpl)CONTAINING_RECORD(iface, CDirectSoundNotifyImpl, lpVtbl); + + CurEventList = This->EventListHead; + + while(CurEventList) + { + for(Index = 0; Index < CurEventList->NotifyCount; Index++) + { + if (NewPosition > OldPosition) + { + /* buffer progress no overlap */ + if (OldPosition < CurEventList->Notify[Index].Position && CurEventList->Notify[Index].Position <= NewPosition) + { + /* process event */ + SetEvent(CurEventList->Notify[Index].KsEventData.EventHandle.Event); + } + } + else + { + /* buffer wrap-arround */ + if (OldPosition < CurEventList->Notify[Index].Position || NewPosition > CurEventList->Notify[Index].Position) + { + /* process event */ + SetEvent(CurEventList->Notify[Index].KsEventData.EventHandle.Event); + } + } + } + + /* iterate to next event list */ + CurEventList = CurEventList->lpNext; + } +} + +HRESULT +NewDirectSoundNotify( + LPDIRECTSOUNDNOTIFY * Notify, + BOOL bLoop, + BOOL bMix, + HANDLE hPin, + DWORD BufferSize) +{ + LPCDirectSoundNotifyImpl This = HeapAlloc(GetProcessHeap(), 0, sizeof(CDirectSoundNotifyImpl)); + + if (!This) + return DSERR_OUTOFMEMORY; + + This->lpVtbl = &vt_DirectSoundNotify; + This->bLoop = bLoop; + This->bMix = bMix; + This->hPin = hPin; + This->ref = 1; + This->EventListHead = NULL; + This->BufferSize = BufferSize; + + *Notify = (LPDIRECTSOUNDNOTIFY)&This->lpVtbl; + return DS_OK; + +} diff --git a/reactos/dll/directx/dsound_new/precomp.h b/reactos/dll/directx/dsound_new/precomp.h index 760c46e6a3f..36139b745c1 100644 --- a/reactos/dll/directx/dsound_new/precomp.h +++ b/reactos/dll/directx/dsound_new/precomp.h @@ -252,4 +252,19 @@ NewDirectSoundCaptureBuffer( LPFILTERINFO Filter, LPCDSCBUFFERDESC lpcDSBufferDesc); +/* notify.c */ +VOID +DoNotifyPositionEvents( + LPDIRECTSOUNDNOTIFY iface, + DWORD OldPosition, + DWORD NewPosition); + +HRESULT +NewDirectSoundNotify( + LPDIRECTSOUNDNOTIFY * Notify, + BOOL bLoop, + BOOL bMix, + HANDLE hPin, + DWORD BufferSize); + #endif -- 2.17.1