/* Script to Answer On Voice Calls */

Call RxFuncAdd 'SysSleep', 'RexxUtil', 'SysSleep'
Call RxFuncAdd 'SysGetKey', 'RexxUtil', 'SysGetKey'
Call RxFuncAdd 'SysCls', 'RexxUtil', 'SysCls'
Call RxFuncAdd 'SysTempFileName', 'RexxUtil', 'SysTempFileName'
Call RxFuncAdd 'SysFileDelete', 'RexxUtil', 'SysFileDelete'
Call RxFuncAdd 'SysFileTree', 'RexxUtil', 'SysFileTree'
Call RxFuncAdd 'SysSwitchSession', 'RexxUtil', 'SysSwitchSession'
Call RxFuncAdd 'RxAsyncRead', 'RXASYNC', 'RxAsyncRead'
Call RxFuncAdd 'RxAsyncWait', 'RXASYNC', 'RxAsyncWait'
call RxFuncAdd 'RxAsyncLoadFuncs', 'RXASYNC', 'RxAsyncLoadFuncs'
call RxAsyncLoadFuncs

signal on halt

/* --------------------- Initialization ----------------------------- */


Call SysFileTree tauto.ini, rc
if rc.0 = 0 then
do
say "tauto.ini file not found, Please create according to documentation."
signal prog_quit
end
else

do while lines(tauto.ini) \= "0"
rc=linein(tauto.ini,,1)
parse upper value rc with selvar selvalue .
 select
 when left(selvar,1)='[' | left(selvar,1)=';' | selvar='' then NOP
 when selvar='COMPORT' then interpret selvar '=selvalue'
 when selvar='RINGTIME' then interpret selvar '=selvalue'
 when selvar='ADD_AON' then interpret selvar '=selvalue'
 when selvar='USE_SOUND' then interpret selvar '=selvalue'
 when selvar='MAINLOG' then interpret selvar '=selvalue'
 when selvar='DEBUG' then interpret selvar '=selvalue'
 when selvar='SWITCHSES' then interpret selvar '=selvalue'
 when left(selvar,4)='DTMF' then interpret selvar '=selvalue'
 otherwise
 say "Unknown Directive" selvar
 signal prog_quit
 end
end
call stream tauto.ini,'c','close'

/* [Global] */
init="AT&F1H0E1V1"
hang="ATZ"
offhook="ATH1"
command_delay=0.5    /* delay between AT commands (sec) */
silence='ATMO'

/* [AON+RINGING Emulation] AVC56 ONLY !!! */
ringing="ATR1"
AonInit="ATJ2S90=19S30=0S99=1S70=3S7="RingTime||Add_aon

/* [Voice] */
VoiceInit="ATE0J2#CLS=8"
speaker="AT#VLS=4M1"
record="AT#VRX"
playback="AT#VTX"
beep_1="AT#VTS=[933,0,12]"
dle=x2c(10)
dle_etx=x2c(10)x2c(3)
cancel=x2c(10)x2c(18)
VoiceDir=".\VOICE"
GreetDir=".\GREET"

/* [DTMFs] */


/* [Internal] Don't modify w/o necessity !!! */
PortHandle=''
remaining=''
end_rec=1
aonname=1
lend=x2c(a5)
extern_run=0
num=0
rez=0
rej=0
crlf=d2c(13)d2c(10)

/* ------------- Entry Point -------------- */

parse arg par
PortHandle=par
if par <> "" then
do
call com_init

rc = RxAsyncWrite( PortHandle, 0, AonInit||crlf, 'Remaining' )
if rc <> 0 then signal err1
call check_string "AonInit", "OK", "  AON Init Error... Exitting... ;("

extern_run=1
signal ans
end

port_not_checked=1


rc=" -- "date()"г  " time() " Program Started --"
num=num+length(rc)
call lineout numlog,crlf
call charout numlog,rc
call stream numlog,'c','close'

space:
rez=0
rej=0

patrol:
dtmf_comp=""

Call SysCls

rc=crlf "       Automatic AVC56 AutoAnswer v 1.02a (c) By Alek Winner." crlf
say rc
if mainlog then call charout rclog,rc

if port_not_checked then
do
call comport_check
port_not_checked=0
end


hallo=greetdir"\hallo.gsm"

rc = RxAsyncWrite( PortHandle, 0, init||crlf, 'Remaining' )
if rc <> 0 then signal err1

rc = RxAsyncWrite( PortHandle, 0, init||crlf, 'Remaining' )
if rc <> 0 then signal err1

call check_string "Init", "OK", "  Modem Init Error... Exitting... ;("


rc = RxAsyncWrite( PortHandle, 0, AonInit||crlf, 'Remaining' )
if rc <> 0 then signal err1
call check_string "AonInit", "OK", "  AON Init Error... Exitting... ;("


if mainlog then call charout rclog,crlf
rc=" "date()"г  " time() "  Modem Initialized OK" crlf
say rc
if mainlog then call charout rclog,rc

rc=linein(numlog,,0)
rc=stream(numlog,'c','seek <'num)
do while rc <> ''
rc=linein(numlog)
say rc
end
call stream numlog,'c','close'

say
say "        Waiting For Enemy Calls..." rez "granted" "|" rej "rejected"
say
say "        Press <A> to Answer, <N> for New or <ESC> to Exit..."
say

InpStr=""
do while InpStr \= 'RING'||crlf

rc =  RxAsyncRead( PortHandle, 0, 1500, 'InpStr' )

if chars()=1 then
  do
  key=c2d(SysGetKey(noecho))
    select
    when key=110 | key=78 then signal sel_key  /* (N) */
    when key=27 then signal term
    when key=97 | key=65 then
     do
     rc = RxAsyncWrite( PortHandle, 0, 'RING'||crlf, 'Remaining' )
     if rc <> 0 then signal err1
     end
    otherwise
    end
  end

end

ans:

call syssleep command_delay


rc=" "date()"г  " time() "  Answering..." crlf
say rc
if mainlog then call charout rclog,rc

/* --------------- AON & Emulation part --------------- */

if switchses=1 then rc=SysSwitchSession(tauto.cmd)

rc = RxAsyncWrite( PortHandle, 0, offhook||crlf, 'Remaining' )
if rc <> 0 then signal err1


InpStr=""
do until left(InpStr,6) = 'CALLER'
rc = RxAsyncRead( PortHandle, 0, -1, 'InpStr' )
if rc <> 0 then signal err1
db="OffHook" InpStr crlf
if debug then call charout debug.log,db

 if InpStr='OK'||crlf then
  do
  caller='CALLER ID:XXXXXXX:X'
  signal not_det
  end

end

caller=InpStr
call check_string "Offhook", "OK", "  Modem not Report Offhook... Exitting... ;("


not_det:

rc=" "date()"г  " time() " " caller crlf
say rc
if mainlog then call charout rclog,rc

user="Unknown"

do while rc \= ""
rc=linein(users.lst,,1)
if subword(rc,1,2)=left(caller,17) then
  do
  user=subword(rc,6)
  permit=word(rc,3)
  if permit='rejected' | permit='admin_mob' then signal reject
  hallo=greetdir"\"word(rc,4)
  rc=""
  end
end
call stream users.lst,'c','close'

if use_sound then '@start /c tnum.cmd' caller

aonname=SysTempFileName(voicedir'\aw???.num')
voicename=left(aonname,14)"gsm"

rc=crlf" "time()" "left(caller,19)  " granted " right(voicename,9) " "left(user,14)" "
num=num+length(rc)
call charout numlog,rc
call stream numlog,'c','close'


rc=" "date()"г  " time() " " aonname crlf
say rc
if mainlog then call charout rclog,rc
call lineout aonname,caller
call stream aonname,'c','close'


if permit="admin" then signal owner_proc


ring_begin:

rc = RxAsyncWrite( PortHandle, 0, ringing||crlf, 'Remaining' )
if rc <> 0 then signal err1

inpstr=""
rc=time(R)
do until inpstr="OK"||crlf

 if chars()=1 then
 do
 key=c2d(SysGetKey(noecho))
 if key=82 | key=114 then ring_flag=1   /* (R) */
 else signal sel_key
 end

call syssleep 1

rc = RxAsyncRead( PortHandle, 0, 7000, 'InpStr' )
if rc<>0 then signal err1

if inpstr="RINGBACK"||crlf then
do
rc=" "date()"г  " time() " " 'Ringing...' crlf
say rc
if mainlog then call charout rclog,rc
call beep 600,650
end

if ring_flag=1 then
do
ring_flag=0
signal ring_begin
end

end

if time(E) < ringtime then
do
rc=" No Message"
num=num+length(rc)
call charout numlog,rc
if extern_run then signal term
signal patrol
end

ring_end:


rez=rez+1

rc=crlf date()"г  " time() "  Launching Autoanswer call N" rez crlf
say rc
if mainlog then call charout rclog,rc



/* ------------ AutoAnswer Part ------------------ */

call voice_init

call play_file

go_rec:

call beep_to_line

rc = RxAsyncWrite( PortHandle, 0, record||crlf, 'Remaining' )
if rc <> 0 then signal err1
call check_string "record", "CONNECT", "  Error switching to RECORD mode... Exitting... ;("


rc=" "date()"г  " time() "  Recording..." crlf
say rc
if mainlog then call charout rclog,rc


busy=0


rc=" "date()"г  " time() " " voicename crlf
say rc
if mainlog then call charout rclog,rc



do until c2x(rc) = ''

frame=''

do while c2x(right(frame,2)) <> 'A5A5'

fram=frame

db = RxAsyncRead( PortHandle, 0, 2000, 'frame',,lend )
if db <> 0 then
  do

  if voicename='busy.fil' then
   do
   voicename=oldvoice
   call stream "busy.fil",'c','close'
   call SysFileDelete("busy.fil")
   end

  call stream voicename,'c','close'
  signal done

  end

frame=fram||frame
end

 n=length(frame)
 i=1

 do while i <= n

 rc=SUBSTR(frame,i,1)
 i=i+1

 if c2x(rc)=10 then
 do
 rc=SUBSTR(frame,i,1)
 i=i+1

 say c2x(rc)

   select

   when c2x(rc)=10 then NOP

   when rc='b' then
     do
     rc=SUBSTR(frame,i,1)
     i=i+1

     xx=" "date()"г  " time() "  Обнаружен сигнал в линии..." crlf
     say xx
     if mainlog then call charout rclog,xx

     call RxAsyncTxImmediate PortHandle, c2x(dle)
     end_rec="d_tone"

     end

   when rc='d' then
     do
     rc=SUBSTR(frame,i,1)
     i=i+1

     tm=time(R)
     say tm
     if tm>13 | busy=0 then
      do
      busy=0
      tm=02
      if voicename="busy.fil" then
       do
        bsy="BSY"
        do until bsy=""
        bsy=charin("busy.fil",,1)
        call charout oldvoice,bsy
       end
      voicename=oldvoice
      bsy="BSY=" bsy crlf
      say bsy
      if debug then call charout debug.log,bsy
      call stream "busy.fil",'c','close'
      call SysFileDelete("busy.fil")
      end
      else
       do
       oldvoice=voicename
       voicename="busy.fil"
       end
  end

     if busy<3 & tm<13 then busy=busy+1
     say busy "BUSY VALUE"
     if busy=3 then
       do
       call stream "busy.fil",'c','close'
       call SysFileDelete("busy.fil")

       bussy:
       xx=" "date()"г  " time() "  Обнаружен сигнал в линии..." crlf
       say xx
       if mainlog then call charout rclog,xx

       call RxAsyncTxImmediate PortHandle, c2x(dle)
       end_rec="d_tone"

       end
     end


   when rc='#' then
     do
     DTMF_COMP=""
     rc=SUBSTR(frame,i,1)
     i=i+1
     end


   when rc='1' | rc='2' | rc='3' | rc='4' | rc='5' | rc='6' | rc='7' | rc='8' | rc='9' | rc='0' | rc='*' then
     do
     rc0=" "date()"г  " time() " " "Pressed "rc crlf
     say rc0
     if mainlog then call charout rclog,rc0


     if DTMF_COMP="PASSED" then
     do

      if value(DTMF_||rc) <> "" then
        do
        call RxAsyncTxImmediate PortHandle, c2x(dle)
        db="pressed" rc crlf
        if debug then call charout debug.log,db
        end_rec=value(DTMF_||rc)
        end
      else NOP

     end
     else
     do
     DTMF_COMP=DTMF_COMP||rc
      IF DTMF_PASS=DTMF_COMP THEN
       do
       DTMF_COMP="PASSED"
       call RxAsyncTxImmediate PortHandle, c2x(dle)
       db="Pass entered" rc crlf
       if debug then call charout debug.log,db
       end_rec="ADMIN"
       end
     end

   rc=SUBSTR(frame,i,1)
   i=i+1
   end

   otherwise
   call beep 262,250
   rc=" "date()"г  " time() " " "ERROR Pressed "rc crlf
   say rc
   if mainlog then call charout rclog,rc

   rc=SUBSTR(frame,i,1)
   i=i+1
   end
 end

call charout voicename,rc
if chars()=1 then
do
rc=SysGetKey(noecho)
call RxAsyncTxImmediate PortHandle, c2x(dle)
end_rec="kb_key"
end
end
end

done:

select

when end_rec="PLAY_NEW" then
 do
 ext=".gsm"
 call play_new
 end

when left(end_rec,9)="PLAY_FILE" then
 do
 hallo=greetdir"\"||substr(end_rec,11)
 call voice_init
 call play_file
 end

when end_rec="GOODBYE" then NOP

when end_rec="ADMIN" then
 do
 hallo=greetdir"\owner.gsm"
 signal owner_proc
 end

when end_rec="d_tone" then NOP

when end_rec="kb_key" then NOP

otherwise
end

rc=" "chars(voicename) / 38 * 0.02 "sec"
num=num+length(rc)
call charout numlog,rc

call close_all
if extern_run then signal term
signal patrol



/* --- Banner Proc --------*/


/* --- Banner Ends --------*/






/* --- Check Port State --------*/
comport_check:
if stream(comport,'c','open') = 'NOTREADY:32' then signal err0

call stream comport,'c','close'
rc = RxAsyncOpen( Comport, 'PortHandle' )

com_init:

rc = RxAsyncSetLnCtrl( PortHandle, 57600, 8, 'N', 1 )
if rc <> 0 then signal err0

rc=RxAsyncSetDcbInfo(PortHandle,400,50,'00001001','10000000','','','','','' )
return

err0:
rc=" "date()"г  " time() "  Comport is not respond... ;(" crlf
say rc
if mainlog then call charout rclog,rc
call beep 262,250
exit
/* -----------------------------*/



/* -- Check Modem String --------- */
check_string:
PARSE ARG deb_str, ok_str, err_str

InpStr = ""
do until InpStr=ok_str||crlf | InpStr='ERROR'||crlf
rc = RxAsyncRead( PortHandle, 0, 3000, 'InpStr' )
if rc <> 0 then signal err1
db=deb_str InpStr crlf
if debug then call charout debug.log,db
end

if InpStr = ok_str||crlf then return

err1:
rc=" "date()"г  " time() err_str crlf
say rc
if mainlog then call charout rclog,rc
call beep 262,250
signal term
/* -- Check Modem String - Ends -- */



/* ----- Close All Files -------*/
close_all:
call stream hallo,'c','close'
call stream voicename,'c','close'
call stream numlog,'c','close'
call stream rclog,'c','close'
call stream debug.log,'c','close'
return
/* -----------------------------*/


/* ---- Play Voice File --------*/
play_file:

rc = RxAsyncWrite( PortHandle, 0, playback||crlf, 'Remaining' )
if rc <> 0 then signal err1
call check_string "Playback", "CONNECT", "  PlayBack Failed... Exitting... ;("

rc=" "date()"г  " time() "  Playing..." crlf
say rc
if mainlog then call charout rclog,rc

do forever

write_buf=''

do 50

rc=charin(hallo,,1)
if c2x(rc)="" then signal done_play

if c2x(rc)=10 then write_buf=write_buf||rc
write_buf=write_buf||rc

if chars()=1 then
  do
  rc=SysGetKey(noecho)
  call RxAsyncWrite PortHandle, 2, cancel, 'Remaining'
  signal done_play
  end

end

rc = RxAsyncWrite( PortHandle, 0, write_buf, 'Remaining' )
if rc <> 0 then signal done_play

end

done_play:


call RxAsyncWrite PortHandle, 2, dle_etx, 'Remaining'

call cancel_stream

call stream hallo,'c','close'
return
/* ----------------------------------------- */


/* ----------- Play New Messages ------------*/
play_new:
rc=linein(numlog,,0)
rc=stream(numlog,'c','seek <'num)

rc=" "date()"г  " time() " " "Play New..."
say rc
if mainlog then call charout rclog,rc

begin_new:
caller=" "linein(numlog,,1) crlf
hallo=word(caller,5)
if hallo='' then
do
call voice_init
call beep_to_line
hallo=greetdir"\hallo.gsm"
call close_all
return
end

if substr(caller,3,2) = '--' then signal begin_new

say crlf caller
if mainlog then call charout rclog,crlf||caller

hall=hallo
call voice_init

aonname=substr(word(caller,3),4,7)

do while rc \= ""
rc=linein(users.lst,,1)
parse value rc with . c_id . . v_name . .
if c_id = "ID:"||aonname & left(v_name,1) <> "-" then
  do
  hallo=".\names\"v_name||ext
  if ext=".gsm" then call play_file
  else if use_sound then call play_wav_file
  signal speak
  end
end


do i=1 to 7
hallo=".\number\"substr(aonname,i,1)".gsm"
call play_file
end

speak:
call stream users.lst,'c','close'

hallo=hall

if right(hallo,3)\='gsm' then signal begin_new

rc=" "date()"г  " time() " " hallo crlf
say rc
if mainlog then call charout rclog,rc

hallo=VoiceDir"\"hallo
call voice_init
call play_file
signal begin_new
return
/* ------------------------------------------------------------- */

/* ------------ Voice Initialization ------------------------- */

voice_init:

rc = RxAsyncWrite( PortHandle, 0, VoiceInit||crlf, 'Remaining' )
if rc <> 0 then signal err1
call check_string "VoiceInit", "OK", "Error entering to Voice mode... Exitting... ;("


rc = RxAsyncWrite( PortHandle, 0, speaker||crlf, 'Remaining' )
if rc <> 0 then signal err1
call check_string "Speaker", "OK", "  Error setting audio device... ;("
return

/* ---------------  Voice Init Endp  -------------------------*/


/* ---- Reading Tail of Stream from Port ---- */

cancel_stream:

rc=" "date()"г  " time() "  Done..." crlf
say rc
if mainlog then call charout rclog,rc

do until rc='VCON'||crlf
db = RxAsyncRead( PortHandle, 0, 0, 'rc' )
db="process end" rc crlf
if debug then call charout debug.log,db
end

return

/* -------------- End Proc ----------------- */


/* ---------------  Beep To Line  --------------------------*/
beep_to_line:

rc = RxAsyncWrite( PortHandle, 0, beep_1||crlf, 'Remaining' )
if rc <> 0 then signal err1
call check_string "Beep_1", "OK", ""

return
/* ---------------  Beep To Line Ends ----------------------*/

/* ---------------  Reject Proc  -------------- */
reject:

call stream users.lst,'c','close'
if use_sound then '@start /c tnum.cmd' caller

rej=rej+1

rc=crlf" "time()" "left(caller,19) " rejected"  "--------- " left(user,14) " No Message"
num=num+length(rc)
call charout numlog,rc

call syssleep 0.5

if permit="admin_mob" then
do
call voice_init
hallo=".\number\"rez".gsm"
call play_file
hallo=".\number\"rej".gsm"
call play_file
end

call stream numlog,'c','close'

if extern_run then signal hang_line
signal patrol
/* -------------- Reject End --------------- */

/* -------------- Ring Break Proc -------------- */
ring_break:

call RxAsyncTxImmediate PortHandle, c2x(dle)
call syssleep 1
call check_string "ringing", "OK", "  Ring Emulation not Work... Exitting... ;("

return
/* -------------- Ring break Ends -------------- */

/* -------------- Owner_Proc ------------------- */
owner_proc:

call voice_init
call play_file

if rez=0 & rej=0 then hallo=greetdir"\call_off.gsm"
else
do
hallo=greetdir"\call_on.gsm"
call play_file
hallo=greetdir"\white.gsm"
call play_file
hallo=".\number\"rez".gsm"
call play_file
hallo=greetdir"\black.gsm"
call play_file
hallo=".\number\"rej".gsm"
end

call play_file
signal go_rec

/* -------------- Owner_Endp ------------------- */

/* -------------- Play_Wave_File --------------- */
play_wav_file:

/* Load the DLL, initialize MCI REXX support */
call RXFUNCADD 'mciRxInit','MCIAPI','mciRxInit'
rc=mciRxInit()

retst=''
myopen="Open" hallo "Alias Wave shareable"
myplay="Play Wave Wait"

MacRC = mciRxSendString(myopen, 'RetSt', '0', '0')

MacRC = mciRxSendString(myplay, 'RetSt', '0', '0')

MacRC = mciRxSendString('close Wave wait', 'RetSt', '0', '0')

MacRC = mciRxExit()
return

/* -------------- Play_Wave_File Ends ---------- */


fals_key:
key=c2d(SysGetKey())

sel_key:
select
when key=27 | key=32 then
do
rc=" "date()"г  " time() "  ESC pressed, Aborting... ;)" crlf
say rc
if mainlog then call charout rclog,rc

call ring_break

rc=" Aborted..."
num=num+length(rc)
call charout numlog,rc
call stream numlog,'c','close'

signal patrol
end

when key=13 then
do
call ring_break
signal ring_end
end

when key=110 | key=78 then    /* (N) */
do
ext=".wav"
call play_new
signal space
end

otherwise
return
end

hang_line:
rc = RxAsyncWrite( PortHandle, 0, init||crlf, 'Remaining' )
if rc <> 0 then signal err1

call check_string "Init", "OK", "  Modem not ready... Exitting... ;("


halt:
say "Меня убили..."
term:

call close_all
call RxAsyncClose PortHandle

/*
do until rc=-1
rc = RxAsyncRead( PortHandle, 0, 0, 'InpStr' )
db="Echo" InpStr crlf
if debug then call charout debug.log,db
end
*/

prog_quit: