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
;
267 PULONG NewLogicalPinNodeConnectedFrom
;
272 ASSERT(Topology
->TopologyNodesCount
> Connection
->ToNode
);
273 ASSERT(Topology
->TopologyNodesCount
> Connection
->FromNode
);
276 InNode
= &Topology
->TopologyNodes
[Connection
->FromNode
];
277 OutNode
= &Topology
->TopologyNodes
[Connection
->ToNode
];
279 /* get logical pin node id */
280 LogicalPinId
= Connection
->ToNodePin
;
282 /* get existing count */
283 Count
= OutNode
->NodeConnectedFromCount
;
285 /* allocate new nodes array */
286 NewNodes
= MixerContext
->Alloc(sizeof(PTOPOLOGY_NODE
) * (Count
+ 1));
291 return MM_STATUS_NO_MEMORY
;
294 /* allocate logical pin nodes array */
295 NewLogicalPinNodeConnectedFrom
= MixerContext
->Alloc((Count
+ 1) * sizeof(ULONG
));
296 if (!NewLogicalPinNodeConnectedFrom
)
299 MixerContext
->Free(NewNodes
);
300 return MM_STATUS_NO_MEMORY
;
305 /* copy existing nodes */
306 MixerContext
->Copy(NewNodes
, OutNode
->NodeConnectedFrom
, sizeof(PTOPOLOGY
) * Count
);
308 /* copy existing logical pin node array */
309 MixerContext
->Copy(NewLogicalPinNodeConnectedFrom
, OutNode
->LogicalPinNodeConnectedFrom
, sizeof(ULONG
) * Count
);
311 /* release old nodes array */
312 MixerContext
->Free(OutNode
->NodeConnectedFrom
);
314 /* release old logical pin node array */
315 MixerContext
->Free(OutNode
->LogicalPinNodeConnectedFrom
);
318 /* add new topology node */
319 NewNodes
[OutNode
->NodeConnectedFromCount
] = InNode
;
321 /* add logical node id */
322 NewLogicalPinNodeConnectedFrom
[OutNode
->NodeConnectedFromCount
] = LogicalPinId
;
324 /* replace old nodes array */
325 OutNode
->NodeConnectedFrom
= NewNodes
;
327 /* replace old logical pin node array */
328 OutNode
->LogicalPinNodeConnectedFrom
= NewLogicalPinNodeConnectedFrom
;
330 /* increment nodes count */
331 OutNode
->NodeConnectedFromCount
++;
333 /* get existing count */
334 Count
= InNode
->NodeConnectedToCount
;
336 /* allocate new nodes array */
337 NewNodes
= MixerContext
->Alloc(sizeof(PTOPOLOGY_NODE
) * (Count
+ 1));
342 return MM_STATUS_NO_MEMORY
;
347 /* copy existing nodes */
348 MixerContext
->Copy(NewNodes
, InNode
->NodeConnectedTo
, sizeof(PTOPOLOGY
) * Count
);
350 /* release old nodes array */
351 MixerContext
->Free(InNode
->NodeConnectedTo
);
354 /* add new topology node */
355 NewNodes
[InNode
->NodeConnectedToCount
] = OutNode
;
357 /* replace old nodes array */
358 InNode
->NodeConnectedTo
= NewNodes
;
360 /* increment nodes count */
361 InNode
->NodeConnectedToCount
++;
364 return MM_STATUS_SUCCESS
;
368 MMixerAddPinToPinConnection(
369 IN PMIXER_CONTEXT MixerContext
,
376 /* now enlarge PinConnectedTo */
377 Count
= InPin
->PinConnectedToCount
;
379 /* allocate pin connection index */
380 NewPinsIndex
= MixerContext
->Alloc(sizeof(ULONG
) * (Count
+ 1));
385 return MM_STATUS_NO_MEMORY
;
390 /* copy existing nodes */
391 MixerContext
->Copy(NewPinsIndex
, InPin
->PinConnectedTo
, sizeof(ULONG
) * Count
);
393 /* release old nodes array */
394 MixerContext
->Free(InPin
->PinConnectedTo
);
397 /* add new topology node */
398 NewPinsIndex
[Count
] = OutPin
->PinId
;
400 /* replace old nodes array */
401 InPin
->PinConnectedTo
= NewPinsIndex
;
403 /* increment pin count */
404 InPin
->PinConnectedToCount
++;
406 /* now enlarge PinConnectedFrom */
407 Count
= OutPin
->PinConnectedFromCount
;
409 /* allocate pin connection index */
410 NewPinsIndex
= MixerContext
->Alloc(sizeof(ULONG
) * (Count
+ 1));
415 return MM_STATUS_NO_MEMORY
;
420 /* copy existing nodes */
421 MixerContext
->Copy(NewPinsIndex
, OutPin
->PinConnectedFrom
, sizeof(ULONG
) * Count
);
423 /* release old nodes array */
424 MixerContext
->Free(OutPin
->PinConnectedFrom
);
427 /* add new topology node */
428 NewPinsIndex
[Count
] = InPin
->PinId
;
430 /* replace old nodes array */
431 OutPin
->PinConnectedFrom
= NewPinsIndex
;
433 /* increment pin count */
434 OutPin
->PinConnectedFromCount
++;
437 return MM_STATUS_SUCCESS
;
441 MMixerHandleNodePinConnection(
442 IN PMIXER_CONTEXT MixerContext
,
443 IN PKSTOPOLOGY_CONNECTION Connection
,
444 IN OUT PTOPOLOGY Topology
)
450 if (Connection
->FromNode
== KSFILTER_NODE
&&
451 Connection
->ToNode
== KSFILTER_NODE
)
453 /* Pin -> Pin direction */
456 ASSERT(Topology
->TopologyPinsCount
> Connection
->FromNodePin
);
457 ASSERT(Topology
->TopologyPinsCount
> Connection
->ToNodePin
);
460 return MMixerAddPinToPinConnection(MixerContext
,
461 &Topology
->TopologyPins
[Connection
->FromNodePin
],
462 &Topology
->TopologyPins
[Connection
->ToNodePin
]);
465 else if (Connection
->FromNode
== KSFILTER_NODE
)
467 /* Pin -> Node direction */
470 ASSERT(Topology
->TopologyPinsCount
> Connection
->FromNodePin
);
471 ASSERT(Topology
->TopologyNodesCount
> Connection
->ToNode
);
472 ASSERT(Connection
->ToNode
!= KSFILTER_NODE
);
475 Pin
= &Topology
->TopologyPins
[Connection
->FromNodePin
];
478 Node
= &Topology
->TopologyNodes
[Connection
->ToNode
];
481 Pin
->PinId
= Connection
->FromNodePin
;
483 /* mark as visited */
485 Node
->Visited
= TRUE
;
488 return MMixerAddPinConnection(MixerContext
, Pin
, Node
, TRUE
);
490 else if (Connection
->ToNode
== KSFILTER_NODE
)
492 /* Node -> Pin direction */
495 ASSERT(Topology
->TopologyPinsCount
> Connection
->ToNodePin
);
496 ASSERT(Topology
->TopologyNodesCount
> Connection
->FromNode
);
497 ASSERT(Connection
->FromNode
!= KSFILTER_NODE
);
500 Pin
= &Topology
->TopologyPins
[Connection
->ToNodePin
];
503 Node
= &Topology
->TopologyNodes
[Connection
->FromNode
];
506 Pin
->PinId
= Connection
->ToNodePin
;
508 /* mark as visited */
510 Node
->Visited
= TRUE
;
513 return MMixerAddPinConnection(MixerContext
, Pin
, Node
, FALSE
);
517 return MM_STATUS_INVALID_PARAMETER
;
521 MMixerExploreTopology(
522 IN PMIXER_CONTEXT MixerContext
,
523 IN PKSMULTIPLE_ITEM NodeConnections
,
524 IN PKSMULTIPLE_ITEM NodeTypes
,
525 IN OUT PTOPOLOGY Topology
)
529 PKSTOPOLOGY_CONNECTION Connection
;
533 ASSERT(Topology
->TopologyNodesCount
== NodeTypes
->Count
);
535 /* get topology node types */
536 Guids
= (LPGUID
)(NodeTypes
+ 1);
538 /* get node connections */
539 Connection
= (PKSTOPOLOGY_CONNECTION
)(NodeConnections
+ 1);
541 for(Index
= 0; Index
< NodeConnections
->Count
; Index
++)
543 if (Connection
[Index
].FromNode
== KSFILTER_NODE
||
544 Connection
[Index
].ToNode
== KSFILTER_NODE
)
546 /* handle connection from Pin -> Node / Node->Pin */
547 Status
= MMixerHandleNodePinConnection(MixerContext
,
554 /* handle connection from Node -> Node */
555 Status
= MMixerHandleNodeToNodeConnection(MixerContext
,
560 if (Status
!= MM_STATUS_SUCCESS
)
562 /* failed to handle connection */
568 return MM_STATUS_SUCCESS
;
572 MMixerAddPinIndexToArray(
573 IN PMIXER_CONTEXT MixerContext
,
576 OUT PULONG OutPinCount
,
581 for(Index
= 0; Index
< MaxPins
; Index
++)
583 if (OutPins
[Index
] != MAXULONG
)
585 if (OutPins
[Index
] > PinId
)
587 /* shift entries up */
588 MixerContext
->Copy(&OutPins
[Index
+ 1], &OutPins
[Index
], (MaxPins
- (Index
+ 1)) * sizeof(ULONG
));
591 OutPins
[Index
] = PinId
;
593 /* increment pin count */
603 OutPins
[Index
] = PinId
;
605 /* increment pin count */
615 MMixerGetUpOrDownStreamPins(
616 IN PMIXER_CONTEXT MixerContext
,
617 IN PTOPOLOGY Topology
,
618 IN PTOPOLOGY_NODE TopologyNode
,
620 OUT PULONG OutPinCount
,
623 ULONG Index
, TopologyNodesCount
, PinsCount
;
624 PTOPOLOGY_NODE
*TopologyNodes
;
629 ASSERT(TopologyNode
->Visited
== FALSE
);
633 /* use pins to which a node is attached to */
634 PinsCount
= TopologyNode
->PinConnectedFromCount
;
635 Pins
= TopologyNode
->PinConnectedFrom
;
637 TopologyNodesCount
= TopologyNode
->NodeConnectedFromCount
;
638 TopologyNodes
= TopologyNode
->NodeConnectedFrom
;
642 /* use pins which are attached to a node */
643 PinsCount
= TopologyNode
->PinConnectedToCount
;
644 Pins
= TopologyNode
->PinConnectedTo
;
646 TopologyNodesCount
= TopologyNode
->NodeConnectedToCount
;
647 TopologyNodes
= TopologyNode
->NodeConnectedTo
;
650 /* add all diretly connected pins */
651 for(Index
= 0; Index
< PinsCount
; Index
++)
654 ASSERT(Pins
[Index
] < Topology
->TopologyPinsCount
);
657 Pin
= &Topology
->TopologyPins
[Pins
[Index
]];
659 /* pin should not have been visited */
660 ASSERT(Pin
->Visited
== FALSE
);
661 ASSERT(Pins
[Index
] == Pin
->PinId
);
663 /* FIXME support Pin -> Pin connections in iteration */
666 /* indicates a very broken topology Pin -> Pin -> Node <-... */
667 ASSERT(Pin
->PinConnectedFromCount
== 0);
671 /* indicates a very broken topology -> Node -> Pin -> Pin */
672 ASSERT(Pin
->PinConnectedToCount
== 0);
675 /* add them to pin array */
676 MMixerAddPinIndexToArray(MixerContext
, Pin
->PinId
, Topology
->TopologyPinsCount
, OutPinCount
, OutPins
);
678 /* mark pin as visited */
682 /* mark node as visited */
683 TopologyNode
->Visited
= TRUE
;
685 /* now visit all connected nodes */
686 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
688 /* recursively visit them */
689 MMixerGetUpOrDownStreamPins(MixerContext
, Topology
, TopologyNodes
[Index
], bUpStream
, OutPinCount
, OutPins
);
695 MMixerGetNodeIndexFromGuid(
696 IN PTOPOLOGY Topology
,
697 IN
const GUID
* NodeType
)
701 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
703 if (IsEqualGUIDAligned(NodeType
, &Topology
->TopologyNodes
[Index
].NodeType
))
714 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(
715 IN PMIXER_CONTEXT MixerContext
,
716 IN PTOPOLOGY Topology
,
719 OUT PULONG OutPinsCount
,
722 PTOPOLOGY_NODE TopologyNode
;
724 /* reset visited status */
725 MMixerResetTopologyVisitStatus(Topology
);
728 ASSERT(Topology
->TopologyNodesCount
> NodeIndex
);
730 /* get topology node */
731 TopologyNode
= &Topology
->TopologyNodes
[NodeIndex
];
733 /* now visit all upstream pins & nodes */
734 MMixerGetUpOrDownStreamPins(MixerContext
, Topology
, TopologyNode
, bUpStream
, OutPinsCount
, OutPins
);
738 MMixerGetUpOrDownstreamNodes(
739 IN PMIXER_CONTEXT MixerContext
,
740 IN PTOPOLOGY Topology
,
741 IN PTOPOLOGY_NODE TopologyNode
,
743 OUT PULONG OutNodeCount
,
746 ULONG Index
, TopologyNodesCount
;
747 PTOPOLOGY_NODE Node
, *TopologyNodes
;
751 /* use nodes to which a node is attached to */
752 TopologyNodesCount
= TopologyNode
->NodeConnectedFromCount
;
753 TopologyNodes
= TopologyNode
->NodeConnectedFrom
;
757 /* use nodes which are attached to a node */
758 TopologyNodesCount
= TopologyNode
->NodeConnectedToCount
;
759 TopologyNodes
= TopologyNode
->NodeConnectedTo
;
763 ASSERT(TopologyNode
->Visited
== FALSE
);
765 /* add all connected nodes */
766 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
769 Node
= TopologyNodes
[Index
];
771 /* node should not have been visited */
772 ASSERT(Node
->Visited
== FALSE
);
774 /* mark node as visited */
775 TopologyNode
->Visited
= TRUE
;
777 /* add them to node array */
778 MMixerAddPinIndexToArray(MixerContext
, Node
->NodeIndex
, Topology
->TopologyNodesCount
, OutNodeCount
, OutNodes
);
780 /* recursively visit them */
781 MMixerGetUpOrDownstreamNodes(MixerContext
, Topology
, TopologyNodes
[Index
], bUpStream
, OutNodeCount
, OutNodes
);
786 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(
787 IN PMIXER_CONTEXT MixerContext
,
788 IN PTOPOLOGY Topology
,
791 OUT PULONG OutNodesCount
,
794 PTOPOLOGY_NODE TopologyNode
;
796 /* reset visited status */
797 MMixerResetTopologyVisitStatus(Topology
);
800 ASSERT(Topology
->TopologyNodesCount
> NodeIndex
);
802 /* get topology node */
803 TopologyNode
= &Topology
->TopologyNodes
[NodeIndex
];
805 /* now visit all upstream pins & nodes */
806 MMixerGetUpOrDownstreamNodes(MixerContext
, Topology
, TopologyNode
, bUpStream
, OutNodesCount
, OutNodes
);
809 return MM_STATUS_SUCCESS
;
814 MMixerGetAllUpOrDownstreamPinsFromPinIndex(
815 IN PMIXER_CONTEXT MixerContext
,
816 IN PTOPOLOGY Topology
,
819 OUT PULONG OutPinsCount
,
822 ULONG Index
, TopologyNodesCount
, TopologyPinsCount
;
824 PTOPOLOGY_NODE
*TopologyNodes
;
828 Pin
= &Topology
->TopologyPins
[PinIndex
];
832 /* use nodes to which this pin is attached to */
833 TopologyNodes
= Pin
->NodesConnectedFrom
;
834 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
836 /* use pins to which this pin is attached to */
837 TopologyPins
= Pin
->PinConnectedFrom
;
838 TopologyPinsCount
= Pin
->PinConnectedFromCount
;
843 /* use nodes which are attached to a pin */
844 TopologyNodes
= Pin
->NodesConnectedTo
;
845 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
847 /* use pins which are attached to this pin */
848 TopologyPins
= Pin
->PinConnectedTo
;
849 TopologyPinsCount
= Pin
->PinConnectedToCount
;
853 /* reset visited status */
854 MMixerResetTopologyVisitStatus(Topology
);
857 ASSERT(Topology
->TopologyPinsCount
> PinIndex
);
859 /* add pins which are directly connected to this pin */
860 for(Index
= 0; Index
< TopologyPinsCount
; Index
++)
862 /* add them to pin array */
863 MMixerAddPinIndexToArray(MixerContext
, TopologyPins
[Index
], Topology
->TopologyPinsCount
, OutPinsCount
, OutPins
);
866 /* now visit all up / down stream pins & nodes */
867 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
869 /* explore all connected pins with helper */
870 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext
, Topology
, TopologyNodes
[Index
]->NodeIndex
, bUpStream
, OutPinsCount
, OutPins
);
874 return MM_STATUS_SUCCESS
;
879 MMixerGetAllUpOrDownstreamNodesFromPinIndex(
880 IN PMIXER_CONTEXT MixerContext
,
881 IN PTOPOLOGY Topology
,
884 OUT PULONG OutNodesCount
,
887 ULONG Index
, TopologyNodesCount
;
889 PTOPOLOGY_NODE
*TopologyNodes
;
891 /* mark them as empty */
895 Pin
= &Topology
->TopologyPins
[PinIndex
];
899 /* use nodes to which a pin is attached to */
900 TopologyNodes
= Pin
->NodesConnectedFrom
;
901 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
905 /* use nodes which are attached to a node */
906 TopologyNodes
= Pin
->NodesConnectedTo
;
907 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
911 /* reset visited status */
912 MMixerResetTopologyVisitStatus(Topology
);
915 ASSERT(Topology
->TopologyPinsCount
> PinIndex
);
917 /* now visit all up / down stream pins & nodes */
918 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
920 /* add node to array */
921 MMixerAddPinIndexToArray(MixerContext
, TopologyNodes
[Index
]->NodeIndex
, Topology
->TopologyNodesCount
, OutNodesCount
, OutNodes
);
923 /* explore all connected nodes with helper */
924 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext
, Topology
, TopologyNodes
[Index
]->NodeIndex
, bUpStream
, OutNodesCount
, OutNodes
);
930 MMixerGetNextNodesFromPinIndex(
931 IN PMIXER_CONTEXT MixerContext
,
932 IN PTOPOLOGY Topology
,
935 OUT PULONG OutNodesCount
,
939 TOPOLOGY_NODE
**TopologyNodes
;
940 ULONG TopologyNodesCount
;
944 ASSERT(PinIndex
< Topology
->TopologyPinsCount
);
947 Pin
= &Topology
->TopologyPins
[PinIndex
];
951 /* get up stream nodes */
952 TopologyNodes
= Pin
->NodesConnectedFrom
;
953 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
957 /* get down stream nodes */
958 TopologyNodes
= Pin
->NodesConnectedTo
;
959 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
962 /* store topology nodes ids */
963 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
965 OutNodes
[Index
] = TopologyNodes
[Index
]->NodeIndex
;
968 /* store topology nodes count */
969 *OutNodesCount
= TopologyNodesCount
;
973 MMixerGetNextNodesFromNodeIndex(
974 IN PMIXER_CONTEXT MixerContext
,
975 IN PTOPOLOGY Topology
,
978 OUT PULONG OutNodesCount
,
981 TOPOLOGY_NODE
**TopologyNodes
;
982 ULONG TopologyNodesCount
;
986 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
990 /* get up stream nodes */
991 TopologyNodes
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFrom
;
992 TopologyNodesCount
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFromCount
;
996 /* get down stream nodes */
997 TopologyNodes
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedTo
;
998 TopologyNodesCount
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedToCount
;
1001 /* store topology nodes ids */
1002 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
1004 OutNodes
[Index
] = TopologyNodes
[Index
]->NodeIndex
;
1007 /* store topology nodes count */
1008 *OutNodesCount
= TopologyNodesCount
;
1012 MMixerGetTopologyPinCount(
1013 IN PTOPOLOGY Topology
,
1014 OUT PULONG PinCount
)
1016 /* store pin count */
1017 *PinCount
= Topology
->TopologyPinsCount
;
1021 MMixerAllocateTopologyPinArray(
1022 IN PMIXER_CONTEXT MixerContext
,
1023 IN PTOPOLOGY Topology
,
1024 OUT PULONG
* OutPins
)
1030 ASSERT(Topology
->TopologyPinsCount
!= 0);
1032 /* allocate topology pins */
1033 Pins
= MixerContext
->Alloc(Topology
->TopologyPinsCount
* sizeof(ULONG
));
1038 return MM_STATUS_NO_MEMORY
;
1041 /* mark index as unused */
1042 for(Index
= 0; Index
< Topology
->TopologyPinsCount
; Index
++)
1043 Pins
[Index
] = MAXULONG
;
1049 return MM_STATUS_SUCCESS
;
1053 MMixerAllocateTopologyNodeArray(
1054 IN PMIXER_CONTEXT MixerContext
,
1055 IN PTOPOLOGY Topology
,
1056 OUT PULONG
* OutNodes
)
1062 ASSERT(Topology
->TopologyNodesCount
!= 0);
1064 /* allocate topology pins */
1065 Nodes
= MixerContext
->Alloc(Topology
->TopologyNodesCount
* sizeof(ULONG
));
1070 return MM_STATUS_NO_MEMORY
;
1073 /* mark index as unused */
1074 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
1075 Nodes
[Index
] = MAXULONG
;
1081 return MM_STATUS_SUCCESS
;
1085 MMixerIsNodeTerminator(
1086 IN PTOPOLOGY Topology
,
1088 OUT ULONG
* bTerminator
)
1091 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1093 /* check if node has multiple parents */
1094 if (Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFromCount
> 1)
1096 /* node is connected to multiple other nodes */
1097 *bTerminator
= TRUE
;
1103 /* check if node is mux / sum node */
1104 if (IsEqualGUIDAligned(&Topology
->TopologyNodes
[NodeIndex
].NodeType
, &KSNODETYPE_SUM
) ||
1105 IsEqualGUIDAligned(&Topology
->TopologyNodes
[NodeIndex
].NodeType
, &KSNODETYPE_MUX
))
1107 /* classic terminator */
1108 *bTerminator
= TRUE
;
1115 /* node is not a terminator */
1116 *bTerminator
= FALSE
;
1120 MMixerIsNodeConnectedToPin(
1121 IN PMIXER_CONTEXT MixerContext
,
1122 IN PTOPOLOGY Topology
,
1126 OUT PULONG bConnected
)
1128 MIXER_STATUS Status
;
1129 ULONG Index
, PinsCount
;
1132 /* allocate pin index array */
1133 Status
= MMixerAllocateTopologyPinArray(MixerContext
, Topology
, &Pins
);
1135 if (Status
!= MM_STATUS_SUCCESS
)
1137 /* failed to allocate */
1141 /* now get connected pins */
1143 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext
, Topology
, NodeIndex
, bUpStream
, &PinsCount
, Pins
);
1146 *bConnected
= FALSE
;
1148 for(Index
= 0; Index
< PinsCount
; Index
++)
1150 if (Pins
[Index
] == PinId
)
1152 /* pin is connected */
1158 /* free pin index array */
1159 MixerContext
->Free(Pins
);
1162 return MM_STATUS_SUCCESS
;
1166 MMixerGetConnectedFromLogicalTopologyPins(
1167 IN PTOPOLOGY Topology
,
1169 OUT PULONG OutPinCount
,
1173 PTOPOLOGY_NODE Node
;
1176 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1179 Node
= &Topology
->TopologyNodes
[NodeIndex
];
1181 for(Index
= 0; Index
< Node
->NodeConnectedFromCount
; Index
++)
1183 /* copy logical pin id */
1184 OutPins
[Index
] = Node
->LogicalPinNodeConnectedFrom
[Index
];
1187 /* store pin count */
1188 *OutPinCount
= Node
->NodeConnectedFromCount
;
1192 MMixerGetNodeTypeFromTopology(
1193 IN PTOPOLOGY Topology
,
1197 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1199 return &Topology
->TopologyNodes
[NodeIndex
].NodeType
;
1203 MMixerSetTopologyPinReserved(
1204 IN PTOPOLOGY Topology
,
1208 ASSERT(PinId
< Topology
->TopologyPinsCount
);
1211 Topology
->TopologyPins
[PinId
].Reserved
= TRUE
;
1215 MMixerIsTopologyPinReserved(
1216 IN PTOPOLOGY Topology
,
1218 OUT PULONG bReserved
)
1221 ASSERT(PinId
< Topology
->TopologyPinsCount
);
1223 /* get reserved status */
1224 *bReserved
= Topology
->TopologyPins
[PinId
].Reserved
;
1228 MMixerSetTopologyNodeReserved(
1229 IN PTOPOLOGY Topology
,
1233 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1236 Topology
->TopologyNodes
[NodeIndex
].Reserved
= TRUE
;
1240 MMixerIsTopologyNodeReserved(
1241 IN PTOPOLOGY Topology
,
1243 OUT PULONG bReserved
)
1246 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1248 /* get reserved status */
1249 *bReserved
= Topology
->TopologyNodes
[NodeIndex
].Reserved
;
1254 MMixerCreateTopology(
1255 IN PMIXER_CONTEXT MixerContext
,
1257 IN PKSMULTIPLE_ITEM NodeConnections
,
1258 IN PKSMULTIPLE_ITEM NodeTypes
,
1259 OUT PTOPOLOGY
*OutTopology
)
1261 MIXER_STATUS Status
;
1264 /* allocate topology */
1265 Status
= MMixerAllocateTopology(MixerContext
, NodeTypes
->Count
, PinCount
, &Topology
);
1267 if (Status
!= MM_STATUS_SUCCESS
)
1269 /* failed to allocate topology */
1273 /* initialize topology nodes */
1274 MMixerInitializeTopologyNodes(MixerContext
, NodeTypes
, Topology
);
1276 /* explore topology */
1277 Status
= MMixerExploreTopology(MixerContext
, NodeConnections
, NodeTypes
, Topology
);
1279 if (Status
!= MM_STATUS_SUCCESS
)
1281 /* failed to allocate topology */
1285 MMixerPrintTopology(Topology
);
1288 *OutTopology
= Topology
;
1291 return MM_STATUS_SUCCESS
;