Auto Attendant Source
<PRE>
//automatic attendant by Ulianov Fernandez & Bob Davis Last update 2/19/99
#include <stdio.h> /* ptintf */
#include <graph.h>
#include <stdlib.h> /* exit */
#include <conio.h>
#include "d40.h"
#include "vfcns.h"
#include "d40lib.h"
#define FOREVER 1 /* loop forever within do-while loop */
#define ST_IDLE 2 /* waiting for an incoming call */
#define ST_OFFHK 3 /* go offhook to accept call */
#define ST_GREET 4 /* play initial prompt */
#define ST_DIGITS 5 /* Gets 3 dtmf digits */
#define ST_HOLD 6 /* play please hold message */
#define ST_DIAL 7 /* Dial number */
#define ST_ONHK 8 /* close the file and go onhook */
#define ST_BUSY 9 /* Play extension is busy */
#define ST_NOANS 10 /* Play naanswer message */
#define ST_LIST 11 /* Play list of extensions */
static RWB d4xrwb = {0}; /* d4x common read-write block */
static struct {
int state; /* next state number to execute */
int file_handle; /* place to store record file handle */
char digsave[4]; /* storage for dtmf digits and term char */
} port[5] = {0}; /* allocate channel structures (1 based) */
static int greetfh; /* file handle for "GREET.vox" */
static int busyfh; /* file handle for "BUSY.vox" */
static int holdfh; /* file handle for "HOLD.vox" */
static int listfh; /* file handle for "list.vox" */
static int noansfh; /* file handle for "noans.vox" */
void sysinit();
int process_event(int,int,int);
int curr_state(int,int,int);
int next_state(int);
int play(int,int);
int dial_digits(int,char *);
int get_digits(int,char *,int);
int get_conn(int,int,int);
int draw_box(int,int,int,int);
/****************************************************************
* NAME : main(argc,argv)
* DESCRIPTION : entrypoint to application
****************************************************************/
void main (argc,argv)
int argc;
char *argv[]; {
EVTBLK d4evtblk; /* d4x event status block */
int channel, /* d4x or dti channel number */
evtcode, /* termination event code */
evtdata, /* event data */
errcode;
sysinit(5); /* Start up system, use interupt #5 */
greetfh = vhopen("greet.vox",READ);
busyfh = vhopen("busy.vox",READ);
holdfh = vhopen("hold.vox",READ);
listfh = vhopen("list.vox",READ);
noansfh = vhopen("noans.vox",READ);
while (FOREVER) {
if (kbhit()) {
if (getch()==27)
break;}
if (gtevtblk(&d4evtblk)==(-1)) {
channel = d4evtblk.devchan;
evtcode = d4evtblk.evtcode;
evtdata = d4evtblk.evtdata;
port[channel].state = process_event(channel,evtcode,evtdata);
errcode = next_state(channel);}}
vhclose(greetfh);
vhclose(busyfh);
vhclose(holdfh);
vhclose(listfh);
vhclose(noansfh);
stopsys();
exit(0); }
/****************************************************************
* NAME : process_event(channel,evtcode,evtdata)
* DESCRIPTION : begin initial processing of the event code
****************************************************************/
int process_event(channel,evtcode,evtdata)
int channel,evtcode,evtdata; {
draw_box( 1, 1, 6,20);
draw_box( 1,21, 6,40);
draw_box( 1,41, 6,60);
draw_box( 1,61, 6,80);
_settextcolor (2);
_settextposition(2, 5); printf("Channel 1");
_settextposition(2, 25); printf("Channel 2");
_settextposition(2, 45); printf("Channel 3");
_settextposition(2, 65); printf("Channel 4");
switch (evtcode) {
case T_RING: /* rings received (cst event) */
case T_LCON: /* loop current on (cst event) answer call*/
if (port[channel].state==ST_IDLE)
return(ST_OFFHK);
case T_LC: /* loop current off (cst event) */
case T_LCTERM: /* loop current termination (rwb event) */
if (port[channel].state!=ST_IDLE && port[channel].state!=ST_ONHK)
if (port[channel].file_handle!=0) {
vhclose(port[channel].file_handle);
port[channel].file_handle = 0; }
return(ST_ONHK);
break;
case T_ONH: /* on hook complete */
case T_OFFH: /* off hook complete */
case T_EOF: /* end of file (play or record) */
case T_TIME: /* timeout (rwb event) */
case T_SIL: /* max silence (rwb event) */
case T_MAXDT: /* max dtmf received (rwb event) */
case T_TERMDT: /* Normal termination digit (rwb event) */
return(curr_state(channel,evtcode,evtdata));
case T_CATERM: /* Termination event of callp() (try ext)*/
return(get_conn(channel,evtcode,evtdata));
case T_DIAL: /* Termination event of dial() (busy)*/
return(ST_BUSY);
default: /* unexpected or error termination event*/
port[channel].state = ST_GREET;
return(curr_state(channel,evtcode,evtdata)); }
return(port[channel].state); }
/****************************************************************
* NAME : curr_state(channel,evtcode)
* DESCRIPTION : complete processing of the current state
****************************************************************/
int curr_state(channel,evtcode,evtdata)
int channel,evtcode,evtdata; {
switch (port[channel].state) {
case ST_IDLE:
return(ST_OFFHK);
case ST_OFFHK:
clrdtmf(channel); /* Clear out DTMF to work with D42/D */
_settextposition(3,((channel*20)-18));
printf("Receiving call. ");
return(ST_GREET);
case ST_GREET:
return(ST_DIGITS);
case ST_DIGITS:
if (port[channel].digsave[0]<'0'|| port[channel].digsave[0]>'9')
return(ST_ONHK); /* Hang up, no digits received */
if (port[channel].digsave[0]=='0')
return(ST_HOLD); /* Dial operator */
if (port[channel].digsave[0]=='9')
return(ST_LIST);
if (port[channel].digsave[1]<'0'|| port[channel].digsave[1]>'9')
return(ST_GREET); /* NOT ENOUGH digits received */
if (port[channel].digsave[2]<'0'|| port[channel].digsave[2]>'9')
return(ST_GREET); /* NOT ENOUGH digits received */
return(ST_HOLD); /* default - it is valid */
case ST_HOLD:
return(ST_DIAL);
case ST_DIAL:
return(ST_ONHK); /* Hang up if connected */
case ST_BUSY:
return(ST_GREET);
case ST_LIST:
return(ST_GREET);
case ST_ONHK:
_settextposition(3,((channel*20)-18));
printf("Ready for call. ");
_settextposition(4,((channel*20)-18));
printf(" ");
_settextposition(5,((channel*20)-18));
printf(" "); // }
return(ST_IDLE);
default:
return ST_GREET; }
return(port[channel].state); }
/****************************************************************
* NAME : next_state(channel)
* DESCRIPTION : begin the next state, initiate multi-tasking function
****************************************************************/
int next_state(channel)
int channel; {
int errcode = 0;
switch (port[channel].state) {
case ST_IDLE:
break;
case ST_OFFHK:
errcode = sethook(channel,H_OFFH);
break;
case ST_GREET: /* play the greeting message */
errcode = play(channel,greetfh);
break;
case ST_DIGITS: /* wait for 3 digits */
errcode = get_digits(channel,port[channel].digsave,3);
break;
case ST_HOLD: /* Play "please hold." */
errcode = play(channel,holdfh);
break;
case ST_DIAL: /* DIAL the digits */
errcode = dial_digits(channel,port[channel].digsave);
break;
case ST_BUSY: /* Extension is busy */
clrdtmf(channel);
errcode = play(channel,busyfh);
break;
case ST_ONHK: /* go on hook, terminate call */
errcode = sethook(channel,H_ONH);
break;
case ST_LIST: /* LIST extensions message */
_settextposition(4,((channel*20)-18));
printf("Playing list. ");
clrdtmf(channel);
errcode = play(channel,listfh);
break;
return(errcode); } }
/****************************************************************
* NAME : sysinit()
* DESCRIPTION : initialize d4x system
****************************************************************/
void sysinit() {
int channel,rc,chan;
int d4xint=5;
stopsys();
if ((rc = startsys(d4xint,SM_EVENT,0,0,&channel))!=0){
printf("error starting system");
exit(1);}
for (chan=1; chan<=channel; chan++) {
setcst(chan,C_LC|C_RING|C_OFFH|C_ONH|C_WKRECV,1);
sethook(chan,H_ONH);
port[chan].state = ST_ONHK; } }
/****************************************************************
* NAME : dial_digits(channel,digitp)
* DESCRIPTION : dial 3 digits received
****************************************************************/
int dial_digits(channel,digitp)
int channel;
char *digitp; {
char tempstr[10]; // Modifications to callp for faster connect
CPB d4xcpb;
clrcpb (&d4xcpb);
d4xcpb.nbrdna=2; // Detect in 1 ring if busy
d4xcpb.hedge=2; // Detect voice on rising edge
setcparm(channel,&d4xcpb);
sprintf(tempstr,"&,,%c%c%c",*(digitp+0),*(digitp+1),*(digitp+2));
_settextposition(4,((channel*20)-18));
printf("Dialing: %s ",tempstr);
return(callp(channel,tempstr)); }
/****************************************************************
* NAME : get_conn(channel,evtcode,evtdata)
* DESCRIPTION : check for a busy
****************************************************************/
int get_conn(channel,evtcode,evtdata)
int channel,evtdata,evtcode; {
switch(evtdata){
int rc;
case CA_BUSY:
_settextposition(5,((channel*20)-18));
printf("Extension busy.");
if ((rc=dial(channel,"&"))!=0){} /* recover from busy */
break;
case CA_CONN:
break; }
return(curr_state(channel,evtcode,evtdata)); }
/****************************************************************
* NAME : play(channel,fh)
* DESCRIPTION : play from disk file
****************************************************************/
int play(channel,fh)
int channel,fh; {
int mode = PM_NORM;
if (vhseek(fh,(long int)0,0)==(long int)-1)
return(-1); /* start at begining of file */
clrrwb(&d4xrwb);
d4xrwb.filehndl = fh; /* the file to play from */
d4xrwb.maxdtmf = 1; /* stop on any digit */
d4xrwb.termdtmf = '@'; /* stop on any digit */
d4xrwb.loopsig = 1;
return(xplayf(channel,mode,&d4xrwb)); }
/****************************************************************
* NAME : get_digits(channel,buffer,maxdig)
* DESCRIPTION : initiate the get dtmf string function
****************************************************************/
int get_digits(channel,buffer,maxdig)
int channel;
char *buffer;
int maxdig; {
clrrwb(&d4xrwb);
d4xrwb.maxdtmf = maxdig; /* num of dtmf digits */
d4xrwb.xferoff = d4getoff(buffer); /* user's dtmf buffer */
d4xrwb.xferseg = d4getseg(buffer);
d4xrwb.maxsec = 9; /* max time allowed (sec) */
d4xrwb.maxsil = 4; /* silence timeout (sec) */
d4xrwb.loopsig = 1;
return(getdtmfs(channel,&d4xrwb)); }
/****************************************************************
* NAME : draw_box(x1, y1, x2, y2)
* DESCRIPTION : draw a box given top left and bottom right corners
****************************************************************/
int draw_box(x1,y1,x2,y2)
int x1,y1,x2,y2; {
int a;
for (a=x1; a<x2; a++) { //draw sides
_settextposition(a,y1); printf("%c",186);
_settextposition(a,y2); printf("%c",186); }
for (a=y1; a<y2; a++) { //draw top & bottom
_settextposition(x1,a); printf("%c",205);
_settextposition(x2,a); printf("%c",205); }
_settextposition(x1,y1);printf("%c",201);
_settextposition(x2,y2);printf("%c",188);
_settextposition(x1,y2);printf("%c",187);
_settextposition(x2,y1);printf("%c",200);
return (x1,y1,x2,y2); }
/***** END OF FILE ******/
</PRE>