]> git.donarmstrong.com Git - lib.git/blob - emacs_el/lyqi-midi.el
update templates, add lyqi and update ls-R
[lib.git] / emacs_el / lyqi-midi.el
1 ;;      $RCSfile: lyqi-midi.el,v $      
2 ;;      $Revision: 1.7 $        
3 ;;      $Date: 2004/03/14 15:16:05 $    
4 ;;      $Author: nicolas $      
5 ;;; 
6 ;;; Part of lyqi, a major emacs mode derived from LilyPond-Mode,
7 ;;; for quick note insertion while editing GNU LilyPond music scores.
8 ;;; 
9 ;;; (c) copyright 2003 Nicolas Sceaux <nicolas.sceaux@free.fr>
10 ;;; See http://nicolas.sceaux.free.fr/lilypond/
11 ;;;     
12
13 (require 'eieio)
14 (require 'lyqi-base)
15
16 (defcustom lyqi-midi-demon-command "timidity -iA -B2,8 -Os -EFreverb=0"
17   "Command used to start the midi demon."
18   :group 'lyqi
19   :type  'string)
20
21 (defcustom lyqi-midi-keyboard-command "mymidikbd"
22   "Command used to start the midi keyboard process."
23   :group 'lyqi
24   :type  'string)
25
26 (defcustom lyqi-midi-enabled-default nil
27   "Automatically launch midi?"
28   :group 'lyqi
29   :type  'boolean)
30
31 (defcustom lyqi-midi-external-timidity-port 128
32   "ALSA port of external timidity server."
33   :group 'lyqi
34   :type 'integer)
35
36 (defcustom lyqi-midi-use-external-timidity-server nil
37   "If true, don't start a new timidity server, but use an existing
38 one, which port is `lyqi-midi-external-timidity-port'."
39   :group 'lyqi
40   :type  'boolean)
41
42 (defvar lyqi-midi-tempo 80
43   "Tempo used for play back (quaters per minute).")
44
45 (defvar lyqi-midi-manually-off nil
46   "Tells if user has previously switched off midi")
47
48 (defvar lyqi-midi-timidity nil
49   "The timidity demon process.")
50
51 (defvar lyqi-midi-keyboard nil
52   "The midi keyboard process.")
53
54 (defvar lyqi-midi-on nil
55   "Say if midi processes are running")
56
57 (defun lyqi-midi-set-timidity-alsa-port (port)
58   "When using an external timidity demon, set its ALSA sequencer port."
59   (interactive "nTimidity ALSA port: ")
60   (setf lyqi-midi-external-timidity-port port)
61   (when lyqi-midi-timidity
62     (setf (slot-value lyqi-midi-timidity 'seqport) port)))
63
64 (defun lyqi-midi-timidity-start ()
65   (process-start lyqi-midi-timidity)
66   (mapcar (lambda (client)
67             (setf (slot-value client 'server-port)
68                   (slot-value lyqi-midi-timidity 'seqport)))
69           (list lyqi-midi-keyboard)))
70           ;;(list lyqi-midi-keyboard lyqi-midi-rumor)))
71
72 (defun lyqi-midi-start ()
73   "Starts the timidity process with ALSA interface
74 and the keyboard process."
75   (unless lyqi-midi-on
76     (lyqi-midi-timidity-start)
77     (process-start lyqi-midi-keyboard))
78   (setq lyqi-midi-on (and (process-runningp lyqi-midi-timidity)
79                           (process-runningp lyqi-midi-keyboard))))
80
81 (defun lyqi-midi-stop ()
82   "Stops timidity and keyboard processes."
83   (process-stop lyqi-midi-timidity)
84   (process-stop lyqi-midi-keyboard)
85   (setq lyqi-midi-on nil))
86
87 (defmethod play-note ((note mudela-note) &optional short)
88   "Play the given note, by sending its pitch and length (in sec) 
89 to the midi keyboard process."
90   (when (process-runningp lyqi-midi-keyboard)
91     (with-slots (duration dots) note
92       (process-send-string
93        (process-name (slot-value lyqi-midi-keyboard 'process))
94        (format "%d %f\n" 
95                (midi-pitch note)
96                (if short
97                    -1.0
98                    (* (expt 2.0 (- 3 duration))
99                       (do ((i 0 (1+ i))
100                            (sum 0.0 (+ sum (expt 2.0 (- i)))))
101                           ((> i dots) sum))
102                       (/ 60.0 (* 1.0 lyqi-midi-tempo)))))))))
103
104 (defmethod play-note ((word mudela-word-duration) &optional short)
105   "Play the given note, by sending its pitch and length (in sec)
106 to the midi keyboard process."
107   (when (process-runningp lyqi-midi-keyboard)
108     (with-slots (duration dots) word
109       (process-send-string (process-name (slot-value lyqi-midi-keyboard 'process))
110                            (format "%d %f\n" 
111                                    -1
112                                    (* (expt 2.0 (- 3 duration))
113                                       (do ((i 0 (1+ i))
114                                            (sum 0.0 (+ sum (expt 2.0 (- i)))))
115                                           ((> i dots) sum))
116                                       (/ 60.0 (* 1.0 lyqi-midi-tempo))))))))
117
118 (defmethod play-note ((word mudela-word) &optional short)
119            "Play the given note, by sending its pitch and length (in sec)
120 to the midi keyboard process."
121   nil)
122
123 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
124 (defclass midi-process ()
125   ((command :initarg :command
126             :initform nil
127             :documentation "process start command")
128    (args    :initarg :args
129             :initform nil
130             :documentation "process command arguments")
131    (name    :initarg :name
132             :initform nil
133             :documentation "process name")
134    (process :initform nil
135             :documentation "process object")))
136 (defmethod process-runningp ((process midi-process))
137   "Return t if the process is running, nil otherwise."
138   (with-slots ((proc process)) process
139       (and proc (eq (process-status proc) 'run))))
140 (defmethod process-start ((process midi-process))
141   "Start the process"
142   (unless (process-runningp process)
143     (with-slots (name command args) process
144         (setf (slot-value process 'process)
145               (apply 'start-process name name (append (split-string command " ")
146                                                       args))))))
147 (defmethod process-stop ((process midi-process))
148   "Stop the process"
149   (when (process-runningp process)
150     (with-slots ((proc process)) process
151         (delete-process (process-name proc)))))
152
153 (defclass timidity-server (midi-process)
154   ((seqport :initform nil
155             :documentation "Timidity ALSA sequencer port")))
156 (defmethod process-start :AFTER ((timidity timidity-server))
157   "Grep the sequencer port."
158   ;; we have to wait a bit before reading timidity's output
159   (sleep-for 1)
160   (let ((port
161          (with-current-buffer (buffer-name (process-buffer (slot-value timidity 'process)))
162            (goto-char (point-max))
163            (if (re-search-backward "Opening sequencer port: \\([0-9]+\\):" nil t)
164                (buffer-substring (match-beginning 1) 
165                                  (match-end 1))))))
166     (when port
167       (setf (slot-value timidity 'seqport) (string-to-int port)))))
168
169 (defclass external-timidity-server (midi-process)
170   ((seqport ;:initform lyqi-midi-external-timidity-port
171             :documentation "External timidity ALSA sequencer port")))
172 (defmethod process-runningp ((timidity external-timidity-server))
173   t)
174 (defmethod process-start ((timidity external-timidity-server))
175   t)
176 (defmethod process-stop ((timidity external-timidity-server))
177   t)
178
179
180 (defclass timidity-client (midi-process)
181   ((server-port :initform nil
182                 :documentation "The timidity server ALSA port")))
183
184 (defclass mymidikbd (timidity-client) nil)
185 (defmethod process-start :BEFORE ((kbd mymidikbd))
186   "Update command argument list before execution."
187   (setf (slot-value kbd 'args)
188         (list (number-to-string (slot-value kbd 'server-port)))))
189
190 (provide 'lyqi-midi)
191