Author: janderwald Date: Wed Mar 11 12:30:33 2009 New Revision: 39946
URL: http://svn.reactos.org/svn/reactos?rev=39946&view=rev Log: - Add kmixer to bootcd - Check if device supports a specified format. When the device doesnt support a format, query its datarange and create a format which it supports and create a kmixer pin which is used to convert the format - Load kmixer.sys when sysaudio starts - Call kmixer when there is work to do. - Bitrate increasing / decreasing is not working at all. (Need to find a working algorithm, volunteers?) - Install kmixer service when an audio adapter is installed
Modified: trunk/reactos/boot/bootdata/packages/reactos.dff trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.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/sysaudio/control.c trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c trunk/reactos/drivers/wdm/audio/sysaudio/dispatcher.c trunk/reactos/drivers/wdm/audio/sysaudio/main.c trunk/reactos/drivers/wdm/audio/sysaudio/pin.c trunk/reactos/drivers/wdm/audio/sysaudio/sysaudio.h trunk/reactos/media/inf/audio.inf
Modified: trunk/reactos/boot/bootdata/packages/reactos.dff URL: http://svn.reactos.org/svn/reactos/trunk/reactos/boot/bootdata/packages/reac... ============================================================================== --- trunk/reactos/boot/bootdata/packages/reactos.dff [iso-8859-1] (original) +++ trunk/reactos/boot/bootdata/packages/reactos.dff [iso-8859-1] Wed Mar 11 12:30:33 2009 @@ -474,6 +474,7 @@ drivers\video\miniport\vbe\vbemp.sys 2 drivers\video\videoprt\videoprt.sys 2
+drivers\wdm\audio\filters\kmixer\kmixer.sys 2 drivers\wdm\audio\sysaudio\sysaudio.sys 2 drivers\wdm\audio\legacy\wdmaud\wdmaud.sys 2 drivers\wdm\audio\backpln\portcls\portcls.sys 2
Modified: trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/backpln/p... ============================================================================== --- trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/backpln/portcls/irpstream.c [iso-8859-1] Wed Mar 11 12:30:33 2009 @@ -66,7 +66,7 @@
if (CurMapping->Irp) { - CurMapping->Irp->IoStatus.Information = CurMapping->Header->DataUsed; + CurMapping->Irp->IoStatus.Information = CurMapping->Header->FrameExtent; CurMapping->Irp->IoStatus.Status = STATUS_SUCCESS; IoCompleteRequest(CurMapping->Irp, IO_SOUND_INCREMENT); }
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] Wed Mar 11 12:30:33 2009 @@ -379,7 +379,9 @@
if (This->Stream) { - This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue); + while(!This->IrpQueue->lpVtbl->CancelBuffers(This->IrpQueue)) + KeStallExecutionProcessor(10); + This->Stream->lpVtbl->SetState(This->Stream, KSSTATE_STOP); This->State = KSSTATE_STOP;
@@ -680,7 +682,7 @@ //DPRINT1("Completing Irp %p\n", Packet->Irp);
Packet->Irp->IoStatus.Status = STATUS_SUCCESS; - Packet->Irp->IoStatus.Information = Packet->Header.DataUsed; + Packet->Irp->IoStatus.Information = Packet->Header.FrameExtent; IoCompleteRequest(Packet->Irp, IO_SOUND_INCREMENT); StatusBlock->Status = STATUS_SUCCESS; }
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] Wed Mar 11 12:30:33 2009 @@ -8,19 +8,172 @@
#include "kmixer.h"
+const GUID KSPROPSETID_Connection = {0x1D58C920L, 0xAC9B, 0x11CF, {0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00}}; + +NTSTATUS +PerformQualityConversion( + PUCHAR Buffer, + ULONG BufferLength, + ULONG OldWidth, + ULONG NewWidth, + PVOID * Result, + PULONG ResultLength) +{ + ULONG Samples; + ULONG Index; + + ASSERT(OldWidth != NewWidth); + + /* FIXME + * This code does not work at all + */ + + Samples = BufferLength / (OldWidth / 8); + DPRINT1("Samples %u BufferLength %u\n", Samples, BufferLength); + + if (OldWidth == 8 && NewWidth == 16) + { + USHORT Sample; + PUSHORT BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(USHORT)); + if (!BufferOut) + return STATUS_INSUFFICIENT_RESOURCES; + + for(Index = 0; Index < Samples; Index++) + { + Sample = Buffer[Index]; + BufferOut[Index] = Sample * 256; + } + *Result = BufferOut; + *ResultLength = Samples * sizeof(USHORT); + DPRINT1("done\n"); + } + else if (OldWidth == 8 && NewWidth == 32) + { + PULONG BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(ULONG)); + if (!BufferOut) + return STATUS_INSUFFICIENT_RESOURCES; + + for(Index = 0; Index < Samples; Index++) + { + BufferOut[Index] = Buffer[Index] * 16777216; + } + *Result = BufferOut; + *ResultLength = Samples * sizeof(ULONG); + } + else if (OldWidth == 16 && NewWidth == 32) + { + PULONG BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(ULONG)); + if (!BufferOut) + return STATUS_INSUFFICIENT_RESOURCES; + + for(Index = 0; Index < Samples; Index++) + { + BufferOut[Index] = Buffer[Index] * 65536; + } + *Result = BufferOut; + *ResultLength = Samples * sizeof(ULONG); + } + + else if (OldWidth == 16 && NewWidth == 8) + { + PUCHAR BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(UCHAR)); + if (!BufferOut) + return STATUS_INSUFFICIENT_RESOURCES; + + for(Index = 0; Index < Samples; Index++) + { + BufferOut[Index] = (Buffer[Index] / 256) & 0xFF; + } + *Result = BufferOut; + *ResultLength = Samples * sizeof(UCHAR); + } + else if (OldWidth == 32 && NewWidth == 8) + { + PUCHAR BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(UCHAR)); + if (!BufferOut) + return STATUS_INSUFFICIENT_RESOURCES; + + for(Index = 0; Index < Samples; Index++) + { + BufferOut[Index] = (Buffer[Index] / 16777216) & 0xFF; + } + *Result = BufferOut; + *ResultLength = Samples * sizeof(UCHAR); + } + else if (OldWidth == 32 && NewWidth == 16) + { + PUSHORT BufferOut = ExAllocatePool(NonPagedPool, Samples * sizeof(USHORT)); + if (!BufferOut) + return STATUS_INSUFFICIENT_RESOURCES; + + for(Index = 0; Index < Samples; Index++) + { + BufferOut[Index] = (Buffer[Index] / 65536) & 0xFFFF; + } + *Result = BufferOut; + *ResultLength = Samples * sizeof(USHORT); + } + else + { + DPRINT1("Not implemented conversion OldWidth %u NewWidth %u\n", OldWidth, NewWidth); + return STATUS_NOT_IMPLEMENTED; + } + + return STATUS_SUCCESS; +} + + NTSTATUS NTAPI Pin_fnDeviceIoControl( PDEVICE_OBJECT DeviceObject, PIRP Irp) { + PIO_STACK_LOCATION IoStack; + PKSPROPERTY Property; DPRINT1("Pin_fnDeviceIoControl called DeviceObject %p Irp %p\n", DeviceObject);
- //TODO - // silverblade - // Perform Sample Rate Conversion - // Stream Mixing - // Up/down sampling + 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 (Property->Id == KSPROPERTY_CONNECTION_DATAFORMAT && 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; + + + Irp->IoStatus.Information = 0; + Irp->IoStatus.Status = STATUS_SUCCESS; + IoCompleteRequest(Irp, IO_NO_INCREMENT); + return STATUS_SUCCESS; + } + } + }
Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_UNSUCCESSFUL; @@ -179,9 +332,73 @@ 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; + DPRINT1("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
- return FALSE; + + 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); + StreamHeader = (PKSSTREAM_HEADER)Buffer; + + 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); + + if (BaseFormat->WaveFormatEx.wBitsPerSample != TransformedFormat->WaveFormatEx.wBitsPerSample) + { + Status = PerformQualityConversion(StreamHeader->Data, + StreamHeader->DataUsed, + BaseFormat->WaveFormatEx.wBitsPerSample, + TransformedFormat->WaveFormatEx.wBitsPerSample, + &BufferOut, + &BufferLength); + if (NT_SUCCESS(Status)) + { + DPRINT1("Old BufferSize %u NewBufferSize %u\n", StreamHeader->DataUsed, BufferLength); + ExFreePool(StreamHeader->Data); + StreamHeader->Data = BufferOut; + StreamHeader->DataUsed = BufferLength; + } + } + + if (BaseFormat->WaveFormatEx.nSamplesPerSec != TransformedFormat->WaveFormatEx.nSamplesPerSec) + { + /* sample format conversion must be done in a deferred routine */ + return FALSE; + } + + if (NT_SUCCESS(Status)) + return TRUE; + else + return TRUE; }
static KSDISPATCH_TABLE PinTable =
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] Wed Mar 11 12:30:33 2009 @@ -21,7 +21,9 @@ const GUID KSPROPSETID_General = {0x1464EDA5L, 0x6A8F, 0x11D1, {0x9A, 0xA7, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}}; 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 KSDATAFORMAT_TYPE_AUDIO = {0x73647561L, 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}};
NTSTATUS SetIrpIoStatus( @@ -145,13 +147,18 @@ { NTSTATUS Status; PSYSAUDIO_CLIENT AudioClient; - HANDLE RealPinHandle, VirtualPinHandle; + HANDLE RealPinHandle, VirtualPinHandle, MixerPinHandle = NULL; HANDLE Filter; - ULONG NumHandels; - PFILE_OBJECT FileObject; + ULONG NumHandels, BytesReturned; + PFILE_OBJECT FileObject, MixerFileObject = NULL; PSYSAUDIO_PIN_HANDLE ClientPinHandle; PPIN_WORKER_CONTEXT WorkerContext = (PPIN_WORKER_CONTEXT)Context; + PKSPIN_CONNECT PinConnect = NULL; + KSPROPERTY PinRequest; + PKSDATAFORMAT_WAVEFORMATEX ClientFormat; + Filter = WorkerContext->PinConnect->PinToHandle; +
WorkerContext->PinConnect->PinToHandle = NULL;
@@ -162,11 +169,78 @@ ASSERT(WorkerContext->Entry->Pins); ASSERT(WorkerContext->Entry->NumberOfPins > WorkerContext->PinConnect->PinId);
+ PinConnect = WorkerContext->PinConnect; + ClientFormat = (PKSDATAFORMAT_WAVEFORMATEX)(PinConnect + 1); + + if (WorkerContext->CreateMixerPin) + { + PinConnect = ExAllocatePool(NonPagedPool, sizeof(KSPIN_CONNECT) + WorkerContext->MixerFormat->DataFormat.FormatSize); + if (!PinConnect) + { + /* no memory */ + SetIrpIoStatus(WorkerContext->Irp, STATUS_NO_MEMORY, 0); + ExFreePool(WorkerContext->DispatchContext); + ExFreePool(WorkerContext->MixerFormat); + ExFreePool(WorkerContext); + return; + } + + 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); + + 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; + } + + Status = ObReferenceObjectByHandle(MixerPinHandle, + GENERIC_READ | GENERIC_WRITE, + IoFileObjectType, KernelMode, (PVOID*)&MixerFileObject, 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->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"); - Status = KsCreatePin(WorkerContext->Entry->Handle, WorkerContext->PinConnect, GENERIC_READ | GENERIC_WRITE, &RealPinHandle); + + 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)) { @@ -295,12 +369,15 @@ 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; + } 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; }
/// increase reference count @@ -428,6 +505,7 @@ 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, @@ -443,6 +521,13 @@ 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; } @@ -469,6 +554,11 @@ PPIN_WORKER_CONTEXT WorkerContext; PDISPATCH_CONTEXT DispatchContext; ULONG Index, SubIndex; + BOOL CreateMixerPin; + PKSDATARANGE_AUDIO AudioRange; + PKSDATAFORMAT_WAVEFORMATEX MixerFormat = NULL, ClientFormat; + + PKSMULTIPLE_ITEM MultipleItem;
IoStack = IoGetCurrentIrpStackLocation(Irp);
@@ -522,6 +612,113 @@ return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); }
+ /* check the format */ + PinRequest.PinId = PinConnect->PinId; + PinRequest.Property.Set = KSPROPSETID_Pin; + PinRequest.Property.Flags = KSPROPERTY_TYPE_SET; + PinRequest.Property.Id = KSPROPERTY_PIN_PROPOSEDATAFORMAT; + + 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); + if (!NT_SUCCESS(Status)) + { + //DPRINT("Property Request KSPROPERTY_PIN_PROPOSEDATAFORMAT failed with %x\n", Status); + + if (!DeviceExtension->KMixerHandle || !DeviceExtension->KMixerFileObject) + { + DPRINT1("KMixer is not available\n"); + DbgBreakPoint(); + 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); + 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; @@ -531,12 +728,16 @@ 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); }
@@ -572,6 +773,8 @@ { /* 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); + if (MixerFormat) + ExFreePool(MixerFormat); return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); } } @@ -579,6 +782,8 @@ WorkItem = IoAllocateWorkItem(DeviceObject); if (!WorkItem) { + if (MixerFormat) + ExFreePool(MixerFormat); Irp->IoStatus.Information = 0; Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; IoCompleteRequest(Irp, IO_NO_INCREMENT); @@ -590,6 +795,8 @@ if (!WorkerContext) { /* invalid parameters */ + if (MixerFormat) + ExFreePool(MixerFormat); IoFreeWorkItem(WorkItem); return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); } @@ -599,6 +806,8 @@ if (!DispatchContext) { /* invalid parameters */ + if (MixerFormat) + ExFreePool(MixerFormat); IoFreeWorkItem(WorkItem); ExFreePool(WorkerContext); return SetIrpIoStatus(Irp, STATUS_NO_MEMORY, 0); @@ -613,6 +822,8 @@ Status = SetPinFormat(Entry, PinConnect, Length); if (!NT_SUCCESS(Status)) { + if (MixerFormat) + ExFreePool(MixerFormat); IoFreeWorkItem(WorkItem); ExFreePool(WorkerContext); ExFreePool(DispatchContext); @@ -632,6 +843,9 @@ WorkerContext->Irp = Irp; WorkerContext->PinConnect = PinConnect; WorkerContext->AudioClient = ClientInfo; + WorkerContext->CreateMixerPin = CreateMixerPin; + WorkerContext->DeviceExtension = DeviceExtension; + WorkerContext->MixerFormat = MixerFormat;
DPRINT("Queing Irp %p\n", Irp); /* queue the work item */
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/... ============================================================================== --- trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/sysaudio/deviface.c [iso-8859-1] Wed Mar 11 12:30:33 2009 @@ -106,8 +106,51 @@ DPRINT1("Num Pins %u Num WaveIn Pins %u Name WaveOut Pins %u\n", DeviceEntry->NumberOfPins, DeviceEntry->NumWaveInPin, DeviceEntry->NumWaveOutPin); }
- - +NTSTATUS +OpenDevice( + IN PUNICODE_STRING DeviceName, + IN PHANDLE HandleOut, + IN PFILE_OBJECT * FileObjectOut) +{ + NTSTATUS Status; + HANDLE NodeHandle; + PFILE_OBJECT FileObject; + OBJECT_ATTRIBUTES ObjectAttributes; + IO_STATUS_BLOCK IoStatusBlock; + + InitializeObjectAttributes(&ObjectAttributes, DeviceName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); + + Status = ZwCreateFile(&NodeHandle, + GENERIC_READ | GENERIC_WRITE, + &ObjectAttributes, + &IoStatusBlock, + NULL, + 0, + 0, + FILE_OPEN, + FILE_SYNCHRONOUS_IO_NONALERT, + NULL, + 0); + + + if (!NT_SUCCESS(Status)) + { + DPRINT1("ZwCreateFile failed with %x\n", Status); + return Status; + } + + Status = ObReferenceObjectByHandle(NodeHandle, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); + if (!NT_SUCCESS(Status)) + { + ZwClose(NodeHandle); + DPRINT1("ObReferenceObjectByHandle failed with %x\n", Status); + return Status; + } + + *HandleOut = NodeHandle; + *FileObjectOut = FileObject; + return Status; +}
NTSTATUS NTAPI @@ -129,11 +172,7 @@ { /* a new device has arrived */
- PFILE_OBJECT FileObject = NULL; PKSAUDIO_DEVICE_ENTRY DeviceEntry; - HANDLE NodeHandle; - IO_STATUS_BLOCK IoStatusBlock; - OBJECT_ATTRIBUTES ObjectAttributes; PIO_WORKITEM WorkItem;
DeviceEntry = ExAllocatePool(NonPagedPool, sizeof(KSAUDIO_DEVICE_ENTRY)); @@ -172,21 +211,7 @@
DPRINT1("Sym %wZ\n", &DeviceEntry->DeviceName);
- InitializeObjectAttributes(&ObjectAttributes, &DeviceEntry->DeviceName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); - - Status = ZwCreateFile(&NodeHandle, - GENERIC_READ | GENERIC_WRITE, - &ObjectAttributes, - &IoStatusBlock, - NULL, - 0, - 0, - FILE_OPEN, - FILE_SYNCHRONOUS_IO_NONALERT, - NULL, - 0); - - + Status = OpenDevice(&DeviceEntry->DeviceName, &DeviceEntry->Handle, &DeviceEntry->FileObject); if (!NT_SUCCESS(Status)) { DPRINT1("ZwCreateFile failed with %x\n", Status); @@ -194,19 +219,7 @@ return Status; }
- Status = ObReferenceObjectByHandle(NodeHandle, GENERIC_READ | GENERIC_WRITE, IoFileObjectType, KernelMode, (PVOID*)&FileObject, NULL); - if (!NT_SUCCESS(Status)) - { - ZwClose(NodeHandle); - ExFreePool(DeviceEntry); - DPRINT1("ObReferenceObjectByHandle failed with %x\n", Status); - return Status; - } - - DeviceEntry->Handle = NodeHandle; - DeviceEntry->FileObject = FileObject; - - DPRINT1("Successfully opened audio device %u handle %p file object %p device object %p\n", DeviceExtension->KsAudioDeviceList, NodeHandle, FileObject, FileObject->DeviceObject); + DPRINT1("Successfully opened audio device %u handle %p file object %p device object %p\n", DeviceExtension->KsAudioDeviceList, DeviceEntry->Handle, DeviceEntry->FileObject, DeviceEntry->FileObject->DeviceObject); DeviceExtension->NumberOfKsAudioDevices++;
WorkItem = IoAllocateWorkItem(DeviceObject);
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] Wed Mar 11 12:30:33 2009 @@ -334,3 +334,27 @@ return Status; }
+NTSTATUS +SysAudioOpenKMixer( + IN SYSAUDIODEVEXT *DeviceExtension) +{ + NTSTATUS Status; + + UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\Device\kmixer"); + UNICODE_STRING DevicePath = RTL_CONSTANT_STRING(L"\Registry\Machine\System\CurrentControlSet\Services\kmixer"); + + Status = ZwLoadDriver(&DevicePath); + + if (NT_SUCCESS(Status)) + { + Status = OpenDevice(&DeviceName, &DeviceExtension->KMixerHandle, &DeviceExtension->KMixerFileObject); + if (!NT_SUCCESS(Status)) + { + DeviceExtension->KMixerHandle = NULL; + DeviceExtension->KMixerFileObject = NULL; + } + } + + DPRINT("Status %lx KMixerHandle %p KMixerFileObject %p\n", Status, DeviceExtension->KMixerHandle, DeviceExtension->KMixerFileObject); + return STATUS_SUCCESS; +}
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/... ============================================================================== --- trunk/reactos/drivers/wdm/audio/sysaudio/main.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/sysaudio/main.c [iso-8859-1] Wed Mar 11 12:30:33 2009 @@ -140,6 +140,13 @@ goto cleanup; }
+ Status = SysAudioOpenKMixer(DeviceExtension); + if (!NT_SUCCESS(Status)) + { + DPRINT1("SysAudioOpenKMixer failed with %x\n", Status); + goto cleanup; + } + /* set io flags */ DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; /* clear initializing flag */
Modified: trunk/reactos/drivers/wdm/audio/sysaudio/pin.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/sysaudio/... ============================================================================== --- trunk/reactos/drivers/wdm/audio/sysaudio/pin.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/sysaudio/pin.c [iso-8859-1] Wed Mar 11 12:30:33 2009 @@ -222,6 +222,18 @@ //DPRINT1("Pin_fnFastWrite called DeviceObject %p Irp %p\n", DeviceObject);
Context = (PDISPATCH_CONTEXT)FileObject->FsContext2; + +#if 1 + if (Context->hMixerPin && Context->MixerFileObject) + { + Status = KsStreamIo(Context->MixerFileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Mixing stream failed with %lx\n", Status); + return FALSE; + } + } +#endif Status = KsStreamIo(Context->FileObject, NULL, NULL, NULL, NULL, 0, IoStatus, Buffer, Length, KSSTREAM_WRITE, KernelMode); if (Status == STATUS_SUCCESS) return TRUE;
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] Wed Mar 11 12:30:33 2009 @@ -6,6 +6,7 @@ BOOL bHandle; ULONG PinId; HANDLE hPin; + HANDLE hMixer; }SYSAUDIO_PIN_HANDLE, *PSYSAUDIO_PIN_HANDLE;
@@ -62,6 +63,10 @@ PVOID KsAudioNotificationEntry; PVOID EchoCancelNotificationEntry; KMUTEX Mutex; + + PFILE_OBJECT KMixerFileObject; + HANDLE KMixerHandle; + }SYSAUDIODEVEXT, *PSYSAUDIODEVEXT;
typedef struct @@ -71,16 +76,21 @@ ULONG PinId; PKSAUDIO_DEVICE_ENTRY AudioEntry;
+ HANDLE hMixerPin; + PFILE_OBJECT MixerFileObject; }DISPATCH_CONTEXT, *PDISPATCH_CONTEXT;
typedef struct { PIRP Irp; BOOL CreateRealPin; + BOOL CreateMixerPin; PKSAUDIO_DEVICE_ENTRY Entry; KSPIN_CONNECT * PinConnect; PDISPATCH_CONTEXT DispatchContext; PSYSAUDIO_CLIENT AudioClient; + PSYSAUDIODEVEXT DeviceExtension; + PKSDATAFORMAT_WAVEFORMATEX MixerFormat; }PIN_WORKER_CONTEXT, *PPIN_WORKER_CONTEXT;
NTSTATUS @@ -101,6 +111,16 @@ PDEVICE_OBJECT DeviceObject, PIRP Irp);
+NTSTATUS +SysAudioOpenKMixer( + IN SYSAUDIODEVEXT *DeviceExtension); + +NTSTATUS +OpenDevice( + IN PUNICODE_STRING DeviceName, + IN PHANDLE HandleOut, + IN PFILE_OBJECT * FileObjectOut); + PKSAUDIO_DEVICE_ENTRY GetListEntry( IN PLIST_ENTRY Head,
Modified: trunk/reactos/media/inf/audio.inf URL: http://svn.reactos.org/svn/reactos/trunk/reactos/media/inf/audio.inf?rev=399... ============================================================================== --- trunk/reactos/media/inf/audio.inf [iso-8859-1] (original) +++ trunk/reactos/media/inf/audio.inf [iso-8859-1] Wed Mar 11 12:30:33 2009 @@ -34,20 +34,28 @@ wdmaud.sys portcls.sys drmk.sys +kmixer.sys
[Audio.CopyFiles.UserMode] wdmaud.drv ksuser.dll
[Audio_Inst.NT.Services] -AddService = wdmaud, , wdmaud_Service_Inst -AddService = sysaudio, , sysaudio_Service_Inst +AddService = wdmaud,,wdmaud_Service_Inst +AddService = sysaudio,,sysaudio_Service_Inst +AddService = kmixer,,kmixer_Service_Inst
[wdmaud_Service_Inst] ServiceType = 1 StartType = 3 ErrorControl = 0 ServiceBinary = %12%\wdmaud.sys + +[kmixer_Service_Inst] +ServiceType = 1 +StartType = 3 +ErrorControl = 0 +ServiceBinary = %12%\kmixer.sys
[sysaudio_Service_Inst] ServiceType = 1