diff --git a/reactos/drivers/wdm/audio/filters/splitter/filter.c b/reactos/drivers/wdm/audio/filters/splitter/filter.c index 62610d4a00f..2613b972163 100644 --- a/reactos/drivers/wdm/audio/filters/splitter/filter.c +++ b/reactos/drivers/wdm/audio/filters/splitter/filter.c @@ -14,7 +14,48 @@ FilterProcess( IN PKSFILTER Filter, IN PKSPROCESSPIN_INDEXENTRY ProcessPinsIndex) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + ULONG Index; + PKSPROCESSPIN CurPin, Pin; + BOOLEAN PendingFrames = FALSE; + + if (ProcessPinsIndex->Count) + { + /* check if there are outstanding frames */ + for(Index = 1; Index < ProcessPinsIndex->Count; Index++) + { + /* get current pin */ + CurPin = ProcessPinsIndex->Pins[Index]; + + if (CurPin->BytesAvailable && CurPin->Pin->DeviceState == KSSTATE_RUN) + { + /* pin has pending frames + * to keep all pins synchronized, every pin has to wait untill each chained pin has send its frames downwards + */ + PendingFrames = TRUE; + } + } + } + + if (!PendingFrames && ProcessPinsIndex->Count) + { + /* get first pin */ + Pin = ProcessPinsIndex->Pins[0]; + + /* check if there is new data available */ + if (Pin->BytesAvailable) + { + for(Index = 1; Index < ProcessPinsIndex->Count; Index++) + { + /* get current pin */ + CurPin = ProcessPinsIndex->Pins[Index]; + + /* copy the frame to pin */ + RtlMoveMemory(CurPin->Data, Pin->Data, Pin->BytesAvailable); + CurPin->BytesUsed = Pin->BytesAvailable; + } + } + } + /* done */ + return STATUS_SUCCESS; } diff --git a/reactos/drivers/wdm/audio/filters/splitter/pin.c b/reactos/drivers/wdm/audio/filters/splitter/pin.c index 5ecd841b638..6286812ba1c 100644 --- a/reactos/drivers/wdm/audio/filters/splitter/pin.c +++ b/reactos/drivers/wdm/audio/filters/splitter/pin.c @@ -14,8 +14,45 @@ PinCreate( IN PKSPIN Pin, IN PIRP Irp) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PKSFILTER Filter; + PKSPIN FirstPin; + PPIN_CONTEXT PinContext; + + /* first get the parent filter */ + Filter = KsPinGetParentFilter(Pin); + + /* now get first child pin */ + FirstPin = KsFilterGetFirstChildPin(Filter, Pin->Id); + + /* sanity check */ + ASSERT(FirstPin); + + if (FirstPin != Pin) + { + /* a previous pin already exists */ + if (RtlCompareMemory(FirstPin->ConnectionFormat, Pin->ConnectionFormat, Pin->ConnectionFormat->FormatSize) != Pin->ConnectionFormat->FormatSize) + { + /* each instantiated pin must have the same connection format */ + return STATUS_INVALID_PARAMETER; + } + } + + /* allocate pin context */ + PinContext = ExAllocatePool(NonPagedPool, sizeof(PIN_CONTEXT)); + if (!PinContext) + return STATUS_INSUFFICIENT_RESOURCES; + + /* store pin context */ + Pin->Context = PinContext; + + /* clear pin context */ + RtlZeroMemory(PinContext, sizeof(PIN_CONTEXT)); + + /* FIXME + * check allocator framing and apply to all pins + */ + + return STATUS_SUCCESS; } NTSTATUS @@ -24,8 +61,14 @@ PinClose( IN PKSPIN Pin, IN PIRP Irp) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + /* is there a context */ + if (Pin->Context) + { + /* free pin context */ + ExFreePool(Pin->Context); + } + + return STATUS_SUCCESS; } VOID @@ -33,7 +76,22 @@ NTAPI PinReset( IN PKSPIN Pin) { - UNIMPLEMENTED + PKSFILTER Filter; + + /* sanity check */ + ASSERT(Pin->Context); + + /* clear pin context */ + RtlZeroMemory(Pin->Context, sizeof(PIN_CONTEXT)); + + /* get parent filter */ + Filter = KsPinGetParentFilter(Pin); + + /* sanity check */ + ASSERT(Filter); + + /* attempt processing */ + KsFilterAttemptProcessing(Filter, TRUE); } NTSTATUS @@ -43,8 +101,25 @@ PinState( IN KSSTATE ToState, IN KSSTATE FromState) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PKSFILTER Filter; + + /* should the pin stop */ + if (ToState == KSSTATE_STOP) + { + /* clear pin context */ + RtlZeroMemory(Pin->Context, sizeof(PIN_CONTEXT)); + } + + /* get parent filter */ + Filter = KsPinGetParentFilter(Pin); + + /* sanity check */ + ASSERT(Filter); + + /* attempt processing */ + KsFilterAttemptProcessing(Filter, TRUE); + + return STATUS_SUCCESS; } NTSTATUS @@ -54,8 +129,49 @@ AudioPositionPropertyHandler( IN PKSIDENTIFIER Request, IN OUT PVOID Data) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PKSFILTER Filter; + PKSPIN Pin, FirstPin; + PFILE_OBJECT FileObject; + NTSTATUS Status; + ULONG BytesReturned; + + /* first get the pin */ + Pin = KsGetPinFromIrp(Irp); + + /* sanity check */ + ASSERT(Pin); + + /* get parent filter */ + Filter = KsPinGetParentFilter(Pin); + + /* acquire filter control mutex */ + KsFilterAcquireControl(Filter); + + /* get first pin */ + FirstPin = KsFilterGetFirstChildPin(Filter, Pin->Id); + + /* get connected pin of first pin */ + FileObject = KsPinGetConnectedPinFileObject(FirstPin); + + if (!FileObject) + { + /* no pin connected */ + Status = STATUS_INVALID_PARAMETER; + } + else + { + /* perform request */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)Request, sizeof(KSPROPERTY), Data, sizeof(KSAUDIO_POSITION), &BytesReturned); + + /* store result size */ + Irp->IoStatus.Information = sizeof(KSAUDIO_POSITION); + } + + /* release control */ + KsFilterReleaseControl(Filter); + + /* done */ + return Status; } NTSTATUS @@ -70,7 +186,54 @@ PinIntersectHandler( OUT PVOID Data OPTIONAL, OUT PULONG DataSize) { - UNIMPLEMENTED - return STATUS_NOT_IMPLEMENTED; + PKSPIN FirstPin; + NTSTATUS Status; + + /* get first pin */ + FirstPin = KsFilterGetFirstChildPin((PKSFILTER)Context, Pin->PinId); + + /* sanity check */ + ASSERT(FirstPin); + + /* check for matching dataformat */ + if (!IsEqualGUIDAligned(&FirstPin->ConnectionFormat->SubFormat, &DataRange->SubFormat) || + !IsEqualGUIDAligned(&FirstPin->ConnectionFormat->Specifier, &DataRange->Specifier) || + !IsEqualGUIDAligned(&GUID_NULL, &DataRange->SubFormat) || + !IsEqualGUIDAligned(&GUID_NULL, &DataRange->Specifier)) + { + /* no match */ + return STATUS_NO_MATCH; + } + + + if (DataBufferSize) + { + /* there is output buffer */ + if (DataBufferSize >= FirstPin->ConnectionFormat->FormatSize) + { + /* copy dataformat */ + RtlMoveMemory(Data, FirstPin->ConnectionFormat, FirstPin->ConnectionFormat->FormatSize); + + /* store output length */ + *DataSize = FirstPin->ConnectionFormat->FormatSize; + + Status = STATUS_SUCCESS; + } + else + { + /* buffer too small */ + Status = STATUS_BUFFER_TOO_SMALL; + } + } + else + { + /* store output length */ + *DataSize = FirstPin->ConnectionFormat->FormatSize; + + Status = STATUS_BUFFER_OVERFLOW; + } + + /* done */ + return Status; } diff --git a/reactos/drivers/wdm/audio/filters/splitter/precomp.h b/reactos/drivers/wdm/audio/filters/splitter/precomp.h index 2954c6b099c..7492e214cf7 100644 --- a/reactos/drivers/wdm/audio/filters/splitter/precomp.h +++ b/reactos/drivers/wdm/audio/filters/splitter/precomp.h @@ -58,4 +58,13 @@ PinIntersectHandler( OUT PVOID Data OPTIONAL, OUT PULONG DataSize); + + +typedef struct +{ + ULONG BytesAvailable; + ULONG BytesProcessed; +}PIN_CONTEXT, *PPIN_CONTEXT; + + #endif diff --git a/reactos/drivers/wdm/audio/filters/splitter/splitter.c b/reactos/drivers/wdm/audio/filters/splitter/splitter.c index 9ad0900f839..7496815ad0c 100644 --- a/reactos/drivers/wdm/audio/filters/splitter/splitter.c +++ b/reactos/drivers/wdm/audio/filters/splitter/splitter.c @@ -12,6 +12,8 @@ const GUID PIN_VIDEO_CAPTURE = {0xfb6c4281, 0x0353, 0x11d1, {0x90, 0x5f, 0x0, 0x const GUID KSPROPSETID_Audio = {0x45FFAAA0, 0x6E1B, 0x11D0, {0xBC, 0xF2, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}; const GUID KSCATEGORY_AUDIO_SPLITTER = {0x9EA331FA, 0xB91B, 0x45F8, {0x92, 0x85, 0xBD, 0x2B, 0xC7, 0x7A, 0xFC, 0xDE}}; const GUID KSNAME_Filter = {0x9b365890, 0x165f, 0x11d0, {0xa1, 0x95, 0x00, 0x20, 0xaf, 0xd1, 0x56, 0xe4}}; +const GUID GUID_NULL = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + KSPROPERTY_ITEM PinPropertyTable[] =