!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! SD360 - Spectral Dynamics NeXtMidas Macro
!
! @author Jeff Schoen
!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
startmacro/msgid=main/remote=localhost:9000/poll=.001 d:samples s:format
switch DEBUG   debug        GET DEF=false SDEF=true
switch VERBOSE verbose      GET DEF=false SDEF=true
switch STATEM  statemachine GET DEF=false SDEF=true

timer set

switch "SRATE" sr    get 1e5
switch "OVER"  over  get 0
switch "SFREQ" sfreq get sr/10
switch "CFREQ" cfreq get 0
switch "AMP"   amp   get 1e4
switch "NEXP"  nexp  get 1
switch "NAVG"  navg  get 1
switch "NFFT"  nfft  get 1k

switch "PKTSIZE" l:pktsize get 3

pipe init

panel/setup/controls=gc

gc label macro "SD360"

if /server neqs "NULL"

  switch SERVER l:port get 9000

  waveform _wave format 10e10 sin freq=sfreq amp=amp delta=1/sr /throttle=real
  fft _wave _waveb{form=sb} nfft=nfft navg=navg over=over /dbf
  rmif/STATEM=^statemachine/VERBOSE=^verbose/http port sfreq|_waveb /ppt={RETRY=2,TIMEPING=3}

  gc button state "" "Run,Pause,Exit" /idef=1 /toff /input
  gc dvalue sfreq "SineFreq" sfreq -sr sr sr/20
  gc dvalue cfreq "CentFreq" cfreq -sr sr sr/20
  gc choice test  "Test    " "Get,Set,Reset,Ping,Keys,Send,Recv,PktSize"
  gc dvalue linkbw  "Link BW " 0 0 128e3 1 /edit=0 /fmt="###.### ?by/s"
  gc lvalue linklat "Link Lat" 0 0 100000 1 /edit=0 /fmt="##### msec"

elseif /client neqs "NULL"

  switch CLIENT l:port get 9002
  env get "SERVER" remote

  rmif/STATEM=^statemachine/VERBOSE=^verbose/http/prange=5 port ,, {ID=XM,HP=^remote} q:ack|_waveb

  gc button state "" "Open,Close,Exit"
  gc dvalue sfreq "SineFreq" 0 -sr sr sr/20
  gc dvalue cfreq "CentFreq" 0 -sr sr sr/20
  gc choice test  "Test    " "Get,Set,Reset,Ping,Keys,Send,Recv,PktSize"
  gc choice comp  "Compress" "Off,Data,Plot" /idef=1
  gc dvalue linkbw  "Link BW " 0 0 128e3 1 /edit=0 /fmt="###.### ?by/s"
  gc lvalue linklat "Link Lat" 0 0 100000 1 /edit=0 /fmt="##### msec"

else  ! local version

  waveform _wave format samples sin freq=sfreq amp=amp delta=1/sr
  fft _wave _waveb nfft=nfft navg=navg over=over /dbf

  gc button state "Action  " "Run,Pause,Exit" "Run"
  gc choice shape "Shape   " reg.waveform.shapeList /idef=1
  gc choice wind  "Window  " reg.fft.windowList /idef=2
  gc dvalue sfreq "Sine Freq" sfreq -sr sr sr/20
  gc dvalue cfreq "Center Freq" cfreq -sr sr sr/20
  gc choice fftsz "FFT Size" "250,512,768,1K,2000,2K,4000,4K,8K" "1K"
  gc dvalue over  "Overlap " over 0 1 .1 /mon=reg.fft.over /msg=F
  gc lvalue nexp  "Average "  nexp 1 100 1 /mon=reg.fft.nexp /msg=F
  gc choice form  "Format  " "SF,CF,SI,CI" reg.waveform.format

endif

if /headless isfalse then
  ! The {CL=8} qualifier tells plot to consume 8 frames of data for each frame of data that was
  ! plotted (this is because {TL=1} is implicit). In effect this provides a very fast block
  ! thin of the data before it is displayed by the line plotter.
  plot/id=plot1/nice _waveb{cl=8} cnt=motion type=line y1=-100 y2=80 MIMIC=plot2
  plot/id=plot2/nice _waveb       cnt=click            z1=-100 z2=80 MIMIC=plot1 /lpb=16
  feature ,, mark1 {TYPE=SYM|VRIDE,SYMBOL=CIRCLE,NAME=MARK,COLOR=YELLOW,ENABLE=1,X=SR/10} plot1
  gc label  debug "Debug" 0
  gc choice tests "Test    " "PopUp,Active,Procedure,Subroutine,SubThread,Files,Dialog,Plot"
  gc pipemon pmon _waveb
endif

if /icons pexists then
  switch "ICONS" icons get
  fname icdir "ICONS" "/" "" ice
  set reg.panel.icondir icdir
  set reg.panel.panes.plot2.iconbar icons
endif

set this.timers 1
set this.timer(0) 2
if /server le 0 and /client le 0 pipe waitfor waveform
pipe off

timer elapse

endmacro


!******************************************************************************!
! This is the callback procedure that is automatically called by NeXtMidas
! when there is a (targeted or automatic) message (msg) to send to this macro.
! See the Users's Guide ->Macros ->Messages in Macros section for more details
!******************************************************************************!
procedure processMessage m:msg
  if debug then
    say "^reg.main.name: Got message name=^msg.name fid=^msg.fid info=^msg.info data=^msg.data"
  endif

if msg.name eqs "TIMER" AND msg.info EQ 0 then
  if reg.rmif rexists and gc.LINKBW rexists  ! /server or /client
    set gc.LINKBW.value reg.rmif.linkBW
    set gc.LINKLAT.value reg.rmif.linkLatency
  endif

elseif msg.name eqs "STATE"
 if msg.data eqs "EXIT"
  pipe stop
 elseif msg.data eqs "PAUSE"
  pipe pause
 elseif msg.data eqs "RUN"
  pipe wait
 elseif msg.data eqs "OPEN"
  send "RMIF" "OPEN" {ID=XM,HP=^remote} /SYNC
  send "XM" "ADDC" "Q:ACK" 1
  send "XM" "ADDC" {_WAVEB=_WAVEB} 2
 elseif msg.data eqs "CLOSE"
  send "XM" "CLOSE"
 else
  warn "Unknown Action=^msg.data"
 endif

elseif msg.name eqs "GET"
  ! fill in the table values
  foreach key inTable msg.data
    set msg.data.^key gc.^{key}.value
  endfor
  ! send back the results to the client
  send msg.fid "RET" msg.data

elseif msg.name eqs "RET"
  ! fill in the table values
  foreach key inTable msg.data
    set gc.^{key}.value msg.data.^key
  endfor

elseif msg.name eqs "SET"
  ! loop through the table values
  foreach key inTable msg.data
    set gc.^{key}.action msg.data.^key
  endfor
  ! send back the results to the client
  sendto msg.fid "ACK" msg.data

elseif msg.name eqs "ACK"
  ! loop through the table values
  foreach key inTable msg.data
    set gc.^{key}.value msg.data.^key
  endfor

elseif msg.name eqs "PROPERTY"
  say "Got Remote Property ^msg.data"

elseif msg.name eqs "TEST"
  if msg.data eqs "PING"
    sendto "XM" "PING"
  elseif msg.data eqs "GET"
    sendto "XM" "GET" {SFREQ=,CFREQ=}
  elseif msg.data eqs "SET"
    sendto "XM" "SET" {SFREQ=20e3,CFREQ=10e3}
  elseif msg.data eqs "RESET"
    sendto "XM" "SET" {SFREQ=^sfreq,CFREQ=^cfreq}
  elseif msg.data eqs "KEYS"
    sendto "XM" "KEYS"
  elseif msg.data eqs "SEND"
    sendto "XM" "TESTLINK" info=pktsize
  elseif msg.data eqs "RECV"
    sendto "XM" "TESTLINK" info=-pktsize
  elseif msg.data eqs "PKTSIZE"
    gc/temp menu pktsize "PktSize" "2,4,8,16,32,64,128,256,512,1K,2K,4K,8K,16K,32K" pktsize
  endif

elseif msg.name eqs "TESTS"
  if msg.data eqs "POPUP"
    gc/wait prompt timeup "Time Up: "
    gc/wait prompt duration "Duration: "
  elseif msg.data eqs "ACTIVE"
    set gc.DEBUG.active 0
  elseif msg.data eqs "PROCEDURE"
    call testproc 1 2 3
  elseif msg.data eqs "SUBROUTINE"
    call testsub 1 2 3 msg
  elseif msg.data eqs "SUBTHREAD"
    call/bg testsub 4 5 6 msg
  elseif msg.data eqs "DIALOG"
    gc/temp/handle=dlog/wtheme=browser dialog "DIALOG" "Test Dialog Box" 300 -6 "Apply,Submit,Cancel" "Apply"
    gc/panel=dlog choice shape "Shape   " reg.waveform.shapeList reg.waveform.shape
    gc/panel=dlog button wind  "Window  " reg.fft.windowList reg.fft.window /tleft /nc=3
    gc/panel=dlog dvalue sfreq "SineFreq" reg.waveform.freq sfreq -sr sr sr/20
    gc/panel=dlog text   text  "TextInfo" "A test message" 30 3
    gc/panel=dlog menu   form  "Format  " "SF,CF,SI,CI" reg.waveform.format /tleft /nc=4
    gc/panel=dlog list   list  "TextList" "A,B,C,D,E,F,G,Another Long One" 30 3
  elseif msg.data eqs "FILES"
    gc/temp file FILE "File " "abc"
  elseif msg.data eqs "PLOT"
    plot/bg _waveb
  endif

elseif msg.name eqs "DIALOG"
  set gc.wind.action msg.data.wind.value
  set gc.shape.action msg.data.shape.value
  set gc.sfreq.action msg.data.sfreq.value
  set gc.form.action msg.data.form.value

elseif msg.name eqs "PKTSIZE"
  set l:pktsize ^msg.info

elseif msg.name eqs "WIND"
  set reg.fft.window msg.data

elseif msg.name eqs "SHAPE"
  set reg.waveform.shape msg.data

elseif msg.name eqs "FFTSZ"
  set reg.fft.nfft ^msg.data

elseif msg.name eqs "FORM"
  set reg.waveform.format msg.data

elseif msg.name eqs "SFREQ"
  if /client le 0 set reg.waveform.freq msg.data
  if /client gt 0 send "XM" "SET" {SFREQ=^msg.data}
  if /server gt 0 send "RMIF" "ACK" {SFREQ=^msg.data}

elseif msg.name eqs "CFREQ"
  ! nothing to do yet
  if /client gt 0 send "XM" "SET" {CFREQ=^msg.data}
  if /server gt 0 send "RMIF" "ACK" {CFREQ=^msg.data}

elseif msg.fid eqss "PLOT" then
  res fid msg.fid
  if msg.name eqs "POINTER"
    pause 0.1
    message prune ,, msg
    if fid eqs "PLOT1" then set msg.name "MARK"
  endif
  if msg.name eqs "MARK" then
    set mark1.x ^msg.data.x  ! Update plot marker
    set gc.SFREQ.action msg.data.x
    if fid eqs "PLOT2" then set gc.CFREQ.action msg.data.x
  endif
  if msg.name neqs "MARK" and /client gt 0 and reg.xm.status eqs "OPENED" then
    set tmp reg.^fid
    send "XM" "MODIFY" {PROPERTY=_WAVEB,TRIM1=^tmp.x1i,TRIM2=^tmp.x2i}
    say "Trimming to ^tmp.x1i ^tmp.x2i"
  endif

elseif msg.name eqs "COMP"
  set l:tmp1 gc.COMP.item-1
  set l:tmp2 reg.PLOT1.ix21
  info "Setting compression = ^tmp1 with plotwidth = ^tmp2"
  send "XM" "MODIFY" {PROPERTY=_WAVEB,COMP=^tmp1,PLOTWIDTH=^tmp2}

elseif msg.name eqs "LINKERR" then
  say "LinkErr = ^msg.data"

elseif msg.name eqs "PROPERTY" then
  say "Got Remote property ^msg.data"

elseif msg.name eqs "OPENED" then
  send "XM" "GET" {SFREQ=?,CFREQ=?}

elseif msg.name eqs "CLOSED" OR msg.name eqs "OPEN" OR msg.name eqs "CLOSE" then
  ! do nothing
else
  say "Unhandled message ^msg.name = ^msg.data from ^msg.fid"
endif
return

procedure init
!say "In init"
return

procedure open
!say "In open"
return

procedure close
!say "In close"
return

procedure testproc pa1 pa2 pa3
say "Called TESTPROC ^pa1 ^pa2 ^pa3"
results
return

subroutine testsub l:pa1 l:pa2 l:pa3 o:pa4
say "Called TESTSUB ^pa1 ^pa2 ^pa3"
results
gc/wait prompt duration1 "Duration1: "
say "Called TESTSUB back from Popup1"
gc/wait prompt duration2 "Duration2: "
say "Called TESTSUB back from Popup2"
return
