[ros-diffs] [janderwald] 39946: - 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

janderwald at svn.reactos.org janderwald at svn.reactos.org
Wed Mar 11 10:30:34 CET 2009


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/reactos.dff?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/portcls/irpstream.c?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/portcls/pin_wavecyclic.c?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/kmixer/pin.c?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/control.c?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/deviface.c?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/dispatcher.c?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/main.c?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/pin.c?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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/sysaudio.h?rev=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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=39946&r1=39945&r2=39946&view=diff
==============================================================================
--- 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



More information about the Ros-diffs mailing list