2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS Kernel Streaming
4 * FILE: lib/drivers/sound/mmixer/topology.c
5 * PURPOSE: Topology Handling Functions
6 * PROGRAMMER: Johannes Anderwald
15 ULONG Index
, SubIndex
;
17 DPRINT("Num Pins %lu NumNodes %lu\n", Topology
->TopologyPinsCount
, Topology
->TopologyNodesCount
);
19 for(Index
= 0; Index
< Topology
->TopologyPinsCount
; Index
++)
21 DPRINT("PinId %lu NodesConnectedFromCount %lu NodesConnectedToCount %lu Visited %lu\n", Topology
->TopologyPins
[Index
].PinId
,
22 Topology
->TopologyPins
[Index
].NodesConnectedFromCount
, Topology
->TopologyPins
[Index
].NodesConnectedToCount
, Topology
->TopologyPins
[Index
].Visited
);
24 for(SubIndex
= 0; SubIndex
< Topology
->TopologyPins
[Index
].NodesConnectedFromCount
; SubIndex
++)
25 DPRINT("NodesConnectedFrom Index %lu NodeId %lu\n", SubIndex
, Topology
->TopologyPins
[Index
].NodesConnectedFrom
[SubIndex
]->NodeIndex
);
27 for(SubIndex
= 0; SubIndex
< Topology
->TopologyPins
[Index
].NodesConnectedToCount
; SubIndex
++)
28 DPRINT("NodesConnectedTo Index %lu NodeId %lu\n", SubIndex
, Topology
->TopologyPins
[Index
].NodesConnectedTo
[SubIndex
]->NodeIndex
);
31 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
33 DPRINT("NodeId %lu NodesConnectedFromCount %lu NodesConnectedToCount %lu Visited %lu PinConnectedFromCount %lu PinConnectedToCount %lu\n", Topology
->TopologyNodes
[Index
].NodeIndex
,
34 Topology
->TopologyNodes
[Index
].NodeConnectedFromCount
, Topology
->TopologyNodes
[Index
].NodeConnectedToCount
, Topology
->TopologyNodes
[Index
].Visited
,
35 Topology
->TopologyNodes
[Index
].PinConnectedFromCount
, Topology
->TopologyNodes
[Index
].PinConnectedToCount
);
43 MMixerAllocateTopology(
44 IN PMIXER_CONTEXT MixerContext
,
47 OUT PTOPOLOGY
* OutTopology
)
51 /* allocate topology */
52 Topology
= (PTOPOLOGY
)MixerContext
->Alloc(sizeof(TOPOLOGY
));
57 return MM_STATUS_NO_MEMORY
;
60 /* allocate topology pins */
61 Topology
->TopologyPins
= (PPIN
) MixerContext
->Alloc(sizeof(PIN
) * PinCount
);
63 if (!Topology
->TopologyPins
)
66 MixerContext
->Free(Topology
);
69 return MM_STATUS_NO_MEMORY
;
72 /* allocate topology nodes */
75 Topology
->TopologyNodes
= (PTOPOLOGY_NODE
) MixerContext
->Alloc(sizeof(TOPOLOGY_NODE
) * NodesCount
);
77 if (!Topology
->TopologyNodes
)
80 MixerContext
->Free(Topology
->TopologyPins
);
81 MixerContext
->Free(Topology
);
84 return MM_STATUS_NO_MEMORY
;
88 /* initialize topology */
89 Topology
->TopologyPinsCount
= PinCount
;
90 Topology
->TopologyNodesCount
= NodesCount
;
93 *OutTopology
= Topology
;
96 return MM_STATUS_SUCCESS
;
100 MMixerResetTopologyVisitStatus(
101 IN OUT PTOPOLOGY Topology
)
105 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
107 /* reset visited status */
108 Topology
->TopologyNodes
[Index
].Visited
= FALSE
;
111 for(Index
= 0; Index
< Topology
->TopologyPinsCount
; Index
++)
113 /* reset visited status */
114 Topology
->TopologyPins
[Index
].Visited
= FALSE
;
119 MMixerInitializeTopologyNodes(
120 IN PMIXER_CONTEXT MixerContext
,
121 IN PKSMULTIPLE_ITEM NodeTypes
,
122 IN OUT PTOPOLOGY Topology
)
128 ASSERT(Topology
->TopologyNodesCount
== NodeTypes
->Count
);
130 /* get topology node types */
131 Guids
= (LPGUID
)(NodeTypes
+ 1);
133 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
135 /* store node connection index */
136 Topology
->TopologyNodes
[Index
].NodeIndex
= Index
;
138 /* store topology node type */
139 MixerContext
->Copy(&Topology
->TopologyNodes
[Index
].NodeType
, &Guids
[Index
], sizeof(GUID
));
144 MMixerAddPinConnection(
145 IN PMIXER_CONTEXT MixerContext
,
147 IN PTOPOLOGY_NODE Node
,
151 PULONG NewPinsIndex
, OldPinsIndex
;
152 PTOPOLOGY_NODE
* NewNodes
, *OldNodes
;
156 /* get existing count */
157 Count
= Pin
->NodesConnectedToCount
;
158 OldNodes
= Pin
->NodesConnectedTo
;
162 /* get existing count */
163 Count
= Pin
->NodesConnectedFromCount
;
164 OldNodes
= Pin
->NodesConnectedFrom
;
167 /* allocate new nodes array */
168 NewNodes
= MixerContext
->Alloc(sizeof(PTOPOLOGY_NODE
) * (Count
+ 1));
173 return MM_STATUS_NO_MEMORY
;
178 /* copy existing nodes */
179 MixerContext
->Copy(NewNodes
, OldNodes
, sizeof(PTOPOLOGY
) * Count
);
181 /* release old nodes array */
182 MixerContext
->Free(OldNodes
);
185 /* add new topology node */
186 NewNodes
[Count
] = Node
;
190 /* replace old nodes array */
191 Pin
->NodesConnectedTo
= NewNodes
;
193 /* increment nodes count */
194 Pin
->NodesConnectedToCount
++;
196 /* now enlarge PinConnectedFromCount*/
197 Count
= Node
->PinConnectedFromCount
;
199 /* connected pin count for node */
200 OldPinsIndex
= Node
->PinConnectedFrom
;
204 /* replace old nodes array */
205 Pin
->NodesConnectedFrom
= NewNodes
;
207 /* increment nodes count */
208 Pin
->NodesConnectedFromCount
++;
210 /* now enlarge PinConnectedFromCount*/
211 Count
= Node
->PinConnectedToCount
;
213 /* connected pin count for node */
214 OldPinsIndex
= Node
->PinConnectedTo
;
217 /* allocate pin connection index */
218 NewPinsIndex
= MixerContext
->Alloc(sizeof(ULONG
) * (Count
+ 1));
223 return MM_STATUS_NO_MEMORY
;
228 /* copy existing nodes */
229 MixerContext
->Copy(NewPinsIndex
, OldPinsIndex
, sizeof(ULONG
) * Count
);
231 /* release old nodes array */
232 MixerContext
->Free(OldPinsIndex
);
235 /* add new topology node */
236 NewPinsIndex
[Count
] = Pin
->PinId
;
240 /* replace old nodes array */
241 Node
->PinConnectedFrom
= NewPinsIndex
;
243 /* increment pin count */
244 Node
->PinConnectedFromCount
++;
248 /* replace old nodes array */
249 Node
->PinConnectedTo
= NewPinsIndex
;
251 /* increment pin count */
252 Node
->PinConnectedToCount
++;
256 return MM_STATUS_SUCCESS
;
260 MMixerHandleNodeToNodeConnection(
261 IN PMIXER_CONTEXT MixerContext
,
262 IN PKSTOPOLOGY_CONNECTION Connection
,
263 IN OUT PTOPOLOGY Topology
)
265 PTOPOLOGY_NODE InNode
, OutNode
;
266 PTOPOLOGY_NODE
* NewNodes
;
270 ASSERT(Topology
->TopologyNodesCount
> Connection
->ToNode
);
271 ASSERT(Topology
->TopologyNodesCount
> Connection
->FromNode
);
274 InNode
= &Topology
->TopologyNodes
[Connection
->FromNode
];
275 OutNode
= &Topology
->TopologyNodes
[Connection
->ToNode
];
277 /* get existing count */
278 Count
= OutNode
->NodeConnectedFromCount
;
280 /* allocate new nodes array */
281 NewNodes
= MixerContext
->Alloc(sizeof(PTOPOLOGY_NODE
) * (Count
+ 1));
286 return MM_STATUS_NO_MEMORY
;
291 /* copy existing nodes */
292 MixerContext
->Copy(NewNodes
, OutNode
->NodeConnectedFrom
, sizeof(PTOPOLOGY
) * Count
);
294 /* release old nodes array */
295 MixerContext
->Free(OutNode
->NodeConnectedFrom
);
298 /* add new topology node */
299 NewNodes
[OutNode
->NodeConnectedFromCount
] = InNode
;
301 /* replace old nodes array */
302 OutNode
->NodeConnectedFrom
= NewNodes
;
304 /* increment nodes count */
305 OutNode
->NodeConnectedFromCount
++;
307 /* get existing count */
308 Count
= InNode
->NodeConnectedToCount
;
310 /* allocate new nodes array */
311 NewNodes
= MixerContext
->Alloc(sizeof(PTOPOLOGY_NODE
) * (Count
+ 1));
316 return MM_STATUS_NO_MEMORY
;
321 /* copy existing nodes */
322 MixerContext
->Copy(NewNodes
, InNode
->NodeConnectedTo
, sizeof(PTOPOLOGY
) * Count
);
324 /* release old nodes array */
325 MixerContext
->Free(InNode
->NodeConnectedTo
);
328 /* add new topology node */
329 NewNodes
[InNode
->NodeConnectedToCount
] = OutNode
;
331 /* replace old nodes array */
332 InNode
->NodeConnectedTo
= NewNodes
;
334 /* increment nodes count */
335 InNode
->NodeConnectedToCount
++;
338 return MM_STATUS_SUCCESS
;
342 MMixerAddPinToPinConnection(
343 IN PMIXER_CONTEXT MixerContext
,
350 /* now enlarge PinConnectedTo */
351 Count
= InPin
->PinConnectedToCount
;
353 /* allocate pin connection index */
354 NewPinsIndex
= MixerContext
->Alloc(sizeof(ULONG
) * (Count
+ 1));
359 return MM_STATUS_NO_MEMORY
;
364 /* copy existing nodes */
365 MixerContext
->Copy(NewPinsIndex
, InPin
->PinConnectedTo
, sizeof(ULONG
) * Count
);
367 /* release old nodes array */
368 MixerContext
->Free(InPin
->PinConnectedTo
);
371 /* add new topology node */
372 NewPinsIndex
[Count
] = OutPin
->PinId
;
374 /* replace old nodes array */
375 InPin
->PinConnectedTo
= NewPinsIndex
;
377 /* increment pin count */
378 InPin
->PinConnectedToCount
++;
380 /* now enlarge PinConnectedFrom */
381 Count
= OutPin
->PinConnectedFromCount
;
383 /* allocate pin connection index */
384 NewPinsIndex
= MixerContext
->Alloc(sizeof(ULONG
) * (Count
+ 1));
389 return MM_STATUS_NO_MEMORY
;
394 /* copy existing nodes */
395 MixerContext
->Copy(NewPinsIndex
, OutPin
->PinConnectedFrom
, sizeof(ULONG
) * Count
);
397 /* release old nodes array */
398 MixerContext
->Free(OutPin
->PinConnectedFrom
);
401 /* add new topology node */
402 NewPinsIndex
[Count
] = InPin
->PinId
;
404 /* replace old nodes array */
405 OutPin
->PinConnectedFrom
= NewPinsIndex
;
407 /* increment pin count */
408 OutPin
->PinConnectedFromCount
++;
411 return MM_STATUS_SUCCESS
;
415 MMixerHandleNodePinConnection(
416 IN PMIXER_CONTEXT MixerContext
,
417 IN PKSTOPOLOGY_CONNECTION Connection
,
418 IN OUT PTOPOLOGY Topology
)
424 if (Connection
->FromNode
== KSFILTER_NODE
&&
425 Connection
->ToNode
== KSFILTER_NODE
)
427 /* Pin -> Pin direction */
430 ASSERT(Topology
->TopologyPinsCount
> Connection
->FromNodePin
);
431 ASSERT(Topology
->TopologyPinsCount
> Connection
->ToNodePin
);
434 return MMixerAddPinToPinConnection(MixerContext
,
435 &Topology
->TopologyPins
[Connection
->FromNodePin
],
436 &Topology
->TopologyPins
[Connection
->ToNodePin
]);
439 else if (Connection
->FromNode
== KSFILTER_NODE
)
441 /* Pin -> Node direction */
444 ASSERT(Topology
->TopologyPinsCount
> Connection
->FromNodePin
);
445 ASSERT(Topology
->TopologyNodesCount
> Connection
->ToNode
);
446 ASSERT(Connection
->ToNode
!= KSFILTER_NODE
);
449 Pin
= &Topology
->TopologyPins
[Connection
->FromNodePin
];
452 Node
= &Topology
->TopologyNodes
[Connection
->ToNode
];
455 Pin
->PinId
= Connection
->FromNodePin
;
457 /* mark as visited */
459 Node
->Visited
= TRUE
;
462 return MMixerAddPinConnection(MixerContext
, Pin
, Node
, TRUE
);
464 else if (Connection
->ToNode
== KSFILTER_NODE
)
466 /* Node -> Pin direction */
469 ASSERT(Topology
->TopologyPinsCount
> Connection
->ToNodePin
);
470 ASSERT(Topology
->TopologyNodesCount
> Connection
->FromNode
);
471 ASSERT(Connection
->FromNode
!= KSFILTER_NODE
);
474 Pin
= &Topology
->TopologyPins
[Connection
->ToNodePin
];
477 Node
= &Topology
->TopologyNodes
[Connection
->FromNode
];
480 Pin
->PinId
= Connection
->ToNodePin
;
482 /* mark as visited */
484 Node
->Visited
= TRUE
;
487 return MMixerAddPinConnection(MixerContext
, Pin
, Node
, FALSE
);
491 return MM_STATUS_INVALID_PARAMETER
;
495 MMixerExploreTopology(
496 IN PMIXER_CONTEXT MixerContext
,
497 IN PKSMULTIPLE_ITEM NodeConnections
,
498 IN PKSMULTIPLE_ITEM NodeTypes
,
499 IN OUT PTOPOLOGY Topology
)
503 PKSTOPOLOGY_CONNECTION Connection
;
507 ASSERT(Topology
->TopologyNodesCount
== NodeTypes
->Count
);
509 /* get topology node types */
510 Guids
= (LPGUID
)(NodeTypes
+ 1);
512 /* get node connections */
513 Connection
= (PKSTOPOLOGY_CONNECTION
)(NodeConnections
+ 1);
515 for(Index
= 0; Index
< NodeConnections
->Count
; Index
++)
517 if (Connection
[Index
].FromNode
== KSFILTER_NODE
||
518 Connection
[Index
].ToNode
== KSFILTER_NODE
)
520 /* handle connection from Pin -> Node / Node->Pin */
521 Status
= MMixerHandleNodePinConnection(MixerContext
,
528 /* handle connection from Node -> Node */
529 Status
= MMixerHandleNodeToNodeConnection(MixerContext
,
534 if (Status
!= MM_STATUS_SUCCESS
)
536 /* failed to handle connection */
542 return MM_STATUS_SUCCESS
;
546 MMixerAddPinIndexToArray(
547 IN PMIXER_CONTEXT MixerContext
,
550 OUT PULONG OutPinCount
,
555 for(Index
= 0; Index
< MaxPins
; Index
++)
557 if (OutPins
[Index
] != MAXULONG
)
559 if (OutPins
[Index
] > PinId
)
561 /* shift entries up */
562 MixerContext
->Copy(&OutPins
[Index
+ 1], &OutPins
[Index
], (MaxPins
- (Index
+ 1)) * sizeof(ULONG
));
565 OutPins
[Index
] = PinId
;
567 /* increment pin count */
577 OutPins
[Index
] = PinId
;
579 /* increment pin count */
589 MMixerGetUpOrDownStreamPins(
590 IN PMIXER_CONTEXT MixerContext
,
591 IN PTOPOLOGY Topology
,
592 IN PTOPOLOGY_NODE TopologyNode
,
594 OUT PULONG OutPinCount
,
597 ULONG Index
, TopologyNodesCount
, PinsCount
;
598 PTOPOLOGY_NODE
*TopologyNodes
;
603 ASSERT(TopologyNode
->Visited
== FALSE
);
607 /* use pins to which a node is attached to */
608 PinsCount
= TopologyNode
->PinConnectedFromCount
;
609 Pins
= TopologyNode
->PinConnectedFrom
;
611 TopologyNodesCount
= TopologyNode
->NodeConnectedFromCount
;
612 TopologyNodes
= TopologyNode
->NodeConnectedFrom
;
616 /* use pins which are attached to a node */
617 PinsCount
= TopologyNode
->PinConnectedToCount
;
618 Pins
= TopologyNode
->PinConnectedTo
;
620 TopologyNodesCount
= TopologyNode
->NodeConnectedToCount
;
621 TopologyNodes
= TopologyNode
->NodeConnectedTo
;
624 /* add all diretly connected pins */
625 for(Index
= 0; Index
< PinsCount
; Index
++)
628 ASSERT(Pins
[Index
] < Topology
->TopologyPinsCount
);
631 Pin
= &Topology
->TopologyPins
[Pins
[Index
]];
633 /* pin should not have been visited */
634 ASSERT(Pin
->Visited
== FALSE
);
635 ASSERT(Pins
[Index
] == Pin
->PinId
);
637 /* FIXME support Pin -> Pin connections in iteration */
640 /* indicates a very broken topology Pin -> Pin -> Node <-... */
641 ASSERT(Pin
->PinConnectedFromCount
== 0);
645 /* indicates a very broken topology -> Node -> Pin -> Pin */
646 ASSERT(Pin
->PinConnectedToCount
== 0);
649 /* add them to pin array */
650 MMixerAddPinIndexToArray(MixerContext
, Pin
->PinId
, Topology
->TopologyPinsCount
, OutPinCount
, OutPins
);
652 /* mark pin as visited */
656 /* mark node as visited */
657 TopologyNode
->Visited
= TRUE
;
659 /* now visit all connected nodes */
660 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
662 /* recursively visit them */
663 MMixerGetUpOrDownStreamPins(MixerContext
, Topology
, TopologyNodes
[Index
], bUpStream
, OutPinCount
, OutPins
);
669 MMixerGetNodeIndexFromGuid(
670 IN PTOPOLOGY Topology
,
671 IN
const GUID
* NodeType
)
675 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
677 if (IsEqualGUIDAligned(NodeType
, &Topology
->TopologyNodes
[Index
].NodeType
))
688 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(
689 IN PMIXER_CONTEXT MixerContext
,
690 IN PTOPOLOGY Topology
,
693 OUT PULONG OutPinsCount
,
696 PTOPOLOGY_NODE TopologyNode
;
698 /* reset visited status */
699 MMixerResetTopologyVisitStatus(Topology
);
702 ASSERT(Topology
->TopologyNodesCount
> NodeIndex
);
704 /* get topology node */
705 TopologyNode
= &Topology
->TopologyNodes
[NodeIndex
];
707 /* now visit all upstream pins & nodes */
708 MMixerGetUpOrDownStreamPins(MixerContext
, Topology
, TopologyNode
, bUpStream
, OutPinsCount
, OutPins
);
712 MMixerGetUpOrDownstreamNodes(
713 IN PMIXER_CONTEXT MixerContext
,
714 IN PTOPOLOGY Topology
,
715 IN PTOPOLOGY_NODE TopologyNode
,
717 OUT PULONG OutNodeCount
,
720 ULONG Index
, TopologyNodesCount
;
721 PTOPOLOGY_NODE Node
, *TopologyNodes
;
725 /* use nodes to which a node is attached to */
726 TopologyNodesCount
= TopologyNode
->NodeConnectedFromCount
;
727 TopologyNodes
= TopologyNode
->NodeConnectedFrom
;
731 /* use nodes which are attached to a node */
732 TopologyNodesCount
= TopologyNode
->NodeConnectedToCount
;
733 TopologyNodes
= TopologyNode
->NodeConnectedTo
;
737 ASSERT(TopologyNode
->Visited
== FALSE
);
739 /* add all connected nodes */
740 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
743 Node
= TopologyNodes
[Index
];
745 /* node should not have been visited */
746 ASSERT(Node
->Visited
== FALSE
);
748 /* add them to node array */
749 MMixerAddPinIndexToArray(MixerContext
, Node
->NodeIndex
, Topology
->TopologyNodesCount
, OutNodeCount
, OutNodes
);
751 /* recursively visit them */
752 MMixerGetUpOrDownstreamNodes(MixerContext
, Topology
, TopologyNodes
[Index
], bUpStream
, OutNodeCount
, OutNodes
);
755 /* mark node as visited */
756 TopologyNode
->Visited
= TRUE
;
761 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(
762 IN PMIXER_CONTEXT MixerContext
,
763 IN PTOPOLOGY Topology
,
766 OUT PULONG OutNodesCount
,
769 PTOPOLOGY_NODE TopologyNode
;
771 /* reset visited status */
772 MMixerResetTopologyVisitStatus(Topology
);
775 ASSERT(Topology
->TopologyNodesCount
> NodeIndex
);
777 /* get topology node */
778 TopologyNode
= &Topology
->TopologyNodes
[NodeIndex
];
780 /* now visit all upstream pins & nodes */
781 MMixerGetUpOrDownstreamNodes(MixerContext
, Topology
, TopologyNode
, bUpStream
, OutNodesCount
, OutNodes
);
784 return MM_STATUS_SUCCESS
;
789 MMixerGetAllUpOrDownstreamPinsFromPinIndex(
790 IN PMIXER_CONTEXT MixerContext
,
791 IN PTOPOLOGY Topology
,
794 OUT PULONG OutPinsCount
,
797 ULONG Index
, TopologyNodesCount
, TopologyPinsCount
;
799 PTOPOLOGY_NODE
*TopologyNodes
;
803 Pin
= &Topology
->TopologyPins
[PinIndex
];
807 /* use nodes to which this pin is attached to */
808 TopologyNodes
= Pin
->NodesConnectedFrom
;
809 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
811 /* use pins to which this pin is attached to */
812 TopologyPins
= Pin
->PinConnectedFrom
;
813 TopologyPinsCount
= Pin
->PinConnectedFromCount
;
818 /* use nodes which are attached to a pin */
819 TopologyNodes
= Pin
->NodesConnectedTo
;
820 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
822 /* use pins which are attached to this pin */
823 TopologyPins
= Pin
->PinConnectedTo
;
824 TopologyPinsCount
= Pin
->PinConnectedToCount
;
828 /* reset visited status */
829 MMixerResetTopologyVisitStatus(Topology
);
832 ASSERT(Topology
->TopologyPinsCount
> PinIndex
);
834 /* add pins which are directly connected to this pin */
835 for(Index
= 0; Index
< TopologyPinsCount
; Index
++)
837 /* add them to pin array */
838 MMixerAddPinIndexToArray(MixerContext
, TopologyPins
[Index
], Topology
->TopologyPinsCount
, OutPinsCount
, OutPins
);
841 /* now visit all up / down stream pins & nodes */
842 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
844 /* explore all connected pins with helper */
845 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext
, Topology
, TopologyNodes
[Index
]->NodeIndex
, bUpStream
, OutPinsCount
, OutPins
);
849 return MM_STATUS_SUCCESS
;
854 MMixerGetAllUpOrDownstreamNodesFromPinIndex(
855 IN PMIXER_CONTEXT MixerContext
,
856 IN PTOPOLOGY Topology
,
859 OUT PULONG OutNodesCount
,
862 ULONG Index
, TopologyNodesCount
;
864 PTOPOLOGY_NODE
*TopologyNodes
;
866 /* mark them as empty */
870 Pin
= &Topology
->TopologyPins
[PinIndex
];
874 /* use nodes to which a pin is attached to */
875 TopologyNodes
= Pin
->NodesConnectedFrom
;
876 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
880 /* use nodes which are attached to a node */
881 TopologyNodes
= Pin
->NodesConnectedTo
;
882 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
886 /* reset visited status */
887 MMixerResetTopologyVisitStatus(Topology
);
890 ASSERT(Topology
->TopologyPinsCount
> PinIndex
);
892 /* now visit all up / down stream pins & nodes */
893 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
895 /* add node to array */
896 MMixerAddPinIndexToArray(MixerContext
, TopologyNodes
[Index
]->NodeIndex
, Topology
->TopologyNodesCount
, OutNodesCount
, OutNodes
);
898 /* explore all connected nodes with helper */
899 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext
, Topology
, TopologyNodes
[Index
]->NodeIndex
, bUpStream
, OutNodesCount
, OutNodes
);
905 MMixerGetNextNodesFromPinIndex(
906 IN PMIXER_CONTEXT MixerContext
,
907 IN PTOPOLOGY Topology
,
910 OUT PULONG OutNodesCount
,
914 TOPOLOGY_NODE
**TopologyNodes
;
915 ULONG TopologyNodesCount
;
919 ASSERT(PinIndex
< Topology
->TopologyPinsCount
);
922 Pin
= &Topology
->TopologyPins
[PinIndex
];
926 /* get up stream nodes */
927 TopologyNodes
= Pin
->NodesConnectedFrom
;
928 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
932 /* get down stream nodes */
933 TopologyNodes
= Pin
->NodesConnectedTo
;
934 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
937 /* store topology nodes ids */
938 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
940 OutNodes
[Index
] = TopologyNodes
[Index
]->NodeIndex
;
943 /* store topology nodes count */
944 *OutNodesCount
= TopologyNodesCount
;
948 MMixerGetNextNodesFromNodeIndex(
949 IN PMIXER_CONTEXT MixerContext
,
950 IN PTOPOLOGY Topology
,
953 OUT PULONG OutNodesCount
,
956 TOPOLOGY_NODE
**TopologyNodes
;
957 ULONG TopologyNodesCount
;
961 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
965 /* get up stream nodes */
966 TopologyNodes
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFrom
;
967 TopologyNodesCount
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFromCount
;
971 /* get down stream nodes */
972 TopologyNodes
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedTo
;
973 TopologyNodesCount
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedToCount
;
976 /* store topology nodes ids */
977 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
979 OutNodes
[Index
] = TopologyNodes
[Index
]->NodeIndex
;
982 /* store topology nodes count */
983 *OutNodesCount
= TopologyNodesCount
;
987 MMixerGetTopologyPinCount(
988 IN PTOPOLOGY Topology
,
991 /* store pin count */
992 *PinCount
= Topology
->TopologyPinsCount
;
996 MMixerAllocateTopologyPinArray(
997 IN PMIXER_CONTEXT MixerContext
,
998 IN PTOPOLOGY Topology
,
999 OUT PULONG
* OutPins
)
1005 ASSERT(Topology
->TopologyPinsCount
!= 0);
1007 /* allocate topology pins */
1008 Pins
= MixerContext
->Alloc(Topology
->TopologyPinsCount
* sizeof(ULONG
));
1013 return MM_STATUS_NO_MEMORY
;
1016 /* mark index as unused */
1017 for(Index
= 0; Index
< Topology
->TopologyPinsCount
; Index
++)
1018 Pins
[Index
] = MAXULONG
;
1024 return MM_STATUS_SUCCESS
;
1028 MMixerAllocateTopologyNodeArray(
1029 IN PMIXER_CONTEXT MixerContext
,
1030 IN PTOPOLOGY Topology
,
1031 OUT PULONG
* OutNodes
)
1037 ASSERT(Topology
->TopologyNodesCount
!= 0);
1039 /* allocate topology pins */
1040 Nodes
= MixerContext
->Alloc(Topology
->TopologyNodesCount
* sizeof(ULONG
));
1045 return MM_STATUS_NO_MEMORY
;
1048 /* mark index as unused */
1049 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
1050 Nodes
[Index
] = MAXULONG
;
1056 return MM_STATUS_SUCCESS
;
1060 MMixerIsNodeTerminator(
1061 IN PTOPOLOGY Topology
,
1063 OUT ULONG
* bTerminator
)
1066 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1068 /* check if node has multiple parents */
1069 if (Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFromCount
> 1)
1071 /* node is connected to multiple other nodes */
1072 *bTerminator
= TRUE
;
1078 /* check if node is mux / sum node */
1079 if (IsEqualGUIDAligned(&Topology
->TopologyNodes
[NodeIndex
].NodeType
, &KSNODETYPE_SUM
) ||
1080 IsEqualGUIDAligned(&Topology
->TopologyNodes
[NodeIndex
].NodeType
, &KSNODETYPE_MUX
))
1082 /* classic terminator */
1083 *bTerminator
= TRUE
;
1090 /* node is not a terminator */
1091 *bTerminator
= FALSE
;
1095 MMixerIsNodeConnectedToPin(
1096 IN PMIXER_CONTEXT MixerContext
,
1097 IN PTOPOLOGY Topology
,
1101 OUT PULONG bConnected
)
1103 MIXER_STATUS Status
;
1104 ULONG Index
, PinsCount
;
1107 /* allocate pin index array */
1108 Status
= MMixerAllocateTopologyPinArray(MixerContext
, Topology
, &Pins
);
1110 if (Status
!= MM_STATUS_SUCCESS
)
1112 /* failed to allocate */
1116 /* now get connected pins */
1118 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext
, Topology
, NodeIndex
, bUpStream
, &PinsCount
, Pins
);
1121 *bConnected
= FALSE
;
1123 for(Index
= 0; Index
< PinsCount
; Index
++)
1125 if (Pins
[Index
] == PinId
)
1127 /* pin is connected */
1133 /* free pin index array */
1134 MixerContext
->Free(Pins
);
1137 return MM_STATUS_SUCCESS
;
1141 MMixerGetNodeTypeFromTopology(
1142 IN PTOPOLOGY Topology
,
1146 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1148 return &Topology
->TopologyNodes
[NodeIndex
].NodeType
;
1152 MMixerSetTopologyNodeReserved(
1153 IN PTOPOLOGY Topology
,
1157 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1160 Topology
->TopologyNodes
[NodeIndex
].Reserved
= TRUE
;
1164 MMixerIsTopologyNodeReserved(
1165 IN PTOPOLOGY Topology
,
1167 OUT PULONG bReserved
)
1170 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1172 /* get reserved status */
1173 *bReserved
= Topology
->TopologyNodes
[NodeIndex
].Reserved
;
1178 MMixerCreateTopology(
1179 IN PMIXER_CONTEXT MixerContext
,
1181 IN PKSMULTIPLE_ITEM NodeConnections
,
1182 IN PKSMULTIPLE_ITEM NodeTypes
,
1183 OUT PTOPOLOGY
*OutTopology
)
1185 MIXER_STATUS Status
;
1188 /* allocate topology */
1189 Status
= MMixerAllocateTopology(MixerContext
, NodeTypes
->Count
, PinCount
, &Topology
);
1191 if (Status
!= MM_STATUS_SUCCESS
)
1193 /* failed to allocate topology */
1197 /* initialize topology nodes */
1198 MMixerInitializeTopologyNodes(MixerContext
, NodeTypes
, Topology
);
1200 /* explore topology */
1201 Status
= MMixerExploreTopology(MixerContext
, NodeConnections
, NodeTypes
, Topology
);
1203 if (Status
!= MM_STATUS_SUCCESS
)
1205 /* failed to allocate topology */
1209 MMixerPrintTopology(Topology
);
1212 *OutTopology
= Topology
;
1215 return MM_STATUS_SUCCESS
;