/****************************************************************************
* @file    adsTelEpMenu.c
*
* Contents: This file contains functions for the 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 "adsTelEp.h"
#include "adsTel.h"
#include "adsTelCommon.h"


/****************************************************************************/
/******************* TYPE DEFINITIONS ***************************************/
/****************************************************************************/

/*External IP Lines*/
typedef enum{
    ADS_EX_LINE_0 = 0,
    ADS_EX_LINE_1,
    ADS_EX_LINE_INVALID,
} AdsEpExLine_t;

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

/*Menu function storage*/
typedef struct
{
    char *name;                      /* menu item name */
    AdsEpMenuFunc menuFunc;          /* Service routine */
} AdsEpMenu_t;


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

/*menu functions*/
void adsEpOffHook (void);
void adsEpOnHook (void);
void adsEpMakeCall (void);
void adsEpSwitchLine (void);
void adsEp3WayCall (void);
void adsEpRevert2WayCall (void);
void adsEpSendDTMF (void);
void adsEpSetParameter (void);
void adsEpGetParameters (void);
void adsEpExit(void);


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

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


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

/*Call Router ID*/
static AdsTelRtrHandle_t callRouter;

/*PCM endpoint handles*/
AdsTelEpHandle_t pcmEp[MAX_PCM_LINES_SUPPORTED];

/*information structure for external lines*/
AdsTelDesc_t  epList[MAX_IP_LINES_SUPPORTED];

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

/*The ALSA rate for each channel*/
static unsigned int alsaRate[MAX_PCM_LINES_SUPPORTED];

/*The ALSA format for each channel*/
static unsigned int alsaFormat[MAX_PCM_LINES_SUPPORTED];

/*Menu jump location*/
jmp_buf atPrtMenu;

/*The external line that is currently connected*/
static AdsEpExLine_t curActLine = ADS_EX_LINE_INVALID;

/* define the menu table */
AdsEpMenu_t adsEpMenu[] =
{
/*      item name                     menuFunc
    -----------------------------------------------------*/
    { "Print Menu",                NULL},
    { "Off Hook",                  adsEpOffHook},
    { "On Hook",                   adsEpOnHook},
    { "Make A Call",               adsEpMakeCall},
    { "Switch Line",               adsEpSwitchLine},
    { "3 Way Call",                adsEp3WayCall},
    { "Revert to 2 Way Call",      adsEpRevert2WayCall},
    { "Send DTMF String",          adsEpSendDTMF},
    { "Set Parameter",             adsEpSetParameter},
    { "Print Component Paramters", adsEpGetParameters},
    { "Exit",                      adsEpExit},
    { NULL,                        NULL}
};

/*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];

/*hold music player handles*/
AdsTelMediaHandle_t nbHoldHandle;
AdsTelMediaHandle_t wbHoldHandle;


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

/*******************************************************
 *Menu option to take the application off hook
 *******************************************************/
void adsEpOffHook(void)
{
    int i = 0;
    unsigned int toneID = RFC_TID_DIAL;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;
    char plugHw[ADS_TEL_CODELET_STRLEN];

    /*Do nothing if the phone is already off hook*/
    if ((curActLine != ADS_EX_LINE_INVALID))
    {
        printf("Info - Phone is already off hook\n");
        return;
    }

    /*Reset External Line states*/
    for (i=0; i<MAX_IP_LINES_SUPPORTED; i++)
    {
        epList[i].state = ADS_LINE_STATE_DIAL;
    }

    curActLine = ADS_EX_LINE_0;

    /*get the ALSA hardware ID*/
    i = adsRefAppGetStr("\nEnter the ALSA hardware ID in the form"
                        " \"plughw:x,x\": ", plugHw);


    /*Set Up ALSA*/
    for (i=0; i<MAX_PCM_LINES_SUPPORTED; i++)
    {
        if (ADS_TEL_STATUS_SUCCESS != adsTelAlsaOpenChan(i,
                                        plugHw,
                                        alsaFormat[i],
                                        alsaRate[i]))
        {
            printf("\nERROR:%s: Failed to set up ALSA for channel %u\n",
                   __FUNCTION__, i);
            return;
        }
    }

    /*Set up the router*/
    status = adsTelRouterCreate(&transId, ADS_TEL_CALL_PRIOR_NORMAL,
                                ADS_TEL_RTR_NORMAL, &callRouter);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelRouterCreate failed with error"
               " code %i\n", __FUNCTION__, status);
        return;
    }

    /*Set up the PCM endpoint*/
    status = adsTelEpCreate(&transId,
                            ADS_TEL_PIPE_PCM_IN,
                            ADS_TEL_PIPE_PCM_OUT,
                            ALSA_PCM_DATA_TYPE,
                            (adsTelEpDataCb_t)ads_inbound_cb,
                            (adsTelEpDataCb_t)ads_outbound_cb,
                            ADS_TEL_CALL_PRIOR_NORMAL,
                            callRouter,
                            &pcmEp[PCM_MAIN_LINE]);

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

    /*Connect the Endpoint inbound and outbound pipelines*/
    status = adsTelEpConStatusSet(&transId,
                                  pcmEp[PCM_MAIN_LINE],
                                  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;
    }

    /*Play dial tone on PCM endpoint*/
    status = adsTelEpTonePlay(&transId,
                              pcmEp[PCM_MAIN_LINE],
                              ADS_TEL_PIPE_DIR_OUT, /*PCM outbound direction*/
                              PCM_OUT_TG, /*comp ID*/
                              1, /*num tones*/
                              &toneID);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelEpTonePlay failed with error"
               " code %i\n", __FUNCTION__, status);
        return;
    }

    return;
}


/*******************************************************
 *Menu option to place the application on hook
 *******************************************************/
void adsEpOnHook(void)
{
    int i = 0;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;

    if (curActLine == ADS_EX_LINE_INVALID)
    {
        printf("Info - Phone is already on hook\n");
        return;
    }

    /*Stop the PCM tone generators (if running)*/
    if (ADS_TEL_STATUS_SUCCESS != adsTelEpCompStop(&transId,
                                        pcmEp[PCM_MAIN_LINE],
                                        ADS_TEL_PIPE_DIR_OUT,
                                                 PCM_OUT_TG)) {
        printf("\nERROR:%s: unable to STOP the Tone Generator "
                                  "on PCM output\n", __FUNCTION__);
        return;
    }

    /*Stop the PCM tone generators (if running)*/
    if (ADS_TEL_STATUS_SUCCESS != adsTelEpCompStop(&transId,
                                        pcmEp[PCM_MAIN_LINE],
                                        ADS_TEL_PIPE_DIR_IN,
                                                 PCM_IN_TG)) {
        printf("\nERROR:%s: unable to STOP the Tone Generator "
                                  "on PCM input\n", __FUNCTION__);
        return;
    }

    for (i=0; i<MAX_IP_LINES_SUPPORTED; i++)
    {
        if (epList[i].state == ADS_LINE_STATE_ON_HOLD)
        {
            /*Stop hold music if enabled*/
            status = adsTelEpCompStop(&transId,
                                      epList[i].epHandle,
                                      ADS_TEL_PIPE_DIR_OUT,
                                      IP_OUT_PLY);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to adsTelEpCompStop"
                       " failed with error code %i\n",
                       __FUNCTION__, status);
                continue;
            }
        }


        if (epList[i].state != ADS_LINE_STATE_DIAL)
        {

            /*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("Error:%s: Call to adsTelEpConStatusSet failed with"
                       " error code %i\n", __FUNCTION__, status);
                continue;
            }

            /*disconnect the IP Endpoint*/
            status = adsTelEpDestroy(&transId, epList[i].epHandle);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to adsTelEpDestroy failed with"
                       " error code %u for IP Line %i\n",
                       __FUNCTION__, status, i);
                continue;
            }

            /*reset the channel epHandle*/
            epList[i].epHandle = ADS_TEL_EP_NUM_EPS;

            /*shutdown the RTP Session*/
            if (ADS_TEL_STATUS_SUCCESS !=
                adsTelRtpSessionDestroy(i*RTP_PORT_MULTIPLIER))
            {
                printf("\nERROR:%s: Failed to tear down the RTP session for"
                       " IP line %u\n", __FUNCTION__, i);
                continue;
            }
        }

    }

    /*tear down PCM endpoint*/
    for (i=0; i<MAX_PCM_LINES_SUPPORTED; i++)
    {
        /*Disconnect the Endpoint inbound and outbound pipelines*/
        status = adsTelEpConStatusSet(&transId,
                                      pcmEp[i],
                                      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);
            continue;
        }

        /*disconnect the IP Endpoint*/
        status = adsTelEpDestroy(&transId, pcmEp[i]);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Call to adsTelEpDestroy failed with"
                   " error code %i for PCM %u\n",
                   __FUNCTION__, status, i);
            continue;
        }

        /*reset the channel epHandle*/
        pcmEp[i] = ADS_TEL_EP_NUM_EPS;

        /*shutdown the ALSA Sessions*/
        if (ADS_TEL_STATUS_SUCCESS != adsTelALSACloseChan(i))
        {
            printf("\nERROR:%s: Failed to tear down the ALSA session for"
                   " PCM line %i\n", __FUNCTION__, i);
            continue;
        }

    }

    /*tear down the router*/
    status = adsTelRouterDestroy(&transId, callRouter);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelRouterDestroy failed with error"
               " code %i\n", __FUNCTION__, status);
    }

    /*set the on hook status*/
    curActLine = ADS_EX_LINE_INVALID;

    return;
}


/*******************************************************
 *Menu option to make a call
 *******************************************************/
void adsEpMakeCall(void)
{
    unsigned int i = 0;
    unsigned int localChan = 0;
    unsigned int remoteChan = 0;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;
    char remoteIp[ADS_TEL_CODELET_STRLEN];
    unsigned int toneID = RFC_TID_DIAL;
    AdsTelMediaDesc_t segments[MEDIA_SEG];

    /*Check if the phone is on hook*/
    if (curActLine == ADS_EX_LINE_INVALID)
    {
        printf("\nERROR:%s: - Phone is on hook\n", __FUNCTION__);
        return;
    }

    /*get the local line number*/
    status = adsRefAppGetNum("\nEnter the local line number to use:",
            &localChan, NULL);
    if ((status != ADS_TEL_STATUS_SUCCESS) ||
       (localChan >= MAX_IP_LINES_SUPPORTED))
    {
        printf("\nERROR:%s: Invalid line entered\n", __FUNCTION__);
        return;
    }

    /*check if the line is free*/
    if ( epList[localChan].state != ADS_LINE_STATE_DIAL)
    {
        printf("\nERROR:%s: Line is already in use\n", __FUNCTION__);
        return;
    }

    /*switch lines if this is not the current call*/
    if (curActLine != localChan)
    {
        if ( epList[curActLine].state != ADS_LINE_STATE_DIAL)
        {

            /*Disconnect the inbound callback for the current line*/
            status = adsTelEpConStatusSet(&transId,
                                          epList[curActLine].epHandle,
                                          ADS_TEL_EP_CONN_OUT);

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

            /*set the player to play in a loop*/
            segments[0].offset = 0;
            segments[0].handle = epList[curActLine].onHoldHandle;
            segments[0].length = 0;
            segments[0].next = 0;

            /*play hold music*/
            status = adsTelEpPlayAudio(&transId,
                                       epList[curActLine].epHandle,
                                       ADS_TEL_PIPE_DIR_OUT,
                                       IP_OUT_PLY,
                                       segments,
                                       1);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to adsTelEpPlayAudio failed with"
                        " error code %i\n", __FUNCTION__, status);
                return;
            }

            /*set the current line state to on hold*/
            epList[curActLine].state = ADS_LINE_STATE_ON_HOLD;

            /*Play dial tone on PCM endpoint*/
            status = adsTelEpTonePlay(&transId,
                                      pcmEp[PCM_MAIN_LINE],
                                      /*PCM outbound direction*/
                                      ADS_TEL_PIPE_DIR_OUT,
                                      PCM_OUT_TG, /*comp ID*/
                                      1, /*num tones*/
                                      &toneID);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to adsTelEpTonePlay failed with error"
                       " code %i\n", __FUNCTION__, status);
                return;
            }
        }

        /*set the current line value*/
        curActLine = localChan;
    }

    /*get the remote line number*/
    status = adsRefAppGetNum("\nEnter the remote line number to use:",
                &remoteChan, NULL);
    if ((status != ADS_TEL_STATUS_SUCCESS) ||
       (remoteChan >= MAX_IP_LINES_SUPPORTED))
    {
        printf("\nERROR:%s Invalid line entered\n", __FUNCTION__);
        return;
    }

    /*get the remote IP Address*/
    i = adsRefAppGetStr("\nEnter the IP Address of the remote party\n",
                        remoteIp);

    /*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[localChan].codec), NULL);
    if ((status != ADS_TEL_STATUS_SUCCESS) ||
       (epList[localChan].codec < ADS_TEL_PARAM_CODER_TYPE_G711MU_10MS) ||
       (epList[localChan].codec > ADS_TEL_PARAM_CODER_TYPE_G726_16) ||
       (epList[localChan].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[localChan].de_codec=epList[localChan].codec;

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

    /*Stop the tone generator on PCM out*/
    if (ADS_TEL_STATUS_SUCCESS != adsTelEpCompStop(&transId,
                                        pcmEp[PCM_MAIN_LINE],
                                        ADS_TEL_PIPE_DIR_OUT,
                                                 PCM_OUT_TG)) {
        printf("\nERROR:%s: Unable to STOP the Tone Generator "
                                      "on PCM output\n", __FUNCTION__);
        return;
    }

    /*Setup the new IP 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,
                            callRouter,
                            &epList[localChan].epHandle);

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

    /*Configure the endpoint*/
    configureCallPCMtoIP(localChan, 0, epList[localChan].mfppVal);
    configureCallIPtoPCM(localChan, 0);

    /*Setup the RTP Stream*/
    if (ADS_TEL_STATUS_SUCCESS != adsTelRtpSessionCreate(
                                       localChan*RTP_PORT_MULTIPLIER,
                                       remoteIp,
                                       remoteChan*RTP_PORT_MULTIPLIER))
    {
        printf("\nERROR:%s: Failed to set up the RTP session\n", __FUNCTION__);
        return;
    }

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

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


    /*set the line state to connected*/
    epList[curActLine].state = ADS_LINE_STATE_CONNECTED;

    return;
}


/*******************************************************
 *Menu option to switch between the external lines
 *******************************************************/
void adsEpSwitchLine(void)
{
    unsigned int option = 0;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;
    unsigned int toneID = RFC_TID_DIAL;
    AdsTelMediaDesc_t segments[MEDIA_SEG];

    if (curActLine == ADS_EX_LINE_INVALID)
    {
        printf("\nERROR:%s: - Phone is on hook\n", __FUNCTION__);
        return;
    }


    switch (epList[curActLine].state)
    {
        case ADS_LINE_STATE_3WAY:
        {
            printf("\nERROR:%s: - Please exit 3 way call first\n",
                       __FUNCTION__);
            return;
        }

        case ADS_LINE_STATE_CONNECTED:
        {
            while (1)
            {
                printf("\nTerminate current call (%u=Yes %u=No):",
                    SWITCH_TERMINATE, SWITCH_NO_TERMINATE);
                status = adsRefAppGetNum(NULL, &option, NULL);
                if (((option != SWITCH_TERMINATE)&&
                   (option != SWITCH_NO_TERMINATE)) ||
                   (status != ADS_TEL_STATUS_SUCCESS))
                {
                    printf("\nERROR:%s: Invalid input\n", __FUNCTION__);
                    continue;
                }

                /*terminate the call*/
                if (option == SWITCH_TERMINATE)
                {
                    /*Disconnect the Endpoint inbound and outbound
                     *pipelines */
                    status = adsTelEpConStatusSet(&transId,
                                                  epList[curActLine].epHandle,
                                                  ADS_TEL_EP_CONN_NONE);
                    if (status != ADS_TEL_STATUS_SUCCESS)
                    {
                        printf("\nERROR:%s: Call to adsTelEpConStatusSet "
                               "failed with error code %i\n for line %u\n",
                               __FUNCTION__, status, curActLine);
                    }

                    /*free current IP pipeline from the router*/
                    status = adsTelEpDestroy(&transId,
                                             epList[curActLine].epHandle);
                    if (status != ADS_TEL_STATUS_SUCCESS)
                    {
                        printf("\nERROR:%s: Call to adsTelEpDestroy failed "
                               "with error code %i for IP %u\n",
                               __FUNCTION__, status, curActLine);
                    }

                    /*Tear down the RTP connection*/
                    adsTelRtpSessionDestroy(curActLine*
                                            RTP_PORT_MULTIPLIER);

                    epList[curActLine].state = ADS_LINE_STATE_DIAL;
                    break;
                }
                else
                {
                    /*switch without terminating the call*/
                    /*Disconnect IP inbound callback*/
                    status = adsTelEpConStatusSet(&transId,
                                             epList[curActLine].epHandle,
                                             ADS_TEL_EP_CONN_OUT);

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


                    /*play on hold music*/
                    /*set the player to play in a loop*/
                    segments[0].offset = 0;
                    segments[0].handle = epList[curActLine].onHoldHandle;
                    segments[0].length = 0;
                    segments[0].next = 0;

                    status = adsTelEpPlayAudio(&transId,
                                               epList[curActLine].epHandle,
                                               ADS_TEL_PIPE_DIR_OUT,
                                               IP_OUT_PLY,
                                               segments,
                                               1);
                    if (status != ADS_TEL_STATUS_SUCCESS)
                    {
                        printf("\nERROR:%s: Call to adsTelEpPlayAudio"
                                " failed with error code %i\n",
                               __FUNCTION__, status);
                    }

                    epList[curActLine].state = ADS_LINE_STATE_ON_HOLD;

                    break;

                }
            } /*end of while*/
            break;
        }

        case ADS_LINE_STATE_DIAL:
        {
            /*Stop dial tone if its not needed for new line*/
            status = adsTelEpCompStop(&transId,
                                      pcmEp[PCM_MAIN_LINE],
                                      ADS_TEL_PIPE_DIR_OUT,
                                      PCM_OUT_TG);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to  adsTelEpCompStop"
                       " failed with error code %i\n",
                       __FUNCTION__, status);
                return;
            }
            break;
        }

        default:
            printf("\nERROR:%s: - Endpoint App has reached an invalid state"
                   " for line %u!\n", __FUNCTION__, curActLine);
    }

    /*switch current line*/
    /*NB needs to be modified if number of lines supported becomes > 2*/
    if (curActLine == ADS_EX_LINE_0)
    {
        curActLine=ADS_EX_LINE_1;
    }
    else
    {
        curActLine=ADS_EX_LINE_0;
    }

    switch (epList[curActLine].state)
    {
        case ADS_LINE_STATE_ON_HOLD:
        {
            /*Stop hold music if enabled*/
            status = adsTelEpCompStop(&transId,
                                      epList[curActLine].epHandle,
                                      ADS_TEL_PIPE_DIR_OUT,
                                      IP_OUT_PLY);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to adsTelEpCompStop"
                       " failed with error code %i\n",
                       __FUNCTION__, status);
            }

            /*Enable the endpoint callbacks*/
            status = adsTelEpConStatusSet(&transId,
                                          epList[curActLine].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);
            }

            /*set the line state to connected*/
            epList[curActLine].state = ADS_LINE_STATE_CONNECTED;
            break;
        }

        case ADS_LINE_STATE_DIAL:
        {
            /*Play dial tone on PCM endpoint*/
            status = adsTelEpTonePlay(&transId,
                                      pcmEp[PCM_MAIN_LINE],
                                      ADS_TEL_PIPE_DIR_OUT,
                                      PCM_OUT_TG, /*comp ID*/
                                      1, /*num tones*/
                                      &toneID);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Call to adsTelEpTonePlay failed with"
                       " error code %i\n", __FUNCTION__, status);
            }
            break;
        }

        default:
            printf("\nERROR:%s: - Endpoint App has reached an invalid state"
                   " for line %u!\n", __FUNCTION__, curActLine);
    }
}


/*******************************************************
 *Menu option to enable a three way call
 *******************************************************/
void adsEp3WayCall(void)
{
    unsigned int i = 0;
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;

    for (i=0; i<MAX_IP_LINES_SUPPORTED; i++)
    {
        if ((epList[i].state != ADS_LINE_STATE_CONNECTED) &&
            (epList[i].state != ADS_LINE_STATE_ON_HOLD))
        {
            printf("\nERROR:%s: - Both lines must be connected before enabling"
                   "3 way calling\n", __FUNCTION__);
            return;
        }
    }

    /*turn off hold music for line on hold*/
    if (curActLine == ADS_EX_LINE_0)
    {
        i=ADS_EX_LINE_1;
    }
    else
    {
        i=ADS_EX_LINE_0;
    }
    status = adsTelEpCompStop(&transId,
                          epList[i].epHandle,
                          ADS_TEL_PIPE_DIR_OUT,
                          IP_OUT_PLY);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelEpCompStop"
               " failed with error code %i\n",
               __FUNCTION__, status);
        return;
    }

    /*Enable the pipeline callbacks*/
    status = adsTelEpConStatusSet(&transId,
                                  epList[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;
    }

    for (i=0; i<MAX_IP_LINES_SUPPORTED; i++)
    {
        epList[i].state = ADS_LINE_STATE_3WAY;
    }

    return;
}


/*******************************************************
 * Menu option to revert to a two wall call
 * curActLine is connected and !curActLine is placed
 * on hold
 *******************************************************/
void adsEpRevert2WayCall(void)
{
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;
    AdsTelMediaDesc_t segments[MEDIA_SEG];
    unsigned int i = 0;

    /*Check that 3 way call is enabled*/
    if (epList[curActLine].state != ADS_LINE_STATE_3WAY)
    {
        printf("\nERROR:%s: - 3 way calling is not enabled\n", __FUNCTION__);
        return;
    }

    /*play hold music on non current line*/
    /*set the player to play in a loop*/
    segments[0].offset = 0;
    segments[0].handle = epList[curActLine].onHoldHandle;
    segments[0].length = 0;
    segments[0].next = 0;

    if (curActLine == ADS_EX_LINE_0)
    {
        i=ADS_EX_LINE_1;
    }
    else
    {
        i=ADS_EX_LINE_0;
    }

    status = adsTelEpPlayAudio(&transId,
                               epList[i].epHandle,
                               ADS_TEL_PIPE_DIR_OUT,
                               IP_OUT_PLY,
                               segments,
                               1);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelEpPlayAudio failed"
               " with error code %i\n",
               __FUNCTION__, status);
    }

    /*Disconnect inbound CB for line to be disconnected*/
    status = adsTelEpConStatusSet(&transId,
                                  epList[i].epHandle,
                                  ADS_TEL_EP_CONN_OUT);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Call to adsTelEpConStatusSet"
               " failed with error code %i\n",
               __FUNCTION__, status);
    }

    /*Set states*/
    epList[i].state = ADS_LINE_STATE_ON_HOLD;
    epList[curActLine].state = ADS_LINE_STATE_CONNECTED;
    return;
}


/*******************************************************
 *Menu option to send a DTMF string
 *******************************************************/
void adsEpSendDTMF(void)
{
    int i = 0;
    unsigned int numTones = 0, direction = 0;
    unsigned int pToneID[ADS_TEL_MAX_TONES];
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;

    if (curActLine == ADS_EX_LINE_INVALID)
    {
        printf("\nERROR:%s: - Phone is on hook\n", __FUNCTION__);
        return;
    }

    /*get the pipeline direction */
    status = adsRefAppGetNum("\nEnter the line direction: "
                       "1 play to PCM side - 0 play to IP side - ",
                       &direction, NULL);
    if (((direction != 0)&&(direction != 1)) ||
        (status != ADS_TEL_STATUS_SUCCESS)) {
        printf("\nERROR:%s: wrong direction; it must be 0 or 1\n",
                __FUNCTION__);
        return;
    }

    /*get string of numbers*/
    status = adsRefAppGetNum("\nEnter the number of tones "
                        "to be played - ", &numTones, NULL);
    if ((numTones > ADS_TEL_MAX_TONES)||(numTones < 1)||
        (status != ADS_TEL_STATUS_SUCCESS)) {
        printf("\nERROR:%s: wrong numTones; it must be in range {1 - %d}\n",
                __FUNCTION__, ADS_TEL_MAX_TONES);
        return;
    }

    printf("\t\tDTMF tone IDs = 0~15\n"
           "\t\tCall progress tone IDs = Dial:66, Ring:70, Busy:72, CW:79\n"
           "\t\tExamples of user-added tone IDs = 251~255\n");

    for (i = 0; i < numTones; i++)
    {
         status= adsRefAppGetNum("\tEnter the tone id - ", &pToneID[i], NULL);
         if ((status != ADS_TEL_STATUS_SUCCESS)||(pToneID[i] < 0)
                || (pToneID[i] > ADS_TEL_MAX_TONE_ID))
         {
             printf("\nERROR:%s: wrong tone id\n", __FUNCTION__);
             return;
         }
    }

    /*play tones out on the PCM side*/
    if (direction == 1) {
        if (ADS_TEL_STATUS_SUCCESS != adsTelEpTonePlay(&transId,
                    pcmEp[PCM_MAIN_LINE],
                    (AdsTelPipeDir_t)direction,
                    PCM_OUT_TG, /*comp ID*/
                    numTones, /*num tones*/
                    pToneID))
        {
            printf("\nERROR:%s: Unable to Play the Tone\n", __FUNCTION__);
            return;
        }
    /*play tones out on the IP side*/
    } else {
                if (ADS_TEL_STATUS_SUCCESS != adsTelEpTonePlay(&transId,
                    pcmEp[PCM_MAIN_LINE],
                    (AdsTelPipeDir_t)direction,
                    PCM_IN_TG, /*comp ID*/
                    numTones, /*num tones*/
                    pToneID))
        {
            printf("\nERROR:%s: Unable to Play the Tone\n", __FUNCTION__);
            return;
        }
    }

    return;
}


/*******************************************************
 *Menu option to set a components parameter values
 *******************************************************/
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 epType = 0;
    unsigned int i = 0;
    unsigned int j = 0;
    unsigned int maxEpSupported = 0;
    char inpEpStr[ADS_TEL_CODELET_STRLEN];
    char tempStr[ADS_TEL_CODELET_STRLEN];
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;


    /*get the endpoint type*/
    printf("\nEnter the pipeline Type(PCM=%u, IP=%u):",
           ADS_TEL_PIPE_CONN_TYPE_PCM, ADS_TEL_PIPE_CONN_TYPE_IP);
    status = adsRefAppGetNum(NULL, &epType, NULL);
    if (((epType != ADS_TEL_PIPE_CONN_TYPE_IP)&&
       (epType != ADS_TEL_PIPE_CONN_TYPE_PCM))||
       (status != ADS_TEL_STATUS_SUCCESS))
    {
        printf("\nERROR:%s: Invalid endpoint type entered\n", __FUNCTION__);
        return;
    }

    /*set the maximum supported value*/
    if (epType == ADS_TEL_PIPE_CONN_TYPE_IP)
    {
        maxEpSupported = MAX_IP_LINES_SUPPORTED;
    }
    else
    {
        maxEpSupported = MAX_PCM_LINES_SUPPORTED;
    }


    /*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: ",
           maxEpSupported-1, maxEpSupported);
    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 number\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;
            /*set the parameter for one channel*/
            if(option < maxEpSupported)
            {
                setParam(option, epType, pipeDir, compId, 1);
            }
            else
            {
                /*if the all channels option is selected then set the paramater
                  for all the channels*/
                if(option == maxEpSupported)
                {
                    for(epNum=0; epNum<maxEpSupported; epNum++)
                    {
                        setParam(epNum, epType, pipeDir, compId, 1);
                    }
                    break;
                }
                else
                {
                    printf("\nERROR:%s: Invalid channel number: %u\n",
                           __FUNCTION__, option);
                }
            }
        }
        j++;
    }while(j<=inpStrLen);

}


/*******************************************************
 *Menu option to retrieve 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 epType = 0;
    unsigned int i = 0;
    unsigned int j = 0;
    unsigned int maxEpSupported = 0;
    char inpEpStr[ADS_TEL_CODELET_STRLEN];
    char tempStr[ADS_TEL_CODELET_STRLEN];
    AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;


    /*get the endpoint type*/
    printf("\nEnter the pipeline Type(PCM=%u, IP=%u):",
           ADS_TEL_PIPE_CONN_TYPE_PCM, ADS_TEL_PIPE_CONN_TYPE_IP);
    status = adsRefAppGetNum(NULL, &epType, NULL);
    if ((epType >= ADS_TEL_PIPE_CONN_TYPE_DELIMITER) ||
        (status != ADS_TEL_STATUS_SUCCESS))
    {
        printf("\nERROR:%s: Invalid endpoint type entered\n", __FUNCTION__);
        return;
    }

    /*set the maximum supported value*/
    if (epType == ADS_TEL_PIPE_CONN_TYPE_IP)
    {
        maxEpSupported = MAX_IP_LINES_SUPPORTED;
    }
    else
    {
        maxEpSupported = MAX_PCM_LINES_SUPPORTED;
    }


    /*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: ",
           maxEpSupported-1, maxEpSupported);
    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;
    }

    /*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 < maxEpSupported)
            {
                getParams(option, epType, pipeDir, compId);
            }
            else
            {
                /*if the all channels option is selected then get the paramaters
                  for all the channels*/
                if(option == maxEpSupported)
                {
                    for(epNum=0; epNum<maxEpSupported; epNum++)
                    {
                        getParams(epNum, epType, 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 adsEpExit(void)
{
    adsEpOnHook();

    /* start to allow exit from thread */
    adsTelALSAStartTrigger();
    return;

}


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

    /*get the endpoint handle*/
    if (epType == ADS_TEL_PIPE_CONN_TYPE_IP)
    {
        /*Verify that epNumber is valid*/
        if (epNumber >= MAX_IP_LINES_SUPPORTED)
        {
            printf("\nERROR:%s: Invalid IP endpoint number\n", __FUNCTION__);
            return ADS_TEL_STATUS_FAIL;
        }
        epHandle = epList[epNumber].epHandle;
    }
    else
    {
        /*Verify that epNumber is valid*/
        if (epNumber >= MAX_PCM_LINES_SUPPORTED)
        {
            printf("\nERROR:%s: Invalid PCM endpoint number\n", __FUNCTION__);
            return ADS_TEL_STATUS_FAIL;
        }
        epHandle = pcmEp[epNumber];
    }


    /*check that the endpoint is configured*/
    if (epHandle == ADS_TEL_EP_NUM_EPS)
    {
        printf("\nERROR:%s: EP handle is null for %u\n", __FUNCTION__,
                epNumber);
        return ADS_TEL_STATUS_FAIL;
    }

    status = adsTelEpCompParamsSet(&transId,
                                   epHandle,
                                   pipeDir,
                                   compId,    /*comp ID*/
                                   numParams, /*numParams*/
                                   paramNums, /*par num*/
                                   paramVals);/*param value*/
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s:  Call to adsTelEpCompParamsSet failed with error"
               " code %i\n", __FUNCTION__, status);
    }

    return status;
}


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

    /*get the endpoint handle*/
    if (epType == ADS_TEL_PIPE_CONN_TYPE_IP)
    {
        /*Verify that epNumber is valid*/
        if (epNumber >= MAX_IP_LINES_SUPPORTED)
        {
            printf("\nERROR:%s: Invalid IP endpoint number\n", __FUNCTION__);
            return ADS_TEL_STATUS_FAIL;
        }
        epHandle = epList[epNumber].epHandle;
    }
    else
    {
        /*Verify that epNumber is valid*/
        if (epNumber >= MAX_PCM_LINES_SUPPORTED)
        {
            printf("\nERROR:%s: Invalid PCM endpoint number\n", __FUNCTION__);
            return ADS_TEL_STATUS_FAIL;
        }
        epHandle = pcmEp[epNumber];
    }


    /*check that the endpoint is configured*/
    if (epHandle == ADS_TEL_EP_NUM_EPS)
    {
        printf("\nERROR:%s: EP handle is null for %u\n",
                __FUNCTION__, epNumber);
        return ADS_TEL_STATUS_FAIL;
    }

    status = adsTelEpCompParamsGet(&transId,
                                   epHandle,
                                   pipeDir,
                                   compId); /*param value*/
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s:  Call to adsTelEpCompParamsGet failed with error"
               " code %i\n", __FUNCTION__, status);
    }

    return status;
}



/**********************************************************************
 * Configures PCM inbound and the IP outbound pipelines based on
 * the encoder and MFPP settings
 **********************************************************************/
 void configureCallPCMtoIP(unsigned int lineNum,
                             unsigned int pcmNum,
                             unsigned int mfppVal)
{
     AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;
    /***configure blocks that switch automatically according to
        the payload***/

    /**PCM inbound**/

    /*Enable HPF*/
    paramNums[0] = ADS_TEL_PARMID_HPF_ENABLE;
    paramVals[0] = ADS_TEL_PARAM_ON;
    status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
              ADS_TEL_PIPE_DIR_IN, PCM_IN_HPF, NUM_PARAMS_1);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
    printf("\nERROR:%s: Failed to configure inbound PCM HPF\n",
           __FUNCTION__);
    }

    /*EC*/
    paramNums[0] = ADS_TEL_PARAMID_EC_AECENABLE;
    paramVals[0] = ADS_TEL_PARAM_OFF;
    status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                  ADS_TEL_PIPE_DIR_IN, PCM_IN_EC, NUM_PARAMS_1);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Failed to configure inbound PCM AEC\n",
               __FUNCTION__);
    }

    /*PCM AGC Configuration*/
    paramNums[0] = ADS_TEL_PARMID_AGC_ENABLE;
    paramVals[0] = ADS_TEL_PARAM_ON;
    status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                    ADS_TEL_PIPE_DIR_IN, PCM_IN_AGC, NUM_PARAMS_1);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Failed to configure inbound PCM AGC\n",
                __FUNCTION__);
    }

    /**IP outbound**/

    /*Encoder*/
    paramNums[0] = ADS_TEL_PARMID_ENC_CTYPE;
    paramVals[0] = epList[lineNum].codec;
    paramNums[1] = ADS_TEL_PARMID_ENC_MFPP;
    paramVals[1] = mfppVal;
    status = setParam(lineNum, ADS_TEL_PIPE_CONN_TYPE_IP,
                      ADS_TEL_PIPE_DIR_OUT, IP_OUT_ENC, NUM_PARAMS_2);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Failed to configure ountbound IP Encoder\n",
                __FUNCTION__);
    }

    /***Configuration of blocks that don't automatically switch on the fly***/
    /**CODEC SENT IS NB**/
    if ((epList[lineNum].codec < ADS_TEL_PARAM_CODER_TYPE_G722_64) ||
     (epList[lineNum].codec > ADS_TEL_PARAM_CODER_TYPE_G722_48))
     {
        /**PCM inbound**/
        if (alsaRate[pcmNum] == PCM_STREAM_RATE_8K)
        {
            /*ALSA IS NB*/
            /*SRC*/
            paramNums[0] = ADS_TEL_PARMID_SRC_ENABLE;
            paramVals[0] = ADS_TEL_PARAM_OFF;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_IN, PCM_IN_SRC, NUM_PARAMS_1);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure inbound PCM SRC\n",
                       __FUNCTION__);
            }
        }
        else
        {
            /*ALSA IS WB*/
            /*SRC*/
            paramNums[0] = ADS_TEL_PARMID_SRC_MODE;
            paramVals[0] = ADS_TEL_PARAM_SRC_DOWNSAMPLE;
            paramNums[1] = ADS_TEL_PARMID_SRC_ENABLE;
            paramVals[1] = ADS_TEL_PARAM_ON;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
              ADS_TEL_PIPE_DIR_IN, PCM_IN_SRC, NUM_PARAMS_2);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
            printf("ERROR:%s: Failed to configure inbound PCM SRC\n",
            __FUNCTION__);
            }

        }

        /* TG config */
        paramNums[0] = ADS_TEL_PARMID_TG_PCM_MODE;
        paramVals[0] = ADS_TEL_PARAM_NB;
        paramNums[1] = ADS_TEL_PARMID_TG_RFC2833;
        paramVals[1] = ADS_TEL_PARAM_OFF;
        status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                      ADS_TEL_PIPE_DIR_IN, PCM_IN_TG, NUM_PARAMS_2);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure inbound PCM TG\n",
                   __FUNCTION__);
        }
        /**IP outbound**/

        /* PLY Configuration */
        epList[lineNum].onHoldHandle = nbHoldHandle;
        paramNums[0] = ADS_TEL_PARMID_PLY_MODE;
        paramVals[0] = ADS_TEL_PARAM_NB;
        status = setParam(lineNum, ADS_TEL_PIPE_CONN_TYPE_IP,
                      ADS_TEL_PIPE_DIR_OUT, IP_OUT_PLY, NUM_PARAMS_1);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure outbound IP player\n",
                   __FUNCTION__);
        }
    }
    else
    {
        /**CODEC IS WB**/
        if (alsaRate[pcmNum] == PCM_STREAM_RATE_16K)
        {
            /**PCM inbound**/
            /*ALSA is WB*/
            /*SRC*/
            paramNums[0] = ADS_TEL_PARMID_SRC_ENABLE;
            paramVals[0] = ADS_TEL_PARAM_OFF;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_IN, PCM_IN_SRC, NUM_PARAMS_1);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure inbound PCM SRC\n",
                       __FUNCTION__);
            }

            /*TG*/
            paramNums[0] = ADS_TEL_PARMID_TG_PCM_MODE;
            paramVals[0] = ADS_TEL_PARAM_WB;
            paramNums[1] = ADS_TEL_PARMID_TG_RFC2833;
            paramVals[1] = ADS_TEL_PARAM_OFF;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_IN, PCM_IN_TG, NUM_PARAMS_2);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure inbound PCM TG\n",
                       __FUNCTION__);
            }

            /**IP Outbound**/
            /*PLY*/
            epList[lineNum].onHoldHandle = wbHoldHandle;
            paramNums[0] = ADS_TEL_PARMID_PLY_MODE;
            paramVals[0] = ADS_TEL_PARAM_WB;
            status = setParam(lineNum, ADS_TEL_PIPE_CONN_TYPE_IP,
                          ADS_TEL_PIPE_DIR_OUT, IP_OUT_PLY, NUM_PARAMS_1);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure outbound IP player\n",
                       __FUNCTION__);
            }
        }
        else
        {
            /*ALSA is NB*/
            /*The whole pipleline can be NB, the encoder will upsample*/
            /**PCM inbound**/
            /*SRC*/
            paramNums[0] = ADS_TEL_PARMID_SRC_ENABLE;
            paramVals[0] = ADS_TEL_PARAM_OFF;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_IN, PCM_IN_SRC, NUM_PARAMS_1);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure inbound PCM SRC\n",
                       __FUNCTION__);
            }

            /* TG */
            paramNums[0] = ADS_TEL_PARMID_TG_PCM_MODE;
            paramVals[0] = ADS_TEL_PARAM_NB;
            paramNums[1] = ADS_TEL_PARMID_TG_RFC2833;
            paramVals[1] = ADS_TEL_PARAM_OFF;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_IN, PCM_IN_TG, NUM_PARAMS_2);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure inbound PCM TG\n",
                       __FUNCTION__);
            }

            /**IP outbound**/

            /*PLY*/
            epList[lineNum].onHoldHandle = nbHoldHandle;
            paramNums[0] = ADS_TEL_PARMID_PLY_MODE;
            paramVals[0] = ADS_TEL_PARAM_NB;
            status = setParam(lineNum, ADS_TEL_PIPE_CONN_TYPE_IP,
                          ADS_TEL_PIPE_DIR_OUT, IP_OUT_PLY, NUM_PARAMS_1);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure outbound IP player\n",
                       __FUNCTION__);
            }
        }
    }
    return;
}

/**********************************************************************
 * Configures IP inbound and PCM outbound pipelines based on
 * the decoder settings
 **********************************************************************/
void configureCallIPtoPCM(unsigned int lineNum,
                             unsigned int pcmNum)
{
     AdsTelStatus_t status = ADS_TEL_STATUS_SUCCESS;
    /***configure components that switch automatically according
         to the payload***/

    /**IP Inbound**/

    /* DEC*/
    paramNums[0] = ADS_TEL_PARMID_DEC_CTYPE;
    paramVals[0] = epList[lineNum].de_codec;
    status = setParam(lineNum, ADS_TEL_PIPE_CONN_TYPE_IP,
                      ADS_TEL_PIPE_DIR_IN, IP_IN_DEC, NUM_PARAMS_1);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
        printf("\nERROR:%s: Failed to configure inbound IP Decoder\n",
                __FUNCTION__);
    }

    /*ALC*/
    paramNums[0] = ADS_TEL_PARMID_AGC_ENABLE;
    paramVals[0] = ADS_TEL_PARAM_ON;
    status = setParam(lineNum, ADS_TEL_PIPE_CONN_TYPE_IP,
              ADS_TEL_PIPE_DIR_IN, IP_IN_ALC, NUM_PARAMS_1);
    if (status != ADS_TEL_STATUS_SUCCESS)
    {
    printf("\nERROR:%s: Failed to configure inbound IP AGC\n",
           __FUNCTION__);
    }

    /**CODEC RECEIVED IS NB**/
    if ((epList[lineNum].de_codec < ADS_TEL_PARAM_CODER_TYPE_G722_64) ||
     (epList[lineNum].de_codec > ADS_TEL_PARAM_CODER_TYPE_G722_48))
     {
         /**IP Inbound**/
        /*TG*/
        paramNums[0] = ADS_TEL_PARMID_TG_PCM_MODE;
        paramVals[0] = ADS_TEL_PARAM_NB;
        status = setParam(lineNum, ADS_TEL_PIPE_CONN_TYPE_IP,
                      ADS_TEL_PIPE_DIR_IN, IP_IN_TG, NUM_PARAMS_1);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure inbound IP TG\n",
                   __FUNCTION__);
        }

        /**PCM outbound**/
        /*TG*/
        paramNums[0] = ADS_TEL_PARMID_TG_PCM_MODE;
        paramVals[0] = ADS_TEL_PARAM_NB;
        paramNums[1] = ADS_TEL_PARMID_TG_RFC2833;
        paramVals[1] = ADS_TEL_PARAM_OFF;
        status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                      ADS_TEL_PIPE_DIR_OUT, PCM_OUT_TG, NUM_PARAMS_2);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure outbound PCM TG\n",
                   __FUNCTION__);
        }

        /*PLY*/
        epList[lineNum].onHoldHandle = nbHoldHandle;
        paramNums[0] = ADS_TEL_PARMID_PLY_MODE;
        paramVals[0] = ADS_TEL_PARAM_NB;
        status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                      ADS_TEL_PIPE_DIR_OUT, PCM_OUT_PLY, NUM_PARAMS_1);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure outbound PCM player\n",
                   __FUNCTION__);
        }

        if (alsaRate[pcmNum] == PCM_STREAM_RATE_8K)
        {
            /*ALSA IS NB*/ /*The SRC is on to add an extra security*/
            /*SRC*/
            paramNums[0] = ADS_TEL_PARMID_SRC_MODE;
            paramVals[0] = ADS_TEL_PARAM_SRC_DOWNSAMPLE;
            paramNums[1] = ADS_TEL_PARMID_SRC_ENABLE;
            paramVals[1] = ADS_TEL_PARAM_ON;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_OUT, PCM_OUT_SRC, NUM_PARAMS_1);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure outbound PCM SRC\n",
                       __FUNCTION__);
            }
        }
        else
        {
            /*ALSA is WB*/
            /*SRC*/
            paramNums[0] = ADS_TEL_PARMID_SRC_MODE;
            paramVals[0] = ADS_TEL_PARAM_SRC_UPSAMPLE;
            paramNums[1] = ADS_TEL_PARMID_SRC_ENABLE;
            paramVals[1] = ADS_TEL_PARAM_ON;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_OUT, PCM_OUT_SRC, NUM_PARAMS_2);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure outbound PCM SRC\n",
                       __FUNCTION__);
            }
        }
     }
     else
     {
        /* Code received is WB The pipeline will be is the same format*/
        /**IP Inbound**/
        /*TG Configuration*/
        paramNums[0] = ADS_TEL_PARMID_TG_PCM_MODE;
        paramVals[0] = ADS_TEL_PARAM_WB;
        status = setParam(lineNum, ADS_TEL_PIPE_CONN_TYPE_IP,
                      ADS_TEL_PIPE_DIR_IN, IP_IN_TG, NUM_PARAMS_1);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure inbound IP TG\n",
                   __FUNCTION__);
        }

         /**PCM outbound**/
        /*TG*/
        paramNums[0] = ADS_TEL_PARMID_TG_PCM_MODE;
        paramVals[0] = ADS_TEL_PARAM_WB;
        paramNums[1] = ADS_TEL_PARMID_TG_RFC2833;
        paramVals[1] = ADS_TEL_PARAM_OFF;
        status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                      ADS_TEL_PIPE_DIR_OUT, PCM_OUT_TG, NUM_PARAMS_2);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure outbound PCM TG\n",
                   __FUNCTION__);
        }

        /*PLY*/
        epList[lineNum].onHoldHandle = wbHoldHandle;
        paramNums[0] = ADS_TEL_PARMID_PLY_MODE;
        paramVals[0] = ADS_TEL_PARAM_WB;
        status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                      ADS_TEL_PIPE_DIR_OUT, PCM_OUT_PLY, NUM_PARAMS_1);
        if (status != ADS_TEL_STATUS_SUCCESS)
        {
            printf("\nERROR:%s: Failed to configure outbound PCM player\n",
                   __FUNCTION__);
        }

        if (alsaRate[pcmNum] == PCM_STREAM_RATE_8K)
        {
            /*SRC*/
            paramNums[0] = ADS_TEL_PARMID_SRC_MODE;
            paramVals[0] = ADS_TEL_PARAM_SRC_DOWNSAMPLE;
            paramNums[1] = ADS_TEL_PARMID_SRC_ENABLE;
            paramVals[1] = ADS_TEL_PARAM_ON;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_OUT, PCM_OUT_SRC, NUM_PARAMS_2);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure outbound PCM SRC\n",
                       __FUNCTION__);
            }
       }
        else
        {
            /*ALSA is WB*/
            /*SRC*/
            paramNums[0] = ADS_TEL_PARMID_SRC_MODE;
            paramVals[0] = ADS_TEL_PARAM_SRC_UPSAMPLE;
            paramNums[1] = ADS_TEL_PARMID_SRC_ENABLE;
            paramVals[1] = ADS_TEL_PARAM_ON;
            status = setParam(pcmNum, ADS_TEL_PIPE_CONN_TYPE_PCM,
                          ADS_TEL_PIPE_DIR_OUT, PCM_OUT_SRC, NUM_PARAMS_2);
            if (status != ADS_TEL_STATUS_SUCCESS)
            {
                printf("\nERROR:%s: Failed to configure outbound PCM SRC\n",
                       __FUNCTION__);
            }
        }
    }
    return;
}

/******** **************************
 * initialise the tracking arrays
 **********************************/
void initEpTrackingArrays(void)
{
    unsigned int i = 0;

    /*initialise the PCM tracking arrays*/
    for (i=0; i<MAX_PCM_LINES_SUPPORTED; i++)
    {
        /*ephandle*/
        pcmEp[i] = ADS_TEL_EP_NUM_EPS;

        /*set the ALSA rate*/
        alsaRate[i] = ALSA_PCM_STREAM_RATE;

        /*Set the ALSA FORMAT*/
        alsaFormat[i] = ALSA_PCM_FORMAT;

    }

    /*initialise the IP endpoint handles*/
    for (i=0; i<MAX_IP_LINES_SUPPORTED; i++)
    {
        epList[i].epHandle = ADS_TEL_EP_NUM_EPS;
    }

    return;
}


/*******************************************
 * 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; adsEpMenu[i].name != NULL; i++)
        {
            printf("%3d - %s\n", i, adsEpMenu[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;
        }

        adsEpMenu[selectedItem].menuFunc();


    } while(selectedItem != lastItem);
    return ADS_TEL_STATUS_SUCCESS;
}



