Probably the best way to show the basic library functions and the library calling conventions is to provide a simple example. The example below simply waits for an incoming call on the first channel of the first E1 port, then plays a message and receives some DTMF. It is assumed that the reader is familiar with the Telecom Engine standard library set and the Aculab Call Control library (CXACULAB.DLL).
$include "aculab.inc"
int port, chan, vox_chan, x, event;
var filename:64;
var tone:1;
main
port=0
chan=1;
vox_chan=1;
filename="hello.vox";
// Make full duplex H.100 bus routing between voice channel and network port/channel
CClisten(port,chan,SMgetslot(vox_chan));
SMlisten(vox_chan, CCgetslot(port, chan));
// Enable inbound calls on this port/channel
CCenablein(port,chan);
// loop waiting for incoming call
while(1)
x=CCwait(port,chan,CC_WAIT_FOREVER,&event);
if(x > 0 and event eq CS_INCOMING_CALL_DETECTED)
break;
endif
endwhile
// Cause jump to onsignal if remote disconnect is received
CCuse(port,chan);
// Answer the call
CCaccept(port,chan);
// Play a vox file to caller
SMplay(vox_chan,filename);
// Wait for some digits.. parmaters are:
//SMwaittones(voice_chan,max_tones,first_delay10ths,inter_delay10ths) ,term_digits,&num_digits]
SMwaittones(vox_chan,1,40,40);
// Get any received digits
tone=Smgettones(vox_chan);
if(tone strneq "")
// make the file name up from the tone received
filename="PROMPT" & tone & ".vox";
SMplay(vox_chan,filename);
endif
// Cause jump top onsignal
task_hangup(task_getpid());
endmain
onsignal
// Hangup the call
CCdisconnect(port,chan,CAUSE_NORMAL);
// Wait for state to return to IDLE the release call
while(1)
x=CCwait(port,chan,CC_WAIT_FOREVER,&event);
if(x eq CS_IDLE)
break;
endif
endwhile
// release the call
CCrelease(port,chan);
// restart the application to wait for another call..
restart;
endonsignal
The program should be fairly self explanatory but I will describe the key parts of the program below.
The “aculab.inc” file is provided with the library and defines all the constants that are used with the library such as CC_WAIT_FOREVER, CAUSE_NORMAL, CS_INCOMING_CALL_DETECTED etc. These are be described in more detail in the call control library function library reference (CXACULAB).
The first call: CClisten() simply makes the receiving stream/channel of the call control channel ‘Listen’ to the transmit stream/channel of the Voice channel, so that anything that is output by the voice channel will be heard by the caller.
The second call: SMlisten() makes the receiving stream/channel voice channel ‘listen’ to the transmit stream/channel of the Call control channel, so that any DTMF digits or other audio transmitted by the caller will be heard by the voice channel.
As mentioned above all this is done by switching from and to the extern H.100 or SCBUS.
The CCenablein(port,channel) allows inbound calls to be received on the channel, and then the application goes into a loop waiting for calls.
The CCwait(port,channel,timeout_100ms,&event) function call will wait for the specified timeout (in 10ths of a second) for an event. If the timeout is defined as -1 (CC_WAIT_FOREVER) then the call will not return until an event is found or it is aborted by a CCabort() call. Really the only event that should be received here is CS_INCOMING_CALL_DETECTED but we do a specific check for it anyway in case the channel was in a unknown state when the program started (probably some error handling should be carried out if we found an unexpected event).
Once a CS_INCOMING_CALL_DETECTED event has been received then the call is answered immediately with CCaccept(port,channel) and CCuse(port,channel) forces the program to jump to the onsignal function if the CS_REMOTE_DISCONNECT event is received from this point on.
After this there are some calls to the Speech Module library fuctions.
First a voice prompt is played to the caller using the SMplay(vox_chan,filename) function after which the application waits for some DTMF input using the SMwaittones(vox_chan, num_dig,first_delay10ths, inter_delay10ths) function.
The SMwaitones() function puts the task into a blocking state until one of the terminating conditions is met. The terminating condition could be that the requested number of digits has been received (num_dig) or the timeout waiting for the first digit (first_delay10ths) was exceeded, or the inter-digit timeout was exceeded (inter_delay10ths). SMwaittones() will then copy any digits received into the internal digit buffer for the voice channel. The next call SMgettones(vox_chan) returns any digits that have been copied to the internal digit buffer for the voice channel.
The application then checks if a tone was received and if so will use the received DTMF to make the name of a prompt file which is then played using the SMplay() function.
The application then forces itself to the onsignal function by calling task_hagup() with it’s own process id where the call is disconnected using the CCdisconnect(port,channel) call and the application goes into a loop waiting for the channel to return to the CS_IDLE state before releasing the call with CCrelease(port,channel) and restarting the program to wait for the next call.