eci.el

New Message Reply About this list Date view Thread view Subject view Author view Other groups

Subject: eci.el
From: Mario Lang (mlang_AT_delysid.org)
Date: Tue Oct 08 2002 - 21:19:23 EEST


Hello.

Given the recent talk of switching to socket/tcp based controlling completely,
I've attempted to implement eci.el.

The example sort of works, I need to tweak the output accept
code a bit, but the overall thing works quite nicely.

Comments and suggestions are very welcome.

Try it by invoking M-x eci-example RET

;;; eci.el --- Implementing the ECI in Emacs-Lisp.

;; Written by Mario Lang 2002 <mlang_AT_delysid.org>

;; This is only a pretest version. It can use alot of improvements,
;; but the example works.

(defvar eci-program "ecasound"
  "*Program to invoke when doing `eci-init'.")

(defvar eci-buffer "*eci-ecasound*"
  "Buffer name to use for ecasound process buffers.")

(defun eci-init ()
  (save-current-buffer
    (set-buffer (get-buffer-create eci-buffer))
    (start-process "ecasound" (current-buffer) eci-program "-c" "-D")
    (current-buffer)))

(defun eci-interactive-startup ()
  "Used to interactively startup a eci session.
This will mostlyy be used to testing sessions."
  (interactive)
  (switch-to-buffer (eci-init)))

(defun eci-command (command &optional buffer-or-process)
  "Send a ECI command to BUFFER-OR-PROCESS or if that is nil, to the current
buffers process."
  (interactive "sECI Command: ")
  (let ((proc (cond ((processp buffer-or-process) buffer-or-process)
                    ((bufferp buffer-or-process) (get-buffer-process buffer-or-process))
                    (t (get-buffer-process (current-buffer))))))
    (with-current-buffer (process-buffer proc)
      (save-excursion
        (goto-char (process-mark proc))
        (insert-before-markers (format "%s\n" command))
        (process-send-string proc (format "%s\n" command))
        (let ((here (point)) res)
          (when (accept-process-output proc 2)
            (setq res (buffer-substring here (point-max)))
            ; This is a ugly hack which prevents getting out of sync
            (while (accept-process-output proc 0 50))
            res))))))

(defun eci-cs-status (&optional buffer-or-process)
  "Return ChainSetup status as a Lisp object."
  (let ((chains (split-string (eci-command "cs-status" buffer-or-process)
                              "^Chainsetup " ))
        (chainlist))
    (if (string-match "[\\* Controller/Chainsetup status \\*]" (car chains))
        (progn
          (setq chains (cdr chains))
          (mapc
           (lambda (str)
             (if (string-match "(\\([0-9]+\\)) \"\\([^\"\n]+\\)\".*\n\tFilename:\t\t\\([^\n]*\\)\n\tSetup:\t\t\tinputs \\([0-9]+\\) - outputs \\([0-9]+\\) - chains \\([0-9]+\\)\n\tBuffersize:\t\t\\([0-9]+\\)\n\tInternal sample rate:\t\\([0-9]+\\)\n\tDefault sformat:\t\\(.*\\)\n\tFlags:\t\t\t\\(.*\\)\n\tState:[\t ]+\\(.*\\)" str)
                 (setq
                  chainlist
                  (cons
                   (list
                    (string-to-number (match-string 1 str))
                    (match-string 2 str)
                    (list 'filename (match-string 3 str))
                    (list 'inputs (string-to-number (match-string 4 str)))
                    (list 'outputs (string-to-number (match-string 5 str)))
                    (list 'chains (string-to-number (match-string 6 str)))
                    (list 'buffersize (string-to-number (match-string 7 str)))
                    (list 'srate (string-to-number (match-string 8 str)))
                    (list 'sformat (match-string 9 str))
                    (list 'flags (match-string 10 str))
                    (list 'state (match-string 11 str))) chainlist))))
           chains))
      (error "Unknown return value"))
    chainlist))

(defun eci-c-list (&optional buffer-or-process)
  (split-string (eci-command "c-list") "[,\n]"))

(defun eci-cs-list (&optional buffer-or-process)
  (split-string (eci-command "cs-list") "[,\n]"))

(defun eci-c-select (chain &optional buffer-or-process)
  (interactive (list (completing-read "Chain: " (mapcar #'list
                                                        (eci-c-list)))))
  (eci-command (format "c-select %s" chain)))

(defun eci-cs-select (chain &optional buffer-or-process)
  (interactive (list (completing-read "Chainsetup: " (mapcar
                                                      #'list (eci-cs-list)))))
  (eci-command (format "cs-select %s" chain)))

(defun eci-ai-add (filename)
  (interactive "fInput filename: ")
  (eci-command (format "ai-add %s" filename)))

(defun eci-ao-add (filename)
  (interactive "fOutput filename: ")
  (eci-command (format "ao-add %s" filename)))

(defun eci-engine-status (&optional buffer-or-process)
  (car (split-string (eci-command "engine-status") "\n")))

(defun eci-get-position (&optional buffer-or-process)
  (string-to-number (eci-command "get-position" buffer-or-process)))

(defun eci-copp-get (&optional buffer-or-process)
  (string-to-number (eci-command "copp-get" buffer-or-process)))

(defun eci-example ()
  "Implements the example given in the ECI documentation.
This nicely shows that we still have timing problem, but it already
looks quite good."
  (interactive)
  (save-current-buffer
    (set-buffer (eci-init))
    (display-buffer (current-buffer))
    (sit-for 0)
    (eci-command "cs-add play_chainsetup")
    (eci-command "c-add 1st_chain")
    (call-interactively #'eci-ai-add)
    (eci-command "ao-add /dev/dsp")
    (eci-command "cop-add -efl:100")
    (eci-command "cop-select 1")
    (eci-command "copp-select 1")
    (eci-command "cs-connect")
    (eci-command "start")
    (while (and (string= (eci-engine-status) "running")
                (< (eci-get-position) 15))
      (sit-for 1)
      (eci-command (format "copp-set %f" (+ (eci-copp-get) 500))))
    (eci-command "stop")
    (eci-command "cs-disconnect")
    (message (concat "Chain operator status: "
                      (eci-command "cop-status")))))

-- 
CYa,
  Mario


New Message Reply About this list Date view Thread view Subject view Author view Other groups

This archive was generated by hypermail 2b28 : Tue Oct 08 2002 - 21:17:30 EEST