1 ;;; erc-speak.el --- Speech-enable the ERC chat client
3 ;; Copyright 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
5 ;; This file is part of GNU Emacs.
7 ;; GNU Emacs is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; GNU Emacs is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU Emacs; see the file COPYING. If not, write to the
19 ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 ;; Boston, MA 02110-1301, USA.
24 ;; This file contains code to speech enable ERC using Emacspeak's functionality
25 ;; to access a speech synthesizer.
27 ;; It tries to be intelligent and produce actually understandable
28 ;; audio streams :). Hopefully it does. I use it on #debian at irc.debian.org
29 ;; with about 200 users, and I am amazed how easy it works.
31 ;; Currently, erc-speak is only written to listen to channels.
32 ;; There is no special functionality for interaction in the erc buffers.
33 ;; Although this shouldn't be hard. Look at the Todo list, there are
34 ;; definitely many things this script could do nicely to make a better
35 ;; IRC experience for anyone.
37 ;; More info? Read the code. It isn't that complicated.
42 ;; Put erc.el and erc-speak.el somewhere in your load-path and
43 ;; (require 'erc-speak) in your .emacs. Remember to require only erc-speak
44 ;; because otherwise you get conflicts with emacspeak.
48 ;; erc-speak-rate doesn't seem to work here on outloud. Can anyone enlighten
49 ;; me on the use of dtk-interp-queue-set-rate or equivalent?
54 (provide 'emacspeak-erc)
58 (defgroup erc-speak nil
59 "Enable speech synthesis with the ERC chat client using Emacspeak"
62 (defcustom erc-speak-personalities '((erc-default-face paul)
63 (erc-direct-msg-face paul-animated)
64 (erc-input-face paul-smooth)
65 (erc-bold-face paul-bold)
66 (erc-inverse-face betty)
67 (erc-underline-face ursula)
68 (erc-prompt-face harry)
69 (erc-notice-face paul-italic)
70 (erc-action-face paul-monotone)
72 (erc-dangerous-host-face paul-surprized)
73 (erc-pal-face paul-animated)
74 (erc-fool-face paul-angry)
75 (erc-keyword-face paul-animated))
76 "Maps faces used in erc to speaker personalities in emacspeak."
81 (symbol :tag "personality"))))
83 (add-hook 'erc-mode-hook (lambda () (setq voice-lock-mode t)))
85 ;; Override the definition in erc.el
86 (defun erc-put-text-property (start end property value &optional object)
87 "This function sets the appropriate personality on the specified
88 region in addition to setting the requested face."
89 (put-text-property start end property value object)
90 (when (eq property 'face)
91 (put-text-property start end
93 (cadr (assq value erc-speak-personalities))
96 (add-hook 'erc-insert-post-hook 'erc-speak-region)
97 (add-hook 'erc-send-post-hook 'erc-speak-region)
99 (defcustom erc-speak-filter-host t
100 "Set to t if you want to filter out user@host constructs."
104 (defcustom erc-speak-filter-timestamp t
105 "If non-nil, try to filter out the timestamp when speaking arriving messages.
107 Note, your erc-timestamp-format variable needs to start with a [
112 (defcustom erc-speak-acronyms '(("brb" "be right back")
114 ("wtf" "what the fuck")
115 ("rotfl" "rolling on the floor and laughing")
116 ("afaik" "as far as I know")
117 ("afaics" "as far as I can see")
118 ("iirc" "if I remember correctly"))
119 "List of acronyms to expand."
121 :type '(repeat sexp))
123 (defun erc-speak-acronym-replace (string)
124 "Replace acronyms in the current buffer."
125 (let ((case-fold-search nil))
126 (dolist (ac erc-speak-acronyms string)
127 (while (string-match (car ac) string)
128 (setq string (replace-match (cadr ac) nil t string))))))
130 (defcustom erc-speak-smileys '((":-)" "smiling face")
131 (":)" "smiling face")
134 ;; please add more, send me patches, mlang@home.delysid.org tnx
135 "List of smileys and their textual description."
137 :type '(repeat (list 'symbol 'symbol)))
139 (defcustom erc-speak-smiley-personality 'harry
140 "Personality used for smiley announcements."
144 (defun erc-speak-smiley-replace (string)
145 "Replace smileys with textual description."
146 (let ((case-fold-search nil))
147 (dolist (smiley erc-speak-smileys string)
148 (while (string-match (car smiley) string)
149 (let ((repl (cadr smiley)))
150 (put-text-property 0 (length repl) 'personality
151 erc-speak-smiley-personality repl)
152 (setq string (replace-match repl nil t string)))))))
154 (defcustom erc-speak-channel-personality 'harry
155 "*Personality to announce channel names with."
159 (defun erc-speak-region ()
160 "Speak a region containing one IRC message using Emacspeak.
161 This function tries to translate common IRC forms into
163 (let ((target (if (erc-channel-p (erc-default-target))
166 'personality erc-speak-channel-personality)
168 (dtk-stop-immediately nil))
169 (emacspeak-auditory-icon 'progress)
170 (when erc-speak-filter-timestamp
172 (goto-char (point-min))
173 (when (re-search-forward "^\\[[a-zA-Z:,;.0-9 \t-]+\\]" nil t)
174 (narrow-to-region (point) (point-max)))))
176 (goto-char (point-min))
177 (cond ((re-search-forward (concat "^<\\([^>]+\\)> "
179 erc-valid-nick-regexp
181 (let ((from (match-string 1))
182 (to (match-string 2))
183 (text (buffer-substring (match-end 2) (point-max))))
184 (tts-with-punctuations
186 (dtk-speak (concat (erc-propertize
187 (concat target " " from " to " to)
188 'personality erc-speak-channel-personality)
189 (erc-speak-smiley-replace
190 (erc-speak-acronym-replace text)))))))
191 ((re-search-forward "^<\\([^>]+\\)> " nil t)
192 (let ((from (match-string 1))
193 (msg (buffer-substring (match-end 0) (point-max))))
194 (tts-with-punctuations
196 (dtk-speak (concat target " " from " "
197 (erc-speak-smiley-replace
198 (erc-speak-acronym-replace msg)))))))
199 ((re-search-forward (concat "^" (regexp-quote erc-notice-prefix)
202 (let ((notice (buffer-substring (match-beginning 1) (point-max))))
203 (tts-with-punctuations
208 (when erc-speak-filter-host
209 (goto-char (point-min))
210 (when (re-search-forward "([^)@]+@[^)@]+)" nil t)
213 (t (let ((msg (buffer-substring (point-min) (point-max))))
214 (tts-with-punctuations
216 (dtk-speak (concat target " "
217 (erc-speak-smiley-replace
218 (erc-speak-acronym-replace msg)))))))))))
222 ;;; erc-speak.el ends here
225 ;; indent-tabs-mode: t
229 ;; arch-tag: 4499cd13-2829-43b8-83de-d313481531c4