/*****************************************************************************
* @file    adsTelPbxMenu.c
*
* Contents: This file contains functions for the IP PBX Codelet menu.
*
* @par
* INTEL CONFIDENTIAL
* Copyright 2009 Intel Corporation All Rights Reserved.
* 
* The source code contained or described herein and all documents related to the
* source code ("Material") are owned by Intel Corporation or its suppliers or
* licensors. Title to the Material remains with Intel Corporation or its
* suppliers and licensors. The Material may contain trade secrets and proprietary
* and confidential information of Intel Corporation and its suppliers and
* licensors, and is protected by worldwide copyright and trade secret laws and
* treaty provisions. No part of the Material may be used, copied, reproduced,
* modified, published, uploaded, posted, transmitted, distributed, or disclosed
* in any way without Intels prior express written permission.
* No license under any patent, copyright, trade secret or other intellectual
* property right is granted to or conferred upon you by disclosure or delivery
* of the Materials, either expressly, by implication, inducement, estoppel or
* otherwise. Any license under such intellectual property rights must be
* express and approved by Intel in writing.
* 
* Include any supplier copyright notices as supplier requires Intel to use.
* Include supplier trademarks or logos as supplier requires Intel to use,
* preceded by an asterisk.
* An asterisked footnote can be added as follows: 
*   *Third Party trademarks are the property of their respective owners.
* 
* Unless otherwise agreed by Intel in writing, you may not remove or alter this
* notice or any other notice embedded in Materials by Intel or Intels suppliers
* or licensors in any way.
* 
*  version: ADS.L.1.1.0-160
******************************************************************************/

/****************************************************************************/
/******************* INCLUDES ***********************************************/
/****************************************************************************/

#include <setjmp.h>
#include "adsTel.h"
#include "adsTelRTP.h"
#include "adsTelPbx.h"
#include "adsTelCommon.h"



/****************************************************************************/
/******************* TYPEDEFS ***********************************************/
/****************************************************************************/



/*menu function type definition*/
typedef void (*AdsPbxMenuFunc) (void);

typedef struct
{
    char *name;                      /* menu item name */
    AdsPbxMenuFunc menuFunc;          /* Service routine */
} AdsPbxMenu_t;


/****************************************************************************/
/******************* STATIC FUNCTION DECLARATIONS ***************************/
/****************************************************************************/

/*menu functions*/
void adsPbxSetupCall (void);
void adsPbxSetupMaxIpCalls (void);
void adsPbxExit(void);
void adsPbxAllCallTeardown(void);
void adsPbxCallTeardown(void);
void adsEpSetParameter (void);
void adsEpGetParameters (void);


/*Create a call connection*/
AdsTelStatus_t adsPbxCallCreate(unsigned int callId,
                             unsigned int numCons,
                             unsigned int *pConList,
                             char         *pIpAddr);

/*Destroy a call connection*/
AdsTelStatus_t adsPbxCallDestroy(unsigned int callId);

/*set a component paramter*/
AdsTelStatus_t setParam(unsigned int epNumber, unsigned int pipeDir,
                        unsigned int compId,   unsigned int numParams);

/*get a component's paramter values*/
AdsTelStatus_t getParams(unsigned int epNumber, unsigned int pipeDir,
                         unsigned int compId);

/*Function used in the EP only, will simply return when call
* from the callback function on a codec chamge*/
void configureCallIPtoPCM(unsigned int lineNum,
                            unsigned int pcmNum);


/****************************************************************************/
/******************* GLOBAL VARIABLES ***************************************/
/****************************************************************************/

/*Menu jump location*/
jmp_buf atPrtMenu;


/* define the menu table */
AdsPbxMenu_t adsPbxMenu[] =
{
/*      item name                     menuFunc
    -----------------------------------------------------*/
    { "Print Menu",                NULL},
    { "Setup Call",                adsPbxSetupCall},
    { "Setup Max IP Calls",        adsPbxSetupMaxIpCalls},
    { "Teardown Call",             adsPbxCallTeardown},
    { "Teardown All Calls",        adsPbxAllCallTeardown},
    { "Set Parameter",             adsEpSetParameter},
    { "Print Component Paramters", adsEpGetParameters},
    { "Exit",                      adsPbxExit},
    { NULL,                        NULL}
};

/*call tracking array*/
static AdsTelRtrHandle_t callList[MAX_CALLS_SUPPORTED]; /*(max IP)/2*/

/*Ep tracking array*/
AdsTelDesc_t epList[MAX_EP_SUPPORTED];

/*transaction ID*/
static unsigned int transId = 0;

/*array to hold parameter numbers for set parameter calls*/
unsigned int paramNums[ADS_TEL_MAX_PARAMS];

/*array to hold parameter values for set parameter calls*/
int paramVals[ADS_TEL_MAX_PARAMS];


/****************************************************************************/
/******************* FUNCTION DEFINITIONS ***********************************/
/****************************************************************************/

/*******************************************************
 *Menu option to setup a call
 *******************************************************/
void adsPbxSetupCall(void)
{
    char ipAddr[ADS_MAX_EP_CONS][ADS_TEL_CODELET_STRLEN];
    unsigned int callId = 0;
    unsigned int addEp = 1;
    unsigned int numCons = 0;
    unsigned int i = 0;
    unsigned int epCons[ADS_MAX_EP_CONS];
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;

    /*get the call number to use*/
    status = adsRefAppGetNum("\nEnter the call ID: ", &callId, NULL);

    /*verify that the call number is valid*/
    if ((status != ADS_TEL_STATUS_SUCCESS) || (callId >= MAX_CALLS_SUPPORTED))
    {
        printf("\nERROR:%s: Call ID %u is invalid\n",
               __FUNCTION__, callId);
        return;
    }

    /*check that the call ID is not already in use*/
    if (callList[callId] != MAX_CALLS_SUPPORTED)
    {
        printf("\nERROR:%s: Call ID is already in use\n",
               __FUNCTION__);
        return;
    }

    while (addEp == 1)
     {

        status = adsRefAppGetNum("\nEnter the endpoint number: ",
                                &epCons[numCons], NULL);

        /*check that the endpoint number is valid*/
        if ((status != ADS_TEL_STATUS_SUCCESS) ||
            (epCons[numCons] >= MAX_EP_SUPPORTED))
        {
            printf("\nERROR:%s: Input is not a valid endpoint number\n",
                   __FUNCTION__);
            return;
        }


        /*check that the endpoint is not already in use*/
        if (epList[epCons[numCons]].epHandle != MAX_EP_SUPPORTED)
        {
            printf("\nERROR:%s: endpoint is already in use\n",
                   __FUNCTION__);
            return;
        }

        /*get the remote IP Address*/
        i = adsRefAppGetStr("\nEnter the IP Address of the remote party: ",
                            ipAddr[numCons]);

        /*Get the Codec to use*/
        printf("\nPass Through Mode: %u\n", ADS_TEL_PARAM_CODER_TYPE_PASSTHRU);
        printf("G711 U Law: %u\n", ADS_TEL_PARAM_CODER_TYPE_G711MU_10MS);
        printf("G711 A law: %u\n", ADS_TEL_PARAM_CODER_TYPE_G711A_10MS);
        printf("G729A:   %u\n", ADS_TEL_PARAM_CODER_TYPE_G729A);
        printf("G723:    %u\n", ADS_TEL_PARAM_CODER_TYPE_G723);
        printf("G722_64: %u\n", ADS_TEL_PARAM_CODER_TYPE_G722_64);
        printf("G722_56: %u\n", ADS_TEL_PARAM_CODER_TYPE_G722_56);
        printf("G722_48: %u\n", ADS_TEL_PARAM_CODER_TYPE_G722_48);
        printf("G726_40: %u\n", ADS_TEL_PARAM_CODER_TYPE_G726_40);
        printf("G726_32: %u\n", ADS_TEL_PARAM_CODER_TYPE_G726_32);
        printf("G726_24: %u\n", ADS_TEL_PARAM_CODER_TYPE_G726_24);
        printf("G726_16: %u\n", ADS_TEL_PARAM_CODER_TYPE_G726_16);
        printf("G729_1:  %u\n", ADS_TEL_PARAM_CODER_TYPE_G729_1);
        printf("G722_1:  %u\n", ADS_TEL_PARAM_CODER_TYPE_G722_1);
        status = adsRefAppGetNum("\nEnter the codec to use:",
                                &(epList[epCons[numCons]].codec), NULL);
        if ((status != ADS_TEL_STATUS_SUCCESS) ||
       (epList[epCons[numCons]].codec < ADS_TEL_PARAM_CODER_TYPE_G711MU_10MS)||
       (epList[epCons[numCons]].codec > ADS_TEL_PARAM_CODER_TYPE_G726_16) ||
       (epList[epCons[numCons]].codec == ADS_TEL_PARAM_CODER_TYPE_G723))
        {
            printf("\nERROR:%s: Invalid Codec entered\n", __FUNCTION__);
            return;
        }


        /*set the de_codec at the same value as the codec*/
        epList[epCons[numCons]].de_codec = epList[epCons[numCons]].codec;

        /*get the MFPP value*/
        status = adsRefAppGetNum("\nEnter the number of frames per packet:",
                    &(epList[epCons[numCons]].mfppVal), NULL);
        if ((epList[epCons[numCons]].mfppVal < ADS_TEL_MIN_MFPP) ||
            (epList[epCons[numCons]].mfppVal > ADS_TEL_MAX_MFPP) ||
            (status != ADS_TEL_STATUS_SUCCESS))
        {
            printf("\nERROR:%s: Invalid mfpp size\n", __FUNCTION__);
            return;
        }

        numCons++;

        /*If the max numer of connections is already connected then exit*/
        if (numCons == ADS_MAX_EP_CONS)
        {
            break;
        }

        printf("\nAdd another endpoint (%u=Yes %u=No):", YES, NO);
        status = adsRefAppGetNum(NULL, &addEp, NULL);
        if (((addEp != YES)&&(addEp != NO))
                       || (status != ADS_TEL_STATUS_SUCCESS))
        {
            printf("\nERROR:%s Invalid input\n", __FUNCTION__);
            addEp = NO;
            /* Do not return here, assume it is a NO */
        }
    }


    /*Setup the call based on the provided information*/
    adsPbxCallCreate(callId, numCons, epCons, ipAddr[0]);


    return;
}


/**********************************************************************
 * This function will set up the max IP calls allowed in the following
 * format. RTP Port number match the EP number. Inbound and outbound
 * RTP port numbers are the same for an endpoint.
 * EP 0  <-> EP 1  (RTP 6000 <-> RTP 6002)
 * EP 2  <-> EP 3
 * EP 4  <-> EP 5
 *   .    .          .
 *   .    .          .
 *   .    .          .
 * EP MAX_CALLS_SUPPORTED-2  <-> EP MAX_CALLS_SUPPORTED-1
 **********************************************************************/
void adsPbxSetupMaxIpCalls(void)
{
    char ipAddr[TWO_PARTY_CALL][ADS_TEL_CODELET_STRLEN];
    unsigned int epCons[TWO_PARTY_CALL];
    unsigned int i = 0;
    unsigned int codec = 0;
    unsigned int mfppVal = 0;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;

    /*Enter the remote IP address*/
    i = adsRefAppGetStr("\nEnter the IP Address of the remote party: ",
                        ipAddr[0]);

    /*Get the Codec to use*/
    printf("\nPass Through Mode: %u\n", ADS_TEL_PARAM_CODER_TYPE_PASSTHRU);
    printf("G711 U Law: %u\n", ADS_TEL_PARAM_CODER_TYPE_G711MU_10MS);
    printf("G711 A law: %u\n", ADS_TEL_PARAM_CODER_TYPE_G711A_10MS);
    printf("G729A:   %u\n", ADS_TEL_PARAM_CODER_TYPE_G729A);
    printf("G723:    %u\n", ADS_TEL_PARAM_CODER_TYPE_G723);
    printf("G722_64: %u\n", ADS_TEL_PARAM_CODER_TYPE_G722_64);
    printf("G722_56: %u\n", ADS_TEL_PARAM_CODER_TYPE_G722_56);
    printf("G722_48: %u\n", ADS_TEL_PARAM_CODER_TYPE_G722_48);
    printf("G726_40: %u\n", ADS_TEL_PARAM_CODER_TYPE_G726_40);
    printf("G726_32: %u\n", ADS_TEL_PARAM_CODER_TYPE_G726_32);
    printf("G726_24: %u\n", ADS_TEL_PARAM_CODER_TYPE_G726_24);
    printf("G726_16: %u\n", ADS_TEL_PARAM_CODER_TYPE_G726_16);
    printf("G729_1:  %u\n", ADS_TEL_PARAM_CODER_TYPE_G729_1);
    printf("G722_1:  %u\n", ADS_TEL_PARAM_CODER_TYPE_G722_1);
    status = adsRefAppGetNum("\nEnter the codec to use:", &codec, NULL);
    if ((status != ADS_TEL_STATUS_SUCCESS) ||
           (codec < ADS_TEL_PARAM_CODER_TYPE_G711MU_10MS) ||
           (codec > ADS_TEL_PARAM_CODER_TYPE_G726_16) ||
           (codec == ADS_TEL_PARAM_CODER_TYPE_G723))
    {
        printf("\nERROR:%s: Invalid Codec entered\n", __FUNCTION__);
        return;
    }

    status = adsRefAppGetNum("\nEnter the number of frames per packet:",
                &mfppVal, NULL);
    if ((mfppVal < ADS_TEL_MIN_MFPP) || (mfppVal > ADS_TEL_MAX_MFPP)
        || (status != ADS_TEL_STATUS_SUCCESS))
    {
        printf("\nERROR:%s: Invalid mfpp size\n", __FUNCTION__);
        return;
    }

    /*all endpoints will use the same remote address*/
    strcpy(ipAddr[1],ipAddr[0]);

    /* Setup the calls:
     * Calls: 0,1,2,3 etc.
     * EPs (0,1), (2,3), (4,5), (6,7), etc. */
    for (i=0; i<MAX_CALLS_SUPPORTED; i++)
    {
        /*check that the call ID is not already in use*/
        if (callList[i] != MAX_CALLS_SUPPORTED)
        {
            printf("\nERROR:%s: Call ID %u is already in use\n",
                   __FUNCTION__, callList[i]);
            continue;
        }

        /*check that the endpoint are not already being used*/
        if ((epList[i * RTP_PORT_MULTIPLIER].epHandle != MAX_EP_SUPPORTED) ||
            (epList[(i*RTP_PORT_MULTIPLIER)+1].epHandle != MAX_EP_SUPPORTED))
        {
            printf("\nERROR:%s: Call %u failed - Endpoints in use\n",
                   __FUNCTION__, i);
            continue;
        }

        /*set the codec and MFPP*/
        epList[i * RTP_PORT_MULTIPLIER].codec = codec;
        epList[(i*RTP_PORT_MULTIPLIER)+1].codec = codec;
        epList[i * RTP_PORT_MULTIPLIER].de_codec = codec;
        epList[(i*RTP_PORT_MULTIPLIER)+1].de_codec = codec;
        epList[i * RTP_PORT_MULTIPLIER].mfppVal = mfppVal;
        epList[(i*RTP_PORT_MULTIPLIER)+1].mfppVal = mfppVal;

        /*set the endpoints to connect*/
        epCons[0] = i * RTP_PORT_MULTIPLIER;
        epCons[1] = (i * RTP_PORT_MULTIPLIER) + 1;

        adsPbxCallCreate(i, TWO_PARTY_CALL, epCons, ipAddr[0]);
    }

    return;
}


/*******************************************************
 *Menu option to tear down a call
 *******************************************************/
void adsPbxCallTeardown(void)
{
    unsigned int callId = 0;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;
    /*get the call number to use*/
    status = adsRefAppGetNum("\nEnter the call number to teardown: ", &callId,
                NULL);

    /*verify that the call number is valid*/
    if ((status != ADS_TEL_STATUS_SUCCESS) || (callId >= MAX_CALLS_SUPPORTED))
    {
        printf("\nERROR:%s: Call ID is invalid\n",
               __FUNCTION__);
        return;
    }

    if (callList[callId] == MAX_CALLS_SUPPORTED)
    {
        printf("\nERROR:%s: Call is not set up\n", __FUNCTION__);
        return;
    }

    /*Teardown the call*/
    if (ADS_TEL_STATUS_SUCCESS != adsPbxCallDestroy(callId))
    {
        printf("\nERROR:%s: Failed to teardown call\n", __FUNCTION__);
    }

    return;
}


/*******************************************************
 *Menu option to tear down all calls
 *******************************************************/
void adsPbxAllCallTeardown(void)
{
    unsigned int i = 0;


    /*teardown all IP calls*/
    for (i=0; i<MAX_CALLS_SUPPORTED; i++)
    {
        if (callList[i] != MAX_CALLS_SUPPORTED)
        {
            adsPbxCallDestroy(i);
        }

    }

    return;
}


/*******************************************************
 *Menu option to set a parameter
 *******************************************************/
void adsEpSetParameter(void)
{
    unsigned int inpStrLen = 0;
    unsigned int pipeDir = 0;
    unsigned int compId = 0;
    unsigned int option = 0;
    unsigned int epNum = 0;
    unsigned int i = 0;
    unsigned int j = 0;
    char inpEpStr[ADS_TEL_CODELET_STRLEN];
    char tempStr[ADS_TEL_CODELET_STRLEN];
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;

    /*get the endpoint IDs*/
    printf("\nEnter the endpoint numbers(0-%d) delimited by comma"
           "\nin the format x,y,z OR enter %d for all channels: ",
           MAX_EP_SUPPORTED-1, MAX_EP_SUPPORTED);
    inpStrLen = adsRefAppGetStr(NULL, inpEpStr);

    /*get the pipeline direction*/
    printf("\nEnter the pipeline Direction(Inbound=%u, Outbound=%u):",
           ADS_TEL_PIPE_DIR_IN, ADS_TEL_PIPE_DIR_OUT);
    status = adsRefAppGetNum(NULL, &pipeDir, NULL);
    if (((pipeDir != ADS_TEL_PIPE_DIR_OUT)&&(pipeDir != ADS_TEL_PIPE_DIR_IN))
            || (status != ADS_TEL_STATUS_SUCCESS))
    {
        printf("\nERROR:%s: Invalid pipeline direction entered\n",
                __FUNCTION__);
        return;
    }

    /*get the component ID*/
    status = adsRefAppGetNum("\nEnter the component ID(position in pipeline):",
                                &compId, NULL);
    if ((compId >= ADS_MAX_COMPS_PER_PIPE) ||
        (status != ADS_TEL_STATUS_SUCCESS))
    {
        printf("\nERROR:%s: Invalid Component ID entered\n", __FUNCTION__);
        return;
    }

    /*get the paramter number*/
    status = adsRefAppGetNum("\nEnter the parameter number:", &paramNums[0],
                    NULL);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Invalid parameter number\n", __FUNCTION__);
    }

    /*get the paramter value*/
    status = adsRefAppGetNum("\nEnter the parameter value:",
                    NULL, &paramVals[0]);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Invalid parameter value\n", __FUNCTION__);
    }

    /*extract the endpoint IDs from the input string and set the parameters*/
    do
    {
        /*copy the input string into a temporary string until either a , is
          encountered or the end of the string is reached*/
        tempStr[i++]=inpEpStr[j];
        if( (inpEpStr[j]==',') || (j==inpStrLen) )
        {
            if(j==inpStrLen)
            {
              tempStr[i]='\0';
            }
            else
            {
              tempStr[i-1]='\0';
            }

            /*convert the integer string to an integer
              and set the parameter*/
            option=atoi(tempStr);
            i=0;
            if(option < MAX_EP_SUPPORTED)
            {
                setParam(option, pipeDir, compId, NUM_PARAMS_1);
            }
            else
            {

                /*if the all channels option is selected then set the paramater
                  for all the channels*/
                if(option == MAX_EP_SUPPORTED)
                {
                    for(epNum=0; epNum<MAX_EP_SUPPORTED; epNum++)
                    {
                        setParam(epNum, pipeDir, compId, NUM_PARAMS_1);
                    }
                    break;
                }
                else
                {
                    printf("\nERROR:%s: Invalid channel number: %u\n",
                           __FUNCTION__, option);
                }
            }
        }
        j++;
    }while(j<=inpStrLen);

    return;
}


/*******************************************************
 *Menu option to get a components parameter values
 *******************************************************/
void adsEpGetParameters(void)
{
    unsigned int inpStrLen = 0;
    unsigned int pipeDir = 0;
    unsigned int compId = 0;
    unsigned int option = 0;
    unsigned int epNum = 0;
    unsigned int i = 0;
    unsigned int j = 0;
    char inpEpStr[ADS_TEL_CODELET_STRLEN];
    char tempStr[ADS_TEL_CODELET_STRLEN];
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;


    /*get the endpoint IDs*/
    printf("\nEnter the endpoint numbers(0-%d) delimited by comma"
           "\nin the format x,y,z OR enter %d for all channels: ",
           MAX_EP_SUPPORTED-1, MAX_EP_SUPPORTED);
    inpStrLen = adsRefAppGetStr(NULL, inpEpStr);

    /*get the pipeline direction*/
    printf("\nEnter the pipeline Direction(Inbound=%u, Outbound=%u):",
           ADS_TEL_PIPE_DIR_IN, ADS_TEL_PIPE_DIR_OUT);
    status = adsRefAppGetNum(NULL, &pipeDir, NULL);
    if (((pipeDir != ADS_TEL_PIPE_DIR_OUT)&& (pipeDir != ADS_TEL_PIPE_DIR_IN))
            || (status != ADS_TEL_STATUS_SUCCESS))
    {
        printf("\nERROR:%s: Invalid pipeline direction entered\n",
               __FUNCTION__);
        return;
    }

    /*get the component ID*/
    status = adsRefAppGetNum("Enter the component ID(position in pipeline):",
                               &compId, NULL);
    if ((compId >= ADS_MAX_COMPS_PER_PIPE) ||
        (status != ADS_TEL_STATUS_SUCCESS))
    {
        printf("\nERROR:%s: Invalid Component ID entered\n", __FUNCTION__);
        return;
    }

    /*extract the endpoint IDs from the input string and get the parameters*/
    do
    {
        /*copy the input string into a temporary string until either a , is
          encountered or the end of the string is reached*/
        tempStr[i++]=inpEpStr[j];
        if( (inpEpStr[j]==',') || (j==inpStrLen) )
        {
            if(j==inpStrLen)
            {
              tempStr[i]='\0';
            }
            else
            {
              tempStr[i-1]='\0';
            }

            /*convert the integer string to an integer
              and get the parameters*/
            option=atoi(tempStr);
            i=0;
            if(option < MAX_EP_SUPPORTED)
            {
                getParams(option, pipeDir, compId);
            }
            else
            {

                /*if the all channels option is selected then get the paramaters
                  for all the channels*/
                if(option == MAX_EP_SUPPORTED)
                {
                    for(epNum=0; epNum<MAX_EP_SUPPORTED; epNum++)
                    {
                        getParams(epNum, pipeDir, compId);
                    }
                    break;
                }
                else
                {
                    printf("\nERROR:%s: Invalid channel number: %u\n",
                           __FUNCTION__, option);
                }
            }
        }
        j++;
    }while(j<=inpStrLen);

    return;

}

/*******************************************************
 *Menu option to exit the application
 *******************************************************/
void adsPbxExit(void)
{
    /*tear down all calls*/
    adsPbxAllCallTeardown();

    return;
}


/*******************************************************
 *Set a component paramter
 *******************************************************/
AdsTelStatus_t setParam(unsigned int epNumber, unsigned int pipeDir,
                        unsigned int compId,   unsigned int numParams)
{
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;


    /*check that the endpoint is configured*/
    if (epList[epNumber].epHandle == MAX_EP_SUPPORTED)
    {
        return ADS_TEL_STATUS_FAIL;
    }

    status = adsTelEpCompParamsSet(&transId,
                                   epList[epNumber].epHandle,
                                   pipeDir,
                                   compId,
                                   numParams,
                                   paramNums,
                                   paramVals);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelEpCompParamsSet failed with error"
               " code %i\n", __FUNCTION__, status);
        return status;
    }

    return ADS_TEL_STATUS_SUCCESS;
}


/*******************************************************
 *Get a component's paramter values
 *******************************************************/
AdsTelStatus_t getParams(unsigned int epNumber, unsigned int pipeDir,
                         unsigned int compId)
{
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;



    /*check that the endpoint is configured*/
    if (epList[epNumber].epHandle == MAX_EP_SUPPORTED)
    {
        return ADS_TEL_STATUS_FAIL;
    }

    status = adsTelEpCompParamsGet(&transId,
                                   epList[epNumber].epHandle,
                                   pipeDir,
                                   compId);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s:  Call to adsTelEpCompParamsGet failed with error"
               " code %i\n", __FUNCTION__, status);
        return status;
    }

    return ADS_TEL_STATUS_SUCCESS;
}


/*******************************************************
 *Initialise tracking arrays
 *******************************************************/
void initPbxTrackingArrays(void)
{
    unsigned int i = 0;

    for (i=0; i<MAX_CALLS_SUPPORTED; i++)
    {
        callList[i] = MAX_CALLS_SUPPORTED;
    }

    for (i=0; i<MAX_EP_SUPPORTED; i++)
    {
        epList[i].callId = MAX_CALLS_SUPPORTED;
        epList[i].epHandle = MAX_EP_SUPPORTED;
    }
}


/*******************************************************
 *Create a call connection
 *******************************************************/
AdsTelStatus_t adsPbxCallCreate(unsigned int callId,
                             unsigned int numCons,
                             unsigned int *pConList,
                             char         *pIpAddr)
{
    unsigned int i = 0;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;


    /*setup the call*/
    status = adsTelRouterCreate(&transId, ADS_TEL_CALL_PRIOR_NORMAL,
                                ADS_TEL_RTR_NORMAL, &callList[callId]);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelRouterCreate failed with error"
               " code %i\n", __FUNCTION__, status);
        return ADS_TEL_STATUS_FAIL;
    }

    /*create the endpoints*/
    for (i=0; i<numCons; i++)
    {
        /*Set up the endpoint*/
        status = adsTelEpCreate(&transId,
                                ADS_TEL_PIPE_IP_IN,
                                ADS_TEL_PIPE_IP_OUT,
                                0,
                                (adsTelEpDataCb_t)ads_ip_inbound_cb,
                                (adsTelEpDataCb_t)ads_ip_outbound_cb,
                                ADS_TEL_CALL_PRIOR_NORMAL,
                                callList[callId],
                                &(epList[*(pConList+i)].epHandle));

        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Call to adsTelEpCreate failed with error"
                   " code %i\n", __FUNCTION__, status);
            return ADS_TEL_STATUS_FAIL;
        }

        /*configure the encoder with the codec and MFPP settings*/
        paramNums[0] = ADS_TEL_PARMID_ENC_CTYPE;
        paramVals[0] = epList[*(pConList+i)].codec;

        paramNums[1] = ADS_TEL_PARMID_ENC_MFPP;
        paramVals[1] = epList[*(pConList+i)].mfppVal;

        status = setParam(*(pConList+i), ADS_TEL_PIPE_DIR_OUT,
                          IP_OUT_ENC, NUM_PARAMS_2);

        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure Encoder\n", __FUNCTION__);
        }


        /*configure TG for WB if neccesary*/
        if ((epList[*(pConList+i)].codec >= ADS_TEL_PARAM_CODER_TYPE_G722_64) &&
            (epList[*(pConList+i)].codec <= ADS_TEL_PARAM_CODER_TYPE_G722_48))
        {
            paramVals[0] = ADS_TEL_PARAM_WB;
        }
        else
        {
            paramVals[0] = ADS_TEL_PARAM_NB;
        }

        /*configure the Tone Generator*/
        paramNums[0] = ADS_TEL_PARMID_TG_PCM_MODE;


        status = setParam(*(pConList+i), ADS_TEL_PIPE_DIR_IN,
                          IP_IN_TG, NUM_PARAMS_1);

        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure TG\n", __FUNCTION__);
        }

        /*configure the ALC*/
        paramNums[0] = ADS_TEL_PARMID_AGC_ENABLE;
        paramVals[0] = ADS_TEL_PARAM_OFF;

        status = setParam(*(pConList+i), ADS_TEL_PIPE_DIR_IN,
                          IP_IN_ALC, NUM_PARAMS_1);

        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure ALC\n", __FUNCTION__);
        }

        /*Set the call ID*/
        epList[*(pConList+i)].callId = callId;

        /*Setup the RTP Stream*/
        if (ADS_TEL_STATUS_SUCCESS != adsTelRtpSessionCreate(
                        (*(pConList+i))*RTP_PORT_MULTIPLIER, /*local chan*/
                        pIpAddr+(ADS_TEL_CODELET_STRLEN*i),  /*remote IP*/
                        (*(pConList+i))*RTP_PORT_MULTIPLIER))/*remote chan*/
        {
            printf("\nERROR:%s: Failed to set up the RTP session for"
                   " endpoint %u\n", __FUNCTION__, *(pConList+i));
            return ADS_TEL_STATUS_FAIL;
        }

        /*Connect the Endpoint inbound and outbound pipelines*/
        status = adsTelEpConStatusSet(&transId,
                                      epList[*(pConList+i)].epHandle,
                                      ADS_TEL_EP_CONN_BOTH);

        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Call to adsTelEpConStatusSet failed with error"
                   " code %i\n", __FUNCTION__, status);
            return ADS_TEL_STATUS_FAIL;
        }


    } /*num cons loop*/

    return status;

}


/*******************************************************
 *Destroy a call connection
 *******************************************************/
AdsTelStatus_t adsPbxCallDestroy(unsigned int callId)
{
    unsigned int i = 0;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;


    /*Destroy all the endpoints connected to the call*/
    for (i=0; i<MAX_EP_SUPPORTED; i++)
    {
        if (epList[i].callId == callId)
        {
            /*Disconnect the Endpoint inbound and outbound pipelines*/
            status = adsTelEpConStatusSet(&transId,
                                          epList[i].epHandle,
                                          ADS_TEL_EP_CONN_NONE);

            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to adsTelEpConStatusSet failed with"
                       " error code %i\n", __FUNCTION__, status);
                return ADS_TEL_STATUS_FAIL;
            }

            /*Destroy the endpoint endpoint*/
            status = adsTelEpDestroy(&transId,
                                     epList[i].epHandle);

            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to adsTelEndPtDestroy failed with"
                       "error code %i\n", __FUNCTION__, status);
                return ADS_TEL_STATUS_FAIL;
            }

            /*Teardown the RTP Stream*/
            if (ADS_TEL_STATUS_SUCCESS !=
                adsTelRtpSessionDestroy(i*RTP_PORT_MULTIPLIER))
            {
                printf("\nERROR:%s: Failed to tear down the RTP session for"
                       " endpoint %u\n", __FUNCTION__, i);
                return ADS_TEL_STATUS_FAIL;
            }

            /*reset the tracking array*/
            epList[i].callId = MAX_CALLS_SUPPORTED;
            epList[i].epHandle = MAX_EP_SUPPORTED;
        }
    }

    /*teardown the call router*/
    status = adsTelRouterDestroy(&transId, callList[callId]);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelRouterDestroy failed with error"
               " code %i\n", __FUNCTION__, status);
        return ADS_TEL_STATUS_FAIL;
    }

    /*reset the call tracking array*/
    callList[callId] = MAX_CALLS_SUPPORTED;

    return ADS_TEL_STATUS_SUCCESS;
}


/*******************************************
 * demo menu main function
 *******************************************/
int adsRefAppDemoMenu(void)
{
    unsigned int selectedItem=0;
    int lastItem = -1;
    int i;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;

    selectedItem = setjmp(atPrtMenu);

    do
    {
        selectedItem=0;
       /* print the test menu */
        printf( "\n----------------------------------------\n"
                  "-      IP Endpoint Demo Menu          -\n"
                  "----------------------------------------\n");

        for (i = 0; adsPbxMenu[i].name != NULL; i++)
        {
            printf("%3d - %s\n", i, adsPbxMenu[i].name);
        }
        lastItem = i - 1;

        /* select a menu item */
        status = adsRefAppGetNum("Please select test item - ", &selectedItem,
                    NULL);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            /* Invalid input Don't need to print*/
            continue;
        }

        /* skip if not a menu item */
        if (selectedItem >= lastItem || !selectedItem)
        {
          continue;
        }

        adsPbxMenu[selectedItem].menuFunc();

    } while(selectedItem != lastItem);

    return ADS_TEL_STATUS_SUCCESS;
}

/*simply return, as called by convertEpToRtp in asdTelUtils, but not needed
* for the pbx*/
void configureCallIPtoPCM(unsigned int lineNum,
                            unsigned int pcmNum)
{
    return;
}




