Author: janderwald
Date: Tue Dec 8 22:10:02 2009
New Revision: 44473
URL:
http://svn.reactos.org/svn/reactos?rev=44473&view=rev
Log:
[MMIXER]
- Finish porting of code from wdmaud
Added:
trunk/reactos/lib/drivers/sound/mmixer/controls.c (with props)
trunk/reactos/lib/drivers/sound/mmixer/filter.c (with props)
trunk/reactos/lib/drivers/sound/mmixer/sup.c (with props)
Modified:
trunk/reactos/lib/drivers/sound/mmixer/mixer.c
trunk/reactos/lib/drivers/sound/mmixer/mmixer.h
trunk/reactos/lib/drivers/sound/mmixer/mmixer.rbuild
trunk/reactos/lib/drivers/sound/mmixer/priv.h
Added: trunk/reactos/lib/drivers/sound/mmixer/controls.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/c…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmixer/controls.c (added)
+++ trunk/reactos/lib/drivers/sound/mmixer/controls.c [iso-8859-1] Tue Dec 8 22:10:02
2009
@@ -1,0 +1,949 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Kernel Streaming
+ * FILE: lib/drivers/sound/mmixer/controls.c
+ * PURPOSE: Mixer Control Iteration Functions
+ * PROGRAMMER: Johannes Anderwald
+ */
+
+#include "priv.h"
+
+MIXER_STATUS
+MMixerGetTargetPinsByNodeConnectionIndex(
+ IN PMIXER_CONTEXT MixerContext,
+ 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;
+ MIXER_STATUS 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 MM_STATUS_SUCCESS;
+ }
+
+ // get all node indexes referenced by that node
+ if (bUpDirection)
+ {
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections,
Connection[NodeConnectionIndex].FromNode, TRUE, FALSE, &NodeConnectionCount,
&NodeConnection);
+ }
+ else
+ {
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections,
Connection[NodeConnectionIndex].ToNode, TRUE, TRUE, &NodeConnectionCount,
&NodeConnection);
+ }
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ for(Index = 0; Index < NodeConnectionCount; Index++)
+ {
+ // iterate recursively into the nodes
+ Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext,
NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Pins);
+ ASSERT(Status == MM_STATUS_SUCCESS);
+ }
+ // free node connection indexes
+ MixerContext->Free(NodeConnection);
+ }
+
+ return Status;
+}
+
+MIXER_STATUS
+MMixerGetControlsFromPinByConnectionIndex(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN ULONG bUpDirection,
+ IN ULONG NodeConnectionIndex,
+ OUT PULONG Nodes)
+{
+ PKSTOPOLOGY_CONNECTION CurConnection;
+ LPGUID NodeType;
+ ULONG NodeIndex;
+ MIXER_STATUS Status;
+ ULONG NodeConnectionCount, Index;
+ PULONG NodeConnection;
+
+
+ /* get current connection */
+ CurConnection = MMixerGetConnectionByIndex(NodeConnections, NodeConnectionIndex);
+
+ if (bUpDirection)
+ NodeIndex = CurConnection->FromNode;
+ else
+ NodeIndex = CurConnection->ToNode;
+
+ /* get target node type of current connection */
+ NodeType = MMixerGetNodeType(NodeTypes, NodeIndex);
+
+ if (IsEqualGUIDAligned(NodeType, &KSNODETYPE_SUM) || IsEqualGUIDAligned(NodeType,
&KSNODETYPE_MUX))
+ {
+ if (bUpDirection)
+ {
+ /* add the sum / mux node to destination line */
+ Nodes[NodeIndex] = TRUE;
+ }
+
+ return MM_STATUS_SUCCESS;
+ }
+
+ /* now add the node */
+ Nodes[NodeIndex] = TRUE;
+
+
+ /* get all node indexes referenced by that node */
+ if (bUpDirection)
+ {
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE,
FALSE, &NodeConnectionCount, &NodeConnection);
+ }
+ else
+ {
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE,
TRUE, &NodeConnectionCount, &NodeConnection);
+ }
+
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ for(Index = 0; Index < NodeConnectionCount; Index++)
+ {
+ /* iterate recursively into the nodes */
+ Status = MMixerGetControlsFromPinByConnectionIndex(MixerContext,
NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Nodes);
+ ASSERT(Status == MM_STATUS_SUCCESS);
+ }
+ /* free node connection indexes */
+ MixerContext->Free(NodeConnection);
+ }
+
+ return Status;
+}
+
+MIXER_STATUS
+MMixerAddMixerControl(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_INFO MixerInfo,
+ IN HANDLE hDevice,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN ULONG NodeIndex,
+ IN LPMIXERLINE_EXT MixerLine,
+ OUT LPMIXERCONTROLW MixerControl)
+{
+ LPGUID NodeType;
+ KSP_NODE Node;
+ ULONG BytesReturned;
+ MIXER_STATUS Status;
+ LPWSTR Name;
+
+ /* initialize mixer control */
+ MixerControl->cbStruct = sizeof(MIXERCONTROLW);
+ MixerControl->dwControlID = MixerInfo->ControlId;
+
+ /* get node type */
+ NodeType = MMixerGetNodeType(NodeTypes, NodeIndex);
+ /* store control type */
+ MixerControl->dwControlType = MMixerGetControlTypeFromTopologyNode(NodeType);
+
+ MixerControl->fdwControl = MIXERCONTROL_CONTROLF_UNIFORM; //FIXME
+ MixerControl->cMultipleItems = 0; //FIXME
+
+ if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
+ {
+ MixerControl->Bounds.dwMinimum = 0;
+ MixerControl->Bounds.dwMaximum = 1;
+ }
+ else if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
+ {
+ MixerControl->Bounds.dwMinimum = 0;
+ MixerControl->Bounds.dwMaximum = 0xFFFF;
+ MixerControl->Metrics.cSteps = 0xC0; //FIXME
+ }
+
+ /* setup request to retrieve name */
+ Node.NodeId = NodeIndex;
+ Node.Property.Id = KSPROPERTY_TOPOLOGY_NAME;
+ Node.Property.Flags = KSPROPERTY_TYPE_GET;
+ Node.Property.Set = KSPROPSETID_Topology;
+ Node.Reserved = 0;
+
+ /* get node name size */
+ Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Node,
sizeof(KSP_NODE), NULL, 0, &BytesReturned);
+
+ if (Status == MM_STATUS_MORE_ENTRIES)
+ {
+ ASSERT(BytesReturned != 0);
+ Name = (LPWSTR)MixerContext->Alloc(BytesReturned);
+ if (!Name)
+ {
+ /* not enough memory */
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* get node name */
+ Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Node,
sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ RtlMoveMemory(MixerControl->szShortName, Name,
(min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
+ MixerControl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
+
+ RtlMoveMemory(MixerControl->szName, Name, (min(MIXER_LONG_NAME_CHARS,
wcslen(Name)+1)) * sizeof(WCHAR));
+ MixerControl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
+ }
+
+ /* free name buffer */
+ MixerContext->Free(Name);
+ }
+
+ MixerInfo->ControlId++;
+#if 0
+ if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUX)
+ {
+ KSNODEPROPERTY Property;
+ ULONG PinId = 2;
+
+ /* setup the request */
+ RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY));
+
+ Property.NodeId = NodeIndex;
+ Property.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE;
+ Property.Property.Flags = KSPROPERTY_TYPE_SET;
+ Property.Property.Set = KSPROPSETID_Audio;
+
+ /* get node volume level info */
+ Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY,
(PVOID)&Property, sizeof(KSNODEPROPERTY), (PVOID)&PinId, sizeof(ULONG),
&BytesReturned);
+
+ DPRINT1("Status %x NodeIndex %u PinId %u\n", Status, NodeIndex,
PinId);
+ //DbgBreakPoint();
+ }else
+#endif
+ if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
+ {
+ KSNODEPROPERTY_AUDIO_CHANNEL Property;
+ ULONG Length;
+ PKSPROPERTY_DESCRIPTION Desc;
+ PKSPROPERTY_MEMBERSHEADER Members;
+ PKSPROPERTY_STEPPING_LONG Range;
+
+ Length = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) +
sizeof(KSPROPERTY_STEPPING_LONG);
+ Desc = (PKSPROPERTY_DESCRIPTION)MixerContext->Alloc(Length);
+ ASSERT(Desc);
+
+ /* setup the request */
+ RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL));
+
+ Property.NodeProperty.NodeId = NodeIndex;
+ Property.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
+ Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT;
+ Property.NodeProperty.Property.Set = KSPROPSETID_Audio;
+
+ /* get node volume level info */
+ Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY,
(PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), Desc, Length,
&BytesReturned);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ LPMIXERVOLUME_DATA VolumeData;
+ ULONG Steps, MaxRange, Index;
+ LONG Value;
+
+ Members = (PKSPROPERTY_MEMBERSHEADER)(Desc + 1);
+ Range = (PKSPROPERTY_STEPPING_LONG)(Members + 1);
+
+ DPRINT("NodeIndex %u Range Min %d Max %d Steps %x UMin %x UMax
%x\n", NodeIndex, Range->Bounds.SignedMinimum, Range->Bounds.SignedMaximum,
Range->SteppingDelta, Range->Bounds.UnsignedMinimum,
Range->Bounds.UnsignedMaximum);
+
+ MaxRange = Range->Bounds.UnsignedMaximum -
Range->Bounds.UnsignedMinimum;
+
+ if (MaxRange)
+ {
+ ASSERT(MaxRange);
+ VolumeData =
(LPMIXERVOLUME_DATA)MixerContext->Alloc(sizeof(MIXERVOLUME_DATA));
+ if (!VolumeData)
+ return MM_STATUS_NO_MEMORY;
+
+ Steps = MaxRange / Range->SteppingDelta + 1;
+
+ /* store mixer control info there */
+ VolumeData->Header.dwControlID = MixerControl->dwControlID;
+ VolumeData->SignedMaximum = Range->Bounds.SignedMaximum;
+ VolumeData->SignedMinimum = Range->Bounds.SignedMinimum;
+ VolumeData->SteppingDelta = Range->SteppingDelta;
+ VolumeData->ValuesCount = Steps;
+ VolumeData->InputSteppingDelta = 0x10000 / Steps;
+
+ VolumeData->Values = (PLONG)MixerContext->Alloc(sizeof(LONG) *
Steps);
+ if (!VolumeData->Values)
+ {
+ MixerContext->Free(Desc);
+ MixerContext->Free(VolumeData);
+
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ Value = Range->Bounds.SignedMinimum;
+ for(Index = 0; Index < Steps; Index++)
+ {
+ VolumeData->Values[Index] = Value;
+ Value += Range->SteppingDelta;
+ }
+ InsertTailList(&MixerLine->LineControlsExtraData,
&VolumeData->Header.Entry);
+ }
+ }
+ MixerContext->Free(Desc);
+ }
+
+
+ DPRINT("Status %x Name %S\n", Status, MixerControl->szName);
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerAddMixerSourceLine(
+ IN PMIXER_CONTEXT MixerContext,
+ IN OUT LPMIXER_INFO MixerInfo,
+ IN HANDLE hDevice,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN ULONG PinId,
+ IN ULONG bBridgePin,
+ IN ULONG bTargetPin)
+{
+ LPMIXERLINE_EXT SrcLine, DstLine;
+ MIXER_STATUS Status;
+ KSP_PIN Pin;
+ LPWSTR PinName;
+ GUID NodeType;
+ ULONG BytesReturned, ControlCount, Index;
+ PULONG Nodes;
+
+ if (!bTargetPin)
+ {
+ /* allocate src mixer line */
+ SrcLine = (LPMIXERLINE_EXT)MixerContext->Alloc(sizeof(MIXERLINE_EXT));
+
+ if (!SrcLine)
+ return MM_STATUS_NO_MEMORY;
+
+ /* zero struct */
+ RtlZeroMemory(SrcLine, sizeof(MIXERLINE_EXT));
+
+ }
+ else
+ {
+ ASSERT(!IsListEmpty(&MixerInfo->LineList));
+ SrcLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
+ }
+
+ /* get destination line */
+ DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DESTINATION_LINE);
+ ASSERT(DstLine);
+
+
+ if (!bTargetPin)
+ {
+ /* initialize mixer src line */
+ SrcLine->hDevice = hDevice;
+ SrcLine->PinId = PinId;
+ SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
+
+ /* initialize mixer destination line */
+ SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
+ SrcLine->Line.dwDestination = 0;
+ SrcLine->Line.dwSource = DstLine->Line.cConnections;
+ SrcLine->Line.dwLineID = (DstLine->Line.cConnections * 0x10000);
+ SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE;
+ SrcLine->Line.dwUser = 0;
+ SrcLine->Line.cChannels = DstLine->Line.cChannels;
+ SrcLine->Line.cConnections = 0;
+ SrcLine->Line.Target.dwType = 1;
+ SrcLine->Line.Target.dwDeviceID = DstLine->Line.Target.dwDeviceID;
+ SrcLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
+ SrcLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
+ SrcLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
+ InitializeListHead(&SrcLine->LineControlsExtraData);
+ wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
+
+ }
+
+ /* allocate a node arrary */
+ Nodes = (PULONG)MixerContext->Alloc(sizeof(ULONG) * NodeTypes->Count);
+
+ if (!Nodes)
+ {
+ /* not enough memory */
+ if (!bTargetPin)
+ {
+ MixerContext->Free(SrcLine);
+ }
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ Status = MMixerGetControlsFromPin(MixerContext, NodeConnections, NodeTypes, PinId,
bTargetPin, Nodes);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* something went wrong */
+ if (!bTargetPin)
+ {
+ MixerContext->Free(SrcLine);
+ }
+ MixerContext->Free(Nodes);
+ return Status;
+ }
+
+ /* now count all nodes controlled by that pin */
+ ControlCount = 0;
+ for(Index = 0; Index < NodeTypes->Count; Index++)
+ {
+ if (Nodes[Index])
+ ControlCount++;
+ }
+
+ /* now allocate the line controls */
+ if (ControlCount)
+ {
+ SrcLine->LineControls =
(LPMIXERCONTROLW)MixerContext->Alloc(sizeof(MIXERCONTROLW) * ControlCount);
+
+ if (!SrcLine->LineControls)
+ {
+ /* no memory available */
+ if (!bTargetPin)
+ {
+ MixerContext->Free(SrcLine);
+ }
+ MixerContext->Free(Nodes);
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ SrcLine->NodeIds = (PULONG)MixerContext->Alloc(sizeof(ULONG) *
ControlCount);
+ if (!SrcLine->NodeIds)
+ {
+ /* no memory available */
+ MixerContext->Free(SrcLine->LineControls);
+ if (!bTargetPin)
+ {
+ MixerContext->Free(SrcLine);
+ }
+ MixerContext->Free(Nodes);
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* zero line controls */
+ RtlZeroMemory(SrcLine->LineControls, sizeof(MIXERCONTROLW) * ControlCount);
+ RtlZeroMemory(SrcLine->NodeIds, sizeof(ULONG) * ControlCount);
+
+ ControlCount = 0;
+ for(Index = 0; Index < NodeTypes->Count; Index++)
+ {
+ if (Nodes[Index])
+ {
+ /* store the node index for retrieving / setting details */
+ SrcLine->NodeIds[ControlCount] = Index;
+
+ Status = MMixerAddMixerControl(MixerContext, MixerInfo, hDevice,
NodeTypes, Index, SrcLine, &SrcLine->LineControls[ControlCount]);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* increment control count on success */
+ ControlCount++;
+ }
+ }
+ }
+ /* store control count */
+ SrcLine->Line.cControls = ControlCount;
+ }
+
+ /* release nodes array */
+ MixerContext->Free(Nodes);
+
+ /* 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 = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin,
sizeof(KSP_PIN), (LPVOID)&NodeType, sizeof(GUID), &BytesReturned);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ //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 = MixerContext->Control(hDevice, 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)MixerContext->Alloc(BytesReturned);
+ if (PinName)
+ {
+ /* try get pin name */
+ Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY,
(PVOID)&Pin, sizeof(KSP_PIN), (LPVOID)PinName, BytesReturned, &BytesReturned);
+
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ 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';
+ }
+ MixerContext->Free(PinName);
+ }
+ }
+
+ /* insert src line */
+ if (!bTargetPin)
+ {
+ InsertTailList(&MixerInfo->LineList, &SrcLine->Entry);
+ DstLine->Line.cConnections++;
+ }
+
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerCreateDestinationLine(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_INFO MixerInfo,
+ IN ULONG bInputMixer)
+{
+ LPMIXERLINE_EXT DestinationLine;
+
+ // allocate a mixer destination line
+ DestinationLine = (LPMIXERLINE_EXT) MixerContext->Alloc(sizeof(MIXERLINE_EXT));
+ if (!MixerInfo)
+ {
+ // no memory
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* initialize mixer destination line */
+ DestinationLine->Line.cbStruct = sizeof(MIXERLINEW);
+ DestinationLine->Line.dwSource = MAXULONG;
+ DestinationLine->Line.dwLineID = DESTINATION_LINE;
+ DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE;
+ DestinationLine->Line.dwUser = 0;
+ DestinationLine->Line.dwComponentType = (bInputMixer == 0 ?
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
+ DestinationLine->Line.cChannels = 2; //FIXME
+ wcscpy(DestinationLine->Line.szShortName, L"Summe"); //FIXME
+ wcscpy(DestinationLine->Line.szName, L"Summe"); //FIXME
+ DestinationLine->Line.Target.dwType = (bInputMixer == 0 ?
MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
+ DestinationLine->Line.Target.dwDeviceID = !bInputMixer;
+ DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
+ DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
+ DestinationLine->Line.Target.vDriverVersion =
MixerInfo->MixCaps.vDriverVersion;
+ wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
+
+
+ // insert into mixer info
+ InsertHeadList(&MixerInfo->LineList, &DestinationLine->Entry);
+
+ // done
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerGetControlsFromPin(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN ULONG PinId,
+ IN ULONG bUpDirection,
+ OUT PULONG Nodes)
+{
+ ULONG NodeConnectionCount, Index;
+ MIXER_STATUS Status;
+ PULONG NodeConnection;
+
+ /* sanity check */
+ ASSERT(PinId != (ULONG)-1);
+
+ /* get all node indexes referenced by that pin */
+ if (bUpDirection)
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, PinId, FALSE, FALSE,
&NodeConnectionCount, &NodeConnection);
+ else
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, PinId, FALSE, TRUE,
&NodeConnectionCount, &NodeConnection);
+
+ for(Index = 0; Index < NodeConnectionCount; Index++)
+ {
+ /* get all associated controls */
+ Status = MMixerGetControlsFromPinByConnectionIndex(MixerContext, NodeConnections,
NodeTypes, bUpDirection, NodeConnection[Index], Nodes);
+ }
+
+ MixerContext->Free(NodeConnection);
+
+ return Status;
+}
+
+
+
+
+MIXER_STATUS
+MMixerAddMixerSourceLines(
+ IN PMIXER_CONTEXT MixerContext,
+ IN OUT LPMIXER_INFO MixerInfo,
+ IN HANDLE hDevice,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN ULONG PinsCount,
+ IN ULONG BridgePinIndex,
+ IN ULONG TargetPinIndex,
+ IN PULONG Pins)
+{
+ ULONG Index;
+
+ for(Index = PinsCount; Index > 0; Index--)
+ {
+ if (Pins[Index-1])
+ {
+ MMixerAddMixerSourceLine(MixerContext, MixerInfo, hDevice, NodeConnections,
NodeTypes, Index-1, (Index -1 == BridgePinIndex), (Index -1 == TargetPinIndex));
+ }
+ }
+ return MM_STATUS_SUCCESS;
+}
+
+
+MIXER_STATUS
+MMixerHandlePhysicalConnection(
+ IN PMIXER_CONTEXT MixerContext,
+ IN OUT LPMIXER_INFO MixerInfo,
+ IN ULONG bInput,
+ IN PKSPIN_PHYSICALCONNECTION OutConnection)
+{
+ PULONG PinsRef = NULL, PinConnectionIndex = NULL, PinsSrcRef;
+ ULONG PinsRefCount, Index, PinConnectionIndexCount;
+ MIXER_STATUS 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 = MixerContext->Open(OutConnection->SymbolicLinkName, &hDevice);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ DPRINT1("OpenDevice failed with %x\n", Status);
+ return Status;
+ }
+
+ // get connected filter pin count
+ PinsRefCount = MMixerGetFilterPinCount(MixerContext, hDevice);
+ ASSERT(PinsRefCount);
+
+ PinsRef = (PULONG)MixerContext->Alloc(sizeof(ULONG) * PinsRefCount);
+ if (!PinsRef)
+ {
+ // no memory
+ MixerContext->Close(hDevice);
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+
+ // get topology node types
+ Status = MMixerGetFilterTopologyProperty(MixerContext, hDevice,
KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ MixerContext->Close(hDevice);
+ MixerContext->Free(PinsRef);
+ return Status;
+ }
+
+ // get topology connections
+ Status = MMixerGetFilterTopologyProperty(MixerContext, hDevice,
KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ MixerContext->Close(hDevice);
+ MixerContext->Free(PinsRef);
+ MixerContext->Free(NodeTypes);
+ return Status;
+ }
+ // gets connection index of the bridge pin which connects to a node
+ DPRINT("Pin %u\n", OutConnection->Pin);
+
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, OutConnection->Pin,
FALSE, !bInput, &PinConnectionIndexCount, &PinConnectionIndex);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ MixerContext->Close(hDevice);
+ MixerContext->Free(PinsRef);
+ MixerContext->Free(NodeTypes);
+ MixerContext->Free(NodeConnections);
+ return Status;
+ }
+
+ /* there should be no split in the bride pin */
+ ASSERT(PinConnectionIndexCount == 1);
+
+ /* find all target pins of this connection */
+ Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext, NodeConnections,
NodeTypes, FALSE, PinConnectionIndex[0], PinsRef);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ MixerContext->Close(hDevice);
+ MixerContext->Free(PinsRef);
+ MixerContext->Free(NodeTypes);
+ MixerContext->Free(NodeConnections);
+ MixerContext->Free(PinConnectionIndex);
+ return Status;
+ }
+
+ for(Index = 0; Index < PinsRefCount; Index++)
+ {
+ if (PinsRef[Index])
+ {
+ // found a target pin, now get all references
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, Index, FALSE,
FALSE, &MixerControlsCount, &MixerControls);
+ if (Status != MM_STATUS_SUCCESS)
+ break;
+
+ /* sanity check */
+ ASSERT(MixerControlsCount == 1);
+
+ PinsSrcRef = (PULONG)MixerContext->Alloc(PinsRefCount * sizeof(ULONG));
+ if (!PinsSrcRef)
+ {
+ /* no memory */
+ MixerContext->Close(hDevice);
+ MixerContext->Free(PinsRef);
+ MixerContext->Free(NodeTypes);
+ MixerContext->Free(NodeConnections);
+ MixerContext->Free(PinConnectionIndex);
+ MixerContext->Free(MixerControls);
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ // now get all connected source pins
+ Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext,
NodeConnections, NodeTypes, TRUE, MixerControls[0], PinsSrcRef);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ // failed */
+ MixerContext->Close(hDevice);
+ MixerContext->Free(PinsRef);
+ MixerContext->Free(NodeTypes);
+ MixerContext->Free(NodeConnections);
+ MixerContext->Free(PinConnectionIndex);
+ MixerContext->Free(MixerControls);
+ MixerContext->Free(PinsSrcRef);
+ return Status;
+ }
+
+ /* add pins from target line */
+ if (!bInput)
+ {
+ // dont add bridge pin for input mixers
+ PinsSrcRef[Index] = TRUE;
+ PinsSrcRef[OutConnection->Pin] = TRUE;
+ }
+ PinsSrcRef[OutConnection->Pin] = TRUE;
+
+ Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, FileObject,
NodeConnections, NodeTypes, PinsRefCount, OutConnection->Pin, Index, PinsSrcRef);
+
+ MixerContext->Free(MixerControls);
+ MixerContext->Free(PinsSrcRef);
+ }
+ }
+
+ return Status;
+}
+
+
+MIXER_STATUS
+MMixerInitializeFilter(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer,
+ IN LPWSTR DeviceName,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN ULONG PinCount,
+ IN ULONG NodeIndex,
+ IN ULONG bInputMixer)
+{
+ LPMIXER_INFO MixerInfo;
+ MIXER_STATUS Status;
+ PKSPIN_PHYSICALCONNECTION OutConnection;
+ ULONG Index;
+ ULONG * Pins;
+
+ // allocate a mixer info struct
+ MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
+ if (!MixerInfo)
+ {
+ // no memory
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ // 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;
+ MixerInfo->hMixer = hMixer;
+
+ // initialize line list
+ InitializeListHead(&MixerInfo->LineList);
+
+ /* FIXME find mixer name */
+
+ Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInputMixer);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ // failed to create destination line
+ MixerContext->Free(MixerInfo);
+ return Status;
+ }
+
+
+ // now allocate an array which will receive the indices of the pin
+ // which has a ADC / DAC nodetype in its path
+ Pins = (PULONG)MixerContext->Alloc(PinCount * sizeof(ULONG));
+
+ if (!Pins)
+ {
+ // no memory
+ MMixerFreeMixerInfo(MixerContext, MixerInfo);
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ // now get the target pins of the ADC / DAC node
+ Status = MMixerGetTargetPins(MixerContext, NodeTypes, NodeConnections, NodeIndex,
bInputMixer, Pins, PinCount);
+
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ // failed to locate target pins
+ MixerContext->Free(Pins);
+ MMixerFreeMixerInfo(MixerContext, MixerInfo);
+ return Status;
+ }
+
+ // now check all pins and generate new lines for destination lines
+ for(Index = 0; Index < PinCount; Index++)
+ {
+ // is the current index a target pin
+ if (Pins[Index])
+ {
+ // check if the pin has a physical connection
+ Status = MMixerGetPhysicalConnection(MixerContext, hMixer, Index,
&OutConnection);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ // the pin has a physical connection
+ Status = MMixerHandlePhysicalConnection(MixerContext, MixerInfo,
bInputMixer, OutConnection);
+
+ MixerContext->Free(OutConnection);
+ }
+ }
+ }
+ MixerContext->Free(Pins);
+
+ //FIXME
+ // store MixerInfo in context
+
+
+ // done
+ return Status;
+}
+
+MIXER_STATUS
+MMixerSetupFilter(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer,
+ IN PULONG DeviceCount,
+ IN LPWSTR DeviceName)
+{
+ PKSMULTIPLE_ITEM NodeTypes, NodeConnections;
+ MIXER_STATUS Status;
+ ULONG PinCount;
+ ULONG NodeIndex;
+
+ // get number of pins
+ PinCount = MMixerGetFilterPinCount(MixerContext, hMixer);
+ ASSERT(PinCount);
+
+
+ // get filter node types
+ Status = MMixerGetFilterTopologyProperty(MixerContext, hMixer,
KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ // failed
+ return Status;
+ }
+
+ // get filter node connections
+ Status = MMixerGetFilterTopologyProperty(MixerContext, hMixer,
KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ // failed
+ MixerContext->Free(NodeTypes);
+ return Status;
+ }
+
+ // check if the filter has an wave out node
+ NodeIndex = MMixerGetIndexOfGuid(NodeTypes, &KSNODETYPE_DAC);
+ if (NodeIndex != MAXULONG)
+ {
+ // it has
+ Status = MMixerInitializeFilter(MixerContext, hMixer, DeviceName, NodeTypes,
NodeConnections, PinCount, NodeIndex, FALSE);
+
+ // check for success
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ // increment mixer count
+ (*DeviceCount)++;
+ }
+
+ }
+
+ // check if the filter has an wave in node
+ NodeIndex = MMixerGetIndexOfGuid(NodeTypes, &KSNODETYPE_ADC);
+ if (NodeIndex != MAXULONG)
+ {
+ // it has
+ Status = MMixerInitializeFilter(MixerContext, hMixer, DeviceName, NodeTypes,
NodeConnections, PinCount, NodeIndex, TRUE);
+
+ // check for success
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ // increment mixer count
+ (*DeviceCount)++;
+ }
+
+ }
+
+ //free resources
+ MixerContext->Free((PVOID)NodeTypes);
+ MixerContext->Free((PVOID)NodeConnections);
+
+ // done
+ return Status;
+}
Propchange: trunk/reactos/lib/drivers/sound/mmixer/controls.c
------------------------------------------------------------------------------
svn:eol-style = native
Added: trunk/reactos/lib/drivers/sound/mmixer/filter.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/f…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmixer/filter.c (added)
+++ trunk/reactos/lib/drivers/sound/mmixer/filter.c [iso-8859-1] Tue Dec 8 22:10:02 2009
@@ -1,0 +1,207 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Kernel Streaming
+ * FILE: lib/drivers/sound/mmixer/filter.c
+ * PURPOSE: Mixer Filter Functions
+ * PROGRAMMER: Johannes Anderwald
+ */
+
+
+
+#include "priv.h"
+
+ULONG
+MMixerGetFilterPinCount(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer)
+{
+ KSPROPERTY Pin;
+ MIXER_STATUS Status;
+ ULONG NumPins, BytesReturned;
+
+ // setup property request
+ Pin.Flags = KSPROPERTY_TYPE_GET;
+ Pin.Set = KSPROPSETID_Pin;
+ Pin.Id = KSPROPERTY_PIN_CTYPES;
+
+ // query pin count
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin,
sizeof(KSPROPERTY), (PVOID)&NumPins, sizeof(ULONG), (PULONG)&BytesReturned);
+
+ // check for success
+ if (Status != MM_STATUS_SUCCESS)
+ return 0;
+
+ return NumPins;
+}
+
+MIXER_STATUS
+MMixerGetFilterTopologyProperty(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer,
+ IN ULONG PropertyId,
+ OUT PKSMULTIPLE_ITEM * OutMultipleItem)
+{
+ KSPROPERTY Property;
+ PKSMULTIPLE_ITEM MultipleItem;
+ MIXER_STATUS Status;
+ ULONG BytesReturned;
+
+ // setup property request
+ Property.Id = PropertyId;
+ Property.Flags = KSPROPERTY_TYPE_GET;
+ Property.Set = KSPROPSETID_Topology;
+
+ // query for the size
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property,
sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
+
+ if (Status != MM_STATUS_MORE_ENTRIES)
+ return Status;
+
+ // allocate an result buffer
+ MultipleItem = (PKSMULTIPLE_ITEM)MixerContext->Alloc(BytesReturned);
+
+ if (!MultipleItem)
+ {
+ // not enough memory
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ // query again with allocated buffer
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property,
sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
+
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ // failed
+ MixerContext->Free((PVOID)MultipleItem);
+ return Status;
+ }
+
+ // store result
+ *OutMultipleItem = MultipleItem;
+
+ // done
+ return Status;
+}
+
+MIXER_STATUS
+MMixerGetPhysicalConnection(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer,
+ IN ULONG PinId,
+ OUT PKSPIN_PHYSICALCONNECTION *OutConnection)
+{
+ KSP_PIN Pin;
+ MIXER_STATUS 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 = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin,
sizeof(KSP_PIN), NULL, 0, &BytesReturned);
+
+ if (Status == MM_STATUS_UNSUCCESSFUL)
+ {
+ // pin does not have a physical connection
+ return Status;
+ }
+
+ Connection = (PKSPIN_PHYSICALCONNECTION)MixerContext->Alloc(BytesReturned);
+ if (!Connection)
+ {
+ // not enough memory
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ // query the pin for the physical connection
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin,
sizeof(KSP_PIN), (PVOID)Connection, BytesReturned, &BytesReturned);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ // failed to query the physical connection
+ MixerContext->Free(Connection);
+ return Status;
+ }
+
+ // store connection
+ *OutConnection = Connection;
+ return Status;
+}
+
+ULONG
+MMixerGetControlTypeFromTopologyNode(
+ 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;
+}
Propchange: trunk/reactos/lib/drivers/sound/mmixer/filter.c
------------------------------------------------------------------------------
svn:eol-style = native
Modified: trunk/reactos/lib/drivers/sound/mmixer/mixer.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/m…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmixer/mixer.c [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mmixer/mixer.c [iso-8859-1] Tue Dec 8 22:10:02 2009
@@ -11,311 +11,8 @@
#include "priv.h"
MIXER_STATUS
-MMixerVerifyContext(
- IN PMIXER_CONTEXT MixerContext)
-{
- if (MixerContext->SizeOfStruct != sizeof(MIXER_CONTEXT))
- return MM_STATUS_INVALID_PARAMETER;
-
- if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free)
- return MM_STATUS_INVALID_PARAMETER;
-
- if (!MixerContext->MixerContext)
- return MM_STATUS_INVALID_PARAMETER;
-
- return MM_STATUS_SUCCESS;
-}
-
-VOID
-MMixerFreeMixerInfo(
+MMixerInitialize(
IN PMIXER_CONTEXT MixerContext,
- IN LPMIXER_INFO MixerInfo)
-{
- //UNIMPLEMENTED
- // FIXME
- // free all lines
-
- MixerContext->Free((PVOID)MixerInfo);
-}
-
-ULONG
-MMixerGetFilterPinCount(
- IN PMIXER_CONTEXT MixerContext,
- IN HANDLE hMixer)
-{
- KSPROPERTY Pin;
- MIXER_STATUS Status;
- ULONG NumPins, BytesReturned;
-
- // setup property request
- Pin.Flags = KSPROPERTY_TYPE_GET;
- Pin.Set = KSPROPSETID_Pin;
- Pin.Id = KSPROPERTY_PIN_CTYPES;
-
- // query pin count
- Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin,
sizeof(KSPROPERTY), (PVOID)&NumPins, sizeof(ULONG), (PULONG)&BytesReturned);
-
- // check for success
- if (Status != MM_STATUS_SUCCESS)
- return 0;
-
- return NumPins;
-}
-
-ULONG
-MMixerGetIndexOfGuid(
- PKSMULTIPLE_ITEM MultipleItem,
- LPCGUID NodeType)
-{
- ULONG Index;
- LPGUID Guid;
-
- Guid = (LPGUID)(MultipleItem+1);
-
- /* iterate through node type array */
- for(Index = 0; Index < MultipleItem->Count; Index++)
- {
- if (IsEqualGUIDAligned(NodeType, Guid))
- {
- /* found matching guid */
- return Index;
- }
- Guid++;
- }
- return MAXULONG;
-}
-
-
-MIXER_STATUS
-MMixerGetFilterTopologyProperty(
- IN PMIXER_CONTEXT MixerContext,
- IN HANDLE hMixer,
- IN ULONG PropertyId,
- OUT PKSMULTIPLE_ITEM * OutMultipleItem)
-{
- KSPROPERTY Property;
- PKSMULTIPLE_ITEM MultipleItem;
- MIXER_STATUS Status;
- ULONG BytesReturned;
-
- // setup property request
- Property.Id = PropertyId;
- Property.Flags = KSPROPERTY_TYPE_GET;
- Property.Set = KSPROPSETID_Topology;
-
- // query for the size
- Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property,
sizeof(KSPROPERTY), NULL, 0, &BytesReturned);
-
- if (Status != MM_STATUS_MORE_ENTRIES)
- return Status;
-
- // allocate an result buffer
- MultipleItem = (PKSMULTIPLE_ITEM)MixerContext->Alloc(BytesReturned);
-
- if (!MultipleItem)
- {
- // not enough memory
- return MM_STATUS_NO_MEMORY;
- }
-
- // query again with allocated buffer
- Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property,
sizeof(KSPROPERTY), (PVOID)MultipleItem, BytesReturned, &BytesReturned);
-
- if (Status != MM_STATUS_SUCCESS)
- {
- // failed
- MixerContext->Free((PVOID)MultipleItem);
- return Status;
- }
-
- // store result
- *OutMultipleItem = MultipleItem;
-
- // done
- return Status;
-}
-
-MIXER_STATUS
-MMixerCreateDestinationLine(
- IN PMIXER_CONTEXT MixerContext,
- IN LPMIXER_INFO MixerInfo,
- IN ULONG bInputMixer)
-{
- LPMIXERLINE_EXT DestinationLine;
-
- // allocate a mixer destination line
- DestinationLine = (LPMIXERLINE_EXT) MixerContext->Alloc(sizeof(MIXERLINE_EXT));
- if (!MixerInfo)
- {
- // no memory
- return MM_STATUS_NO_MEMORY;
- }
-
- /* initialize mixer destination line */
- DestinationLine->Line.cbStruct = sizeof(MIXERLINEW);
- DestinationLine->Line.dwSource = MAXULONG;
- DestinationLine->Line.dwLineID = DESTINATION_LINE;
- DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE;
- DestinationLine->Line.dwUser = 0;
- DestinationLine->Line.dwComponentType = (bInputMixer == 0 ?
MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
- DestinationLine->Line.cChannels = 2; //FIXME
- wcscpy(DestinationLine->Line.szShortName, L"Summe"); //FIXME
- wcscpy(DestinationLine->Line.szName, L"Summe"); //FIXME
- DestinationLine->Line.Target.dwType = (bInputMixer == 0 ?
MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
- DestinationLine->Line.Target.dwDeviceID = !bInputMixer;
- DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
- DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
- DestinationLine->Line.Target.vDriverVersion =
MixerInfo->MixCaps.vDriverVersion;
- wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
-
-
- // insert into mixer info
- InsertHeadList(&MixerInfo->LineList, &DestinationLine->Entry);
-
- // done
- return MM_STATUS_SUCCESS;
-}
-
-MIXER_STATUS
-MMixerInitializeFilter(
- IN PMIXER_CONTEXT MixerContext,
- IN HANDLE hMixer,
- IN LPWSTR DeviceName,
- IN PKSMULTIPLE_ITEM NodeTypes,
- IN PKSMULTIPLE_ITEM NodeConnections,
- IN ULONG PinCount,
- IN ULONG NodeIndex,
- IN ULONG bInputMixer)
-{
- LPMIXER_INFO MixerInfo;
- MIXER_STATUS Status;
- ULONG * Pins;
-
- // allocate a mixer info struct
- MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
- if (!MixerInfo)
- {
- // no memory
- return MM_STATUS_NO_MEMORY;
- }
-
- // 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;
- MixerInfo->hMixer = hMixer;
-
- // initialize line list
- InitializeListHead(&MixerInfo->LineList);
-
- /* FIXME find mixer name */
-
- Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInputMixer);
- if (Status != MM_STATUS_SUCCESS)
- {
- // failed to create destination line
- MixerContext->Free(MixerInfo);
- return Status;
- }
-
-
- // now allocate an array which will receive the indices of the pin
- // which has a ADC / DAC nodetype in its path
- Pins = (PULONG)MixerContext->Alloc(PinCount * sizeof(ULONG));
-
- if (!Pins)
- {
- // no memory
- MMixerFreeMixerInfo(MixerContext, MixerInfo);
- return MM_STATUS_NO_MEMORY;
- }
-
-
- //UNIMPLEMENTED
- // get target pins and find all nodes
- return MM_STATUS_NOT_IMPLEMENTED;
-}
-
-MIXER_STATUS
-MMixerSetupFilter(
- IN PMIXER_CONTEXT MixerContext,
- IN HANDLE hMixer,
- IN PULONG DeviceCount,
- IN LPWSTR DeviceName)
-{
- PKSMULTIPLE_ITEM NodeTypes, NodeConnections;
- MIXER_STATUS Status;
- ULONG PinCount;
- ULONG NodeIndex;
-
- // get number of pins
- PinCount = MMixerGetFilterPinCount(MixerContext, hMixer);
- ASSERT(PinCount);
-
-
- // get filter node types
- Status = MMixerGetFilterTopologyProperty(MixerContext, hMixer,
KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
- if (Status != MM_STATUS_SUCCESS)
- {
- // failed
- return Status;
- }
-
- // get filter node connections
- Status = MMixerGetFilterTopologyProperty(MixerContext, hMixer,
KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
- if (Status != MM_STATUS_SUCCESS)
- {
- // failed
- MixerContext->Free(NodeTypes);
- return Status;
- }
-
- // check if the filter has an wave out node
- NodeIndex = MMixerGetIndexOfGuid(NodeTypes, &KSNODETYPE_DAC);
- if (NodeIndex != MAXULONG)
- {
- // it has
- Status = MMixerInitializeFilter(MixerContext, hMixer, DeviceName, NodeTypes,
NodeConnections, PinCount, NodeIndex, FALSE);
-
- // check for success
- if (Status == MM_STATUS_SUCCESS)
- {
- // increment mixer count
- (*DeviceCount)++;
- }
-
- }
-
- // check if the filter has an wave in node
- NodeIndex = MMixerGetIndexOfGuid(NodeTypes, &KSNODETYPE_ADC);
- if (NodeIndex != MAXULONG)
- {
- // it has
- Status = MMixerInitializeFilter(MixerContext, hMixer, DeviceName, NodeTypes,
NodeConnections, PinCount, NodeIndex, TRUE);
-
- // check for success
- if (Status == MM_STATUS_SUCCESS)
- {
- // increment mixer count
- (*DeviceCount)++;
- }
-
- }
-
- //free resources
- MixerContext->Free((PVOID)NodeTypes);
- MixerContext->Free((PVOID)NodeConnections);
-
- // done
- return Status;
-}
-
-
-MIXER_STATUS
-MMixerInitialize(
- IN PMIXER_CONTEXT MixerContext,
IN PMIXER_ENUM EnumFunction,
IN PVOID EnumContext)
{
Modified: trunk/reactos/lib/drivers/sound/mmixer/mmixer.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/m…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmixer/mmixer.h [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mmixer/mmixer.h [iso-8859-1] Tue Dec 8 22:10:02 2009
@@ -37,7 +37,12 @@
ULONG nOutBufferSize,
PULONG lpBytesReturned);
+typedef MIXER_STATUS(*PMIXER_OPEN)(
+ IN LPCWSTR DevicePath,
+ OUT PHANDLE hDevice);
+typedef MIXER_STATUS(*PMIXER_CLOSE)(
+ IN HANDLE hDevice);
typedef VOID (*PMIXER_EVENT)(
IN PVOID MixerEvent);
@@ -51,6 +56,8 @@
PMIXER_ALLOC Alloc;
PMIXER_DEVICE_CONTROL Control;
PMIXER_FREE Free;
+ PMIXER_OPEN Open;
+ PMIXER_CLOSE Close;
}MIXER_CONTEXT, *PMIXER_CONTEXT;
Modified: trunk/reactos/lib/drivers/sound/mmixer/mmixer.rbuild
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/m…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmixer/mmixer.rbuild [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mmixer/mmixer.rbuild [iso-8859-1] Tue Dec 8 22:10:02
2009
@@ -3,5 +3,8 @@
<module name="mmixer" type="staticlibrary"
allowwarnings="false" unicode="yes">
<include base="ReactOS">include/reactos/libs/sound</include>
<define name="NDEBUG">1</define>
+ <file>controls.c</file>
+ <file>filter.c</file>
<file>mixer.c</file>
+ <file>sup.c</file>
</module>
Modified: trunk/reactos/lib/drivers/sound/mmixer/priv.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/p…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmixer/priv.h [iso-8859-1] (original)
+++ trunk/reactos/lib/drivers/sound/mmixer/priv.h [iso-8859-1] Tue Dec 8 22:10:02 2009
@@ -14,6 +14,8 @@
#include "mmixer.h"
+#include <debug.h>
+
typedef struct
{
MIXERCAPSW MixCaps;
@@ -26,13 +28,124 @@
{
LIST_ENTRY Entry;
ULONG PinId;
- ULONG DeviceIndex;
+ HANDLE hDevice;
MIXERLINEW Line;
LPMIXERCONTROLW LineControls;
PULONG NodeIds;
LIST_ENTRY LineControlsExtraData;
}MIXERLINE_EXT, *LPMIXERLINE_EXT;
+typedef struct
+{
+ LIST_ENTRY Entry;
+ ULONG dwControlID;
+}MIXERCONTROL_DATA, *LPMIXERCONTROL_DATA;
+
+typedef struct
+{
+ MIXERCONTROL_DATA Header;
+ LONG SignedMinimum;
+ LONG SignedMaximum;
+ LONG SteppingDelta;
+ ULONG InputSteppingDelta;
+ ULONG ValuesCount;
+ PLONG Values;
+}MIXERVOLUME_DATA, *LPMIXERVOLUME_DATA;
+
+
#define DESTINATION_LINE 0xFFFF0000
+ULONG
+MMixerGetFilterPinCount(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer);
+
+LPGUID
+MMixerGetNodeType(
+ IN PKSMULTIPLE_ITEM MultipleItem,
+ IN ULONG Index);
+
+MIXER_STATUS
+MMixerGetNodeIndexes(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PKSMULTIPLE_ITEM MultipleItem,
+ IN ULONG NodeIndex,
+ IN ULONG bNode,
+ IN ULONG bFrom,
+ OUT PULONG NodeReferenceCount,
+ OUT PULONG *NodeReference);
+
+PKSTOPOLOGY_CONNECTION
+MMixerGetConnectionByIndex(
+ IN PKSMULTIPLE_ITEM MultipleItem,
+ IN ULONG Index);
+
+ULONG
+MMixerGetControlTypeFromTopologyNode(
+ IN LPGUID NodeType);
+
+LPMIXERLINE_EXT
+MMixerGetSourceMixerLineByLineId(
+ LPMIXER_INFO MixerInfo,
+ DWORD dwLineID);
+
+MIXER_STATUS
+MMixerGetFilterTopologyProperty(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer,
+ IN ULONG PropertyId,
+ OUT PKSMULTIPLE_ITEM * OutMultipleItem);
+
+VOID
+MMixerFreeMixerInfo(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_INFO MixerInfo);
+
+MIXER_STATUS
+MMixerGetTargetPins(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN ULONG NodeIndex,
+ IN ULONG bUpDirection,
+ OUT PULONG Pins,
+ IN ULONG PinCount);
+
+MIXER_STATUS
+MMixerGetPhysicalConnection(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer,
+ IN ULONG PinId,
+ OUT PKSPIN_PHYSICALCONNECTION *OutConnection);
+
+ULONG
+MMixerGetIndexOfGuid(
+ PKSMULTIPLE_ITEM MultipleItem,
+ LPCGUID NodeType);
+
+MIXER_STATUS
+MMixerSetupFilter(
+ IN PMIXER_CONTEXT MixerContext,
+ IN HANDLE hMixer,
+ IN PULONG DeviceCount,
+ IN LPWSTR DeviceName);
+
+MIXER_STATUS
+MMixerGetTargetPinsByNodeConnectionIndex(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN ULONG bUpDirection,
+ IN ULONG NodeConnectionIndex,
+ OUT PULONG Pins);
+
+MIXER_STATUS
+MMixerGetControlsFromPin(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN ULONG PinId,
+ IN ULONG bUpDirection,
+ OUT PULONG Nodes);
+
#endif
Added: trunk/reactos/lib/drivers/sound/mmixer/sup.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/lib/drivers/sound/mmixer/s…
==============================================================================
--- trunk/reactos/lib/drivers/sound/mmixer/sup.c (added)
+++ trunk/reactos/lib/drivers/sound/mmixer/sup.c [iso-8859-1] Tue Dec 8 22:10:02 2009
@@ -1,0 +1,282 @@
+/*
+ * COPYRIGHT: See COPYING in the top level directory
+ * PROJECT: ReactOS Kernel Streaming
+ * FILE: lib/drivers/sound/mmixer/sup.c
+ * PURPOSE: Mixer Support Functions
+ * PROGRAMMER: Johannes Anderwald
+ */
+
+
+
+#include "priv.h"
+
+MIXER_STATUS
+MMixerVerifyContext(
+ IN PMIXER_CONTEXT MixerContext)
+{
+ if (MixerContext->SizeOfStruct != sizeof(MIXER_CONTEXT))
+ return MM_STATUS_INVALID_PARAMETER;
+
+ if (!MixerContext->Alloc || !MixerContext->Control || !MixerContext->Free)
+ return MM_STATUS_INVALID_PARAMETER;
+
+ if (!MixerContext->MixerContext)
+ return MM_STATUS_INVALID_PARAMETER;
+
+ return MM_STATUS_SUCCESS;
+}
+
+VOID
+MMixerFreeMixerInfo(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_INFO MixerInfo)
+{
+ //UNIMPLEMENTED
+ // FIXME
+ // free all lines
+
+ MixerContext->Free((PVOID)MixerInfo);
+}
+
+LPMIXERLINE_EXT
+MMixerGetSourceMixerLineByLineId(
+ LPMIXER_INFO MixerInfo,
+ DWORD dwLineID)
+{
+ PLIST_ENTRY Entry;
+ LPMIXERLINE_EXT MixerLineSrc;
+
+ /* get first entry */
+ Entry = MixerInfo->LineList.Flink;
+
+ while(Entry != &MixerInfo->LineList)
+ {
+ MixerLineSrc = (LPMIXERLINE_EXT)CONTAINING_RECORD(Entry, MIXERLINE_EXT, Entry);
+ DPRINT("dwLineID %x dwLineID %x\n", MixerLineSrc->Line.dwLineID,
dwLineID);
+ if (MixerLineSrc->Line.dwLineID == dwLineID)
+ return MixerLineSrc;
+
+ Entry = Entry->Flink;
+ }
+
+ return NULL;
+}
+
+ULONG
+MMixerGetIndexOfGuid(
+ PKSMULTIPLE_ITEM MultipleItem,
+ LPCGUID NodeType)
+{
+ ULONG Index;
+ LPGUID Guid;
+
+ Guid = (LPGUID)(MultipleItem+1);
+
+ /* iterate through node type array */
+ for(Index = 0; Index < MultipleItem->Count; Index++)
+ {
+ if (IsEqualGUIDAligned(NodeType, Guid))
+ {
+ /* found matching guid */
+ return Index;
+ }
+ Guid++;
+ }
+ return MAXULONG;
+}
+
+PKSTOPOLOGY_CONNECTION
+MMixerGetConnectionByIndex(
+ IN PKSMULTIPLE_ITEM MultipleItem,
+ IN ULONG Index)
+{
+ PKSTOPOLOGY_CONNECTION Descriptor;
+
+ ASSERT(Index < MultipleItem->Count);
+
+ Descriptor = (PKSTOPOLOGY_CONNECTION)(MultipleItem + 1);
+ return &Descriptor[Index];
+}
+
+LPGUID
+MMixerGetNodeType(
+ IN PKSMULTIPLE_ITEM MultipleItem,
+ IN ULONG Index)
+{
+ LPGUID NodeType;
+
+ ASSERT(Index < MultipleItem->Count);
+
+ NodeType = (LPGUID)(MultipleItem + 1);
+ return &NodeType[Index];
+}
+
+MIXER_STATUS
+MMixerGetNodeIndexes(
+ IN PMIXER_CONTEXT MixerContext,
+ 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++)
+ {
+ 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 &&
Connection->FromNode == KSFILTER_NODE)
+ {
+ // node id has a connection
+ Count++;
+ }
+ }
+ else
+ {
+ if (Connection->ToNodePin == NodeIndex &&
Connection->ToNode == KSFILTER_NODE)
+ {
+ // node id has a connection
+ Count++;
+ }
+ }
+ }
+
+
+ // move to next connection
+ Connection++;
+ }
+
+ ASSERT(Count != 0);
+
+ /* now allocate node index array */
+ Refs = (PULONG)MixerContext->Alloc(sizeof(ULONG) * Count);
+ if (!Refs)
+ {
+ // not enough memory
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ 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 &&
Connection->FromNode == KSFILTER_NODE)
+ {
+ /* node id has a connection */
+ Refs[Count] = Index;
+ Count++;
+ }
+ }
+ else
+ {
+ if (Connection->ToNodePin == NodeIndex &&
Connection->ToNode == KSFILTER_NODE)
+ {
+ /* node id has a connection */
+ Refs[Count] = Index;
+ Count++;
+ }
+ }
+ }
+
+ /* move to next connection */
+ Connection++;
+ }
+
+ /* store result */
+ *NodeReference = Refs;
+ *NodeReferenceCount = Count;
+
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerGetTargetPins(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PKSMULTIPLE_ITEM NodeTypes,
+ IN PKSMULTIPLE_ITEM NodeConnections,
+ IN ULONG NodeIndex,
+ IN ULONG bUpDirection,
+ OUT PULONG Pins,
+ IN ULONG PinCount)
+{
+ ULONG NodeConnectionCount, Index;
+ MIXER_STATUS Status;
+ PULONG NodeConnection;
+
+ // sanity check */
+ ASSERT(NodeIndex != (ULONG)-1);
+
+ /* get all node indexes referenced by that pin */
+ if (bUpDirection)
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE,
FALSE, &NodeConnectionCount, &NodeConnection);
+ else
+ Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, NodeIndex, TRUE,
TRUE, &NodeConnectionCount, &NodeConnection);
+
+ //DPRINT("NodeIndex %u Status %x Count %u\n", NodeIndex, Status,
NodeConnectionCount);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ for(Index = 0; Index < NodeConnectionCount; Index++)
+ {
+ Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext,
NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Pins);
+ ASSERT(Status == STATUS_SUCCESS);
+ }
+ MixerContext->Free((PVOID)NodeConnection);
+ }
+
+ return Status;
+}
Propchange: trunk/reactos/lib/drivers/sound/mmixer/sup.c
------------------------------------------------------------------------------
svn:eol-style = native