- Partly implement IMasterClock
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 8 May 2009 13:02:08 +0000 (13:02 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Fri, 8 May 2009 13:02:08 +0000 (13:02 +0000)
- Implement IAllocatorMXF for IPortPinDMus
- Implement rendering midi streams using IMXF object
- WIP, not tested yet

svn path=/trunk/; revision=40837

reactos/drivers/wdm/audio/backpln/portcls/guids.c
reactos/drivers/wdm/audio/backpln/portcls/interfaces.h
reactos/drivers/wdm/audio/backpln/portcls/pin_dmus.c

index 703aba0..0dd4a78 100644 (file)
@@ -65,13 +65,15 @@ const GUID KS_CATEGORY_TOPOLOGY = {0xDDA54A40, 0x1E4C, 0x11D1, {0xA0, 0x50, 0x40
 
 
 const GUID KSDATAFORMAT_TYPE_AUDIO =             {0x73647561L, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
-const GUID KSDATAFORMAT_SUBTYPE_PCM =            {0x00000001, 0x0000, 0x0010,  {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}};
+const GUID KSDATAFORMAT_SUBTYPE_PCM =            {0x00000001L, 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_Topology                = {0x720D4AC0L, 0x7533, 0x11D0, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 const GUID KSPROPSETID_Pin                     = {0x8C134960L, 0x51AD, 0x11CF, {0x87, 0x8A, 0x94, 0xF8, 0x01, 0xC1, 0x00, 0x00}};
 const GUID KSPROPSETID_Connection              = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}};
 
+const GUID IID_IAllocatorMXF                   = {0xa5f0d62cL, 0xb30f, 0x11d2, {0xb7, 0xa3, 0x00, 0x60, 0x08, 0x33, 0x16, 0xc1}};
+
 ///
 /// undocumented guids
 
index 58d7a92..2fe1fe5 100644 (file)
@@ -678,4 +678,6 @@ DECLARE_INTERFACE_(IDmaChannelInit, IUnknown)
         IN PDEVICE_OBJECT DeviceObject) PURE;
 };
 
+#undef INTERFACE
+
 #endif
index d8898a0..7e5f8d4 100644 (file)
@@ -14,6 +14,9 @@ typedef struct
 {
     IPortPinDMusVtbl *lpVtbl;
     IServiceSinkVtbl *lpVtblServiceSink;
+    IMasterClockVtbl *lpVtblMasterClock;
+    IAllocatorMXFVtbl *lpVtblAllocatorMXF;
+    IMXFVtbl *lpVtblMXF;
 
     LONG ref;
     IPortDMus * Port;
@@ -23,6 +26,11 @@ typedef struct
 
     PSERVICEGROUP ServiceGroup;
 
+    PMXF Mxf;
+    ULONGLONG SchedulePreFetch;
+    NPAGED_LOOKASIDE_LIST LookAsideEvent;
+    NPAGED_LOOKASIDE_LIST LookAsideBuffer;
+
     PMINIPORTMIDI MidiMiniport;
     PMINIPORTMIDISTREAM MidiStream;
 
@@ -39,8 +47,15 @@ typedef struct
     ULONG PreCompleted;
     ULONG PostCompleted;
 
+    ULONG LastTag;
+
 }IPortPinDMusImpl;
 
+typedef struct
+{
+    DMUS_KERNEL_EVENT Event;
+    PVOID Tag;
+}DMUS_KERNEL_EVENT_WITH_TAG, *PDMUS_KERNEL_EVENT_WITH_TAG;
 
 typedef struct
 {
@@ -49,10 +64,263 @@ typedef struct
     KSSTATE State;
 }SETSTREAM_CONTEXT, *PSETSTREAM_CONTEXT;
 
+//==================================================================================================================================
+
+
+static
+NTSTATUS
+NTAPI
+IMasterClock_fnQueryInterface(
+    IMasterClock* iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblMasterClock);
+
+    DPRINT("IServiceSink_fnQueryInterface entered\n");
+
+    if (IsEqualGUIDAligned(refiid, &IID_IUnknown))
+    {
+        *Output = &This->lpVtblServiceSink;
+        InterlockedIncrement(&This->ref);
+        return STATUS_SUCCESS;
+    }
+    return STATUS_UNSUCCESSFUL;
+}
+
+static
+ULONG
+NTAPI
+IMasterClock_fnAddRef(
+    IMasterClock* iface)
+{
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblMasterClock);
+    DPRINT("IServiceSink_fnAddRef entered\n");
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static
+ULONG
+NTAPI
+IMasterClock_fnRelease(
+    IMasterClock* iface)
+{
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblMasterClock);
+
+    InterlockedDecrement(&This->ref);
+
+    DPRINT("IServiceSink_fnRelease entered %u\n", This->ref);
+
+    if (This->ref == 0)
+    {
+        FreeItem(This, TAG_PORTCLASS);
+        return 0;
+    }
+    /* Return new reference count */
+    return This->ref;
+}
+
+static
+NTSTATUS
+NTAPI
+IMasterClock_fnGetTime(
+    IMasterClock* iface,
+    OUT REFERENCE_TIME  *prtTime)
+{
+    UNIMPLEMENTED
+    return STATUS_SUCCESS;
+}
+
+static IMasterClockVtbl vt_IMasterClock = 
+{
+    IMasterClock_fnQueryInterface,
+    IMasterClock_fnAddRef,
+    IMasterClock_fnRelease,
+    IMasterClock_fnGetTime
+};
+
+//==================================================================================================================================
+
+
+static
+NTSTATUS
+NTAPI
+IAllocatorMXF_fnQueryInterface(
+    IAllocatorMXF* iface,
+    IN  REFIID refiid,
+    OUT PVOID* Output)
+{
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
+
+    DPRINT("IServiceSink_fnQueryInterface entered\n");
+
+    if (IsEqualGUIDAligned(refiid, &IID_IAllocatorMXF) ||
+        IsEqualGUIDAligned(refiid, &IID_IUnknown))
+    {
+        *Output = &This->lpVtblServiceSink;
+        InterlockedIncrement(&This->ref);
+        return STATUS_SUCCESS;
+    }
+    return STATUS_UNSUCCESSFUL;
+}
+
+static
+ULONG
+NTAPI
+IAllocatorMXF_fnAddRef(
+    IAllocatorMXF* iface)
+{
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
+    DPRINT("IServiceSink_fnAddRef entered\n");
+
+    return InterlockedIncrement(&This->ref);
+}
+
+static
+ULONG
+NTAPI
+IAllocatorMXF_fnRelease(
+    IAllocatorMXF* iface)
+{
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
+
+    InterlockedDecrement(&This->ref);
+
+    DPRINT("IServiceSink_fnRelease entered %u\n", This->ref);
+
+    if (This->ref == 0)
+    {
+        FreeItem(This, TAG_PORTCLASS);
+        return 0;
+    }
+    /* Return new reference count */
+    return This->ref;
+}
+
+static
+NTSTATUS
+NTAPI
+IAllocatorMXF_fnGetMessage(
+    IAllocatorMXF* iface,
+    OUT PDMUS_KERNEL_EVENT * ppDMKEvt)
+{
+    PVOID Buffer;
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
+
+    Buffer = ExAllocateFromNPagedLookasideList(&This->LookAsideEvent);
+    if (!Buffer)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    *ppDMKEvt = Buffer;
+    RtlZeroMemory(Buffer, sizeof(DMUS_KERNEL_EVENT));
+    return STATUS_SUCCESS;
+}
+
+static
+USHORT
+NTAPI
+IAllocatorMXF_fnGetBufferSize(
+    IAllocatorMXF* iface)
+{
+    return PAGE_SIZE;
+}
+
+static
+NTSTATUS
+NTAPI
+IAllocatorMXF_fnGetBuffer(
+    IAllocatorMXF* iface,
+    OUT PBYTE * ppBuffer)
+{
+    PVOID Buffer;
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
+
+    Buffer = ExAllocateFromNPagedLookasideList(&This->LookAsideBuffer);
+    if (!Buffer)
+        return STATUS_INSUFFICIENT_RESOURCES;
+
+    *ppBuffer = Buffer;
+    RtlZeroMemory(Buffer, PAGE_SIZE);
+    return STATUS_SUCCESS;
+}
+
+static
 NTSTATUS
 NTAPI
-IPortDMus_fnProcessNewIrp(
-    IPortPinDMusImpl * This);
+IAllocatorMXF_fnPutBuffer(
+    IAllocatorMXF* iface,
+    IN PBYTE pBuffer)
+{
+    PDMUS_KERNEL_EVENT_WITH_TAG Event = (PDMUS_KERNEL_EVENT_WITH_TAG)pBuffer;
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
+
+    This->IrpQueue->lpVtbl->ReleaseMappingWithTag(This->IrpQueue, Event->Tag);
+
+    ExFreeToNPagedLookasideList(&This->LookAsideBuffer, pBuffer);
+    return STATUS_SUCCESS;
+}
+
+static
+NTSTATUS
+NTAPI
+IAllocatorMXF_fnSetState(
+    IAllocatorMXF* iface,
+    IN KSSTATE State)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static
+NTSTATUS
+NTAPI
+IAllocatorMXF_fnPutMessage(
+    IAllocatorMXF* iface,
+    IN PDMUS_KERNEL_EVENT pDMKEvt)
+{
+    IPortPinDMusImpl * This = (IPortPinDMusImpl*)CONTAINING_RECORD(iface, IPortPinDMusImpl, lpVtblAllocatorMXF);
+
+    ExFreeToNPagedLookasideList(&This->LookAsideEvent, pDMKEvt);
+    return STATUS_SUCCESS;
+}
+
+static
+NTSTATUS
+NTAPI
+IAllocatorMXF_fnConnectOutput(
+    IAllocatorMXF* iface,
+    IN PMXF sinkMXF)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static
+NTSTATUS
+NTAPI
+IAllocatorMXF_fnDisconnectOutput(
+    IAllocatorMXF* iface,
+    IN PMXF sinkMXF)
+{
+    UNIMPLEMENTED
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static IAllocatorMXFVtbl vt_IAllocatorMXF =
+{
+    IAllocatorMXF_fnQueryInterface,
+    IAllocatorMXF_fnAddRef,
+    IAllocatorMXF_fnRelease,
+    IAllocatorMXF_fnSetState,
+    IAllocatorMXF_fnPutMessage,
+    IAllocatorMXF_fnConnectOutput,
+    IAllocatorMXF_fnDisconnectOutput,
+    IAllocatorMXF_fnGetMessage,
+    IAllocatorMXF_fnGetBufferSize,
+    IAllocatorMXF_fnGetBuffer,
+    IAllocatorMXF_fnPutBuffer
+};
 
 //==================================================================================================================================
 
@@ -110,6 +378,8 @@ IServiceSink_fnRelease(
     /* Return new reference count */
     return This->ref;
 }
+
+
 static
 VOID
 NTAPI
@@ -118,8 +388,9 @@ SetStreamWorkerRoutine(
     IN PVOID  Context)
 {
     IPortPinDMusImpl * This;
-    PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
     KSSTATE State;
+    NTSTATUS Status;
+    PSETSTREAM_CONTEXT Ctx = (PSETSTREAM_CONTEXT)Context;
 
     This = Ctx->Pin;
     State = Ctx->State;
@@ -132,9 +403,18 @@ SetStreamWorkerRoutine(
         return;
 
     /* Set the state */
-    if (NT_SUCCESS(This->MidiStream->lpVtbl->SetState(This->MidiStream, State)))
+    if (This->MidiStream)
+    {
+        Status = This->MidiStream->lpVtbl->SetState(This->MidiStream, State);
+    }
+    else
     {
-        /* Set internal state to stop */
+        Status = This->Mxf->lpVtbl->SetState(This->Mxf, State);
+    }
+
+    if (NT_SUCCESS(Status))
+    {
+        /* Set internal state to requested state */
         This->State = State;
 
         if (This->State == KSSTATE_STOP)
@@ -237,6 +517,59 @@ TransferMidiData(
 
 }
 
+VOID
+TransferMidiDataToDMus(
+    IPortPinDMusImpl * This)
+{
+    NTSTATUS Status;
+    PHYSICAL_ADDRESS  PhysicalAddress;
+    ULONG BufferSize, Flags;
+    PVOID Buffer;
+    PDMUS_KERNEL_EVENT_WITH_TAG Event, LastEvent = NULL, Root = NULL;
+
+    do
+    {
+        This->LastTag++;
+        Status = This->IrpQueue->lpVtbl->GetMappingWithTag(This->IrpQueue, UlongToPtr(This->LastTag), &PhysicalAddress, &Buffer, &BufferSize, &Flags);
+        if (!NT_SUCCESS(Status))
+        {
+            break;
+        }
+
+        Status = IAllocatorMXF_fnGetMessage((IAllocatorMXF*)&This->lpVtblAllocatorMXF, (PDMUS_KERNEL_EVENT*)&Event);
+        if (!NT_SUCCESS(Status))
+            break;
+
+        //FIXME
+        //set up struct
+        //Event->Event.usFlags = DMUS_KEF_EVENT_COMPLETE;
+        Event->Event.cbStruct = sizeof(DMUS_KERNEL_EVENT);
+        Event->Event.cbEvent = BufferSize;
+        Event->Event.uData.pbData = Buffer;
+
+
+        if (!Root)
+            Root = Event;
+        else
+            LastEvent->Event.pNextEvt = (struct _DMUS_KERNEL_EVENT *)Event;
+
+        LastEvent = Event;
+        LastEvent->Event.pNextEvt = NULL;
+        LastEvent->Tag = UlongToPtr(This->LastTag);
+
+    }while(TRUE);
+
+    if (!Root)
+    {
+        SetStreamState(This, KSSTATE_STOP);
+        return;
+    }
+
+    Status = This->Mxf->lpVtbl->PutMessage(This->Mxf, (PDMUS_KERNEL_EVENT)Root);
+    DPRINT("Status %x\n", Status);
+}
+
+
 static
 VOID
 NTAPI
@@ -251,8 +584,10 @@ IServiceSink_fnRequestService(
     {
         TransferMidiData(This);
     }
-
-
+    else if (This->Mxf)
+    {
+        TransferMidiDataToDMus(This);
+    }
 }
 
 static IServiceSinkVtbl vt_IServiceSink = 
@@ -486,7 +821,7 @@ IPortPinDMus_fnClose(
     PCLOSESTREAM_CONTEXT Ctx;
     IPortPinDMusImpl * This = (IPortPinDMusImpl*)iface;
 
-    if (This->MidiStream)
+    if (This->MidiStream || This->Mxf)
     {
         Ctx = AllocateItem(NonPagedPool, sizeof(CLOSESTREAM_CONTEXT), TAG_PORTCLASS);
         if (!Ctx)
@@ -757,6 +1092,38 @@ IPortPinDMus_fnInit(
         if (!NT_SUCCESS(Status))
             return Status;
     }
+    else
+    {
+        Status = This->Miniport->lpVtbl->NewStream(This->Miniport,
+                                                   &This->Mxf,
+                                                   NULL,
+                                                   NonPagedPool,
+                                                   ConnectDetails->PinId,
+                                                   Capture, //FIXME
+                                                   This->Format,
+                                                   &This->ServiceGroup,
+                                                   (PAllocatorMXF)&This->lpVtblAllocatorMXF,
+                                                   (PMASTERCLOCK)&This->lpVtblMasterClock,
+                                                   &This->SchedulePreFetch);
+
+        DPRINT("IPortPinDMus_fnInit Status %x\n", Status);
+
+        if (!NT_SUCCESS(Status))
+            return Status;
+
+        if (Capture == DMUS_STREAM_MIDI_CAPTURE)
+        {
+            Status = This->Mxf->lpVtbl->ConnectOutput(This->Mxf, (PMXF)&This->lpVtblMXF);
+            if (!NT_SUCCESS(Status))
+            {
+                DPRINT("IMXF_ConnectOutput failed with Status %x\n", Status);
+                return Status;
+            }
+        }
+
+        ExInitializeNPagedLookasideList(&This->LookAsideEvent, NULL, NULL, 0, sizeof(DMUS_KERNEL_EVENT_WITH_TAG), TAG_PORTCLASS, 0);
+        ExInitializeNPagedLookasideList(&This->LookAsideBuffer, NULL, NULL, 0, PAGE_SIZE, TAG_PORTCLASS, 0);
+    }
 
     if (This->ServiceGroup)
     {
@@ -832,6 +1199,8 @@ NTSTATUS NewPortPinDMus(
     This->ref = 1;
     This->lpVtbl = &vt_IPortPinDMus;
     This->lpVtblServiceSink = &vt_IServiceSink;
+    This->lpVtblMasterClock = &vt_IMasterClock;
+    This->lpVtblAllocatorMXF = &vt_IAllocatorMXF;
 
 
     /* store result */
@@ -839,6 +1208,3 @@ NTSTATUS NewPortPinDMus(
 
     return STATUS_SUCCESS;
 }
-
-
-