home *** CD-ROM | disk | FTP | other *** search
- (in-package :oou)
- (oou-provide :NEC-PC-VCR-vp)
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
- ;; NEC-PC-VCR-vp.lisp
- ;;
- ;; Copyright ⌐ 1991 Northwestern University Institute for the Learning Sciences
- ;; All Rights Reserved
- ;;
- ;; author: Michael S. Engber
- ;;
- ;; video player class for controling Pioneer laserdisc players
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (oou-dependencies :video-player
- :serial-port
- )
-
- (export '(NEC-PC-VCR-vp
- ))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defclass NEC-PC-VCR-vp (serial-port video-player)
- ((tape-format :reader tape-format)
- (stop-frame)
- (check-tape-on-load-p :accessor check-tape-on-load-p
- :initarg :check-tape-on-load-p))
- (:default-initargs
- :check-tape-on-load-p t
- :open-on-init-p nil
- :baud 1200))
-
- (defmethod vp-features ((vp NEC-PC-VCR-vp))
- '(:freeze :step-forward :scan))
-
- (defmethod vp-init :after ((vp NEC-PC-VCR-vp))
- (sport-open vp :flush-p nil)
- (npv-cmd vp "PW" :arg 1))
-
- (defmethod vp-dispose :after ((vp NEC-PC-VCR-vp))
- (sport-close vp))
-
- (defmethod vp-load ((vp NEC-PC-VCR-vp) &key)
- (when (eq :no-tape (npv-cur-state vp)) (error "no tape in PC-VCR"))
- (when (check-tape-on-load-p vp)
- (let ((header-str (npv-cmd vp "HR" :error-p nil)))
- (when (char= #\E (char header-str 0))
- (error "tape does not have address codes (~s)" header-str))))
- (let ((fmt-string (npv-cmd vp "DS" :arg 7)))
- (setf (slot-value vp 'tape-format)
- (cond ((string= fmt-string "STANDARD") :SP)
- ((string= fmt-string "EXTENDED") :EP)
- (t (error "unknown tape format ~s" fmt-string)))))
- (vp-seek vp 90)
- (vp-play vp)
- (vp-freeze vp)
- (setf (slot-value vp 'stop-frame) (npv-cur-frame vp))
- t)
-
- (defmethod vp-loaded-p ((vp NEC-PC-VCR-vp))
- (and (slot-boundp vp 'tape-format)
- (not (eq :no-tape (npv-cur-state vp)))))
-
- (defmethod vp-max-frame ((vp NEC-PC-VCR-vp)) 999999)
-
- (defmethod vp-min-frame ((vp NEC-PC-VCR-vp)) 90)
-
- (defmethod vp-current-frame ((vp NEC-PC-VCR-vp))
- (let ((state (npv-cur-state vp)))
- (if (eq state :stop)
- (slot-value vp 'stop-frame)
- (let ((addr (npv-cur-addr vp))
- (fr (if (eq state :play-ps) (npv-cur-rel-frame vp) 0)))
- (+ (* 30 addr) fr)))))
-
- (defmethod vp-seek ((vp NEC-PC-VCR-vp) frame &key &allow-other-keys)
- (npv-cmd vp "JF" :frame frame :format :frame)
- t)
-
- (defmethod vp-play ((vp NEC-PC-VCR-vp))
- (if (frame-limit-p vp)
- (npv-cmd vp "SP" :frame (max-frame-limit vp) :format :addr+fr))
- (npv-cmd vp "PL")
- t)
-
- ;before we stop - we must record our frame number cause the PC-VCR
- ;won't give it to us once we're stopped.
- (defmethod vp-stop :before ((vp NEC-PC-VCR-vp))
- (case (npv-cur-state vp)
- (:stop )
- (:play-ps (setf (slot-value vp 'stop-frame) (npv-cur-frame vp)))
- (otherwise (npv-cmd vp "PS")
- (setf (slot-value vp 'stop-frame) (npv-cur-frame vp)))))
-
- (defmethod vp-stop ((vp NEC-PC-VCR-vp))
- (case (npv-cur-state vp)
- (:stop )
- (:play-ps (npv-cmd vp "ST"))
- (otherwise (npv-cmd vp "ST")))
- t)
-
- (defmethod vp-freeze ((vp NEC-PC-VCR-vp))
- (case (npv-cur-state vp)
- (:play-ps )
- (:stop )
- (otherwise (npv-cmd vp "PS")))
- t)
-
- (defmethod vp-step ((vp NEC-PC-VCR-vp) direction)
- (ecase direction
- (:forward
- (npv-ensure-paused vp)
- (npv-cmd vp "FS"))
- (:reverse
- (error "NEC-PC-VCR doesn't support reverse stepping.")))
- t)
-
-
- ;;SL can be improved
- (defmethod vp-scan ((vp NEC-PC-VCR-vp) direction speed-x)
- (flet ((pick-high-speed (req-speed tape-format)
- (ecase tape-format
- (:SP (if (< req-speed 8) 1 2))
- (:EP (if (< req-speed 19) 1 2)))))
- (ecase direction
- (:forward
- (cond
- ((> speed-x 1)
- (npv-cmd vp "FF" :arg (pick-high-speed speed-x (tape-format vp))))
- ((< speed-x 1)
- (vp-play vp)
- (npv-cmd vp "SL"))
- (t
- (vp-play vp))))
- (:reverse
- (npv-cmd vp "RW" :arg (pick-high-speed speed-x (tape-format vp)))))
- t))
-
- ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
- (defvar *npv-error-strings*
- #("(0) PC-VCR not powered on"
- "(1) tape address read incorrectly"
- "(2) no tape in unit"
- "(3) unused error code"
- "(4) syntax error (unrecognized command)"
- "(5) invalid, missing, or excess parameters"
- "(6) command buffer overflow"
- "(7) unused error code"
- "(8) tape header read incorrectly"
- "(9) command execution failed or current mode prevented execution"
- ))
-
-
- (defun npv-echeck (result-string cmd-string verbose-p)
- (when (char= #\E (char result-string 0))
- (when verbose-p
- (error "~s :~s ~% >~s"
- cmd-string
- result-string
- (svref *npv-error-strings* (parse-integer result-string :start 2)))))
- t)
-
- (defvar *npv-status-keys*
- #(
- :no-tape :stop :rec :rec-ps :ff
- :j-srch :p-srch :play :unused :play-ps
- :rp-srch :rj-srch :rew :sc-ff :sc-play
- :sc-rew :slow-1/30 :slow-1/10 :slow-1/5 :pi-ps
- :pi-play :ad-ps :ad-play :ai-ps :ai-play
- ))
-
- (defmethod npv-cur-state ((vp NEC-PC-VCR-vp))
- (let ((state-code-str (npv-cmd vp "DS")))
- (unless (and (char= #\S (char state-code-str 0)) (char= #\S (char state-code-str 1)))
- (error "malformed state code ~s." state-code-str))
- (svref *npv-status-keys* (parse-integer state-code-str :start 2))))
-
- ;can only be called from :play-ps or :play state
- (defmethod npv-cur-addr ((vp NEC-PC-VCR-vp))
- (parse-integer (npv-cmd vp "RP" :arg 0) :start 2))
-
- ;can only be called from :play-ps state
- (defmethod npv-cur-rel-frame ((vp NEC-PC-VCR-vp))
- (parse-integer (npv-cmd vp "RF") :start 2) 0)
-
- ;can only be called from :play-ps state
- (defmethod npv-cur-frame ((vp NEC-PC-VCR-vp))
- (+ (* 30 (npv-cur-addr vp)) (npv-cur-rel-frame vp)))
-
-
- ;;this is useful because certain commands can only be issued from this state
- (defmethod npv-ensure-paused ((vp NEC-PC-VCR-vp))
- (case (npv-cur-state vp)
- (:play-ps)
- (:play
- (npv-cmd vp "PS"))
- (:stop
- (npv-cmd vp "PL")
- (npv-cmd vp "PS"))
- (otherwise
- (npv-cmd vp "PS")))
- t)
-
-
- (defmethod npv-addr-string ((vp NEC-PC-VCR-vp) frame format)
- (setf frame (min (max frame 0) (vp-max-frame vp)))
- (ecase format
- (:frame (princ-to-string frame))
- (:addr (princ-to-string (round frame 30)))
- (:addr+fr (multiple-value-bind (addr fr) (floor frame 30)
- (format nil "~a:~a" addr fr)))))
-
- (defmethod npv-cmd ((vp NEC-PC-VCR-vp) code-string
- &key
- (arg "")
- (frame nil)
- (format nil)
- (response-p t)
- (error-p t)
- (flush-p t))
- (let ((cmd-string (if frame
- (format nil "~a~a" code-string (npv-addr-string vp frame format))
- (format nil "~a~a" code-string arg))))
- (when (or flush-p response-p) (npv-flush vp))
- (sport-write-line vp cmd-string)
- (let ((1st-response (npv-read vp :wait-p t)))
- (unless (npv-echeck 1st-response cmd-string error-p)
- (return-from npv-cmd 1st-response))
- (when response-p
- (let ((2nd-response (npv-read vp :wait-p t)))
- (unless (npv-echeck 2nd-response cmd-string error-p)
- (return-from npv-cmd 2nd-response))
- (unless (string= 2nd-response "AO")
- (let ((3rd-response (npv-read vp :wait-p t)))
- (unless (npv-echeck 3rd-response cmd-string error-p)
- (return-from npv-cmd 3rd-response))))
- 2nd-response)))))
-
- (defmethod npv-read ((vp NEC-PC-VCR-vp) &key (wait-p nil))
- (multiple-value-bind (str eoln-p) (sport-read-line vp :wait-p wait-p)
- (if eoln-p str (error "partial response (~s) read" str))))
-
- (defmethod npv-flush ((vp NEC-PC-VCR-vp))
- (sport-flush vp))
-
- #|
-
- (setf vp (make-instance 'NEC-PC-VCR-vp :port :printer))
- (vp-init vp)
- (vp-load vp)
- (vp-loaded-p vp)
-
- (npv-cur-rel-frame vp)
- (npv-ensure-paused vp)
-
- (npv-cur-state vp)
-
- (vp-current-frame vp)
-
- (vp-play vp)
- (vp-freeze vp)
- (vp-stop vp)
- (vp-scan vp :forward 2)
- (vp-scan vp :reverse 2)
-
- (progn
- (vp-step vp :forward)
- (vp-current-frame vp))
-
-
-
-
- (npv-cmd p "ST")
-
- |#