   (concat (make-temp-name
 	   (expand-file-name "emacs-eci" temporary-file-directory))
 	  suffix))
+
+(defun ecasound-read-from-minibuffer (prompt default)
+  (let ((result (read-from-minibuffer
+		 (format "%s (default %S): " prompt default)
+		 nil nil nil nil default)))
+    (if (and result (not (string= result "")))
+	result
+      default)))
+
+(defconst ecasound-signalview-clipped-threshold (- 1.0 (/ 1.0 16384)))
+
+(defconst ecasound-signalview-bar-length 55)
+
+(defun ecasound-signalview (bufsize format input output)
+  (interactive
+   (list
+    (ecasound-read-from-minibuffer "Buffersize" "128")
+    (ecasound-read-from-minibuffer "Format" "s16_le,2,44100,i")
+    (let ((file (read-file-name "Input: ")))
+      (if (file-exists-p file)
+	  (expand-file-name file)
+	file))
+    (ecasound-read-from-minibuffer "Output" "null")))
+  (let* ((eci-parse-cleanup-buffer nil)
+	 (handle (eci-init))
+	 (channels (string-to-number (nth 1 (split-string format ","))))
+	 (chinfo (make-vector channels nil)))
+    (dotimes (ch channels) (aset chinfo ch (cons 0 0)))
+    (eci-cs-add "signalview" handle)
+    (eci-c-add "analysis" handle)
+    (eci-cs-set-audio-format format handle)
+    (eci-ai-add input handle)
+    (eci-ao-add output handle)
+    (eci-cop-add "-evp" handle)
+    (eci-cop-add "-ev" handle)
+    (set-buffer (get-buffer-create "*Ecasound-signalview*"))
+    (erase-buffer)
+    (dotimes (ch channels)
+      (insert "---\n"))
+    (setq header-line-format
+	 (list (concat "Channel#"
+		       (make-string (- ecasound-signalview-bar-length 3) 32)
+		       "| max-value  clipped")))
+    (set (make-variable-buffer-local 'ecasignalview-position) "unknown")
+    (set (make-variable-buffer-local 'ecasignalview-engine-status) "unknown")
+    (setq mode-line-format
+	  (list
+	   (list
+	    (- ecasound-signalview-bar-length 3)
+	    (format "Input: %s, output: %s" input output)
+	    'ecasignalview-engine-status)
+	   " | " 'ecasignalview-position))
+    (switch-to-buffer-other-window (current-buffer))
+    (eci-cs-connect handle)
+    (eci-start handle)
+    (sit-for 0.8)
+    (eci-cop-select 1 handle)
+    (while (string= (setq ecasignalview-engine-status
+			  (eci-engine-status handle)) "running")
+      (let ((inhibit-quit t) (inhibit-redisplay t))
+	(setq ecasignalview-position
+	      (let ((secs (eci-cs-get-position handle)))
+		(format "%02d:%02d.%02d"
+			(/ secs 60)
+			(% (round (floor secs)) 60)
+			(* (- secs (floor secs)) 100))))
+	(delete-region (point-min) (point-max))
+	(dotimes (ch channels)
+	  (insert (format "ch%d: " (1+ ch)))
+	  (let ((val (progn (eci-copp-select (1+ ch) handle)
+			    (eci-copp-get handle)))
+		(bl ecasound-signalview-bar-length))
+	    (insert
+	     (concat
+	      (make-string (round (* val bl)) ?*)
+	      (make-string (- bl (round (* val bl))) ? )))
+	    (if (> val (car (aref chinfo ch)))
+		(setcar (aref chinfo ch) val))
+	    (if (> val ecasound-signalview-clipped-threshold)
+	      (incf (cdr (aref chinfo ch))))
+	    (insert (format "| %.4f     %d\n" (car (aref chinfo ch))
+			    (cdr (aref chinfo ch))))))
+	(goto-char (point-min)))
+      (sit-for 0.1)
+      (fit-window-to-buffer))
+    (goto-char (point-max))
+    (let ((pos (point)))
+      (insert
+       (nth 2
+	    (nth 2
+		 (nthcdr 2
+			 (assoc "Volume analysis"
+				(assoc "analysis"
+				       (eci-cop-status handle)))))))
+      (goto-char pos))
+    (recenter channels)
+    (fit-window-to-buffer)))
 
 (defun ecasound-normalize (filename)
   "Normalize a audio file using ECI."

;;
;; Todo:
;;
;; * Convince Kai to make NetECI look and behave exactly like ecasound -c.
;; This would make it very easy to make neteci connections using the current
;; code.  Just set eci-program to (host . port).
;; * Cache things like c-, cs- and cop-list as well as c-, cs- and
;; engine-status in buffer-local variables like it's already done for
;; cop- and ladspa-register.
;; * Tweak the mode-line to include status information like engine-status
;; or inputs/outputs/chains or the current selected cs or chains.
;; * Add NetECI support to fetch status info (eci-hide-output t calls)
;; via a separate, not visible buffer.
;; * Write eci-cop-register alike support for preset-register.
;; * Copy documentation for ECI commands into eci-* docstrings and menu
;; :help keywords.
;; * Expand the menu.
;; * Bind most important interactive functions in ecasound-aim-mode-map
;; (which layout to use?)

;;; History:
;; 
;; Version: 0.7.5
;;
;; * Added ctrl-register parsing support and `ecasound-ctrl-add'.
;; * Added preset-register support (so far only for cop-add completion)
;; * Fixed cop-status parsing bug which caused ecasound-cop-edit to not
;; work in some cases.
;; * New macro defeci which handles defining ECI commands in lisp.
;; * Several other minor tweaks and fixes.


;; Author: Mario Lang <mlang@delysid.org>
;; Keywords: audio, ecasound, eci, comint, process, pcomplete
;; Version: 0.7.6

;; This file is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
