pro command_laser,buff,device,device=device1,resp=resp,value=value,rawresp=rawresp,nowait=nowait
;+
;  Name:
;    command_laser
;  Purpose:
;    Command the laser disk player/recorder -- using C routine to get response.
;
;  Calling Sequence:
;    command_laser, buff [,device=device, rawresp=rawresp, value=value]
;    command_laser, buff [,device, resp=resp, rawresp=rawresp, nowait=nowait]
;    command_laser, buff [,device]
;
;  Note:
;    'play' replaces a lot of the commands that might clutter up a command
;	list.  it does slow step, and fast play.  on the panasonics it
;	can go up to 10x speed.  on the sony, it only defaults to 3x speed.
;	for slower than 1x rates, there are 255 speeds.
;	this command also determines which direction to go; it's not
;	automatic on the panasonic.
;    calling sequence for play:
;
;	command_laser,'play',device=1,value=[128./255,end_frame]
;
;    the type of machine is determine by the response on the terminal
;    line.  the terminal line is expected to be 9600 baud for the PANASONIC,
;    and 1200 baud for the SONY; the SONY has problems losing characters
;    if they are sent too fast (might only be a problem with the
;    model 3000 series SONY).
;
;    this routine depends on the C routine 'call.c' written in 1/95
; 
;  Input:
;    buff   = String containing command, .eg. 'eject', 'rec', 'record'
;  Optional Input Keyword:
;    device = 0 or 1 for recorder or player (def=0)
;             (device can also just be a input parameter)
;    value = value that might be required for that particular type of
;		command, such as 'jump' (need frame number)
;		'play' needs an array of 2 numbers
;			value(0)=.004-10
;			value(1)=end frame-number
;    nowait = flag to tell C program NOT to wait for complete response from
;		the laser disk player.
;
;  Optional output keyword:
;    resp   = response from laser disk
;    rawresp = response from the laser disk (byte form) sometimes, ascii
;				just won't do.
;
;  Common Blocks:
;	LASER
;  Procedure:
;    given the string passed by 'buff', this routine looks through its
;    list of known commands to see if it knows how to control the
;    SONY, or PANASONIC machines.  the equivalent instruction is looked
;    up, depending on what machine is being commanded.
;
; 
;  Modification History:
;	feb-1995 - written by L. Shing
;		commented out fast-forward, and forwar-play commands
;		these are superseded by the play command
;	oct-1995, LS , added a wait statement to make it work with the
;		SONYs in japan.
;-

COMMON LASER,device_str,device_type,call_path,SONY,PANASONIC,stx,etx

on_error,2			; Return to caller if there is a problem

if n_params() eq 0 then return

; Default to 0 (recorder) if undefined (parameter has precedence over keyword)
if (n_elements(device) eq 0) and (n_elements(device1) eq 0) then device = 0 $
else if (n_elements(device) eq 0) and (n_elements(device1) gt 0) then $
        device=device1


; recurse if buff is a vector of commands.
if (n_elements(buff) gt 1 ) then begin
        for indx=0,(n_elements(buff)-1) do $
          command_laser,buff(indx),device,resp=resp,rawresp=rawresp,value=value
	return
endif


; initialize the common variables if they aren't already defined
if (n_elements(device_type) eq 0) then laser_init


; figure out what it is if we've never run the port before
if (device_type(device) eq -1) then get_laser_type,device


; create the string equivalent of ,value, if it was passed
;			might need it in constructing the command
if (n_elements(value) ne 0) then begin
		v=abs(value)
		val=strtrim(string(long(v)),2)
		endif else val=''

ps=0
direction=0
if (n_elements(value) gt 1) then begin
		command_laser,'@',device=device,resp=ps
		direction=long(v(1))-ps
		endif


; go case insensitive
buff=strlowcase(buff)

; the following are possible commands known, and in ascii
; a space defines the beginning of the command
; this is done so that expressions in the middle of a word won't be
; intrepretted as a possible command
ENTER=string('40'xb)
REP=string('44'xb)

BP=' beep bp'
BP_COMMANDS=['huh?', 'BP'+val(0)+':']

STAT=' status stat'
STAT_COMMANDS=[string('67'xb), 'PS'+val(0)+':']

EJ=' eject ej'
EJ_COMMANDS=[string('2A'xb), 'EJ']

AC=' all clear ac cl ca'
AC_COMMANDS=[string('56'xb), 'AC']

REC=' record rec'
REC_COMMANDS=[string('E9'xb), 'GS:']
; uncomment the next line if you don't want to record.  same as forward step.
;REC_COMMANDS=[string('2B'xb), 'JF1:']  ; this line is for testing purposes RECTEST

RECM=' rm'
RECM_COMMANDS=[string('E0'xb), 'RM']

RR=' rr'
RR_COMMANDS=[string('BC'xb), 'RR']

CRECM=' rc'
CRECM_COMMANDS=[string('56'xb), 'RC']

ON=' online on'
ON_COMMANDS=['', 'ON']

OFF=' offline off of'
OFF_COMMANDS=['', 'OF']

POS=' pos position where frame number fn no @'
POS_COMMANDS=[string('60'xb), 'NO']

JMP=' jump go goto jp jmp search srch'
JMP_COMMANDS=['CU'+val(0)+'@', 'SR'+val(0)+':']

;FP=' forwardplay fplay fwdplay fp'
;FP_COMMANDS=[string('3A'xb), 'PF'+val(0)+':']

FS=' fstep fwdstp stp inc increment next'
FS_COMMANDS=[string('2B'xb), 'JF1:']

;FF=' fastforward ff'
;FF_COMMANDS=[string('3B'xb), 'FF'+val(0)+':']

RS=' rstep decrement dec back previous'
RS_COMMANDS=[string('2C'xb), 'JR1:']

PLAY=' play vplay'
PLAY_COMMANDS=['','']

; construct the complex 'play' command for forward, backward, speed
nl=n_elements(v)
if (nl gt 2) then nrep=strtrim(string(long(v(2))),2) $
		else nrep='1'
if (nl gt 1) then $
   if (v(0) le 1) then begin
	v(0)=1/(v(0)+.0001)+.5
	if (v(0) gt 255) then v(0)=255
	val(0)=strtrim(string(long(v(0))),2)
	if (direction gt 0) then $
		PLAY_COMMANDS=[REP+val(1)+string('3D'xb)+ENTER+nrep+ENTER+val(0)+ENTER,'LF'+val(0)+':'+val(1)+':'] $
		else PLAY_COMMANDS=[REP+val(1)+string('3D'xb)+ENTER+nrep+ENTER+val(0)+ENTER,'LR'+val(0)+':'+val(1)+':']
	endif else begin
		if (v(0) gt 10) then v(0)=10
		pana_speed=strtrim(string(long(v(0)+.5)),2)
		if (direction gt 0) then $
		  PLAY_COMMANDS=[REP+val(1)+string('3B'xb)+ENTER+nrep+ENTER,'FF'+pana_speed+':'+val(1)+':'] $
		  else PLAY_COMMANDS=[REP+val(1)+string('3B'xb)+ENTER+nrep+ENTER,'FR'+pana_speed+':'+val(1)+':']
		endelse
;

HLP=' help hlp ?'

indx=device_type(device)

noparse=1
; go through each of the known commands, and get the proper command
;					to send to the machine
case 1 of 

; the most used commands should be placed on top of the case statement
; this is in case the command is ambiguous, and more than one interpretation
; is possible.
        strpos(AC,' '+buff) ne -1: command=AC_COMMANDS(device_type(device))
        strpos(POS,' '+buff) ne -1: command=POS_COMMANDS(indx)
        strpos(JMP,' '+buff) ne -1: command=JMP_COMMANDS(indx)
        strpos(FS,' '+buff) ne -1: command=FS_COMMANDS(indx)
        strpos(REC,' '+buff) ne -1:command=REC_COMMANDS(indx)
	strpos(RECM,' '+buff) ne -1:begin
					command_laser,'clear',device
					command=RECM_COMMANDS(indx)
				    end
	strpos(CRECM,' '+buff) ne -1:command=CRECM_COMMANDS(indx)
	strpos(ON,' '+buff) ne -1: command=ON_COMMANDS(indx)
	strpos(OFF,' '+buff) ne -1: command=OFF_COMMANDS(indx)
        strpos(RS,' '+buff) ne -1: command=RS_COMMANDS(indx)
;        strpos(FP,' '+buff) ne -1: command=FP_COMMANDS(indx)
	strpos(BP,' '+buff) ne -1: command=BP_COMMANDS(indx)
	strpos(EJ,' '+buff) ne -1: command=EJ_COMMANDS(indx)
;	strpos(FF,' '+buff) ne -1: command=FF_COMMANDS(indx)
	strpos(STAT,' '+buff) ne -1: command=STAT_COMMANDS(indx)
	strpos(RR,' '+buff) ne -1: command=RR_COMMANDS(indx)
	strpos(PLAY,' '+buff) ne -1: begin
		if (n_elements(v) lt 2) then stop,'****error in command_laser ****** "play" needs 2 values, speed and end-frame'
		command_laser,'clear',device
		noparse=2
		command=PLAY_COMMANDS(indx)
		end

		; the help command
	strpos(HLP,' '+buff) ne -1: begin
		print,''
		print,'COMMAND      :  possible permutations to recognize command'
		print,'------------------------------------------------------'
		print,'*beep            :'+BP
		print,'eject            :'+EJ
		print,'all clear        :'+AC
		print,'on line          :'+ON
		print,'off line         :'+OFF
		print,'record mode      :'+RECM
		print,'clear record mode:'+CRECM
		print,'status           :'+STAT
		print,'record 1         :'+REC
		print,'position         :'+POS
		print,'**jump           :'+JMP
		print,'***play          :'+PLAY
;		print,'*forward play    :'+FP
;		print,'fast forward     :'+FF
		print,'*forward step    :'+FS
		print,'reverse step     :'+RS
		print,''
		print,'-------------------------------------------------------'
		print,' note, all commands are case insensitive'
		print,'*  : value parameter optional'
		print,'** : needs a value'
		print,'***: needs 2 values, speed & end-frame, '
		print,'            e.g. value=[.5,300] implies half speed to frame 300'
		command=''
		end
	else: command='huh?'
endcase

; send the command using laser_write
if (command(0) eq 'huh?') then print,"don't know how to do that with this device" $
      else if (command(0) ne '') then laser_write,command,device=device,resp=resp,rawresp=rawresp,nowait=nowait,noparse=noparse

case 1 of
; do some post processing of the commands.  for instance, calculating frame
; numbers and converting the response to long.

  strpos(POS,' '+buff) ne -1: begin
	if (n_elements(rawresp) lt 5) then command_laser,'@',device,resp=resp
	if (data_type(resp) ne 3) then resp=long(strmid(resp,strpos(resp,'O')+1,5))
	end
  strpos(RR,' '+buff)  ne -1: begin
	if (device_type(device) eq SONY) then begin
		first_frame=long(strmid(resp,0,5))
		last_frame=long(strmid(resp,5,5))
		resp=last_frame-first_frame
		endif else resp=long(strmid(resp,strpos(resp,'R')+2,5))
	end
  strpos(RECM,' '+buff) ne -1: begin
	if (device_type(device) eq SONY) then begin
		laser_write,ENTER,device
        	laser_write,ENTER,device
        	laser_write,ENTER,device
		wait,1
	      endif
	command_laser,'RR',device,resp=resp,rawresp=rawresp
	end
  else: command='huh?'
endcase
return
end
