Simple VOIP -> TDM example
Previous Topic  Next Topic 

To make or receive a VOIP call a Virtual Media Processing channel needs to be created on a DSP module connected to the board which has the VOIP capability (Using SMcreateVMP()).        The supported codecs can then be specified for that VMP channel using the SMsetcodec() function.


The usual call control functions can then be used to receive an inbound VOIP call,  but before accepting the call the call accept parameters must be setup with the VMP channel so that the media stream (codec) can be processed.    This is done using the CCsetparm() functions.


In the example below, once the VOIP call has been received we then make an outbound call over the E1 port and when this answers we create a TDM endpoint so that the E1 stream can be connected to the VMP port  in a full duplex connection so that the two parties can talk to each other.          This is done through the CCcreateTDM() functions and the SMfeedlisten() function.


Here is a small program showing this functionality:



$include "aculab.inc"


int vox_chan, port, chan, vmp_chan, module_id;

int call_state;


main


    vox_chan=1;

    module_id=0;

    e1port=0;

    e1chan=1;


    ipport=8;

    ipchan=1;


    vmp_chan=SMcreateVMP(module_id);        // Create a VMP channel

    // specify a codec on the vmp channel

    SMsetcodec(vmp_chan,0,G711_ALAW);


    // Keep a track of where we are so that we know how to clear down the call in onsignal

    call_state=0;

   

    // Wait for an inbound call on IP channel(using the newly created VMP when we accept)

    CCenablein(ipport,ipchan);

    CCuse(ipport,ipchan);    // Hangup will cause jump to onsignal

    while(1)

           x=CCwait(ipport,ipchan,WAIT_FOREVER,&state);

           if(state eq CS_INCOMING_CALL_DET)

                call_state=1;    // need to clear down ip call

                CCalerting(ipport,ipchan);   // send INCOMING_RINGING event

           else if(state eq CS_WAIT_FOR_ACCEPT)


                // specify a codec on the vmp channel

                SMsetcodec(vmp_chan,0,G711_ALAW);

     

                // Set the VMP and CODEC array into the call accept parameters..

                CCclrparms(ipport,ipchan,PARM_TYPE_ACCEPT);

                CCsetparm(ipport,ipchan,PARM_TYPE_ACCEPT,CP_IPTEL_VMPRXID,vmp_chan);

                CCsetparm(ipport,ipchan,PARM_TYPE_ACCEPT,CP_IPTEL_VMPTXID,vmp_chan);

                CCsetparm(ipport,ipchan,PARM_TYPE_ACCEPT,CP_IPTEL_CODECS,vmp_chan);

                CCaccept(ipport,ipchan);

                break;

           endif endif

     endwhile


    task_sigctl("(");    // Temporarily prevent hangup from causing jump to onsignal


    // Create the TDM endpoint for the E1 port

    tdm_chan=CCcreateTDM(e1port,e1chan);    // Get a TDM endpoint for an E1 channel

  

    // ** Now connect the feeds from the VMP and TDM endpoint to make

    // ** a full duplex connection to connect the conversations from the IP to E1 calls  

    // ** we do this here so that VOIP call will hear call progress tones..


    // The vmp_chan will now listen to the tdm_chan datafeed

    SMfeedlisten(vmp_chan,TYPE_VMP,tdm_chan,TYPE_TDM);

    // The tdm_chan will now listen to the vpm_chan datafeed

    SMfeedlisten(tdm_chan,TYPE_TDM,vpm_chan,TYPE_VPM);

  

    call_state=2;    // need to clear down ip call and destroy TDM

    task_sigctl(")");    // Allow hangup to cause jump to onsignal again..


    // hangup on E1 port will cause jump to onsignal

    CCuse(e1port,e1chan);

    call_state=3;    // need to clear down both IP and E1 calls

    // Now make outbound call on E1 port/channel

    x=CCmkcall(e1port,e1chan,"123456"."987654");

    while(1)

           x=CCwait(e1port,e1chan,WAIT_FOREVER,&state);

           if(state eq CS_OUTGOING_RINGING)

                applog("Outgoing ringing")   // send INCOMING_RINGING event

           else if(state eq CS_CALL_CONNECTED)

                break;

           endif endif

    endwhile


       // We just loop here waiting for a hangup from either side which will cause jump to onsignal

      while(1)

           sleep(40);   // four second sleep

      endwhile

endmain


onsignal


    applog("We are in ONSIGNAL!!!!");


    // Release the VMP channel

    SMdestroyVMP(vmp_chan,VMP_TYPE);


    // do we need to clear down the inbound IP call?

    if(call_state)

        CCdisconnect(ipport,ipchan,LC_NORMAL);

        if(call_state >=2)

              SMdestroyTDM(tdm_chan);

        endif

     

        last_state=-1;

        while(1)

          # wait for idle

          applog("CCIN: in onsig CCwaiting for CS_IDLE");

          x=CCwait(ipport,ipchan,10,&state,last_state);

          applog("CCIN: CCwait returned x=",x," state=",state);

             if(state eq 0)

                   applog("ipport=",ipport," ipchan=",ipchan," Incoming went to IDLE");

                   CCrelease(ipport,ipchan);

                  break;

          endif

          task_sleep(1);

       endwhile

    endif


   // do we need to clear down the outbound E1 call?

   if(call_state >=3)

        CCdisconnect(e1port,e1chan,LC_NORMAL);

        last_state=-1;

        while(1)

          # wait for idle

          applog("CCIN: in onsig CCwaiting for CS_IDLE");

          x=CCwait(e1port,e1chan,10,&state,last_state);

          applog("CCIN: CCwait returned x=",x," state=",state);

             if(state eq 0)

                   applog("e1port=",e1port," ipchan=",e1chan," Incoming went to IDLE");

                   CCrelease(e1port,e1chan);

                  break;

          endif

          task_sleep(1);

       endwhile

    endif

   

    restart;

endonsignal