[DSOUND]
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 7 Nov 2009 13:49:01 +0000 (13:49 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 7 Nov 2009 13:49:01 +0000 (13:49 +0000)
- 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
reactos/dll/directx/dsound_new/capturebuffer.c
reactos/dll/directx/dsound_new/dsound_new.rbuild
reactos/dll/directx/dsound_new/notify.c [new file with mode: 0644]
reactos/dll/directx/dsound_new/precomp.h

index 62d93c5..4a86ef1 100644 (file)
@@ -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;
index df042a2..c6ac772 100644 (file)
@@ -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,
index a7f1646..762337b 100644 (file)
@@ -22,6 +22,7 @@
        <file>dsound.c</file>
        <file>enum.c</file>
        <file>misc.c</file>
+       <file>notify.c</file>
        <file>primary.c</file>
        <file>property.c</file>
        <file>regsvr.c</file>
diff --git a/reactos/dll/directx/dsound_new/notify.c b/reactos/dll/directx/dsound_new/notify.c
new file mode 100644 (file)
index 0000000..e3e31da
--- /dev/null
@@ -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;
+
+}
index 760c46e..36139b7 100644 (file)
@@ -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