2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/mmixer/controls.c
5 * PURPOSE: Mixer Control Iteration Functions
6 * PROGRAMMER: Johannes Anderwald
12 MMixerGetTargetPinsByNodeConnectionIndex(
13 IN PMIXER_CONTEXT MixerContext
,
14 IN PKSMULTIPLE_ITEM NodeConnections
,
15 IN PKSMULTIPLE_ITEM NodeTypes
,
16 IN ULONG bUpDirection
,
17 IN ULONG NodeConnectionIndex
,
20 PKSTOPOLOGY_CONNECTION Connection
;
21 ULONG PinId
, NodeConnectionCount
, Index
;
22 PULONG NodeConnection
;
27 ASSERT(NodeConnectionIndex
< NodeConnections
->Count
);
29 Connection
= (PKSTOPOLOGY_CONNECTION
)(NodeConnections
+ 1);
31 //DPRINT("FromNode %u FromNodePin %u -> ToNode %u ToNodePin %u\n", Connection[NodeConnectionIndex].FromNode, Connection[NodeConnectionIndex].FromNodePin, Connection[NodeConnectionIndex].ToNode, Connection[NodeConnectionIndex].ToNodePin );
33 if ((Connection
[NodeConnectionIndex
].ToNode
== KSFILTER_NODE
&& bUpDirection
== FALSE
) ||
34 (Connection
[NodeConnectionIndex
].FromNode
== KSFILTER_NODE
&& bUpDirection
== TRUE
))
36 /* iteration stops here */
38 PinId
= Connection
[NodeConnectionIndex
].FromNodePin
;
40 PinId
= Connection
[NodeConnectionIndex
].ToNodePin
;
42 //DPRINT("GetTargetPinsByNodeIndex FOUND Target Pin %u Parsed %u\n", PinId, Pins[PinId]);
44 /* mark pin index as a target pin */
46 return MM_STATUS_SUCCESS
;
49 // get all node indexes referenced by that node
52 Status
= MMixerGetNodeIndexes(MixerContext
, NodeConnections
, Connection
[NodeConnectionIndex
].FromNode
, TRUE
, FALSE
, &NodeConnectionCount
, &NodeConnection
);
56 Status
= MMixerGetNodeIndexes(MixerContext
, NodeConnections
, Connection
[NodeConnectionIndex
].ToNode
, TRUE
, TRUE
, &NodeConnectionCount
, &NodeConnection
);
59 if (Status
== MM_STATUS_SUCCESS
)
61 for(Index
= 0; Index
< NodeConnectionCount
; Index
++)
63 // iterate recursively into the nodes
64 Status
= MMixerGetTargetPinsByNodeConnectionIndex(MixerContext
, NodeConnections
, NodeTypes
, bUpDirection
, NodeConnection
[Index
], Pins
);
65 ASSERT(Status
== MM_STATUS_SUCCESS
);
67 // free node connection indexes
68 MixerContext
->Free(NodeConnection
);
75 MMixerGetControlsFromPinByConnectionIndex(
76 IN PMIXER_CONTEXT MixerContext
,
77 IN PKSMULTIPLE_ITEM NodeConnections
,
78 IN PKSMULTIPLE_ITEM NodeTypes
,
79 IN ULONG bUpDirection
,
80 IN ULONG NodeConnectionIndex
,
83 PKSTOPOLOGY_CONNECTION CurConnection
;
87 ULONG NodeConnectionCount
, Index
;
88 PULONG NodeConnection
;
91 /* get current connection */
92 CurConnection
= MMixerGetConnectionByIndex(NodeConnections
, NodeConnectionIndex
);
95 NodeIndex
= CurConnection
->FromNode
;
97 NodeIndex
= CurConnection
->ToNode
;
99 /* get target node type of current connection */
100 NodeType
= MMixerGetNodeType(NodeTypes
, NodeIndex
);
102 if (IsEqualGUIDAligned(NodeType
, &KSNODETYPE_SUM
) || IsEqualGUIDAligned(NodeType
, &KSNODETYPE_MUX
))
106 /* add the sum / mux node to destination line */
107 Nodes
[NodeIndex
] = TRUE
;
110 return MM_STATUS_SUCCESS
;
113 /* now add the node */
114 Nodes
[NodeIndex
] = TRUE
;
117 /* get all node indexes referenced by that node */
120 Status
= MMixerGetNodeIndexes(MixerContext
, NodeConnections
, NodeIndex
, TRUE
, FALSE
, &NodeConnectionCount
, &NodeConnection
);
124 Status
= MMixerGetNodeIndexes(MixerContext
, NodeConnections
, NodeIndex
, TRUE
, TRUE
, &NodeConnectionCount
, &NodeConnection
);
127 if (Status
!= MM_STATUS_SUCCESS
)
129 for(Index
= 0; Index
< NodeConnectionCount
; Index
++)
131 /* iterate recursively into the nodes */
132 Status
= MMixerGetControlsFromPinByConnectionIndex(MixerContext
, NodeConnections
, NodeTypes
, bUpDirection
, NodeConnection
[Index
], Nodes
);
133 ASSERT(Status
== MM_STATUS_SUCCESS
);
135 /* free node connection indexes */
136 MixerContext
->Free(NodeConnection
);
143 MMixerAddMixerControl(
144 IN PMIXER_CONTEXT MixerContext
,
145 IN LPMIXER_INFO MixerInfo
,
147 IN PKSMULTIPLE_ITEM NodeTypes
,
149 IN LPMIXERLINE_EXT MixerLine
,
150 OUT LPMIXERCONTROLW MixerControl
)
158 /* initialize mixer control */
159 MixerControl
->cbStruct
= sizeof(MIXERCONTROLW
);
160 MixerControl
->dwControlID
= MixerInfo
->ControlId
;
163 NodeType
= MMixerGetNodeType(NodeTypes
, NodeIndex
);
164 /* store control type */
165 MixerControl
->dwControlType
= MMixerGetControlTypeFromTopologyNode(NodeType
);
167 MixerControl
->fdwControl
= MIXERCONTROL_CONTROLF_UNIFORM
; //FIXME
168 MixerControl
->cMultipleItems
= 0; //FIXME
170 if (MixerControl
->dwControlType
== MIXERCONTROL_CONTROLTYPE_MUTE
)
172 MixerControl
->Bounds
.dwMinimum
= 0;
173 MixerControl
->Bounds
.dwMaximum
= 1;
175 else if (MixerControl
->dwControlType
== MIXERCONTROL_CONTROLTYPE_VOLUME
)
177 MixerControl
->Bounds
.dwMinimum
= 0;
178 MixerControl
->Bounds
.dwMaximum
= 0xFFFF;
179 MixerControl
->Metrics
.cSteps
= 0xC0; //FIXME
182 /* setup request to retrieve name */
183 Node
.NodeId
= NodeIndex
;
184 Node
.Property
.Id
= KSPROPERTY_TOPOLOGY_NAME
;
185 Node
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
186 Node
.Property
.Set
= KSPROPSETID_Topology
;
189 /* get node name size */
190 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Node
, sizeof(KSP_NODE
), NULL
, 0, &BytesReturned
);
192 if (Status
== MM_STATUS_MORE_ENTRIES
)
194 ASSERT(BytesReturned
!= 0);
195 Name
= (LPWSTR
)MixerContext
->Alloc(BytesReturned
);
198 /* not enough memory */
199 return MM_STATUS_NO_MEMORY
;
203 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Node
, sizeof(KSP_NODE
), (LPVOID
)Name
, BytesReturned
, &BytesReturned
);
204 if (Status
!= MM_STATUS_SUCCESS
)
206 MixerContext
->Copy(MixerControl
->szShortName
, Name
, (min(MIXER_SHORT_NAME_CHARS
, wcslen(Name
)+1)) * sizeof(WCHAR
));
207 MixerControl
->szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
209 MixerContext
->Copy(MixerControl
->szName
, Name
, (min(MIXER_LONG_NAME_CHARS
, wcslen(Name
)+1)) * sizeof(WCHAR
));
210 MixerControl
->szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
213 /* free name buffer */
214 MixerContext
->Free(Name
);
217 MixerInfo
->ControlId
++;
219 if (MixerControl
->dwControlType
== MIXERCONTROL_CONTROLTYPE_MUX
)
221 KSNODEPROPERTY Property
;
224 /* setup the request */
225 RtlZeroMemory(&Property
, sizeof(KSNODEPROPERTY
));
227 Property
.NodeId
= NodeIndex
;
228 Property
.Property
.Id
= KSPROPERTY_AUDIO_MUX_SOURCE
;
229 Property
.Property
.Flags
= KSPROPERTY_TYPE_SET
;
230 Property
.Property
.Set
= KSPROPSETID_Audio
;
232 /* get node volume level info */
233 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSNODEPROPERTY
), (PVOID
)&PinId
, sizeof(ULONG
), &BytesReturned
);
235 DPRINT1("Status %x NodeIndex %u PinId %u\n", Status
, NodeIndex
, PinId
);
239 if (MixerControl
->dwControlType
== MIXERCONTROL_CONTROLTYPE_VOLUME
)
241 KSNODEPROPERTY_AUDIO_CHANNEL Property
;
243 PKSPROPERTY_DESCRIPTION Desc
;
244 PKSPROPERTY_MEMBERSHEADER Members
;
245 PKSPROPERTY_STEPPING_LONG Range
;
247 Length
= sizeof(KSPROPERTY_DESCRIPTION
) + sizeof(KSPROPERTY_MEMBERSHEADER
) + sizeof(KSPROPERTY_STEPPING_LONG
);
248 Desc
= (PKSPROPERTY_DESCRIPTION
)MixerContext
->Alloc(Length
);
251 /* setup the request */
252 RtlZeroMemory(&Property
, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL
));
254 Property
.NodeProperty
.NodeId
= NodeIndex
;
255 Property
.NodeProperty
.Property
.Id
= KSPROPERTY_AUDIO_VOLUMELEVEL
;
256 Property
.NodeProperty
.Property
.Flags
= KSPROPERTY_TYPE_BASICSUPPORT
;
257 Property
.NodeProperty
.Property
.Set
= KSPROPSETID_Audio
;
259 /* get node volume level info */
260 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Property
, sizeof(KSNODEPROPERTY_AUDIO_CHANNEL
), Desc
, Length
, &BytesReturned
);
262 if (Status
== MM_STATUS_SUCCESS
)
264 LPMIXERVOLUME_DATA VolumeData
;
265 ULONG Steps
, MaxRange
, Index
;
268 Members
= (PKSPROPERTY_MEMBERSHEADER
)(Desc
+ 1);
269 Range
= (PKSPROPERTY_STEPPING_LONG
)(Members
+ 1);
271 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
);
273 MaxRange
= Range
->Bounds
.UnsignedMaximum
- Range
->Bounds
.UnsignedMinimum
;
278 VolumeData
= (LPMIXERVOLUME_DATA
)MixerContext
->Alloc(sizeof(MIXERVOLUME_DATA
));
280 return MM_STATUS_NO_MEMORY
;
282 Steps
= MaxRange
/ Range
->SteppingDelta
+ 1;
284 /* store mixer control info there */
285 VolumeData
->Header
.dwControlID
= MixerControl
->dwControlID
;
286 VolumeData
->SignedMaximum
= Range
->Bounds
.SignedMaximum
;
287 VolumeData
->SignedMinimum
= Range
->Bounds
.SignedMinimum
;
288 VolumeData
->SteppingDelta
= Range
->SteppingDelta
;
289 VolumeData
->ValuesCount
= Steps
;
290 VolumeData
->InputSteppingDelta
= 0x10000 / Steps
;
292 VolumeData
->Values
= (PLONG
)MixerContext
->Alloc(sizeof(LONG
) * Steps
);
293 if (!VolumeData
->Values
)
295 MixerContext
->Free(Desc
);
296 MixerContext
->Free(VolumeData
);
298 return MM_STATUS_NO_MEMORY
;
301 Value
= Range
->Bounds
.SignedMinimum
;
302 for(Index
= 0; Index
< Steps
; Index
++)
304 VolumeData
->Values
[Index
] = Value
;
305 Value
+= Range
->SteppingDelta
;
307 InsertTailList(&MixerLine
->LineControlsExtraData
, &VolumeData
->Header
.Entry
);
310 MixerContext
->Free(Desc
);
314 DPRINT("Status %x Name %S\n", Status
, MixerControl
->szName
);
315 return MM_STATUS_SUCCESS
;
319 MMixerAddMixerSourceLine(
320 IN PMIXER_CONTEXT MixerContext
,
321 IN OUT LPMIXER_INFO MixerInfo
,
323 IN PKSMULTIPLE_ITEM NodeConnections
,
324 IN PKSMULTIPLE_ITEM NodeTypes
,
329 LPMIXERLINE_EXT SrcLine
, DstLine
;
334 ULONG BytesReturned
, ControlCount
, Index
;
339 /* allocate src mixer line */
340 SrcLine
= (LPMIXERLINE_EXT
)MixerContext
->Alloc(sizeof(MIXERLINE_EXT
));
343 return MM_STATUS_NO_MEMORY
;
346 RtlZeroMemory(SrcLine
, sizeof(MIXERLINE_EXT
));
351 ASSERT(!IsListEmpty(&MixerInfo
->LineList
));
352 SrcLine
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
355 /* get destination line */
356 DstLine
= MMixerGetSourceMixerLineByLineId(MixerInfo
, DESTINATION_LINE
);
362 /* initialize mixer src line */
363 SrcLine
->hDevice
= hDevice
;
364 SrcLine
->PinId
= PinId
;
365 SrcLine
->Line
.cbStruct
= sizeof(MIXERLINEW
);
367 /* initialize mixer destination line */
368 SrcLine
->Line
.cbStruct
= sizeof(MIXERLINEW
);
369 SrcLine
->Line
.dwDestination
= 0;
370 SrcLine
->Line
.dwSource
= DstLine
->Line
.cConnections
;
371 SrcLine
->Line
.dwLineID
= (DstLine
->Line
.cConnections
* 0x10000);
372 SrcLine
->Line
.fdwLine
= MIXERLINE_LINEF_ACTIVE
| MIXERLINE_LINEF_SOURCE
;
373 SrcLine
->Line
.dwUser
= 0;
374 SrcLine
->Line
.cChannels
= DstLine
->Line
.cChannels
;
375 SrcLine
->Line
.cConnections
= 0;
376 SrcLine
->Line
.Target
.dwType
= 1;
377 SrcLine
->Line
.Target
.dwDeviceID
= DstLine
->Line
.Target
.dwDeviceID
;
378 SrcLine
->Line
.Target
.wMid
= MixerInfo
->MixCaps
.wMid
;
379 SrcLine
->Line
.Target
.wPid
= MixerInfo
->MixCaps
.wPid
;
380 SrcLine
->Line
.Target
.vDriverVersion
= MixerInfo
->MixCaps
.vDriverVersion
;
381 InitializeListHead(&SrcLine
->LineControlsExtraData
);
382 wcscpy(SrcLine
->Line
.Target
.szPname
, MixerInfo
->MixCaps
.szPname
);
386 /* allocate a node arrary */
387 Nodes
= (PULONG
)MixerContext
->Alloc(sizeof(ULONG
) * NodeTypes
->Count
);
391 /* not enough memory */
394 MixerContext
->Free(SrcLine
);
396 return MM_STATUS_NO_MEMORY
;
399 Status
= MMixerGetControlsFromPin(MixerContext
, NodeConnections
, NodeTypes
, PinId
, bTargetPin
, Nodes
);
400 if (Status
!= MM_STATUS_SUCCESS
)
402 /* something went wrong */
405 MixerContext
->Free(SrcLine
);
407 MixerContext
->Free(Nodes
);
411 /* now count all nodes controlled by that pin */
413 for(Index
= 0; Index
< NodeTypes
->Count
; Index
++)
422 /* now allocate the line controls */
425 SrcLine
->LineControls
= (LPMIXERCONTROLW
)MixerContext
->Alloc(sizeof(MIXERCONTROLW
) * ControlCount
);
427 if (!SrcLine
->LineControls
)
429 /* no memory available */
432 MixerContext
->Free(SrcLine
);
434 MixerContext
->Free(Nodes
);
435 return MM_STATUS_NO_MEMORY
;
438 SrcLine
->NodeIds
= (PULONG
)MixerContext
->Alloc(sizeof(ULONG
) * ControlCount
);
439 if (!SrcLine
->NodeIds
)
441 /* no memory available */
442 MixerContext
->Free(SrcLine
->LineControls
);
445 MixerContext
->Free(SrcLine
);
447 MixerContext
->Free(Nodes
);
448 return MM_STATUS_NO_MEMORY
;
451 /* zero line controls */
452 RtlZeroMemory(SrcLine
->LineControls
, sizeof(MIXERCONTROLW
) * ControlCount
);
453 RtlZeroMemory(SrcLine
->NodeIds
, sizeof(ULONG
) * ControlCount
);
456 for(Index
= 0; Index
< NodeTypes
->Count
; Index
++)
460 /* store the node index for retrieving / setting details */
461 SrcLine
->NodeIds
[ControlCount
] = Index
;
463 Status
= MMixerAddMixerControl(MixerContext
, MixerInfo
, hDevice
, NodeTypes
, Index
, SrcLine
, &SrcLine
->LineControls
[ControlCount
]);
464 if (Status
== MM_STATUS_SUCCESS
)
466 /* increment control count on success */
471 /* store control count */
472 SrcLine
->Line
.cControls
= ControlCount
;
475 /* release nodes array */
476 MixerContext
->Free(Nodes
);
478 /* get pin category */
481 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
482 Pin
.Property
.Set
= KSPROPSETID_Pin
;
483 Pin
.Property
.Id
= KSPROPERTY_PIN_CATEGORY
;
485 /* try get pin category */
486 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (LPVOID
)&NodeType
, sizeof(GUID
), &BytesReturned
);
487 if (Status
!= MM_STATUS_SUCCESS
)
493 /* retrieve pin name */
496 Pin
.Property
.Flags
= KSPROPERTY_TYPE_GET
;
497 Pin
.Property
.Set
= KSPROPSETID_Pin
;
498 Pin
.Property
.Id
= KSPROPERTY_PIN_NAME
;
500 /* try get pin name size */
501 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), NULL
, 0, &BytesReturned
);
503 if (Status
== MM_STATUS_MORE_ENTRIES
)
505 PinName
= (LPWSTR
)MixerContext
->Alloc(BytesReturned
);
508 /* try get pin name */
509 Status
= MixerContext
->Control(hDevice
, IOCTL_KS_PROPERTY
, (PVOID
)&Pin
, sizeof(KSP_PIN
), (LPVOID
)PinName
, BytesReturned
, &BytesReturned
);
511 if (Status
== MM_STATUS_SUCCESS
)
513 MixerContext
->Copy(SrcLine
->Line
.szShortName
, PinName
, (min(MIXER_SHORT_NAME_CHARS
, wcslen(PinName
)+1)) * sizeof(WCHAR
));
514 SrcLine
->Line
.szShortName
[MIXER_SHORT_NAME_CHARS
-1] = L
'\0';
516 MixerContext
->Copy(SrcLine
->Line
.szName
, PinName
, (min(MIXER_LONG_NAME_CHARS
, wcslen(PinName
)+1)) * sizeof(WCHAR
));
517 SrcLine
->Line
.szName
[MIXER_LONG_NAME_CHARS
-1] = L
'\0';
519 MixerContext
->Free(PinName
);
523 /* insert src line */
526 InsertTailList(&MixerInfo
->LineList
, &SrcLine
->Entry
);
527 DstLine
->Line
.cConnections
++;
530 return MM_STATUS_SUCCESS
;
534 MMixerCreateDestinationLine(
535 IN PMIXER_CONTEXT MixerContext
,
536 IN LPMIXER_INFO MixerInfo
,
537 IN ULONG bInputMixer
)
539 LPMIXERLINE_EXT DestinationLine
;
541 // allocate a mixer destination line
542 DestinationLine
= (LPMIXERLINE_EXT
) MixerContext
->Alloc(sizeof(MIXERLINE_EXT
));
546 return MM_STATUS_NO_MEMORY
;
549 /* initialize mixer destination line */
550 DestinationLine
->Line
.cbStruct
= sizeof(MIXERLINEW
);
551 DestinationLine
->Line
.dwSource
= MAXULONG
;
552 DestinationLine
->Line
.dwLineID
= DESTINATION_LINE
;
553 DestinationLine
->Line
.fdwLine
= MIXERLINE_LINEF_ACTIVE
;
554 DestinationLine
->Line
.dwUser
= 0;
555 DestinationLine
->Line
.dwComponentType
= (bInputMixer
== 0 ? MIXERLINE_COMPONENTTYPE_DST_SPEAKERS
: MIXERLINE_COMPONENTTYPE_DST_WAVEIN
);
556 DestinationLine
->Line
.cChannels
= 2; //FIXME
557 wcscpy(DestinationLine
->Line
.szShortName
, L
"Summe"); //FIXME
558 wcscpy(DestinationLine
->Line
.szName
, L
"Summe"); //FIXME
559 DestinationLine
->Line
.Target
.dwType
= (bInputMixer
== 0 ? MIXERLINE_TARGETTYPE_WAVEOUT
: MIXERLINE_TARGETTYPE_WAVEIN
);
560 DestinationLine
->Line
.Target
.dwDeviceID
= !bInputMixer
;
561 DestinationLine
->Line
.Target
.wMid
= MixerInfo
->MixCaps
.wMid
;
562 DestinationLine
->Line
.Target
.wPid
= MixerInfo
->MixCaps
.wPid
;
563 DestinationLine
->Line
.Target
.vDriverVersion
= MixerInfo
->MixCaps
.vDriverVersion
;
564 wcscpy(DestinationLine
->Line
.Target
.szPname
, MixerInfo
->MixCaps
.szPname
);
567 // insert into mixer info
568 InsertHeadList(&MixerInfo
->LineList
, &DestinationLine
->Entry
);
571 return MM_STATUS_SUCCESS
;
575 MMixerGetControlsFromPin(
576 IN PMIXER_CONTEXT MixerContext
,
577 IN PKSMULTIPLE_ITEM NodeConnections
,
578 IN PKSMULTIPLE_ITEM NodeTypes
,
580 IN ULONG bUpDirection
,
583 ULONG NodeConnectionCount
, Index
;
585 PULONG NodeConnection
;
588 ASSERT(PinId
!= (ULONG
)-1);
590 /* get all node indexes referenced by that pin */
592 Status
= MMixerGetNodeIndexes(MixerContext
, NodeConnections
, PinId
, FALSE
, FALSE
, &NodeConnectionCount
, &NodeConnection
);
594 Status
= MMixerGetNodeIndexes(MixerContext
, NodeConnections
, PinId
, FALSE
, TRUE
, &NodeConnectionCount
, &NodeConnection
);
596 for(Index
= 0; Index
< NodeConnectionCount
; Index
++)
598 /* get all associated controls */
599 Status
= MMixerGetControlsFromPinByConnectionIndex(MixerContext
, NodeConnections
, NodeTypes
, bUpDirection
, NodeConnection
[Index
], Nodes
);
602 MixerContext
->Free(NodeConnection
);
611 MMixerAddMixerSourceLines(
612 IN PMIXER_CONTEXT MixerContext
,
613 IN OUT LPMIXER_INFO MixerInfo
,
615 IN PKSMULTIPLE_ITEM NodeConnections
,
616 IN PKSMULTIPLE_ITEM NodeTypes
,
618 IN ULONG BridgePinIndex
,
619 IN ULONG TargetPinIndex
,
624 for(Index
= PinsCount
; Index
> 0; Index
--)
626 DPRINT("MMixerAddMixerSourceLines Index %lu Pin %lu\n", Index
-1, Pins
[Index
-1]);
629 MMixerAddMixerSourceLine(MixerContext
, MixerInfo
, hDevice
, NodeConnections
, NodeTypes
, Index
-1, (Index
-1 == BridgePinIndex
), (Index
-1 == TargetPinIndex
));
632 return MM_STATUS_SUCCESS
;
637 MMixerHandlePhysicalConnection(
638 IN PMIXER_CONTEXT MixerContext
,
639 IN OUT LPMIXER_INFO MixerInfo
,
641 IN PKSPIN_PHYSICALCONNECTION OutConnection
)
643 PULONG PinsRef
= NULL
, PinConnectionIndex
= NULL
, PinsSrcRef
;
644 ULONG PinsRefCount
, Index
, PinConnectionIndexCount
;
646 HANDLE hDevice
= NULL
;
647 PKSMULTIPLE_ITEM NodeTypes
= NULL
;
648 PKSMULTIPLE_ITEM NodeConnections
= NULL
;
649 PULONG MixerControls
;
650 ULONG MixerControlsCount
;
653 // open the connected filter
654 Status
= MixerContext
->Open(OutConnection
->SymbolicLinkName
, &hDevice
);
655 if (Status
!= MM_STATUS_SUCCESS
)
657 DPRINT("OpenDevice failed with %x\n", Status
);
661 // get connected filter pin count
662 PinsRefCount
= MMixerGetFilterPinCount(MixerContext
, hDevice
);
663 ASSERT(PinsRefCount
);
665 PinsRef
= (PULONG
)MixerContext
->Alloc(sizeof(ULONG
) * PinsRefCount
);
669 MixerContext
->Close(hDevice
);
670 return MM_STATUS_UNSUCCESSFUL
;
673 // get topology node types
674 Status
= MMixerGetFilterTopologyProperty(MixerContext
, hDevice
, KSPROPERTY_TOPOLOGY_NODES
, &NodeTypes
);
675 if (Status
!= MM_STATUS_SUCCESS
)
677 MixerContext
->Close(hDevice
);
678 MixerContext
->Free(PinsRef
);
682 // get topology connections
683 Status
= MMixerGetFilterTopologyProperty(MixerContext
, hDevice
, KSPROPERTY_TOPOLOGY_CONNECTIONS
, &NodeConnections
);
684 if (Status
!= MM_STATUS_SUCCESS
)
686 MixerContext
->Close(hDevice
);
687 MixerContext
->Free(PinsRef
);
688 MixerContext
->Free(NodeTypes
);
691 // gets connection index of the bridge pin which connects to a node
692 DPRINT("Pin %lu\n", OutConnection
->Pin
);
694 Status
= MMixerGetNodeIndexes(MixerContext
, NodeConnections
, OutConnection
->Pin
, FALSE
, !bInput
, &PinConnectionIndexCount
, &PinConnectionIndex
);
695 if (Status
!= MM_STATUS_SUCCESS
)
697 MixerContext
->Close(hDevice
);
698 MixerContext
->Free(PinsRef
);
699 MixerContext
->Free(NodeTypes
);
700 MixerContext
->Free(NodeConnections
);
704 /* there should be no split in the bride pin */
705 ASSERT(PinConnectionIndexCount
== 1);
707 /* find all target pins of this connection */
708 Status
= MMixerGetTargetPinsByNodeConnectionIndex(MixerContext
, NodeConnections
, NodeTypes
, FALSE
, PinConnectionIndex
[0], PinsRef
);
709 if (Status
!= MM_STATUS_SUCCESS
)
711 MixerContext
->Close(hDevice
);
712 MixerContext
->Free(PinsRef
);
713 MixerContext
->Free(NodeTypes
);
714 MixerContext
->Free(NodeConnections
);
715 MixerContext
->Free(PinConnectionIndex
);
719 for(Index
= 0; Index
< PinsRefCount
; Index
++)
721 DPRINT("PinsRefCount %lu Index %lu Value %lu\n", PinsRefCount
, Index
, PinsRef
[Index
]);
724 // found a target pin, now get all references
725 Status
= MMixerGetNodeIndexes(MixerContext
, NodeConnections
, Index
, FALSE
, FALSE
, &MixerControlsCount
, &MixerControls
);
726 if (Status
!= MM_STATUS_SUCCESS
)
728 DPRINT("MMixerGetNodeIndexes failed with %u\n", Status
);
733 ASSERT(MixerControlsCount
== 1);
735 PinsSrcRef
= (PULONG
)MixerContext
->Alloc(PinsRefCount
* sizeof(ULONG
));
739 MixerContext
->Close(hDevice
);
740 MixerContext
->Free(PinsRef
);
741 MixerContext
->Free(NodeTypes
);
742 MixerContext
->Free(NodeConnections
);
743 MixerContext
->Free(PinConnectionIndex
);
744 MixerContext
->Free(MixerControls
);
745 return MM_STATUS_NO_MEMORY
;
748 // now get all connected source pins
749 Status
= MMixerGetTargetPinsByNodeConnectionIndex(MixerContext
, NodeConnections
, NodeTypes
, TRUE
, MixerControls
[0], PinsSrcRef
);
750 if (Status
!= MM_STATUS_SUCCESS
)
753 MixerContext
->Close(hDevice
);
754 MixerContext
->Free(PinsRef
);
755 MixerContext
->Free(NodeTypes
);
756 MixerContext
->Free(NodeConnections
);
757 MixerContext
->Free(PinConnectionIndex
);
758 MixerContext
->Free(MixerControls
);
759 MixerContext
->Free(PinsSrcRef
);
763 /* add pins from target line */
766 // dont add bridge pin for input mixers
767 PinsSrcRef
[Index
] = TRUE
;
768 PinsSrcRef
[OutConnection
->Pin
] = TRUE
;
770 PinsSrcRef
[OutConnection
->Pin
] = TRUE
;
772 Status
= MMixerAddMixerSourceLines(MixerContext
, MixerInfo
, hDevice
, NodeConnections
, NodeTypes
, PinsRefCount
, OutConnection
->Pin
, Index
, PinsSrcRef
);
774 MixerContext
->Free(MixerControls
);
775 MixerContext
->Free(PinsSrcRef
);
784 MMixerInitializeFilter(
785 IN PMIXER_CONTEXT MixerContext
,
786 IN PMIXER_LIST MixerList
,
788 IN LPWSTR DeviceName
,
789 IN PKSMULTIPLE_ITEM NodeTypes
,
790 IN PKSMULTIPLE_ITEM NodeConnections
,
793 IN ULONG bInputMixer
)
795 LPMIXER_INFO MixerInfo
;
797 PKSPIN_PHYSICALCONNECTION OutConnection
;
802 // allocate a mixer info struct
803 MixerInfo
= (LPMIXER_INFO
) MixerContext
->Alloc(sizeof(MIXER_INFO
));
807 return MM_STATUS_NO_MEMORY
;
810 // intialize mixer caps */
811 MixerInfo
->MixCaps
.wMid
= MM_MICROSOFT
; //FIXME
812 MixerInfo
->MixCaps
.wPid
= MM_PID_UNMAPPED
; //FIXME
813 MixerInfo
->MixCaps
.vDriverVersion
= 1; //FIXME
814 MixerInfo
->MixCaps
.fdwSupport
= 0;
815 MixerInfo
->MixCaps
.cDestinations
= 1;
816 MixerInfo
->hMixer
= hMixer
;
818 // initialize line list
819 InitializeListHead(&MixerInfo
->LineList
);
821 /* FIXME find mixer name */
823 Status
= MMixerCreateDestinationLine(MixerContext
, MixerInfo
, bInputMixer
);
824 if (Status
!= MM_STATUS_SUCCESS
)
826 // failed to create destination line
827 MixerContext
->Free(MixerInfo
);
832 // now allocate an array which will receive the indices of the pin
833 // which has a ADC / DAC nodetype in its path
834 Pins
= (PULONG
)MixerContext
->Alloc(PinCount
* sizeof(ULONG
));
839 MMixerFreeMixerInfo(MixerContext
, MixerInfo
);
840 return MM_STATUS_NO_MEMORY
;
843 // now get the target pins of the ADC / DAC node
844 Status
= MMixerGetTargetPins(MixerContext
, NodeTypes
, NodeConnections
, NodeIndex
, bInputMixer
, Pins
, PinCount
);
846 if (Status
!= MM_STATUS_SUCCESS
)
848 // failed to locate target pins
849 MixerContext
->Free(Pins
);
850 MMixerFreeMixerInfo(MixerContext
, MixerInfo
);
851 DPRINT("MMixerGetTargetPins failed with %u\n", Status
);
855 // filter hasnt been used
858 // now check all pins and generate new lines for destination lines
859 for(Index
= 0; Index
< PinCount
; Index
++)
861 DPRINT("Index %lu TargetPin %lu\n", Index
, Pins
[Index
]);
862 // is the current index a target pin
865 // check if the pin has a physical connection
866 Status
= MMixerGetPhysicalConnection(MixerContext
, hMixer
, Index
, &OutConnection
);
867 if (Status
== MM_STATUS_SUCCESS
)
869 // the pin has a physical connection
870 Status
= MMixerHandlePhysicalConnection(MixerContext
, MixerInfo
, bInputMixer
, OutConnection
);
871 DPRINT("MMixerHandlePhysicalConnection status %u\n", Status
);
872 MixerContext
->Free(OutConnection
);
877 MixerContext
->Free(Pins
);
881 // store mixer info in list
882 InsertTailList(&MixerList
->MixerList
, &MixerInfo
->Entry
);
883 MixerList
->MixerListCount
++;
884 DPRINT("New MixerCount %lu\n", MixerList
->MixerListCount
);
889 // filter exposes its topology on the same filter
890 MMixerFreeMixerInfo(MixerContext
, MixerInfo
);
899 IN PMIXER_CONTEXT MixerContext
,
900 IN PMIXER_LIST MixerList
,
902 IN PULONG DeviceCount
,
903 IN LPWSTR DeviceName
)
905 PKSMULTIPLE_ITEM NodeTypes
, NodeConnections
;
910 // get number of pins
911 PinCount
= MMixerGetFilterPinCount(MixerContext
, hMixer
);
913 DPRINT("NumOfPins: %lu\n", PinCount
);
915 // get filter node types
916 Status
= MMixerGetFilterTopologyProperty(MixerContext
, hMixer
, KSPROPERTY_TOPOLOGY_NODES
, &NodeTypes
);
917 if (Status
!= MM_STATUS_SUCCESS
)
923 // get filter node connections
924 Status
= MMixerGetFilterTopologyProperty(MixerContext
, hMixer
, KSPROPERTY_TOPOLOGY_CONNECTIONS
, &NodeConnections
);
925 if (Status
!= MM_STATUS_SUCCESS
)
928 MixerContext
->Free(NodeTypes
);
932 // check if the filter has an wave out node
933 NodeIndex
= MMixerGetIndexOfGuid(NodeTypes
, &KSNODETYPE_DAC
);
934 if (NodeIndex
!= MAXULONG
)
938 Status
= MMixerInitializeFilter(MixerContext
, MixerList
, hMixer
, DeviceName
, NodeTypes
, NodeConnections
, PinCount
, NodeIndex
, FALSE
);
939 DPRINT("MMixerInitializeFilter Status %u\n", Status
);
941 if (Status
== MM_STATUS_SUCCESS
)
943 // increment mixer count
949 // check if the filter has an wave in node
950 NodeIndex
= MMixerGetIndexOfGuid(NodeTypes
, &KSNODETYPE_ADC
);
951 if (NodeIndex
!= MAXULONG
)
954 Status
= MMixerInitializeFilter(MixerContext
, MixerList
, hMixer
, DeviceName
, NodeTypes
, NodeConnections
, PinCount
, NodeIndex
, TRUE
);
955 DPRINT("MMixerInitializeFilter Status %u\n", Status
);
957 if (Status
== MM_STATUS_SUCCESS
)
959 // increment mixer count
966 MixerContext
->Free((PVOID
)NodeTypes
);
967 MixerContext
->Free((PVOID
)NodeConnections
);