[ros-diffs] [janderwald] 44473: [MMIXER] - Finish porting of code from wdmaud

janderwald at svn.reactos.org janderwald at svn.reactos.org
Tue Dec 8 22:10:02 CET 2009


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/controls.c?rev=44473&view=auto
==============================================================================
--- 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/filter.c?rev=44473&view=auto
==============================================================================
--- 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/mixer.c?rev=44473&r1=44472&r2=44473&view=diff
==============================================================================
--- 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/mmixer.h?rev=44473&r1=44472&r2=44473&view=diff
==============================================================================
--- 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/mmixer.rbuild?rev=44473&r1=44472&r2=44473&view=diff
==============================================================================
--- 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/priv.h?rev=44473&r1=44472&r2=44473&view=diff
==============================================================================
--- 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/sup.c?rev=44473&view=auto
==============================================================================
--- 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




More information about the Ros-diffs mailing list