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
18 ULONG Index
, SubIndex
;
20 DPRINT("Num Pins %lu NumNodes %lu\n", Topology
->TopologyPinsCount
, Topology
->TopologyNodesCount
);
22 for(Index
= 0; Index
< Topology
->TopologyPinsCount
; Index
++)
24 DPRINT("PinId %lu NodesConnectedFromCount %lu NodesConnectedToCount %lu Visited %lu\n", Topology
->TopologyPins
[Index
].PinId
,
25 Topology
->TopologyPins
[Index
].NodesConnectedFromCount
, Topology
->TopologyPins
[Index
].NodesConnectedToCount
, Topology
->TopologyPins
[Index
].Visited
);
27 for(SubIndex
= 0; SubIndex
< Topology
->TopologyPins
[Index
].NodesConnectedFromCount
; SubIndex
++)
28 DPRINT("NodesConnectedFrom Index %lu NodeId %lu\n", SubIndex
, Topology
->TopologyPins
[Index
].NodesConnectedFrom
[SubIndex
]->NodeIndex
);
30 for(SubIndex
= 0; SubIndex
< Topology
->TopologyPins
[Index
].NodesConnectedToCount
; SubIndex
++)
31 DPRINT("NodesConnectedTo Index %lu NodeId %lu\n", SubIndex
, Topology
->TopologyPins
[Index
].NodesConnectedTo
[SubIndex
]->NodeIndex
);
34 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
36 DPRINT("NodeId %lu NodesConnectedFromCount %lu NodesConnectedToCount %lu Visited %lu PinConnectedFromCount %lu PinConnectedToCount %lu\n", Topology
->TopologyNodes
[Index
].NodeIndex
,
37 Topology
->TopologyNodes
[Index
].NodeConnectedFromCount
, Topology
->TopologyNodes
[Index
].NodeConnectedToCount
, Topology
->TopologyNodes
[Index
].Visited
,
38 Topology
->TopologyNodes
[Index
].PinConnectedFromCount
, Topology
->TopologyNodes
[Index
].PinConnectedToCount
);
46 MMixerAllocateTopology(
47 IN PMIXER_CONTEXT MixerContext
,
50 OUT PTOPOLOGY
* OutTopology
)
54 /* allocate topology */
55 Topology
= (PTOPOLOGY
)MixerContext
->Alloc(sizeof(TOPOLOGY
));
60 return MM_STATUS_NO_MEMORY
;
63 /* allocate topology pins */
64 Topology
->TopologyPins
= (PPIN
) MixerContext
->Alloc(sizeof(PIN
) * PinCount
);
66 if (!Topology
->TopologyPins
)
69 MixerContext
->Free(Topology
);
72 return MM_STATUS_NO_MEMORY
;
75 /* allocate topology nodes */
78 Topology
->TopologyNodes
= (PTOPOLOGY_NODE
) MixerContext
->Alloc(sizeof(TOPOLOGY_NODE
) * NodesCount
);
80 if (!Topology
->TopologyNodes
)
83 MixerContext
->Free(Topology
->TopologyPins
);
84 MixerContext
->Free(Topology
);
87 return MM_STATUS_NO_MEMORY
;
91 /* initialize topology */
92 Topology
->TopologyPinsCount
= PinCount
;
93 Topology
->TopologyNodesCount
= NodesCount
;
96 *OutTopology
= Topology
;
99 return MM_STATUS_SUCCESS
;
103 MMixerResetTopologyVisitStatus(
104 IN OUT PTOPOLOGY Topology
)
108 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
110 /* reset visited status */
111 Topology
->TopologyNodes
[Index
].Visited
= FALSE
;
114 for(Index
= 0; Index
< Topology
->TopologyPinsCount
; Index
++)
116 /* reset visited status */
117 Topology
->TopologyPins
[Index
].Visited
= FALSE
;
122 MMixerInitializeTopologyNodes(
123 IN PMIXER_CONTEXT MixerContext
,
124 IN PKSMULTIPLE_ITEM NodeTypes
,
125 IN OUT PTOPOLOGY Topology
)
131 ASSERT(Topology
->TopologyNodesCount
== NodeTypes
->Count
);
133 /* get topology node types */
134 Guids
= (LPGUID
)(NodeTypes
+ 1);
136 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
138 /* store node connection index */
139 Topology
->TopologyNodes
[Index
].NodeIndex
= Index
;
141 /* store topology node type */
142 MixerContext
->Copy(&Topology
->TopologyNodes
[Index
].NodeType
, &Guids
[Index
], sizeof(GUID
));
147 MMixerAddPinConnection(
148 IN PMIXER_CONTEXT MixerContext
,
150 IN PTOPOLOGY_NODE Node
,
154 PULONG NewPinsIndex
, OldPinsIndex
;
155 PTOPOLOGY_NODE
* NewNodes
, *OldNodes
;
159 /* get existing count */
160 Count
= Pin
->NodesConnectedToCount
;
161 OldNodes
= Pin
->NodesConnectedTo
;
165 /* get existing count */
166 Count
= Pin
->NodesConnectedFromCount
;
167 OldNodes
= Pin
->NodesConnectedFrom
;
170 /* allocate new nodes array */
171 NewNodes
= MixerContext
->Alloc(sizeof(PTOPOLOGY_NODE
) * (Count
+ 1));
176 return MM_STATUS_NO_MEMORY
;
181 /* copy existing nodes */
182 MixerContext
->Copy(NewNodes
, OldNodes
, sizeof(PTOPOLOGY
) * Count
);
184 /* release old nodes array */
185 MixerContext
->Free(OldNodes
);
188 /* add new topology node */
189 NewNodes
[Count
] = Node
;
193 /* replace old nodes array */
194 Pin
->NodesConnectedTo
= NewNodes
;
196 /* increment nodes count */
197 Pin
->NodesConnectedToCount
++;
199 /* now enlarge PinConnectedFromCount*/
200 Count
= Node
->PinConnectedFromCount
;
202 /* connected pin count for node */
203 OldPinsIndex
= Node
->PinConnectedFrom
;
207 /* replace old nodes array */
208 Pin
->NodesConnectedFrom
= NewNodes
;
210 /* increment nodes count */
211 Pin
->NodesConnectedFromCount
++;
213 /* now enlarge PinConnectedFromCount*/
214 Count
= Node
->PinConnectedToCount
;
216 /* connected pin count for node */
217 OldPinsIndex
= Node
->PinConnectedTo
;
220 /* allocate pin connection index */
221 NewPinsIndex
= MixerContext
->Alloc(sizeof(ULONG
) * (Count
+ 1));
226 return MM_STATUS_NO_MEMORY
;
231 /* copy existing nodes */
232 MixerContext
->Copy(NewPinsIndex
, OldPinsIndex
, sizeof(ULONG
) * Count
);
234 /* release old nodes array */
235 MixerContext
->Free(OldPinsIndex
);
238 /* add new topology node */
239 NewPinsIndex
[Count
] = Pin
->PinId
;
243 /* replace old nodes array */
244 Node
->PinConnectedFrom
= NewPinsIndex
;
246 /* increment pin count */
247 Node
->PinConnectedFromCount
++;
251 /* replace old nodes array */
252 Node
->PinConnectedTo
= NewPinsIndex
;
254 /* increment pin count */
255 Node
->PinConnectedToCount
++;
259 return MM_STATUS_SUCCESS
;
263 MMixerHandleNodeToNodeConnection(
264 IN PMIXER_CONTEXT MixerContext
,
265 IN PKSTOPOLOGY_CONNECTION Connection
,
266 IN OUT PTOPOLOGY Topology
)
268 PTOPOLOGY_NODE InNode
, OutNode
;
269 PTOPOLOGY_NODE
* NewNodes
;
270 PULONG NewLogicalPinNodeConnectedFrom
;
275 ASSERT(Topology
->TopologyNodesCount
> Connection
->ToNode
);
276 ASSERT(Topology
->TopologyNodesCount
> Connection
->FromNode
);
279 InNode
= &Topology
->TopologyNodes
[Connection
->FromNode
];
280 OutNode
= &Topology
->TopologyNodes
[Connection
->ToNode
];
282 /* get logical pin node id */
283 LogicalPinId
= Connection
->ToNodePin
;
285 /* get existing count */
286 Count
= OutNode
->NodeConnectedFromCount
;
288 /* allocate new nodes array */
289 NewNodes
= MixerContext
->Alloc(sizeof(PTOPOLOGY_NODE
) * (Count
+ 1));
294 return MM_STATUS_NO_MEMORY
;
297 /* allocate logical pin nodes array */
298 NewLogicalPinNodeConnectedFrom
= MixerContext
->Alloc((Count
+ 1) * sizeof(ULONG
));
299 if (!NewLogicalPinNodeConnectedFrom
)
302 MixerContext
->Free(NewNodes
);
303 return MM_STATUS_NO_MEMORY
;
308 /* copy existing nodes */
309 MixerContext
->Copy(NewNodes
, OutNode
->NodeConnectedFrom
, sizeof(PTOPOLOGY
) * Count
);
311 /* copy existing logical pin node array */
312 MixerContext
->Copy(NewLogicalPinNodeConnectedFrom
, OutNode
->LogicalPinNodeConnectedFrom
, sizeof(ULONG
) * Count
);
314 /* release old nodes array */
315 MixerContext
->Free(OutNode
->NodeConnectedFrom
);
317 /* release old logical pin node array */
318 MixerContext
->Free(OutNode
->LogicalPinNodeConnectedFrom
);
321 /* add new topology node */
322 NewNodes
[OutNode
->NodeConnectedFromCount
] = InNode
;
324 /* add logical node id */
325 NewLogicalPinNodeConnectedFrom
[OutNode
->NodeConnectedFromCount
] = LogicalPinId
;
327 /* replace old nodes array */
328 OutNode
->NodeConnectedFrom
= NewNodes
;
330 /* replace old logical pin node array */
331 OutNode
->LogicalPinNodeConnectedFrom
= NewLogicalPinNodeConnectedFrom
;
333 /* increment nodes count */
334 OutNode
->NodeConnectedFromCount
++;
336 /* get existing count */
337 Count
= InNode
->NodeConnectedToCount
;
339 /* allocate new nodes array */
340 NewNodes
= MixerContext
->Alloc(sizeof(PTOPOLOGY_NODE
) * (Count
+ 1));
345 return MM_STATUS_NO_MEMORY
;
350 /* copy existing nodes */
351 MixerContext
->Copy(NewNodes
, InNode
->NodeConnectedTo
, sizeof(PTOPOLOGY
) * Count
);
353 /* release old nodes array */
354 MixerContext
->Free(InNode
->NodeConnectedTo
);
357 /* add new topology node */
358 NewNodes
[InNode
->NodeConnectedToCount
] = OutNode
;
360 /* replace old nodes array */
361 InNode
->NodeConnectedTo
= NewNodes
;
363 /* increment nodes count */
364 InNode
->NodeConnectedToCount
++;
367 return MM_STATUS_SUCCESS
;
371 MMixerAddPinToPinConnection(
372 IN PMIXER_CONTEXT MixerContext
,
379 /* now enlarge PinConnectedTo */
380 Count
= InPin
->PinConnectedToCount
;
382 /* allocate pin connection index */
383 NewPinsIndex
= MixerContext
->Alloc(sizeof(ULONG
) * (Count
+ 1));
388 return MM_STATUS_NO_MEMORY
;
393 /* copy existing nodes */
394 MixerContext
->Copy(NewPinsIndex
, InPin
->PinConnectedTo
, sizeof(ULONG
) * Count
);
396 /* release old nodes array */
397 MixerContext
->Free(InPin
->PinConnectedTo
);
400 /* add new topology node */
401 NewPinsIndex
[Count
] = OutPin
->PinId
;
403 /* replace old nodes array */
404 InPin
->PinConnectedTo
= NewPinsIndex
;
406 /* increment pin count */
407 InPin
->PinConnectedToCount
++;
409 /* now enlarge PinConnectedFrom */
410 Count
= OutPin
->PinConnectedFromCount
;
412 /* allocate pin connection index */
413 NewPinsIndex
= MixerContext
->Alloc(sizeof(ULONG
) * (Count
+ 1));
418 return MM_STATUS_NO_MEMORY
;
423 /* copy existing nodes */
424 MixerContext
->Copy(NewPinsIndex
, OutPin
->PinConnectedFrom
, sizeof(ULONG
) * Count
);
426 /* release old nodes array */
427 MixerContext
->Free(OutPin
->PinConnectedFrom
);
430 /* add new topology node */
431 NewPinsIndex
[Count
] = InPin
->PinId
;
433 /* replace old nodes array */
434 OutPin
->PinConnectedFrom
= NewPinsIndex
;
436 /* increment pin count */
437 OutPin
->PinConnectedFromCount
++;
440 return MM_STATUS_SUCCESS
;
444 MMixerHandleNodePinConnection(
445 IN PMIXER_CONTEXT MixerContext
,
446 IN PKSTOPOLOGY_CONNECTION Connection
,
447 IN OUT PTOPOLOGY Topology
)
453 if (Connection
->FromNode
== KSFILTER_NODE
&&
454 Connection
->ToNode
== KSFILTER_NODE
)
456 /* Pin -> Pin direction */
459 ASSERT(Topology
->TopologyPinsCount
> Connection
->FromNodePin
);
460 ASSERT(Topology
->TopologyPinsCount
> Connection
->ToNodePin
);
463 return MMixerAddPinToPinConnection(MixerContext
,
464 &Topology
->TopologyPins
[Connection
->FromNodePin
],
465 &Topology
->TopologyPins
[Connection
->ToNodePin
]);
468 else if (Connection
->FromNode
== KSFILTER_NODE
)
470 /* Pin -> Node direction */
473 ASSERT(Topology
->TopologyPinsCount
> Connection
->FromNodePin
);
474 ASSERT(Topology
->TopologyNodesCount
> Connection
->ToNode
);
475 ASSERT(Connection
->ToNode
!= KSFILTER_NODE
);
478 Pin
= &Topology
->TopologyPins
[Connection
->FromNodePin
];
481 Node
= &Topology
->TopologyNodes
[Connection
->ToNode
];
484 Pin
->PinId
= Connection
->FromNodePin
;
486 /* mark as visited */
488 Node
->Visited
= TRUE
;
491 return MMixerAddPinConnection(MixerContext
, Pin
, Node
, TRUE
);
493 else if (Connection
->ToNode
== KSFILTER_NODE
)
495 /* Node -> Pin direction */
498 ASSERT(Topology
->TopologyPinsCount
> Connection
->ToNodePin
);
499 ASSERT(Topology
->TopologyNodesCount
> Connection
->FromNode
);
500 ASSERT(Connection
->FromNode
!= KSFILTER_NODE
);
503 Pin
= &Topology
->TopologyPins
[Connection
->ToNodePin
];
506 Node
= &Topology
->TopologyNodes
[Connection
->FromNode
];
509 Pin
->PinId
= Connection
->ToNodePin
;
511 /* mark as visited */
513 Node
->Visited
= TRUE
;
516 return MMixerAddPinConnection(MixerContext
, Pin
, Node
, FALSE
);
520 return MM_STATUS_INVALID_PARAMETER
;
524 MMixerExploreTopology(
525 IN PMIXER_CONTEXT MixerContext
,
526 IN PKSMULTIPLE_ITEM NodeConnections
,
527 IN PKSMULTIPLE_ITEM NodeTypes
,
528 IN OUT PTOPOLOGY Topology
)
531 PKSTOPOLOGY_CONNECTION Connection
;
535 ASSERT(Topology
->TopologyNodesCount
== NodeTypes
->Count
);
537 /* get node connections */
538 Connection
= (PKSTOPOLOGY_CONNECTION
)(NodeConnections
+ 1);
540 for(Index
= 0; Index
< NodeConnections
->Count
; Index
++)
542 if (Connection
[Index
].FromNode
== KSFILTER_NODE
||
543 Connection
[Index
].ToNode
== KSFILTER_NODE
)
545 /* handle connection from Pin -> Node / Node->Pin */
546 Status
= MMixerHandleNodePinConnection(MixerContext
,
553 /* handle connection from Node -> Node */
554 Status
= MMixerHandleNodeToNodeConnection(MixerContext
,
559 if (Status
!= MM_STATUS_SUCCESS
)
561 /* failed to handle connection */
567 return MM_STATUS_SUCCESS
;
571 MMixerAddPinIndexToArray(
572 IN PMIXER_CONTEXT MixerContext
,
575 OUT PULONG OutPinCount
,
580 for(Index
= 0; Index
< MaxPins
; Index
++)
582 if (OutPins
[Index
] != MAXULONG
)
584 if (OutPins
[Index
] > PinId
)
586 /* shift entries up */
587 MixerContext
->Copy(&OutPins
[Index
+ 1], &OutPins
[Index
], (MaxPins
- (Index
+ 1)) * sizeof(ULONG
));
590 OutPins
[Index
] = PinId
;
592 /* increment pin count */
602 OutPins
[Index
] = PinId
;
604 /* increment pin count */
614 MMixerGetUpOrDownStreamPins(
615 IN PMIXER_CONTEXT MixerContext
,
616 IN PTOPOLOGY Topology
,
617 IN PTOPOLOGY_NODE TopologyNode
,
619 OUT PULONG OutPinCount
,
622 ULONG Index
, TopologyNodesCount
, PinsCount
;
623 PTOPOLOGY_NODE
*TopologyNodes
;
628 ASSERT(TopologyNode
->Visited
== FALSE
);
632 /* use pins to which a node is attached to */
633 PinsCount
= TopologyNode
->PinConnectedFromCount
;
634 Pins
= TopologyNode
->PinConnectedFrom
;
636 TopologyNodesCount
= TopologyNode
->NodeConnectedFromCount
;
637 TopologyNodes
= TopologyNode
->NodeConnectedFrom
;
641 /* use pins which are attached to a node */
642 PinsCount
= TopologyNode
->PinConnectedToCount
;
643 Pins
= TopologyNode
->PinConnectedTo
;
645 TopologyNodesCount
= TopologyNode
->NodeConnectedToCount
;
646 TopologyNodes
= TopologyNode
->NodeConnectedTo
;
649 /* add all diretly connected pins */
650 for(Index
= 0; Index
< PinsCount
; Index
++)
653 ASSERT(Pins
[Index
] < Topology
->TopologyPinsCount
);
656 Pin
= &Topology
->TopologyPins
[Pins
[Index
]];
658 /* pin should not have been visited */
659 ASSERT(Pin
->Visited
== FALSE
);
660 ASSERT(Pins
[Index
] == Pin
->PinId
);
662 /* FIXME support Pin -> Pin connections in iteration */
665 /* indicates a very broken topology Pin -> Pin -> Node <-... */
666 ASSERT(Pin
->PinConnectedFromCount
== 0);
670 /* indicates a very broken topology -> Node -> Pin -> Pin */
671 ASSERT(Pin
->PinConnectedToCount
== 0);
674 /* add them to pin array */
675 MMixerAddPinIndexToArray(MixerContext
, Pin
->PinId
, Topology
->TopologyPinsCount
, OutPinCount
, OutPins
);
677 /* mark pin as visited */
681 /* mark node as visited */
682 TopologyNode
->Visited
= TRUE
;
684 /* now visit all connected nodes */
685 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
687 /* recursively visit them */
688 MMixerGetUpOrDownStreamPins(MixerContext
, Topology
, TopologyNodes
[Index
], bUpStream
, OutPinCount
, OutPins
);
694 MMixerGetNodeIndexFromGuid(
695 IN PTOPOLOGY Topology
,
696 IN
const GUID
* NodeType
)
700 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
702 if (IsEqualGUIDAligned(NodeType
, &Topology
->TopologyNodes
[Index
].NodeType
))
713 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(
714 IN PMIXER_CONTEXT MixerContext
,
715 IN PTOPOLOGY Topology
,
718 OUT PULONG OutPinsCount
,
721 PTOPOLOGY_NODE TopologyNode
;
723 /* reset visited status */
724 MMixerResetTopologyVisitStatus(Topology
);
727 ASSERT(Topology
->TopologyNodesCount
> NodeIndex
);
729 /* get topology node */
730 TopologyNode
= &Topology
->TopologyNodes
[NodeIndex
];
732 /* now visit all upstream pins & nodes */
733 MMixerGetUpOrDownStreamPins(MixerContext
, Topology
, TopologyNode
, bUpStream
, OutPinsCount
, OutPins
);
737 MMixerGetUpOrDownstreamNodes(
738 IN PMIXER_CONTEXT MixerContext
,
739 IN PTOPOLOGY Topology
,
740 IN PTOPOLOGY_NODE TopologyNode
,
742 OUT PULONG OutNodeCount
,
745 ULONG Index
, TopologyNodesCount
;
746 PTOPOLOGY_NODE Node
, *TopologyNodes
;
750 /* use nodes to which a node is attached to */
751 TopologyNodesCount
= TopologyNode
->NodeConnectedFromCount
;
752 TopologyNodes
= TopologyNode
->NodeConnectedFrom
;
756 /* use nodes which are attached to a node */
757 TopologyNodesCount
= TopologyNode
->NodeConnectedToCount
;
758 TopologyNodes
= TopologyNode
->NodeConnectedTo
;
762 ASSERT(TopologyNode
->Visited
== FALSE
);
764 /* add all connected nodes */
765 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
768 Node
= TopologyNodes
[Index
];
770 /* node should not have been visited */
771 ASSERT(Node
->Visited
== FALSE
);
773 /* mark node as visited */
774 TopologyNode
->Visited
= TRUE
;
776 /* add them to node array */
777 MMixerAddPinIndexToArray(MixerContext
, Node
->NodeIndex
, Topology
->TopologyNodesCount
, OutNodeCount
, OutNodes
);
779 /* recursively visit them */
780 MMixerGetUpOrDownstreamNodes(MixerContext
, Topology
, TopologyNodes
[Index
], bUpStream
, OutNodeCount
, OutNodes
);
785 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(
786 IN PMIXER_CONTEXT MixerContext
,
787 IN PTOPOLOGY Topology
,
790 OUT PULONG OutNodesCount
,
793 PTOPOLOGY_NODE TopologyNode
;
795 /* reset visited status */
796 MMixerResetTopologyVisitStatus(Topology
);
799 ASSERT(Topology
->TopologyNodesCount
> NodeIndex
);
801 /* get topology node */
802 TopologyNode
= &Topology
->TopologyNodes
[NodeIndex
];
804 /* now visit all upstream pins & nodes */
805 MMixerGetUpOrDownstreamNodes(MixerContext
, Topology
, TopologyNode
, bUpStream
, OutNodesCount
, OutNodes
);
808 return MM_STATUS_SUCCESS
;
813 MMixerGetAllUpOrDownstreamPinsFromPinIndex(
814 IN PMIXER_CONTEXT MixerContext
,
815 IN PTOPOLOGY Topology
,
818 OUT PULONG OutPinsCount
,
821 ULONG Index
, TopologyNodesCount
, TopologyPinsCount
;
823 PTOPOLOGY_NODE
*TopologyNodes
;
827 Pin
= &Topology
->TopologyPins
[PinIndex
];
831 /* use nodes to which this pin is attached to */
832 TopologyNodes
= Pin
->NodesConnectedFrom
;
833 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
835 /* use pins to which this pin is attached to */
836 TopologyPins
= Pin
->PinConnectedFrom
;
837 TopologyPinsCount
= Pin
->PinConnectedFromCount
;
842 /* use nodes which are attached to a pin */
843 TopologyNodes
= Pin
->NodesConnectedTo
;
844 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
846 /* use pins which are attached to this pin */
847 TopologyPins
= Pin
->PinConnectedTo
;
848 TopologyPinsCount
= Pin
->PinConnectedToCount
;
852 /* reset visited status */
853 MMixerResetTopologyVisitStatus(Topology
);
856 ASSERT(Topology
->TopologyPinsCount
> PinIndex
);
858 /* add pins which are directly connected to this pin */
859 for(Index
= 0; Index
< TopologyPinsCount
; Index
++)
861 /* add them to pin array */
862 MMixerAddPinIndexToArray(MixerContext
, TopologyPins
[Index
], Topology
->TopologyPinsCount
, OutPinsCount
, OutPins
);
865 /* now visit all up / down stream pins & nodes */
866 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
868 /* explore all connected pins with helper */
869 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext
, Topology
, TopologyNodes
[Index
]->NodeIndex
, bUpStream
, OutPinsCount
, OutPins
);
873 return MM_STATUS_SUCCESS
;
878 MMixerGetAllUpOrDownstreamNodesFromPinIndex(
879 IN PMIXER_CONTEXT MixerContext
,
880 IN PTOPOLOGY Topology
,
883 OUT PULONG OutNodesCount
,
886 ULONG Index
, TopologyNodesCount
;
888 PTOPOLOGY_NODE
*TopologyNodes
;
890 /* mark them as empty */
894 Pin
= &Topology
->TopologyPins
[PinIndex
];
898 /* use nodes to which a pin is attached to */
899 TopologyNodes
= Pin
->NodesConnectedFrom
;
900 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
904 /* use nodes which are attached to a node */
905 TopologyNodes
= Pin
->NodesConnectedTo
;
906 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
910 /* reset visited status */
911 MMixerResetTopologyVisitStatus(Topology
);
914 ASSERT(Topology
->TopologyPinsCount
> PinIndex
);
916 /* now visit all up / down stream pins & nodes */
917 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
919 /* add node to array */
920 MMixerAddPinIndexToArray(MixerContext
, TopologyNodes
[Index
]->NodeIndex
, Topology
->TopologyNodesCount
, OutNodesCount
, OutNodes
);
922 /* explore all connected nodes with helper */
923 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext
, Topology
, TopologyNodes
[Index
]->NodeIndex
, bUpStream
, OutNodesCount
, OutNodes
);
929 MMixerGetNextNodesFromPinIndex(
930 IN PMIXER_CONTEXT MixerContext
,
931 IN PTOPOLOGY Topology
,
934 OUT PULONG OutNodesCount
,
938 TOPOLOGY_NODE
**TopologyNodes
;
939 ULONG TopologyNodesCount
;
943 ASSERT(PinIndex
< Topology
->TopologyPinsCount
);
946 Pin
= &Topology
->TopologyPins
[PinIndex
];
950 /* get up stream nodes */
951 TopologyNodes
= Pin
->NodesConnectedFrom
;
952 TopologyNodesCount
= Pin
->NodesConnectedFromCount
;
956 /* get down stream nodes */
957 TopologyNodes
= Pin
->NodesConnectedTo
;
958 TopologyNodesCount
= Pin
->NodesConnectedToCount
;
961 /* store topology nodes ids */
962 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
964 OutNodes
[Index
] = TopologyNodes
[Index
]->NodeIndex
;
967 /* store topology nodes count */
968 *OutNodesCount
= TopologyNodesCount
;
972 MMixerGetNextNodesFromNodeIndex(
973 IN PMIXER_CONTEXT MixerContext
,
974 IN PTOPOLOGY Topology
,
977 OUT PULONG OutNodesCount
,
980 TOPOLOGY_NODE
**TopologyNodes
;
981 ULONG TopologyNodesCount
;
985 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
989 /* get up stream nodes */
990 TopologyNodes
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFrom
;
991 TopologyNodesCount
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFromCount
;
995 /* get down stream nodes */
996 TopologyNodes
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedTo
;
997 TopologyNodesCount
= Topology
->TopologyNodes
[NodeIndex
].NodeConnectedToCount
;
1000 /* store topology nodes ids */
1001 for(Index
= 0; Index
< TopologyNodesCount
; Index
++)
1003 OutNodes
[Index
] = TopologyNodes
[Index
]->NodeIndex
;
1006 /* store topology nodes count */
1007 *OutNodesCount
= TopologyNodesCount
;
1011 MMixerGetTopologyPinCount(
1012 IN PTOPOLOGY Topology
,
1013 OUT PULONG PinCount
)
1015 /* store pin count */
1016 *PinCount
= Topology
->TopologyPinsCount
;
1020 MMixerAllocateTopologyPinArray(
1021 IN PMIXER_CONTEXT MixerContext
,
1022 IN PTOPOLOGY Topology
,
1023 OUT PULONG
* OutPins
)
1029 ASSERT(Topology
->TopologyPinsCount
!= 0);
1031 /* allocate topology pins */
1032 Pins
= MixerContext
->Alloc(Topology
->TopologyPinsCount
* sizeof(ULONG
));
1037 return MM_STATUS_NO_MEMORY
;
1040 /* mark index as unused */
1041 for(Index
= 0; Index
< Topology
->TopologyPinsCount
; Index
++)
1042 Pins
[Index
] = MAXULONG
;
1048 return MM_STATUS_SUCCESS
;
1052 MMixerAllocateTopologyNodeArray(
1053 IN PMIXER_CONTEXT MixerContext
,
1054 IN PTOPOLOGY Topology
,
1055 OUT PULONG
* OutNodes
)
1061 ASSERT(Topology
->TopologyNodesCount
!= 0);
1063 /* allocate topology pins */
1064 Nodes
= MixerContext
->Alloc(Topology
->TopologyNodesCount
* sizeof(ULONG
));
1069 return MM_STATUS_NO_MEMORY
;
1072 /* mark index as unused */
1073 for(Index
= 0; Index
< Topology
->TopologyNodesCount
; Index
++)
1074 Nodes
[Index
] = MAXULONG
;
1080 return MM_STATUS_SUCCESS
;
1084 MMixerIsNodeTerminator(
1085 IN PTOPOLOGY Topology
,
1087 OUT ULONG
* bTerminator
)
1090 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1092 /* check if node has multiple parents */
1093 if (Topology
->TopologyNodes
[NodeIndex
].NodeConnectedFromCount
> 1)
1095 /* node is connected to multiple other nodes */
1096 *bTerminator
= TRUE
;
1102 /* check if node is mux / sum node */
1103 if (IsEqualGUIDAligned(&Topology
->TopologyNodes
[NodeIndex
].NodeType
, &KSNODETYPE_SUM
) ||
1104 IsEqualGUIDAligned(&Topology
->TopologyNodes
[NodeIndex
].NodeType
, &KSNODETYPE_MUX
))
1106 /* classic terminator */
1107 *bTerminator
= TRUE
;
1114 /* node is not a terminator */
1115 *bTerminator
= FALSE
;
1119 MMixerIsNodeConnectedToPin(
1120 IN PMIXER_CONTEXT MixerContext
,
1121 IN PTOPOLOGY Topology
,
1125 OUT PULONG bConnected
)
1127 MIXER_STATUS Status
;
1128 ULONG Index
, PinsCount
;
1131 /* allocate pin index array */
1132 Status
= MMixerAllocateTopologyPinArray(MixerContext
, Topology
, &Pins
);
1134 if (Status
!= MM_STATUS_SUCCESS
)
1136 /* failed to allocate */
1140 /* now get connected pins */
1142 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext
, Topology
, NodeIndex
, bUpStream
, &PinsCount
, Pins
);
1145 *bConnected
= FALSE
;
1147 for(Index
= 0; Index
< PinsCount
; Index
++)
1149 if (Pins
[Index
] == PinId
)
1151 /* pin is connected */
1157 /* free pin index array */
1158 MixerContext
->Free(Pins
);
1161 return MM_STATUS_SUCCESS
;
1165 MMixerGetConnectedFromLogicalTopologyPins(
1166 IN PTOPOLOGY Topology
,
1168 OUT PULONG OutPinCount
,
1172 PTOPOLOGY_NODE Node
;
1175 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1178 Node
= &Topology
->TopologyNodes
[NodeIndex
];
1180 for(Index
= 0; Index
< Node
->NodeConnectedFromCount
; Index
++)
1182 /* copy logical pin id */
1183 OutPins
[Index
] = Node
->LogicalPinNodeConnectedFrom
[Index
];
1186 /* store pin count */
1187 *OutPinCount
= Node
->NodeConnectedFromCount
;
1191 MMixerGetNodeTypeFromTopology(
1192 IN PTOPOLOGY Topology
,
1196 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1198 return &Topology
->TopologyNodes
[NodeIndex
].NodeType
;
1202 MMixerSetTopologyPinReserved(
1203 IN PTOPOLOGY Topology
,
1207 ASSERT(PinId
< Topology
->TopologyPinsCount
);
1210 Topology
->TopologyPins
[PinId
].Reserved
= TRUE
;
1214 MMixerIsTopologyPinReserved(
1215 IN PTOPOLOGY Topology
,
1217 OUT PULONG bReserved
)
1220 ASSERT(PinId
< Topology
->TopologyPinsCount
);
1222 /* get reserved status */
1223 *bReserved
= Topology
->TopologyPins
[PinId
].Reserved
;
1227 MMixerSetTopologyNodeReserved(
1228 IN PTOPOLOGY Topology
,
1232 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1235 Topology
->TopologyNodes
[NodeIndex
].Reserved
= TRUE
;
1239 MMixerIsTopologyNodeReserved(
1240 IN PTOPOLOGY Topology
,
1242 OUT PULONG bReserved
)
1245 ASSERT(NodeIndex
< Topology
->TopologyNodesCount
);
1247 /* get reserved status */
1248 *bReserved
= Topology
->TopologyNodes
[NodeIndex
].Reserved
;
1253 MMixerCreateTopology(
1254 IN PMIXER_CONTEXT MixerContext
,
1256 IN PKSMULTIPLE_ITEM NodeConnections
,
1257 IN PKSMULTIPLE_ITEM NodeTypes
,
1258 OUT PTOPOLOGY
*OutTopology
)
1260 MIXER_STATUS Status
;
1263 /* allocate topology */
1264 Status
= MMixerAllocateTopology(MixerContext
, NodeTypes
->Count
, PinCount
, &Topology
);
1266 if (Status
!= MM_STATUS_SUCCESS
)
1268 /* failed to allocate topology */
1272 /* initialize topology nodes */
1273 MMixerInitializeTopologyNodes(MixerContext
, NodeTypes
, Topology
);
1275 /* explore topology */
1276 Status
= MMixerExploreTopology(MixerContext
, NodeConnections
, NodeTypes
, Topology
);
1278 if (Status
!= MM_STATUS_SUCCESS
)
1280 /* failed to allocate topology */
1284 MMixerPrintTopology(Topology
);
1287 *OutTopology
= Topology
;
1290 return MM_STATUS_SUCCESS
;