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