[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Search]

erc-speak.el -- Speech enable ERC Internet Relay Chat Client



Hello. I am currently hacking on my first bit more complicated
Lisp program. And I wanted to pass it on to you so that you could
experiment with it or drom me comments.

Please note that I use the script primarily to listen to channels,
but I am not a primary speech user (braille display). So there
are probably many things you as speech only user wouldn't like.

This is a pre-pre-pre-alpha-gamma-ray test version. So dont expect
it to be perfect. For wishes, look at the Todo list first.
If you like this and have some spare time, send me additions.

Here we go:

;;; erc-speak.el -- Speech-enable the ERC chat client

;; Copyright 2001 Mario Lang <mlang@xxxxxxxxxxx>

;; This file is protected by the GNU GPL, same conditions as with
;; Emacs apply, although this file is not part of GNU Emacs.

;;  Commentary:

;; This file contains code to speech enable ERC using Emacspeaks functionality
;; to access a speech synthesizer.
;;
;; It tries to be intelligent and produce actually understandable
;; audio streams :). Hopefully it does. I use it on #debian at irc.debian.org
;; with about 200 users, and I am amazed how easy it works.
;;
;; Currently, erc-speak is only written to listen to channels.
;; There is no special functionality for interaction in the erc buffers.
;; Although this shouldn't be hard. Look at the Todo list, there are
;; definitely many things this script could do nicely to make a better
;; IRC experience for anyone.
;;
;; More info? Read the code. It isn't that complicated.
;;

;;  Installation:

;; Change the (load ...) calls at the beginning of code to point
;; to your erc.el and edo-tools.el files.
;;
;; And load this file.

;;  Bugs:

;; erc-speak-rate doesn't seem to work here on outloud. Can anyone enlighten
;; me on the use of dtk-interp-queue-set-rate or equivalents?

;;  Todo:

;; * Rewrite erc-speak-join and write erc-speak-part/quit to also
;;   use the queue and use erc-speak-debug instead of poor format.
;; * Write acronym handling functions and lists
;; * ACTIONs (spoken with a third voice)
;; * Optimize erc-speak-to-whom for more intelligence
;; * Introduce nickname mapping to something alternatively (names
;;   or sounds)
;; * Implement bold and perhaps colors
;; * Convert defvar to defcustom where useful.
;; * Check library header to make something more LCD like.
;; * Add your wish here.
;;

;;  Code:

(load "~/edo-tools.el")
(load "~/erc.el")

(require 'erc)
(require 'emacspeak)

(defvar erc-speak-moderator 'harry
  "Voice used for the moderator (who writes where to whom)")

(defvar erc-speak-person 'paul
  "Voice used for message content")

(defvar erc-speak-debug t
  "Define whether or not erc-speak should log the content
it receives via the hooks.

We are simply using erc-log-aux and ignoree the erc-debug settings.")

(defvar erc-speak-rate 85
  "The speech rate for IRC traffic.
BUG: dtk-interp-queue-set-rate seems to not work. Any hints?")

(defvar erc-speak-quiet nil
  "Set this to prevent erc-speak from actually talking.
nil    - Happily talk away
'maybe - Don't talk, but keep things in the queue for analysis or later
         playback.
't - Don't talk and discard messages.

You can manipulate the queue when this variable is either nil nor t.")

(defvar erc-speak-message-queue nil
  "A FIFO for messages.")

(defun erc-speak-queue-message (message target nick buffer-name host login spec)
  "Appends the values received by erc-message-hook to erc-speak-message-queue."
  (if erc-speak-debug
      (erc-log-aux (erc-speak-debug 'erc-speak-message
				    message 'message
				    target 'target
				    nick 'nick
				    buffer-name 'buffer
				    host 'host
				    login 'login
				    spec 'spec)))
  (setq erc-speak-message-queue
	(append 
	 erc-speak-message-queue
	 (list (list message target nick buffer-name host login spec)))))

(defun erc-speak-to-whom (message nicks)
  "Find out if message addresses one of nicks nicknames.
If true, nickname is returned, otherwise nil."
  (if (string-match
       (concat "^\\("
	       (substring
		(apply 'concat 
		       (mapcar (lambda (x) (concat "\\|" x )) nicks))
		2)
	       "\\):")
       message)
      (substring message (match-beginning 1) (match-end 1))
    nil))

(defun erc-speak-message ()
  "This function is called via the timer every once in a while.
It pops one or more items of the queue and send them to the speech
server. (intelligence not implemented yet)"
  (if (eq erc-speak-quiet 'nil)
      (if erc-speak-message-queue
	  (let* ((item (car erc-speak-message-queue))
		 (message (car item))
		 (target (car (cdr item)))
		 (nick (car (nthcdr 2 item)))
		 (buffer (car (nthcdr 3 item))))
	    (save-excursion
	      (set-buffer buffer)
	      (let* ((members
		      (mapcar (lambda (x) (car x))
			      channel-members))
		     (to-whom (erc-speak-to-whom message members)))
		(dtk-interp-set-punctuations "some")
		(dtk-interp-queue-set-rate erc-speak-rate)
		(dtk-speak-using-voice
		 erc-speak-moderator
		 (if (eq (elt target 0) ?#)
		     (format "%s: %s"
			     (concat "" (substring target 1) ":")
			     (if to-whom
				 (format "%s writes to %s" nick to-whom)
			       nick))
		   (format "Message from %s" nick)))
		(dtk-speak-using-voice
		 erc-speak-person
		 (format "%s" 
			 (if to-whom
			     (substring message (match-end 0))
			   message)))
		(dtk-force)))
	    (setq erc-speak-message-queue (cdr erc-speak-message-queue))
	    ))))

(defvar erc-speak-message-timer nil
  "Holds the timer object used to speak messages.
Use it with cancel-timer to remove erc-speak-queue-message")

(defvar erc-speak-idle-time 5
  "Start speaking IRC information after specified time.
Actually this currently means \"Try to pop from the FIFO every SEC seconds\".
Idle time behaviour still has to be written (how to find out how long Emacs
is idle?")

(defun erc-speak-setup ()
  "Initialize the timer functions and add hooks."
  (setq erc-speak-message-timer
	(run-at-time erc-speak-idle-time
		     erc-speak-idle-time 'erc-speak-message))
  (add-hook 'erc-message-hook 'erc-speak-queue-message)
  ;; Join and part behaviour has still to be integrated into the queue
  ;; Wondering if this makes sense anyway.
  (add-hook 'erc-join-hook 'erc-speak-join))
  
(defun erc-speak-join (channel nick buffer ip login spec)
  "Attempts to voicify join events."
  (save-excursion
    (set-buffer buffer)
    (if erc-speak-debug
	(erc-log-aux
	 (concat "(erc-speak-join\n"
		 (format "\t\"%s\" ;; channel\n\t\"%s\" ;; nick\n\t\"%s\" ;; buffer\n\t\"%s\" ;; ip\n\t\"%s\" ;; login\n\t\"%s\" ;; spec)\n"
			 channel nick buffer ip login spec))))
    (if (not erc-speak-quiet)
	(progn
	  (dtk-interp-set-punctuations "some")
	  (dtk-interp-queue-set-rate erc-speak-rate)
	  (dtk-speak-using-voice
	   erc-speak-moderator
	   (format "%s joined channel %s"
		   nick channel))
	  (dtk-force)))))

(defun erc-speak-debug (name &rest list)
  "Return useful debug message."
  (let ((item list)
	(result (concat "'(" (symbol-name name) "\n")))
    (while item
      (setq result (concat result
			   "\t;; "
			   (symbol-name (car (cdr item)))
			   "\n\t\""
			   (car item)
			   "\"\n"))
      (setq item (nthcdr 2 item)))
    (concat result ")")))

(erc-speak-setup)
(provide 'erc-speak)

;;  End of file:

-- 
HearYa,
   Mario <mlang@xxxxxxxxxxx>
Homepage(s): http://delysid.org | http://piss.at/

Linux: Because a PC is a terrible thing to waste.
(By komarimf@xxxxxxxxxxx, Mark Komarinski)

-----------------------------------------------------------------------------
To unsubscribe from the emacspeak list or change your address on the
emacspeak list send mail to "emacspeak-request@xxxxxxxxxxx" with a
subject of "unsubscribe" or "help"


Emacspeak Files | Subscribe | Unsubscribe | Search