- Implement looped streaming (needed for dsound bringup)
authorJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 31 Oct 2009 08:26:26 +0000 (08:26 +0000)
committerJohannes Anderwald <johannes.anderwald@reactos.org>
Sat, 31 Oct 2009 08:26:26 +0000 (08:26 +0000)
- Implement GetPosition handler for looped streaming, WIP

svn path=/trunk/; revision=43868

reactos/drivers/wdm/audio/backpln/portcls/interfaces.hpp
reactos/drivers/wdm/audio/backpln/portcls/irpstream.cpp
reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.cpp
reactos/drivers/wdm/audio/backpln/portcls/pin_wavepci.cpp
reactos/drivers/wdm/audio/backpln/portcls/undoc.cpp

index 7b8b6fd..031a00f 100644 (file)
@@ -322,9 +322,8 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
         IN PVOID SilenceBuffer) PURE;
 
     STDMETHOD_(NTSTATUS, AddMapping)(THIS_
-        IN PUCHAR Buffer,
-        IN ULONG BufferSize,
-        IN PIRP Irp) PURE;
+        IN PIRP Irp,
+        OUT PULONG Data) PURE;
 
     STDMETHOD_(NTSTATUS, GetMapping)(THIS_
         OUT PUCHAR * Buffer,
@@ -372,9 +371,8 @@ DECLARE_INTERFACE_(IIrpQueue, IUnknown)
         IN PVOID SilenceBuffer);                       \
                                                        \
     STDMETHODIMP_(NTSTATUS) AddMapping(THIS_           \
-        IN PUCHAR Buffer,                              \
-        IN ULONG BufferSize,                           \
-        IN PIRP Irp);                                  \
+        IN PIRP Irp,                                   \
+        OUT PULONG Data);                              \
                                                        \
     STDMETHODIMP_(NTSTATUS) GetMapping(THIS_           \
         OUT PUCHAR * Buffer,                           \
index f3b1d7b..3759585 100644 (file)
@@ -39,7 +39,7 @@ protected:
     LONG m_NumMappings;
     ULONG m_NumDataAvailable;
     BOOL m_StartStream;
-    KSPIN_CONNECT * m_ConnectDetails;
+    PKSPIN_CONNECT m_ConnectDetails;
     PKSDATAFORMAT_WAVEFORMATEX m_DataFormat;
 
     KSPIN_LOCK m_IrpListLock;
@@ -110,9 +110,8 @@ CIrpQueue::Init(
 NTSTATUS
 NTAPI
 CIrpQueue::AddMapping(
-    IN PUCHAR Buffer,
-    IN ULONG BufferSize,
-    IN PIRP Irp)
+    IN PIRP Irp,
+    OUT PULONG Data)
 {
     PKSSTREAM_HEADER Header;
     NTSTATUS Status = STATUS_SUCCESS;
@@ -125,8 +124,6 @@ CIrpQueue::AddMapping(
     // get current irp stack location
     IoStack = IoGetCurrentIrpStackLocation(Irp);
 
-    PC_ASSERT(!Buffer);
-
     if (!Irp->MdlAddress)
     {
         // ioctl from KsStudio
@@ -172,8 +169,8 @@ CIrpQueue::AddMapping(
 
     NumData = 0;
     // prepare all headers
-       for(Index = 0; Index < NumHeaders; Index++)
-       {
+    for(Index = 0; Index < NumHeaders; Index++)
+    {
         // sanity checks
         PC_ASSERT(Header);
         PC_ASSERT(Mdl);
@@ -181,17 +178,17 @@ CIrpQueue::AddMapping(
         Header->Data = MmGetSystemAddressForMdlSafe(Mdl, NormalPagePriority);
 
         if (!Header->Data)
-               {
+        {
             // insufficient resources
             ExFreePool(Irp->AssociatedIrp.SystemBuffer);
             Irp->AssociatedIrp.SystemBuffer = NULL;
-                       // complete and forget request
+            // complete and forget request
             Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
             Irp->IoStatus.Information = 0;
 
             IoCompleteRequest(Irp, IO_NO_INCREMENT); 
             return STATUS_INSUFFICIENT_RESOURCES;
-               }
+        }
 
         // increment num mappings
         InterlockedIncrement(&m_NumMappings);
@@ -207,10 +204,10 @@ CIrpQueue::AddMapping(
         
         // move to next mdl
         Mdl = Mdl->Next;
-       }
+    }
 
     DPRINT("StreamHeaders %u NumData %u FrameSize %u NumDataAvailable %u\n", NumHeaders, NumData, m_MaxFrameSize, m_NumDataAvailable);
-
+    *Data = NumData;
 
     // mark irp as pending
     IoMarkIrpPending(Irp);
@@ -330,7 +327,7 @@ CIrpQueue::UpdateMapping(
     if (m_CurrentOffset >= Size)
     {
         if (STREAMHEADER_INDEX(m_Irp) + 1 < STREAMHEADER_COUNT(m_Irp))
-               {
+        {
             // the irp has at least one more stream header
             m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(STREAMHEADER_INDEX(m_Irp) + 1);
 
@@ -345,7 +342,7 @@ CIrpQueue::UpdateMapping(
 
             // done
             return;
-               }
+        }
 
         // irp has been processed completly
 
@@ -354,7 +351,7 @@ CIrpQueue::UpdateMapping(
 
         // loop all stream headers
         for(Index = 0; Index < STREAMHEADER_COUNT(m_Irp); Index++)
-               {
+        {
             PC_ASSERT(StreamHeader);
 
             // add size of buffer
@@ -369,20 +366,30 @@ CIrpQueue::UpdateMapping(
 
             // get next stream header
             StreamHeader = (PKSSTREAM_HEADER)((ULONG_PTR)StreamHeader + StreamHeader->Size);
-               }
+        }
+
+        if (m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
+        {
+            // looped streaming repeat the buffers untill
+            // the caller decides to stop the streams
+
+            // reset stream header index
+            m_Irp->Tail.Overlay.DriverContext[OFFSET_HEADERINDEX] = UlongToPtr(0);
+            // re-insert irp
+            KsAddIrpToCancelableQueue(&m_IrpList, &m_IrpListLock, m_Irp, KsListEntryTail, NULL);
+            // clear current irp
+            m_Irp = NULL;
+            // reset offset
+            m_CurrentOffset = 0;
+            // increment available data
+            InterlockedExchangeAdd((PLONG)&m_NumDataAvailable, NumData);
+            // done
+            return;
+        }
 
         m_Irp->IoStatus.Status = STATUS_SUCCESS;
         m_Irp->IoStatus.Information = NumData;
 
-#if 0
-        PC_ASSERT_IRQL(DISPATCH_LEVEL);
-        MmUnlockPages(m_Irp->MdlAddress);
-        IoFreeMdl(m_Irp->MdlAddress);
-        m_Irp->MdlAddress = NULL;
-        ExFreePool(m_Irp->AssociatedIrp.SystemBuffer);
-        m_Irp->AssociatedIrp.SystemBuffer = NULL;
-#endif
-
         // complete the request
         IoCompleteRequest(m_Irp, IO_SOUND_INCREMENT);
         // remove irp as it is complete
index 56f6217..759b261 100644 (file)
@@ -59,7 +59,7 @@ protected:
     PMINIPORTWAVECYCLICSTREAM m_Stream;
     KSSTATE m_State;
     PKSDATAFORMAT m_Format;
-    KSPIN_CONNECT * m_ConnectDetails;
+    PKSPIN_CONNECT m_ConnectDetails;
 
     PVOID m_CommonBuffer;
     ULONG m_CommonBufferSize;
@@ -187,6 +187,7 @@ PinWaveCyclicAudioPosition(
 {
     CPortPinWaveCyclic *Pin;
     PSUBDEVICE_DESCRIPTOR Descriptor;
+    PKSAUDIO_POSITION Position;
 
     // get sub device descriptor 
     Descriptor = (PSUBDEVICE_DESCRIPTOR)KSPROPERTY_ITEM_IRP_STORAGE(Irp);
@@ -206,9 +207,21 @@ PinWaveCyclicAudioPosition(
     {
         // FIXME non multithreading-safe
         // copy audio position
-        RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
 
-        DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
+        Position = (PKSAUDIO_POSITION)Data;
+
+        if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_STREAMING)
+        {
+            RtlMoveMemory(Data, &Pin->m_Position, sizeof(KSAUDIO_POSITION));
+            DPRINT("Play %lu Record %lu\n", Pin->m_Position.PlayOffset, Pin->m_Position.WriteOffset);
+        }
+        else if (Pin->m_ConnectDetails->Interface.Id == KSINTERFACE_STANDARD_LOOPED_STREAMING)
+        {
+            Position->PlayOffset = Pin->m_Position.PlayOffset % Pin->m_Position.WriteOffset;
+            Position->WriteOffset = Pin->m_IrpQueue->NumData();
+        }
+
+
         Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION);
         return STATUS_SUCCESS;
     }
@@ -584,25 +597,21 @@ CPortPinWaveCyclic::HandleKsStream(
     IN PIRP Irp)
 {
     NTSTATUS Status;
+    ULONG Data = 0;
     InterlockedIncrement((PLONG)&m_TotalPackets);
 
     DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
 
-    Status = m_IrpQueue->AddMapping(NULL, 0, Irp);
+    Status = m_IrpQueue->AddMapping(Irp, &Data);
 
     if (NT_SUCCESS(Status))
     {
-
-        PKSSTREAM_HEADER Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
-        PC_ASSERT(Header);
-
         if (m_Capture)
-            m_Position.WriteOffset += Header->FrameExtent;
+            m_Position.WriteOffset += Data;
         else
-            m_Position.WriteOffset += Header->DataUsed;
+            m_Position.WriteOffset += Data;
 
         return STATUS_PENDING;
-
     }
 
     return Status;
index 79ff0a1..273bfae 100644 (file)
@@ -665,22 +665,19 @@ CPortPinWavePci::HandleKsStream(
     IN PIRP Irp)
 {
     NTSTATUS Status;
+    ULONG Data = 0;
     InterlockedIncrement((PLONG)&m_TotalPackets);
 
     DPRINT("IPortPinWaveCyclic_HandleKsStream entered Total %u State %x MinData %u\n", m_TotalPackets, m_State, m_IrpQueue->NumData());
 
-    Status = m_IrpQueue->AddMapping(NULL, 0, Irp);
+    Status = m_IrpQueue->AddMapping(Irp, &Data);
 
     if (NT_SUCCESS(Status))
     {
-
-        PKSSTREAM_HEADER Header = (PKSSTREAM_HEADER)Irp->AssociatedIrp.SystemBuffer;
-        PC_ASSERT(Header);
-
         if (m_Capture)
-            m_Position.WriteOffset += Header->FrameExtent;
+            m_Position.WriteOffset += Data;
         else
-            m_Position.WriteOffset += Header->DataUsed;
+            m_Position.WriteOffset += Data;
 
         return STATUS_PENDING;
     }
index c0b1f85..56c2597 100644 (file)
@@ -8,6 +8,22 @@
 
 #include "private.hpp"
 
+
+KSPIN_INTERFACE PinInterfaces[] = 
+{
+    {
+        {STATIC_KSINTERFACESETID_Standard},
+        KSINTERFACE_STANDARD_STREAMING,
+        0
+    },
+    {
+        {STATIC_KSINTERFACESETID_Standard},
+        KSINTERFACE_STANDARD_LOOPED_STREAMING,
+        0
+    }
+};
+
+
 NTSTATUS
 NTAPI
 KsoDispatchCreateWithGenericFactory(
@@ -450,6 +466,9 @@ PcCreateSubdeviceDescriptor(
         {
             RtlMoveMemory(&Descriptor->Factory.KsPinDescriptor[Index], &SrcDescriptor->KsPinDescriptor, sizeof(KSPIN_DESCRIPTOR));
 
+            Descriptor->Factory.KsPinDescriptor[Index].Interfaces = PinInterfaces;
+            Descriptor->Factory.KsPinDescriptor[Index].InterfacesCount = sizeof(PinInterfaces) / sizeof(KSPIN_INTERFACE);
+
             DPRINT("Index %u DataRangeCount %u\n", Index, SrcDescriptor->KsPinDescriptor.DataRangesCount);
 
             Descriptor->Factory.Instances[Index].CurrentPinInstanceCount = 0;