PageRenderTime 25ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/emacspeak-29.0/lisp/emacspeak-sounds.el

#
Emacs Lisp | 458 lines | 308 code | 46 blank | 104 comment | 18 complexity | a2f1174807cd0bdcf854a33a935b1a82 MD5 | raw file
Possible License(s): MIT
  1. ;;; emacspeak-sounds.el --- Defines Emacspeak auditory icons
  2. ;;; $Id: emacspeak-sounds.el 5798 2008-08-22 17:35:01Z tv.raman.tv $
  3. ;;; $Author: tv.raman.tv $
  4. ;;; Description: Module for adding sound cues to emacspeak
  5. ;;; Keywords:emacspeak, audio interface to emacs, auditory icons
  6. ;;{{{ LCD Archive entry:
  7. ;;; LCD Archive Entry:
  8. ;;; emacspeak| T. V. Raman |raman@cs.cornell.edu
  9. ;;; A speech interface to Emacs |
  10. ;;; $Date: 2007-09-01 15:30:13 -0700 (Sat, 01 Sep 2007) $ |
  11. ;;; $Revision: 4670 $ |
  12. ;;; Location undetermined
  13. ;;;
  14. ;;}}}
  15. ;;{{{ Copyright:
  16. ;;;Copyright (C) 1995 -- 2007, T. V. Raman
  17. ;;; Copyright (c) 1994, 1995 by Digital Equipment Corporation.
  18. ;;; All Rights Reserved.
  19. ;;;
  20. ;;; This file is not part of GNU Emacs, but the same permissions apply.
  21. ;;;
  22. ;;; GNU Emacs is free software; you can redistribute it and/or modify
  23. ;;; it under the terms of the GNU General Public License as published by
  24. ;;; the Free Software Foundation; either version 2, or (at your option)
  25. ;;; any later version.
  26. ;;;
  27. ;;; GNU Emacs is distributed in the hope that it will be useful,
  28. ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  29. ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  30. ;;; GNU General Public License for more details.
  31. ;;;
  32. ;;; You should have received a copy of the GNU General Public License
  33. ;;; along with GNU Emacs; see the file COPYING. If not, write to
  34. ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  35. ;;}}}
  36. ;;{{{ Introduction:
  37. ;;; Commentary:
  38. ;;; This module provides the interface for generating auditory icons in emacspeak.
  39. ;;; Design goal:
  40. ;;; 1) Auditory icons should be used to provide additional feedback,
  41. ;;; not as a gimmick.
  42. ;;; 2) The interface should be usable at all times without the icons:
  43. ;;; e.g. when on a machine without a sound card.
  44. ;;; 3) General principle for when to use an icon:
  45. ;;; Convey information about events taking place in parallel.
  46. ;;; For instance, if making a selection automatically moves the current focus
  47. ;;; to the next choice,
  48. ;;; We speak the next choice, while indicating the fact that something was selected with a sound cue.
  49. ;;; This interface will assume the availability of a shell command "play"
  50. ;;; that can take one or more sound files and play them.
  51. ;;; This module will also provide a mapping between names in the elisp world and actual sound files.
  52. ;;; Modules that wish to use auditory icons should use these names, instead of actual file names.
  53. ;;; As of Emacspeak 13.0, this module defines a themes
  54. ;;; architecture for auditory icons.
  55. ;;; Sound files corresponding to a given theme are found in
  56. ;;; appropriate subdirectories of emacspeak-sounds-directory
  57. ;;}}}
  58. ;;{{{ required modules
  59. ;;; Code:
  60. (require 'cl)
  61. (declaim (optimize (safety 0) (speed 3)))
  62. (require 'custom)
  63. (eval-when (compile)
  64. (require 'dtk-speak)
  65. (require 'emacspeak-aumix))
  66. ;;}}}
  67. ;;{{{ state of auditory icons
  68. (defvar emacspeak-use-auditory-icons nil
  69. "Tells if emacspeak should use auditory icons.
  70. Do not set this variable by hand,
  71. use `emacspeak-toggle-auditory-icons' bound to
  72. \\[emacspeak-toggle-auditory-icons].")
  73. (make-variable-buffer-local 'emacspeak-use-auditory-icons)
  74. ;;}}}
  75. ;;{{{ Setup Audio
  76. ;;;###autoload
  77. (defun emacspeak-audio-setup ()
  78. "Call appropriate audio environment set command."
  79. (interactive)
  80. (cond
  81. ((executable-find "amixer")
  82. (call-interactively 'amixer))
  83. (t (call-interactively 'emacspeak-aumix)))
  84. (emacspeak-auditory-icon 'close-object))
  85. ;;}}}
  86. ;;{{{ Setup sound themes
  87. (defvar emacspeak-sounds-icon-list
  88. '(
  89. alarm
  90. alert-user
  91. ask-question
  92. ask-short-question
  93. button
  94. center
  95. close-object
  96. delete-object
  97. deselect-object
  98. ellipses
  99. fill-object
  100. full
  101. help
  102. item
  103. large-movement
  104. left
  105. mark-object
  106. modified-object
  107. n-answer
  108. new-mail
  109. news
  110. no-answer
  111. off
  112. on
  113. open-object
  114. paragraph
  115. progress
  116. quit
  117. right
  118. save-object
  119. scroll
  120. search-hit
  121. search-miss
  122. section
  123. select-object
  124. shutdown
  125. task-done
  126. unmodified-object
  127. warn-user
  128. window-resize
  129. y-answer
  130. yank-object
  131. yes-answer
  132. )
  133. "List of valid auditory icon names.
  134. If we add new icons we should declare them here. ")
  135. (defsubst emacspeak-sounds-icon-list ()
  136. "Return the list of auditory icons that are currently defined."
  137. (declare (special emacspeak-sounds-icon-list))
  138. emacspeak-sounds-icon-list)
  139. (defvar emacspeak-default-sound
  140. (expand-file-name
  141. "default-8k/button.au"
  142. emacspeak-sounds-directory)
  143. "Default sound to play if requested icon not found.")
  144. (defvar emacspeak-sounds-themes-table
  145. (make-hash-table)
  146. "Maps valid sound themes to the file name extension used by that theme.")
  147. ;;;###autoload
  148. (defun emacspeak-sounds-define-theme (theme-name file-ext)
  149. "Define a sounds theme for auditory icons. "
  150. (declare (special emacspeak-sounds-themes-table))
  151. (setq theme-name (intern theme-name))
  152. (setf (gethash theme-name emacspeak-sounds-themes-table)
  153. file-ext ))
  154. (defgroup emacspeak-sounds nil
  155. "Emacspeak auditory icons."
  156. :group 'emacspeak)
  157. ;;;###autoload
  158. (defcustom emacspeak-sounds-default-theme
  159. (expand-file-name "default-8k/"
  160. emacspeak-sounds-directory)
  161. "Default theme for auditory icons. "
  162. :type '(directory :tag "Sound Theme Directory")
  163. :group 'emacspeak-sounds)
  164. ;;;###autoload
  165. (defcustom emacspeak-play-program
  166. (cond
  167. ((getenv "EMACSPEAK_PLAY_PROGRAM")
  168. (getenv "EMACSPEAK_PLAY_PROGRAM"))
  169. ((file-exists-p "/usr/bin/aplay") "/usr/bin/aplay")
  170. ((file-exists-p "/usr/bin/play") "/usr/bin/play")
  171. ((file-exists-p "/usr/bin/audioplay") "/usr/bin/audioplay")
  172. ((file-exists-p "/usr/demo/SOUND/play") "/usr/demo/SOUND/play")
  173. (t (expand-file-name emacspeak-etc-directory "play")))
  174. "Name of executable that plays sound files. "
  175. :group 'emacspeak-sounds
  176. :type 'string)
  177. (defvar emacspeak-sounds-current-theme
  178. emacspeak-sounds-default-theme
  179. "Name of current theme for auditory icons.
  180. Do not set this by hand;
  181. --use command \\[emacspeak-sounds-select-theme].")
  182. (defsubst emacspeak-sounds-theme-get-extension (theme-name )
  183. "Retrieve filename extension for specified theme. "
  184. (declare (special emacspeak-sounds-themes-table))
  185. (gethash
  186. (intern theme-name)
  187. emacspeak-sounds-themes-table))
  188. (defsubst emacspeak-sounds-define-theme-if-necessary (theme-name)
  189. "Define selected theme if necessary."
  190. (cond
  191. ((emacspeak-sounds-theme-get-extension theme-name)
  192. t)
  193. ((file-exists-p (expand-file-name "define-theme.el"
  194. theme-name))
  195. (load-file (expand-file-name
  196. "define-theme.el"
  197. theme-name)))
  198. (t (error "Theme %s is missing its configuration file. " theme-name))))
  199. (defun emacspeak-sounds-theme-p (theme)
  200. "Predicate to test if theme is available."
  201. (file-exists-p
  202. (expand-file-name theme emacspeak-sounds-directory)))
  203. ;;;###autoload
  204. (defun emacspeak-sounds-select-theme (theme)
  205. "Select theme for auditory icons."
  206. (interactive
  207. (list
  208. (expand-file-name
  209. (read-directory-name "Theme: "
  210. emacspeak-sounds-directory))))
  211. (declare (special emacspeak-sounds-current-theme
  212. emacspeak-sounds-themes-table))
  213. (setq theme (expand-file-name theme emacspeak-sounds-directory))
  214. (unless (file-directory-p theme)
  215. (setq theme (file-name-directory theme)))
  216. (unless (file-exists-p theme)
  217. (error "Theme %s is not installed" theme))
  218. (setq emacspeak-sounds-current-theme theme)
  219. (emacspeak-sounds-define-theme-if-necessary theme)
  220. (emacspeak-auditory-icon 'select-object))
  221. ;;;###autoload
  222. (defsubst emacspeak-get-sound-filename (sound-name)
  223. "Retrieve name of sound file that produces auditory icon SOUND-NAME."
  224. (declare (special emacspeak-sounds-themes-table
  225. emacspeak-sounds-current-theme))
  226. (let ((f
  227. (expand-file-name
  228. (format "%s%s"
  229. sound-name
  230. (emacspeak-sounds-theme-get-extension emacspeak-sounds-current-theme))
  231. emacspeak-sounds-current-theme)))
  232. (if (file-exists-p f)
  233. f
  234. emacspeak-default-sound)))
  235. ;;}}}
  236. ;;{{{ queue an auditory icon
  237. ;;;###autoload
  238. (defun emacspeak-queue-auditory-icon (sound-name)
  239. "Queue auditory icon SOUND-NAME."
  240. (declare (special dtk-speaker-process))
  241. (process-send-string dtk-speaker-process
  242. (format "a %s\n"
  243. (emacspeak-get-sound-filename sound-name ))))
  244. ;;}}}
  245. ;;{{{ native player (emacs 21)
  246. ;;;###autoload
  247. (defun emacspeak-native-auditory-icon (sound-name)
  248. "Play auditory icon using native Emacs player."
  249. (declare (special emacspeak-use-auditory-icons))
  250. (when emacspeak-use-auditory-icons
  251. (play-sound
  252. (list 'sound :file
  253. (format "%s"
  254. (emacspeak-get-sound-filename sound-name ))))))
  255. ;;}}}
  256. ;;{{{ serve an auditory icon
  257. ;;;###autoload
  258. (defun emacspeak-serve-auditory-icon (sound-name)
  259. "Serve auditory icon SOUND-NAME.
  260. Sound is served only if `emacspeak-use-auditory-icons' is true.
  261. See command `emacspeak-toggle-auditory-icons' bound to \\[emacspeak-toggle-auditory-icons ]."
  262. (declare (special dtk-speaker-process
  263. emacspeak-use-auditory-icons))
  264. (when emacspeak-use-auditory-icons
  265. (process-send-string dtk-speaker-process
  266. (format "p %s\n"
  267. (emacspeak-get-sound-filename sound-name )))))
  268. ;;}}}
  269. ;;{{{ Play an icon
  270. (defcustom emacspeak-play-args ""
  271. "Set this to -i if using the play program that ships on sunos/solaris.
  272. Note: on sparc20's there is a sunos bug that causes the machine to crash if
  273. you attempt to play sound when /dev/audio is busy.
  274. It's imperative that you use the -i flag to play on
  275. sparc20's."
  276. :type 'string
  277. :group 'emacspeak-sounds)
  278. (defun emacspeak-play-auditory-icon (sound-name)
  279. "Produce auditory icon SOUND-NAME.
  280. Sound is produced only if `emacspeak-use-auditory-icons' is true.
  281. See command `emacspeak-toggle-auditory-icons' bound to \\[emacspeak-toggle-auditory-icons ]."
  282. (declare (special emacspeak-use-auditory-icons emacspeak-play-program))
  283. (and emacspeak-use-auditory-icons
  284. (let ((process-connection-type nil))
  285. (condition-case err
  286. (start-process
  287. "play" nil emacspeak-play-program
  288. (emacspeak-get-sound-filename sound-name))
  289. (error
  290. (message (error-message-string err)))))))
  291. ;;}}}
  292. ;;{{{ setup play function
  293. (defcustom emacspeak-auditory-icon-function 'emacspeak-serve-auditory-icon
  294. "*Function that plays auditory icons."
  295. :group 'emacspeak-sounds
  296. :type '(choice
  297. (const emacspeak-play-auditory-icon)
  298. (const emacspeak-serve-auditory-icon)
  299. (const emacspeak-native-auditory-icon)
  300. (const emacspeak-queue-auditory-icon)))
  301. ;;;###autoload
  302. (defun emacspeak-auditory-icon (icon)
  303. "Play an auditory ICON."
  304. (declare (special emacspeak-auditory-icon-function
  305. emacspeak-use-auditory-icons))
  306. (when emacspeak-use-auditory-icons
  307. (funcall emacspeak-auditory-icon-function icon)))
  308. ;;}}}
  309. ;;{{{ toggle auditory icons
  310. ;;; This is the main entry point to this module:
  311. ;;;###autoload
  312. (defun emacspeak-toggle-auditory-icons (&optional prefix)
  313. "Toggle use of auditory icons.
  314. Optional interactive PREFIX arg toggles global value."
  315. (interactive "P")
  316. (declare (special emacspeak-use-auditory-icons
  317. dtk-program emacspeak-auditory-icon-function))
  318. (require 'emacspeak-aumix)
  319. (cond
  320. (prefix
  321. (setq emacspeak-use-auditory-icons
  322. (not emacspeak-use-auditory-icons))
  323. (setq-default emacspeak-use-auditory-icons
  324. emacspeak-use-auditory-icons))
  325. (t (setq emacspeak-use-auditory-icons
  326. (not emacspeak-use-auditory-icons))))
  327. (message "Turned %s auditory icons %s"
  328. (if emacspeak-use-auditory-icons "on" "off" )
  329. (if prefix "" "locally"))
  330. (when emacspeak-use-auditory-icons
  331. (emacspeak-auditory-icon 'on)))
  332. (defvar emacspeak-sounds-auditory-icon-players
  333. '("emacspeak-serve-auditory-icon"
  334. "emacspeak-play-auditory-icon"
  335. "emacspeak-native-auditory-icon")
  336. "Table of auditory icon players used when selecting a player.")
  337. (defun emacspeak-select-auditory-icon-player ()
  338. "Pick a player for producing auditory icons."
  339. (declare (special emacspeak-sounds-auditory-icon-players))
  340. (read
  341. (completing-read "Select auditory icon player: "
  342. emacspeak-sounds-auditory-icon-players
  343. nil nil
  344. "emacspeak-")))
  345. ;;;###autoload
  346. (defun emacspeak-set-auditory-icon-player (player)
  347. "Select player used for producing auditory icons.
  348. Recommended choices:
  349. emacspeak-serve-auditory-icon for the wave device.
  350. emacspeak-queue-auditory-icon when using software TTS."
  351. (interactive
  352. (list
  353. (emacspeak-select-auditory-icon-player )))
  354. (declare (special emacspeak-auditory-icon-function))
  355. (setq emacspeak-auditory-icon-function player)) (when (interactive-p)
  356. (emacspeak-auditory-icon 'select-object))
  357. ;;}}}
  358. ;;{{{ Show all icons
  359. (defun emacspeak-play-all-icons ()
  360. "Plays all defined icons and speaks their names."
  361. (interactive)
  362. (mapcar
  363. '(lambda (f)
  364. (emacspeak-auditory-icon f)
  365. (dtk-speak (format "%s" f))
  366. (sleep-for 2))
  367. (emacspeak-sounds-icon-list)))
  368. ;;}}}
  369. ;;{{{ reset local player
  370. (defun emacspeak-sounds-reset-local-player ()
  371. "Ask Emacspeak to use a local audio player.
  372. This lets me have Emacspeak switch to using audioplay on
  373. solaris after I've used it for a while from a remote session
  374. where it would use the more primitive speech-server based
  375. audio player."
  376. (interactive)
  377. (declare (special emacspeak-play-program))
  378. (if (file-exists-p "/usr/demo/SOUND/play")
  379. (setq
  380. emacspeak-play-program "/usr/demo/SOUND/play"
  381. emacspeak-play-args "-i"
  382. emacspeak-auditory-icon-function
  383. 'emacspeak-play-auditory-icon))
  384. (if (file-exists-p "/usr/bin/audioplay")
  385. (setq
  386. emacspeak-play-program "/usr/bin/audioplay"
  387. emacspeak-play-args "-i"
  388. emacspeak-auditory-icon-function 'emacspeak-play-auditory-icon)))
  389. ;;}}}
  390. ;;{{{ flush sound driver
  391. (defcustom emacspeak-sounds-reset-snd-module-command nil
  392. "Command to reset sound module."
  393. :type '(choice
  394. :tag "Command to reset sound modules: "
  395. (const nil :tag "None")
  396. (string :tag "Command "))
  397. :group 'emacspeak-sounds)
  398. ;;;###autoload
  399. (defun emacspeak-sounds-reset-sound ()
  400. "Reload sound drivers."
  401. (interactive)
  402. (declare (special emacspeak-sounds-reset-snd-module-command))
  403. (when emacspeak-sounds-reset-snd-module-command
  404. (shell-command emacspeak-sounds-reset-snd-module-command)))
  405. ;;}}}
  406. (provide 'emacspeak-sounds)
  407. ;;{{{ emacs local variables
  408. ;;; local variables:
  409. ;;; folded-file: t
  410. ;;; byte-compile-dynamic: t
  411. ;;; end:
  412. ;;}}}