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 /* mark node as visited */
749 TopologyNode
->Visited
= TRUE
;
751 /* add them to node array */
752 MMixerAddPinIndexToArray(MixerContext
, Node
->NodeIndex
, Topology
->TopologyNodesCount
, OutNodeCount
, OutNodes
);
754 /* recursively visit them */
755 MMixerGetUpOrDownstreamNodes(MixerContext
, Topology
, TopologyNodes
[Index
], bUpStream
, OutNodeCount
, OutNodes
);
760 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(
761 IN PMIXER_CONTEXT MixerContext
,
762 IN PTOPOLOGY Topology
,
765 OUT PULONG OutNodesCount
,
768 PTOPOLOGY_NODE TopologyNode
;
770 /* reset visited status */
771 MMixerResetTopologyVisitStatus(Topology
);
774 ASSERT(Topology
->TopologyNodesCount
> NodeIndex
);
776 /* get topology node */
777 TopologyNode
= &Topology
->TopologyNodes
[NodeIndex
];
779 /* now visit all upstream pins & nodes */
780 MMixerGetUpOrDownstreamNodes(MixerContext
, Topology
, TopologyNode
, bUpStream
, OutNodesCount
, OutNodes
);
783 return MM_STATUS_SUCCESS
;
788 MMixerGetAllUpOrDownstreamPinsFromPinIndex(
789 IN PMIXER_CONTEXT MixerContext
,
790 IN PTOPOLOGY Topology
,
793 OUT PULONG OutPinsCount
,
796 ULONG Index
, TopologyNodesCount
, TopologyPinsCount
;
798 PTOPOLOGY_NODE
*TopologyNodes
;
802 Pin
= &Topology
->TopologyPins
[PinIndex
];
806 /* use nodes to which this pin is attached to */
807 TopologyNodes
= Pin
->NodesConnectedFrom
;
808 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
810 /* use pins to which this pin is attached to */
811 TopologyPins
= Pin
->PinConnectedFrom
;
812 TopologyPinsCount
= Pin
->PinConnectedFromCount
;
817 /* use nodes which are attached to a pin */
818 TopologyNodes
= Pin
->NodesConnectedTo
;
819 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
821 /* use pins which are attached to this pin */
822 TopologyPins
= Pin
->PinConnectedTo
;
823 TopologyPinsCount
= Pin
->PinConnectedToCount
;
827 /* reset visited status */
828 MMixerResetTopologyVisitStatus(Topology
);
831 ASSERT(Topology
->TopologyPinsCount
> PinIndex
);
833 /* add pins which are directly connected to this pin */
834 for(Index
= 0; Index
< TopologyPinsCount
; Index
++)
836 /* add them to pin array */
837 MMixerAddPinIndexToArray(MixerContext
, TopologyPins
[Index
], Topology
->TopologyPinsCount
, OutPinsCount
, OutPins
);
840 /* now visit all up / down stream pins & nodes */
841 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
843 /* explore all connected pins with helper */
844 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext
, Topology
, TopologyNodes
[Index
]->NodeIndex
, bUpStream
, OutPinsCount
, OutPins
);
848 return MM_STATUS_SUCCESS
;
853 MMixerGetAllUpOrDownstreamNodesFromPinIndex(
854 IN PMIXER_CONTEXT MixerContext
,
855 IN PTOPOLOGY Topology
,
858 OUT PULONG OutNodesCount
,
861 ULONG Index
, TopologyNodesCount
;
863 PTOPOLOGY_NODE
*TopologyNodes
;
865 /* mark them as empty */
869 Pin
= &Topology
->TopologyPins
[PinIndex
];
873 /* use nodes to which a pin is attached to */
874 TopologyNodes
= Pin
->NodesConnectedFrom
;
875 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
879 /* use nodes which are attached to a node */
880 TopologyNodes
= Pin
->NodesConnectedTo
;
881 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
885 /* reset visited status */
886 MMixerResetTopologyVisitStatus(Topology
);
889 ASSERT(Topology
->TopologyPinsCount
> PinIndex
);
891 /* now visit all up / down stream pins & nodes */
892 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
894 /* add node to array */
895 MMixerAddPinIndexToArray(MixerContext
, TopologyNodes
[Index
]->NodeIndex
, Topology
->TopologyNodesCount
, OutNodesCount
, OutNodes
);
897 /* explore all connected nodes with helper */
898 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext
, Topology
, TopologyNodes
[Index
]->NodeIndex
, bUpStream
, OutNodesCount
, OutNodes
);
904 MMixerGetNextNodesFromPinIndex(
905 IN PMIXER_CONTEXT MixerContext
,
906 IN PTOPOLOGY Topology
,
909 OUT PULONG OutNodesCount
,
913 TOPOLOGY_NODE
**TopologyNodes
;
914 ULONG TopologyNodesCount
;
918 ASSERT(PinIndex
< Topology
->TopologyPinsCount
);
921 Pin
= &Topology
->TopologyPins
[PinIndex
];
925 /* get up stream nodes */
926 TopologyNodes
= Pin
->NodesConnectedFrom
;
927 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
931 /* get down stream nodes */
932 TopologyNodes
= Pin
->NodesConnectedTo
;
933 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
936 /* store topology nodes ids */
937 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
939 OutNodes
[Index
] = TopologyNodes
[Index
]->NodeIndex
;
942 /* store topology nodes count */
943 *OutNodesCount
= TopologyNodesCount
;
947 MMixerGetNextNodesFromNodeIndex(
948 IN PMIXER_CONTEXT MixerContext
,
949 IN PTOPOLOGY Topology
,
952 OUT PULONG OutNodesCount
,
955 TOPOLOGY_NODE
**TopologyNodes
;
956 ULONG TopologyNodesCount
;
960 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
964 /* get up stream nodes */
965 TopologyNodes
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFrom
;
966 TopologyNodesCount
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFromCount
;
970 /* get down stream nodes */
971 TopologyNodes
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedTo
;
972 TopologyNodesCount
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedToCount
;
975 /* store topology nodes ids */
976 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
978 OutNodes
[Index
] = TopologyNodes
[Index
]->NodeIndex
;
981 /* store topology nodes count */
982 *OutNodesCount
= TopologyNodesCount
;
986 MMixerGetTopologyPinCount(
987 IN PTOPOLOGY Topology
,
990 /* store pin count */
991 *PinCount
= Topology
->TopologyPinsCount
;
995 MMixerAllocateTopologyPinArray(
996 IN PMIXER_CONTEXT MixerContext
,
997 IN PTOPOLOGY Topology
,
998 OUT PULONG
* OutPins
)
1004 ASSERT(Topology
->TopologyPinsCount
!= 0);
1006 /* allocate topology pins */
1007 Pins
= MixerContext
->Alloc(Topology
->TopologyPinsCount
* sizeof(ULONG
));
1012 return MM_STATUS_NO_MEMORY
;
1015 /* mark index as unused */
1016 for(Index
= 0; Index
< Topology
->TopologyPinsCount
; Index
++)
1017 Pins
[Index
] = MAXULONG
;
1023 return MM_STATUS_SUCCESS
;
1027 MMixerAllocateTopologyNodeArray(
1028 IN PMIXER_CONTEXT MixerContext
,
1029 IN PTOPOLOGY Topology
,
1030 OUT PULONG
* OutNodes
)
1036 ASSERT(Topology
->TopologyNodesCount
!= 0);
1038 /* allocate topology pins */
1039 Nodes
= MixerContext
->Alloc(Topology
->TopologyNodesCount
* sizeof(ULONG
));
1044 return MM_STATUS_NO_MEMORY
;
1047 /* mark index as unused */
1048 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
1049 Nodes
[Index
] = MAXULONG
;
1055 return MM_STATUS_SUCCESS
;
1059 MMixerIsNodeTerminator(
1060 IN PTOPOLOGY Topology
,
1062 OUT ULONG
* bTerminator
)
1065 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1067 /* check if node has multiple parents */
1068 if (Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFromCount
> 1)
1070 /* node is connected to multiple other nodes */
1071 *bTerminator
= TRUE
;
1077 /* check if node is mux / sum node */
1078 if (IsEqualGUIDAligned(&Topology
->TopologyNodes
[NodeIndex
].NodeType
, &KSNODETYPE_SUM
) ||
1079 IsEqualGUIDAligned(&Topology
->TopologyNodes
[NodeIndex
].NodeType
, &KSNODETYPE_MUX
))
1081 /* classic terminator */
1082 *bTerminator
= TRUE
;
1089 /* node is not a terminator */
1090 *bTerminator
= FALSE
;
1094 MMixerIsNodeConnectedToPin(
1095 IN PMIXER_CONTEXT MixerContext
,
1096 IN PTOPOLOGY Topology
,
1100 OUT PULONG bConnected
)
1102 MIXER_STATUS Status
;
1103 ULONG Index
, PinsCount
;
1106 /* allocate pin index array */
1107 Status
= MMixerAllocateTopologyPinArray(MixerContext
, Topology
, &Pins
);
1109 if (Status
!= MM_STATUS_SUCCESS
)
1111 /* failed to allocate */
1115 /* now get connected pins */
1117 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext
, Topology
, NodeIndex
, bUpStream
, &PinsCount
, Pins
);
1120 *bConnected
= FALSE
;
1122 for(Index
= 0; Index
< PinsCount
; Index
++)
1124 if (Pins
[Index
] == PinId
)
1126 /* pin is connected */
1132 /* free pin index array */
1133 MixerContext
->Free(Pins
);
1136 return MM_STATUS_SUCCESS
;
1140 MMixerGetNodeTypeFromTopology(
1141 IN PTOPOLOGY Topology
,
1145 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1147 return &Topology
->TopologyNodes
[NodeIndex
].NodeType
;
1151 MMixerSetTopologyNodeReserved(
1152 IN PTOPOLOGY Topology
,
1156 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1159 Topology
->TopologyNodes
[NodeIndex
].Reserved
= TRUE
;
1163 MMixerIsTopologyNodeReserved(
1164 IN PTOPOLOGY Topology
,
1166 OUT PULONG bReserved
)
1169 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1171 /* get reserved status */
1172 *bReserved
= Topology
->TopologyNodes
[NodeIndex
].Reserved
;
1177 MMixerCreateTopology(
1178 IN PMIXER_CONTEXT MixerContext
,
1180 IN PKSMULTIPLE_ITEM NodeConnections
,
1181 IN PKSMULTIPLE_ITEM NodeTypes
,
1182 OUT PTOPOLOGY
*OutTopology
)
1184 MIXER_STATUS Status
;
1187 /* allocate topology */
1188 Status
= MMixerAllocateTopology(MixerContext
, NodeTypes
->Count
, PinCount
, &Topology
);
1190 if (Status
!= MM_STATUS_SUCCESS
)
1192 /* failed to allocate topology */
1196 /* initialize topology nodes */
1197 MMixerInitializeTopologyNodes(MixerContext
, NodeTypes
, Topology
);
1199 /* explore topology */
1200 Status
= MMixerExploreTopology(MixerContext
, NodeConnections
, NodeTypes
, Topology
);
1202 if (Status
!= MM_STATUS_SUCCESS
)
1204 /* failed to allocate topology */
1208 MMixerPrintTopology(Topology
);
1211 *OutTopology
= Topology
;
1214 return MM_STATUS_SUCCESS
;