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/rea…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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/…
==============================================================================
--- 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=39…
==============================================================================
--- 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