'------------------------------------------------------------------------------
' Digital Message Repeater (X8 button USB player)
' V0.01 02.07.08 AK - initial version
' V0.02 08.07.08 AK - second release
' V0.03 20.08.13 DG - patch for buffer flushing
'------------------------------------------------------------------------------
    Dim ver$(18),dbg,st$(256),cm$(256),com$(256),comb
    ver$="V0.03 20.08.13" : dbg = 0 : cm$ = ""
    st$ = "Digital Message Repeater -- "+ver$ : syslog st$

' handle 2 is Setup settings
' handle 3 is serial for X8/RS
' handle 4 is messages.txt file
' handle 5 is UDP command port
' handle 6 is audio file from USB/flash
' handle 7 is audio output

    Dim _CGI_$(100),_M_P$(2048),set$,dft_v,vol,res,udp_p,ad_gn,att 'settings
    Dim pf$(2),rf$(2),nn$(3),s$(6),s_old$(6),bfile$(6),tmp$(256),file$(30),comX8$(20),new_v$(3),old_v$(3),mf$(30)
    Dim state,hwb,b,inp,btn,i_old,b_old,L,Lcom,i,v,r_min,r_max,bnd,in,bn


    Open "STP:0" as 2 : read 2,set$ : Close 2
    com$="COM:19200,N,8,1,NON:1" 'serial 1 "19200,N,8,1,NON" mode for X8 "D????????????????"
    open com$ as 3 : com$ = ""   'open serial port for X8 volume control

    Open "STP:500" as 2 : read 2,set$ : Close 2
    dft_v = midget(set$,1,1) : if or(dft_v<0,dft_v>20) then dft_v=10 'default volume
    res   = midget(set$,6,2) : if res = 0 then res = 1000            'resistor value
    UDP_p = midget(set$,8,2)                                         'UDP command port
    ad_gn = midget(set$,2,1) : if ad_gn > 15 then ad_gn = 15
    att   = midget(set$,14,1)                            'input attenuation with message

    state = 0 : vol = dft_v : hwb = 7 'initial values

    if UDP_p then open "UDP:0.0.0.0:"+str$(UDP_p) as 5 'open UDP command port

    for b = 0 to hwb 'NB! HW dependant -- change "1" to "7" for Ann1000 or IPAM
       if iostate(201 + b) = 0 then hwb = b - 1 : goto 101
    next b
101 syslog "HW IO = "+str$(hwb+1) 'if button is "pressed" with start => is not allowed on this HW

100 gosub 200 : gosub 230 : goto 100

    end

'------------------------------------------------------------------------------
200 'play possible audio
'------------------------------------------------------------------------------
     if state = 0 then goto 214                 'stop and don't play more

     if state = 1 then                          'open and start play new file

  
     if mediatype(7) then CLOSE 7  
    open "AUD:1,0,0,0" as 7           'output: MP3 play
    write 7,str$(vol),-12             'set Volume (*5%)
    write 7,str$(ad_gn),-2            'set A/D Gain
    write 7,str$(8192+64),-13         'set mixer for 100% input and 100% output

        if mediatype(6) then CLOSE 6
        write 7,"",0                            'flush audio buffer

        'try to find the proper file
        bfile$ = "MSG"+str$(inp)+str$(btn)

        'stop the same file if the same button is pressed
        if file$ then
           if bfile$=mid$(file$,instr(1,file$,"MSG"),5) then
              i_old = -1 : b_old = -1 : s_old$ = "" 'restore initial for input, button, source
              st$ = "the same file "+file$+" is stopped" : syslog st$
              goto 214
           endif
        endif

210     gosub 220 'check file
        if file$ then
           st$ = "open "+file$ : syslog st$ : delay 300 : state = 3
           if rf$ = "!" then ioctl 1,1 else ioctl 1,0    'set relay ON/OFF
           write 7,str$(8192+att),-13     'set mixer for %% input and 100% output
        else                              'file for this input:button is absent
           if bfile$ <> "MSGXX" then
              st$ = "file for number "+str$(inp)+str$(btn)+" is absent" : syslog st$
              bfile$ = "MSGXX" : goto 210 'if non-existing file, brief "blip" should be output
           else
              goto 214 'idle or error state
           endif
        endif

     endif

     if state = 2 then                             'reopen and continue play the same file
        OPEN file$ as 6 : if mediatype(6)=0 then goto 214
        st$ = "reopen "+file$ : syslog st$ : state = 3         'constant playing...
     endif

     'below state = 3 -- playback...
     st$ = "playback "+mid$(file$,instr(1,file$,"MSG")+3,2)+" ["+file$+"]"
     if filesize(7) < 4096 then return             'buffer enough

     if mediatype(6) then read 6,_M_P$ : L = lastlen(6)
     if L > 0 then write 7,_M_P$,L : return 'add to play buffer
     if mediatype(6) then CLOSE 6

201  if state = 3 then if filesize(7) < 32700 then goto 201 'waiting for finishing audio

     if pf$ = "O" then state = 0 else state = 2 'repeat file (also for instant)
     return

214  'idle or error state
     if mediatype(6) then CLOSE 6                  'close playback file if is
'     write 7,"",0                                  'flush audio buffer
     ioctl 1,0                                     'reset relay
'     write 7,str$(8192+64),-13                     'set mixer for 100% input and 100% output
     file$ = "" : pf$ = "" : rf$ = "" :
     state = 0  : st$ = "idle..."
     
     return

'------------------------------------------------------------------------------
220 'check file
'------------------------------------------------------------------------------

     pf$ = "O" : rf$ = "" : file$ = "C_R:usb:///"+bfile$+pf$+rf$+".MP3" 'once file
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "R" : rf$ = "" : file$ = "C_R:usb:///"+bfile$+pf$+rf$+".MP3" 'repeat file
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "M" : rf$ = "" : file$ = "C_R:usb:///"+bfile$+pf$+rf$+".MP3" 'instant file
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "O" : rf$ = "!" : file$ = "C_R:usb:///"+bfile$+pf$+rf$+".MP3" 'once file & relay
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "R" : rf$ = "!" : file$ = "C_R:usb:///"+bfile$+pf$+rf$+".MP3" 'repeat file & relay
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "M" : rf$ = "!" : file$ = "C_R:usb:///"+bfile$+pf$+rf$+".MP3" 'instant file & relay
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "O" : rf$ = "" : file$ = "F_R:"+bfile$+pf$+rf$+".MP3" 'once file
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "R" : rf$ = "" : file$ = "F_R:"+bfile$+pf$+rf$+".MP3" 'repeat file
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "M" : rf$ = "" : file$ = "F_R:"+bfile$+pf$+rf$+".MP3" 'instant file
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "O" : rf$ = "!" : file$ = "F_R:"+bfile$+pf$+rf$+".MP3" 'once file & relay
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "R" : rf$ = "!" : file$ = "F_R:"+bfile$+pf$+rf$+".MP3" 'repeat file & relay
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "M" : rf$ = "!" : file$ = "F_R:"+bfile$+pf$+rf$+".MP3" 'instant file & relay
     OPEN file$ as 6 : if mediatype(6) then return

     pf$ = "" : rf$ = "" : file$ = "" : return
'------------------------------------------------------------------------------
230 'check slow processes
'------------------------------------------------------------------------------
    inp = -1 : btn = -1 'set initial values

    if _CGI_$ then 'check WEB request/command
       com$ = _CGI_$ : lcom = len(com$)
       if and(lcom = 4, mid$(com$,2,1)="=") then 'WEB command

          _CGI_$ = "" 'formal reply to empty frame
          delay 0 : _CGI_$ = "<html><head></head><body>Request:"+com$+"</body></html>"
          delay 0 : _CGI_$ = ""

          s$ = "WEB: " : if dbg then syslog s$+com$
          if mid$(com$,1,1)="m" then i = val(mid$(com$,3,1)) : b = val(mid$(com$,4,1)) : goto 235
          if mid$(com$,1,1)="v" then vol = val(mid$(com$,3,2)) : write 7,str$(vol),-12 : return
          syslog s$+"wrong ASCII command: "+com$ : return
       endif
       gosub 300 'CGI request/reply
       _CGI_$ = "" : return
    endif

    read 3,com$,0 : lcom = lastlen(3)       'check serial for X8/RS volume and button control

    if and(lcom = 17, com$ <> comX8$, mid$(com$,1,1)="D") then 'it is X8 sending
       s$ = "X8: " : comX8$ = com$ : if dbg then syslog s$+com$

       new_v$ = mid$(com$,2,2)           'check the new HW volume
       if new_v$ <> old_v$ then          'if HW Volume is changed
          old_v$ = new_v$
          vol = ((asc(mid$(com$,2,1))-48)*16+(asc(mid$(com$,3,1))-48))*1000*dft_v/255/1000
          if dbg then syslog "vol = "+str$(vol)
          write 7,str$(vol),-12
       endif

       for i = 1 to 7
          v = (asc(mid$(com$,2*i+2,1))-48)*16+(asc(mid$(com$,2*i+3,1))-48) 'value of this input
          if v < 253 then 'value with possible jitter
             for b = 0 to 9
                 r_min = b*res : r_max = (b+1)*res
                 bnd = 128*r_min/(10000+r_min)+128*r_max/(10000+r_max) 'middle boundary
                 if dbg then syslog "v="+str$(v)+" : b="+str$(b)+" : bnd="+str$(bnd)
                 if v <= bnd then goto 235 'this button is pressed
             next b
             syslog "input"+str$(i)+" = "+str$(v)+" > "+str$(bnd)+" (boundary for max button"+str$(b-1)+ "). Check your settings..."
          else
             if and(i_old = i, b_old <> -1, s_old$ = s$) then goto 240 'button b_old is released
          endif
       next i

    endif 'end check of X8

    if and(lcom = 4, mid$(com$,2,1)="=") then 'it is RS ASCII sending
       s$ = "RS: " : if dbg then syslog s$+com$
       if mid$(com$,1,1)="m" then i = val(mid$(com$,3,1)) : b = val(mid$(com$,4,1)) : goto 235
       if mid$(com$,1,1)="v" then vol = val(mid$(com$,3,2)) : write 7,str$(vol),-12 : return
       syslog s$+"wrong ASCII command: "+com$ : return
    endif 'end check of RS

    if UDP_p then
       lcom = -lastlen(5) : if lcom > 0 then read 5, com$ else goto 233 'check UDP packets

       if and(lcom = 4, mid$(com$,2,1)="=") then 'it is UDP ASCII sending
          s$ = "UDP: " : if dbg then syslog s$+com$
          if mid$(com$,1,1)="m" then i = val(mid$(com$,3,1)) : b = val(mid$(com$,4,1)) : goto 235
          if mid$(com$,1,1)="v" then vol = val(mid$(com$,3,2)) : write 7,str$(vol),-12 : return
          syslog s$+"wrong ASCII command: "+com$ : return
       endif 'end check of UDP
233 endif

    'check digital inpit buttons on Ann100/1000
    i = 0 : s$ = "IO: "
    for b = 0 to hwb 'NB! HW dependant -- change "1" to "7" for Ann1000 or IPAM
       if iostate(201 + b) = 0 then goto 235 'button is pressed
    next b
    if and(i_old = i, b_old <> -1, s_old$ = s$) then goto 240 'button is released

    return

235 'button is pressed
    if not(and(i=i_old,b=b_old,or(s_old$="X8: ",s_old$="IO: "))) then 'if new button is pressed
       cm$ = s$+str$(i)+str$(b)+" [i"+str$(i)+":b"+str$(b)+"] is closed/clicked" : syslog cm$
       inp   = i : btn   = b
       i_old = i : b_old = b : s_old$ = s$
       state = 1 'start playing the proper file
    endif
    return 'only one button can be pressed at the time

240 'button is released
    cm$ = s_old$+str$(i_old)+str$(b_old)+" [i"+str$(i_old)+":b"+str$(b_old)+"] is opened" : syslog cm$
    i_old = -1 : b_old = -1 : s_old$ = "" 'restore initial for input, button, source
    if pf$ = "M" then state = 0 'stop instant file
    return 'only one button can be released at the time

'------------------------------------------------------------------------------
300 'CGI request/reply
'------------------------------------------------------------------------------
    syslog "CGI request: "+_CGI_$

    if _CGI_$ = "cmd=table" then 'table request

       mf$ = "C_R:usb:///messages.txt" : open mf$ as 4 : if mediatype(4) then goto 301
       mf$ = "F_R:messages.txt"        : open mf$ as 4 : if mediatype(4) then goto 301
       mf$ = "" 'flag "no messages.txt"
301    'continue...

       _CGI_$ = "" : delay 10
       write -1,"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n",0
       write -1,"<html><head><title>Message Table</title></head><body><table border=1>",0
       write -1,"\r\n<tr><td><b>N</b></td><td><b>File</b></td><td><b>Type</b></td><td><b>Relay</b></td><td><b>Text</b></td></tr>",0
       if mediatype(6) then close 6 : state  = 0
       for in = 0 to 9
          for bn= 0 to 9
             nn$ = str$(in)+str$(bn) : bfile$ = "MSG"+nn$ : gosub 220 'check file
             if mediatype(6) then close 6
             if file$ then
                write -1,"\r\n<tr><td><a href='/basic.cgi?m="+nn$+"' target='empty' title='call this message'>"+nn$+"</a></td>",0
                write -1,"<td>"+file$+"</td>",0
                if pf$ = "M" then write -1,"<td>momentarily</td>",0
                if pf$ = "O" then write -1,"<td>once</td>",0
                if pf$ = "R" then write -1,"<td>repeated</td>",0
                if rf$ = "!" then write -1,"<td>ON</td>",0 else write -1,"<td>OFF</td>",0
                if mf$ then
                   seek 4,0 'rewind messages.txt, if need
302                read 4,tmp$,0 : if lastlen(4) <= 0 then write -1,"<td>&nbsp;</td>",0 : goto 303
                   if mid$(tmp$,1,2) = nn$ then write -1,"<td>&nbsp;"+mid$(tmp$,4)+"</td>",0 : goto 303
                   goto 302 'read next line from messages.txt
                else
                   write -1,"<td>&nbsp;</td>",0
303             endif
                write -1,"</tr>",0
             endif
          next bn
          write -1," ",0 'NB!??? necessary to avoid HTTP error 405?
       next in
       write -1,"\r\n</table></body></html>\r\n",0
       if mediatype(4) then close 4
       delay 10 : _CGI_$ = "*" : delay 10 : _CGI_$ = "" : return

    endif 'end of table request

    if _CGI_$ = "cmd=panel" then 'panel request

       mf$ = "C_R:usb:///messages.txt" : open mf$ as 4 : if mediatype(4) then goto 311
       mf$ = "F_R:messages.txt"        : open mf$ as 4 : if mediatype(4) then goto 311
       mf$ = "" : goto 399 'flag "no messages.txt" -- to finish for panel request
311    'continue...

       _CGI_$ = "" : delay 10
       write -1,"HTTP/1.0 200 OK\r\nContent-type: text/html\r\n\r\n",0
       write -1,"<html><head><title>Button Panel</title></head><body><table><tr>",0

312    read 4,tmp$,0 : if lastlen(4) <= 0 then goto 313
       if len(tmp$)=0 then write -1,"\r\n</tr><tr>",0 : goto 312
       write -1,"\r\n<td><form action='/basic.cgi' method='GET' target='empty'>",0
       write -1,"<input type='hidden' name='m' value='"+mid$(tmp$,1,2)+"'>",0
       write -1,"<input type='submit' value='"+mid$(tmp$,4)+"'></form></td>",0
       goto 312 'read next line from messages.txt

313    write -1,"\r\n</tr></table></body></html>\r\n",0
       if mediatype(4) then close 4
       delay 10 : _CGI_$ = "*" : delay 10 : _CGI_$ = "" : return

    endif 'end of panel request

399 'reply for wrong request
    _CGI_$ = "" : delay 0 : _CGI_$ = "<html><head></head><body>Wrong Request</body></html>"
    return
'------------------------------------------------------------------------------
