ReactOS  0.4.14-dev-317-g96040ec
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 
14 VOID
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 */
60  return MM_STATUS_NO_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 */
72  return MM_STATUS_NO_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 */
87  return MM_STATUS_NO_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 
102 VOID
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 
121 VOID
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 
559  if (Status != MM_STATUS_SUCCESS)
560  {
561  /* failed to handle connection */
562  return Status;
563  }
564  }
565 
566  /* done */
567  return MM_STATUS_SUCCESS;
568 }
569 
570 VOID
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 
613 VOID
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 
693 ULONG
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 
712 VOID
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 
736 VOID
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 
877 VOID
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 
928 VOID
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 
971 VOID
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 
1010 VOID
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 
1083 VOID
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 
1134  if (Status != MM_STATUS_SUCCESS)
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 
1164 VOID
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 
1190 LPGUID
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 
1201 VOID
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 
1213 VOID
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 
1226 VOID
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 
1238 VOID
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 
1255  IN ULONG PinCount,
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 
1266  if (Status != MM_STATUS_SUCCESS)
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 
1278  if (Status != MM_STATUS_SUCCESS)
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 }
ULONG PinConnectedFromCount
Definition: precomp.h:26
VOID MMixerResetTopologyVisitStatus(IN OUT PTOPOLOGY Topology)
Definition: topology.c:103
VOID MMixerIsNodeTerminator(IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT ULONG *bTerminator)
Definition: topology.c:1084
#define IN
Definition: typedefs.h:38
#define TRUE
Definition: types.h:120
ULONG MMixerGetNodeIndexFromGuid(IN PTOPOLOGY Topology, IN const GUID *NodeType)
Definition: topology.c:694
PPIN TopologyPins
Definition: precomp.h:60
VOID MMixerIsTopologyNodeReserved(IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT PULONG bReserved)
Definition: topology.c:1239
ULONG TopologyNodesCount
Definition: precomp.h:62
MIXER_STATUS MMixerExploreTopology(IN PMIXER_CONTEXT MixerContext, IN PKSMULTIPLE_ITEM NodeConnections, IN PKSMULTIPLE_ITEM NodeTypes, IN OUT PTOPOLOGY Topology)
Definition: topology.c:524
MIXER_STATUS MMixerHandleNodePinConnection(IN PMIXER_CONTEXT MixerContext, IN PKSTOPOLOGY_CONNECTION Connection, IN OUT PTOPOLOGY Topology)
Definition: topology.c:444
ULONG PinId
Definition: precomp.h:38
PTOPOLOGY_NODE TopologyNodes
Definition: precomp.h:63
struct KSTOPOLOGY_CONNECTION * PKSTOPOLOGY_CONNECTION
ULONG NodeConnectedFromCount
Definition: precomp.h:22
MIXER_STATUS MMixerAddPinToPinConnection(IN PMIXER_CONTEXT MixerContext, IN OUT PPIN InPin, IN OUT PPIN OutPin)
Definition: topology.c:371
VOID MMixerPrintTopology(PTOPOLOGY Topology)
Definition: topology.c:15
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
const GUID KSNODETYPE_MUX
Definition: sup.c:23
struct __TOPOLOGY_NODE__ ** NodeConnectedFrom
Definition: precomp.h:23
_In_ const GUID _In_ ULONG PinCount
Definition: strmini.h:504
struct __TOPOLOGY_NODE__ * PTOPOLOGY_NODE
ULONG NodeIndex
Definition: precomp.h:17
#define IsEqualGUIDAligned(guid1, guid2)
Definition: wdm.template.h:233
MIXER_STATUS MMixerAllocateTopologyPinArray(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, OUT PULONG *OutPins)
Definition: topology.c:1020
Definition: precomp.h:36
MIXER_CONTEXT MixerContext
Definition: mmixer.c:46
union node Node
Definition: types.h:1255
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
#define KSFILTER_NODE
Definition: ks.h:44
PULONG LogicalPinNodeConnectedFrom
Definition: precomp.h:24
MIXER_STATUS MMixerAddPinConnection(IN PMIXER_CONTEXT MixerContext, IN PPIN Pin, IN PTOPOLOGY_NODE Node, IN ULONG bPinToNode)
Definition: topology.c:147
MIXER_STATUS MMixerHandleNodeToNodeConnection(IN PMIXER_CONTEXT MixerContext, IN PKSTOPOLOGY_CONNECTION Connection, IN OUT PTOPOLOGY Topology)
Definition: topology.c:263
ULONG TopologyPinsCount
Definition: precomp.h:59
void DPRINT(...)
Definition: polytest.cpp:61
VOID MMixerSetTopologyPinReserved(IN PTOPOLOGY Topology, IN ULONG PinId)
Definition: topology.c:1202
VOID MMixerInitializeTopologyNodes(IN PMIXER_CONTEXT MixerContext, IN PKSMULTIPLE_ITEM NodeTypes, IN OUT PTOPOLOGY Topology)
Definition: topology.c:122
NodeType
Definition: Node.h:5
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
PMIXER_FREE Free
Definition: mmixer.h:96
IN PDCB IN VBO IN ULONG IN BOOLEAN Pin
Definition: fatprocs.h:415
PTOPOLOGY_NODE * NodesConnectedTo
Definition: precomp.h:41
VOID MMixerGetConnectedFromLogicalTopologyPins(IN PTOPOLOGY Topology, IN ULONG NodeIndex, OUT PULONG OutPinCount, OUT PULONG OutPins)
Definition: topology.c:1165
static const UCHAR Index[8]
Definition: usbohci.c:18
const GUID KSNODETYPE_SUM
Definition: sup.c:14
BOOL bConnected
Definition: fdebug.c:27
VOID MMixerSetTopologyNodeReserved(IN PTOPOLOGY Topology, IN ULONG NodeIndex)
Definition: topology.c:1227
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
ULONG NodesConnectedToCount
Definition: precomp.h:40
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
MIXER_STATUS MMixerAllocateTopologyNodeArray(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, OUT PULONG *OutNodes)
Definition: topology.c:1052
struct TOPOLOGY * PTOPOLOGY
ULONG Visited
Definition: precomp.h:52
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
PMIXER_ALLOC Alloc
Definition: mmixer.h:94
VOID MMixerIsTopologyPinReserved(IN PTOPOLOGY Topology, IN ULONG PinId, OUT PULONG bReserved)
Definition: topology.c:1214
Status
Definition: gdiplustypes.h:24
#define MAXULONG
Definition: typedefs.h:250
ULONG NodeConnectedToCount
Definition: precomp.h:19
MIXER_STATUS
Definition: mmixer.h:3
ULONG PinConnectedToCount
Definition: precomp.h:29
unsigned int * PULONG
Definition: retypes.h:1
static PCNODE_DESCRIPTOR TopologyNodes[]
struct __TOPOLOGY_NODE__ ** NodeConnectedTo
Definition: precomp.h:20
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
PTOPOLOGY_NODE * NodesConnectedFrom
Definition: precomp.h:44
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 MMixerAddPinIndexToArray(IN PMIXER_CONTEXT MixerContext, IN ULONG PinId, IN ULONG MaxPins, OUT PULONG OutPinCount, OUT PULONG OutPins)
Definition: topology.c:571
struct PIN * PPIN
MIXER_STATUS MMixerAllocateTopology(IN PMIXER_CONTEXT MixerContext, IN ULONG NodesCount, IN ULONG PinCount, OUT PTOPOLOGY *OutTopology)
Definition: topology.c:46
VOID MMixerGetTopologyPinCount(IN PTOPOLOGY Topology, OUT PULONG PinCount)
Definition: topology.c:1011
#define OUT
Definition: typedefs.h:39
unsigned int ULONG
Definition: retypes.h:1
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 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 MMixerGetAllUpOrDownstreamNodesFromPinIndex(IN PMIXER_CONTEXT MixerContext, IN PTOPOLOGY Topology, IN ULONG PinIndex, IN ULONG bUpStream, OUT PULONG OutNodesCount, OUT PULONG OutNodes)
Definition: topology.c:878
PMIXER_COPY Copy
Definition: mmixer.h:99
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
ULONG NodesConnectedFromCount
Definition: precomp.h:43
Definition: dlist.c:348
LPGUID MMixerGetNodeTypeFromTopology(IN PTOPOLOGY Topology, IN ULONG NodeIndex)
Definition: topology.c:1191
GUID * LPGUID
Definition: guiddef.h:81