Author: janderwald Date: Tue Sep 29 14:26:48 2009 New Revision: 43224
URL: http://svn.reactos.org/svn/reactos?rev=43224&view=rev Log: - Implement enumerating mixer source and destination lines
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/control.c [iso-8859-1] Tue Sep 29 14:26:48 2009 @@ -319,9 +319,11 @@ KSPIN_DATAFLOW DataFlow; PWDMAUD_DEVICE_EXTENSION DeviceExtension;
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - DeviceInfo->DeviceCount = GetNumOfMixerDevices(DeviceObject); + DeviceInfo->DeviceCount = DeviceExtension->MixerInfoCount; return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); }
@@ -336,7 +338,7 @@ Pin.Property.Id = KSPROPERTY_SYSAUDIO_DEVICE_COUNT; Pin.Property.Flags = KSPROPERTY_TYPE_GET;
- DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&Count, sizeof(ULONG), &BytesReturned); if (!NT_SUCCESS(Status)) { @@ -706,9 +708,11 @@
DPRINT("WdmAudCapabilities entered\n");
+ DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + if (DeviceInfo->DeviceType == MIXER_DEVICE_TYPE) { - Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo); + Status = WdmAudMixerCapabilities(DeviceObject, DeviceInfo, ClientInfo, DeviceExtension); return SetIrpIoStatus(Irp, Status, sizeof(WDMAUD_DEVICE_INFO)); }
@@ -727,7 +731,7 @@
RtlZeroMemory(&ComponentId, sizeof(KSCOMPONENTID));
- DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + Status = KsSynchronousIoControlDevice(DeviceExtension->FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&PinProperty, sizeof(KSP_PIN), (PVOID)&ComponentId, sizeof(KSCOMPONENTID), &BytesReturned); if (NT_SUCCESS(Status)) {
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/entry.c [iso-8859-1] Tue Sep 29 14:26:48 2009 @@ -76,6 +76,9 @@ return Status; }
+ Status = WdmAudMixerInitialize(DeviceObject); + DPRINT("WdmAudMixerInitialize Status %x\n", Status); + DeviceObject->Flags |= DO_DIRECT_IO | DO_POWER_PAGABLE; DeviceObject->Flags &= ~ DO_DEVICE_INITIALIZING;
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/mixer.c [iso-8859-1] Tue Sep 29 14:26:48 2009 @@ -10,6 +10,88 @@
const GUID KSNODETYPE_DAC = {0x507AE360L, 0xC554, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; const GUID KSNODETYPE_ADC = {0x4D837FE0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_AGC = {0xE88C9BA0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_LOUDNESS = {0x41887440L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_MUTE = {0x02B223C0L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_TONE = {0x7607E580L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_VOLUME = {0x3A5ACC00L, 0xC557, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_PEAKMETER = {0xa085651e, 0x5f0d, 0x4b36, {0xa8, 0x69, 0xd1, 0x95, 0xd6, 0xab, 0x4b, 0x9e}}; +const GUID KSNODETYPE_MUX = {0x2CEAF780, 0xC556, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_STEREO_WIDE = {0xA9E69800L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_CHORUS = {0x20173F20L, 0xC559, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_REVERB = {0xEF0328E0L, 0xC558, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; +const GUID KSNODETYPE_SUPERMIX = {0xE573ADC0L, 0xC555, 0x11D0, {0x8A, 0x2B, 0x00, 0xA0, 0xC9, 0x25, 0x5A, 0xC1}}; + + +LPMIXERLINE_SOURCE +GetSourceMixerLine( + LPMIXER_INFO MixerInfo, + DWORD dwSource) +{ + PLIST_ENTRY Entry; + LPMIXERLINE_SOURCE MixerLineSrc; + + /* get first entry */ + Entry = MixerInfo->SourceLineList.Flink; + + while(Entry != &MixerInfo->SourceLineList) + { + MixerLineSrc = (LPMIXERLINE_SOURCE)CONTAINING_RECORD(Entry, MIXERLINE_SOURCE, Entry); + DPRINT("dwSource %x dwSource %x\n", MixerLineSrc->Line.dwSource, dwSource); + if (MixerLineSrc->Line.dwSource == dwSource) + return MixerLineSrc; + + Entry = Entry->Flink; + } + + return NULL; +} + +LPMIXERLINE_SOURCE +GetSourceMixerLineByLineId( + LPMIXER_INFO MixerInfo, + DWORD dwLineID) +{ + PLIST_ENTRY Entry; + LPMIXERLINE_SOURCE MixerLineSrc; + + /* get first entry */ + Entry = MixerInfo->SourceLineList.Flink; + + while(Entry != &MixerInfo->SourceLineList) + { + MixerLineSrc = (LPMIXERLINE_SOURCE)CONTAINING_RECORD(Entry, MIXERLINE_SOURCE, Entry); + DPRINT("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID, dwLineID); + if (MixerLineSrc->Line.dwLineID == dwLineID) + return MixerLineSrc; + + Entry = Entry->Flink; + } + + return NULL; +} + + + +ULONG +GetPinCount( + IN PFILE_OBJECT FileObject) +{ + KSPROPERTY Pin; + NTSTATUS Status; + ULONG NumPins, BytesReturned; + + Pin.Flags = KSPROPERTY_TYPE_GET; + Pin.Set = KSPROPSETID_Pin; + Pin.Id = KSPROPERTY_PIN_CTYPES; + + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSPROPERTY), (PVOID)&NumPins, sizeof(ULONG), &BytesReturned); + if (!NT_SUCCESS(Status)) + return 0; + + return NumPins; +} +
ULONG GetSysAudioDeviceCount( @@ -84,6 +166,40 @@ }
NTSTATUS +OpenDevice( + IN LPWSTR Device, + OUT PHANDLE DeviceHandle, + OUT PFILE_OBJECT * FileObject) +{ + NTSTATUS Status; + HANDLE hDevice; + + /* now open the device */ + Status = WdmAudOpenSysAudioDevice(Device, &hDevice); + + if (!NT_SUCCESS(Status)) + { + return Status; + } + + *DeviceHandle = hDevice; + + if (FileObject) + { + Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL); + + if (!NT_SUCCESS(Status)) + { + ZwClose(hDevice); + } + } + + return Status; + +} + + +NTSTATUS OpenSysAudioDeviceByIndex( IN PDEVICE_OBJECT DeviceObject, IN ULONG DeviceIndex, @@ -92,41 +208,23 @@ { LPWSTR Device = NULL; NTSTATUS Status; - HANDLE hDevice;
Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, &Device); if (!NT_SUCCESS(Status)) return Status;
- /* now open the device */ - Status = WdmAudOpenSysAudioDevice(Device, &hDevice); + Status = OpenDevice(Device, DeviceHandle, FileObject);
/* free device buffer */ ExFreePool(Device);
- if (!NT_SUCCESS(Status)) - { - return Status; - } - - *DeviceHandle = hDevice; - - if (FileObject) - { - Status = ObReferenceObjectByHandle(hDevice, FILE_READ_DATA | FILE_WRITE_DATA, IoFileObjectType, KernelMode, (PVOID*)FileObject, NULL); - - if (!NT_SUCCESS(Status)) - { - ZwClose(hDevice); - } - } - return Status; }
NTSTATUS -GetFilterNodeTypes( - PFILE_OBJECT FileObject, +GetFilterNodeProperty( + IN PFILE_OBJECT FileObject, + IN ULONG PropertyId, PKSMULTIPLE_ITEM * Item) { NTSTATUS Status; @@ -135,7 +233,7 @@ KSPROPERTY Property;
/* setup query request */ - Property.Id = KSPROPERTY_TOPOLOGY_NODES; + Property.Id = PropertyId; Property.Flags = KSPROPERTY_TYPE_GET; Property.Set = KSPROPSETID_Topology;
@@ -214,20 +312,803 @@ }
ULONG -GetNumOfMixerDevices( - IN PDEVICE_OBJECT DeviceObject) -{ - ULONG DeviceCount, Index, Count; +GetControlTypeFromTopologyNode( + IN LPGUID NodeType) +{ + if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_AGC)) + { + // automatic gain control + return MIXERCONTROL_CONTROLTYPE_ONOFF; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_LOUDNESS)) + { + // loudness control + return MIXERCONTROL_CONTROLTYPE_LOUDNESS; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUTE )) + { + // mute control + return MIXERCONTROL_CONTROLTYPE_MUTE; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_TONE)) + { + // tpne control + //FIXME + // MIXERCONTROL_CONTROLTYPE_ONOFF if KSPROPERTY_AUDIO_BASS_BOOST is supported + // MIXERCONTROL_CONTROLTYPE_BASS if KSPROPERTY_AUDIO_BASS is supported + // MIXERCONTROL_CONTROLTYPE_TREBLE if KSPROPERTY_AUDIO_TREBLE is supported + UNIMPLEMENTED; + return MIXERCONTROL_CONTROLTYPE_ONOFF; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_VOLUME)) + { + // volume control + return MIXERCONTROL_CONTROLTYPE_VOLUME; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_PEAKMETER)) + { + // peakmeter control + return MIXERCONTROL_CONTROLTYPE_PEAKMETER; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX)) + { + // mux control + return MIXERCONTROL_CONTROLTYPE_MUX; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_MUX)) + { + // mux control + return MIXERCONTROL_CONTROLTYPE_MUX; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_STEREO_WIDE)) + { + // stero wide control + return MIXERCONTROL_CONTROLTYPE_FADER; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_CHORUS)) + { + // chorus control + return MIXERCONTROL_CONTROLTYPE_FADER; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_REVERB)) + { + // reverb control + return MIXERCONTROL_CONTROLTYPE_FADER; + } + else if (IsEqualGUIDAligned(NodeType, (LPGUID)&KSNODETYPE_SUPERMIX)) + { + // supermix control + // MIXERCONTROL_CONTROLTYPE_MUTE if KSPROPERTY_AUDIO_MUTE is supported + UNIMPLEMENTED; + return MIXERCONTROL_CONTROLTYPE_VOLUME; + } + UNIMPLEMENTED + return 0; +} + +NTSTATUS +GetPhysicalConnection( + IN PFILE_OBJECT FileObject, + IN ULONG PinId, + OUT PKSPIN_PHYSICALCONNECTION *OutConnection) +{ + KSP_PIN Pin; + NTSTATUS Status; + ULONG BytesReturned; + PKSPIN_PHYSICALCONNECTION Connection; + + /* setup the request */ + Pin.Property.Flags = KSPROPERTY_TYPE_GET; + Pin.Property.Id = KSPROPERTY_PIN_PHYSICALCONNECTION; + Pin.Property.Set = KSPROPSETID_Pin; + Pin.PinId = PinId; + + /* query the pin for the physical connection */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + + if (Status == STATUS_NOT_FOUND) + { + /* pin does not have a physical connection */ + return Status; + } + + Connection = ExAllocatePool(NonPagedPool, BytesReturned); + if (!Connection) + { + /* not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* query the pin for the physical connection */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Connection, BytesReturned, &BytesReturned); + if (!NT_SUCCESS(Status)) + { + /* failed to query the physical connection */ + ExFreePool(Connection); + return Status; + } + + /* store connection */ + *OutConnection = Connection; + return Status; +} + +NTSTATUS +GetNodeIndexes( + IN PKSMULTIPLE_ITEM MultipleItem, + IN ULONG NodeIndex, + IN ULONG bNode, + IN ULONG bFrom, + OUT PULONG NodeReferenceCount, + OUT PULONG *NodeReference) +{ + ULONG Index, Count = 0; + PKSTOPOLOGY_CONNECTION Connection; + PULONG Refs; + + /* KSMULTIPLE_ITEM is followed by several KSTOPOLOGY_CONNECTION */ + Connection = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1); + + /* first count all referenced nodes */ + for(Index = 0; Index < MultipleItem->Count; Index++) + { + //DPRINT1("FromPin %u FromNode %u ToPin %u ToNode %u\n", Connection->FromNodePin, Connection->FromNode, Connection->ToNodePin, Connection->ToNode); + if (bNode) + { + if (bFrom) + { + if (Connection->FromNode == NodeIndex) + { + /* node id has a connection */ + Count++; + } + } + else + { + if (Connection->ToNode == NodeIndex) + { + /* node id has a connection */ + Count++; + } + } + } + else + { + if (bFrom) + { + if (Connection->FromNodePin == NodeIndex) + { + /* node id has a connection */ + Count++; + } + } + else + { + if (Connection->ToNodePin == NodeIndex) + { + /* node id has a connection */ + Count++; + } + } + } + + + /* move to next connection */ + Connection++; + } + + ASSERT(Count != 0); + + /* now allocate node index array */ + Refs = ExAllocatePool(NonPagedPool, sizeof(ULONG) * Count); + if (!Refs) + { + /* not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + Count = 0; + Connection = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1); + for(Index = 0; Index < MultipleItem->Count; Index++) + { + if (bNode) + { + if (bFrom) + { + if (Connection->FromNode == NodeIndex) + { + /* node id has a connection */ + Refs[Count] = Index; + Count++; + } + } + else + { + if (Connection->ToNode == NodeIndex) + { + /* node id has a connection */ + Refs[Count] = Index; + Count++; + } + } + } + else + { + if (bFrom) + { + if (Connection->FromNodePin == NodeIndex) + { + /* node id has a connection */ + Refs[Count] = Index; + Count++; + } + } + else + { + if (Connection->ToNodePin == NodeIndex) + { + /* node id has a connection */ + Refs[Count] = Index; + Count++; + } + } + } + + /* move to next connection */ + Connection++; + } + + /* store result */ + *NodeReference = Refs; + *NodeReferenceCount = Count; + + return STATUS_SUCCESS; +} + + +NTSTATUS +GetTargetPinsByNodeConnectionIndex( + IN PKSMULTIPLE_ITEM NodeConnections, + IN PKSMULTIPLE_ITEM NodeTypes, + IN ULONG bUpDirection, + IN ULONG NodeConnectionIndex, + OUT PULONG Pins) +{ + PKSTOPOLOGY_CONNECTION Connection; + ULONG PinId, NodeConnectionCount, Index; + PULONG NodeConnection; + NTSTATUS Status; + + + /* sanity check */ + ASSERT(NodeConnectionIndex < NodeConnections->Count); + + Connection = (PKSTOPOLOGY_CONNECTION)(NodeConnections + 1); + + DPRINT("FromNode %u FromNodePin %u -> ToNode %u ToNodePin %u\n", Connection[NodeConnectionIndex].FromNode, Connection[NodeConnectionIndex].FromNodePin, Connection[NodeConnectionIndex].ToNode, Connection[NodeConnectionIndex].ToNodePin ); + + if ((Connection[NodeConnectionIndex].ToNode == KSFILTER_NODE && bUpDirection == FALSE) || + (Connection[NodeConnectionIndex].FromNode == KSFILTER_NODE && bUpDirection == TRUE)) + { + /* iteration stops here */ + if (bUpDirection) + PinId = Connection[NodeConnectionIndex].FromNodePin; + else + PinId = Connection[NodeConnectionIndex].ToNodePin; + + DPRINT("GetTargetPinsByNodeIndex FOUND Target Pin %u Parsed %u\n", PinId, Pins[PinId]); + + /* mark pin index as a target pin */ + Pins[PinId] = TRUE; + return STATUS_SUCCESS; + } + + /* get all node indexes referenced by that node */ + if (bUpDirection) + { + Status = GetNodeIndexes(NodeConnections, Connection[NodeConnectionIndex].FromNode, TRUE, FALSE, &NodeConnectionCount, &NodeConnection); + } + else + { + Status = GetNodeIndexes(NodeConnections, Connection[NodeConnectionIndex].ToNode, TRUE, TRUE, &NodeConnectionCount, &NodeConnection); + } + + if (NT_SUCCESS(Status)) + { + for(Index = 0; Index < NodeConnectionCount; Index++) + { + /* iterate recursively into the nodes */ + Status = GetTargetPinsByNodeConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Pins); + ASSERT(Status == STATUS_SUCCESS); + } + /* free node connection indexes */ + ExFreePool(NodeConnection); + } + + return Status; +} + + + +NTSTATUS +GetTargetPins( + PKSMULTIPLE_ITEM NodeTypes, + PKSMULTIPLE_ITEM NodeConnections, + IN ULONG NodeIndex, + IN ULONG bUpDirection, + PULONG Pins, + ULONG PinCount) +{ + ULONG NodeConnectionCount, Index; + NTSTATUS Status; + PULONG NodeConnection; + + /* sanity check */ + ASSERT(NodeIndex != (ULONG)-1); + + /* get all node indexes referenced by that pin */ + if (bUpDirection) + Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, FALSE, &NodeConnectionCount, &NodeConnection); + else + Status = GetNodeIndexes(NodeConnections, NodeIndex, TRUE, TRUE, &NodeConnectionCount, &NodeConnection); + + DPRINT("NodeIndex %u Status %x Count %u\n", NodeIndex, Status, NodeConnectionCount); + + if (NT_SUCCESS(Status)) + { + for(Index = 0; Index < NodeConnectionCount; Index++) + { + Status = GetTargetPinsByNodeConnectionIndex(NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Pins); + ASSERT(Status == STATUS_SUCCESS); + } + ExFreePool(NodeConnection); + } + + return Status; +} + +PULONG +AllocatePinArray( + ULONG PinCount) +{ + PULONG Pins = ExAllocatePool(NonPagedPool, PinCount * sizeof(ULONG)); + if (!Pins) + return NULL; + + RtlZeroMemory(Pins, sizeof(ULONG) * PinCount); + + return Pins; +} + +NTSTATUS +AddMixerSourceLine( + IN OUT LPMIXER_INFO MixerInfo, + IN PFILE_OBJECT FileObject, + IN ULONG PinId) +{ + LPMIXERLINE_SOURCE SrcLine; + NTSTATUS Status; + KSP_PIN Pin; + LPWSTR PinName; + GUID NodeType; + ULONG BytesReturned; + + /* allocate src mixer line */ + SrcLine = (LPMIXERLINE_SOURCE)ExAllocatePool(NonPagedPool, sizeof(MIXERLINE_SOURCE)); + if (!SrcLine) + return STATUS_INSUFFICIENT_RESOURCES; + + /* zero struct */ + RtlZeroMemory(SrcLine, sizeof(MIXERLINE_SOURCE)); + + /* initialize mixer src line */ + SrcLine->FileObject = FileObject; + SrcLine->PinId = PinId; + SrcLine->Line.cbStruct = sizeof(MIXERLINEW); + + /* initialize mixer destination line */ + SrcLine->Line.cbStruct = sizeof(MIXERLINEW); + SrcLine->Line.dwDestination = 0; + SrcLine->Line.dwSource = MixerInfo->DestinationLine.cConnections; + SrcLine->Line.dwLineID = (MixerInfo->DestinationLine.cConnections * 0x10000); + SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE; + SrcLine->Line.dwUser = 0; + SrcLine->Line.cChannels = MixerInfo->DestinationLine.cChannels; + SrcLine->Line.cConnections = 0; + SrcLine->Line.cControls = 1; //FIXME + + //HACK + SrcLine->LineControls = ExAllocatePool(NonPagedPool, SrcLine->Line.cControls * sizeof(MIXERCONTROLW)); + if (!SrcLine->LineControls) + { + /* not enough memory */ + ExFreePool(SrcLine); + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* clear line controls */ + RtlZeroMemory(SrcLine->LineControls, sizeof(MIXERCONTROLW)); + + /* fill in pseudo mixer control */ + SrcLine->LineControls->dwControlID = 1; //FIXME + SrcLine->LineControls->cbStruct = sizeof(MIXERCONTROLW); + SrcLine->LineControls->fdwControl = 0; + SrcLine->LineControls->cMultipleItems = 0; + wcscpy(SrcLine->LineControls->szName, L"test"); + wcscpy(SrcLine->LineControls->szShortName, L"test"); + + + /* get pin category */ + Pin.PinId = PinId; + Pin.Reserved = 0; + Pin.Property.Flags = KSPROPERTY_TYPE_GET; + Pin.Property.Set = KSPROPSETID_Pin; + Pin.Property.Id = KSPROPERTY_PIN_CATEGORY; + + /* try get pin category */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (LPVOID)&NodeType, sizeof(GUID), &BytesReturned); + if (NT_SUCCESS(Status)) + { + //FIXME + //map component type + } + + /* retrieve pin name */ + Pin.PinId = PinId; + Pin.Reserved = 0; + Pin.Property.Flags = KSPROPERTY_TYPE_GET; + Pin.Property.Set = KSPROPSETID_Pin; + Pin.Property.Id = KSPROPERTY_PIN_NAME; + + /* try get pin name size */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned); + + if (Status != STATUS_MORE_ENTRIES) + { + SrcLine->Line.szShortName[0] = L'\0'; + SrcLine->Line.szName[0] = L'\0'; + } + else + { + PinName = (LPWSTR)ExAllocatePool(NonPagedPool, BytesReturned); + if (PinName) + { + /* try get pin name */ + Status = KsSynchronousIoControlDevice(FileObject, KernelMode, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (LPVOID)PinName, BytesReturned, &BytesReturned); + + if (NT_SUCCESS(Status)) + { + RtlMoveMemory(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR)); + SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0'; + + RtlMoveMemory(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR)); + SrcLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0'; + } + ExFreePool(PinName); + } + } + + SrcLine->Line.Target.dwType = 1; + SrcLine->Line.Target.dwDeviceID = MixerInfo->DestinationLine.Target.dwDeviceID; + SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid; + SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid; + SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; + wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname); + + + /* insert src line */ + InsertTailList(&MixerInfo->SourceLineList, &SrcLine->Entry); + MixerInfo->DestinationLine.cConnections++; + + return STATUS_SUCCESS; +} + + +NTSTATUS +AddMixerSourceLines( + IN OUT LPMIXER_INFO MixerInfo, + IN PFILE_OBJECT FileObject, + IN ULONG PinsCount, + IN PULONG Pins) +{ + ULONG Index; + NTSTATUS Status = STATUS_SUCCESS; + + for(Index = PinsCount; Index > 0; Index--) + { + if (Pins[Index-1]) + { + AddMixerSourceLine(MixerInfo, FileObject, Index-1); + } + } + return Status; +} + + + +NTSTATUS +HandlePhysicalConnection( + IN OUT LPMIXER_INFO MixerInfo, + IN ULONG bInput, + IN PKSPIN_PHYSICALCONNECTION OutConnection) +{ + PULONG PinsRef = NULL, PinConnectionIndex = NULL, PinsSrcRef; + ULONG PinsRefCount, Index, PinConnectionIndexCount; + NTSTATUS Status; + HANDLE hDevice = NULL; + PFILE_OBJECT FileObject = NULL; + PKSMULTIPLE_ITEM NodeTypes = NULL; + PKSMULTIPLE_ITEM NodeConnections = NULL; + PULONG MixerControls; + ULONG MixerControlsCount; + + + /* open the connected filter */ + Status = OpenDevice(OutConnection->SymbolicLinkName, &hDevice, &FileObject); + if (!NT_SUCCESS(Status)) + { + DPRINT1("OpenDevice failed with %x\n", Status); + return Status; + } + + /* get connected filter pin count */ + PinsRefCount = GetPinCount(FileObject); + ASSERT(PinsRefCount); + + PinsRef = AllocatePinArray(PinsRefCount); + if (!PinsRef) + { + /* no memory */ + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + /* get topology node types */ + Status = GetFilterNodeProperty(FileObject, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes); + if (!NT_SUCCESS(Status)) + { + DPRINT1("GetFilterNodeProperty failed with %x\n", Status); + goto cleanup; + } + + /* get topology connections */ + Status = GetFilterNodeProperty(FileObject, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections); + if (!NT_SUCCESS(Status)) + { + DPRINT1("GetFilterNodeProperty failed with %x\n", Status); + goto cleanup; + } + /* gets connection index of the bridge pin which connects to a node */ + DPRINT("Pin %u\n", OutConnection->Pin); + Status = GetNodeIndexes(NodeConnections, OutConnection->Pin, FALSE, !bInput, &PinConnectionIndexCount, &PinConnectionIndex); + if (!NT_SUCCESS(Status)) + { + DPRINT1("GetNodeIndexes failed with %x\n", Status); + goto cleanup; + } + + /* there should be no split in the bride pin */ + ASSERT(PinConnectionIndexCount == 1); + + /* find all target pins of this connection */ + Status = GetTargetPinsByNodeConnectionIndex(NodeConnections, NodeTypes, FALSE, PinConnectionIndex[0], PinsRef); + if (!NT_SUCCESS(Status)) + { + DPRINT1("GetTargetPinsByNodeConnectionIndex failed with %x\n", Status); + goto cleanup; + } + + for(Index = 0; Index < PinsRefCount; Index++) + { + if (PinsRef[Index]) + { + + /* found a target pin, now get all references */ + Status = GetNodeIndexes(NodeConnections, Index, FALSE, FALSE, &MixerControlsCount, &MixerControls); + if (!NT_SUCCESS(Status)) + break; + + /* sanity check */ + ASSERT(MixerControlsCount == 1); + + + PinsSrcRef = AllocatePinArray(PinsRefCount); + if (!PinsSrcRef) + { + /* no memory */ + ExFreePool(MixerControls); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + /* now get all connected source pins */ + Status = GetTargetPinsByNodeConnectionIndex(NodeConnections, NodeTypes, TRUE, MixerControls[0], PinsSrcRef); + if (!NT_SUCCESS(Status)) + { + /* no memory */ + ExFreePool(MixerControls); + ExFreePool(PinsSrcRef); + Status = STATUS_INSUFFICIENT_RESOURCES; + goto cleanup; + } + + /* add pins from target line */ + if (!bInput) + { + // dont add bridge pin for input mixers + PinsSrcRef[Index] = TRUE; + PinsSrcRef[OutConnection->Pin] = TRUE; + } + + Status = AddMixerSourceLines(MixerInfo, FileObject, PinsRefCount, PinsSrcRef); + + ExFreePool(MixerControls); + ExFreePool(PinsSrcRef); + } + } + +cleanup: + + if (PinsRef) + ExFreePool(PinsRef); + + if (NodeConnections) + ExFreePool(NodeConnections); + + if (NodeTypes) + ExFreePool(NodeTypes); + + if (FileObject) + ObDereferenceObject(FileObject); + + if (hDevice) + ZwClose(hDevice); + + if (PinConnectionIndex) + ExFreePool(PinConnectionIndex); + + + return Status; +} + + + +NTSTATUS +InitializeMixer( + IN PDEVICE_OBJECT DeviceObject, + IN ULONG DeviceIndex, + IN OUT LPMIXER_INFO MixerInfo, + IN HANDLE hDevice, + IN PFILE_OBJECT FileObject, + IN ULONG PinCount, + IN PKSMULTIPLE_ITEM NodeTypes, + IN PKSMULTIPLE_ITEM NodeConnections, + IN ULONG NodeIndex, + IN ULONG bInput) +{ + WCHAR Buffer[100]; + LPWSTR Device; + NTSTATUS Status; + PULONG Pins; + ULONG Index; + PKSPIN_PHYSICALCONNECTION OutConnection; + + /* initialize mixer info */ + MixerInfo->hMixer = hDevice; + MixerInfo->MixerFileObject = FileObject; + + /* intialize mixer caps */ + MixerInfo->MixCaps.wMid = MM_MICROSOFT; //FIXME + MixerInfo->MixCaps.wPid = MM_PID_UNMAPPED; //FIXME + MixerInfo->MixCaps.vDriverVersion = 1; //FIXME + MixerInfo->MixCaps.fdwSupport = 0; + MixerInfo->MixCaps.cDestinations = 1; + + /* get target pnp name */ + Status = GetSysAudioDevicePnpName(DeviceObject, DeviceIndex, &Device); + if (NT_SUCCESS(Status)) + { + /* find product name */ + Status = FindProductName(Device, sizeof(Buffer) / sizeof(WCHAR), Buffer); + if (NT_SUCCESS(Status)) + { + if (bInput) + wcscat(Buffer, L" Input"); + else + wcscat(Buffer, L" output"); + RtlMoveMemory(MixerInfo->MixCaps.szPname, Buffer, min(MAXPNAMELEN, wcslen(Buffer)+1) * sizeof(WCHAR)); + MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; + } + ExFreePool(Device); + } + + /* initialize mixer destination line */ + MixerInfo->DestinationLine.cbStruct = sizeof(MIXERLINEW); + MixerInfo->DestinationLine.dwSource = MAXULONG; + MixerInfo->DestinationLine.dwLineID = 0xFFFF0000; + MixerInfo->DestinationLine.fdwLine = MIXERLINE_LINEF_ACTIVE; + MixerInfo->DestinationLine.dwUser = 0; + MixerInfo->DestinationLine.dwComponentType = (bInput == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN); + MixerInfo->DestinationLine.cChannels = 2; //FIXME + MixerInfo->DestinationLine.cControls = 0; //FIXME + wcscpy(MixerInfo->DestinationLine.szShortName, L"Summe"); //FIXME + wcscpy(MixerInfo->DestinationLine.szName, L"Summe"); //FIXME + MixerInfo->DestinationLine.Target.dwType = (bInput == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN); + MixerInfo->DestinationLine.Target.dwDeviceID = !bInput; + MixerInfo->DestinationLine.Target.wMid = MixerInfo->MixCaps.wMid; + MixerInfo->DestinationLine.Target.wPid = MixerInfo->MixCaps.wPid; + MixerInfo->DestinationLine.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion; + wcscpy(MixerInfo->DestinationLine.Target.szPname, MixerInfo->MixCaps.szPname); + + + /* initialize source line list */ + InitializeListHead(&MixerInfo->SourceLineList); + + Pins = AllocatePinArray(PinCount); + if (!Pins) + return STATUS_INSUFFICIENT_RESOURCES; + + if (bInput) + { + Status = GetTargetPins(NodeTypes, NodeConnections, NodeIndex, TRUE, Pins, PinCount); + } + else + { + Status = GetTargetPins(NodeTypes, NodeConnections, NodeIndex, FALSE, Pins, PinCount); + } + + for(Index = 0; Index < PinCount; Index++) + { + if (Pins[Index]) + { + Status = GetPhysicalConnection(FileObject, Index, &OutConnection); + if (NT_SUCCESS(Status)) + { + Status = HandlePhysicalConnection(MixerInfo, bInput, OutConnection); + } + } + } + ExFreePool(Pins); + + return STATUS_SUCCESS; +} + +NTSTATUS +WdmAudMixerInitialize( + IN PDEVICE_OBJECT DeviceObject) +{ + ULONG DeviceCount, Index, Count, NodeIndex, PinCount; NTSTATUS Status; HANDLE hDevice; PFILE_OBJECT FileObject; - PKSMULTIPLE_ITEM MultipleItem; + PKSMULTIPLE_ITEM NodeTypes, NodeConnections; + BOOL bCloseHandle; + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + + /* get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; +
/* get number of devices */ DeviceCount = GetSysAudioDeviceCount(DeviceObject);
if (!DeviceCount) - return 0; + { + /* no audio devices available atm */ + DeviceExtension->MixerInfoCount = 0; + DeviceExtension->MixerInfo = NULL; + return STATUS_SUCCESS; + } + + /* each virtual audio device can at most have an input + output mixer */ + DeviceExtension->MixerInfo = ExAllocatePool(NonPagedPool, sizeof(MIXER_INFO) * DeviceCount * 2); + if (!DeviceExtension->MixerInfo) + { + /* not enough memory */ + return STATUS_INSUFFICIENT_RESOURCES; + } + + /* clear mixer info */ + RtlZeroMemory(DeviceExtension->MixerInfo, sizeof(MIXER_INFO) * DeviceCount * 2);
Index = 0; Count = 0; @@ -239,102 +1120,72 @@ if (NT_SUCCESS(Status)) { /* retrieve all available node types */ - Status = GetFilterNodeTypes(FileObject, &MultipleItem); - if (NT_SUCCESS(Status)) - { - if (CountNodeType(MultipleItem, (LPGUID)&KSNODETYPE_DAC)) + Status = GetFilterNodeProperty(FileObject, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + ZwClose(hDevice); + break; + } + + Status = GetFilterNodeProperty(FileObject, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections); + if (!NT_SUCCESS(Status)) + { + ObDereferenceObject(FileObject); + ZwClose(hDevice); + ExFreePool(NodeTypes); + break; + } + + /* get num of pins */ + PinCount = GetPinCount(FileObject); + bCloseHandle = TRUE; + /* get the first available dac node index */ + NodeIndex = GetNodeTypeIndex(NodeTypes, (LPGUID)&KSNODETYPE_DAC); + if (NodeIndex != (ULONG)-1) + { + Status = InitializeMixer(DeviceObject, Index, &DeviceExtension->MixerInfo[Count], hDevice, FileObject, PinCount, NodeTypes, NodeConnections, NodeIndex, FALSE); + if (NT_SUCCESS(Status)) { - /* increment (output) mixer count */ + /* increment mixer offset */ Count++; + bCloseHandle = FALSE; } - - if (CountNodeType(MultipleItem, (LPGUID)&KSNODETYPE_ADC)) + } + + /* get the first available adc node index */ + NodeIndex = GetNodeTypeIndex(NodeTypes, (LPGUID)&KSNODETYPE_ADC); + if (NodeIndex != (ULONG)-1) + { + Status = InitializeMixer(DeviceObject, Index, &DeviceExtension->MixerInfo[Count], hDevice, FileObject, PinCount, NodeTypes, NodeConnections, NodeIndex, TRUE); + if (NT_SUCCESS(Status)) { - /* increment (input) mixer count */ + /* increment mixer offset */ Count++; + bCloseHandle = FALSE; } - ExFreePool(MultipleItem); - } - ObDereferenceObject(FileObject); - ZwClose(hDevice); - } - + } + + /* free node connections array */ + ExFreePool(NodeTypes); + ExFreePool(NodeConnections); + + if (bCloseHandle) + { + /* close virtual audio device */ + ObDereferenceObject(FileObject); + ZwClose(hDevice); + } + } + /* increment virtual audio device index */ Index++; }while(Index < DeviceCount);
- return Count; -} - -ULONG -IsOutputMixer( - IN PDEVICE_OBJECT DeviceObject, - IN ULONG DeviceIndex) -{ - ULONG DeviceCount, Index, Count; - NTSTATUS Status; - HANDLE hDevice; - PFILE_OBJECT FileObject; - PKSMULTIPLE_ITEM MultipleItem; - - /* get number of devices */ - DeviceCount = GetSysAudioDeviceCount(DeviceObject); - - if (!DeviceCount) - return 0; - - Index = 0; - Count = 0; - do - { - /* open the virtual audio device */ - Status = OpenSysAudioDeviceByIndex(DeviceObject, Index, &hDevice, &FileObject); - - if (NT_SUCCESS(Status)) - { - /* retrieve all available node types */ - Status = GetFilterNodeTypes(FileObject, &MultipleItem); - if (NT_SUCCESS(Status)) - { - if (CountNodeType(MultipleItem, (LPGUID)&KSNODETYPE_DAC)) - { - /* increment (output) mixer count */ - if (DeviceIndex == Count) - { - ExFreePool(MultipleItem); - ObDereferenceObject(FileObject); - ZwClose(hDevice); - return TRUE; - } - - Count++; - } - - if (CountNodeType(MultipleItem, (LPGUID)&KSNODETYPE_ADC)) - { - /* increment (input) mixer count */ - if (DeviceIndex == Count) - { - ExFreePool(MultipleItem); - ObDereferenceObject(FileObject); - ZwClose(hDevice); - return FALSE; - } - Count++; - } - ExFreePool(MultipleItem); - } - ObDereferenceObject(FileObject); - ZwClose(hDevice); - } - - Index++; - }while(Index < DeviceCount); - - ASSERT(0); - return FALSE; -} - - + /* store mixer count */ + DeviceExtension->MixerInfoCount = Count; + + return Status; +}
@@ -342,43 +1193,19 @@ WdmAudMixerCapabilities( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo) -{ - NTSTATUS Status; - LPWSTR Device; - WCHAR Buffer[100]; - - Status = GetSysAudioDevicePnpName(DeviceObject, DeviceInfo->DeviceIndex,&Device); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to get device name %x\n", Status); - return Status; - } - - DeviceInfo->u.MixCaps.cDestinations = 1; //FIXME - - Status = FindProductName(Device, sizeof(Buffer) / sizeof(WCHAR), Buffer); - - /* check for success */ - if (!NT_SUCCESS(Status)) - { - DeviceInfo->u.MixCaps.szPname[0] = L'\0'; - } - else - { - if (IsOutputMixer(DeviceObject, DeviceInfo->DeviceIndex)) - { - wcscat(Buffer, L" output"); - } - else - { - wcscat(Buffer, L" Input"); - } - RtlMoveMemory(DeviceInfo->u.MixCaps.szPname, Buffer, min(MAXPNAMELEN, wcslen(Buffer)+1) * sizeof(WCHAR)); - DeviceInfo->u.MixCaps.szPname[MAXPNAMELEN-1] = L'\0'; - } - - return Status; + IN PWDMAUD_CLIENT ClientInfo, + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension) +{ + if ((ULONG)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount) + { + /* invalid parameter */ + return STATUS_INVALID_PARAMETER; + } + + /* copy cached mixer caps */ + RtlMoveMemory(&DeviceInfo->u.MixCaps, &DeviceExtension->MixerInfo[(ULONG)DeviceInfo->hDevice].MixCaps, sizeof(MIXERCAPSW)); + + return STATUS_SUCCESS; }
@@ -391,10 +1218,14 @@ { ULONG Index; PWDMAUD_HANDLE Handels; + PWDMAUD_DEVICE_EXTENSION DeviceExtension;
DPRINT("WdmAudControlOpenMixer\n");
- if (DeviceInfo->DeviceIndex >= GetNumOfMixerDevices(DeviceObject)) + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + + if (DeviceInfo->DeviceIndex >= DeviceExtension->MixerInfoCount) { /* mixer index doesnt exist */ return SetIrpIoStatus(Irp, STATUS_UNSUCCESSFUL, 0); @@ -442,7 +1273,57 @@ IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + LPMIXERLINE_SOURCE MixerLineSrc; + + /* get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceInfo->Flags == MIXER_GETLINEINFOF_DESTINATION) + { + if ((ULONG)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount) + { + /* invalid parameter */ + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + if (DeviceInfo->u.MixLine.dwDestination != 0) + { + /* invalid parameter */ + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + /* copy cached data */ + RtlCopyMemory(&DeviceInfo->u.MixLine, &DeviceExtension->MixerInfo[(ULONG)DeviceInfo->hDevice].DestinationLine, sizeof(MIXERLINEW)); + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + } + else if (DeviceInfo->Flags == MIXER_GETLINEINFOF_SOURCE) + { + if ((ULONG)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount) + { + /* invalid parameter */ + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + if (DeviceInfo->u.MixLine.dwSource >= DeviceExtension->MixerInfo[(ULONG)DeviceInfo->hDevice].DestinationLine.cConnections) + { + DPRINT1("dwSource %u Destinations %u\n", DeviceInfo->u.MixLine.dwSource, DeviceExtension->MixerInfo[(ULONG)DeviceInfo->hDevice].DestinationLine.cConnections); + /* invalid parameter */ + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + MixerLineSrc = GetSourceMixerLine(&DeviceExtension->MixerInfo[(ULONG)DeviceInfo->hDevice], DeviceInfo->u.MixLine.dwSource); + if (MixerLineSrc) + { + DPRINT("Line %u Name %S\n", MixerLineSrc->Line.dwSource, MixerLineSrc->Line.szName); + RtlCopyMemory(&DeviceInfo->u.MixLine, &MixerLineSrc->Line, sizeof(MIXERLINEW)); + } + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + } + + DPRINT1("Flags %x\n", DeviceInfo->Flags); UNIMPLEMENTED; + //DbgBreakPoint(); return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
@@ -456,6 +1337,32 @@ IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo) { + LPMIXERLINE_SOURCE MixerLineSrc; + PWDMAUD_DEVICE_EXTENSION DeviceExtension; + + /* get device extension */ + DeviceExtension = (PWDMAUD_DEVICE_EXTENSION)DeviceObject->DeviceExtension; + + if (DeviceInfo->Flags == MIXER_GETLINECONTROLSF_ALL) + { + if ((ULONG)DeviceInfo->hDevice >= DeviceExtension->MixerInfoCount) + { + /* invalid parameter */ + return SetIrpIoStatus(Irp, STATUS_INVALID_PARAMETER, 0); + } + + MixerLineSrc = GetSourceMixerLineByLineId(&DeviceExtension->MixerInfo[(ULONG)DeviceInfo->hDevice], DeviceInfo->u.MixControls.dwLineID); + ASSERT(MixerLineSrc); + if (MixerLineSrc) + { + RtlMoveMemory(DeviceInfo->u.MixControls.pamxctrl, MixerLineSrc->LineControls, min(MixerLineSrc->Line.cControls, DeviceInfo->u.MixControls.cControls) * sizeof(MIXERLINECONTROLSW)); + } + return SetIrpIoStatus(Irp, STATUS_SUCCESS, sizeof(WDMAUD_DEVICE_INFO)); + + + + } + UNIMPLEMENTED; //DbgBreakPoint(); return SetIrpIoStatus(Irp, STATUS_NOT_IMPLEMENTED, 0);
Modified: trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/wdm/audio/legacy/wd... ============================================================================== --- trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] (original) +++ trunk/reactos/drivers/wdm/audio/legacy/wdmaud/wdmaud.h [iso-8859-1] Tue Sep 29 14:26:48 2009 @@ -8,6 +8,7 @@ #define NDEBUG #include <debug.h> #include <ksmedia.h> +#include <mmreg.h> #include <mmsystem.h> #include <stdlib.h> #include <stdio.h> @@ -35,6 +36,29 @@ typedef struct { LIST_ENTRY Entry; + ULONG PinId; + PFILE_OBJECT FileObject; + MIXERLINEW Line; + LPMIXERCONTROLW LineControls; +}MIXERLINE_SOURCE, *LPMIXERLINE_SOURCE; + + +typedef struct +{ + HANDLE hMixer; + PFILE_OBJECT MixerFileObject; + + MIXERCAPSW MixCaps; + MIXERLINEW DestinationLine; + + LIST_ENTRY SourceLineList; + +}MIXER_INFO, *LPMIXER_INFO; + + +typedef struct +{ + LIST_ENTRY Entry; UNICODE_STRING SymbolicLink; }SYSAUDIO_ENTRY, *PSYSAUDIO_ENTRY;
@@ -50,6 +74,10 @@ LIST_ENTRY SysAudioDeviceList; HANDLE hSysAudio; PFILE_OBJECT FileObject; + + ULONG MixerInfoCount; + LPMIXER_INFO MixerInfo; +
}WDMAUD_DEVICE_EXTENSION, *PWDMAUD_DEVICE_EXTENSION;
@@ -118,7 +146,8 @@ WdmAudMixerCapabilities( IN PDEVICE_OBJECT DeviceObject, IN PWDMAUD_DEVICE_INFO DeviceInfo, - IN PWDMAUD_CLIENT ClientInfo); + IN PWDMAUD_CLIENT ClientInfo, + IN PWDMAUD_DEVICE_EXTENSION DeviceExtension);
NTSTATUS NTAPI @@ -160,6 +189,9 @@ IN PWDMAUD_DEVICE_INFO DeviceInfo, IN PWDMAUD_CLIENT ClientInfo);
+NTSTATUS +WdmAudMixerInitialize( + IN PDEVICE_OBJECT DeviceObject);
#endif