<pre>
/***************************************************************
* VOICE MAIL II PROGRAM by Bob Davis *
***************************************************************/
#include <time.h>
#include <sys\timeb.h>
#include <graph.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h> /* Lattice Compiler: <dos.h> */
#include <io.h> /* Lattice Compiler: <fcntl.h> */
#include <d40.h>
#include <vfcns.h>
#include <d40lib.h>
#define D4X_INTR 5 /* default hardware interrupt */
#define MAXCHAN 24 /* maximum number of channels */
#define MAXDIG 3 /* max number of digits */
#define FOREVER 1 /* loop forever do-while loop */
#define ST_IDLE 2 /* waiting for an incoming call */
#define ST_OFFHK 3 /* go offhook to accept call */
#define ST_PROMPT 4 /* play initial prompt */
#define ST_RECORD 5 /* record the message */
#define ST_ONHK 6 /* close file and go onhook */
static RWB d4xrwb = {0}; /* d4x common read-write block */
static struct {
int state; /* next state number to execute */
int file_handle; /* storsge for record file handle */
char digsave[MAXDIG+1]; /* storage for dtmf digits and term char */
} port[MAXCHAN+1] = {0}; /* allocate channel structures (1 based) */
static char *argp; /* global path pointer */
void sysinit(int);
int process_event(int,int,int);
int curr_state(int,int,int);
int next_state(int);
int play(int,int);
int record(int,int);
char tmpbuf[128] ;
time_t ltime;
struct tm *today;
struct _timeb tstruct;
/****************************************************************
* NAME : main(argc,argv) - start of application *
****************************************************************/
void main (argc,argv)
int argc;
char *argv[]; {
EVTBLK d4evtblk; /* d4x event status block */
int channel,evtcode,evtdata,d4xintr=D4X_INTR,errcode;
_clearscreen( _GWINDOW );
sysinit(d4xintr); /* initialize the d/4x hardware */
while (FOREVER) { /* check to see if a key was pressed */
if (kbhit()) if (getch()==27) break;
if (gtevtblk(&d4evtblk)==(-1)) {/* get event inf from status block */
channel = d4evtblk.devchan;
evtcode = d4evtblk.evtcode;
evtdata = d4evtblk.evtdata; /* process the event, save next state */
port[channel].state = process_event(channel,evtcode,evtdata);
errcode = next_state(channel);/* begin new state, check error code */
if (errcode!=0) printf("error on channel %d,\n",channel); } }
exit(0); }
/****************************************************************
* NAME : sysinit(d4xintr) - initialize d4x system *
* INPUT : d4xintr = d4x hardware interrupt *
****************************************************************/
void sysinit(d4xintr)
int d4xintr; {
int channel,errcode,n;
n = getvctr(); /* check to see if D40DRV is installed */
if (n==0) {
printf("D/4x device driver not installed\n");
stopsys();
exit(1); }
stopsys(); /* make sure that the system has stopped */
errcode = startsys(d4xintr,SM_EVENT,0,0,&channel);
if (errcode!=0) {
printf("Unable to start D/4x system, Return code %d\n",errcode);
stopsys();
exit(1); }
if (channel>MAXCHAN) channel = MAXCHAN;
for (n=1; n<=channel; n++) { /* set all channels init to onhook state */
setcst(n,C_LC|C_RING|C_OFFH|C_ONH,4); /* "1" is number of rings */
sethook(n,H_ONH);
port[n].state = ST_ONHK; }}
/******************************************************************
* NAME : process_event(channel,evtcode,evtdata) *
* INPUT : evtcode=termination event, evtdata=termination status *
******************************************************************/
int process_event(channel,evtcode,evtdata)
int channel,evtcode,evtdata; {
switch (evtcode) { /* check for termination events */
case T_RING: /* rings received (cst event) */
case T_LCON: /* loop current on (cst event) */
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: /* termination digit (rwb event) */
return(curr_state(channel,evtcode,evtdata));
break;
default: /* unexpected/error termination event*/
printf("Channel %d, Event Code %d\n",channel,evtcode);
port[channel].state = ST_PROMPT;
return(curr_state(channel,evtcode,evtdata)); }
return(port[channel].state); }
/****************************************************************
* NAME : curr_state(channel,evtcode) *
* INPUT : channel=channel number, evtcode=term code, evtdata=term status
****************************************************************/
int curr_state(channel,evtcode,evtdata)
int channel,evtcode,evtdata; {
char *namep;
switch (port[channel].state) {
case ST_IDLE:
return(ST_OFFHK);
case ST_OFFHK:
port[channel].file_handle = 0;
sprintf(namep,"line%d/greet.spc",channel);
port[channel].file_handle = vhopen(namep,READ);
if (port[channel].file_handle == 0) {
sprintf(namep,"greet.spc"); /* Protect from deleted greetings */
port[channel].file_handle = vhopen(namep,READ); }
return(ST_PROMPT);
case ST_PROMPT:
vhclose(port[channel].file_handle);
port[channel].file_handle = 0;
_tzset();
time( <ime );
today = localtime( <ime );
strftime( tmpbuf, 128, "%d%H%M", today);
sprintf(namep,"line%d/M%s.spc ",channel,tmpbuf);
port[channel].file_handle = vhopen(namep,READ);
if (port[channel].file_handle > 0) {
vhclose(port[channel].file_handle);
port[channel].file_handle = vhopen(namep,APPEND);}
else {
port[channel].file_handle = vhopen(namep,CREATE);}
_settextposition(channel, 20);
printf(namep); /* display message number */
return(ST_RECORD);
case ST_RECORD:
vhclose(port[channel].file_handle);
port[channel].file_handle = 0;
return(ST_ONHK);
case ST_ONHK:
_ltoa(_filelength(port[channel].file_handle),namep,16);
if (namep == 0) { /* delete messages of 0 bytes */
remove ("port[channel].file_handle"); }
return(ST_IDLE); }
return(port[channel].state); }
/****************************************************************
* NAME : next_state(channel) - initiate multi-tasking function *
* INPUT : channel = channel number *
****************************************************************/
int next_state(channel)
int channel; {
int errcode = 0;
_settextposition(channel, 10);
switch (port[channel].state) {
case ST_IDLE: /* channel idle, waiting for incoming call */
printf("Waiting");
_settextposition(channel, 1);
printf("Line %d", channel);
break;
case ST_OFFHK: /* call received, go off hook */
printf("Ringing");
errcode = sethook(channel,H_OFFH);
break;
case ST_PROMPT: /* play the greeting message */
clrdtmf(channel);
printf("Playing");
errcode = play(channel,port[channel].file_handle);
break;
case ST_RECORD: /* begin the record operation */
clrdtmf(channel);
printf("Record ");
errcode = record(channel,port[channel].file_handle);
break;
case ST_ONHK: /* go on hook & terminate the call */
errcode = sethook(channel,H_ONH);
break; }
return(errcode); }
/****************************************************************
* NAME : play(channel,fh) - play from disk file *
* INPUT : channel=channel number, fh=file handle of the file *
****************************************************************/
int play(channel,fh)
int channel,fh; {
int mode = PM_NORM;
if (vhseek(fh,(long int)0,0)==(long int)-1) return(-1);
clrrwb(&d4xrwb);
d4xrwb.filehndl = fh; /* the file to play from */
d4xrwb.loopsig = 1;
return(xplayf(channel,mode,&d4xrwb)); }
/****************************************************************
* NAME : record(channel,fh) - record to disk file *
* INPUT : channel=channel number, fh = file handle of the file *
****************************************************************/
int record(channel,fh)
int channel,fh; { /* int mode = RM_NORM */
int mode = RM_SCOMP; /* use silence compressed record */
clrrwb(&d4xrwb);
d4xrwb.filehndl = fh; /* the file to record to */
d4xrwb.maxsec = 300; /* max time allowed (sec) */
d4xrwb.maxsil = 9; /* silence timeout (sec) */
d4xrwb.rwbflags = RW_TONE; /* tone initiation */
d4xrwb.rwbdata1 = 3; /* .6 msec tone (x.2 msec) */
d4xrwb.loopsig = 1;
return(recfile(channel,&d4xrwb,mode)); }
// EOF
</pre>