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>