Author: janderwald Date: Fri Mar 13 01:11:53 2009 New Revision: 39992
URL: http://svn.reactos.org/svn/reactos?rev=39992&view=rev Log: - Disable some debug prints - Close the real pin on exit / when a new wave stream is played. This should fix stuttering when changing the sample rate - Always create the mixer pin
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.c trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c trunk/reactos/drivers/wdm/audio/sysaudio/control.c trunk/reactos/drivers/wdm/audio/sysaudio/dispatcher.c trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/dispatcher.c [iso-8859-1] Fri Mar 13 01:11:53 2009 @@ -10,7 +10,7 @@ IIrpTarget * IrpTarget; PKSOBJECT_CREATE_ITEM CreateItem;
- DPRINT1("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject); + //DPRINT1("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
/* access the create item */ CreateItem = KSCREATE_ITEM_IRP_STORAGE(Irp); @@ -114,7 +114,7 @@
IrpTarget = (IIrpTarget*)CreateItem->Context;
- DPRINT1("IrpTarget %p\n", IrpTarget); + //DPRINT1("IrpTarget %p\n", IrpTarget);
return IrpTarget->lpVtbl->Close(IrpTarget, DeviceObject, Irp); }
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/pin_wavecyclic.c [iso-8859-1] Fri Mar 13 01:11:53 2009 @@ -15,6 +15,7 @@ PMINIPORTWAVECYCLICSTREAM Stream; KSSTATE State; PKSDATAFORMAT Format; + KSPIN_CONNECT * ConnectDetails;
PVOID CommonBuffer; ULONG CommonBufferSize; @@ -184,8 +185,8 @@ } DPRINT1("Stopping %u\n", This->IrpQueue->lpVtbl->NumMappings(This->IrpQueue));
- This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_PAUSE); - This->State = KSSTATE_PAUSE; + This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP); + This->State = KSSTATE_STOP; return; }
@@ -306,7 +307,7 @@
IoStack = IoGetCurrentIrpStackLocation(Irp);
- DPRINT1("IPortPinWave_HandleKsProperty entered\n"); + //DPRINT1("IPortPinWave_HandleKsProperty entered\n");
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(KSPROPERTY)) { @@ -365,7 +366,16 @@ PKSDATAFORMAT DataFormat = (PKSDATAFORMAT)Irp->UserBuffer; if (Property->Flags & KSPROPERTY_TYPE_SET) { - PKSDATAFORMAT NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); + PKSDATAFORMAT NewDataFormat; + if (!RtlCompareMemory(DataFormat, This->Format, DataFormat->FormatSize)) + { + Irp->IoStatus.Information = DataFormat->FormatSize; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + + NewDataFormat = AllocateItem(NonPagedPool, DataFormat->FormatSize, TAG_PORTCLASS); if (!NewDataFormat) { Irp->IoStatus.Information = 0; @@ -377,11 +387,18 @@
if (This->Stream) { + ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL); + ASSERT(NewDataFormat->FormatSize == sizeof(KSDATAFORMAT_WAVEFORMATEX)); + ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.MajorFormat, &KSDATAFORMAT_TYPE_AUDIO)); + ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.SubFormat, &KSDATAFORMAT_SUBTYPE_PCM)); + ASSERT(IsEqualGUIDAligned(&((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->DataFormat.Specifier, &KSDATAFORMAT_SPECIFIER_WAVEFORMATEX)); + Status = This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP); + ASSERT(Status == STATUS_SUCCESS); This->State = KSSTATE_STOP; - DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nChannels, - ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.wBitsPerSample, - ((PKSDATAFORMAT_WAVEFORMATEX)DataFormat)->WaveFormatEx.nSamplesPerSec); + DPRINT1("NewDataFormat: Channels %u Bits %u Samples %u\n", ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nChannels, + ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.wBitsPerSample, + ((PKSDATAFORMAT_WAVEFORMATEX)NewDataFormat)->WaveFormatEx.nSamplesPerSec);
Status = This->Stream->lpVtbl->SetFormat(This->Stream, NewDataFormat); if (NT_SUCCESS(Status)) @@ -399,7 +416,6 @@
} DPRINT1("Failed to set format\n"); -DbgBreakPoint(); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -549,8 +565,20 @@ return KsDispatchInvalidDeviceRequest(DeviceObject, Irp); }
-/* - * @unimplemented +VOID +NTAPI +CloseStreamRoutine( + IN PDEVICE_OBJECT DeviceObject, + IN PVOID Context) +{ + PMINIPORTWAVECYCLICSTREAM Stream = (PMINIPORTWAVECYCLICSTREAM)Context; + + DPRINT("CloseStreamRoutine %p\n", Stream); + Stream->lpVtbl->Release(Stream); +} + +/* + * @implemented */ NTSTATUS NTAPI @@ -559,9 +587,50 @@ IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { + ISubdevice *ISubDevice; + NTSTATUS Status; + SUBDEVICE_DESCRIPTOR * Descriptor; + PIO_WORKITEM WorkItem; + + IPortPinWaveCyclicImpl * This = (IPortPinWaveCyclicImpl*)iface; DPRINT1("IPortPinWaveCyclic_fnClose\n");
- //FIXME + Status = This->Port->lpVtbl->QueryInterface(This->Port, &IID_ISubdevice, (PVOID*)&ISubDevice); + if (NT_SUCCESS(Status)) + { + Status = ISubDevice->lpVtbl->GetDescriptor(ISubDevice, &Descriptor); + if (NT_SUCCESS(Status)) + { + ISubDevice->lpVtbl->Release(ISubDevice); + Descriptor->Factory.Instances[This->ConnectDetails->PinId].CurrentPinInstanceCount--; + DPRINT1("InstanceCount %u\n", Descriptor->Factory.Instances[This->ConnectDetails->PinId].CurrentPinInstanceCount); + } + } + + + if (This->Stream) + { + This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP); + } + + This->ServiceGroup->lpVtbl->RemoveMember(This->ServiceGroup, (PSERVICESINK)&This->lpVtblServiceSink); + This->ServiceGroup->lpVtbl->Release(This->ServiceGroup); + This->DmaChannel->lpVtbl->Release(This->DmaChannel); + + if (This->Format) + ExFreePool(This->Format); + + This->IrpQueue->lpVtbl->Release(This->IrpQueue); + + + if (This->Stream) + { + WorkItem = IoAllocateWorkItem(DeviceObject); + if (WorkItem) + { + IoQueueWorkItem(WorkItem, CloseStreamRoutine, DelayedWorkQueue, (PVOID)This->Stream); + } + }
Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; @@ -716,6 +785,7 @@ This->Port = Port; This->Filter = Filter; This->KsPinDescriptor = KsPinDescriptor; + This->ConnectDetails = ConnectDetails; This->Miniport = GetWaveCyclicMiniport(Port);
DeviceObject = GetDeviceObject(Port);
Modified: trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/filters/k... ============================================================================== --- trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/filters/kmixer/pin.c [iso-8859-1] Fri Mar 13 01:11:53 2009 @@ -163,42 +163,32 @@ PIRP Irp) { PIO_STACK_LOCATION IoStack; - PKSPROPERTY Property; - DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject); + PKSP_PIN Property; + //DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
IoStack = IoGetCurrentIrpStackLocation(Irp);
- if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSPROPERTY) && IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSDATAFORMAT_WAVEFORMATEX)) - { - Property = (PKSPROPERTY)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; - - if (IsEqualGUIDAligned(&Property->Set, &KSPROPSETID_Connection)) + if (IoStack->Parameters.DeviceIoControl.InputBufferLength == sizeof(KSP_PIN) && IoStack->Parameters.DeviceIoControl.OutputBufferLength == sizeof(KSDATAFORMAT_WAVEFORMATEX)) + { + Property = (PKSP_PIN)IoStack->Parameters.DeviceIoControl.Type3InputBuffer; + + if (IsEqualGUIDAligned(&Property->Property.Set, &KSPROPSETID_Connection)) { - if (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT && Property->Flags == KSPROPERTY_TYPE_SET) + if (Property->Property.Id == KSPROPERTY_CONNECTION_DATAFORMAT && Property->Property.Flags == KSPROPERTY_TYPE_SET) { - PKSDATAFORMAT_WAVEFORMATEX WaveFormat2; - PKSDATAFORMAT_WAVEFORMATEX WaveFormat = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX)); - - if (!WaveFormat) - { - Irp->IoStatus.Information = 0; - Irp->IoStatus.Status = STATUS_NO_MEMORY; - IoCompleteRequest(Irp, IO_NO_INCREMENT); - return STATUS_NO_MEMORY; - } - - if (IoStack->FileObject->FsContext2) - { - ExFreePool(IoStack->FileObject->FsContext2); - } - - WaveFormat2 = (PKSDATAFORMAT_WAVEFORMATEX)Irp->UserBuffer; - WaveFormat->WaveFormatEx.nChannels = WaveFormat2->WaveFormatEx.nChannels; - WaveFormat->WaveFormatEx.nSamplesPerSec = WaveFormat2->WaveFormatEx.nSamplesPerSec; - WaveFormat->WaveFormatEx.wBitsPerSample = WaveFormat2->WaveFormatEx.wBitsPerSample; - - IoStack->FileObject->FsContext2 = (PVOID)WaveFormat; - + PKSDATAFORMAT_WAVEFORMATEX Formats; + PKSDATAFORMAT_WAVEFORMATEX WaveFormat; + + Formats = (PKSDATAFORMAT_WAVEFORMATEX)IoStack->FileObject->FsContext2; + WaveFormat = (PKSDATAFORMAT_WAVEFORMATEX)Irp->UserBuffer; + + ASSERT(Property->PinId == 0 || Property->PinId == 1); + ASSERT(Formats); + ASSERT(WaveFormat); + + Formats[Property->PinId].WaveFormatEx.nChannels = WaveFormat->WaveFormatEx.nChannels; + Formats[Property->PinId].WaveFormatEx.wBitsPerSample = WaveFormat->WaveFormatEx.wBitsPerSample; + Formats[Property->PinId].WaveFormatEx.nSamplesPerSec = WaveFormat->WaveFormatEx.nSamplesPerSec;
Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_SUCCESS; @@ -207,7 +197,7 @@ } } } - + DPRINT1("Size %u Expected %u\n",IoStack->Parameters.DeviceIoControl.OutputBufferLength, sizeof(KSDATAFORMAT_WAVEFORMATEX)); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -365,54 +355,34 @@ PIO_STATUS_BLOCK IoStatus, PDEVICE_OBJECT DeviceObject) { - PKSPIN_CONNECT ConnectDetails; PKSSTREAM_HEADER StreamHeader; PVOID BufferOut; ULONG BufferLength; NTSTATUS Status = STATUS_SUCCESS; - LPWSTR PinName = L"{146F1A80-4791-11D0-A5D6-28DB04C10000}\"; - - PKSDATAFORMAT_WAVEFORMATEX BaseFormat, TransformedFormat; + PKSDATAFORMAT_WAVEFORMATEX Formats; + PKSDATAFORMAT_WAVEFORMATEX InputFormat, OutputFormat;
//DPRINT1("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
- - BaseFormat = (PKSDATAFORMAT_WAVEFORMATEX)FileObject->FsContext2; - if (!BaseFormat) - { - DPRINT1("Expected DataFormat\n"); - DbgBreakPoint(); - IoStatus->Status = STATUS_UNSUCCESSFUL; - IoStatus->Information = 0; - return FALSE; - } - - if (FileObject->FileName.Length < wcslen(PinName) + sizeof(KSPIN_CONNECT) + sizeof(KSDATAFORMAT)) - { - DPRINT1("Expected DataFormat\n"); - DbgBreakPoint(); - IoStatus->Status = STATUS_INVALID_PARAMETER; - IoStatus->Information = 0; - return FALSE; - } - - ConnectDetails = (PKSPIN_CONNECT)(FileObject->FileName.Buffer + wcslen(PinName)); - TransformedFormat = (PKSDATAFORMAT_WAVEFORMATEX)(ConnectDetails + 1); + Formats = (PKSDATAFORMAT_WAVEFORMATEX)FileObject->FsContext2; + + InputFormat = Formats; + OutputFormat = (Formats + 1); StreamHeader = (PKSSTREAM_HEADER)Buffer;
#if 0 DPRINT1("Num Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n", - BaseFormat->WaveFormatEx.nChannels, TransformedFormat->WaveFormatEx.nChannels, - BaseFormat->WaveFormatEx.nSamplesPerSec, TransformedFormat->WaveFormatEx.nSamplesPerSec, - BaseFormat->WaveFormatEx.wBitsPerSample, TransformedFormat->WaveFormatEx.wBitsPerSample); -#endif - - if (BaseFormat->WaveFormatEx.wBitsPerSample != TransformedFormat->WaveFormatEx.wBitsPerSample) + InputFormat->WaveFormatEx.nChannels, OutputFormat->WaveFormatEx.nChannels, + InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec, + InputFormat->WaveFormatEx.wBitsPerSample, OutputFormat->WaveFormatEx.wBitsPerSample); +#endif + + if (InputFormat->WaveFormatEx.wBitsPerSample != OutputFormat->WaveFormatEx.wBitsPerSample) { Status = PerformQualityConversion(StreamHeader->Data, StreamHeader->DataUsed, - BaseFormat->WaveFormatEx.wBitsPerSample, - TransformedFormat->WaveFormatEx.wBitsPerSample, + InputFormat->WaveFormatEx.wBitsPerSample, + OutputFormat->WaveFormatEx.wBitsPerSample, &BufferOut, &BufferLength); if (NT_SUCCESS(Status)) @@ -424,10 +394,10 @@ } }
- if (BaseFormat->WaveFormatEx.nSamplesPerSec != TransformedFormat->WaveFormatEx.nSamplesPerSec) + if (InputFormat->WaveFormatEx.nSamplesPerSec != OutputFormat->WaveFormatEx.nSamplesPerSec) { /* sample format conversion must be done in a deferred routine */ - DPRINT1("SampleRate conversion not available yet\n"); + DPRINT1("SampleRate conversion not available yet %u %u\n", InputFormat->WaveFormatEx.nSamplesPerSec, OutputFormat->WaveFormatEx.nSamplesPerSec); return FALSE; }
@@ -457,6 +427,18 @@ { NTSTATUS Status; KSOBJECT_HEADER ObjectHeader; + PKSDATAFORMAT DataFormat; + PIO_STACK_LOCATION IoStack; + + + DataFormat = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX) * 2); + if (!DataFormat) + return STATUS_INSUFFICIENT_RESOURCES; + + RtlZeroMemory(DataFormat, sizeof(KSDATAFORMAT_WAVEFORMATEX) * 2); + + IoStack = IoGetCurrentIrpStackLocation(Irp); + IoStack->FileObject->FsContext2 = (PVOID)DataFormat;
/* allocate object header */ Status = KsAllocateObjectHeader(&ObjectHeader, 0, NULL, Irp, &PinTable);
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] Fri Mar 13 01:11:53 2009 @@ -144,7 +144,7 @@
if (DeviceInfo->DeviceType != WAVE_OUT_DEVICE_TYPE && DeviceInfo->DeviceType != WAVE_IN_DEVICE_TYPE) { - DPRINT1("FIXME: only waveout devices are supported\n"); + DPRINT1("FIXME: only waveout / wavein devices are supported\n"); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); }
@@ -154,7 +154,6 @@ DPRINT1("Invalid device index %u\n", DeviceInfo->DeviceIndex); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); } -
Length = sizeof(KSDATAFORMAT_WAVEFORMATEX) + sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO); InstanceInfo = ExAllocatePool(NonPagedPool, Length); @@ -343,8 +342,6 @@ } } } - else - DPRINT1("KSPROPERTY_PIN_CTYPES index %u failed with %x\n", Index, Status); }
@@ -370,7 +367,7 @@ ULONG BytesReturned; PFILE_OBJECT FileObject;
- DPRINT1("WdmAudControlDeviceState\n"); + //DPRINT1("WdmAudControlDeviceState\n");
Status = ObReferenceObjectByHandle(DeviceInfo->hDevice, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); if (!NT_SUCCESS(Status)) @@ -389,7 +386,7 @@
ObDereferenceObject(FileObject);
- DPRINT1("WdmAudControlDeviceState Status %x\n", Status); + //DPRINT1("WdmAudControlDeviceState Status %x\n", Status); return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); }
@@ -468,7 +465,6 @@
DPRINT("WdmAudCapabilities entered\n");
- Status = GetFilterIdAndPinId(DeviceObject, DeviceInfo, ClientInfo, &FilterId, &PinId); if (!NT_SUCCESS(Status)) { @@ -595,7 +591,7 @@
IoStack = IoGetCurrentIrpStackLocation(Irp);
- DPRINT1("WdmAudDeviceControl entered\n"); + DPRINT("WdmAudDeviceControl entered\n");
if (IoStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(WDMAUD_DEVICE_INFO)) { @@ -621,7 +617,7 @@ } ClientInfo = (PWDMAUD_CLIENT)IoStack->FileObject->FsContext;
- DPRINT1("WdmAudDeviceControl entered\n"); + DPRINT("WdmAudDeviceControl entered\n");
switch(IoStack->Parameters.DeviceIoControl.IoControlCode) {
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/control.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/... ============================================================================== --- trunk/reactos/drivers/wdm/audio/sysaudio/control.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/sysaudio/control.c [iso-8859-1] Fri Mar 13 01:11:53 2009 @@ -33,7 +33,14 @@ { Irp->IoStatus.Information = Length; Irp->IoStatus.Status = Status; - IoCompleteRequest(Irp, IO_NO_INCREMENT); + if (Status != STATUS_PENDING) + { + IoCompleteRequest(Irp, IO_NO_INCREMENT); + } + else + { + IoMarkIrpPending(Irp); + } return Status;
} @@ -139,6 +146,90 @@ return SetIrpIoStatus(Irp, STATUS_SUCCESS, 0); }
+NTSTATUS +SetMixerInputOutputFormat( + IN PFILE_OBJECT FileObject, + IN PKSDATAFORMAT InputFormat, + IN PKSDATAFORMAT OutputFormat) +{ + KSP_PIN PinRequest; + ULONG BytesReturned; + NTSTATUS Status; + + /* re-using pin */ + PinRequest.Property.Set = KSPROPSETID_Connection; + PinRequest.Property.Flags = KSPROPERTY_TYPE_SET; + PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT; + + /* set the input format */ + PinRequest.PinId = 0; + //DPRINT1("InputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", InputFormat, InputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX)); + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, + (PVOID)&PinRequest, + sizeof(KSP_PIN), + (PVOID)InputFormat, + InputFormat->FormatSize, + &BytesReturned); + if (!NT_SUCCESS(Status)) + return Status; + + /* set the the output format */ + PinRequest.PinId = 1; + //DPRINT1("OutputFormat %p Size %u WaveFormatSize %u DataFormat %u WaveEx %u\n", OutputFormat, OutputFormat->FormatSize, sizeof(KSDATAFORMAT_WAVEFORMATEX), sizeof(KSDATAFORMAT), sizeof(WAVEFORMATEX)); + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, + (PVOID)&PinRequest, + sizeof(KSP_PIN), + (PVOID)OutputFormat, + OutputFormat->FormatSize, + &BytesReturned); + return Status; +} + + +NTSTATUS +CreateMixerPinAndSetFormat( + IN HANDLE KMixerHandle, + IN KSPIN_CONNECT *PinConnect, + IN PKSDATAFORMAT InputFormat, + IN PKSDATAFORMAT OutputFormat, + OUT PHANDLE MixerPinHandle, + OUT PFILE_OBJECT *MixerFileObject) +{ + NTSTATUS Status; + HANDLE PinHandle; + PFILE_OBJECT FileObject; + + Status = KsCreatePin(KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &PinHandle); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create Mixer Pin with %x\n", Status); + return STATUS_UNSUCCESSFUL; + } + + Status = ObReferenceObjectByHandle(PinHandle, + GENERIC_READ | GENERIC_WRITE, + IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to get file object with %x\n", Status); + return STATUS_UNSUCCESSFUL; + } + + Status = SetMixerInputOutputFormat(FileObject, InputFormat, OutputFormat); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + ZwClose(PinHandle); + } + + *MixerPinHandle = PinHandle; + *MixerFileObject = FileObject; + return Status; +} + + VOID NTAPI CreatePinWorkerRoutine( @@ -147,22 +238,22 @@ { NTSTATUS Status; PSYSAUDIO_CLIENT AudioClient; - HANDLE RealPinHandle, VirtualPinHandle, MixerPinHandle = NULL; + HANDLE RealPinHandle, VirtualPinHandle; HANDLE Filter; - ULONG NumHandels, BytesReturned; - PFILE_OBJECT FileObject, MixerFileObject = NULL; + ULONG NumHandels; + PFILE_OBJECT FileObject; PSYSAUDIO_PIN_HANDLE ClientPinHandle; PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context; PKSPIN_CONNECT PinConnect = NULL; - KSPROPERTY PinRequest; - PKSDATAFORMAT_WAVEFORMATEX ClientFormat; + PKSDATAFORMAT ClientFormat; + KSP_PIN PinRequest; + ULONG BytesReturned;
Filter = WorkerContext->PinConnect->PinToHandle;
- WorkerContext->PinConnect->PinToHandle = NULL;
- DPRINT1("CreatePinWorkerRoutine entered\n"); + DPRINT("CreatePinWorkerRoutine entered\n");
ASSERT(WorkerContext->Entry); ASSERT(WorkerContext->PinConnect); @@ -170,7 +261,7 @@ ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
PinConnect = WorkerContext->PinConnect; - ClientFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1); + ClientFormat = (PKSDATAFORMAT)(PinConnect + 1);
if (WorkerContext->CreateMixerPin) { @@ -188,8 +279,14 @@ RtlMoveMemory(PinConnect, WorkerContext->PinConnect, sizeof(KSPIN_CONNECT)); RtlMoveMemory((PinConnect + 1), WorkerContext->MixerFormat, WorkerContext->MixerFormat->DataFormat.FormatSize);
- - Status = KsCreatePin(WorkerContext->DeviceExtension->KMixerHandle, PinConnect, GENERIC_READ | GENERIC_WRITE, &MixerPinHandle); + Status = CreateMixerPinAndSetFormat(WorkerContext->DeviceExtension->KMixerHandle, + PinConnect, + (PKSDATAFORMAT)(WorkerContext->PinConnect + 1), + (PKSDATAFORMAT)WorkerContext->MixerFormat, + &WorkerContext->DispatchContext->hMixerPin, + &WorkerContext->DispatchContext->MixerFileObject); + + ExFreePool(WorkerContext->MixerFormat);
if (!NT_SUCCESS(Status)) { @@ -199,10 +296,60 @@ ExFreePool(WorkerContext); return; } - - Status = ObReferenceObjectByHandle(MixerPinHandle, + } + else + { + Status = CreateMixerPinAndSetFormat(WorkerContext->DeviceExtension->KMixerHandle, + WorkerContext->PinConnect, + (PKSDATAFORMAT)(WorkerContext->PinConnect + 1), + (PKSDATAFORMAT)(WorkerContext->PinConnect + 1), + &WorkerContext->DispatchContext->hMixerPin, + &WorkerContext->DispatchContext->MixerFileObject); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to create Mixer Pin with %x\n", Status); + SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0); + ExFreePool(WorkerContext->DispatchContext); + ExFreePool(WorkerContext); + return; + } + } + + if (WorkerContext->CreateRealPin) + { + /* create the real pin */ + DPRINT("Creating real pin\n"); + + if (WorkerContext->CreateMixerPin) + Status = KsCreatePin(WorkerContext->Entry->Handle, PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); + else + Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); + + DPRINT1("Status %x\n", Status); + if (!NT_SUCCESS(Status)) + { + PKSDATAFORMAT_WAVEFORMATEX RequestedFormat = (PKSDATAFORMAT_WAVEFORMATEX)(WorkerContext->PinConnect + 1); + DPRINT1("Failed to create Pin with %x\nNumChannels: %u BitsPerSample %u SampleRate %u\n", Status, + RequestedFormat->WaveFormatEx.nChannels, RequestedFormat->WaveFormatEx.wBitsPerSample, RequestedFormat->WaveFormatEx.nSamplesPerSec); + + if (WorkerContext->CreateMixerPin) + { + /* The mixer pin format should have been accepted */ + ObDereferenceObject(WorkerContext->DispatchContext->MixerFileObject); + ZwClose(WorkerContext->DispatchContext->hMixerPin); + ASSERT(0); + } + + SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0); + ExFreePool(WorkerContext->DispatchContext); + ExFreePool(WorkerContext); + return; + } + + /* get pin file object */ + Status = ObReferenceObjectByHandle(RealPinHandle, GENERIC_READ | GENERIC_WRITE, - IoFileObjectType, KernelMode, (PVOID*)&MixerFileObject, NULL); + IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL);
if (!NT_SUCCESS(Status)) { @@ -213,94 +360,58 @@ return; }
- WorkerContext->DispatchContext->hMixerPin = MixerPinHandle; - WorkerContext->DispatchContext->MixerFileObject = MixerFileObject; - - PinRequest.Set = KSPROPSETID_Connection; - PinRequest.Flags = KSPROPERTY_TYPE_SET; - PinRequest.Id = KSPROPERTY_CONNECTION_DATAFORMAT; - - DPRINT1("ClientFormat %p Channels %u Samples %u Bits %u\n", ClientFormat, ClientFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.wBitsPerSample); - - Status = KsSynchronousIoControlDevice(MixerFileObject, KernelMode, IOCTL_KS_PROPERTY, - (PVOID)&PinRequest, - sizeof(KSPROPERTY), - (PVOID)ClientFormat, - sizeof(KSDATAFORMAT_WAVEFORMATEX), - &BytesReturned); - - } - - if (WorkerContext->CreateRealPin) - { - /* create the real pin */ - DPRINT("Creating real pin\n"); - - if (WorkerContext->CreateMixerPin) - Status = KsCreatePin(WorkerContext->Entry->Handle, PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); - else - Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); - - DPRINT1("Status %x\n", Status); + if (WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount == 1) + { + /* store the pin handle there is the pin can only be instantiated once*/ + WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = RealPinHandle; + } + + WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 0; + WorkerContext->DispatchContext->Handle = RealPinHandle; + WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId; + WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry; + WorkerContext->DispatchContext->FileObject = FileObject; + } + else + { + WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry; + WorkerContext->DispatchContext->Handle = WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle; + WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId; + + /* get pin file object */ + Status = ObReferenceObjectByHandle(WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle, + GENERIC_READ | GENERIC_WRITE, + IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + if (!NT_SUCCESS(Status)) { - DPRINT1("Failed to create Pin with %x\n", Status); + DPRINT1("Failed to get file object with %x %p\n", Status, WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle); SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0); ExFreePool(WorkerContext->DispatchContext); ExFreePool(WorkerContext); return; } - - /* get pin file object */ - Status = ObReferenceObjectByHandle(RealPinHandle, - GENERIC_READ | GENERIC_WRITE, - IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - - DPRINT1("Status %x\n", Status); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get file object with %x\n", Status); - SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0); - ExFreePool(WorkerContext->DispatchContext); - ExFreePool(WorkerContext); - return; - } - - if (WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].MaxPinInstanceCount == 1) - { - /* store the pin handle there is the pin can only be instantiated once*/ - WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle = RealPinHandle; - } - - WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References = 1; - WorkerContext->DispatchContext->Handle = RealPinHandle; - WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId; - WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry; WorkerContext->DispatchContext->FileObject = FileObject; - } - else - { - WorkerContext->DispatchContext->AudioEntry = WorkerContext->Entry; - WorkerContext->DispatchContext->Handle = WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle; - WorkerContext->DispatchContext->PinId = WorkerContext->PinConnect->PinId; - - /* get pin file object */ - Status = ObReferenceObjectByHandle(WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].PinHandle, - GENERIC_READ | GENERIC_WRITE, - IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get file object with %x\n", Status); - SetIrpIoStatus(WorkerContext->Irp, STATUS_UNSUCCESSFUL, 0); - ExFreePool(WorkerContext->DispatchContext); - ExFreePool(WorkerContext); - return; - } - WorkerContext->DispatchContext->FileObject = FileObject; - } - - DPRINT1("creating virtual pin\n"); + + + /* re-using pin */ + PinRequest.Property.Set = KSPROPSETID_Connection; + PinRequest.Property.Flags = KSPROPERTY_TYPE_SET; + PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT; + PinRequest.PinId = PinConnect->PinId; + + if (WorkerContext->MixerFormat) + ClientFormat = (PKSDATAFORMAT)WorkerContext->MixerFormat; + else + ClientFormat = (PKSDATAFORMAT)(WorkerContext->PinConnect + 1); + + /* set the format on the real pin */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSPROPERTY), + (PVOID)ClientFormat, ClientFormat->FormatSize, &BytesReturned); + + } + + DPRINT("creating virtual pin\n"); /* now create the virtual audio pin which is exposed to wdmaud */ Status = KsCreatePin(Filter, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &VirtualPinHandle);
@@ -369,27 +480,28 @@ AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = TRUE; AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = RealPinHandle; AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId; - AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = MixerPinHandle; - + AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = WorkerContext->DispatchContext->hMixerPin; + AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].DispatchContext = WorkerContext->DispatchContext; } else { AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].bHandle = FALSE; AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hPin = VirtualPinHandle; AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].PinId = WorkerContext->PinConnect->PinId; - AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = MixerPinHandle; + AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].hMixer = WorkerContext->DispatchContext->hMixerPin; + AudioClient->Devs[AudioClient->NumDevices -1].ClientHandles[NumHandels].DispatchContext = WorkerContext->DispatchContext; }
/// increase reference count + AudioClient->Devs[AudioClient->NumDevices -1].ClientHandlesCount++; WorkerContext->Entry->Pins[WorkerContext->PinConnect->PinId].References++; - AudioClient->Devs[AudioClient->NumDevices -1].ClientHandlesCount++; }
/* store pin context */ FileObject->FsContext2 = (PVOID)WorkerContext->DispatchContext;
- DPRINT1("Successfully created virtual pin %p\n", VirtualPinHandle); + DPRINT("Successfully created virtual pin %p\n", VirtualPinHandle); *((PHANDLE)WorkerContext->Irp->UserBuffer) = VirtualPinHandle;
SetIrpIoStatus(WorkerContext->Irp, STATUS_SUCCESS, sizeof(HANDLE)); @@ -488,48 +600,97 @@ } }
-NTSTATUS -SetPinFormat( - PKSAUDIO_DEVICE_ENTRY Entry, - KSPIN_CONNECT * PinConnect, - ULONG Length) +BOOL +ComputeCompatibleFormat( + IN PKSAUDIO_DEVICE_ENTRY Entry, + IN ULONG PinId, + IN PSYSAUDIODEVEXT DeviceExtension, + IN PKSDATAFORMAT_WAVEFORMATEX ClientFormat, + OUT PKSDATAFORMAT_WAVEFORMATEX MixerFormat) { + BOOL bFound; + ULONG BytesReturned; KSP_PIN PinRequest; - PFILE_OBJECT FileObject; - ULONG BytesReturned; + PKSDATARANGE_AUDIO AudioRange; NTSTATUS Status; - - /* re-using pin */ - PinRequest.Property.Set = KSPROPSETID_Connection; - PinRequest.Property.Flags = KSPROPERTY_TYPE_SET; - PinRequest.Property.Id = KSPROPERTY_CONNECTION_DATAFORMAT; - PinRequest.PinId = PinConnect->PinId; - - - /* get pin file object */ - Status = ObReferenceObjectByHandle(Entry->Pins[PinConnect->PinId].PinHandle, - GENERIC_READ | GENERIC_WRITE, - IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get pin file object with %x\n", Status); - return Status; - } - - Length -= sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO); - Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSPROPERTY), - (PVOID)(PinConnect + 1), Length, &BytesReturned); - ObDereferenceObject(FileObject); - - if (!NT_SUCCESS(Status)) - { - /* set the format on the mixer pin */ - UNIMPLEMENTED - return STATUS_SUCCESS; - } - - return Status; + ULONG Index; + PKSMULTIPLE_ITEM MultipleItem; + + if (!DeviceExtension->KMixerHandle || !DeviceExtension->KMixerFileObject) + { + DPRINT1("KMixer is not available\n"); + return STATUS_UNSUCCESSFUL; + } + + PinRequest.PinId = PinId; + PinRequest.Property.Set = KSPROPSETID_Pin; + PinRequest.Property.Flags = KSPROPERTY_TYPE_GET; + PinRequest.Property.Id = KSPROPERTY_PIN_DATARANGES; + + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + if (Status != STATUS_BUFFER_TOO_SMALL) + { + DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status); + return STATUS_UNSUCCESSFUL; + } + + MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned); + if (!MultipleItem) + { + return STATUS_NO_MEMORY; + } + + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); + if (!NT_SUCCESS(Status)) + { + DPRINT("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status); + ExFreePool(MultipleItem); + return STATUS_UNSUCCESSFUL; + } + + AudioRange = (PKSDATARANGE_AUDIO)(MultipleItem + 1); + bFound = FALSE; + for(Index = 0; Index < MultipleItem->Count; Index++) + { + if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO)) + { + UNIMPLEMENTED + AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); + } + MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); + MixerFormat->DataFormat.Flags = 0; + MixerFormat->DataFormat.Reserved = 0; + MixerFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; + MixerFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; + MixerFormat->DataFormat.SampleSize = 4; + MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag; + MixerFormat->WaveFormatEx.nChannels = min(AudioRange->MaximumChannels, ClientFormat->WaveFormatEx.nChannels); + MixerFormat->WaveFormatEx.nSamplesPerSec = max(AudioRange->MinimumSampleFrequency, min(AudioRange->MaximumSampleFrequency, ClientFormat->WaveFormatEx.nSamplesPerSec)); + MixerFormat->WaveFormatEx.wBitsPerSample = max(AudioRange->MinimumBitsPerSample, min(AudioRange->MaximumBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample)); + MixerFormat->WaveFormatEx.cbSize = 0; + MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8; + MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8); + + bFound = TRUE; + break; + + AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); + } + ExFreePool(MultipleItem); + + +#if 0 + DPRINT1("\nNum Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n ClientFormat %p", + MixerFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nChannels, + MixerFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.nSamplesPerSec, + MixerFormat->WaveFormatEx.wBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample, ClientFormat); +#endif + + if (bFound) + return STATUS_SUCCESS; + else + return STATUS_NOT_IMPLEMENTED; }
@@ -555,10 +716,9 @@ PDISPATCH_CONTEXT DispatchContext; ULONG Index, SubIndex; BOOL CreateMixerPin; - PKSDATARANGE_AUDIO AudioRange; + ULONG DeviceId; PKSDATAFORMAT_WAVEFORMATEX MixerFormat = NULL, ClientFormat;
- PKSMULTIPLE_ITEM MultipleItem;
IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -611,6 +771,27 @@ DPRINT("Invalid PinId %x\n", PinConnect->PinId); return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); } + +Retry: + /* get the instances count */ + PinRequest.PinId = PinConnect->PinId; + PinRequest.Property.Set = KSPROPSETID_Pin; + PinRequest.Property.Flags = KSPROPERTY_TYPE_GET; + PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES; + + Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned); + if (!NT_SUCCESS(Status)) + { + DPRINT("Property Request KSPROPERTY_PIN_GLOBALCINSTANCES failed with %x\n", Status); + return SetIrpIoStatus(Irp, Status, 0); + } + + if (PinInstances.PossibleCount == 0) + { + /* caller wanted to open an instance-less pin */ + return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); + } +
/* check the format */ PinRequest.PinId = PinConnect->PinId; @@ -620,12 +801,6 @@
CreateMixerPin = FALSE; BytesReturned = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSPIN_CONNECT) - sizeof(SYSAUDIO_INSTANCE_INFO); - if (BytesReturned != sizeof(KSDATAFORMAT_WAVEFORMATEX)) - { - UNIMPLEMENTED - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - ClientFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1);
Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)ClientFormat, BytesReturned, &BytesReturned); @@ -640,136 +815,58 @@ return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); }
- PinRequest.PinId = PinConnect->PinId; - PinRequest.Property.Set = KSPROPSETID_Pin; - PinRequest.Property.Flags = KSPROPERTY_TYPE_GET; - PinRequest.Property.Id = KSPROPERTY_PIN_DATARANGES; - - Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), NULL, 0, &BytesReturned); - if (Status != STATUS_BUFFER_TOO_SMALL) - { - DPRINT1("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - MultipleItem = ExAllocatePool(NonPagedPool, BytesReturned); - if (!MultipleItem) - { - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - MixerFormat = ExAllocatePool(NonPagedPool, sizeof(KSDATAFORMAT_WAVEFORMATEX)); if (!MixerFormat) { - ExFreePool(MultipleItem); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)MultipleItem, BytesReturned, &BytesReturned); + return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); + } + + Status = ComputeCompatibleFormat(Entry, PinConnect->PinId, DeviceExtension, ClientFormat, MixerFormat); if (!NT_SUCCESS(Status)) { - DPRINT("Property Request KSPROPERTY_PIN_DATARANGES failed with %x\n", Status); ExFreePool(MixerFormat); - ExFreePool(MultipleItem); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - CreateMixerPin = FALSE; - AudioRange = (PKSDATARANGE_AUDIO)(MultipleItem + 1); - for(Index = 0; Index < MultipleItem->Count; Index++) - { - if (AudioRange->DataRange.FormatSize != sizeof(KSDATARANGE_AUDIO)) - { - UNIMPLEMENTED - AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); - } - MixerFormat->DataFormat.FormatSize = sizeof(KSDATAFORMAT) + sizeof(WAVEFORMATEX); - MixerFormat->DataFormat.Flags = 0; - MixerFormat->DataFormat.Reserved = 0; - MixerFormat->DataFormat.MajorFormat = KSDATAFORMAT_TYPE_AUDIO; - MixerFormat->DataFormat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - MixerFormat->DataFormat.Specifier = KSDATAFORMAT_SPECIFIER_WAVEFORMATEX; - MixerFormat->DataFormat.SampleSize = 4; - MixerFormat->WaveFormatEx.wFormatTag = ClientFormat->WaveFormatEx.wFormatTag; - MixerFormat->WaveFormatEx.nChannels = min(AudioRange->MaximumChannels, ClientFormat->WaveFormatEx.nChannels); - MixerFormat->WaveFormatEx.nSamplesPerSec = max(AudioRange->MinimumSampleFrequency, min(AudioRange->MaximumSampleFrequency, ClientFormat->WaveFormatEx.nSamplesPerSec)); - MixerFormat->WaveFormatEx.wBitsPerSample = max(AudioRange->MinimumBitsPerSample, min(AudioRange->MaximumBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample)); - MixerFormat->WaveFormatEx.cbSize = 0; - MixerFormat->WaveFormatEx.nBlockAlign = (MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.wBitsPerSample) / 8; - MixerFormat->WaveFormatEx.nAvgBytesPerSec = MixerFormat->WaveFormatEx.nChannels * MixerFormat->WaveFormatEx.nSamplesPerSec * (MixerFormat->WaveFormatEx.wBitsPerSample / 8); - - CreateMixerPin = TRUE; - break; - - AudioRange = (PKSDATARANGE_AUDIO)((PUCHAR)AudioRange + AudioRange->DataRange.FormatSize); - } - ExFreePool(MultipleItem); - if (!CreateMixerPin) - { - ExFreePool(MixerFormat); - DPRINT1("No Format found :(\n"); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } -#if 0 - DPRINT1("\nNum Channels %u Old Channels %u\n SampleRate %u Old SampleRate %u\n BitsPerSample %u Old BitsPerSample %u\n ClientFormat %p", - MixerFormat->WaveFormatEx.nChannels, ClientFormat->WaveFormatEx.nChannels, - MixerFormat->WaveFormatEx.nSamplesPerSec, ClientFormat->WaveFormatEx.nSamplesPerSec, - MixerFormat->WaveFormatEx.wBitsPerSample, ClientFormat->WaveFormatEx.wBitsPerSample, ClientFormat); -#endif - } - - /* get the instances count */ - PinRequest.PinId = PinConnect->PinId; - PinRequest.Property.Set = KSPROPSETID_Pin; - PinRequest.Property.Flags = KSPROPERTY_TYPE_GET; - PinRequest.Property.Id = KSPROPERTY_PIN_CINSTANCES; - - Status = KsSynchronousIoControlDevice(Entry->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinRequest, sizeof(KSP_PIN), (PVOID)&PinInstances, sizeof(KSPIN_CINSTANCES), &BytesReturned); - if (!NT_SUCCESS(Status)) - { - DPRINT("Property Request KSPROPERTY_PIN_GLOBALCINSTANCES failed with %x\n", Status); - if (MixerFormat) - ExFreePool(MixerFormat); - return SetIrpIoStatus(Irp, Status, 0); - } - - if (PinInstances.PossibleCount == 0) - { - /* caller wanted to open an instance-less pin */ - if (MixerFormat) - ExFreePool(MixerFormat); - return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); - } - - if (PinInstances.CurrentCount == PinInstances.PossibleCount) - { - for (Index = 0; Index < ClientInfo->NumDevices; Index++) - { - if (ClientInfo->Devs[Index].DeviceId == InstanceInfo->DeviceNumber) - { - if (ClientInfo->Devs[Index].ClientHandlesCount) + return SetIrpIoStatus(Irp, Status, 0); + } + CreateMixerPin = TRUE; + } + + DeviceId = (ULONG)-1; + + /* scan the clientinfo if the client has already opened device with the specified pin */ + for (Index = 0; Index < ClientInfo->NumDevices; Index++) + { + if (ClientInfo->Devs[Index].DeviceId == InstanceInfo->DeviceNumber) + { + DeviceId = Index; + if (ClientInfo->Devs[Index].ClientHandlesCount) + { + for(SubIndex = 0; SubIndex < ClientInfo->Devs[Index].ClientHandlesCount; SubIndex++) { - for(SubIndex = 0; SubIndex < ClientInfo->Devs[Index].ClientHandlesCount; SubIndex++) + if (ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId == PinConnect->PinId) { - if (ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId == PinConnect->PinId) - { - /* reuse opened pin */ - Length = IoStack->Parameters.DeviceIoControl.InputBufferLength - sizeof(KSPIN_CONNECT) + sizeof(SYSAUDIO_INSTANCE_INFO); - Status = SetPinFormat(Entry, PinConnect, Length); - DPRINT1("Reusing instance handle Status %x\n", Status); - ASSERT(ClientInfo->Devs[Index].ClientHandles[SubIndex].bHandle == FALSE); - *((PHANDLE)Irp->UserBuffer) = ClientInfo->Devs[Index].ClientHandles[SubIndex].hPin; - return SetIrpIoStatus(Irp, Status, sizeof(HANDLE)); - } + /* the pin has been already opened by the client, re-use it */ + ASSERT(ClientInfo->Devs[Index].ClientHandles[SubIndex].bHandle == FALSE); + + DispatchContext = ClientInfo->Devs[Index].ClientHandles[SubIndex].DispatchContext; + ObDereferenceObject(DispatchContext->MixerFileObject); + ObDereferenceObject(DispatchContext->FileObject); + ZwClose(DispatchContext->hMixerPin); + ZwClose(DispatchContext->Handle); + ClientInfo->Devs[Index].ClientHandles[SubIndex].PinId = (ULONG)-1; + goto Retry; } } - - } - } - + } + } + } + + ASSERT(DeviceId != (ULONG)-1); + + if (PinInstances.CurrentCount == PinInstances.PossibleCount) + { /* pin already exists */ ASSERT(Entry->Pins[PinConnect->PinId].PinHandle != NULL); - if (Entry->Pins[PinConnect->PinId].References > 1) + if (Entry->Pins[PinConnect->PinId].References) { /* FIXME need ksmixer */ DPRINT1("Device %u Pin %u References %u is already occupied, try later\n", InstanceInfo->DeviceNumber, PinConnect->PinId, Entry->Pins[PinConnect->PinId].References); @@ -816,28 +913,14 @@ RtlZeroMemory(WorkerContext, sizeof(PIN_WORKER_CONTEXT)); RtlZeroMemory(DispatchContext, sizeof(DISPATCH_CONTEXT));
- if (PinInstances.CurrentCount == PinInstances.PossibleCount) - { - /* re-using pin */ - Status = SetPinFormat(Entry, PinConnect, Length); - if (!NT_SUCCESS(Status)) - { - if (MixerFormat) - ExFreePool(MixerFormat); - IoFreeWorkItem(WorkItem); - ExFreePool(WorkerContext); - ExFreePool(DispatchContext); - return SetIrpIoStatus(Irp, Status, 0); - } - } - else - { - /* create the real pin */ + DPRINT1("PinInstances.CurrentCount %u\n", PinInstances.CurrentCount); + + if (PinInstances.CurrentCount < PinInstances.PossibleCount) + { WorkerContext->CreateRealPin = TRUE; }
/* set up context */ - WorkerContext->DispatchContext = DispatchContext; WorkerContext->Entry = Entry; WorkerContext->Irp = Irp;
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/dispatcher.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/... ============================================================================== --- trunk/reactos/drivers/wdm/audio/sysaudio/dispatcher.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/sysaudio/dispatcher.c [iso-8859-1] Fri Mar 13 01:11:53 2009 @@ -24,7 +24,7 @@ { PIO_STACK_LOCATION IoStack;
- DPRINT("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject); + //DPRINT("Dispatch_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
IoStack = IoGetCurrentIrpStackLocation(Irp); if (IoStack->Parameters.DeviceIoControl.IoControlCode == IOCTL_KS_PROPERTY) @@ -95,6 +95,8 @@ PIO_STACK_LOCATION IoStatus; ULONG Index, SubIndex; PSYSAUDIODEVEXT DeviceExtension; + PDISPATCH_CONTEXT DispatchContext; +
IoStatus = IoGetCurrentIrpStackLocation(Irp);
@@ -105,6 +107,7 @@ DPRINT1("Client %p NumDevices %u\n", Client, Client->NumDevices); for(Index = 0; Index < Client->NumDevices; Index++) { + DPRINT1("Index %u Device %u Handels Count %u\n", Index, Client->Devs[Index].DeviceId, Client->Devs[Index].ClientHandlesCount); if (Client->Devs[Index].ClientHandlesCount) { Entry = GetListEntry(&DeviceExtension->KsAudioDeviceList, Client->Devs[Index].DeviceId); @@ -112,7 +115,9 @@
for(SubIndex = 0; SubIndex < Client->Devs[Index].ClientHandlesCount; SubIndex++) { - ASSERT(Entry->NumberOfPins > Client->Devs[Index].ClientHandles[SubIndex].PinId); + if (Client->Devs[Index].ClientHandles[SubIndex].PinId == (ULONG)-1) + continue; + if (Client->Devs[Index].ClientHandles[SubIndex].bHandle) { DPRINT1("Closing handle %p\n", Client->Devs[Index].ClientHandles[SubIndex].hPin); @@ -125,6 +130,21 @@ /* this is pin which can only be instantiated once * so we just need to release the reference count on that pin */ Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References--; + + DispatchContext = (PDISPATCH_CONTEXT)Client->Devs[Index].ClientHandles[SubIndex].DispatchContext; + ObDereferenceObject(DispatchContext->MixerFileObject); + ObDereferenceObject(DispatchContext->FileObject); + ZwClose(DispatchContext->hMixerPin); + ExFreePool(DispatchContext); + + //DPRINT1("Index %u DeviceIndex %u Pin %u References %u\n", Index, Client->Devs[Index].DeviceId, SubIndex, Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References); + if (!Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].References) + { + DPRINT1("Closing pin %p\n", Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle); + + ZwClose(Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle); + Entry->Pins[Client->Devs[Index].ClientHandles[SubIndex].PinId].PinHandle = NULL; + } } } ExFreePool(Client->Devs[Index].ClientHandles);
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/... ============================================================================== --- trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h [iso-8859-1] Fri Mar 13 01:11:53 2009 @@ -7,6 +7,7 @@ ULONG PinId; HANDLE hPin; HANDLE hMixer; + PVOID DispatchContext; }SYSAUDIO_PIN_HANDLE, *PSYSAUDIO_PIN_HANDLE;