;;; emacspeak-daisy.el --- daisy Front-end for emacspeak desktop ;;; $Id$ ;;; $Author: tv.raman.tv $ ;;; Description: Emacspeak front-end for DAISY Talking Books ;;; Keywords: Emacspeak, daisy Digital Talking Books ;;{{{ LCD Archive entry: ;;; LCD Archive Entry: ;;; emacspeak| T. V. Raman |raman@cs.cornell.edu ;;; A speech interface to Emacs | ;;; $Date: 2008-06-21 10:50:41 -0700 (Sat, 21 Jun 2008) $ | ;;; $Revision: 4541 $ | ;;; Location undetermined ;;; ;;}}} ;;{{{ Copyright: ;;; Copyright (C) 1999, 2011 T. V. Raman ;;; All Rights Reserved. ;;; ;;; This file is not part of GNU Emacs, but the same permissions apply. ;;; ;;; GNU Emacs is free software; you can redistribute it and/or modify ;;; it under the terms of the GNU General Public License as published by ;;; the Free Software Foundation; either version 2, or (at your option) ;;; any later version. ;;; ;;; GNU Emacs is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;;; GNU General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with GNU Emacs; see the file COPYING. If not, write to ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. ;;}}} ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;{{{ Introduction: ;;; Commentary: ;;; Daisy Digital Talking Book Reader ;;}}} ;;{{{ required modules ;;; Code: (require 'emacspeak-preamble) (require 'xml-parse) ;;}}} ;;{{{ Customization variables (defgroup emacspeak-daisy nil "Daisy Digital Talking Books for the Emacspeak desktop." :group 'emacspeak) ;;}}} ;;{{{ Book structure ;;; Book structure (defstruct emacspeak-daisy-book base basename title content audio-process nav-center) (defsubst emacspeak-daisy-book-name (this-book) "Return a canonical name for the book." (expand-file-name (emacspeak-daisy-book-basename this-book) (emacspeak-daisy-book-base this-book))) ;;}}} ;;{{{ helpers (defvar emacspeak-daisy-frame-seconds 0.02612219949104336 "Number of seconds in a frame.") (defsubst emacspeak-daisy-time-string-to-frame (timestr) "Convert time string (hh:mm:ss.SS) to frame number.(0.026s/f)" (declare (special emacspeak-daisy-frame-seconds)) (save-match-data (string-match "\\(..\\):\\(..\\):\\(...**\\)" timestr) (let* ((h (string-to-number (substring timestr (match-beginning 1) (match-end 1)))) (m (string-to-number (substring timestr (match-beginning 2) (match-end 2)))) (s (string-to-number (substring timestr (match-beginning 3) (match-end 3)))) (total (+ (* 3600 h) (* m 60) s))) (round (/ total emacspeak-daisy-frame-seconds))))) (defsubst emacspeak-daisy-resolve-uri (relative book) "Resolve relative URI with respect to base URI of book." (expand-file-name relative (emacspeak-daisy-book-base book))) ;;}}} ;;{{{ find element by id (defun xml-find-tag-by-id (tree id) "Walk tree and return node matching id." (let ((children (xml-tag-children tree)) (current nil) (found nil)) (cond ((and (xml-tag-with-attributes-p tree) (string-equal (xml-tag-attr tree "id") id) tree)) (t (while (and children (not found)) (setq current (pop children)) (unless (stringp current) (setq found (xml-find-tag-by-id current id)))) found)))) ;;}}} ;;{{{ return matching children (defun xml-children-by-name (tag name) "Return list of children matching NAME, of an xml-parse'd XML TAG." (let ((children (xml-tag-children tag))) (remove-if #'(lambda (tag) (not (string-equal name (xml-tag-name tag)))) children))) ;;}}} ;;{{{ play audio clip (defvar emacspeak-daisy-mpg123-player "mpg123" "MPG123 executable for playing mp3 files.") (defun emacspeak-daisy-play-audio (clip) "Play clip specified by clip. Clip is the result of parsing element