ReactOS 0.4.15-dev-7834-g00c4b3d
topology.c
Go to the documentation of this file.
1/*
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
7 */
8
9#include "precomp.h"
10
11// #define NDEBUG
12#include <debug.h>
13
14VOID
16 PTOPOLOGY Topology)
17{
18 ULONG Index, SubIndex;
19
20 DPRINT("Num Pins %lu NumNodes %lu\n", Topology->TopologyPinsCount, Topology->TopologyNodesCount);
21
22 for(Index = 0; Index < Topology->TopologyPinsCount; Index++)
23 {
24 DPRINT("PinId %lu NodesConnectedFromCount %lu NodesConnectedToCount %lu Visited %lu\n", Topology->TopologyPins[Index].PinId,
26
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);
29
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);
32 }
33
34 for(Index = 0; Index < Topology->TopologyNodesCount; Index++)
35 {
36 DPRINT("NodeId %lu NodesConnectedFromCount %lu NodesConnectedToCount %lu Visited %lu PinConnectedFromCount %lu PinConnectedToCount %lu\n", Topology->TopologyNodes[Index].NodeIndex,
39 }
40}
41
45 IN ULONG NodesCount,
47 OUT PTOPOLOGY * OutTopology)
48{
49 PTOPOLOGY Topology;
50
51 /* allocate topology */
52 Topology = (PTOPOLOGY)MixerContext->Alloc(sizeof(TOPOLOGY));
53
54 if (!Topology)
55 {
56 /* out of memory */
58 }
59
60 /* allocate topology pins */
61 Topology->TopologyPins = (PPIN) MixerContext->Alloc(sizeof(PIN) * PinCount);
62
63 if (!Topology->TopologyPins)
64 {
65 /* release memory */
66 MixerContext->Free(Topology);
67
68 /* out of memory */
70 }
71
72 /* allocate topology nodes */
73 if (NodesCount)
74 {
75 Topology->TopologyNodes = (PTOPOLOGY_NODE) MixerContext->Alloc(sizeof(TOPOLOGY_NODE) * NodesCount);
76
77 if (!Topology->TopologyNodes)
78 {
79 /* release memory */
80 MixerContext->Free(Topology->TopologyPins);
81 MixerContext->Free(Topology);
82
83 /* out of memory */
85 }
86 }
87
88 /* initialize topology */
89 Topology->TopologyPinsCount = PinCount;
90 Topology->TopologyNodesCount = NodesCount;
91
92 /* store result */
93 *OutTopology = Topology;
94
95 /* done */
96 return MM_STATUS_SUCCESS;
97}
98
99VOID
101 IN OUT PTOPOLOGY Topology)
102{
103 ULONG Index;
104
105 for(Index = 0; Index < Topology->TopologyNodesCount; Index++)
106 {
107 /* reset visited status */
108 Topology->TopologyNodes[Index].Visited = FALSE;
109 }
110
111 for(Index = 0; Index < Topology->TopologyPinsCount; Index++)
112 {
113 /* reset visited status */
114 Topology->TopologyPins[Index].Visited = FALSE;
115 }
116}
117
118VOID
121 IN PKSMULTIPLE_ITEM NodeTypes,
122 IN OUT PTOPOLOGY Topology)
123{
124 ULONG Index;
125 LPGUID Guids;
126
127 /* sanity check */
128 ASSERT(Topology->TopologyNodesCount == NodeTypes->Count);
129
130 /* get topology node types */
131 Guids = (LPGUID)(NodeTypes + 1);
132
133 for(Index = 0; Index < Topology->TopologyNodesCount; Index++)
134 {
135 /* store node connection index */
136 Topology->TopologyNodes[Index].NodeIndex = Index;
137
138 /* store topology node type */
139 MixerContext->Copy(&Topology->TopologyNodes[Index].NodeType, &Guids[Index], sizeof(GUID));
140 }
141}
142
146 IN PPIN Pin,
148 IN ULONG bPinToNode)
149{
150 ULONG Count;
151 PULONG NewPinsIndex, OldPinsIndex;
152 PTOPOLOGY_NODE * NewNodes, *OldNodes;
153
154 if (bPinToNode)
155 {
156 /* get existing count */
157 Count = Pin->NodesConnectedToCount;
158 OldNodes = Pin->NodesConnectedTo;
159 }
160 else
161 {
162 /* get existing count */
163 Count = Pin->NodesConnectedFromCount;
164 OldNodes = Pin->NodesConnectedFrom;
165 }
166
167 /* allocate new nodes array */
168 NewNodes = MixerContext->Alloc(sizeof(PTOPOLOGY_NODE) * (Count + 1));
169
170 if (!NewNodes)
171 {
172 /* out of memory */
173 return MM_STATUS_NO_MEMORY;
174 }
175
176 if (Count)
177 {
178 /* copy existing nodes */
179 MixerContext->Copy(NewNodes, OldNodes, sizeof(PTOPOLOGY) * Count);
180
181 /* release old nodes array */
182 MixerContext->Free(OldNodes);
183 }
184
185 /* add new topology node */
186 NewNodes[Count] = Node;
187
188 if (bPinToNode)
189 {
190 /* replace old nodes array */
191 Pin->NodesConnectedTo = NewNodes;
192
193 /* increment nodes count */
194 Pin->NodesConnectedToCount++;
195
196 /* now enlarge PinConnectedFromCount*/
197 Count = Node->PinConnectedFromCount;
198
199 /* connected pin count for node */
200 OldPinsIndex = Node->PinConnectedFrom;
201 }
202 else
203 {
204 /* replace old nodes array */
205 Pin->NodesConnectedFrom = NewNodes;
206
207 /* increment nodes count */
208 Pin->NodesConnectedFromCount++;
209
210 /* now enlarge PinConnectedFromCount*/
211 Count = Node->PinConnectedToCount;
212
213 /* connected pin count for node */
214 OldPinsIndex = Node->PinConnectedTo;
215 }
216
217 /* allocate pin connection index */
218 NewPinsIndex = MixerContext->Alloc(sizeof(ULONG) * (Count + 1));
219
220 if (!NewPinsIndex)
221 {
222 /* out of memory */
223 return MM_STATUS_NO_MEMORY;
224 }
225
226 if (Count)
227 {
228 /* copy existing nodes */
229 MixerContext->Copy(NewPinsIndex, OldPinsIndex, sizeof(ULONG) * Count);
230
231 /* release old nodes array */
232 MixerContext->Free(OldPinsIndex);
233 }
234
235 /* add new topology node */
236 NewPinsIndex[Count] = Pin->PinId;
237
238 if (bPinToNode)
239 {
240 /* replace old nodes array */
241 Node->PinConnectedFrom = NewPinsIndex;
242
243 /* increment pin count */
244 Node->PinConnectedFromCount++;
245 }
246 else
247 {
248 /* replace old nodes array */
249 Node->PinConnectedTo = NewPinsIndex;
250
251 /* increment pin count */
252 Node->PinConnectedToCount++;
253 }
254
255 /* done */
256 return MM_STATUS_SUCCESS;
257}
258
262 IN PKSTOPOLOGY_CONNECTION Connection,
263 IN OUT PTOPOLOGY Topology)
264{
265 PTOPOLOGY_NODE InNode, OutNode;
266 PTOPOLOGY_NODE * NewNodes;
267 PULONG NewLogicalPinNodeConnectedFrom;
268 ULONG Count;
269 ULONG LogicalPinId;
270
271 /* sanity checks */
272 ASSERT(Topology->TopologyNodesCount > Connection->ToNode);
273 ASSERT(Topology->TopologyNodesCount > Connection->FromNode);
274
275 /* get node */
276 InNode = &Topology->TopologyNodes[Connection->FromNode];
277 OutNode = &Topology->TopologyNodes[Connection->ToNode];
278
279 /* get logical pin node id */
280 LogicalPinId = Connection->ToNodePin;
281
282 /* get existing count */
283 Count = OutNode->NodeConnectedFromCount;
284
285 /* allocate new nodes array */
286 NewNodes = MixerContext->Alloc(sizeof(PTOPOLOGY_NODE) * (Count + 1));
287
288 if (!NewNodes)
289 {
290 /* out of memory */
291 return MM_STATUS_NO_MEMORY;
292 }
293
294 /* allocate logical pin nodes array */
295 NewLogicalPinNodeConnectedFrom = MixerContext->Alloc((Count + 1) * sizeof(ULONG));
296 if (!NewLogicalPinNodeConnectedFrom)
297 {
298 /* out of memory */
299 MixerContext->Free(NewNodes);
300 return MM_STATUS_NO_MEMORY;
301 }
302
303 if (Count)
304 {
305 /* copy existing nodes */
306 MixerContext->Copy(NewNodes, OutNode->NodeConnectedFrom, sizeof(PTOPOLOGY) * Count);
307
308 /* copy existing logical pin node array */
309 MixerContext->Copy(NewLogicalPinNodeConnectedFrom, OutNode->LogicalPinNodeConnectedFrom, sizeof(ULONG) * Count);
310
311 /* release old nodes array */
313
314 /* release old logical pin node array */
316 }
317
318 /* add new topology node */
319 NewNodes[OutNode->NodeConnectedFromCount] = InNode;
320
321 /* add logical node id */
322 NewLogicalPinNodeConnectedFrom[OutNode->NodeConnectedFromCount] = LogicalPinId;
323
324 /* replace old nodes array */
325 OutNode->NodeConnectedFrom = NewNodes;
326
327 /* replace old logical pin node array */
328 OutNode->LogicalPinNodeConnectedFrom = NewLogicalPinNodeConnectedFrom;
329
330 /* increment nodes count */
331 OutNode->NodeConnectedFromCount++;
332
333 /* get existing count */
334 Count = InNode->NodeConnectedToCount;
335
336 /* allocate new nodes array */
337 NewNodes = MixerContext->Alloc(sizeof(PTOPOLOGY_NODE) * (Count + 1));
338
339 if (!NewNodes)
340 {
341 /* out of memory */
342 return MM_STATUS_NO_MEMORY;
343 }
344
345 if (Count)
346 {
347 /* copy existing nodes */
348 MixerContext->Copy(NewNodes, InNode->NodeConnectedTo, sizeof(PTOPOLOGY) * Count);
349
350 /* release old nodes array */
352 }
353
354 /* add new topology node */
355 NewNodes[InNode->NodeConnectedToCount] = OutNode;
356
357 /* replace old nodes array */
358 InNode->NodeConnectedTo = NewNodes;
359
360 /* increment nodes count */
361 InNode->NodeConnectedToCount++;
362
363 /* done */
364 return MM_STATUS_SUCCESS;
365}
366
370 IN OUT PPIN InPin,
371 IN OUT PPIN OutPin)
372{
373 ULONG Count;
374 PULONG NewPinsIndex;
375
376 /* now enlarge PinConnectedTo */
377 Count = InPin->PinConnectedToCount;
378
379 /* allocate pin connection index */
380 NewPinsIndex = MixerContext->Alloc(sizeof(ULONG) * (Count + 1));
381
382 if (!NewPinsIndex)
383 {
384 /* out of memory */
385 return MM_STATUS_NO_MEMORY;
386 }
387
388 if (Count)
389 {
390 /* copy existing nodes */
391 MixerContext->Copy(NewPinsIndex, InPin->PinConnectedTo, sizeof(ULONG) * Count);
392
393 /* release old nodes array */
394 MixerContext->Free(InPin->PinConnectedTo);
395 }
396
397 /* add new topology node */
398 NewPinsIndex[Count] = OutPin->PinId;
399
400 /* replace old nodes array */
401 InPin->PinConnectedTo = NewPinsIndex;
402
403 /* increment pin count */
404 InPin->PinConnectedToCount++;
405
406 /* now enlarge PinConnectedFrom */
407 Count = OutPin->PinConnectedFromCount;
408
409 /* allocate pin connection index */
410 NewPinsIndex = MixerContext->Alloc(sizeof(ULONG) * (Count + 1));
411
412 if (!NewPinsIndex)
413 {
414 /* out of memory */
415 return MM_STATUS_NO_MEMORY;
416 }
417
418 if (Count)
419 {
420 /* copy existing nodes */
421 MixerContext->Copy(NewPinsIndex, OutPin->PinConnectedFrom, sizeof(ULONG) * Count);
422
423 /* release old nodes array */
424 MixerContext->Free(OutPin->PinConnectedFrom);
425 }
426
427 /* add new topology node */
428 NewPinsIndex[Count] = InPin->PinId;
429
430 /* replace old nodes array */
431 OutPin->PinConnectedFrom = NewPinsIndex;
432
433 /* increment pin count */
434 OutPin->PinConnectedFromCount++;
435
436 /* done */
437 return MM_STATUS_SUCCESS;
438}
439
443 IN PKSTOPOLOGY_CONNECTION Connection,
444 IN OUT PTOPOLOGY Topology)
445{
446 PPIN Pin;
448
449 /* check type */
450 if (Connection->FromNode == KSFILTER_NODE &&
451 Connection->ToNode == KSFILTER_NODE)
452 {
453 /* Pin -> Pin direction */
454
455 /* sanity checks */
456 ASSERT(Topology->TopologyPinsCount > Connection->FromNodePin);
457 ASSERT(Topology->TopologyPinsCount > Connection->ToNodePin);
458
459 /* add connection */
461 &Topology->TopologyPins[Connection->FromNodePin],
462 &Topology->TopologyPins[Connection->ToNodePin]);
463
464 }
465 else if (Connection->FromNode == KSFILTER_NODE)
466 {
467 /* Pin -> Node direction */
468
469 /* sanity checks */
470 ASSERT(Topology->TopologyPinsCount > Connection->FromNodePin);
471 ASSERT(Topology->TopologyNodesCount > Connection->ToNode);
472 ASSERT(Connection->ToNode != KSFILTER_NODE);
473
474 /* get pin */
475 Pin = &Topology->TopologyPins[Connection->FromNodePin];
476
477 /* get node */
478 Node = &Topology->TopologyNodes[Connection->ToNode];
479
480 /* initialize pin */
481 Pin->PinId = Connection->FromNodePin;
482
483 /* mark as visited */
484 Pin->Visited = TRUE;
485 Node->Visited = TRUE;
486
487 /* add connection */
489 }
490 else if (Connection->ToNode == KSFILTER_NODE)
491 {
492 /* Node -> Pin direction */
493
494 /* sanity checks */
495 ASSERT(Topology->TopologyPinsCount > Connection->ToNodePin);
496 ASSERT(Topology->TopologyNodesCount > Connection->FromNode);
497 ASSERT(Connection->FromNode != KSFILTER_NODE);
498
499 /* get pin */
500 Pin = &Topology->TopologyPins[Connection->ToNodePin];
501
502 /* get node */
503 Node = &Topology->TopologyNodes[Connection->FromNode];
504
505 /* initialize pin */
506 Pin->PinId = Connection->ToNodePin;
507
508 /* mark as visited */
509 Pin->Visited = TRUE;
510 Node->Visited = TRUE;
511
512 /* add connection */
514 }
515 /* invalid call */
516 ASSERT(0);
518}
519
523 IN PKSMULTIPLE_ITEM NodeConnections,
524 IN PKSMULTIPLE_ITEM NodeTypes,
525 IN OUT PTOPOLOGY Topology)
526{
527 ULONG Index;
528 PKSTOPOLOGY_CONNECTION Connection;
530
531 /* sanity check */
532 ASSERT(Topology->TopologyNodesCount == NodeTypes->Count);
533
534 /* get node connections */
535 Connection = (PKSTOPOLOGY_CONNECTION)(NodeConnections + 1);
536
537 for(Index = 0; Index < NodeConnections->Count; Index++)
538 {
539 if (Connection[Index].FromNode == KSFILTER_NODE ||
540 Connection[Index].ToNode == KSFILTER_NODE)
541 {
542 /* handle connection from Pin -> Node / Node->Pin */
544 &Connection[Index],
545 Topology);
546
547 }
548 else
549 {
550 /* handle connection from Node -> Node */
552 &Connection[Index],
553 Topology);
554 }
555
557 {
558 /* failed to handle connection */
559 return Status;
560 }
561 }
562
563 /* done */
564 return MM_STATUS_SUCCESS;
565}
566
567VOID
570 IN ULONG PinId,
571 IN ULONG MaxPins,
572 OUT PULONG OutPinCount,
573 OUT PULONG OutPins)
574{
575 ULONG Index;
576
577 for(Index = 0; Index < MaxPins; Index++)
578 {
579 if (OutPins[Index] != MAXULONG)
580 {
581 if (OutPins[Index] > PinId)
582 {
583 /* shift entries up */
584 MixerContext->Copy(&OutPins[Index + 1], &OutPins[Index], (MaxPins - (Index + 1)) * sizeof(ULONG));
585
586 /* store pin id */
587 OutPins[Index] = PinId;
588
589 /* increment pin count */
590 (*OutPinCount)++;
591
592 /* done */
593 return;
594 }
595 }
596 else
597 {
598 /* store pin id */
599 OutPins[Index] = PinId;
600
601 /* increment pin count */
602 (*OutPinCount)++;
603
604 /* done */
605 return;
606 }
607 }
608}
609
610VOID
613 IN PTOPOLOGY Topology,
614 IN PTOPOLOGY_NODE TopologyNode,
615 IN ULONG bUpStream,
616 OUT PULONG OutPinCount,
617 OUT PULONG OutPins)
618{
619 ULONG Index, TopologyNodesCount, PinsCount;
621 PULONG Pins;
622 PPIN Pin;
623
624 /* sanity check */
625 ASSERT(TopologyNode->Visited == FALSE);
626
627 if (bUpStream)
628 {
629 /* use pins to which a node is attached to */
630 PinsCount = TopologyNode->PinConnectedFromCount;
631 Pins = TopologyNode->PinConnectedFrom;
632
633 TopologyNodesCount = TopologyNode->NodeConnectedFromCount;
634 TopologyNodes = TopologyNode->NodeConnectedFrom;
635 }
636 else
637 {
638 /* use pins which are attached to a node */
639 PinsCount = TopologyNode->PinConnectedToCount;
640 Pins = TopologyNode->PinConnectedTo;
641
642 TopologyNodesCount = TopologyNode->NodeConnectedToCount;
643 TopologyNodes = TopologyNode->NodeConnectedTo;
644 }
645
646 /* add all diretly connected pins */
647 for(Index = 0; Index < PinsCount; Index++)
648 {
649 /* sanity check */
650 ASSERT(Pins[Index] < Topology->TopologyPinsCount);
651
652 /* get pin */
653 Pin = &Topology->TopologyPins[Pins[Index]];
654
655 /* pin should not have been visited */
656 ASSERT(Pin->Visited == FALSE);
657 ASSERT(Pins[Index] == Pin->PinId);
658
659 /* FIXME support Pin -> Pin connections in iteration */
660 if (bUpStream)
661 {
662 /* indicates a very broken topology Pin -> Pin -> Node <-... */
663 ASSERT(Pin->PinConnectedFromCount == 0);
664 }
665 else
666 {
667 /* indicates a very broken topology -> Node -> Pin -> Pin */
668 ASSERT(Pin->PinConnectedToCount == 0);
669 }
670
671 /* add them to pin array */
672 MMixerAddPinIndexToArray(MixerContext, Pin->PinId, Topology->TopologyPinsCount, OutPinCount, OutPins);
673
674 /* mark pin as visited */
675 Pin->Visited = TRUE;
676 }
677
678 /* mark node as visited */
679 TopologyNode->Visited = TRUE;
680
681 /* now visit all connected nodes */
682 for(Index = 0; Index < TopologyNodesCount; Index++)
683 {
684 /* recursively visit them */
685 MMixerGetUpOrDownStreamPins(MixerContext, Topology, TopologyNodes[Index], bUpStream, OutPinCount, OutPins);
686 }
687
688}
689
690ULONG
692 IN PTOPOLOGY Topology,
693 IN const GUID * NodeType)
694{
695 ULONG Index;
696
697 for(Index = 0; Index < Topology->TopologyNodesCount; Index++)
698 {
699 if (IsEqualGUIDAligned(NodeType, &Topology->TopologyNodes[Index].NodeType))
700 {
701 return Index;
702 }
703 }
704
705 return MAXULONG;
706}
707
708VOID
711 IN PTOPOLOGY Topology,
712 IN ULONG NodeIndex,
713 IN ULONG bUpStream,
714 OUT PULONG OutPinsCount,
715 OUT PULONG OutPins)
716{
717 PTOPOLOGY_NODE TopologyNode;
718
719 /* reset visited status */
721
722 /* sanity check */
723 ASSERT(Topology->TopologyNodesCount > NodeIndex);
724
725 /* get topology node */
726 TopologyNode = &Topology->TopologyNodes[NodeIndex];
727
728 /* now visit all upstream pins & nodes */
729 MMixerGetUpOrDownStreamPins(MixerContext, Topology, TopologyNode, bUpStream, OutPinsCount, OutPins);
730}
731
732VOID
735 IN PTOPOLOGY Topology,
736 IN PTOPOLOGY_NODE TopologyNode,
737 IN ULONG bUpStream,
738 OUT PULONG OutNodeCount,
739 OUT PULONG OutNodes)
740{
741 ULONG Index, TopologyNodesCount;
743
744 if (bUpStream)
745 {
746 /* use nodes to which a node is attached to */
747 TopologyNodesCount = TopologyNode->NodeConnectedFromCount;
748 TopologyNodes = TopologyNode->NodeConnectedFrom;
749 }
750 else
751 {
752 /* use nodes which are attached to a node */
753 TopologyNodesCount = TopologyNode->NodeConnectedToCount;
754 TopologyNodes = TopologyNode->NodeConnectedTo;
755 }
756
757 /* sanity check */
758 ASSERT(TopologyNode->Visited == FALSE);
759
760 /* add all connected nodes */
761 for(Index = 0; Index < TopologyNodesCount; Index++)
762 {
763 /* get node */
765
766 /* node should not have been visited */
767 ASSERT(Node->Visited == FALSE);
768
769 /* mark node as visited */
770 TopologyNode->Visited = TRUE;
771
772 /* add them to node array */
773 MMixerAddPinIndexToArray(MixerContext, Node->NodeIndex, Topology->TopologyNodesCount, OutNodeCount, OutNodes);
774
775 /* recursively visit them */
776 MMixerGetUpOrDownstreamNodes(MixerContext, Topology, TopologyNodes[Index], bUpStream, OutNodeCount, OutNodes);
777 }
778}
779
783 IN PTOPOLOGY Topology,
784 IN ULONG NodeIndex,
785 IN ULONG bUpStream,
786 OUT PULONG OutNodesCount,
787 OUT PULONG OutNodes)
788{
789 PTOPOLOGY_NODE TopologyNode;
790
791 /* reset visited status */
793
794 /* sanity check */
795 ASSERT(Topology->TopologyNodesCount > NodeIndex);
796
797 /* get topology node */
798 TopologyNode = &Topology->TopologyNodes[NodeIndex];
799
800 /* now visit all upstream pins & nodes */
801 MMixerGetUpOrDownstreamNodes(MixerContext, Topology, TopologyNode, bUpStream, OutNodesCount, OutNodes);
802
803 /* done */
804 return MM_STATUS_SUCCESS;
805
806}
807
811 IN PTOPOLOGY Topology,
812 IN ULONG PinIndex,
813 IN ULONG bUpStream,
814 OUT PULONG OutPinsCount,
815 OUT PULONG OutPins)
816{
817 ULONG Index, TopologyNodesCount, TopologyPinsCount;
818 PPIN Pin;
820 PULONG TopologyPins;
821
822 /* get pin */
823 Pin = &Topology->TopologyPins[PinIndex];
824
825 if (bUpStream)
826 {
827 /* use nodes to which this pin is attached to */
828 TopologyNodes = Pin->NodesConnectedFrom;
829 TopologyNodesCount = Pin->NodesConnectedFromCount;
830
831 /* use pins to which this pin is attached to */
832 TopologyPins = Pin->PinConnectedFrom;
833 TopologyPinsCount = Pin->PinConnectedFromCount;
834
835 }
836 else
837 {
838 /* use nodes which are attached to a pin */
839 TopologyNodes = Pin->NodesConnectedTo;
840 TopologyNodesCount = Pin->NodesConnectedToCount;
841
842 /* use pins which are attached to this pin */
843 TopologyPins = Pin->PinConnectedTo;
844 TopologyPinsCount = Pin->PinConnectedToCount;
845 }
846
847 /* reset visited status */
849
850 /* sanity check */
851 ASSERT(Topology->TopologyPinsCount > PinIndex);
852
853 /* add pins which are directly connected to this pin */
854 for(Index = 0; Index < TopologyPinsCount; Index++)
855 {
856 /* add them to pin array */
857 MMixerAddPinIndexToArray(MixerContext, TopologyPins[Index], Topology->TopologyPinsCount, OutPinsCount, OutPins);
858 }
859
860 /* now visit all up / down stream pins & nodes */
861 for(Index = 0; Index < TopologyNodesCount; Index++)
862 {
863 /* explore all connected pins with helper */
864 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, TopologyNodes[Index]->NodeIndex, bUpStream, OutPinsCount, OutPins);
865 }
866
867 /* done */
868 return MM_STATUS_SUCCESS;
869
870}
871
872VOID
875 IN PTOPOLOGY Topology,
876 IN ULONG PinIndex,
877 IN ULONG bUpStream,
878 OUT PULONG OutNodesCount,
879 OUT PULONG OutNodes)
880{
881 ULONG Index, TopologyNodesCount;
882 PPIN Pin;
884
885 /* mark them as empty */
886 *OutNodesCount = 0;
887
888 /* get pin */
889 Pin = &Topology->TopologyPins[PinIndex];
890
891 if (bUpStream)
892 {
893 /* use nodes to which a pin is attached to */
894 TopologyNodes = Pin->NodesConnectedFrom;
895 TopologyNodesCount = Pin->NodesConnectedFromCount;
896 }
897 else
898 {
899 /* use nodes which are attached to a node */
900 TopologyNodes = Pin->NodesConnectedTo;
901 TopologyNodesCount = Pin->NodesConnectedToCount;
902 }
903
904 /* reset visited status */
906
907 /* sanity check */
908 ASSERT(Topology->TopologyPinsCount > PinIndex);
909
910 /* now visit all up / down stream pins & nodes */
911 for(Index = 0; Index < TopologyNodesCount; Index++)
912 {
913 /* add node to array */
914 MMixerAddPinIndexToArray(MixerContext, TopologyNodes[Index]->NodeIndex, Topology->TopologyNodesCount, OutNodesCount, OutNodes);
915
916 /* explore all connected nodes with helper */
917 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext, Topology, TopologyNodes[Index]->NodeIndex, bUpStream, OutNodesCount, OutNodes);
918 }
919}
920
921VOID
924 IN PTOPOLOGY Topology,
925 IN ULONG PinIndex,
926 IN ULONG bUpStream,
927 OUT PULONG OutNodesCount,
928 OUT PULONG OutNodes)
929{
930 PPIN Pin;
932 ULONG TopologyNodesCount;
933 ULONG Index;
934
935 /* sanity check */
936 ASSERT(PinIndex < Topology->TopologyPinsCount);
937
938 /* get pin */
939 Pin = &Topology->TopologyPins[PinIndex];
940
941 if (bUpStream)
942 {
943 /* get up stream nodes */
944 TopologyNodes = Pin->NodesConnectedFrom;
945 TopologyNodesCount = Pin->NodesConnectedFromCount;
946 }
947 else
948 {
949 /* get down stream nodes */
950 TopologyNodes = Pin->NodesConnectedTo;
951 TopologyNodesCount = Pin->NodesConnectedToCount;
952 }
953
954 /* store topology nodes ids */
955 for(Index = 0; Index < TopologyNodesCount; Index++)
956 {
957 OutNodes[Index] = TopologyNodes[Index]->NodeIndex;
958 }
959
960 /* store topology nodes count */
961 *OutNodesCount = TopologyNodesCount;
962}
963
964VOID
967 IN PTOPOLOGY Topology,
968 IN ULONG NodeIndex,
969 IN ULONG bUpStream,
970 OUT PULONG OutNodesCount,
971 OUT PULONG OutNodes)
972{
974 ULONG TopologyNodesCount;
975 ULONG Index;
976
977 /* sanity check */
978 ASSERT(NodeIndex < Topology->TopologyNodesCount);
979
980 if (bUpStream)
981 {
982 /* get up stream nodes */
983 TopologyNodes = Topology->TopologyNodes[NodeIndex].NodeConnectedFrom;
984 TopologyNodesCount = Topology->TopologyNodes[NodeIndex].NodeConnectedFromCount;
985 }
986 else
987 {
988 /* get down stream nodes */
989 TopologyNodes = Topology->TopologyNodes[NodeIndex].NodeConnectedTo;
990 TopologyNodesCount = Topology->TopologyNodes[NodeIndex].NodeConnectedToCount;
991 }
992
993 /* store topology nodes ids */
994 for(Index = 0; Index < TopologyNodesCount; Index++)
995 {
996 OutNodes[Index] = TopologyNodes[Index]->NodeIndex;
997 }
998
999 /* store topology nodes count */
1000 *OutNodesCount = TopologyNodesCount;
1001}
1002
1003VOID
1005 IN PTOPOLOGY Topology,
1007{
1008 /* store pin count */
1009 *PinCount = Topology->TopologyPinsCount;
1010}
1011
1015 IN PTOPOLOGY Topology,
1016 OUT PULONG * OutPins)
1017{
1018 PULONG Pins;
1019 ULONG Index;
1020
1021 /* sanity check */
1022 ASSERT(Topology->TopologyPinsCount != 0);
1023
1024 /* allocate topology pins */
1025 Pins = MixerContext->Alloc(Topology->TopologyPinsCount * sizeof(ULONG));
1026
1027 if (!Pins)
1028 {
1029 /* out of memory */
1030 return MM_STATUS_NO_MEMORY;
1031 }
1032
1033 /* mark index as unused */
1034 for(Index = 0; Index < Topology->TopologyPinsCount; Index++)
1035 Pins[Index] = MAXULONG;
1036
1037 /* store result */
1038 *OutPins = Pins;
1039
1040 /* done */
1041 return MM_STATUS_SUCCESS;
1042}
1043
1047 IN PTOPOLOGY Topology,
1048 OUT PULONG * OutNodes)
1049{
1050 PULONG Nodes;
1051 ULONG Index;
1052
1053 /* sanity check */
1054 ASSERT(Topology->TopologyNodesCount != 0);
1055
1056 /* allocate topology pins */
1057 Nodes = MixerContext->Alloc(Topology->TopologyNodesCount * sizeof(ULONG));
1058
1059 if (!Nodes)
1060 {
1061 /* out of memory */
1062 return MM_STATUS_NO_MEMORY;
1063 }
1064
1065 /* mark index as unused */
1066 for(Index = 0; Index < Topology->TopologyNodesCount; Index++)
1067 Nodes[Index] = MAXULONG;
1068
1069 /* store result */
1070 *OutNodes = Nodes;
1071
1072 /* done */
1073 return MM_STATUS_SUCCESS;
1074}
1075
1076VOID
1078 IN PTOPOLOGY Topology,
1079 IN ULONG NodeIndex,
1080 OUT ULONG * bTerminator)
1081{
1082 /* sanity check */
1083 ASSERT(NodeIndex < Topology->TopologyNodesCount);
1084
1085 /* check if node has multiple parents */
1086 if (Topology->TopologyNodes[NodeIndex].NodeConnectedFromCount > 1)
1087 {
1088 /* node is connected to multiple other nodes */
1089 *bTerminator = TRUE;
1090
1091 /* done */
1092 return;
1093 }
1094
1095 /* check if node is mux / sum node */
1096 if (IsEqualGUIDAligned(&Topology->TopologyNodes[NodeIndex].NodeType, &KSNODETYPE_SUM) ||
1097 IsEqualGUIDAligned(&Topology->TopologyNodes[NodeIndex].NodeType, &KSNODETYPE_MUX))
1098 {
1099 /* classic terminator */
1100 *bTerminator = TRUE;
1101
1102 /* done */
1103 return;
1104
1105 }
1106
1107 /* node is not a terminator */
1108 *bTerminator = FALSE;
1109}
1110
1114 IN PTOPOLOGY Topology,
1115 IN ULONG NodeIndex,
1116 IN ULONG PinId,
1117 IN ULONG bUpStream,
1119{
1121 ULONG Index, PinsCount;
1122 PULONG Pins;
1123
1124 /* allocate pin index array */
1126
1128 {
1129 /* failed to allocate */
1130 return Status;
1131 }
1132
1133 /* now get connected pins */
1134 PinsCount = 0;
1135 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, bUpStream, &PinsCount, Pins);
1136
1137 /* set to false */
1138 *bConnected = FALSE;
1139
1140 for(Index = 0; Index < PinsCount; Index++)
1141 {
1142 if (Pins[Index] == PinId)
1143 {
1144 /* pin is connected */
1145 *bConnected = TRUE;
1146 break;
1147 }
1148 }
1149
1150 /* free pin index array */
1151 MixerContext->Free(Pins);
1152
1153 /* done */
1154 return MM_STATUS_SUCCESS;
1155}
1156
1157VOID
1159 IN PTOPOLOGY Topology,
1160 IN ULONG NodeIndex,
1161 OUT PULONG OutPinCount,
1162 OUT PULONG OutPins)
1163{
1164 ULONG Index;
1166
1167 /* sanity check */
1168 ASSERT(NodeIndex < Topology->TopologyNodesCount);
1169
1170 /* get node */
1171 Node = &Topology->TopologyNodes[NodeIndex];
1172
1173 for(Index = 0; Index < Node->NodeConnectedFromCount; Index++)
1174 {
1175 /* copy logical pin id */
1176 OutPins[Index] = Node->LogicalPinNodeConnectedFrom[Index];
1177 }
1178
1179 /* store pin count */
1180 *OutPinCount = Node->NodeConnectedFromCount;
1181}
1182
1183LPGUID
1185 IN PTOPOLOGY Topology,
1186 IN ULONG NodeIndex)
1187{
1188 /* sanity check */
1189 ASSERT(NodeIndex < Topology->TopologyNodesCount);
1190
1191 return &Topology->TopologyNodes[NodeIndex].NodeType;
1192}
1193
1194VOID
1196 IN PTOPOLOGY Topology,
1197 IN ULONG PinId)
1198{
1199 /* sanity check */
1200 ASSERT(PinId < Topology->TopologyPinsCount);
1201
1202 /* set reserved */
1203 Topology->TopologyPins[PinId].Reserved = TRUE;
1204}
1205
1206VOID
1208 IN PTOPOLOGY Topology,
1209 IN ULONG PinId,
1210 OUT PULONG bReserved)
1211{
1212 /* sanity check */
1213 ASSERT(PinId < Topology->TopologyPinsCount);
1214
1215 /* get reserved status */
1216 *bReserved = Topology->TopologyPins[PinId].Reserved;
1217}
1218
1219VOID
1221 IN PTOPOLOGY Topology,
1222 IN ULONG NodeIndex)
1223{
1224 /* sanity check */
1225 ASSERT(NodeIndex < Topology->TopologyNodesCount);
1226
1227 /* set reserved */
1228 Topology->TopologyNodes[NodeIndex].Reserved = TRUE;
1229}
1230
1231VOID
1233 IN PTOPOLOGY Topology,
1234 IN ULONG NodeIndex,
1235 OUT PULONG bReserved)
1236{
1237 /* sanity check */
1238 ASSERT(NodeIndex < Topology->TopologyNodesCount);
1239
1240 /* get reserved status */
1241 *bReserved = Topology->TopologyNodes[NodeIndex].Reserved;
1242}
1243
1248 IN PKSMULTIPLE_ITEM NodeConnections,
1249 IN PKSMULTIPLE_ITEM NodeTypes,
1250 OUT PTOPOLOGY *OutTopology)
1251{
1253 PTOPOLOGY Topology;
1254
1255 /* allocate topology */
1256 Status = MMixerAllocateTopology(MixerContext, NodeTypes->Count, PinCount, &Topology);
1257
1259 {
1260 /* failed to allocate topology */
1261 return Status;
1262 }
1263
1264 /* initialize topology nodes */
1265 MMixerInitializeTopologyNodes(MixerContext, NodeTypes, Topology);
1266
1267 /* explore topology */
1268 Status = MMixerExploreTopology(MixerContext, NodeConnections, NodeTypes, Topology);
1269
1271 {
1272 /* failed to allocate topology */
1273 return Status;
1274 }
1275
1276 MMixerPrintTopology(Topology);
1277
1278 /* store result */
1279 *OutTopology = Topology;
1280
1281 /* done */
1282 return MM_STATUS_SUCCESS;
1283}
NodeType
Definition: Node.h:6
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
union node Node
Definition: types.h:1255
MIXER_CONTEXT MixerContext
Definition: mmixer.c:41
IN PDCB IN VBO IN ULONG IN BOOLEAN Pin
Definition: fatprocs.h:427
BOOL bConnected
Definition: fdebug.c:27
Status
Definition: gdiplustypes.h:25
#define KSFILTER_NODE
Definition: ks.h:44
#define KSNODETYPE_SUM
Definition: ksmedia.h:363
#define KSNODETYPE_MUX
Definition: ksmedia.h:433
static PCNODE_DESCRIPTOR TopologyNodes[]
MIXER_STATUS
Definition: mmixer.h:4
@ MM_STATUS_INVALID_PARAMETER
Definition: mmixer.h:10
@ MM_STATUS_NO_MEMORY
Definition: mmixer.h:12
@ MM_STATUS_SUCCESS
Definition: mmixer.h:5
#define ASSERT(a)
Definition: mode.c:44
int Count
Definition: noreturn.cpp:7
GUID * LPGUID
Definition: guiddef.h:81
struct __TOPOLOGY_NODE__ * PTOPOLOGY_NODE
struct TOPOLOGY * PTOPOLOGY
struct PIN * PPIN
VOID MMixerPrintTopology()
VOID MMixerGetNextNodesFromPinIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG PinIndex, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes)
Definition: topology.c:922
VOID MMixerGetTopologyPinCount(IN PTOPOLOGY Topology, OUT PULONG PinCount)
Definition: topology.c:1004
VOID MMixerIsTopologyPinReserved(IN PTOPOLOGY Topology, IN ULONG PinId, OUT PULONG bReserved)
Definition: topology.c:1207
VOID MMixerGetUpOrDownstreamNodes(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN PTOPOLOGY_NODE TopologyNode, IN ULONG bUpStream, OUT PULONG OutNodeCount, OUT PULONG OutNodes)
Definition: topology.c:733
MIXER_STATUS MMixerAddPinConnection(IN PMIXER_CONTEXT MixerContext, IN PPIN Pin, IN PTOPOLOGY_NODE Node, IN ULONG bPinToNode)
Definition: topology.c:144
MIXER_STATUS MMixerAllocateTopologyNodeArray(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, OUT PULONG *OutNodes)
Definition: topology.c:1045
ULONG MMixerGetNodeIndexFromGuid(IN PTOPOLOGY Topology, IN const GUID *NodeType)
Definition: topology.c:691
VOID MMixerGetAllUpOrDownstreamNodesFromPinIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG PinIndex, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes)
Definition: topology.c:873
VOID MMixerAddPinIndexToArray(IN PMIXER_CONTEXT MixerContext, IN ULONG PinId, IN ULONG MaxPins, OUT PULONG OutPinCount, OUT PULONG OutPins)
Definition: topology.c:568
VOID MMixerIsTopologyNodeReserved(IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT PULONG bReserved)
Definition: topology.c:1232
VOID MMixerIsNodeTerminator(IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT ULONG *bTerminator)
Definition: topology.c:1077
MIXER_STATUS MMixerExploreTopology(IN PMIXER_CONTEXT MixerContext, IN PKSMULTIPLE_ITEM NodeConnections, IN PKSMULTIPLE_ITEM NodeTypes, IN OUT PTOPOLOGY Topology)
Definition: topology.c:521
VOID MMixerSetTopologyPinReserved(IN PTOPOLOGY Topology, IN ULONG PinId)
Definition: topology.c:1195
MIXER_STATUS MMixerGetAllUpOrDownstreamNodesFromNodeIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes)
Definition: topology.c:781
MIXER_STATUS MMixerHandleNodeToNodeConnection(IN PMIXER_CONTEXT MixerContext, IN PKSTOPOLOGY_CONNECTION Connection, IN OUT PTOPOLOGY Topology)
Definition: topology.c:260
VOID MMixerResetTopologyVisitStatus(IN OUT PTOPOLOGY Topology)
Definition: topology.c:100
VOID MMixerGetAllUpOrDownstreamPinsFromNodeIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG bUpStream, OUT PULONG OutPinsCount, OUT PULONG OutPins)
Definition: topology.c:709
VOID MMixerGetConnectedFromLogicalTopologyPins(IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT PULONG OutPinCount, OUT PULONG OutPins)
Definition: topology.c:1158
LPGUID MMixerGetNodeTypeFromTopology(IN PTOPOLOGY Topology, IN ULONG NodeIndex)
Definition: topology.c:1184
MIXER_STATUS MMixerAddPinToPinConnection(IN PMIXER_CONTEXT MixerContext, IN OUT PPIN InPin, IN OUT PPIN OutPin)
Definition: topology.c:368
MIXER_STATUS MMixerCreateTopology(IN PMIXER_CONTEXT MixerContext, IN ULONG PinCount, IN PKSMULTIPLE_ITEM NodeConnections, IN PKSMULTIPLE_ITEM NodeTypes, OUT PTOPOLOGY *OutTopology)
Definition: topology.c:1245
VOID MMixerGetUpOrDownStreamPins(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN PTOPOLOGY_NODE TopologyNode, IN ULONG bUpStream, OUT PULONG OutPinCount, OUT PULONG OutPins)
Definition: topology.c:611
VOID MMixerInitializeTopologyNodes(IN PMIXER_CONTEXT MixerContext, IN PKSMULTIPLE_ITEM NodeTypes, IN OUT PTOPOLOGY Topology)
Definition: topology.c:119
VOID MMixerGetNextNodesFromNodeIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes)
Definition: topology.c:965
MIXER_STATUS MMixerAllocateTopology(IN PMIXER_CONTEXT MixerContext, IN ULONG NodesCount, IN ULONG PinCount, OUT PTOPOLOGY *OutTopology)
Definition: topology.c:43
MIXER_STATUS MMixerIsNodeConnectedToPin(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG NodeIndex, IN ULONG PinId, IN ULONG bUpStream, OUT PULONG bConnected)
Definition: topology.c:1112
MIXER_STATUS MMixerHandleNodePinConnection(IN PMIXER_CONTEXT MixerContext, IN PKSTOPOLOGY_CONNECTION Connection, IN OUT PTOPOLOGY Topology)
Definition: topology.c:441
MIXER_STATUS MMixerAllocateTopologyPinArray(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, OUT PULONG *OutPins)
Definition: topology.c:1013
MIXER_STATUS MMixerGetAllUpOrDownstreamPinsFromPinIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG PinIndex, IN ULONG bUpStream, OUT PULONG OutPinsCount, OUT PULONG OutPins)
Definition: topology.c:809
VOID MMixerSetTopologyNodeReserved(IN PTOPOLOGY Topology, IN ULONG NodeIndex)
Definition: topology.c:1220
#define DPRINT
Definition: sndvol32.h:71
_In_ const GUID _In_ ULONG PinCount
Definition: strmini.h:505
PMIXER_COPY Copy
Definition: mmixer.h:99
PMIXER_FREE Free
Definition: mmixer.h:96
PMIXER_ALLOC Alloc
Definition: mmixer.h:94
Definition: precomp.h:37
ULONG NodesConnectedToCount
Definition: precomp.h:40
PTOPOLOGY_NODE * NodesConnectedFrom
Definition: precomp.h:44
ULONG PinId
Definition: precomp.h:38
ULONG NodesConnectedFromCount
Definition: precomp.h:43
PTOPOLOGY_NODE * NodesConnectedTo
Definition: precomp.h:41
ULONG Visited
Definition: precomp.h:52
ULONG TopologyPinsCount
Definition: precomp.h:59
PTOPOLOGY_NODE TopologyNodes
Definition: precomp.h:63
PPIN TopologyPins
Definition: precomp.h:60
ULONG TopologyNodesCount
Definition: precomp.h:62
ULONG PinConnectedFromCount
Definition: precomp.h:26
ULONG NodeConnectedFromCount
Definition: precomp.h:22
struct __TOPOLOGY_NODE__ ** NodeConnectedFrom
Definition: precomp.h:23
ULONG NodeConnectedToCount
Definition: precomp.h:19
ULONG NodeIndex
Definition: precomp.h:17
PULONG LogicalPinNodeConnectedFrom
Definition: precomp.h:24
ULONG PinConnectedToCount
Definition: precomp.h:29
struct __TOPOLOGY_NODE__ ** NodeConnectedTo
Definition: precomp.h:20
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
#define IN
Definition: typedefs.h:39
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
Definition: dlist.c:348
struct KSTOPOLOGY_CONNECTION * PKSTOPOLOGY_CONNECTION
_In_ WDFCOLLECTION _In_ ULONG Index
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:235