]> code.delx.au - gnu-emacs-elpa/blob - packages/aumix-mode/aumix-mode.el
Update packages/yasnippet by subtree-merging from its external upstream
[gnu-emacs-elpa] / packages / aumix-mode / aumix-mode.el
1 ;;; aumix-mode.el --- run the aumix program in a buffer
2
3 ;; Copyright (C) 2006,2009-2011,2013-2014 Free Software Foundation, Inc.
4
5 ;; Author: Kevin Ryde <user42_kevin@yahoo.com.au>
6 ;; Version: 7
7 ;; Keywords: multimedia, mixer, aumix
8 ;; URL: http://user42.tuxfamily.org/aumix-mode/index.html
9 ;; EmacsWiki: Aumix
10 ;;
11 ;; aumix-mode.el is free software; you can redistribute it and/or modify it
12 ;; under the terms of the GNU General Public License as published by the
13 ;; Free Software Foundation; either version 3, or (at your option) any later
14 ;; version.
15 ;;
16 ;; aumix-mode.el is distributed in the hope that it will be useful, but
17 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
19 ;; Public License for more details.
20 ;;
21 ;; You can get a copy of the GNU General Public License online at
22 ;; <http://www.gnu.org/licenses/>.
23
24
25 ;;; Commentary:
26
27 ;; "M-x aumix" runs the aumix sound volume adjuster program in a buffer.
28 ;; See the docstrings of `aumix' and `aumix-mode' below.
29
30 ;;; Emacsen:
31
32 ;; Designed for Emacs 20 up. A bit doubtful with XEmacs 21 term.el (see
33 ;; `aumix-mode' docstring below).
34
35 ;;; Install:
36
37 ;; To make M-x aumix available put aumix-mode.el in one of your `load-path'
38 ;; directories and the following in your .emacs
39 ;;
40 ;; (autoload 'aumix "aumix-mode" nil t)
41 ;;
42 ;; If you use desktop.el then make an autoload for the aumix-mode function
43 ;; too so `desktop-read' can load it when restoring an aumix-mode buffer.
44 ;;
45 ;; (autoload 'aumix-mode "aumix-mode" nil t)
46 ;;
47 ;; There's autoload cookies for these functions below if you install via
48 ;; `M-x package-install' or know how to use `update-file-autoloads'.
49
50 ;;; History:
51
52 ;; Version 1 - the first version
53 ;; Version 2 - new program and switches variables
54 ;; - correction to `provide'
55 ;; Version 3 - flag aumix-mode-switches as risky-local-variable
56 ;; Version 4 - correction to `process-kill-without-query' for emacs21
57 ;; - cl for `dotimes' in emacs20
58 ;; Version 5 - ensure curses interface if aumix built with gtk interface
59 ;; - add desktop.el save/restore
60 ;; Version 6 - autoload aumix-mode for desktop.el
61 ;; Version 7 - don't autoload the variables
62
63 ;;; Code:
64
65 (require 'term)
66 (eval-when-compile
67 (unless (fboundp 'dotimes)
68 (require 'cl))) ;; for emacs20 dotimes
69
70
71 ;;;###autoload
72 (defgroup aumix-mode nil "Aumix Mode"
73 :prefix "aumix-mode-"
74 :group 'multimedia
75 :link '(url-link :tag "aumix-mode.el home page"
76 "http://user42.tuxfamily.org/aumix-mode/index.html")
77 :link '(url-link :tag "Aumix home page"
78 "http://jpj.net/~trevor/aumix.html"))
79
80 (defcustom aumix-mode-program "aumix"
81 "Executable program name for aumix."
82 :type 'string
83 :group 'aumix-mode)
84 ;; automatically `risky-local-variable-p' due to name `-program'
85
86 (defcustom aumix-mode-switches nil
87 "List of command line switches to pass to aumix.
88 Only a few aumix options do anything for interactive use.
89 \"-d\" can set a mixer device file (default /dev/mixer), for
90 example
91
92 (setq aumix-mode-switches '(\"-d\" \"/dev/mixer2\"))"
93
94 :type '(repeat string)
95 :group 'aumix-mode)
96 ;;
97 ;; Not sure if switches can do very much damage. Make risky just in case
98 ;; "-d filename" causes ioctls to some device other than a mixer.
99 ;;;###autoload
100 (put 'aumix-mode-switches 'risky-local-variable t)
101
102 (defcustom aumix-mode-hook nil
103 "Hook called by `aumix-mode'.
104 This hook, and the parent `term-mode-hook', are run when the
105 buffer setups are made but before the \"aumix\" program is
106 started. This is convenient for applying `font-lock-mode' or
107 similar before the program output starts.
108
109 See also `term-exec-hook' which runs after \"aumix\" is started."
110
111 :type 'hook
112 :group 'aumix-mode
113 :options '(turn-on-filladapt-mode))
114
115 ;;-----------------------------------------------------------------------------
116
117 (defvar aumix-mode-map (make-sparse-keymap)
118 "Keymap for `aumix-mode'.
119 This inherits from parent keymap `term-raw-map'. That parent
120 keymap is only set when `aumix-mode' is first called, since in
121 Emacs 21 `term-raw-map' is only created then.
122
123 Explicit nil settings in `aumix-mode-map' let control characters
124 have their usual `global-map' meanings instead of `term-send-raw'
125 in `term-raw-map'. This is good for keys aumix doesn't use, in
126 particular C-x and C-h have their usual prefix meanings.
127
128 C-c is left for the various prefixed bindings of `term-raw-map'.
129 C-l and Tab are `term-send-raw' since they're used by the aumix
130 program.")
131 ;;
132 (dotimes (i 31)
133 (let ((key (1+ i))) ;; 1 to 31
134 (unless (member key '(?\C-c ?\C-l ?\t))
135 (define-key aumix-mode-map (vector key) nil))))
136 (define-key aumix-mode-map "Q" 'aumix-mode-quit)
137 (define-key aumix-mode-map "q" 'aumix-mode-quit)
138 (define-key aumix-mode-map "\C-l" 'term-send-raw)
139
140 ;;-----------------------------------------------------------------------------
141
142 (defun aumix-mode-quit ()
143 "Quit from aumix, and kill the buffer.
144 This is a direct kill of the subprocess (rather than sending
145 \"q\" to aumix and waiting for it to exit itself).
146
147 For reference, if you use $LANG or $LANGUAGE set to something
148 other than English then the quit key in aumix might be
149 translated. For example \"b\" (Beenden) in German. In that case
150 the aumix program exits but the buffer remains. The buffer is
151 left on aumix exit so that if it dies then an error message is
152 seen. Re-bind the keys in `aumix-mode-map' if something other
153 than \"q\" for quit is desired."
154
155 (interactive)
156 (kill-buffer nil))
157
158 (defun aumix-mode-kill-process ()
159 "An internal part of aumix-mode.el.
160 This function is designed to be called from `kill-buffer-hook'.
161 Kill the aumix sub-process when killing the buffer."
162 (if (get-buffer-process (current-buffer))
163 (delete-process nil)))
164
165 ;; this is autoloaded for the benefit of desktop.el
166 ;;;###autoload
167 (defun aumix-mode ()
168 "Major mode for running the aumix program.
169 Key bindings are per the aumix program. Press `k' for a summary,
170 or see KEYS in \"man aumix\". `\\[aumix-mode-quit]' quits and kills the buffer.
171
172 The various terminal setups of `term-mode' are unchanged. Note
173 in Emacs 24 the ANSI colours use `font-lock-mode' so be sure
174 that's turned on (which it is by default). In Emacs 21 the
175 opposite was true; if you turn on font lock then you lose the
176 colours.
177
178 In XEmacs 21.4, term.el doesn't seem to work very well with
179 ncurses programs. A message \"Error opening terminal: eterm\" is
180 from aumix (the ncurses library) complaining the terminfo is not
181 found. Adding TERMINFO=/usr/share/xemacs21/xemacs-packages/etc/
182 or wherever the /e/eterm file lives might help. If something
183 doesn't work then C-c C-x C-k will kill the buffer.
184
185 `clone-buffer' doesn't work on an aumix-mode buffer, as of Emacs
186 24.3. Two or more aumix programs can run simultaneously (their
187 displays update with the underlying mixer settings), so perhaps
188 `clone-buffer' could be made to work. A `rename-buffer' and
189 second `M-x aumix' works. But normally only a single aumix-mode
190 buffer is desired.
191
192 ----
193 The aumix home page is
194 URL `http://jpj.net/~trevor/aumix.html'
195 The aumix-mode.el home page is
196 URL `http://user42.tuxfamily.org/aumix-mode/index.html'
197
198 ----
199 \\{aumix-mode-map}
200 "
201
202 (term-mode)
203
204 ;; kill sub-process when killing buffer
205 (if (eval-when-compile (fboundp 'make-local-hook))
206 (make-local-hook 'kill-buffer-hook)) ;; for xemacs21
207 (add-hook 'kill-buffer-hook 'aumix-mode-kill-process
208 nil ;; not append
209 t) ;; buffer-local
210
211 (setq major-mode 'aumix-mode
212 mode-name "Aumix")
213
214 ;; desktop.el no misc-data needed
215 (set (make-local-variable 'desktop-save-buffer) 'ignore)
216
217 (if (eval-when-compile (fboundp 'run-mode-hooks))
218 (run-mode-hooks 'aumix-mode-hook)
219 (run-hooks 'aumix-mode-hook))
220
221 ;; Unset $DISPLAY to ensure aumix uses the curses interface, not the gtk
222 ;; interface if it was built with gtk interface. The "-C" command line
223 ;; option can do that too, but as of aumix 2.9.1 in the curses build -C
224 ;; demands a colour file whereas prefer to leave that as the default
225 ;; colours or let the user put a "-C" colours in aumix-mode-switches.
226 (let ((process-environment (copy-sequence process-environment)))
227 (setenv "DISPLAY" nil)
228
229 (term-exec (current-buffer)
230 "aumix" ;; process name
231 aumix-mode-program nil aumix-mode-switches))
232
233 (term-char-mode)
234
235 (use-local-map aumix-mode-map)
236
237 ;; In term.el of emacs21 and xemacs21 `term-raw-map' is only created
238 ;; when `term-char-mode' is called, so must wait until this point to set
239 ;; it as the parent keymap.
240 (set-keymap-parent aumix-mode-map term-raw-map)
241
242 ;; `term-in-char-mode' looks for (current-local-map) equal to
243 ;; `term-raw-map' to identify char mode, so buffer-local setting of
244 ;; `term-raw-map' to be `aumix-mode-map' instead.
245 (set (make-local-variable 'term-raw-map) aumix-mode-map)
246
247 (let ((proc (get-buffer-process (current-buffer))))
248 ;; adapt to emacs22 pointless incompatible rename of
249 ;; `process-kill-without-query'
250 (if (eval-when-compile (fboundp 'set-process-query-on-exit-flag))
251 (set-process-query-on-exit-flag proc nil) ;; emacs22
252 (process-kill-without-query proc)))) ;; emacs21
253
254 (put 'aumix-mode 'derived-mode-parent 'term-mode)
255
256 ;;;###autoload
257 (defun aumix ()
258 "Run the aumix program in a buffer.
259 An *aumix* buffer is created if it doesn't already exist.
260 See `aumix-mode' for details of operating the mode."
261
262 (interactive)
263 (switch-to-buffer "*aumix*")
264 (unless (eq major-mode 'aumix-mode)
265 (aumix-mode)))
266
267 ;;-----------------------------------------------------------------------------
268 ;; desktop.el save/restore (for emacs22 up)
269 ;;
270 ;; `desktop-create-buffer' loads the .el of an autoload mode func such as
271 ;; `aumix-mode' when it appears in a saved desktop. The alternative would
272 ;; be to autoload `aumix-mode-desktop-restore' and the `eval-after-load',
273 ;; but that seems like more.
274
275 (defun aumix-mode-desktop-restore (file-name buffer-name misc-data)
276 "Restore `aumix-mode' buffer for desktop.el.
277 This is designed for use from `desktop-buffer-mode-handlers'."
278 ;; checkdoc-params: (file-name buffer-name misc-data)
279
280 (set-buffer (get-buffer-create buffer-name))
281 (aumix-mode)
282 (current-buffer)) ;; success, return buffer
283
284 (eval-after-load "desktop"
285 '(when (boundp 'desktop-buffer-mode-handlers) ;; new in emacs22
286 (add-to-list 'desktop-buffer-mode-handlers
287 '(aumix-mode . aumix-mode-desktop-restore))))
288
289 ;;-----------------------------------------------------------------------------
290
291 ;; LocalWords: docstrings dev subprocess el ncurses terminfo eterm usr
292
293 (provide 'aumix-mode)
294
295 ;;; aumix-mode.el ends here