#include "priv.h"
-MIXER_STATUS
-MMixerGetTargetPinsByNodeConnectionIndex(
- IN PMIXER_CONTEXT MixerContext,
- IN PKSMULTIPLE_ITEM NodeConnections,
- IN PKSMULTIPLE_ITEM NodeTypes,
- IN ULONG bUpDirection,
- IN ULONG NodeConnectionIndex,
- IN ULONG PinCount,
- 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]);
-
- // sanity check
- ASSERT(PinId < PinCount);
-
- /* 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], PinCount, 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;
-
- if (NodeIndex > NodeTypes->Count)
- {
- // reached end of pin connection
- return MM_STATUS_SUCCESS;
- }
-
- /* 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;
-}
+const GUID KSNODETYPE_DESKTOP_MICROPHONE = {0xDFF21BE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_LEGACY_AUDIO_CONNECTOR = {0xDFF21FE4, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_TELEPHONE = {0xDFF21EE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_PHONE_LINE = {0xDFF21EE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_DOWN_LINE_PHONE = {0xDFF21EE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_DESKTOP_SPEAKER = {0xDFF21CE4, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_ROOM_SPEAKER = {0xDFF21CE5, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_COMMUNICATION_SPEAKER = {0xDFF21CE6, 0xF70F, 0x11D0, {0xB9,0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_HEADPHONES = {0xDFF21CE2, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO = {0xDFF21CE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_MICROPHONE = {0xDFF21BE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9,0x22, 0x31, 0x96}};
+const GUID KSCATEGORY_AUDIO = {0x6994AD04L, 0x93EF, 0x11D0, {0xA3, 0xCC, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_SPDIF_INTERFACE = {0xDFF21FE5, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_ANALOG_CONNECTOR = {0xDFF21FE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_SPEAKER = {0xDFF21CE1, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_CD_PLAYER = {0xDFF220E3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_SYNTHESIZER = {0xDFF220F3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0, 0xC9, 0x22, 0x31, 0x96}};
+const GUID KSNODETYPE_LINE_CONNECTOR = {0xDFF21FE3, 0xF70F, 0x11D0, {0xB9, 0x17, 0x00, 0xA0,0xC9, 0x22, 0x31, 0x96}};
+const GUID PINNAME_VIDEO_CAPTURE = {0xfb6c4281, 0x353, 0x11d1, {0x90, 0x5f, 0x0, 0x0, 0xc0, 0xcc, 0x16, 0xba}};
MIXER_STATUS
MMixerAddMixerControl(
IN PMIXER_CONTEXT MixerContext,
IN LPMIXER_INFO MixerInfo,
- IN HANDLE hDevice,
- IN PKSMULTIPLE_ITEM NodeTypes,
+ IN HANDLE hMixer,
+ IN PTOPOLOGY Topology,
IN ULONG NodeIndex,
- IN LPMIXERLINE_EXT MixerLine,
- OUT LPMIXERCONTROLW MixerControl)
+ IN LPMIXERLINE_EXT MixerLine)
{
LPGUID NodeType;
KSP_NODE Node;
ULONG BytesReturned;
MIXER_STATUS Status;
LPWSTR Name;
+ LPMIXERCONTROL_EXT MixerControl;
+
+ /* allocate mixer control */
+ MixerControl = MixerContext->Alloc(sizeof(MIXERCONTROL_EXT));
+ if (!MixerControl)
+ {
+ /* no memory */
+ return MM_STATUS_NO_MEMORY;
+ }
+
/* initialize mixer control */
- MixerControl->cbStruct = sizeof(MIXERCONTROLW);
- MixerControl->dwControlID = MixerInfo->ControlId;
+ MixerControl->hDevice = hMixer;
+ MixerControl->NodeID = NodeIndex;
+ MixerControl->ExtraData = NULL;
+
+ MixerControl->Control.cbStruct = sizeof(MIXERCONTROLW);
+ MixerControl->Control.dwControlID = MixerInfo->ControlId;
/* get node type */
- NodeType = MMixerGetNodeType(NodeTypes, NodeIndex);
+ NodeType = MMixerGetNodeTypeFromTopology(Topology, NodeIndex);
/* store control type */
- MixerControl->dwControlType = MMixerGetControlTypeFromTopologyNode(NodeType);
+ MixerControl->Control.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
- }
+ MixerControl->Control.fdwControl = MIXERCONTROL_CONTROLF_UNIFORM; /* FIXME */
+ MixerControl->Control.cMultipleItems = 0;
/* setup request to retrieve name */
Node.NodeId = NodeIndex;
Node.Reserved = 0;
/* get node name size */
- Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), NULL, 0, &BytesReturned);
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), NULL, 0, &BytesReturned);
if (Status == MM_STATUS_MORE_ENTRIES)
{
}
/* get node name */
- Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned);
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Node, sizeof(KSP_NODE), (LPVOID)Name, BytesReturned, &BytesReturned);
if (Status == MM_STATUS_SUCCESS)
{
- MixerContext->Copy(MixerControl->szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
- MixerControl->szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
+ MixerContext->Copy(MixerControl->Control.szShortName, Name, (min(MIXER_SHORT_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
+ MixerControl->Control.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
- MixerContext->Copy(MixerControl->szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
- MixerControl->szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
+ MixerContext->Copy(MixerControl->Control.szName, Name, (min(MIXER_LONG_NAME_CHARS, wcslen(Name)+1)) * sizeof(WCHAR));
+ MixerControl->Control.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
}
/* free name buffer */
MixerContext->Free(Name);
}
+ /* increment control count */
MixerInfo->ControlId++;
-#if 0
- if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_MUX)
+
+ /* insert control */
+ InsertTailList(&MixerLine->ControlsList, &MixerControl->Entry);
+
+ if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_MUX)
{
- KSNODEPROPERTY Property;
- ULONG PinId = 2;
+ ULONG NodesCount;
+ PULONG Nodes;
- /* setup the request */
- RtlZeroMemory(&Property, sizeof(KSNODEPROPERTY));
+ /* allocate topology nodes array */
+ Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &Nodes);
- Property.NodeId = NodeIndex;
- Property.Property.Id = KSPROPERTY_AUDIO_MUX_SOURCE;
- Property.Property.Flags = KSPROPERTY_TYPE_SET;
- Property.Property.Set = KSPROPSETID_Audio;
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* out of memory */
+ return STATUS_NO_MEMORY;
+ }
- /* get node volume level info */
- Status = MixerContext->Control(hDevice, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY), (PVOID)&PinId, sizeof(ULONG), &BytesReturned);
+ /* get connected node count */
+ MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, TRUE, &NodesCount, Nodes);
- DPRINT1("Status %x NodeIndex %u PinId %u\n", Status, NodeIndex, PinId);
- //DbgBreakPoint();
- }else
-#endif
- if (MixerControl->dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
+ /* TODO */
+ MixerContext->Free(Nodes);
+
+ /* setup mux bounds */
+ MixerControl->Control.Bounds.dwMinimum = 0;
+ MixerControl->Control.Bounds.dwMaximum = NodesCount - 1;
+ MixerControl->Control.Metrics.dwReserved[0] = NodesCount;
+ MixerControl->Control.cMultipleItems = NodesCount;
+ MixerControl->Control.fdwControl |= MIXERCONTROL_CONTROLF_MULTIPLE;
+ }
+ else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_MUTE)
+ {
+ MixerControl->Control.Bounds.dwMinimum = 0;
+ MixerControl->Control.Bounds.dwMaximum = 1;
+ }
+ else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_ONOFF)
+ {
+ /* only needs to set bounds */
+ MixerControl->Control.Bounds.dwMinimum = 0;
+ MixerControl->Control.Bounds.dwMaximum = 1;
+ }
+ else if (MixerControl->Control.dwControlType == MIXERCONTROL_CONTROLTYPE_VOLUME)
{
KSNODEPROPERTY_AUDIO_CHANNEL Property;
ULONG Length;
PKSPROPERTY_MEMBERSHEADER Members;
PKSPROPERTY_STEPPING_LONG Range;
+ MixerControl->Control.Bounds.dwMinimum = 0;
+ MixerControl->Control.Bounds.dwMaximum = 0xFFFF;
+ MixerControl->Control.Metrics.cSteps = 0xC0; /* FIXME */
+
Length = sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) + sizeof(KSPROPERTY_STEPPING_LONG);
Desc = (PKSPROPERTY_DESCRIPTION)MixerContext->Alloc(Length);
ASSERT(Desc);
Property.NodeProperty.NodeId = NodeIndex;
Property.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
- Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT;
+ Property.NodeProperty.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY;
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);
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Property, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), Desc, Length, &BytesReturned);
if (Status == MM_STATUS_SUCCESS)
{
Steps = MaxRange / Range->SteppingDelta + 1;
/* store mixer control info there */
- VolumeData->Header.dwControlID = MixerControl->dwControlID;
+ VolumeData->Header.dwControlID = MixerControl->Control.dwControlID;
VolumeData->SignedMaximum = Range->Bounds.SignedMaximum;
VolumeData->SignedMinimum = Range->Bounds.SignedMinimum;
VolumeData->SteppingDelta = Range->SteppingDelta;
VolumeData->Values[Index] = Value;
Value += Range->SteppingDelta;
}
- InsertTailList(&MixerLine->LineControlsExtraData, &VolumeData->Header.Entry);
+ MixerControl->ExtraData = VolumeData;
}
}
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;
- LPGUID Node;
- 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);
-
- ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == L'\0');
- 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])
- {
- // get node type
- Node = MMixerGetNodeType(NodeTypes, Index);
-
- if (MMixerGetControlTypeFromTopologyNode(Node))
- {
- // found a node which can be resolved to a type
- 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])
- {
- // get node type
- Node = MMixerGetNodeType(NodeTypes, Index);
-
- if (MMixerGetControlTypeFromTopologyNode(Node))
- {
- /* 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 == MM_STATUS_MORE_ENTRIES)
- {
- 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)
- {
- MixerContext->Copy(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
- SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
-
- MixerContext->Copy(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++;
- }
-
+ DPRINT("Status %x Name %S\n", Status, MixerControl->Control.szName);
return MM_STATUS_SUCCESS;
}
{
LPMIXERLINE_EXT DestinationLine;
- // allocate a mixer destination line
+ /* allocate a mixer destination line */
DestinationLine = (LPMIXERLINE_EXT) MixerContext->Alloc(sizeof(MIXERLINE_EXT));
if (!MixerInfo)
{
- // no memory
+ /* no memory */
return MM_STATUS_NO_MEMORY;
}
/* initialize mixer destination line */
DestinationLine->Line.cbStruct = sizeof(MIXERLINEW);
+ DestinationLine->Line.cChannels = 2; /* FIXME */
+ DestinationLine->Line.cConnections = 0;
+ DestinationLine->Line.cControls = 0;
+ DestinationLine->Line.dwComponentType = (bInputMixer == 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS : MIXERLINE_COMPONENTTYPE_DST_WAVEIN);
+ DestinationLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations;
+ DestinationLine->Line.dwLineID = MixerInfo->MixCaps.cDestinations + DESTINATION_LINE;
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
+ DestinationLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE;
+
if (LineName)
{
DestinationLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
}
- else
- {
- /* FIXME no name was found for pin */
- wcscpy(DestinationLine->Line.szShortName, L"Summe");
- wcscpy(DestinationLine->Line.szName, L"Summe");
- }
DestinationLine->Line.Target.dwType = (bInputMixer == 0 ? MIXERLINE_TARGETTYPE_WAVEOUT : MIXERLINE_TARGETTYPE_WAVEIN);
- DestinationLine->Line.Target.dwDeviceID = !bInputMixer;
+ DestinationLine->Line.Target.dwDeviceID = 0; //FIXME
DestinationLine->Line.Target.wMid = MixerInfo->MixCaps.wMid;
DestinationLine->Line.Target.wPid = MixerInfo->MixCaps.wPid;
DestinationLine->Line.Target.vDriverVersion = MixerInfo->MixCaps.vDriverVersion;
ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == 0);
wcscpy(DestinationLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
- // initialize extra line
- InitializeListHead(&DestinationLine->LineControlsExtraData);
+ /* initialize extra line */
+ InitializeListHead(&DestinationLine->ControlsList);
+
+ /* insert into mixer info */
+ InsertTailList(&MixerInfo->LineList, &DestinationLine->Entry);
- // insert into mixer info
- InsertHeadList(&MixerInfo->LineList, &DestinationLine->Entry);
+ /* increment destination count */
+ MixerInfo->MixCaps.cDestinations++;
- // done
+ /* done */
return MM_STATUS_SUCCESS;
}
MIXER_STATUS
-MMixerGetControlsFromPin(
+MMixerGetPinName(
IN PMIXER_CONTEXT MixerContext,
- IN PKSMULTIPLE_ITEM NodeConnections,
- IN PKSMULTIPLE_ITEM NodeTypes,
+ IN LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
IN ULONG PinId,
- IN ULONG bUpDirection,
- OUT PULONG Nodes)
+ IN OUT LPWSTR * OutBuffer)
{
- ULONG NodeConnectionCount, Index;
+ KSP_PIN Pin;
+ ULONG BytesReturned;
+ LPWSTR Buffer;
MIXER_STATUS Status;
- PULONG NodeConnection;
- /* sanity check */
- ASSERT(PinId != (ULONG)-1);
+ /* prepare pin */
+ Pin.PinId = PinId;
+ Pin.Reserved = 0;
+ Pin.Property.Flags = KSPROPERTY_TYPE_GET;
+ Pin.Property.Set = KSPROPSETID_Pin;
+ Pin.Property.Id = KSPROPERTY_PIN_NAME;
- /* 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);
+ /* try get pin name size */
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
- for(Index = 0; Index < NodeConnectionCount; Index++)
+ /* check if buffer overflowed */
+ if (Status == MM_STATUS_MORE_ENTRIES)
{
- /* get all associated controls */
- Status = MMixerGetControlsFromPinByConnectionIndex(MixerContext, NodeConnections, NodeTypes, bUpDirection, NodeConnection[Index], Nodes);
- }
+ /* allocate buffer */
+ Buffer = (LPWSTR)MixerContext->Alloc(BytesReturned);
+ if (!Buffer)
+ {
+ /* out of memory */
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* try get pin name */
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Buffer, BytesReturned, &BytesReturned);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to get pin name */
+ MixerContext->Free((PVOID)Buffer);
+ return Status;
+ }
- MixerContext->Free(NodeConnection);
+ /* successfully obtained pin name */
+ *OutBuffer = Buffer;
+ return MM_STATUS_SUCCESS;
+ }
+ /* failed to get pin name */
return Status;
}
-
-
-
MIXER_STATUS
-MMixerAddMixerSourceLines(
+MMixerBuildMixerDestinationLine(
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)
+ IN HANDLE hMixer,
+ IN ULONG PinId,
+ IN ULONG bInput)
{
- ULONG Index;
+ LPWSTR PinName;
+ MIXER_STATUS Status;
- for(Index = PinsCount; Index > 0; Index--)
+ /* try get pin name */
+ Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName);
+ if (Status == MM_STATUS_SUCCESS)
{
- DPRINT("MMixerAddMixerSourceLines Index %lu Pin %lu\n", Index-1, Pins[Index-1]);
- if (Pins[Index-1])
- {
- MMixerAddMixerSourceLine(MixerContext, MixerInfo, hDevice, NodeConnections, NodeTypes, Index-1, (Index -1 == BridgePinIndex), (Index -1 == TargetPinIndex));
- }
+ /* create mixer destination line */
+
+ Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, PinName);
+
+ /* free pin name */
+ MixerContext->Free(PinName);
}
+ else
+ {
+ /* create mixer destination line unlocalized */
+ Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInput, L"No Name");
+ }
+
+ return Status;
+}
+
+MIXER_STATUS
+MMixerBuildTopology(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_DATA MixerData,
+ OUT PTOPOLOGY * OutTopology)
+{
+ ULONG PinsCount;
+ PKSMULTIPLE_ITEM NodeTypes = NULL;
+ PKSMULTIPLE_ITEM NodeConnections = NULL;
+ MIXER_STATUS Status;
+
+ if (MixerData->Topology)
+ {
+ /* re-use existing topology */
+ *OutTopology = MixerData->Topology;
+
+ return MM_STATUS_SUCCESS;
+ }
+
+ /* get connected filter pin count */
+ PinsCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice);
+
+ if (!PinsCount)
+ {
+ /* referenced filter does not have any pins */
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+
+ /* get topology node types */
+ Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to get topology node types */
+ return Status;
+ }
+
+ /* get topology connections */
+ Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to get topology connections */
+ MixerContext->Free(NodeTypes);
+ return Status;
+ }
+
+ /* create a topology */
+ Status = MMixerCreateTopology(MixerContext, PinsCount, NodeConnections, NodeTypes, OutTopology);
+
+ /* free node types & connections */
+ MixerContext->Free(NodeConnections);
+ MixerContext->Free(NodeTypes);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* store topology object */
+ MixerData->Topology = *OutTopology;
+ }
+
+ /* done */
+ return Status;
+}
+
+MIXER_STATUS
+MMixerCountMixerControls(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PTOPOLOGY Topology,
+ IN ULONG PinId,
+ IN ULONG bInputMixer,
+ IN ULONG bUpStream,
+ OUT PULONG OutNodesCount,
+ OUT PULONG OutNodes,
+ OUT PULONG OutLineTerminator)
+{
+ PULONG Nodes;
+ ULONG NodesCount, NodeIndex, Count, bTerminator;
+ MIXER_STATUS Status;
+
+ /* allocate an array to store all nodes which are upstream of this pin */
+ Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &Nodes);
+
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* out of memory */
+ return STATUS_NO_MEMORY;
+ }
+
+ /* mark result array as zero */
+ *OutNodesCount = 0;
+
+ /* get next nodes */
+ MMixerGetNextNodesFromPinIndex(MixerContext, Topology, PinId, bUpStream, &NodesCount, Nodes);
+
+ /* assume no topology split before getting line terminator */
+ ASSERT(NodesCount == 1);
+
+ /* get first node */
+ NodeIndex = Nodes[0];
+ Count = 0;
+
+ do
+ {
+ /* check if the node is a terminator */
+ MMixerIsNodeTerminator(Topology, NodeIndex, &bTerminator);
+
+ if (bTerminator)
+ {
+ /* found terminator */
+ if (bInputMixer)
+ {
+ /* add mux source for source destination line */
+ OutNodes[Count] = NodeIndex;
+ Count++;
+ }
+ break;
+ }
+
+ /* store node id */
+ OutNodes[Count] = NodeIndex;
+
+ /* increment node count */
+ Count++;
+
+ /* get next nodes upstream */
+ MMixerGetNextNodesFromNodeIndex(MixerContext, Topology, NodeIndex, bUpStream, &NodesCount, Nodes);
+
+ /* assume there is a node connected */
+ ASSERT(NodesCount != 0);
+ ASSERT(NodesCount == 1);
+
+ /* use first index */
+ NodeIndex = Nodes[0];
+
+ }while(TRUE);
+
+ /* free node index */
+ MixerContext->Free(Nodes);
+
+ /* store nodes count */
+ *OutNodesCount = Count;
+
+ /* store line terminator */
+ *OutLineTerminator = NodeIndex;
+
+ /* done */
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerGetChannelCountEnhanced(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
+ IN ULONG NodeId,
+ OUT PULONG MaxChannels)
+{
+ KSPROPERTY_DESCRIPTION Description;
+ PKSPROPERTY_DESCRIPTION NewDescription;
+ PKSPROPERTY_MEMBERSHEADER Header;
+ ULONG BytesReturned;
+ KSP_NODE Request;
+ MIXER_STATUS Status;
+
+ /* try #1 obtain it via description */
+ Request.NodeId = NodeId;
+ Request.Reserved = 0;
+ Request.Property.Set = KSPROPSETID_Audio;
+ Request.Property.Flags = KSPROPERTY_TYPE_BASICSUPPORT | KSPROPERTY_TYPE_TOPOLOGY;
+ Request.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
+
+
+ /* get description */
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)&Description, sizeof(KSPROPERTY_DESCRIPTION), &BytesReturned);
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ if (Description.DescriptionSize >= sizeof(KSPROPERTY_DESCRIPTION) + sizeof(KSPROPERTY_MEMBERSHEADER) && (Description.MembersListCount > 0))
+ {
+ /* allocate new description */
+ NewDescription = MixerContext->Alloc(Description.DescriptionSize);
+
+ if (!NewDescription)
+ {
+ /* not enough memory */
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* get description */
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_NODE), (PVOID)NewDescription, Description.DescriptionSize, &BytesReturned);
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* get header */
+ Header = (PKSPROPERTY_MEMBERSHEADER)(NewDescription + 1);
+
+ if (Header->Flags & KSPROPERTY_MEMBER_FLAG_BASICSUPPORT_MULTICHANNEL)
+ {
+ /* found enhanced flag */
+ ASSERT(Header->MembersCount > 1);
+
+ /* store channel count */
+ *MaxChannels = Header->MembersCount;
+
+ /* free description */
+ MixerContext->Free(NewDescription);
+
+ /* done */
+ return MM_STATUS_SUCCESS;
+ }
+ }
+
+ /* free description */
+ MixerContext->Free(NewDescription);
+ }
+ }
+
+ /* failed to get channel count enhanced */
+ return MM_STATUS_UNSUCCESSFUL;
+}
+
+VOID
+MMixerGetChannelCountLegacy(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
+ IN ULONG NodeId,
+ OUT PULONG MaxChannels)
+{
+ ULONG BytesReturned;
+ MIXER_STATUS Status;
+ KSNODEPROPERTY_AUDIO_CHANNEL Channel;
+ LONG Volume;
+
+ /* setup request */
+ Channel.Reserved = 0;
+ Channel.NodeProperty.NodeId = NodeId;
+ Channel.NodeProperty.Reserved = 0;
+ Channel.NodeProperty.Property.Flags = KSPROPERTY_TYPE_GET | KSPROPERTY_TYPE_TOPOLOGY;
+ Channel.NodeProperty.Property.Set = KSPROPSETID_Audio;
+ Channel.Channel = 0;
+ Channel.NodeProperty.Property.Id = KSPROPERTY_AUDIO_VOLUMELEVEL;
+
+ do
+ {
+ /* get channel volume */
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Channel, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL), (PVOID)&Volume, sizeof(LONG), &BytesReturned);
+ if (Status != MM_STATUS_SUCCESS)
+ break;
+
+ /* increment channel count */
+ Channel.Channel++;
+
+ }while(TRUE);
+
+ /* store channel count */
+ *MaxChannels = Channel.Channel;
+
+}
+
+VOID
+MMixerGetMaxChannelsForNode(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
+ IN ULONG NodeId,
+ OUT PULONG MaxChannels)
+{
+ MIXER_STATUS Status;
+
+ /* try to get it enhanced */
+ Status = MMixerGetChannelCountEnhanced(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels);
+
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* get it old-fashioned way */
+ MMixerGetChannelCountLegacy(MixerContext, MixerInfo, hMixer, NodeId, MaxChannels);
+ }
+}
+
+MIXER_STATUS
+MMixerAddMixerControlsToMixerLineByNodeIndexArray(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
+ IN PTOPOLOGY Topology,
+ IN OUT LPMIXERLINE_EXT DstLine,
+ IN ULONG NodesCount,
+ IN PULONG Nodes)
+{
+ ULONG Index, Count, bReserved;
+ MIXER_STATUS Status;
+ LPGUID NodeType;
+ ULONG MaxChannels;
+
+ /* initialize control count */
+ Count = 0;
+
+ for(Index = 0; Index < NodesCount; Index++)
+ {
+ /* check if the node has already been reserved to a line */
+ MMixerIsTopologyNodeReserved(Topology, Nodes[Index], &bReserved);
+#if 0 /* MS lies */
+ if (bReserved)
+ {
+ /* node is already used, skip it */
+ continue;
+ }
+#endif
+ /* set node status as used */
+ MMixerSetTopologyNodeReserved(Topology, Nodes[Index]);
+
+ /* query node type */
+ NodeType = MMixerGetNodeTypeFromTopology(Topology, Nodes[Index]);
+
+ if (IsEqualGUIDAligned(NodeType, &KSNODETYPE_VOLUME))
+ {
+ /* calculate maximum channel count for node */
+ MMixerGetMaxChannelsForNode(MixerContext, MixerInfo, hMixer, Nodes[Index], &MaxChannels);
+
+ DPRINT("NodeId %lu MaxChannels %lu Line %S Id %lu\n", Nodes[Index], MaxChannels, DstLine->Line.szName, DstLine->Line.dwLineID);
+ /* calculate maximum channels */
+ DstLine->Line.cChannels = min(DstLine->Line.cChannels, MaxChannels);
+ }
+
+ /* now add the mixer control */
+ Status = MMixerAddMixerControl(MixerContext, MixerInfo, hMixer, Topology, Nodes[Index], DstLine);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* increment control count */
+ Count++;
+ }
+ }
+
+ /* store control count */
+ DstLine->Line.cControls = Count;
+
+ /* done */
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerGetComponentAndTargetType(
+ IN PMIXER_CONTEXT MixerContext,
+ IN OUT LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
+ IN ULONG PinId,
+ OUT PULONG ComponentType,
+ OUT PULONG TargetType)
+{
+ KSPIN_DATAFLOW DataFlow;
+ KSPIN_COMMUNICATION Communication;
+ MIXER_STATUS Status;
+ KSP_PIN Request;
+ ULONG BytesReturned;
+ GUID Guid;
+ BOOLEAN BridgePin = FALSE;
+ PKSPIN_PHYSICALCONNECTION Connection;
+
+ /* first dataflow type */
+ Status = MMixerGetPinDataFlowAndCommunication(MixerContext, hMixer, PinId, &DataFlow, &Communication);
+
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to get dataflow */
+ return Status;
+ }
+
+ /* now get pin category guid */
+ Request.PinId = PinId;
+ Request.Reserved = 0;
+ Request.Property.Flags = KSPROPERTY_TYPE_GET;
+ Request.Property.Set = KSPROPSETID_Pin;
+ Request.Property.Id = KSPROPERTY_PIN_CATEGORY;
+
+
+ /* get pin category */
+ Status = MixerContext->Control(hMixer, IOCTL_KS_PROPERTY, (PVOID)&Request, sizeof(KSP_PIN), &Guid, sizeof(GUID), &BytesReturned);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to get dataflow */
+ return Status;
+ }
+
+ /* check if it has a physical connection */
+ Status = MMixerGetPhysicalConnection(MixerContext, hMixer, PinId, &Connection);
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* pin is a brige pin */
+ BridgePin = TRUE;
+
+ /* free physical connection */
+ MixerContext->Free(Connection);
+ }
+
+ if (DataFlow == KSPIN_DATAFLOW_IN)
+ {
+ if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_MICROPHONE) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_DESKTOP_MICROPHONE))
+ {
+ /* type microphone */
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_LEGACY_AUDIO_CONNECTOR) ||
+ IsEqualGUIDAligned(&Guid, &KSCATEGORY_AUDIO) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPEAKER))
+ {
+ /* type waveout */
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_WAVEOUT;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_CD_PLAYER))
+ {
+ /* type cd player */
+ *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SYNTHESIZER))
+ {
+ /* type synthesizer */
+ *TargetType = MIXERLINE_TARGETTYPE_MIDIOUT;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_LINE_CONNECTOR))
+ {
+ /* type line */
+ *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_LINE;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_TELEPHONE) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_PHONE_LINE) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_DOWN_LINE_PHONE))
+ {
+ /* type telephone */
+ *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_TELEPHONE;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_ANALOG_CONNECTOR))
+ {
+ /* type analog */
+ if (BridgePin)
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
+ else
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
+
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_ANALOG;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPDIF_INTERFACE))
+ {
+ /* type analog */
+ if (BridgePin)
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
+ else
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
+
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_DIGITAL;
+ }
+ else
+ {
+ /* unknown type */
+ *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_SRC_UNDEFINED;
+ DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin);
+ }
+ }
+ else
+ {
+ if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPEAKER) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_DESKTOP_SPEAKER) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_ROOM_SPEAKER) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_COMMUNICATION_SPEAKER))
+ {
+ /* type waveout */
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSCATEGORY_AUDIO) ||
+ IsEqualGUIDAligned(&Guid, &PINNAME_CAPTURE))
+ {
+ /* type wavein */
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_HEADPHONES) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_HEAD_MOUNTED_DISPLAY_AUDIO))
+ {
+ /* type head phones */
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_HEADPHONES;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_TELEPHONE) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_PHONE_LINE) ||
+ IsEqualGUIDAligned(&Guid, &KSNODETYPE_DOWN_LINE_PHONE))
+ {
+ /* type waveout */
+ *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_TELEPHONE;
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_ANALOG_CONNECTOR))
+ {
+ /* type analog */
+ if (BridgePin)
+ {
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
+ }
+ else
+ {
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
+ }
+ }
+ else if (IsEqualGUIDAligned(&Guid, &KSNODETYPE_SPDIF_INTERFACE))
+ {
+ /* type spdif */
+ if (BridgePin)
+ {
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEOUT;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_SPEAKERS;
+ }
+ else
+ {
+ *TargetType = MIXERLINE_TARGETTYPE_WAVEIN;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_WAVEIN;
+ }
+ }
+ else
+ {
+ /* unknown type */
+ *TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ *ComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED;
+ DPRINT1("Unknown Category for PinId %lu BridgePin %lu\n", PinId, BridgePin);
+ }
+ }
+
+ /* done */
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerBuildMixerSourceLine(
+ IN PMIXER_CONTEXT MixerContext,
+ IN OUT LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
+ IN PTOPOLOGY Topology,
+ IN ULONG PinId,
+ IN ULONG NodesCount,
+ IN PULONG Nodes,
+ IN ULONG DestinationLineID,
+ OUT LPMIXERLINE_EXT * OutSrcLine)
+{
+ LPMIXERLINE_EXT SrcLine, DstLine;
+ LPWSTR PinName;
+ MIXER_STATUS Status;
+ ULONG ComponentType, TargetType;
+
+ /* get component and target type */
+ Status = MMixerGetComponentAndTargetType(MixerContext, MixerInfo, hMixer, PinId, &ComponentType, &TargetType);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to get component status */
+ TargetType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ ComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED;
+ }
+
+ /* construct source line */
+ SrcLine = (LPMIXERLINE_EXT)MixerContext->Alloc(sizeof(MIXERLINE_EXT));
+
+ if (!SrcLine)
+ {
+ /* no memory */
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* get destination line */
+ DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
+ ASSERT(DstLine);
+
+ /* initialize mixer src line */
+ SrcLine->PinId = PinId;
+
+ /* initialize mixer line */
+ SrcLine->Line.cbStruct = sizeof(MIXERLINEW);
+ SrcLine->Line.dwDestination = MixerInfo->MixCaps.cDestinations-1;
+ SrcLine->Line.dwSource = DstLine->Line.cConnections;
+ SrcLine->Line.dwLineID = (DstLine->Line.cConnections * SOURCE_LINE)+ (MixerInfo->MixCaps.cDestinations-1);
+ SrcLine->Line.fdwLine = MIXERLINE_LINEF_ACTIVE | MIXERLINE_LINEF_SOURCE;
+ SrcLine->Line.dwComponentType = ComponentType;
+ SrcLine->Line.dwUser = 0;
+ SrcLine->Line.cChannels = DstLine->Line.cChannels;
+ SrcLine->Line.cConnections = 0;
+ SrcLine->Line.Target.dwType = TargetType;
+ 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->ControlsList);
+
+ /* copy name */
+ ASSERT(MixerInfo->MixCaps.szPname[MAXPNAMELEN-1] == L'\0');
+ wcscpy(SrcLine->Line.Target.szPname, MixerInfo->MixCaps.szPname);
+
+ /* get pin name */
+ Status = MMixerGetPinName(MixerContext, MixerInfo, hMixer, PinId, &PinName);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* store pin name as line name */
+ MixerContext->Copy(SrcLine->Line.szShortName, PinName, (min(MIXER_SHORT_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
+ SrcLine->Line.szShortName[MIXER_SHORT_NAME_CHARS-1] = L'\0';
+
+ MixerContext->Copy(SrcLine->Line.szName, PinName, (min(MIXER_LONG_NAME_CHARS, wcslen(PinName)+1)) * sizeof(WCHAR));
+ SrcLine->Line.szName[MIXER_LONG_NAME_CHARS-1] = L'\0';
+
+ /* free pin name buffer */
+ MixerContext->Free(PinName);
+ }
+
+ /* add the controls to mixer line */
+ Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, SrcLine, NodesCount, Nodes);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed */
+ return Status;
+ }
+
+ /* store result */
+ *OutSrcLine = SrcLine;
+
+ return MM_STATUS_SUCCESS;
+}
+
+MIXER_STATUS
+MMixerAddMixerSourceLines(
+ IN PMIXER_CONTEXT MixerContext,
+ IN OUT LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
+ IN PTOPOLOGY Topology,
+ IN ULONG DestinationLineID,
+ IN ULONG LineTerminator)
+{
+ PULONG AllNodes, AllPins, AllPinNodes;
+ ULONG AllNodesCount, AllPinsCount, AllPinNodesCount;
+ ULONG Index, SubIndex, PinId, CurNode, bConnected;
+ MIXER_STATUS Status;
+ LPMIXERLINE_EXT DstLine, SrcLine;
+
+ /* get destination line */
+ DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineID);
+ ASSERT(DstLine);
+
+ /* allocate an array to store all nodes which are upstream of the line terminator */
+ Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllNodes);
+
+ /* check for success */
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* out of memory */
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* allocate an array to store all nodes which are downstream of a particular pin */
+ Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &AllPinNodes);
+
+ /* allocate an array to store all pins which are upstream of this pin */
+ Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &AllPins);
+
+ /* check for success */
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* out of memory */
+ MixerContext->Free(AllNodes);
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* get all nodes which indirectly / directly connect to this node */
+ AllNodesCount = 0;
+ MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllNodesCount, AllNodes);
+
+ /* get all pins which indirectly / directly connect to this node */
+ AllPinsCount = 0;
+ MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, LineTerminator, TRUE, &AllPinsCount, AllPins);
+
+ DPRINT1("LineTerminator %lu\n", LineTerminator);
+ DPRINT1("PinCount %lu\n", AllPinsCount);
+ DPRINT1("AllNodesCount %lu\n", AllNodesCount);
+
+ /* now construct the source lines which are attached to the destination line */
+ Index = AllPinsCount;
+
+ do
+ {
+ /* get current pin id */
+ PinId = AllPins[Index - 1];
+
+ /* reset nodes count */
+ AllPinNodesCount = 0;
+
+ /* now scan all nodes and add them to AllPinNodes array when they are connected to this pin */
+ for(SubIndex = 0; SubIndex < AllNodesCount; SubIndex++)
+ {
+ /* get current node index */
+ CurNode = AllNodes[SubIndex];
+
+ if (CurNode != MAXULONG && CurNode != LineTerminator)
+ {
+ /* check if that node is connected in some way to the current pin */
+ Status = MMixerIsNodeConnectedToPin(MixerContext, Topology, CurNode, PinId, TRUE, &bConnected);
+
+ if (Status != MM_STATUS_SUCCESS)
+ break;
+
+ if (bConnected)
+ {
+ /* it is connected */
+ AllPinNodes[AllPinNodesCount] = CurNode;
+ AllPinNodesCount++;
+
+ /* clear current index */
+ AllNodes[SubIndex] = MAXULONG;
+ }
+ }
+ }
+
+ /* decrement pin index */
+ Index--;
+
+ if (AllPinNodesCount)
+ {
+#ifdef MMIXER_DEBUG
+ ULONG TempIndex;
+#endif
+ /* now build the mixer source line */
+ Status = MMixerBuildMixerSourceLine(MixerContext, MixerInfo, hMixer, Topology, PinId, AllPinNodesCount, AllPinNodes, DestinationLineID, &SrcLine);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* insert into line list */
+ InsertTailList(&MixerInfo->LineList, &SrcLine->Entry);
+
+ /* increment destination line count */
+ DstLine->Line.cConnections++;
+
+ /* mark pin as reserved */
+ MMixerSetTopologyPinReserved(Topology, PinId);
+
+#ifdef MMIXER_DEBUG
+ DPRINT1("Adding PinId %lu AllPinNodesCount %lu to DestinationLine %lu\n", PinId, AllPinNodesCount, DestinationLineID);
+ for(TempIndex = 0; TempIndex < AllPinNodesCount; TempIndex++)
+ DPRINT1("NodeIndex %lu\n", AllPinNodes[TempIndex]);
+#endif
+ }
+ }
+ else
+ {
+#ifdef MMIXER_DEBUG
+ DPRINT1("Discarding DestinationLineID %lu PinId %lu NO NODES!\n", DestinationLineID, PinId);
+#endif
+ }
+
+ }while(Index != 0);
+
return MM_STATUS_SUCCESS;
}
MIXER_STATUS
-MMixerHandlePhysicalConnection(
+MMixerAddMixerControlsToDestinationLine(
IN PMIXER_CONTEXT MixerContext,
- IN PMIXER_LIST MixerList,
IN OUT LPMIXER_INFO MixerInfo,
+ IN HANDLE hMixer,
+ IN PTOPOLOGY Topology,
+ IN ULONG PinId,
IN ULONG bInput,
- IN PKSPIN_PHYSICALCONNECTION OutConnection)
+ IN ULONG DestinationLineId,
+ OUT PULONG OutLineTerminator)
{
- PULONG PinsRef = NULL, PinConnectionIndex = NULL, PinsSrcRef;
- ULONG PinsRefCount, Index, PinConnectionIndexCount;
+ PULONG Nodes;
+ ULONG NodesCount, LineTerminator;
MIXER_STATUS Status;
- PKSMULTIPLE_ITEM NodeTypes = NULL;
- PKSMULTIPLE_ITEM NodeConnections = NULL;
- PULONG MixerControls;
- ULONG MixerControlsCount;
- LPMIXER_DATA MixerData;
+ LPMIXERLINE_EXT DstLine;
+ /* allocate nodes index array */
+ Status = MMixerAllocateTopologyNodeArray(MixerContext, Topology, &Nodes);
- // open the connected filter
- OutConnection->SymbolicLinkName[1] = L'\\';
- MixerData = MMixerGetDataByDeviceName(MixerList, OutConnection->SymbolicLinkName);
- ASSERT(MixerData);
-
- // store connected mixer handle
- MixerInfo->hMixer = MixerData->hDevice;
-
- // get connected filter pin count
- PinsRefCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice);
- ASSERT(PinsRefCount);
-
- PinsRef = (PULONG)MixerContext->Alloc(sizeof(ULONG) * PinsRefCount);
- if (!PinsRef)
+ /* check for success */
+ if (Status != MM_STATUS_SUCCESS)
{
- // no memory
- return MM_STATUS_UNSUCCESSFUL;
+ /* out of memory */
+ return MM_STATUS_NO_MEMORY;
}
- // get topology node types
- Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
+ /* get all destination line controls */
+ Status = MMixerCountMixerControls(MixerContext, Topology, PinId, bInput, TRUE, &NodesCount, Nodes, &LineTerminator);
+
+ /* check for success */
if (Status != MM_STATUS_SUCCESS)
{
- MixerContext->Free(PinsRef);
+ /* failed to count controls */
+ MixerContext->Free(Nodes);
return Status;
}
- // get topology connections
- Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
- if (Status != MM_STATUS_SUCCESS)
+ /* get destination mixer line */
+ DstLine = MMixerGetSourceMixerLineByLineId(MixerInfo, DestinationLineId);
+
+ /* sanity check */
+ ASSERT(DstLine);
+
+ if (NodesCount > 0)
{
- MixerContext->Free(PinsRef);
- MixerContext->Free(NodeTypes);
- return Status;
+ /* add all nodes as mixer controls to the destination line */
+ Status = MMixerAddMixerControlsToMixerLineByNodeIndexArray(MixerContext, MixerInfo, hMixer, Topology, DstLine, NodesCount, Nodes);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to add controls */
+ MixerContext->Free(Nodes);
+ return Status;
+ }
}
- // gets connection index of the bridge pin which connects to a node
- DPRINT("Pin %lu\n", OutConnection->Pin);
- Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, OutConnection->Pin, FALSE, !bInput, &PinConnectionIndexCount, &PinConnectionIndex);
- if (Status != MM_STATUS_SUCCESS)
+ /* store result */
+ *OutLineTerminator = LineTerminator;
+
+ /* return result */
+ return Status;
+}
+
+VOID
+MMixerApplyOutputFilterHack(
+ IN PMIXER_CONTEXT MixerContext,
+ IN LPMIXER_DATA MixerData,
+ IN HANDLE hMixer,
+ IN OUT PULONG PinsCount,
+ IN OUT PULONG Pins)
+{
+ ULONG Count = 0, Index;
+ MIXER_STATUS Status;
+ PKSPIN_PHYSICALCONNECTION Connection;
+
+ for(Index = 0; Index < *PinsCount; Index++)
{
- MixerContext->Free(PinsRef);
- MixerContext->Free(NodeTypes);
- MixerContext->Free(NodeConnections);
- return Status;
+ /* check if it has a physical connection */
+ Status = MMixerGetPhysicalConnection(MixerContext, hMixer, Pins[Index], &Connection);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* remove pin */
+ MixerContext->Copy(&Pins[Index], &Pins[Index + 1], (*PinsCount - (Index + 1)) * sizeof(ULONG));
+
+ /* free physical connection */
+ MixerContext->Free(Connection);
+
+ /* decrement index */
+ Index--;
+
+ /* decrement pin count */
+ (*PinsCount)--;
+ }
+ else
+ {
+ /* simple pin */
+ Count++;
+ }
}
- /* there should be no split in the bridge pin */
- ASSERT(PinConnectionIndexCount == 1);
+ /* store result */
+ *PinsCount = Count;
+}
- /* find all target pins of this connection */
- Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext, NodeConnections, NodeTypes, FALSE, PinConnectionIndex[0], PinsRefCount, PinsRef);
- if (Status != MM_STATUS_SUCCESS)
+MIXER_STATUS
+MMixerHandlePhysicalConnection(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PMIXER_LIST MixerList,
+ IN LPMIXER_DATA MixerData,
+ IN OUT LPMIXER_INFO MixerInfo,
+ IN ULONG bInput,
+ IN PKSPIN_PHYSICALCONNECTION OutConnection)
+{
+ MIXER_STATUS Status;
+ ULONG PinsCount, LineTerminator, DestinationLineID;
+ PULONG Pins;
+ PTOPOLOGY Topology;
+
+ /* first try to open the connected filter */
+ OutConnection->SymbolicLinkName[1] = L'\\';
+ MixerData = MMixerGetDataByDeviceName(MixerList, OutConnection->SymbolicLinkName);
+
+ /* check if the linked connection is found */
+ if (!MixerData)
+ {
+ /* filter references invalid physical connection */
+ return MM_STATUS_UNSUCCESSFUL;
+ }
+
+ DPRINT1("Name %S, Pin %lu bInput %lu\n", OutConnection->SymbolicLinkName, OutConnection->Pin, bInput);
+
+ /* sanity check */
+ ASSERT(MixerData->MixerInfo == NULL || MixerData->MixerInfo == MixerInfo);
+
+ /* associate with mixer */
+ MixerData->MixerInfo = MixerInfo;
+
+ if (MixerData->Topology == NULL)
{
- MixerContext->Free(PinsRef);
- MixerContext->Free(NodeTypes);
- MixerContext->Free(NodeConnections);
- MixerContext->Free(PinConnectionIndex);
- return Status;
+ /* construct new topology */
+ Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to create topology */
+ return Status;
+ }
+
+ /* store topology */
+ MixerData->Topology = Topology;
+ }
+ else
+ {
+ /* re-use existing topology */
+ Topology = MixerData->Topology;
}
- for(Index = 0; Index < PinsRefCount; Index++)
+ /* mark pin as consumed */
+ MMixerSetTopologyPinReserved(Topology, OutConnection->Pin);
+
+ if (!bInput)
{
- DPRINT("PinsRefCount %lu Index %lu Value %lu\n", PinsRefCount, Index, PinsRef[Index]);
- if (PinsRef[Index])
+ /* allocate pin index array which will hold all referenced pins */
+ Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins);
+ if (Status != MM_STATUS_SUCCESS)
{
- // found a target pin, now get all references
- Status = MMixerGetNodeIndexes(MixerContext, NodeConnections, Index, FALSE, FALSE, &MixerControlsCount, &MixerControls);
- if (Status != MM_STATUS_SUCCESS)
- {
- DPRINT("MMixerGetNodeIndexes failed with %u\n", Status);
- break;
- }
+ /* failed to create topology */
+ return Status;
+ }
- /* sanity check */
- ASSERT(MixerControlsCount == 1);
+ /* the mixer is an output mixer
+ * find end pin of the node path
+ */
+ PinsCount = 0;
+ Status = MMixerGetAllUpOrDownstreamPinsFromPinIndex(MixerContext, Topology, OutConnection->Pin, FALSE, &PinsCount, Pins);
- PinsSrcRef = (PULONG)MixerContext->Alloc(PinsRefCount * sizeof(ULONG));
- if (!PinsSrcRef)
- {
- /* no memory */
- MixerContext->Free(PinsRef);
- MixerContext->Free(NodeTypes);
- MixerContext->Free(NodeConnections);
- MixerContext->Free(PinConnectionIndex);
- MixerContext->Free(MixerControls);
- return MM_STATUS_NO_MEMORY;
- }
+ /* check for success */
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to get end pin */
+ MixerContext->Free(Pins);
+ //MMixerFreeTopology(Topology);
- // now get all connected source pins
- Status = MMixerGetTargetPinsByNodeConnectionIndex(MixerContext, NodeConnections, NodeTypes, TRUE, MixerControls[0], PinsRefCount, PinsSrcRef);
- if (Status != MM_STATUS_SUCCESS)
- {
- // failed */
- MixerContext->Free(PinsRef);
- MixerContext->Free(NodeTypes);
- MixerContext->Free(NodeConnections);
- MixerContext->Free(PinConnectionIndex);
- MixerContext->Free(MixerControls);
- MixerContext->Free(PinsSrcRef);
- return Status;
- }
+ /* return error code */
+ return Status;
+ }
+ /* HACK:
+ * some topologies do not have strict boundaries
+ * WorkArround: remove all pin ids which have a physical connection
+ * because bridge pins may belong to different render paths
+ */
+ MMixerApplyOutputFilterHack(MixerContext, MixerData, MixerData->hDevice, &PinsCount, Pins);
- /* 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;
+ /* sanity checks */
+ ASSERT(PinsCount != 0);
+ ASSERT(PinsCount == 1);
+
+ /* create destination line */
+ Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInput);
+
+ /* calculate destination line id */
+ DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
- Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, NodeConnections, NodeTypes, PinsRefCount, OutConnection->Pin, Index, PinsSrcRef);
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to build destination line */
+ MixerContext->Free(Pins);
+
+ /* return error code */
+ return Status;
+ }
+
+ /* add mixer controls to destination line */
+ Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, Pins[0], bInput, DestinationLineID, &LineTerminator);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* now add the rest of the source lines */
+ Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
+ }
- MixerContext->Free(MixerControls);
- MixerContext->Free(PinsSrcRef);
+ /* mark pin as consumed */
+ MMixerSetTopologyPinReserved(Topology, Pins[0]);
+
+ /* free topology pin array */
+ MixerContext->Free(Pins);
+ }
+ else
+ {
+ /* calculate destination line id */
+ DestinationLineID = (DESTINATION_LINE + MixerInfo->MixCaps.cDestinations-1);
+
+ /* add mixer controls */
+ Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Topology, OutConnection->Pin, bInput, DestinationLineID, &LineTerminator);
+
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* now add the rest of the source lines */
+ Status = MMixerAddMixerSourceLines(MixerContext, MixerInfo, MixerData->hDevice, Topology, DestinationLineID, LineTerminator);
}
}
return Status;
}
-
MIXER_STATUS
MMixerInitializeFilter(
IN PMIXER_CONTEXT MixerContext,
IN PMIXER_LIST MixerList,
IN LPMIXER_DATA MixerData,
- IN PKSMULTIPLE_ITEM NodeTypes,
- IN PKSMULTIPLE_ITEM NodeConnections,
- IN ULONG PinCount,
+ IN LPMIXER_INFO MixerInfo,
+ IN PTOPOLOGY Topology,
IN ULONG NodeIndex,
- IN ULONG bInputMixer)
+ IN ULONG bInputMixer,
+ IN OUT LPMIXER_INFO * OutMixerInfo)
{
- LPMIXER_INFO MixerInfo;
+ ULONG Index;
MIXER_STATUS Status;
PKSPIN_PHYSICALCONNECTION OutConnection;
- ULONG Index;
ULONG * Pins;
- ULONG bUsed;
- ULONG BytesReturned;
- KSP_PIN Pin;
- LPWSTR Buffer = NULL;
- ULONG PinId;
+ ULONG PinsFound;
+ ULONG NewMixerInfo = FALSE;
- // allocate a mixer info struct
- MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
- if (!MixerInfo)
+ if (MixerInfo == NULL)
{
- // no memory
- return MM_STATUS_NO_MEMORY;
+ /* allocate a mixer info struct */
+ MixerInfo = (LPMIXER_INFO) MixerContext->Alloc(sizeof(MIXER_INFO));
+ if (!MixerInfo)
+ {
+ /* no memory */
+ return MM_STATUS_NO_MEMORY;
+ }
+
+ /* new mixer info */
+ NewMixerInfo = TRUE;
+
+ /* 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 = 0;
+
+ /* get mixer name */
+ MMixerGetDeviceName(MixerContext, MixerInfo->MixCaps.szPname, MixerData->hDeviceInterfaceKey);
+
+ /* initialize line list */
+ InitializeListHead(&MixerInfo->LineList);
+ InitializeListHead(&MixerInfo->EventList);
+
+ /* associate with mixer data */
+ MixerData->MixerInfo = MixerInfo;
}
- // 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 = MixerData->hDevice;
+ /* store mixer info */
+ *OutMixerInfo = MixerInfo;
- // get mixer name
- MMixerGetDeviceName(MixerContext, MixerInfo, MixerData->hDeviceInterfaceKey);
+ /* now allocate an array which will receive the indices of the pin
+ * which has a ADC / DAC nodetype in its path
+ */
+ Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins);
+ ASSERT(Status == MM_STATUS_SUCCESS);
- // initialize line list
- InitializeListHead(&MixerInfo->LineList);
- InitializeListHead(&MixerInfo->EventList);
+ PinsFound = 0;
- // sanity check
- ASSERT(PinCount);
+ /* now get all sink / source pins, which are attached to the ADC / DAC node
+ * For sink pins (wave out) search up stream
+ * For source pins (wave in) search down stream
+ * The search direction is always the opposite of the current mixer type
+ */
+ PinsFound = 0;
+ MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, !bInputMixer, &PinsFound, Pins);
- // 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 there is no pin found, we have a broken topology */
+ ASSERT(PinsFound != 0);
- if (!Pins)
+ /* now create a wave info struct */
+ Status = MMixerInitializeWaveInfo(MixerContext, MixerList, MixerData, MixerInfo->MixCaps.szPname, bInputMixer, PinsFound, Pins);
+ if (Status != MM_STATUS_SUCCESS)
{
- // no memory
- MMixerFreeMixerInfo(MixerContext, MixerInfo);
- return MM_STATUS_NO_MEMORY;
+ /* failed to create wave info struct */
+ MixerContext->Free(MixerInfo);
+ MixerContext->Free(Pins);
+ return Status;
}
- // now get the target pins of the ADC / DAC node
- Status = MMixerGetTargetPins(MixerContext, NodeTypes, NodeConnections, NodeIndex, !bInputMixer, Pins, PinCount);
+ /* mark all found pins as reserved */
+ for(Index = 0; Index < PinsFound; Index++)
+ {
+ MMixerSetTopologyPinReserved(Topology, Pins[Index]);
+ }
- // find a target pin with a name
- PinId = PinCount +1;
- for(Index = 0; Index < PinCount; Index++)
+ if (bInputMixer)
{
- if (Pins[Index])
+ /* pre create the mixer destination line for input mixers */
+ Status = MMixerBuildMixerDestinationLine(MixerContext, MixerInfo, MixerData->hDevice, Pins[0], bInputMixer);
+
+ if (Status != MM_STATUS_SUCCESS)
{
- // store index of pin
- PinId = Index;
+ /* failed to create mixer destination line */
+ return Status;
+ }
+ }
- /* retrieve pin name */
- Pin.PinId = Index;
- 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(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), NULL, 0, &BytesReturned);
+ /* now get the bridge pin which is at the end of node path
+ * For sink pins (wave out) search down stream
+ * For source pins (wave in) search up stream
+ */
+ MixerContext->Free(Pins);
+ Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins);
+ ASSERT(Status == MM_STATUS_SUCCESS);
- if (Status == MM_STATUS_MORE_ENTRIES)
- {
- Buffer = (LPWSTR)MixerContext->Alloc(BytesReturned);
- if (Buffer)
- {
- /* try get pin name */
- Status = MixerContext->Control(MixerData->hDevice, IOCTL_KS_PROPERTY, (PVOID)&Pin, sizeof(KSP_PIN), (PVOID)Buffer, BytesReturned, &BytesReturned);
- if (Status != MM_STATUS_SUCCESS)
- {
- MixerContext->Free((PVOID)Buffer);
- Buffer = NULL;
- }
- else
- {
- // found name, done
- break;
- }
- }
- }
- }
- }
+ PinsFound = 0;
+ MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, bInputMixer, &PinsFound, Pins);
- if (PinId < PinCount)
- {
- // create an wave info struct
- MMixerInitializeWaveInfo(MixerContext, MixerList, MixerData, MixerInfo->MixCaps.szPname, bInputMixer, PinId);
- }
+ /* if there is no pin found, we have a broken topology */
+ ASSERT(PinsFound != 0);
- Status = MMixerCreateDestinationLine(MixerContext, MixerInfo, bInputMixer, Buffer);
+ /* there should be exactly one bridge pin */
+ ASSERT(PinsFound == 1);
- if (Buffer)
- {
- // free name
- MixerContext->Free(Buffer);
- }
+ DPRINT("BridgePin %lu bInputMixer %lu\n", Pins[0], bInputMixer);
- if (Status != MM_STATUS_SUCCESS)
+ /* does the pin have a physical connection */
+ Status = MMixerGetPhysicalConnection(MixerContext, MixerData->hDevice, Pins[0], &OutConnection);
+
+ if (Status == MM_STATUS_SUCCESS)
{
- // failed to create destination line
- MixerContext->Free(MixerInfo);
- MixerContext->Free(Pins);
+ /* mark pin as reserved */
+ MMixerSetTopologyPinReserved(Topology, Pins[0]);
- return Status;
+ /* topology on the topoloy filter */
+ Status = MMixerHandlePhysicalConnection(MixerContext, MixerList, MixerData, MixerInfo, bInputMixer, OutConnection);
+
+ /* free physical connection data */
+ MixerContext->Free(OutConnection);
+ }
+ else
+ {
+ /* FIXME
+ * handle drivers which expose their topology on the same filter
+ */
+ ASSERT(0);
}
- RtlZeroMemory(Pins, sizeof(ULONG) * PinCount);
- // now get the target pins of the ADC / DAC node
- Status = MMixerGetTargetPins(MixerContext, NodeTypes, NodeConnections, NodeIndex, bInputMixer, Pins, PinCount);
+ /* free pins */
+ MixerContext->Free(Pins);
- if (Status != MM_STATUS_SUCCESS)
+ if (NewMixerInfo)
{
- // failed to locate target pins
- MixerContext->Free(Pins);
- MMixerFreeMixerInfo(MixerContext, MixerInfo);
- DPRINT("MMixerGetTargetPins failed with %u\n", Status);
- return Status;
+ /* insert mixer */
+ InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry);
+ /* increment mixer count */
+ MixerList->MixerListCount++;
}
- // filter hasnt been used
- bUsed = FALSE;
+ /* done */
+ return Status;
+}
+
+VOID
+MMixerHandleAlternativeMixers(
+ IN PMIXER_CONTEXT MixerContext,
+ IN PMIXER_LIST MixerList,
+ IN LPMIXER_DATA MixerData,
+ IN PTOPOLOGY Topology)
+{
+ ULONG Index, PinCount, Reserved;
+ MIXER_STATUS Status;
+ ULONG DestinationLineID, LineTerminator;
+ LPMIXERLINE_EXT DstLine;
+
+ DPRINT1("DeviceName %S\n", MixerData->DeviceName);
+
+ /* get topology pin count */
+ MMixerGetTopologyPinCount(Topology, &PinCount);
- // now check all pins and generate new lines for destination lines
for(Index = 0; Index < PinCount; Index++)
{
- DPRINT("Index %lu TargetPin %lu\n", Index, Pins[Index]);
- // is the current index a target pin
- if (Pins[Index])
+ MMixerIsTopologyPinReserved(Topology, Index, &Reserved);
+
+ /* check if it has already been reserved */
+ if (Reserved == TRUE)
{
- // check if the pin has a physical connection
- Status = MMixerGetPhysicalConnection(MixerContext, MixerData->hDevice, Index, &OutConnection);
- if (Status == MM_STATUS_SUCCESS)
- {
- // the pin has a physical connection
- Status = MMixerHandlePhysicalConnection(MixerContext, MixerList, MixerInfo, bInputMixer, OutConnection);
- DPRINT("MMixerHandlePhysicalConnection status %u\n", Status);
- MixerContext->Free(OutConnection);
- bUsed = TRUE;
- }
- else
- {
- // filter exposes the topology on the same filter
- MMixerAddMixerSourceLine(MixerContext, MixerInfo, MixerData->hDevice, NodeConnections, NodeTypes, Index, FALSE, FALSE);
- bUsed = TRUE;
- }
+ /* pin has already been reserved */
+ continue;
}
- }
- MixerContext->Free(Pins);
- if (bUsed)
- {
- // store mixer info in list
- if (!bInputMixer && MixerList->MixerListCount == 1)
+ DPRINT("MixerName %S Available PinID %lu\n", MixerData->DeviceName, Index);
+
+ /* sanity check */
+ ASSERT(MixerData->MixerInfo);
+
+ if (!MixerData->MixerInfo)
{
- //FIXME preferred device should be inserted at front
- //windows always inserts output mixer in front
- InsertHeadList(&MixerList->MixerList, &MixerInfo->Entry);
+ DPRINT1("Expected mixer info\n");
+ continue;
}
- else
+
+ /* build the destination line */
+ Status = MMixerBuildMixerDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, Index, TRUE);
+ if (Status != MM_STATUS_SUCCESS)
{
- InsertTailList(&MixerList->MixerList, &MixerInfo->Entry);
+ /* failed to build destination line */
+ continue;
}
- MixerList->MixerListCount++;
- DPRINT("New MixerCount %lu\n", MixerList->MixerListCount);
- }
- else
- {
- // failed to create a mixer topology
- MMixerFreeMixerInfo(MixerContext, MixerInfo);
- }
- // done
- return Status;
+ /* calculate destination line id */
+ DestinationLineID = (DESTINATION_LINE + MixerData->MixerInfo->MixCaps.cDestinations-1);
+
+ /* add mixer controls to destination line */
+ Status = MMixerAddMixerControlsToDestinationLine(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, Index, TRUE, DestinationLineID, &LineTerminator);
+ if (Status == MM_STATUS_SUCCESS)
+ {
+ /* now add the rest of the source lines */
+ Status = MMixerAddMixerSourceLines(MixerContext, MixerData->MixerInfo, MixerData->hDevice, MixerData->Topology, DestinationLineID, LineTerminator);
+ }
+
+ /* mark pin as consumed */
+ MMixerSetTopologyPinReserved(Topology, Index);
+
+ /* now grab destination line */
+ DstLine = MMixerGetSourceMixerLineByLineId(MixerData->MixerInfo, DestinationLineID);
+
+ /* set type and target as undefined */
+ DstLine->Line.dwComponentType = MIXERLINE_COMPONENTTYPE_DST_UNDEFINED;
+ DstLine->Line.Target.dwType = MIXERLINE_TARGETTYPE_UNDEFINED;
+ DstLine->Line.Target.vDriverVersion = 0;
+ DstLine->Line.Target.wMid = 0;
+ DstLine->Line.Target.wPid = 0;
+ }
}
MIXER_STATUS
IN LPMIXER_DATA MixerData,
IN PULONG DeviceCount)
{
- PKSMULTIPLE_ITEM NodeTypes = NULL, NodeConnections = NULL;
MIXER_STATUS Status;
- ULONG PinCount;
+ PTOPOLOGY Topology;
ULONG NodeIndex;
+ LPMIXER_INFO MixerInfo = NULL;
- // get number of pins
- PinCount = MMixerGetFilterPinCount(MixerContext, MixerData->hDevice);
- ASSERT(PinCount);
- DPRINT("NumOfPins: %lu\n", PinCount);
-
- // get filter node types
- Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
- if (Status != MM_STATUS_SUCCESS)
+ /* check if topology has already been built */
+ if (MixerData->Topology == NULL)
{
- // failed
- return Status;
- }
+ /* build topology */
+ Status = MMixerBuildTopology(MixerContext, MixerData, &Topology);
- // get filter node connections
- Status = MMixerGetFilterTopologyProperty(MixerContext, MixerData->hDevice, KSPROPERTY_TOPOLOGY_CONNECTIONS, &NodeConnections);
- if (Status != MM_STATUS_SUCCESS)
+ if (Status != MM_STATUS_SUCCESS)
+ {
+ /* failed to build topology */
+ return Status;
+ }
+
+ /* store topology */
+ MixerData->Topology = Topology;
+ }
+ else
{
- // failed
- MixerContext->Free(NodeTypes);
- return Status;
+ /* re-use topology */
+ Topology = MixerData->Topology;
}
- // check if the filter has an wave out node
-
- NodeIndex = MMixerGetIndexOfGuid(NodeTypes, &KSNODETYPE_DAC);
+ /* check if the filter has an wave out node */
+ NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_DAC);
if (NodeIndex != MAXULONG)
{
- // it has
- Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NodeTypes, NodeConnections, PinCount, NodeIndex, FALSE);
- DPRINT("MMixerInitializeFilter Status %u\n", Status);
- // check for success
+ /* it has */
+ Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NULL, Topology, NodeIndex, FALSE, &MixerInfo);
+
+ /* check for success */
if (Status == MM_STATUS_SUCCESS)
{
- // increment mixer count
+ /* increment mixer count */
(*DeviceCount)++;
}
-
+ else
+ {
+ /* reset mixer info in case of error */
+ MixerInfo = NULL;
+ }
}
- // check if the filter has an wave in node
- NodeIndex = MMixerGetIndexOfGuid(NodeTypes, &KSNODETYPE_ADC);
+ /* check if the filter has an wave in node */
+ NodeIndex = MMixerGetNodeIndexFromGuid(Topology, &KSNODETYPE_ADC);
if (NodeIndex != MAXULONG)
{
- // it has
- Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, NodeTypes, NodeConnections, PinCount, NodeIndex, TRUE);
- DPRINT("MMixerInitializeFilter Status %u\n", Status);
- // check for success
+ /* it has */
+ Status = MMixerInitializeFilter(MixerContext, MixerList, MixerData, MixerInfo, Topology, NodeIndex, TRUE, &MixerInfo);
+
+ /* check for success */
if (Status == MM_STATUS_SUCCESS)
{
- // increment mixer count
+ /* increment mixer count */
(*DeviceCount)++;
}
}
- //free resources
- MixerContext->Free((PVOID)NodeTypes);
- MixerContext->Free((PVOID)NodeConnections);
+ /* TODO: apply hacks for Wave source line */
- // done
+ /* activate midi devices */
+ //MMixerInitializeMidiForFilter(MixerContext, MixerList, MixerData, Topology);
+
+ /* done */
return Status;
}
MMixerAddEvent(
IN PMIXER_CONTEXT MixerContext,
IN OUT LPMIXER_INFO MixerInfo,
- IN ULONG NodeId)
+ IN PVOID MixerEventContext,
+ IN PMIXER_EVENT MixerEventRoutine)
{
- KSE_NODE Property;
- LPEVENT_ITEM EventData;
- ULONG BytesReturned;
- MIXER_STATUS Status;
+ //KSE_NODE Property;
+ PEVENT_NOTIFICATION_ENTRY EventData;
+ //ULONG BytesReturned;
+ //MIXER_STATUS Status;
- EventData = (LPEVENT_ITEM)MixerContext->AllocEventData(sizeof(LIST_ENTRY));
+ EventData = (PEVENT_NOTIFICATION_ENTRY)MixerContext->AllocEventData(sizeof(EVENT_NOTIFICATION_ENTRY));
if (!EventData)
{
- // not enough memory
+ /* not enough memory */
return MM_STATUS_NO_MEMORY;
}
+#if 0
/* setup request */
Property.Event.Set = KSEVENTSETID_AudioControlChange;
Property.Event.Flags = KSEVENT_TYPE_TOPOLOGY|KSEVENT_TYPE_ENABLE;
Status = MixerContext->Control(MixerInfo->hMixer, IOCTL_KS_ENABLE_EVENT, (PVOID)&Property, sizeof(KSP_NODE), (PVOID)EventData, sizeof(KSEVENTDATA), &BytesReturned);
if (Status != MM_STATUS_SUCCESS)
{
- // failed to add event
+ /* failed to add event */
MixerContext->FreeEventData(EventData);
return Status;
}
+#endif
- //store event
- InsertTailList(&MixerInfo->EventList, &EventData->Entry);
- return Status;
-}
-
-MIXER_STATUS
-MMixerAddEvents(
- IN PMIXER_CONTEXT MixerContext,
- IN OUT LPMIXER_INFO MixerInfo)
-{
- PKSMULTIPLE_ITEM NodeTypes;
- ULONG Index;
- MIXER_STATUS Status;
- LPGUID Guid;
-
- // get filter node types
- Status = MMixerGetFilterTopologyProperty(MixerContext, MixerInfo->hMixer, KSPROPERTY_TOPOLOGY_NODES, &NodeTypes);
-
- if (Status != MM_STATUS_SUCCESS)
- {
- // failed
- return Status;
- }
-
- for(Index = 0; Index < NodeTypes->Count; Index++)
- {
- Guid = MMixerGetNodeType(NodeTypes, Index);
- if (IsEqualGUID(&KSNODETYPE_VOLUME, Guid) || IsEqualGUID(&KSNODETYPE_MUTE, Guid))
- {
- //add an event for volume / mute controls
- //TODO: extra control types
- MMixerAddEvent(MixerContext, MixerInfo, Index);
- }
- }
-
- // free node types
- MixerContext->Free(NodeTypes);
+ /* initialize notification entry */
+ EventData->MixerEventContext = MixerEventContext;
+ EventData->MixerEventRoutine;
+ /* store event */
+ InsertTailList(&MixerInfo->EventList, &EventData->Entry);
return MM_STATUS_SUCCESS;
}
+