ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

topology.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.