;;; chess-sound.el --- Announce chess moves with pre-recorded sound files -*- lexical-binding: t; -*- ;; Copyright (C) 2002-2020 Free Software Foundation, Inc. ;; Author: John Wiegley ;; Maintainer: Mario Lang ;; Keywords: games ;; This program 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 3 of the License, or ;; (at your option) any later version. ;; This program 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 this program. If not, see . ;;; Commentary: ;; This is very similar to chess-announce, except it uses specific ;; .WAV files instead of text-to-speech. ;;; Code: (require 'chess-game) (defgroup chess-sound nil "Code to play specific sounds when announcing chess moves." :group 'chess) (defcustom chess-sound-directory (expand-file-name "sounds" (file-name-directory (or load-file-name buffer-file-name))) "The directory where chess sounds can be found." :type 'directory) (defcustom chess-sound-play-function (if (fboundp 'play-sound-file) #'play-sound-file #'chess-sound-play) "Non-nil if chess-sound should play sounds ." :type 'function) (defcustom chess-sound-program (or (executable-find "esdplay") (executable-find "play")) "Program used to play sounds, if `play-sound-file' does not exist." :type 'file) (defcustom chess-sound-args nil "Additional args to pass to `chess-sound-program', before the .WAV file." :type '(repeat string)) (defcustom chess-sound-my-moves nil "If non-nil, plays the move.wav sound whenever you make a move." :type 'boolean) (defsubst chess-sound (file) (ignore-errors (funcall chess-sound-play-function (expand-file-name (concat file ".wav") chess-sound-directory)))) (defsubst chess-sound-play (file) (apply #'call-process chess-sound-program nil nil nil (append chess-sound-args (list file)))) (defun chess-sound-handler (game event &rest _args) (cond ((eq event 'initialize) (and (file-directory-p chess-sound-directory) (file-readable-p (expand-file-name "move.wav" chess-sound-directory)) (or (eq chess-sound-play-function #'play-sound-file) (and chess-sound-program (file-executable-p chess-sound-program))))) ((eq event 'move) (let* ((ply (chess-game-ply game (1- (chess-game-index game)))) (pos (chess-ply-pos ply))) (if (eq (chess-game-data game 'my-color) (chess-pos-side-to-move pos)) (if chess-sound-my-moves (chess-sound "move")) (let* ((source (chess-ply-source ply)) (target (chess-ply-target ply)) (s-piece (and source (chess-pos-piece pos source))) (t-piece (and target (chess-pos-piece pos target))) (which (chess-ply-keyword ply :which))) (cond ((chess-ply-keyword ply :castle) (chess-sound "O-O")) ((chess-ply-keyword ply :long-castle) (chess-sound "O-O-O")) ((and s-piece t-piece (= t-piece ? ) target) (if which (chess-sound (char-to-string which))) (chess-sound (format "%c_" (downcase s-piece))) (chess-sound (chess-index-to-coord target))) ((and s-piece t-piece target) (if which (chess-sound (char-to-string which))) (chess-sound (format "%c_" (downcase s-piece))) (chess-sound "x_") (chess-sound (format "%c_" (downcase t-piece))) (chess-sound (chess-index-to-coord target)))) (if (chess-ply-keyword ply :promote) (chess-sound (format "%c_" (downcase (chess-ply-keyword ply :promote))))) (if (chess-ply-keyword ply :en-passant) (chess-sound "enpassant")) (if (chess-ply-keyword ply :check) (chess-sound "+_")) (if (chess-ply-keyword ply :checkmate) (chess-sound "#_")) (if (chess-ply-keyword ply :stalemate) (chess-sound "smate")))))))) (provide 'chess-sound) ;;; chess-sound.el ends here