source: svn/newcon3bcm2_21bu/magnum/portinginterface/ape/7552/bape_path_priv.c

Last change on this file was 76, checked in by megakiss, 10 years ago

1W 대기전력을 만족시키기 위하여 POWEROFF시 튜너를 Standby 상태로 함

  • Property svn:executable set to *
File size: 45.2 KB
Line 
1/***************************************************************************
2 *     Copyright (c) 2006-2012, Broadcom Corporation
3 *     All Rights Reserved
4 *     Confidential Property of Broadcom Corporation
5 *
6 *  THIS SOFTWARE MAY ONLY BE USED SUBJECT TO AN EXECUTED SOFTWARE LICENSE
7 *  AGREEMENT  BETWEEN THE USER AND BROADCOM.  YOU HAVE NO RIGHT TO USE OR
8 *  EXPLOIT THIS MATERIAL EXCEPT SUBJECT TO THE TERMS OF SUCH AN AGREEMENT.
9 *
10 * $brcm_Workfile: bape_path_priv.c $
11 * $brcm_Revision: Hydra_Software_Devel/24 $
12 * $brcm_Date: 3/16/12 6:10p $
13 *
14 * Module Description: APE Path routines
15 *
16 * Revision History:
17 *
18 * $brcm_Log: /magnum/portinginterface/ape/7422/bape_path_priv.c $
19 *
20 * Hydra_Software_Devel/24   3/16/12 6:10p gskerl
21 * SW7425-1178: Modified BAPE_PathNode_P_EnumerateUpstreamPathNodes() so
22 * that it calls the callback when unrecursing out of the tree (instead
23 * of when recursing into).
24 *
25 * Hydra_Software_Devel/23   2/21/12 6:41p jgarrett
26 * SW7231-363: Propagating codec and mono format changes properly
27 *
28 * Hydra_Software_Devel/22   2/3/12 4:29p jgarrett
29 * SW7425-2268: Initial bringup of voice conferencing support
30 *
31 * Hydra_Software_Devel/21   1/31/12 6:17p jgarrett
32 * SW7425-2268: Adding initial voice conferencing support
33 *
34 * Hydra_Software_Devel/20   8/2/11 3:27p jgarrett
35 * SWDTV-8150: Adding mixer output connection support
36 *
37 * Hydra_Software_Devel/19   6/20/11 7:02p jgarrett
38 * SW7425-406: Adding input scaling coefficients to mixer
39 *
40 * Hydra_Software_Devel/18   6/15/11 2:12p gskerl
41 * SW7425-321: Fixed Coverity dead code issue
42 *
43 * Hydra_Software_Devel/17   6/14/11 6:50p gskerl
44 * SW7425-321: Added PathNode enumeration functions
45 *
46 * Hydra_Software_Devel/16   5/27/11 11:20a jgarrett
47 * SW7425-408: Revising format propagation logic
48 *
49 * Hydra_Software_Devel/15   5/25/11 5:13p jgarrett
50 * SW7425-408: Properly propagating input format when inputs are added to
51 * a node
52 *
53 * Hydra_Software_Devel/14   5/24/11 3:41p jgarrett
54 * SW7425-559: Fixing warning with B_REFSW_DEBUG=n
55 *
56 * Hydra_Software_Devel/13   5/18/11 6:50p jgarrett
57 * SW7425-408: Adding preliminary DDRE support
58 *
59 * Hydra_Software_Devel/12   4/18/11 10:09p jgarrett
60 * SW7425-361: Refactoring DSP branch decisions
61 *
62 * Hydra_Software_Devel/11   4/17/11 12:29p jgarrett
63 * SW7344-46: Adding debug
64 *
65 * Hydra_Software_Devel/10   4/16/11 12:15p jgarrett
66 * SW7425-371: Removing tab characters
67 *
68 * Hydra_Software_Devel/9   4/14/11 3:25p jgarrett
69 * SW7425-360: Fixing shutdown crash if resources are leaked in the app
70 *
71 * Hydra_Software_Devel/8   4/6/11 1:24a jgarrett
72 * SW35330-35: Merge to main branch
73 *
74 * Hydra_Software_Devel/SW35330-35/1   4/5/11 12:50p jgarrett
75 * SW35330-35: FMM Abstraction refactoring to support DTV
76 *
77 * Hydra_Software_Devel/7   3/22/11 2:35p jgarrett
78 * SW7422-356: Fixing crash on mux stop
79 *
80 * Hydra_Software_Devel/6   3/21/11 7:08p jgarrett
81 * SW7422-356: Adding MuxOutput
82 *
83 * Hydra_Software_Devel/5   3/11/11 12:20p jgarrett
84 * SW7422-146: Enabling PPM Correction
85 *
86 * Hydra_Software_Devel/4   3/3/11 6:31p jgarrett
87 * SW7422-146: Adding SRC and DSOLA and path review feedback
88 *
89 * Hydra_Software_Devel/3   2/28/11 5:15p jgarrett
90 * SW7422-146: Coverity CID 271
91 *
92 * Hydra_Software_Devel/2   2/28/11 4:50p jgarrett
93 * SW7422-146: Adding TruVolume
94 *
95 * Hydra_Software_Devel/1   2/28/11 1:28p jgarrett
96 * SW7422-146: Filter graph reworked to remove mixer dependencies
97 *
98 ***************************************************************************/
99
100#include "bape.h"
101#include "bape_priv.h"
102
103BDBG_MODULE(bape_path_priv);
104
105BDBG_OBJECT_ID(BAPE_PathNode);
106BDBG_OBJECT_ID(BAPE_PathConnector);
107BDBG_OBJECT_ID(BAPE_PathConnection);
108
109#if BDBG_DEBUG_BUILD
110static const char *g_pPathNodeStateNames[BAPE_PathNodeState_eMax] =
111{
112    "Idle",
113    "AllocatingPath",
114    "AllocatedPath",
115    "ConfiguredPath",
116    "Started"
117};
118#endif
119
120#define BAPE_PATH_NODE_STATE_NAME(state) (((state)>=BAPE_PathNodeState_eMax)?"invalid":g_pPathNodeStateNames[(state)])
121
122/***************************************************************************
123Summary:
124Build paths for all downstream connections from a node
125***************************************************************************/
126BERR_Code BAPE_PathNode_P_AcquirePathResources(
127    BAPE_PathNode *pNode
128    )
129{
130    unsigned pathNum;
131    BERR_Code errCode = BERR_SUCCESS;
132
133    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
134
135    BDBG_MSG(("Acquire Path Resources for node %s", pNode->pName));
136
137    if ( pNode->state == BAPE_PathNodeState_eStarted )
138    {
139        /* Stop recursing if we hit a running node.
140           This may occur with mixers, when one input has
141           started, others are allowed to start as well. */
142        BDBG_MSG(("Node %s already started", pNode->pName));
143        return BERR_SUCCESS;
144    }
145
146    pNode->state = BAPE_PathNodeState_eAllocatingPath;
147
148    for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
149    {
150        BAPE_PathConnection *pConnection;
151
152        for ( pConnection = BLST_SQ_FIRST(&pNode->paths[pathNum].connector.connectionList);
153              NULL != pConnection;
154              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
155        {
156            BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
157            BDBG_OBJECT_ASSERT(pConnection->pSink, BAPE_PathNode);
158            /* First, allocate connection resources */
159            if ( NULL != pConnection->pSink->allocatePathFromInput )
160            {
161                BDBG_MSG(("Building connection from %s to %s using connector %s", 
162                          pNode->pName, pConnection->pSink->pName, 
163                          pNode->paths[pathNum].connector.pName));
164                errCode = pConnection->pSink->allocatePathFromInput(pConnection->pSink, pConnection);
165                if ( errCode )
166                {
167                    errCode = BERR_TRACE(errCode);
168                    goto err_acquire;
169                }
170            }
171            else
172            {
173                BDBG_MSG(("Downstream node %s does not support allocatePathFromInput", pConnection->pSink->pName));
174            }
175            if ( NULL != pNode->allocatePathToOutput )
176            {
177                BDBG_MSG(("Building connection to %s from %s using connector %s", 
178                          pConnection->pSink->pName, pNode->pName, 
179                          pNode->paths[pathNum].connector.pName));
180                errCode = pNode->allocatePathToOutput(pNode, pConnection);
181                if ( errCode )
182                {
183                    errCode = BERR_TRACE(errCode);
184                    goto err_acquire;
185                }
186            }
187            /* Now recurse into children */
188            errCode = BAPE_PathNode_P_AcquirePathResources(pConnection->pSink);
189            if ( errCode )
190            {
191                errCode = BERR_TRACE(errCode);
192                goto err_acquire;
193            }
194        }
195    }
196
197    pNode->state = BAPE_PathNodeState_eAllocatedPath;
198    return BERR_SUCCESS;
199
200err_acquire:
201    /* If we've failed, recursively cleanup when we hit a root node */
202    if ( BLST_S_EMPTY(&pNode->upstreamList) )
203    {
204        BAPE_PathNode_P_ReleasePathResources(pNode);
205    }
206    else
207    {
208        /* Set state to allocated and wait for cleanup when we exit back to the top of the stack */
209        pNode->state = BAPE_PathNodeState_eAllocatedPath;
210    }
211    return errCode;
212}
213
214/***************************************************************************
215Summary:
216Teardown paths for all downstream connections from a node as much as possible
217***************************************************************************/
218void BAPE_PathNode_P_ReleasePathResources(
219    BAPE_PathNode *pNode
220    )
221{
222    unsigned pathNum;
223
224    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
225
226    BDBG_MSG(("Release Path Resources for node %s", pNode->pName));
227
228    switch ( pNode->state )
229    {
230    case BAPE_PathNodeState_eAllocatingPath:
231    case BAPE_PathNodeState_eStarted:
232        BDBG_MSG(("Can not release Path Resources for node %s", pNode->pName));
233        return;
234    default:
235        break;
236    }
237
238    for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
239    {
240        BAPE_PathConnection *pConnection;
241
242        for ( pConnection = BLST_SQ_FIRST(&pNode->paths[pathNum].connector.connectionList);
243              NULL != pConnection;
244              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
245        {
246            BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
247            BDBG_OBJECT_ASSERT(pConnection->pSink, BAPE_PathNode);
248            if ( pConnection->pSink->freePathFromInput )
249            {
250                BDBG_MSG(("Teardown connection from %s to %s using connector %s", 
251                          pNode->pName, pConnection->pSink->pName, 
252                          pNode->paths[pathNum].connector.pName));
253                pConnection->pSink->freePathFromInput(pConnection->pSink, pConnection);
254            }
255            BAPE_PathNode_P_ReleasePathResources(pConnection->pSink);
256        }
257    }
258
259    pNode->state = BAPE_PathNodeState_eIdle;
260}
261
262/***************************************************************************
263Summary:
264Configure allocated resources.
265 
266Description:
267FMM Resources will be configured from producer -> consumer.  DSP task is
268allocated prior to this call, and stage settings will be applied. 
269***************************************************************************/
270BERR_Code BAPE_PathNode_P_ConfigurePathResources(
271    BAPE_PathNode *pNode
272    )
273{
274    BERR_Code errCode;
275    unsigned pathNum;
276    BAPE_PathConnection *pConnection;
277
278    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
279
280    BDBG_MSG(("Configure Path Resources for node %s", pNode->pName));
281
282    switch ( pNode->state )
283    {
284    case BAPE_PathNodeState_eAllocatedPath:
285    case BAPE_PathNodeState_eConfiguredPath:
286        break;
287    case BAPE_PathNodeState_eStarted:
288        return BERR_SUCCESS;
289    default:
290        BDBG_ERR(("Invalid path node state transition (%s -> %s)", BAPE_PATH_NODE_STATE_NAME(pNode->state), BAPE_PATH_NODE_STATE_NAME(BAPE_PathNodeState_eConfiguredPath))); 
291        return BERR_TRACE(BERR_NOT_SUPPORTED);
292    }
293
294    for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
295    {
296        for ( pConnection = BLST_SQ_FIRST(&pNode->paths[pathNum].connector.connectionList);
297              NULL != pConnection;
298              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
299        {
300            BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
301            BDBG_OBJECT_ASSERT(pConnection->pSink, BAPE_PathNode);
302            /* First, configure my output to this connection */
303            if ( NULL != pNode->configPathToOutput )
304            {
305                BDBG_MSG(("Configuring connection from %s to %s using connector %s", 
306                          pNode->pName, pConnection->pSink->pName, 
307                          pNode->paths[pathNum].connector.pName));
308                errCode = pNode->configPathToOutput(pNode, pConnection);
309                if ( errCode )
310                {
311                    BDBG_ERR(("Error configuring output from %s to %s on connector %s", pNode->pName, pConnection->pSink->pName, pNode->paths[pathNum].connector.pName));
312                    return BERR_TRACE(errCode);
313                }
314            }
315            /* Next, configure the downstream node's input from this connection */
316            if ( NULL != pConnection->pSink->configPathFromInput )
317            {
318                BDBG_MSG(("Configuring connection to %s from %s using connector %s", 
319                          pConnection->pSink->pName, pNode->pName,
320                          pNode->paths[pathNum].connector.pName));
321                errCode = pConnection->pSink->configPathFromInput(pConnection->pSink, pConnection);
322                if ( errCode )
323                {
324                    BDBG_ERR(("Error configuring %s input from %s on connector %s", pConnection->pSink->pName, pNode->pName, pNode->paths[pathNum].connector.pName));
325                    return BERR_TRACE(errCode);
326                }
327            }
328            /* Now, recurse into the downstream node */
329            errCode = BAPE_PathNode_P_ConfigurePathResources(pConnection->pSink);
330            if ( errCode )
331            {
332                /* Error trace skipped, it will print in one of the cases above */
333                return errCode;
334            }
335        }
336    }
337
338    /* Update state */
339    pNode->state = BAPE_PathNodeState_eConfiguredPath;
340
341    return BERR_SUCCESS;
342}
343
344/***************************************************************************
345Summary:
346Start paths for all downstream connections from a node
347***************************************************************************/
348BERR_Code BAPE_PathNode_P_StartPaths(
349    BAPE_PathNode *pNode
350    )
351{
352    BERR_Code errCode;
353    unsigned pathNum;
354    BAPE_PathConnection *pConnection;
355
356    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
357
358    BDBG_MSG(("Start Path for node %s", pNode->pName));
359
360    switch ( pNode->state )
361    {
362    case BAPE_PathNodeState_eStarted:
363        pNode->numStarts++;
364        return BERR_SUCCESS;
365    case BAPE_PathNodeState_eConfiguredPath:
366        break;
367    default:
368        BDBG_ERR(("Must allocate and configure path prior to starting object"));
369        return BERR_TRACE(BERR_NOT_SUPPORTED);
370    }
371
372    for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
373    {
374        for ( pConnection = BLST_SQ_FIRST(&pNode->paths[pathNum].connector.connectionList);
375              NULL != pConnection;
376              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
377        {
378            BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
379            BDBG_OBJECT_ASSERT(pConnection->pSink, BAPE_PathNode);
380
381            /* First, recurse into children.  This routine starts from consumer..producer */
382            errCode = BAPE_PathNode_P_StartPaths(pConnection->pSink);
383            if ( errCode )
384            {
385                errCode = BERR_TRACE(errCode);
386                goto err_start;
387            }
388
389            /* Now start per-connection consumers */
390            if ( NULL != pConnection->pSink->startPathFromInput )
391            {
392                BDBG_MSG(("Starting connection to %s from %s using connector %s", 
393                          pConnection->pSink->pName, pNode->pName,
394                          pNode->paths[pathNum].connector.pName));
395                errCode = pConnection->pSink->startPathFromInput(pConnection->pSink, pConnection);
396                if ( errCode )
397                {
398                    errCode = BERR_TRACE(errCode);
399                    goto err_start;
400                }
401            }
402            if ( NULL != pNode->startPathToOutput )
403            {
404                BDBG_MSG(("Starting connection from %s to %s using connector %s", 
405                          pNode->pName, pConnection->pSink->pName,
406                          pNode->paths[pathNum].connector.pName));
407                errCode = pNode->startPathToOutput(pNode, pConnection);
408                if ( errCode )
409                {
410                    errCode = BERR_TRACE(errCode);
411                    goto err_start;
412                }
413            }
414        }
415    }
416
417    pNode->numStarts = 1;
418    pNode->state = BAPE_PathNodeState_eStarted;
419    return BERR_SUCCESS;
420
421err_start:
422    /* If we've failed, recursively cleanup when we hit a root node */
423    if ( BLST_S_EMPTY(&pNode->upstreamList) )
424    {
425        BAPE_PathNode_P_StopPaths(pNode);
426    }
427    return errCode;   
428}
429
430/***************************************************************************
431Summary:
432Stop paths for downstream connections from this node
433***************************************************************************/
434void BAPE_PathNode_P_StopPaths(
435    BAPE_PathNode *pNode
436    )
437{
438    unsigned pathNum;
439    BAPE_PathConnection *pConnection;
440    BAPE_PathNodeState exitState;
441
442    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
443
444    BDBG_MSG(("Stop Path for node %s", pNode->pName));
445
446    switch ( pNode->state )
447    {
448    case BAPE_PathNodeState_eIdle:
449        exitState = BAPE_PathNodeState_eIdle;
450        break;
451    case BAPE_PathNodeState_eStarted:
452        if ( pNode->numStarts > 1 )
453        {
454            pNode->numStarts--;
455            return;
456        }
457        /* Otherwise, fall through */
458    default:
459        exitState = BAPE_PathNodeState_eAllocatedPath;
460        break;
461    }
462
463    for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
464    {
465        for ( pConnection = BLST_SQ_FIRST(&pNode->paths[pathNum].connector.connectionList);
466              NULL != pConnection;
467              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
468        {
469            BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
470            BDBG_OBJECT_ASSERT(pConnection->pSink, BAPE_PathNode);
471
472            /* Stop from producer..consumer */
473            if ( NULL != pNode->stopPathToOutput )
474            {
475                BDBG_MSG(("Stopping connection from %s to %s using connector %s", 
476                          pNode->pName, pConnection->pSink->pName, 
477                          pNode->paths[pathNum].connector.pName));
478                pNode->stopPathToOutput(pNode, pConnection);
479            }           
480            if ( NULL != pConnection->pSink->stopPathFromInput )
481            {
482                BDBG_MSG(("Stopping connection to %s from %s using connector %s", 
483                          pConnection->pSink->pName, pNode->pName,
484                          pNode->paths[pathNum].connector.pName));
485                pConnection->pSink->stopPathFromInput(pConnection->pSink, pConnection);
486            }
487            BAPE_PathNode_P_StopPaths(pConnection->pSink);
488        }
489    }
490
491    pNode->numStarts = 0;
492    pNode->state = exitState;
493}
494
495/***************************************************************************
496Summary:
497Determine if a connection is possible
498***************************************************************************/
499BERR_Code BAPE_PathNode_P_ConnectionSupported(
500    BAPE_PathNode *pNode,
501    BAPE_Connector input
502    )
503{
504    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
505    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
506    if ( input->mono && !pNode->monoInputValid )
507    {
508        BDBG_ERR(("Node %s can not support mono input.", pNode->pName));
509        return BERR_TRACE(BERR_NOT_SUPPORTED);
510    }
511    if ( NULL != pNode->connectorSupported )
512    {
513        return pNode->connectorSupported(pNode, input);
514    }
515    return BERR_SUCCESS;
516}
517
518static BAPE_PathConnection *BAPE_PathNode_P_FindConnection(
519    BAPE_PathNode *pNode,
520    BAPE_Connector input
521    )
522{
523    /* Search the upstream list of the sink node to see if we find the source connector */
524    BAPE_PathConnection *pConnection;
525
526    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
527    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
528
529    for ( pConnection = BLST_S_FIRST(&pNode->upstreamList);
530          NULL != pConnection;
531          pConnection = BLST_S_NEXT(pConnection, upstreamNode) )
532    {
533        if ( pConnection->pSource == input )
534        {
535            break;
536        }
537    }
538
539#if BDBG_DEBUG_BUILD
540    /* Sanity check, make sure the link is bi-directional */
541    if ( NULL != pConnection )
542    {
543        BAPE_PathConnection *pDownstreamConnection;
544        for ( pDownstreamConnection = BLST_SQ_FIRST(&input->connectionList);
545              NULL != pDownstreamConnection; 
546              pDownstreamConnection = BLST_SQ_NEXT(pDownstreamConnection, downstreamNode) )
547        {
548            if ( pDownstreamConnection == pConnection )
549            {
550                break;
551            }
552        }
553
554        BDBG_ASSERT(NULL != pDownstreamConnection);
555    }
556#endif
557
558    return pConnection;
559}
560
561/***************************************************************************
562Summary:
563Make a connection
564***************************************************************************/
565BERR_Code BAPE_PathNode_P_AddInput(
566    BAPE_PathNode *pNode,
567    BAPE_Connector input
568    )
569{
570    BERR_Code errCode;
571    BAPE_PathConnection *pConnection;
572
573    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
574    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
575   
576    BDBG_MSG(("Adding input %s %s to node %s", input->pParent->pName, input->pName, pNode->pName));
577
578    /* Make sure we don't have the same connection already */
579    pConnection = BAPE_PathNode_P_FindConnection(pNode, input);
580    if ( pConnection )
581    {
582        BDBG_ERR(("Input %s is already connected to %s", input->pParent->pName, pNode->pName));
583        return BERR_TRACE(BERR_INVALID_PARAMETER);
584    }
585
586    /* Check if this is a valid connection */
587    if ( NULL != pNode->connectorSupported )
588    {
589        errCode = pNode->connectorSupported(pNode, input);
590        if ( errCode )
591        {
592            return BERR_TRACE(errCode);
593        }
594    }
595
596    /* Build the connection node */
597    pConnection = BKNI_Malloc(sizeof(BAPE_PathConnection));
598    if ( NULL == pConnection )
599    {
600        return BERR_TRACE(BERR_OUT_OF_SYSTEM_MEMORY);
601    }
602
603    /* This sets all the handles to invalid entries */
604    BKNI_Memset(pConnection, 0x0, sizeof(BAPE_PathConnection));
605    BAPE_FciIdGroup_Init(&pConnection->inputFciGroup);
606    pConnection->pSource = input;
607    pConnection->pSink = pNode;
608    BLST_S_INSERT_HEAD(&pNode->upstreamList, pConnection, upstreamNode);
609    /* Insert FMM nodes to the head of the list and DSP nodes to the tail */
610    /* This allows branch logic to work better */
611    if ( pNode->type == BAPE_PathNodeType_eEqualizer ||
612         (pNode->type == BAPE_PathNodeType_eMixer && pNode->subtype != BAPE_MixerType_eDsp) )
613    {
614        /* FMM Node */
615        BLST_SQ_INSERT_HEAD(&input->connectionList, pConnection, downstreamNode);
616    }
617    else
618    {
619        /* DSP Node */
620        BLST_SQ_INSERT_TAIL(&input->connectionList, pConnection, downstreamNode);
621    }
622    BDBG_OBJECT_SET(pConnection, BAPE_PathConnection);
623
624    /* Make sure any format changes occur as needed */
625    errCode = BAPE_Connector_P_FormatChange(input);
626    if ( errCode )
627    {
628        (void)BAPE_PathNode_P_RemoveInput(pNode, input);
629        return BERR_TRACE(errCode);
630    }
631
632    /* Notify source that a connection has been made */
633    if ( input->pParent->outputConnectionAdded )
634    {
635        errCode = input->pParent->outputConnectionAdded(input->pParent, pConnection);
636        if ( errCode )
637        {
638            (void)BAPE_PathNode_P_RemoveInput(pNode, input);
639            return BERR_TRACE(errCode);           
640        }
641    }
642       
643    return BERR_SUCCESS;
644}
645
646/***************************************************************************
647Summary:
648Destroy a connection
649***************************************************************************/
650BERR_Code BAPE_PathNode_P_RemoveInput(
651    BAPE_PathNode *pNode,
652    BAPE_Connector input
653    )
654{
655    BAPE_PathConnection *pConnection;
656
657    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
658    BDBG_OBJECT_ASSERT(input, BAPE_PathConnector);
659
660    BDBG_MSG(("Removing input %s %s from node %s", input->pParent->pName, input->pName, pNode->pName));
661
662    pConnection = BAPE_PathNode_P_FindConnection(pNode, input);
663    if ( NULL == pConnection )
664    {
665        BDBG_ERR(("Input %s not connected to %s", input->pParent->pName, pNode->pName));
666        return BERR_TRACE(BERR_INVALID_PARAMETER);
667    }
668
669    BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
670
671    /* Notify source that a connection is being removed */
672    if ( input->pParent->outputConnectionRemoved )
673    {
674        input->pParent->outputConnectionRemoved(input->pParent, pConnection);
675    }
676
677    /* Make sure resources are freed */
678    if ( pNode->freePathFromInput )
679    {
680        pNode->freePathFromInput(pNode, pConnection);
681    }
682
683    /* Make really sure we don't leak resources */
684    BDBG_ASSERT(NULL == pConnection->sfifoGroup);
685    BDBG_ASSERT(NULL == pConnection->srcGroup);
686    BDBG_ASSERT(NULL == pConnection->mixerGroup);
687    BDBG_ASSERT(NULL == pConnection->dfifoGroup);
688    BDBG_ASSERT(NULL == pConnection->loopbackGroup);
689
690    /* Remove connections and free node */
691    BLST_S_REMOVE(&pNode->upstreamList, pConnection, BAPE_PathConnection, upstreamNode);
692    BLST_SQ_REMOVE(&input->connectionList, pConnection, BAPE_PathConnection, downstreamNode);
693    BDBG_OBJECT_DESTROY(pConnection, BAPE_PathConnection);
694    BKNI_Free(pConnection);
695
696    return BERR_SUCCESS;
697}
698
699/***************************************************************************
700Summary:
701Remove all inputs
702***************************************************************************/
703BERR_Code BAPE_PathNode_P_RemoveAllInputs(
704    BAPE_PathNode *pNode
705    )
706{
707    BERR_Code errCode;
708    BAPE_PathConnection *pConnection;
709
710    /* Keep removing the first item from the list until it's empty */
711    for ( pConnection = BLST_S_FIRST(&pNode->upstreamList);
712          pConnection != NULL;
713          pConnection = BLST_S_FIRST(&pNode->upstreamList) )
714    {
715        errCode = BAPE_PathNode_P_RemoveInput(pNode, pConnection->pSource);
716        if ( errCode )
717        {
718            return BERR_TRACE(errCode);
719        }
720    }
721    return BERR_SUCCESS;
722}
723
724static BAPE_ConnectorFormat BAPE_Connector_P_GetFormat(
725    const BAPE_PathConnector *pConnector
726    )
727{
728    BDBG_OBJECT_ASSERT(pConnector, BAPE_PathConnector);
729    if ( pConnector->compressed )
730    {
731        return BAPE_ConnectorFormat_eCompressed;
732    }
733    else if ( pConnector->mono )
734    {
735        return BAPE_ConnectorFormat_eMono;
736    }
737    else
738    {
739        return (pConnector->numChannelPairs <= 1) ? BAPE_ConnectorFormat_eStereo : BAPE_ConnectorFormat_eMultichannel;
740    }
741}
742
743static void BAPE_PathNode_P_AddOutputStatus(
744    BAPE_PathNode *pNode,
745    unsigned rootPathNum,
746    BAPE_PathNodeOutputStatus *pStatus      /* [out] */
747    )
748{
749    unsigned pathNum;
750
751    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
752    BDBG_ASSERT(NULL != pStatus);
753
754    for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
755    {
756        BAPE_PathConnection *pConnection;
757        unsigned numConnections=0;
758        unsigned numFmmOutputs=0;
759        BAPE_ConnectorFormat format = BAPE_Connector_P_GetFormat(&pNode->paths[pathNum].connector);
760
761        for ( pConnection = BLST_SQ_FIRST(&pNode->paths[pathNum].connector.connectionList);
762              NULL != pConnection;
763              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
764        {
765            pStatus->pathStatus[rootPathNum].totalConnections++;
766            numConnections++;
767            if ( pConnection->pSink->type == BAPE_PathNodeType_eMixer ||
768                 pConnection->pSink->type == BAPE_PathNodeType_eEqualizer )
769            {
770                numFmmOutputs++;
771            }
772            BAPE_PathNode_P_AddOutputStatus(pConnection->pSink, rootPathNum, pStatus);           
773        }
774        if ( numConnections > 0 )
775        {
776            switch ( format )
777            {
778            case BAPE_ConnectorFormat_eStereo:
779                pStatus->pathStatus[rootPathNum].totalStereoOutputs+=numConnections;
780                break;
781            case BAPE_ConnectorFormat_eMultichannel:
782                pStatus->pathStatus[rootPathNum].totalMultichannelOutputs+=numConnections;
783                break;
784            case BAPE_ConnectorFormat_eCompressed:
785                pStatus->pathStatus[rootPathNum].totalCompressedOutputs+=numConnections;
786                break;
787            case BAPE_ConnectorFormat_eMono:
788                pStatus->pathStatus[rootPathNum].totalMonoOutputs+=numConnections;
789                break;
790            default:
791                break;
792            }
793            pStatus->pathStatus[rootPathNum].totalBranches += numConnections-1;
794            pStatus->activeConnectors++;
795        }
796    }
797}
798
799void BAPE_PathNode_P_GetOutputStatus(
800    BAPE_PathNode *pNode,
801    BAPE_PathNodeOutputStatus *pStatus      /* [out] */
802    )
803{
804    unsigned pathNum;
805    unsigned activePaths=0;
806
807    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
808    BDBG_ASSERT(NULL != pStatus);
809
810    BKNI_Memset(pStatus, 0, sizeof(*pStatus));
811    pStatus->numPaths = pNode->numPaths;
812
813    for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
814    {
815        BAPE_PathConnection *pConnection;
816        unsigned numConnections=0;
817        unsigned numFmmOutputs=0;
818        BAPE_ConnectorFormat format = BAPE_Connector_P_GetFormat(&pNode->paths[pathNum].connector);
819
820        for ( pConnection = BLST_SQ_FIRST(&pNode->paths[pathNum].connector.connectionList);
821              NULL != pConnection;
822              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
823        {
824            pStatus->pathStatus[pathNum].directConnections++;
825            pStatus->pathStatus[pathNum].totalConnections++;
826            numConnections++;
827            if ( pConnection->pSink->type == BAPE_PathNodeType_eMixer ||
828                 pConnection->pSink->type == BAPE_PathNodeType_eEqualizer )
829            {
830                numFmmOutputs++;
831            }
832            BAPE_PathNode_P_AddOutputStatus(pConnection->pSink, pathNum, pStatus);           
833        }
834        if ( numConnections > 0 )
835        {
836            switch ( format )
837            {
838            case BAPE_ConnectorFormat_eStereo:
839                pStatus->pathStatus[pathNum].totalStereoOutputs++;
840                break;
841            case BAPE_ConnectorFormat_eMultichannel:
842                pStatus->pathStatus[pathNum].totalMultichannelOutputs++;
843                break;
844            case BAPE_ConnectorFormat_eCompressed:
845                pStatus->pathStatus[pathNum].totalCompressedOutputs++;
846                break;
847            case BAPE_ConnectorFormat_eMono:
848                pStatus->pathStatus[pathNum].totalMonoOutputs++;
849                break;
850            default:
851                break;
852            }
853            pStatus->pathStatus[pathNum].totalBranches += numConnections-1;
854            pStatus->activeConnectors++;
855            pStatus->directConnections += numConnections;
856            activePaths++;
857        }
858    }
859    if ( activePaths > 0 )
860    {
861        pStatus->totalBranches += activePaths-1;
862        for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
863        {
864            pStatus->totalStereoOutputs += pStatus->pathStatus[pathNum].totalStereoOutputs;
865            pStatus->totalMultichannelOutputs += pStatus->pathStatus[pathNum].totalMultichannelOutputs;
866            pStatus->totalCompressedOutputs += pStatus->pathStatus[pathNum].totalCompressedOutputs;
867            pStatus->totalConnections += pStatus->pathStatus[pathNum].totalConnections;
868        }
869    }
870}   
871
872/***************************************************************************
873Summary:
874Set an connector's sample rate on the fly (used with decoders)
875***************************************************************************/
876void BAPE_Connector_P_SampleRateChange_isr(
877    BAPE_Connector connector
878    )
879{
880    BAPE_PathConnection *pConnection;
881   
882    BDBG_OBJECT_ASSERT(connector, BAPE_PathConnector);
883    BKNI_ASSERT_ISR_CONTEXT();
884
885    for ( pConnection = BLST_SQ_FIRST(&connector->connectionList);
886          NULL != pConnection;
887          pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
888    {
889        BAPE_PathNode *pNode = pConnection->pSink;
890
891        BDBG_ASSERT(NULL != pNode);
892
893        if ( pConnection->pSink->inputSampleRateChange_isr )
894        {
895            pNode->inputSampleRateChange_isr(pConnection->pSink, pConnection);
896        }
897        else
898        {
899            unsigned i;
900            /* By default just propagate the sample rate change */
901            for ( i = 0; i < pNode->numPaths; i++ )
902            {
903                pNode->paths[i].connector.sampleRate = connector->sampleRate;
904                BAPE_Connector_P_SampleRateChange_isr(&pNode->paths[i].connector);
905            }
906        }
907    }
908}
909
910/***************************************************************************
911Summary:
912Set an connector's sample rate on the fly (used with decoders)
913***************************************************************************/
914BERR_Code BAPE_Connector_P_FormatChange(
915    BAPE_Connector connector
916    )
917{
918    BAPE_PathConnection *pConnection;
919
920    BDBG_OBJECT_ASSERT(connector, BAPE_PathConnector);
921
922    for ( pConnection = BLST_SQ_FIRST(&connector->connectionList);
923          NULL != pConnection;
924          pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
925    {
926        BAPE_PathNode *pNode = pConnection->pSink;
927        BERR_Code errCode;
928
929        BDBG_ASSERT(NULL != pNode);
930
931        BDBG_MSG(("Format changed between %s and %s connector %s",
932                  pConnection->pSource->pParent->pName, pNode->pName, connector->pName));
933
934        if ( pConnection->pSink->connectorSupported )
935        {
936            errCode = pConnection->pSink->connectorSupported(pConnection->pSink, pConnection->pSource);
937            if ( errCode )
938            {
939                return BERR_TRACE(errCode);
940            }
941        }
942       
943        /* Did the format change? */
944        if ( pConnection->numChannelPairs != pConnection->pSource->numChannelPairs ||
945             pConnection->ppmCorrection != pConnection->pSource->ppmCorrection ||
946             pConnection->compressed != pConnection->pSource->compressed ||
947             pConnection->codec != pConnection->pSource->codec ||
948             pConnection->mono != pConnection->pSource->mono )
949        {
950            /* Does this node care? */
951            if ( pConnection->pSink->inputFormatChange )
952            {
953                errCode = pNode->inputFormatChange(pNode, pConnection);
954                if ( errCode )
955                {
956                    return BERR_TRACE(errCode);
957                }
958            }
959            else
960            {
961                pConnection->numChannelPairs = pConnection->pSource->numChannelPairs;
962                pConnection->ppmCorrection = pConnection->pSource->ppmCorrection;
963                pConnection->compressed = pConnection->pSource->compressed;
964                pConnection->codec = pConnection->pSource->codec;
965                pConnection->mono = pConnection->pSource->mono;
966            }
967        }
968    }
969
970    return BERR_SUCCESS;
971}
972
973/***************************************************************************
974Summary:
975Get number of downstream connections for a connector
976***************************************************************************/
977unsigned BAPE_Connector_P_GetNumConnections(
978    BAPE_Connector connector
979    )
980{
981    BAPE_PathConnection *pConnection;
982    unsigned numConnections=0;
983
984    BDBG_OBJECT_ASSERT(connector, BAPE_PathConnector);
985
986    for ( pConnection = BLST_SQ_FIRST(&connector->connectionList);
987          NULL != pConnection;
988          pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
989    {
990        numConnections++;
991    }
992
993    return numConnections;
994}
995
996/***************************************************************************
997Summary:
998Set the connector mute state
999***************************************************************************/
1000void BAPE_Connector_P_SetMute(
1001    BAPE_Connector connector,
1002    bool muted
1003    )
1004{
1005    BAPE_PathConnection *pConnection;
1006
1007    BDBG_OBJECT_ASSERT(connector, BAPE_PathConnector);
1008
1009    for ( pConnection = BLST_SQ_FIRST(&connector->connectionList);
1010          NULL != pConnection;
1011          pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
1012    {
1013        BAPE_PathNode *pNode = pConnection->pSink;
1014
1015        BDBG_ASSERT(NULL != pNode);
1016
1017        BDBG_MSG(("Set mute between %s and %s connector %s to %u",
1018                  pConnection->pSource->pParent->pName, pNode->pName, connector->pName, muted));
1019
1020        if ( pNode->inputMute )
1021        {
1022            /* Stop once we've found a node that can handle this operation */
1023            pNode->inputMute(pNode, pConnection, muted);
1024            return;
1025        }
1026        else
1027        {
1028            unsigned i;
1029
1030            /* Recurse until handled */
1031            for ( i = 0; i < pNode->numPaths; i++ )
1032            {
1033                BAPE_Connector_P_SetMute(&pNode->paths[i].connector, muted);
1034            }
1035        }
1036    }
1037}
1038
1039/***************************************************************************
1040Summary:
1041Remove all downstream connections from this connector
1042***************************************************************************/
1043void BAPE_Connector_P_RemoveAllConnections(
1044    BAPE_Connector connector
1045    )
1046{
1047    BAPE_PathConnection *pConnection;
1048
1049    BDBG_OBJECT_ASSERT(connector, BAPE_PathConnector);
1050   
1051    for ( pConnection = BLST_SQ_FIRST(&connector->connectionList);
1052          NULL != pConnection;
1053          pConnection = BLST_SQ_FIRST(&connector->connectionList) )
1054    {
1055        BAPE_PathNode *pNode;
1056        BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1057        pNode = pConnection->pSink;
1058        BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1059        if ( NULL != pNode->removeInput )
1060        {
1061            pNode->removeInput(pNode, connector);
1062        }
1063        else
1064        {
1065            BERR_Code errCode;
1066            errCode = BAPE_PathNode_P_RemoveInput(pNode, connector);
1067            if ( errCode )
1068            {
1069                (void)BERR_TRACE(errCode);
1070                BDBG_ASSERT(errCode == BERR_SUCCESS);   /* No way to recover if this fails. */
1071                return;
1072            }
1073        }
1074        /* At this point, pConnector will be invalid */
1075    }
1076}
1077
1078static void BAPE_PathNode_P_FindConsumers(
1079    BAPE_PathNode *pNode,
1080    BAPE_PathNodeType type,
1081    unsigned subtype,
1082    bool checkSubtype,
1083    unsigned maxConsumers,
1084    unsigned *pNumFound,        /* [out] */
1085    BAPE_PathNode **pConsumers   /* [out] Must be an array of at least maxConsumers length */
1086    )
1087{
1088    unsigned pathNum;
1089    BAPE_PathConnection *pConnection;
1090
1091    BDBG_OBJECT_ASSERT(pNode, BAPE_PathNode);
1092
1093    for ( pathNum = 0; pathNum < pNode->numPaths; pathNum++ )
1094    {
1095        for ( pConnection = BLST_SQ_FIRST(&pNode->paths[pathNum].connector.connectionList);
1096              NULL != pConnection;
1097              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
1098        {
1099            BDBG_OBJECT_ASSERT(pConnection, BAPE_PathConnection);
1100            BDBG_OBJECT_ASSERT(pConnection->pSink, BAPE_PathNode);
1101
1102            if ( pConnection->pSink->type == type )
1103            {
1104                if ( false == checkSubtype || pConnection->pSink->subtype == subtype )
1105                {
1106                    if ( *pNumFound < maxConsumers )
1107                    {
1108                        pConsumers[*pNumFound] = pConnection->pSink;
1109                        *pNumFound = (*pNumFound)+1;
1110                    }
1111                    else
1112                    {
1113                        return;
1114                    }
1115                }
1116            }
1117            /* recurse */
1118            BAPE_PathNode_P_FindConsumers(pConnection->pSink, type, subtype, checkSubtype, maxConsumers, pNumFound, pConsumers);
1119        }
1120    }
1121}
1122
1123/***************************************************************************
1124Summary:
1125Search for consumers by a type
1126***************************************************************************/
1127void BAPE_PathNode_P_FindConsumersByType(
1128    BAPE_PathNode *pNode,
1129    BAPE_PathNodeType type,
1130    unsigned maxConsumers,
1131    unsigned *pNumFound,        /* [out] */
1132    BAPE_PathNode **pConsumers   /* [out] Must be an array of at least maxConsumers length */
1133    )
1134{
1135    BDBG_ASSERT(NULL != pNumFound);
1136    *pNumFound = 0;
1137    BAPE_PathNode_P_FindConsumers(pNode, type, 0, false, maxConsumers, pNumFound, pConsumers);
1138}
1139
1140/***************************************************************************
1141Summary:
1142Search for consumers by a type and subtype
1143***************************************************************************/
1144void BAPE_PathNode_P_FindConsumersBySubtype(
1145    BAPE_PathNode *pNode,
1146    BAPE_PathNodeType type,
1147    unsigned subtype,
1148    unsigned maxConsumers,
1149    unsigned *pNumFound,        /* [out] */
1150    BAPE_PathNode **pConsumers   /* [out] Must be an array of at least maxConsumers length */
1151    )
1152{
1153    BDBG_ASSERT(NULL != pNumFound);
1154    *pNumFound = 0;
1155    BAPE_PathNode_P_FindConsumers(pNode, type, subtype, true, maxConsumers, pNumFound, pConsumers);
1156}
1157
1158/***************************************************************************
1159Summary:
1160Determine if a node is a consumer from this node
1161***************************************************************************/
1162bool BAPE_PathNode_P_NodeIsConsumer(
1163    BAPE_PathNode *pSourceNode,
1164    BAPE_PathNode *pConsumerNode
1165    )
1166{
1167    unsigned pathNum;
1168    BAPE_PathConnection *pConnection;
1169
1170    BDBG_OBJECT_ASSERT(pSourceNode, BAPE_PathNode);
1171    BDBG_OBJECT_ASSERT(pConsumerNode, BAPE_PathNode);
1172
1173    for ( pathNum = 0; pathNum < pSourceNode->numPaths; pathNum++ )
1174    {
1175        for ( pConnection = BLST_SQ_FIRST(&pSourceNode->paths[pathNum].connector.connectionList);
1176              NULL != pConnection;
1177              pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
1178        {
1179            if ( pConnection->pSink == pConsumerNode )
1180            {
1181                return true;
1182            }
1183            if ( BAPE_PathNode_P_NodeIsConsumer(pConnection->pSink, pConsumerNode) )
1184            {
1185                return true;
1186            }
1187        }
1188    }
1189    return false;
1190}
1191
1192BAPE_PathConnection *BAPE_Connector_P_GetConnectionToSink(
1193    BAPE_Connector connector,
1194    BAPE_PathNode *pSink
1195    )
1196{
1197    BAPE_PathConnection *pConnection;
1198
1199    BDBG_OBJECT_ASSERT(connector, BAPE_PathConnector);
1200    BDBG_OBJECT_ASSERT(pSink, BAPE_PathNode);
1201
1202    for ( pConnection = BLST_SQ_FIRST(&connector->connectionList);
1203          NULL != pConnection;
1204          pConnection = BLST_SQ_NEXT(pConnection, downstreamNode) )
1205    {
1206        if ( pConnection->pSink == pSink )
1207        {
1208            return pConnection;
1209        }
1210    }
1211
1212    return NULL;    /* No connection found if we reach here */
1213}
1214
1215/***************************************************************************
1216Summary:
1217Returns a null-terminated string representation of a BAPE_PathNodeType enum.
1218***************************************************************************/
1219const char *BAPE_PathNode_P_PathNodeTypeToText( BAPE_PathNodeType pathNodeType )
1220{
1221    return ( pathNodeType == BAPE_PathNodeType_eDecoder         ?  "Decoder"        : 
1222             pathNodeType == BAPE_PathNodeType_ePlayback        ?  "Playback"       : 
1223             pathNodeType == BAPE_PathNodeType_eInputCapture    ?  "InputCapture"   : 
1224             pathNodeType == BAPE_PathNodeType_ePostProcessor   ?  "PostProcessor"  : 
1225             pathNodeType == BAPE_PathNodeType_eEncoder         ?  "Encoder"        : 
1226             pathNodeType == BAPE_PathNodeType_eMixer           ?  "Mixer"          : 
1227             pathNodeType == BAPE_PathNodeType_eEqualizer       ?  "Equalizer"      : 
1228             pathNodeType == BAPE_PathNodeType_eMuxOutput       ?  "MuxOutput"      : 
1229             pathNodeType == BAPE_PathNodeType_eMax             ?  "<eMax>"         : 
1230                                                                   "<Undefined>"    );
1231}
1232
1233
1234/***************************************************************************
1235Summary:
1236Do a depth-first, pre-order traversal of the downstream PathNodes.  The
1237specified callback will be called for each PathNode visited (except for the
1238starting PathNode)
1239***************************************************************************/
1240BERR_Code BAPE_PathNode_P_EnumerateUpstreamPathNodes( BAPE_PathNode  *pPathNode, int level, BAPE_PathNode_P_EnumerateCallback callback)
1241{
1242    BERR_Code errCode=BERR_SUCCESS;
1243    BAPE_PathConnection *pPathConnection;
1244    BAPE_PathConnector *pPathConnector;
1245    int index;
1246
1247    /* BDBG_MSG(("%*s%s : %d : pPathNode:%p  level:%d", level*4, "", __FUNCTION__, __LINE__ ,
1248                                                pPathNode, level ));   */
1249    for ( pPathConnection = BLST_S_FIRST(&pPathNode->upstreamList), index=0;
1250          pPathConnection != NULL;
1251          pPathConnection = BLST_S_NEXT(pPathConnection, upstreamNode), index++ )
1252    {
1253        /* BDBG_MSG(("%*s%s : %d : pPathNode:%p  Found pPathConnection:%p", level*4, "", __FUNCTION__, __LINE__ ,
1254                                                pPathNode, pPathConnection ));  */
1255        pPathConnector =  pPathConnection->pSource ;
1256        if ( NULL == pPathConnector )
1257        {
1258            return errCode;
1259        }
1260   
1261        if ( pPathConnector->pParent )
1262        {
1263            level++;
1264                BAPE_PathNode_P_EnumerateUpstreamPathNodes( pPathConnector->pParent, level, callback);
1265                (*callback)(pPathConnector->pParent, level, index);
1266            level--;
1267        }
1268    }
1269    return( errCode );
1270}
1271
1272
1273/***************************************************************************
1274Summary:
1275Do a depth-first, pre-order traversal of the upstream PathNodes.  The
1276specified callback will be called for each PathNode visited (except for the
1277starting PathNode)
1278***************************************************************************/
1279BERR_Code BAPE_PathNode_P_EnumerateDownstreamPathNodes( BAPE_PathNode  *pPathNode, int level, BAPE_PathNode_P_EnumerateCallback callback)
1280{
1281    BERR_Code errCode=BERR_SUCCESS;
1282    unsigned i;
1283    BSTD_UNUSED(level);
1284
1285    for ( i=0 ; i<BAPE_ConnectorFormat_eMax ; i++ )
1286    {
1287        BAPE_PathConnector *pPathConnector = &pPathNode->paths[i].connector;
1288        BAPE_PathConnection  *pPathConnection;
1289        int index;
1290
1291        /* BDBG_MSG(("%*s%s : %d : pPathNode:%p Found pPathConnector:%p  level:%d", level*4, "", __FUNCTION__, __LINE__ ,
1292                                                    pPathNode, pPathConnector, level ));  */
1293
1294        for ( pPathConnection = BLST_SQ_FIRST(&pPathConnector->connectionList), index=0;
1295              pPathConnection != NULL;
1296              pPathConnection = BLST_SQ_NEXT(pPathConnection, downstreamNode), index++ )
1297        {
1298            /* BDBG_MSG(("%*s%s : %d : pPathNode:%p pPathConnector:%p Found pPathConnection:%p  ", level*4, "", __FUNCTION__, __LINE__ ,
1299                                                    pPathNode, pPathConnector, pPathConnection ));  */
1300            if ( pPathConnection->pSink )
1301            {
1302                level++;
1303                (*callback)(pPathConnection->pSink, level, index);
1304                BAPE_PathNode_P_EnumerateDownstreamPathNodes( pPathConnection->pSink, level, callback);
1305                level--;
1306            }
1307        }
1308    }
1309    return( errCode);
1310}
1311
1312
Note: See TracBrowser for help on using the repository browser.