Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentopology.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Kernel Streaming 00004 * FILE: lib/drivers/sound/mmixer/topology.c 00005 * PURPOSE: Topology Handling Functions 00006 * PROGRAMMER: Johannes Anderwald 00007 */ 00008 00009 #include "priv.h" 00010 00011 VOID 00012 MMixerPrintTopology( 00013 PTOPOLOGY Topology) 00014 { 00015 ULONG Index, SubIndex; 00016 00017 DPRINT("Num Pins %lu NumNodes %lu\n", Topology->TopologyPinsCount, Topology->TopologyNodesCount); 00018 00019 for(Index = 0; Index < Topology->TopologyPinsCount; Index++) 00020 { 00021 DPRINT("PinId %lu NodesConnectedFromCount %lu NodesConnectedToCount %lu Visited %lu\n", Topology->TopologyPins[Index].PinId, 00022 Topology->TopologyPins[Index].NodesConnectedFromCount, Topology->TopologyPins[Index].NodesConnectedToCount, Topology->TopologyPins[Index].Visited); 00023 00024 for(SubIndex = 0; SubIndex < Topology->TopologyPins[Index].NodesConnectedFromCount; SubIndex++) 00025 DPRINT("NodesConnectedFrom Index %lu NodeId %lu\n", SubIndex, Topology->TopologyPins[Index].NodesConnectedFrom[SubIndex]->NodeIndex); 00026 00027 for(SubIndex = 0; SubIndex < Topology->TopologyPins[Index].NodesConnectedToCount; SubIndex++) 00028 DPRINT("NodesConnectedTo Index %lu NodeId %lu\n", SubIndex, Topology->TopologyPins[Index].NodesConnectedTo[SubIndex]->NodeIndex); 00029 } 00030 00031 for(Index = 0; Index < Topology->TopologyNodesCount; Index++) 00032 { 00033 DPRINT("NodeId %lu NodesConnectedFromCount %lu NodesConnectedToCount %lu Visited %lu PinConnectedFromCount %lu PinConnectedToCount %lu\n", Topology->TopologyNodes[Index].NodeIndex, 00034 Topology->TopologyNodes[Index].NodeConnectedFromCount, Topology->TopologyNodes[Index].NodeConnectedToCount, Topology->TopologyNodes[Index].Visited, 00035 Topology->TopologyNodes[Index].PinConnectedFromCount, Topology->TopologyNodes[Index].PinConnectedToCount); 00036 } 00037 00038 00039 } 00040 00041 00042 MIXER_STATUS 00043 MMixerAllocateTopology( 00044 IN PMIXER_CONTEXT MixerContext, 00045 IN ULONG NodesCount, 00046 IN ULONG PinCount, 00047 OUT PTOPOLOGY * OutTopology) 00048 { 00049 PTOPOLOGY Topology; 00050 00051 /* allocate topology */ 00052 Topology = (PTOPOLOGY)MixerContext->Alloc(sizeof(TOPOLOGY)); 00053 00054 if (!Topology) 00055 { 00056 /* out of memory */ 00057 return MM_STATUS_NO_MEMORY; 00058 } 00059 00060 /* allocate topology pins */ 00061 Topology->TopologyPins = (PPIN) MixerContext->Alloc(sizeof(PIN) * PinCount); 00062 00063 if (!Topology->TopologyPins) 00064 { 00065 /* release memory */ 00066 MixerContext->Free(Topology); 00067 00068 /* out of memory */ 00069 return MM_STATUS_NO_MEMORY; 00070 } 00071 00072 /* allocate topology nodes */ 00073 if (NodesCount) 00074 { 00075 Topology->TopologyNodes = (PTOPOLOGY_NODE) MixerContext->Alloc(sizeof(TOPOLOGY_NODE) * NodesCount); 00076 00077 if (!Topology->TopologyNodes) 00078 { 00079 /* release memory */ 00080 MixerContext->Free(Topology->TopologyPins); 00081 MixerContext->Free(Topology); 00082 00083 /* out of memory */ 00084 return MM_STATUS_NO_MEMORY; 00085 } 00086 } 00087 00088 /* initialize topology */ 00089 Topology->TopologyPinsCount = PinCount; 00090 Topology->TopologyNodesCount = NodesCount; 00091 00092 /* store result */ 00093 *OutTopology = Topology; 00094 00095 /* done */ 00096 return MM_STATUS_SUCCESS; 00097 } 00098 00099 VOID 00100 MMixerResetTopologyVisitStatus( 00101 IN OUT PTOPOLOGY Topology) 00102 { 00103 ULONG Index; 00104 00105 for(Index = 0; Index < Topology->TopologyNodesCount; Index++) 00106 { 00107 /* reset visited status */ 00108 Topology->TopologyNodes[Index].Visited = FALSE; 00109 } 00110 00111 for(Index = 0; Index < Topology->TopologyPinsCount; Index++) 00112 { 00113 /* reset visited status */ 00114 Topology->TopologyPins[Index].Visited = FALSE; 00115 } 00116 } 00117 00118 VOID 00119 MMixerInitializeTopologyNodes( 00120 IN PMIXER_CONTEXT MixerContext, 00121 IN PKSMULTIPLE_ITEM NodeTypes, 00122 IN OUT PTOPOLOGY Topology) 00123 { 00124 ULONG Index; 00125 LPGUID Guids; 00126 00127 /* sanity check */ 00128 ASSERT(Topology->TopologyNodesCount == NodeTypes->Count); 00129 00130 /* get topology node types */ 00131 Guids = (LPGUID)(NodeTypes + 1); 00132 00133 for(Index = 0; Index < Topology->TopologyNodesCount; Index++) 00134 { 00135 /* store node connection index */ 00136 Topology->TopologyNodes[Index].NodeIndex = Index; 00137 00138 /* store topology node type */ 00139 MixerContext->Copy(&Topology->TopologyNodes[Index].NodeType, &Guids[Index], sizeof(GUID)); 00140 } 00141 } 00142 00143 MIXER_STATUS 00144 MMixerAddPinConnection( 00145 IN PMIXER_CONTEXT MixerContext, 00146 IN PPIN Pin, 00147 IN PTOPOLOGY_NODE Node, 00148 IN ULONG bPinToNode) 00149 { 00150 ULONG Count; 00151 PULONG NewPinsIndex, OldPinsIndex; 00152 PTOPOLOGY_NODE * NewNodes, *OldNodes; 00153 00154 if (bPinToNode) 00155 { 00156 /* get existing count */ 00157 Count = Pin->NodesConnectedToCount; 00158 OldNodes = Pin->NodesConnectedTo; 00159 } 00160 else 00161 { 00162 /* get existing count */ 00163 Count = Pin->NodesConnectedFromCount; 00164 OldNodes = Pin->NodesConnectedFrom; 00165 } 00166 00167 /* allocate new nodes array */ 00168 NewNodes = MixerContext->Alloc(sizeof(PTOPOLOGY_NODE) * (Count + 1)); 00169 00170 if (!NewNodes) 00171 { 00172 /* out of memory */ 00173 return MM_STATUS_NO_MEMORY; 00174 } 00175 00176 if (Count) 00177 { 00178 /* copy existing nodes */ 00179 MixerContext->Copy(NewNodes, OldNodes, sizeof(PTOPOLOGY) * Count); 00180 00181 /* release old nodes array */ 00182 MixerContext->Free(OldNodes); 00183 } 00184 00185 /* add new topology node */ 00186 NewNodes[Count] = Node; 00187 00188 if (bPinToNode) 00189 { 00190 /* replace old nodes array */ 00191 Pin->NodesConnectedTo = NewNodes; 00192 00193 /* increment nodes count */ 00194 Pin->NodesConnectedToCount++; 00195 00196 /* now enlarge PinConnectedFromCount*/ 00197 Count = Node->PinConnectedFromCount; 00198 00199 /* connected pin count for node */ 00200 OldPinsIndex = Node->PinConnectedFrom; 00201 } 00202 else 00203 { 00204 /* replace old nodes array */ 00205 Pin->NodesConnectedFrom = NewNodes; 00206 00207 /* increment nodes count */ 00208 Pin->NodesConnectedFromCount++; 00209 00210 /* now enlarge PinConnectedFromCount*/ 00211 Count = Node->PinConnectedToCount; 00212 00213 /* connected pin count for node */ 00214 OldPinsIndex = Node->PinConnectedTo; 00215 } 00216 00217 /* allocate pin connection index */ 00218 NewPinsIndex = MixerContext->Alloc(sizeof(ULONG) * (Count + 1)); 00219 00220 if (!NewPinsIndex) 00221 { 00222 /* out of memory */ 00223 return MM_STATUS_NO_MEMORY; 00224 } 00225 00226 if (Count) 00227 { 00228 /* copy existing nodes */ 00229 MixerContext->Copy(NewPinsIndex, OldPinsIndex, sizeof(ULONG) * Count); 00230 00231 /* release old nodes array */ 00232 MixerContext->Free(OldPinsIndex); 00233 } 00234 00235 /* add new topology node */ 00236 NewPinsIndex[Count] = Pin->PinId; 00237 00238 if (bPinToNode) 00239 { 00240 /* replace old nodes array */ 00241 Node->PinConnectedFrom = NewPinsIndex; 00242 00243 /* increment pin count */ 00244 Node->PinConnectedFromCount++; 00245 } 00246 else 00247 { 00248 /* replace old nodes array */ 00249 Node->PinConnectedTo = NewPinsIndex; 00250 00251 /* increment pin count */ 00252 Node->PinConnectedToCount++; 00253 } 00254 00255 /* done */ 00256 return MM_STATUS_SUCCESS; 00257 } 00258 00259 MIXER_STATUS 00260 MMixerHandleNodeToNodeConnection( 00261 IN PMIXER_CONTEXT MixerContext, 00262 IN PKSTOPOLOGY_CONNECTION Connection, 00263 IN OUT PTOPOLOGY Topology) 00264 { 00265 PTOPOLOGY_NODE InNode, OutNode; 00266 PTOPOLOGY_NODE * NewNodes; 00267 PULONG NewLogicalPinNodeConnectedFrom; 00268 ULONG Count; 00269 ULONG LogicalPinId; 00270 00271 /* sanity checks */ 00272 ASSERT(Topology->TopologyNodesCount > Connection->ToNode); 00273 ASSERT(Topology->TopologyNodesCount > Connection->FromNode); 00274 00275 /* get node */ 00276 InNode = &Topology->TopologyNodes[Connection->FromNode]; 00277 OutNode = &Topology->TopologyNodes[Connection->ToNode]; 00278 00279 /* get logical pin node id */ 00280 LogicalPinId = Connection->ToNodePin; 00281 00282 /* get existing count */ 00283 Count = OutNode->NodeConnectedFromCount; 00284 00285 /* allocate new nodes array */ 00286 NewNodes = MixerContext->Alloc(sizeof(PTOPOLOGY_NODE) * (Count + 1)); 00287 00288 if (!NewNodes) 00289 { 00290 /* out of memory */ 00291 return MM_STATUS_NO_MEMORY; 00292 } 00293 00294 /* allocate logical pin nodes array */ 00295 NewLogicalPinNodeConnectedFrom = MixerContext->Alloc((Count + 1) * sizeof(ULONG)); 00296 if (!NewLogicalPinNodeConnectedFrom) 00297 { 00298 /* out of memory */ 00299 MixerContext->Free(NewNodes); 00300 return MM_STATUS_NO_MEMORY; 00301 } 00302 00303 if (Count) 00304 { 00305 /* copy existing nodes */ 00306 MixerContext->Copy(NewNodes, OutNode->NodeConnectedFrom, sizeof(PTOPOLOGY) * Count); 00307 00308 /* copy existing logical pin node array */ 00309 MixerContext->Copy(NewLogicalPinNodeConnectedFrom, OutNode->LogicalPinNodeConnectedFrom, sizeof(ULONG) * Count); 00310 00311 /* release old nodes array */ 00312 MixerContext->Free(OutNode->NodeConnectedFrom); 00313 00314 /* release old logical pin node array */ 00315 MixerContext->Free(OutNode->LogicalPinNodeConnectedFrom); 00316 } 00317 00318 /* add new topology node */ 00319 NewNodes[OutNode->NodeConnectedFromCount] = InNode; 00320 00321 /* add logical node id */ 00322 NewLogicalPinNodeConnectedFrom[OutNode->NodeConnectedFromCount] = LogicalPinId; 00323 00324 /* replace old nodes array */ 00325 OutNode->NodeConnectedFrom = NewNodes; 00326 00327 /* replace old logical pin node array */ 00328 OutNode->LogicalPinNodeConnectedFrom = NewLogicalPinNodeConnectedFrom; 00329 00330 /* increment nodes count */ 00331 OutNode->NodeConnectedFromCount++; 00332 00333 /* get existing count */ 00334 Count = InNode->NodeConnectedToCount; 00335 00336 /* allocate new nodes array */ 00337 NewNodes = MixerContext->Alloc(sizeof(PTOPOLOGY_NODE) * (Count + 1)); 00338 00339 if (!NewNodes) 00340 { 00341 /* out of memory */ 00342 return MM_STATUS_NO_MEMORY; 00343 } 00344 00345 if (Count) 00346 { 00347 /* copy existing nodes */ 00348 MixerContext->Copy(NewNodes, InNode->NodeConnectedTo, sizeof(PTOPOLOGY) * Count); 00349 00350 /* release old nodes array */ 00351 MixerContext->Free(InNode->NodeConnectedTo); 00352 } 00353 00354 /* add new topology node */ 00355 NewNodes[InNode->NodeConnectedToCount] = OutNode; 00356 00357 /* replace old nodes array */ 00358 InNode->NodeConnectedTo = NewNodes; 00359 00360 /* increment nodes count */ 00361 InNode->NodeConnectedToCount++; 00362 00363 /* done */ 00364 return MM_STATUS_SUCCESS; 00365 } 00366 00367 MIXER_STATUS 00368 MMixerAddPinToPinConnection( 00369 IN PMIXER_CONTEXT MixerContext, 00370 IN OUT PPIN InPin, 00371 IN OUT PPIN OutPin) 00372 { 00373 ULONG Count; 00374 PULONG NewPinsIndex; 00375 00376 /* now enlarge PinConnectedTo */ 00377 Count = InPin->PinConnectedToCount; 00378 00379 /* allocate pin connection index */ 00380 NewPinsIndex = MixerContext->Alloc(sizeof(ULONG) * (Count + 1)); 00381 00382 if (!NewPinsIndex) 00383 { 00384 /* out of memory */ 00385 return MM_STATUS_NO_MEMORY; 00386 } 00387 00388 if (Count) 00389 { 00390 /* copy existing nodes */ 00391 MixerContext->Copy(NewPinsIndex, InPin->PinConnectedTo, sizeof(ULONG) * Count); 00392 00393 /* release old nodes array */ 00394 MixerContext->Free(InPin->PinConnectedTo); 00395 } 00396 00397 /* add new topology node */ 00398 NewPinsIndex[Count] = OutPin->PinId; 00399 00400 /* replace old nodes array */ 00401 InPin->PinConnectedTo = NewPinsIndex; 00402 00403 /* increment pin count */ 00404 InPin->PinConnectedToCount++; 00405 00406 /* now enlarge PinConnectedFrom */ 00407 Count = OutPin->PinConnectedFromCount; 00408 00409 /* allocate pin connection index */ 00410 NewPinsIndex = MixerContext->Alloc(sizeof(ULONG) * (Count + 1)); 00411 00412 if (!NewPinsIndex) 00413 { 00414 /* out of memory */ 00415 return MM_STATUS_NO_MEMORY; 00416 } 00417 00418 if (Count) 00419 { 00420 /* copy existing nodes */ 00421 MixerContext->Copy(NewPinsIndex, OutPin->PinConnectedFrom, sizeof(ULONG) * Count); 00422 00423 /* release old nodes array */ 00424 MixerContext->Free(OutPin->PinConnectedFrom); 00425 } 00426 00427 /* add new topology node */ 00428 NewPinsIndex[Count] = InPin->PinId; 00429 00430 /* replace old nodes array */ 00431 OutPin->PinConnectedFrom = NewPinsIndex; 00432 00433 /* increment pin count */ 00434 OutPin->PinConnectedFromCount++; 00435 00436 /* done */ 00437 return MM_STATUS_SUCCESS; 00438 } 00439 00440 MIXER_STATUS 00441 MMixerHandleNodePinConnection( 00442 IN PMIXER_CONTEXT MixerContext, 00443 IN PKSTOPOLOGY_CONNECTION Connection, 00444 IN OUT PTOPOLOGY Topology) 00445 { 00446 PPIN Pin; 00447 PTOPOLOGY_NODE Node; 00448 00449 /* check type */ 00450 if (Connection->FromNode == KSFILTER_NODE && 00451 Connection->ToNode == KSFILTER_NODE) 00452 { 00453 /* Pin -> Pin direction */ 00454 00455 /* sanity checks */ 00456 ASSERT(Topology->TopologyPinsCount > Connection->FromNodePin); 00457 ASSERT(Topology->TopologyPinsCount > Connection->ToNodePin); 00458 00459 /* add connection */ 00460 return MMixerAddPinToPinConnection(MixerContext, 00461 &Topology->TopologyPins[Connection->FromNodePin], 00462 &Topology->TopologyPins[Connection->ToNodePin]); 00463 00464 } 00465 else if (Connection->FromNode == KSFILTER_NODE) 00466 { 00467 /* Pin -> Node direction */ 00468 00469 /* sanity checks */ 00470 ASSERT(Topology->TopologyPinsCount > Connection->FromNodePin); 00471 ASSERT(Topology->TopologyNodesCount > Connection->ToNode); 00472 ASSERT(Connection->ToNode != KSFILTER_NODE); 00473 00474 /* get pin */ 00475 Pin = &Topology->TopologyPins[Connection->FromNodePin]; 00476 00477 /* get node */ 00478 Node = &Topology->TopologyNodes[Connection->ToNode]; 00479 00480 /* initialize pin */ 00481 Pin->PinId = Connection->FromNodePin; 00482 00483 /* mark as visited */ 00484 Pin->Visited = TRUE; 00485 Node->Visited = TRUE; 00486 00487 /* add connection */ 00488 return MMixerAddPinConnection(MixerContext, Pin, Node, TRUE); 00489 } 00490 else if (Connection->ToNode == KSFILTER_NODE) 00491 { 00492 /* Node -> Pin direction */ 00493 00494 /* sanity checks */ 00495 ASSERT(Topology->TopologyPinsCount > Connection->ToNodePin); 00496 ASSERT(Topology->TopologyNodesCount > Connection->FromNode); 00497 ASSERT(Connection->FromNode != KSFILTER_NODE); 00498 00499 /* get pin */ 00500 Pin = &Topology->TopologyPins[Connection->ToNodePin]; 00501 00502 /* get node */ 00503 Node = &Topology->TopologyNodes[Connection->FromNode]; 00504 00505 /* initialize pin */ 00506 Pin->PinId = Connection->ToNodePin; 00507 00508 /* mark as visited */ 00509 Pin->Visited = TRUE; 00510 Node->Visited = TRUE; 00511 00512 /* add connection */ 00513 return MMixerAddPinConnection(MixerContext, Pin, Node, FALSE); 00514 } 00515 /* invalid call */ 00516 ASSERT(0); 00517 return MM_STATUS_INVALID_PARAMETER; 00518 } 00519 00520 MIXER_STATUS 00521 MMixerExploreTopology( 00522 IN PMIXER_CONTEXT MixerContext, 00523 IN PKSMULTIPLE_ITEM NodeConnections, 00524 IN PKSMULTIPLE_ITEM NodeTypes, 00525 IN OUT PTOPOLOGY Topology) 00526 { 00527 ULONG Index; 00528 PKSTOPOLOGY_CONNECTION Connection; 00529 MIXER_STATUS Status; 00530 00531 /* sanity check */ 00532 ASSERT(Topology->TopologyNodesCount == NodeTypes->Count); 00533 00534 /* get node connections */ 00535 Connection = (PKSTOPOLOGY_CONNECTION)(NodeConnections + 1); 00536 00537 for(Index = 0; Index < NodeConnections->Count; Index++) 00538 { 00539 if (Connection[Index].FromNode == KSFILTER_NODE || 00540 Connection[Index].ToNode == KSFILTER_NODE) 00541 { 00542 /* handle connection from Pin -> Node / Node->Pin */ 00543 Status = MMixerHandleNodePinConnection(MixerContext, 00544 &Connection[Index], 00545 Topology); 00546 00547 } 00548 else 00549 { 00550 /* handle connection from Node -> Node */ 00551 Status = MMixerHandleNodeToNodeConnection(MixerContext, 00552 &Connection[Index], 00553 Topology); 00554 } 00555 00556 if (Status != MM_STATUS_SUCCESS) 00557 { 00558 /* failed to handle connection */ 00559 return Status; 00560 } 00561 } 00562 00563 /* done */ 00564 return MM_STATUS_SUCCESS; 00565 } 00566 00567 VOID 00568 MMixerAddPinIndexToArray( 00569 IN PMIXER_CONTEXT MixerContext, 00570 IN ULONG PinId, 00571 IN ULONG MaxPins, 00572 OUT PULONG OutPinCount, 00573 OUT PULONG OutPins) 00574 { 00575 ULONG Index; 00576 00577 for(Index = 0; Index < MaxPins; Index++) 00578 { 00579 if (OutPins[Index] != MAXULONG) 00580 { 00581 if (OutPins[Index] > PinId) 00582 { 00583 /* shift entries up */ 00584 MixerContext->Copy(&OutPins[Index + 1], &OutPins[Index], (MaxPins - (Index + 1)) * sizeof(ULONG)); 00585 00586 /* store pin id */ 00587 OutPins[Index] = PinId; 00588 00589 /* increment pin count */ 00590 (*OutPinCount)++; 00591 00592 /* done */ 00593 return; 00594 } 00595 } 00596 else 00597 { 00598 /* store pin id */ 00599 OutPins[Index] = PinId; 00600 00601 /* increment pin count */ 00602 (*OutPinCount)++; 00603 00604 /* done */ 00605 return; 00606 } 00607 } 00608 } 00609 00610 VOID 00611 MMixerGetUpOrDownStreamPins( 00612 IN PMIXER_CONTEXT MixerContext, 00613 IN PTOPOLOGY Topology, 00614 IN PTOPOLOGY_NODE TopologyNode, 00615 IN ULONG bUpStream, 00616 OUT PULONG OutPinCount, 00617 OUT PULONG OutPins) 00618 { 00619 ULONG Index, TopologyNodesCount, PinsCount; 00620 PTOPOLOGY_NODE *TopologyNodes; 00621 PULONG Pins; 00622 PPIN Pin; 00623 00624 /* sanity check */ 00625 ASSERT(TopologyNode->Visited == FALSE); 00626 00627 if (bUpStream) 00628 { 00629 /* use pins to which a node is attached to */ 00630 PinsCount = TopologyNode->PinConnectedFromCount; 00631 Pins = TopologyNode->PinConnectedFrom; 00632 00633 TopologyNodesCount = TopologyNode->NodeConnectedFromCount; 00634 TopologyNodes = TopologyNode->NodeConnectedFrom; 00635 } 00636 else 00637 { 00638 /* use pins which are attached to a node */ 00639 PinsCount = TopologyNode->PinConnectedToCount; 00640 Pins = TopologyNode->PinConnectedTo; 00641 00642 TopologyNodesCount = TopologyNode->NodeConnectedToCount; 00643 TopologyNodes = TopologyNode->NodeConnectedTo; 00644 } 00645 00646 /* add all diretly connected pins */ 00647 for(Index = 0; Index < PinsCount; Index++) 00648 { 00649 /* sanity check */ 00650 ASSERT(Pins[Index] < Topology->TopologyPinsCount); 00651 00652 /* get pin */ 00653 Pin = &Topology->TopologyPins[Pins[Index]]; 00654 00655 /* pin should not have been visited */ 00656 ASSERT(Pin->Visited == FALSE); 00657 ASSERT(Pins[Index] == Pin->PinId); 00658 00659 /* FIXME support Pin -> Pin connections in iteration */ 00660 if (bUpStream) 00661 { 00662 /* indicates a very broken topology Pin -> Pin -> Node <-... */ 00663 ASSERT(Pin->PinConnectedFromCount == 0); 00664 } 00665 else 00666 { 00667 /* indicates a very broken topology -> Node -> Pin -> Pin */ 00668 ASSERT(Pin->PinConnectedToCount == 0); 00669 } 00670 00671 /* add them to pin array */ 00672 MMixerAddPinIndexToArray(MixerContext, Pin->PinId, Topology->TopologyPinsCount, OutPinCount, OutPins); 00673 00674 /* mark pin as visited */ 00675 Pin->Visited = TRUE; 00676 } 00677 00678 /* mark node as visited */ 00679 TopologyNode->Visited = TRUE; 00680 00681 /* now visit all connected nodes */ 00682 for(Index = 0; Index < TopologyNodesCount; Index++) 00683 { 00684 /* recursively visit them */ 00685 MMixerGetUpOrDownStreamPins(MixerContext, Topology, TopologyNodes[Index], bUpStream, OutPinCount, OutPins); 00686 } 00687 00688 } 00689 00690 ULONG 00691 MMixerGetNodeIndexFromGuid( 00692 IN PTOPOLOGY Topology, 00693 IN const GUID * NodeType) 00694 { 00695 ULONG Index; 00696 00697 for(Index = 0; Index < Topology->TopologyNodesCount; Index++) 00698 { 00699 if (IsEqualGUIDAligned(NodeType, &Topology->TopologyNodes[Index].NodeType)) 00700 { 00701 return Index; 00702 } 00703 } 00704 00705 return MAXULONG; 00706 } 00707 00708 00709 VOID 00710 MMixerGetAllUpOrDownstreamPinsFromNodeIndex( 00711 IN PMIXER_CONTEXT MixerContext, 00712 IN PTOPOLOGY Topology, 00713 IN ULONG NodeIndex, 00714 IN ULONG bUpStream, 00715 OUT PULONG OutPinsCount, 00716 OUT PULONG OutPins) 00717 { 00718 PTOPOLOGY_NODE TopologyNode; 00719 00720 /* reset visited status */ 00721 MMixerResetTopologyVisitStatus(Topology); 00722 00723 /* sanity check */ 00724 ASSERT(Topology->TopologyNodesCount > NodeIndex); 00725 00726 /* get topology node */ 00727 TopologyNode = &Topology->TopologyNodes[NodeIndex]; 00728 00729 /* now visit all upstream pins & nodes */ 00730 MMixerGetUpOrDownStreamPins(MixerContext, Topology, TopologyNode, bUpStream, OutPinsCount, OutPins); 00731 } 00732 00733 VOID 00734 MMixerGetUpOrDownstreamNodes( 00735 IN PMIXER_CONTEXT MixerContext, 00736 IN PTOPOLOGY Topology, 00737 IN PTOPOLOGY_NODE TopologyNode, 00738 IN ULONG bUpStream, 00739 OUT PULONG OutNodeCount, 00740 OUT PULONG OutNodes) 00741 { 00742 ULONG Index, TopologyNodesCount; 00743 PTOPOLOGY_NODE Node, *TopologyNodes; 00744 00745 if (bUpStream) 00746 { 00747 /* use nodes to which a node is attached to */ 00748 TopologyNodesCount = TopologyNode->NodeConnectedFromCount; 00749 TopologyNodes = TopologyNode->NodeConnectedFrom; 00750 } 00751 else 00752 { 00753 /* use nodes which are attached to a node */ 00754 TopologyNodesCount = TopologyNode->NodeConnectedToCount; 00755 TopologyNodes = TopologyNode->NodeConnectedTo; 00756 } 00757 00758 /* sanity check */ 00759 ASSERT(TopologyNode->Visited == FALSE); 00760 00761 /* add all connected nodes */ 00762 for(Index = 0; Index < TopologyNodesCount; Index++) 00763 { 00764 /* get node */ 00765 Node = TopologyNodes[Index]; 00766 00767 /* node should not have been visited */ 00768 ASSERT(Node->Visited == FALSE); 00769 00770 /* mark node as visited */ 00771 TopologyNode->Visited = TRUE; 00772 00773 /* add them to node array */ 00774 MMixerAddPinIndexToArray(MixerContext, Node->NodeIndex, Topology->TopologyNodesCount, OutNodeCount, OutNodes); 00775 00776 /* recursively visit them */ 00777 MMixerGetUpOrDownstreamNodes(MixerContext, Topology, TopologyNodes[Index], bUpStream, OutNodeCount, OutNodes); 00778 } 00779 } 00780 00781 MIXER_STATUS 00782 MMixerGetAllUpOrDownstreamNodesFromNodeIndex( 00783 IN PMIXER_CONTEXT MixerContext, 00784 IN PTOPOLOGY Topology, 00785 IN ULONG NodeIndex, 00786 IN ULONG bUpStream, 00787 OUT PULONG OutNodesCount, 00788 OUT PULONG OutNodes) 00789 { 00790 PTOPOLOGY_NODE TopologyNode; 00791 00792 /* reset visited status */ 00793 MMixerResetTopologyVisitStatus(Topology); 00794 00795 /* sanity check */ 00796 ASSERT(Topology->TopologyNodesCount > NodeIndex); 00797 00798 /* get topology node */ 00799 TopologyNode = &Topology->TopologyNodes[NodeIndex]; 00800 00801 /* now visit all upstream pins & nodes */ 00802 MMixerGetUpOrDownstreamNodes(MixerContext, Topology, TopologyNode, bUpStream, OutNodesCount, OutNodes); 00803 00804 /* done */ 00805 return MM_STATUS_SUCCESS; 00806 00807 } 00808 00809 MIXER_STATUS 00810 MMixerGetAllUpOrDownstreamPinsFromPinIndex( 00811 IN PMIXER_CONTEXT MixerContext, 00812 IN PTOPOLOGY Topology, 00813 IN ULONG PinIndex, 00814 IN ULONG bUpStream, 00815 OUT PULONG OutPinsCount, 00816 OUT PULONG OutPins) 00817 { 00818 ULONG Index, TopologyNodesCount, TopologyPinsCount; 00819 PPIN Pin; 00820 PTOPOLOGY_NODE *TopologyNodes; 00821 PULONG TopologyPins; 00822 00823 /* get pin */ 00824 Pin = &Topology->TopologyPins[PinIndex]; 00825 00826 if (bUpStream) 00827 { 00828 /* use nodes to which this pin is attached to */ 00829 TopologyNodes = Pin->NodesConnectedFrom; 00830 TopologyNodesCount = Pin->NodesConnectedFromCount; 00831 00832 /* use pins to which this pin is attached to */ 00833 TopologyPins = Pin->PinConnectedFrom; 00834 TopologyPinsCount = Pin->PinConnectedFromCount; 00835 00836 } 00837 else 00838 { 00839 /* use nodes which are attached to a pin */ 00840 TopologyNodes = Pin->NodesConnectedTo; 00841 TopologyNodesCount = Pin->NodesConnectedToCount; 00842 00843 /* use pins which are attached to this pin */ 00844 TopologyPins = Pin->PinConnectedTo; 00845 TopologyPinsCount = Pin->PinConnectedToCount; 00846 } 00847 00848 00849 /* reset visited status */ 00850 MMixerResetTopologyVisitStatus(Topology); 00851 00852 /* sanity check */ 00853 ASSERT(Topology->TopologyPinsCount > PinIndex); 00854 00855 /* add pins which are directly connected to this pin */ 00856 for(Index = 0; Index < TopologyPinsCount; Index++) 00857 { 00858 /* add them to pin array */ 00859 MMixerAddPinIndexToArray(MixerContext, TopologyPins[Index], Topology->TopologyPinsCount, OutPinsCount, OutPins); 00860 } 00861 00862 /* now visit all up / down stream pins & nodes */ 00863 for(Index = 0; Index < TopologyNodesCount; Index++) 00864 { 00865 /* explore all connected pins with helper */ 00866 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, TopologyNodes[Index]->NodeIndex, bUpStream, OutPinsCount, OutPins); 00867 } 00868 00869 /* done */ 00870 return MM_STATUS_SUCCESS; 00871 00872 } 00873 00874 VOID 00875 MMixerGetAllUpOrDownstreamNodesFromPinIndex( 00876 IN PMIXER_CONTEXT MixerContext, 00877 IN PTOPOLOGY Topology, 00878 IN ULONG PinIndex, 00879 IN ULONG bUpStream, 00880 OUT PULONG OutNodesCount, 00881 OUT PULONG OutNodes) 00882 { 00883 ULONG Index, TopologyNodesCount; 00884 PPIN Pin; 00885 PTOPOLOGY_NODE *TopologyNodes; 00886 00887 /* mark them as empty */ 00888 *OutNodesCount = 0; 00889 00890 /* get pin */ 00891 Pin = &Topology->TopologyPins[PinIndex]; 00892 00893 if (bUpStream) 00894 { 00895 /* use nodes to which a pin is attached to */ 00896 TopologyNodes = Pin->NodesConnectedFrom; 00897 TopologyNodesCount = Pin->NodesConnectedFromCount; 00898 } 00899 else 00900 { 00901 /* use nodes which are attached to a node */ 00902 TopologyNodes = Pin->NodesConnectedTo; 00903 TopologyNodesCount = Pin->NodesConnectedToCount; 00904 } 00905 00906 00907 /* reset visited status */ 00908 MMixerResetTopologyVisitStatus(Topology); 00909 00910 /* sanity check */ 00911 ASSERT(Topology->TopologyPinsCount > PinIndex); 00912 00913 /* now visit all up / down stream pins & nodes */ 00914 for(Index = 0; Index < TopologyNodesCount; Index++) 00915 { 00916 /* add node to array */ 00917 MMixerAddPinIndexToArray(MixerContext, TopologyNodes[Index]->NodeIndex, Topology->TopologyNodesCount, OutNodesCount, OutNodes); 00918 00919 /* explore all connected nodes with helper */ 00920 MMixerGetAllUpOrDownstreamNodesFromNodeIndex(MixerContext, Topology, TopologyNodes[Index]->NodeIndex, bUpStream, OutNodesCount, OutNodes); 00921 } 00922 } 00923 00924 00925 VOID 00926 MMixerGetNextNodesFromPinIndex( 00927 IN PMIXER_CONTEXT MixerContext, 00928 IN PTOPOLOGY Topology, 00929 IN ULONG PinIndex, 00930 IN ULONG bUpStream, 00931 OUT PULONG OutNodesCount, 00932 OUT PULONG OutNodes) 00933 { 00934 PPIN Pin; 00935 TOPOLOGY_NODE **TopologyNodes; 00936 ULONG TopologyNodesCount; 00937 ULONG Index; 00938 00939 /* sanity check */ 00940 ASSERT(PinIndex < Topology->TopologyPinsCount); 00941 00942 /* get pin */ 00943 Pin = &Topology->TopologyPins[PinIndex]; 00944 00945 if (bUpStream) 00946 { 00947 /* get up stream nodes */ 00948 TopologyNodes = Pin->NodesConnectedFrom; 00949 TopologyNodesCount = Pin->NodesConnectedFromCount; 00950 } 00951 else 00952 { 00953 /* get down stream nodes */ 00954 TopologyNodes = Pin->NodesConnectedTo; 00955 TopologyNodesCount = Pin->NodesConnectedToCount; 00956 } 00957 00958 /* store topology nodes ids */ 00959 for(Index = 0; Index < TopologyNodesCount; Index++) 00960 { 00961 OutNodes[Index] = TopologyNodes[Index]->NodeIndex; 00962 } 00963 00964 /* store topology nodes count */ 00965 *OutNodesCount = TopologyNodesCount; 00966 } 00967 00968 VOID 00969 MMixerGetNextNodesFromNodeIndex( 00970 IN PMIXER_CONTEXT MixerContext, 00971 IN PTOPOLOGY Topology, 00972 IN ULONG NodeIndex, 00973 IN ULONG bUpStream, 00974 OUT PULONG OutNodesCount, 00975 OUT PULONG OutNodes) 00976 { 00977 TOPOLOGY_NODE **TopologyNodes; 00978 ULONG TopologyNodesCount; 00979 ULONG Index; 00980 00981 /* sanity check */ 00982 ASSERT(NodeIndex < Topology->TopologyNodesCount); 00983 00984 if (bUpStream) 00985 { 00986 /* get up stream nodes */ 00987 TopologyNodes = Topology->TopologyNodes[NodeIndex].NodeConnectedFrom; 00988 TopologyNodesCount = Topology->TopologyNodes[NodeIndex].NodeConnectedFromCount; 00989 } 00990 else 00991 { 00992 /* get down stream nodes */ 00993 TopologyNodes = Topology->TopologyNodes[NodeIndex].NodeConnectedTo; 00994 TopologyNodesCount = Topology->TopologyNodes[NodeIndex].NodeConnectedToCount; 00995 } 00996 00997 /* store topology nodes ids */ 00998 for(Index = 0; Index < TopologyNodesCount; Index++) 00999 { 01000 OutNodes[Index] = TopologyNodes[Index]->NodeIndex; 01001 } 01002 01003 /* store topology nodes count */ 01004 *OutNodesCount = TopologyNodesCount; 01005 } 01006 01007 VOID 01008 MMixerGetTopologyPinCount( 01009 IN PTOPOLOGY Topology, 01010 OUT PULONG PinCount) 01011 { 01012 /* store pin count */ 01013 *PinCount = Topology->TopologyPinsCount; 01014 } 01015 01016 MIXER_STATUS 01017 MMixerAllocateTopologyPinArray( 01018 IN PMIXER_CONTEXT MixerContext, 01019 IN PTOPOLOGY Topology, 01020 OUT PULONG * OutPins) 01021 { 01022 PULONG Pins; 01023 ULONG Index; 01024 01025 /* sanity check */ 01026 ASSERT(Topology->TopologyPinsCount != 0); 01027 01028 /* allocate topology pins */ 01029 Pins = MixerContext->Alloc(Topology->TopologyPinsCount * sizeof(ULONG)); 01030 01031 if (!Pins) 01032 { 01033 /* out of memory */ 01034 return MM_STATUS_NO_MEMORY; 01035 } 01036 01037 /* mark index as unused */ 01038 for(Index = 0; Index < Topology->TopologyPinsCount; Index++) 01039 Pins[Index] = MAXULONG; 01040 01041 /* store result */ 01042 *OutPins = Pins; 01043 01044 /* done */ 01045 return MM_STATUS_SUCCESS; 01046 } 01047 01048 MIXER_STATUS 01049 MMixerAllocateTopologyNodeArray( 01050 IN PMIXER_CONTEXT MixerContext, 01051 IN PTOPOLOGY Topology, 01052 OUT PULONG * OutNodes) 01053 { 01054 PULONG Nodes; 01055 ULONG Index; 01056 01057 /* sanity check */ 01058 ASSERT(Topology->TopologyNodesCount != 0); 01059 01060 /* allocate topology pins */ 01061 Nodes = MixerContext->Alloc(Topology->TopologyNodesCount * sizeof(ULONG)); 01062 01063 if (!Nodes) 01064 { 01065 /* out of memory */ 01066 return MM_STATUS_NO_MEMORY; 01067 } 01068 01069 /* mark index as unused */ 01070 for(Index = 0; Index < Topology->TopologyNodesCount; Index++) 01071 Nodes[Index] = MAXULONG; 01072 01073 /* store result */ 01074 *OutNodes = Nodes; 01075 01076 /* done */ 01077 return MM_STATUS_SUCCESS; 01078 } 01079 01080 VOID 01081 MMixerIsNodeTerminator( 01082 IN PTOPOLOGY Topology, 01083 IN ULONG NodeIndex, 01084 OUT ULONG * bTerminator) 01085 { 01086 /* sanity check */ 01087 ASSERT(NodeIndex < Topology->TopologyNodesCount); 01088 01089 /* check if node has multiple parents */ 01090 if (Topology->TopologyNodes[NodeIndex].NodeConnectedFromCount > 1) 01091 { 01092 /* node is connected to multiple other nodes */ 01093 *bTerminator = TRUE; 01094 01095 /* done */ 01096 return; 01097 } 01098 01099 /* check if node is mux / sum node */ 01100 if (IsEqualGUIDAligned(&Topology->TopologyNodes[NodeIndex].NodeType, &KSNODETYPE_SUM) || 01101 IsEqualGUIDAligned(&Topology->TopologyNodes[NodeIndex].NodeType, &KSNODETYPE_MUX)) 01102 { 01103 /* classic terminator */ 01104 *bTerminator = TRUE; 01105 01106 /* done */ 01107 return; 01108 01109 } 01110 01111 /* node is not a terminator */ 01112 *bTerminator = FALSE; 01113 } 01114 01115 MIXER_STATUS 01116 MMixerIsNodeConnectedToPin( 01117 IN PMIXER_CONTEXT MixerContext, 01118 IN PTOPOLOGY Topology, 01119 IN ULONG NodeIndex, 01120 IN ULONG PinId, 01121 IN ULONG bUpStream, 01122 OUT PULONG bConnected) 01123 { 01124 MIXER_STATUS Status; 01125 ULONG Index, PinsCount; 01126 PULONG Pins; 01127 01128 /* allocate pin index array */ 01129 Status = MMixerAllocateTopologyPinArray(MixerContext, Topology, &Pins); 01130 01131 if (Status != MM_STATUS_SUCCESS) 01132 { 01133 /* failed to allocate */ 01134 return Status; 01135 } 01136 01137 /* now get connected pins */ 01138 PinsCount = 0; 01139 MMixerGetAllUpOrDownstreamPinsFromNodeIndex(MixerContext, Topology, NodeIndex, bUpStream, &PinsCount, Pins); 01140 01141 /* set to false */ 01142 *bConnected = FALSE; 01143 01144 for(Index = 0; Index < PinsCount; Index++) 01145 { 01146 if (Pins[Index] == PinId) 01147 { 01148 /* pin is connected */ 01149 *bConnected = TRUE; 01150 break; 01151 } 01152 } 01153 01154 /* free pin index array */ 01155 MixerContext->Free(Pins); 01156 01157 /* done */ 01158 return MM_STATUS_SUCCESS; 01159 } 01160 01161 VOID 01162 MMixerGetConnectedFromLogicalTopologyPins( 01163 IN PTOPOLOGY Topology, 01164 IN ULONG NodeIndex, 01165 OUT PULONG OutPinCount, 01166 OUT PULONG OutPins) 01167 { 01168 ULONG Index; 01169 PTOPOLOGY_NODE Node; 01170 01171 /* sanity check */ 01172 ASSERT(NodeIndex < Topology->TopologyNodesCount); 01173 01174 /* get node */ 01175 Node = &Topology->TopologyNodes[NodeIndex]; 01176 01177 for(Index = 0; Index < Node->NodeConnectedFromCount; Index++) 01178 { 01179 /* copy logical pin id */ 01180 OutPins[Index] = Node->LogicalPinNodeConnectedFrom[Index]; 01181 } 01182 01183 /* store pin count */ 01184 *OutPinCount = Node->NodeConnectedFromCount; 01185 } 01186 01187 LPGUID 01188 MMixerGetNodeTypeFromTopology( 01189 IN PTOPOLOGY Topology, 01190 IN ULONG NodeIndex) 01191 { 01192 /* sanity check */ 01193 ASSERT(NodeIndex < Topology->TopologyNodesCount); 01194 01195 return &Topology->TopologyNodes[NodeIndex].NodeType; 01196 } 01197 01198 VOID 01199 MMixerSetTopologyPinReserved( 01200 IN PTOPOLOGY Topology, 01201 IN ULONG PinId) 01202 { 01203 /* sanity check */ 01204 ASSERT(PinId < Topology->TopologyPinsCount); 01205 01206 /* set reserved */ 01207 Topology->TopologyPins[PinId].Reserved = TRUE; 01208 } 01209 01210 VOID 01211 MMixerIsTopologyPinReserved( 01212 IN PTOPOLOGY Topology, 01213 IN ULONG PinId, 01214 OUT PULONG bReserved) 01215 { 01216 /* sanity check */ 01217 ASSERT(PinId < Topology->TopologyPinsCount); 01218 01219 /* get reserved status */ 01220 *bReserved = Topology->TopologyPins[PinId].Reserved; 01221 } 01222 01223 VOID 01224 MMixerSetTopologyNodeReserved( 01225 IN PTOPOLOGY Topology, 01226 IN ULONG NodeIndex) 01227 { 01228 /* sanity check */ 01229 ASSERT(NodeIndex < Topology->TopologyNodesCount); 01230 01231 /* set reserved */ 01232 Topology->TopologyNodes[NodeIndex].Reserved = TRUE; 01233 } 01234 01235 VOID 01236 MMixerIsTopologyNodeReserved( 01237 IN PTOPOLOGY Topology, 01238 IN ULONG NodeIndex, 01239 OUT PULONG bReserved) 01240 { 01241 /* sanity check */ 01242 ASSERT(NodeIndex < Topology->TopologyNodesCount); 01243 01244 /* get reserved status */ 01245 *bReserved = Topology->TopologyNodes[NodeIndex].Reserved; 01246 } 01247 01248 01249 MIXER_STATUS 01250 MMixerCreateTopology( 01251 IN PMIXER_CONTEXT MixerContext, 01252 IN ULONG PinCount, 01253 IN PKSMULTIPLE_ITEM NodeConnections, 01254 IN PKSMULTIPLE_ITEM NodeTypes, 01255 OUT PTOPOLOGY *OutTopology) 01256 { 01257 MIXER_STATUS Status; 01258 PTOPOLOGY Topology; 01259 01260 /* allocate topology */ 01261 Status = MMixerAllocateTopology(MixerContext, NodeTypes->Count, PinCount, &Topology); 01262 01263 if (Status != MM_STATUS_SUCCESS) 01264 { 01265 /* failed to allocate topology */ 01266 return Status; 01267 } 01268 01269 /* initialize topology nodes */ 01270 MMixerInitializeTopologyNodes(MixerContext, NodeTypes, Topology); 01271 01272 /* explore topology */ 01273 Status = MMixerExploreTopology(MixerContext, NodeConnections, NodeTypes, Topology); 01274 01275 if (Status != MM_STATUS_SUCCESS) 01276 { 01277 /* failed to allocate topology */ 01278 return Status; 01279 } 01280 01281 MMixerPrintTopology(Topology); 01282 01283 /* store result */ 01284 *OutTopology = Topology; 01285 01286 /* done */ 01287 return MM_STATUS_SUCCESS; 01288 } 01289 01290 01291 01292 01293 Generated on Fri May 25 2012 04:26:05 for ReactOS by
1.7.6.1
|