summaryrefslogtreecommitdiff
path: root/chess-sound.el
blob: 6c31a9dc7e8bcfd7e83cedcf31193f4676874ace (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; This is very similar to chess-announce, except it uses specific
;; .WAV files instead of text-to-speech.
;;
;; $Revision$

(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
  :group 'chess-sound)

(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 'file
  :group 'chess-sound)

(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
  :group 'chess-sound)

(defcustom chess-sound-args nil
  "Additional args to pass to `chess-sound-program', before the .WAV file."
  :type '(repeat string)
  :group 'chess-sound)

(defun chess-sound-available-p ()
  (and (file-directory-p chess-sound-directory)
       (file-readable-p (expand-file-name "tap.wav"
					  chess-sound-directory))
       (or (eq chess-sound-play-function 'play-sound-file)
	   (file-executable-p chess-sound-program))))

(defun chess-sound-for-game (game)
  "Announce the opponent's moves in GAME."
  (chess-game-add-hook game 'chess-sound-handler))

(defun chess-sound (ch)
  (let ((file
	 (cond
	  ((stringp ch)
	   (format "%s.wav" ch))
	  ((memq ch '(?\# ?\+ ?k ?q ?b ?n ?r ?p ?x))
	   (format "%c_.wav" ch))
	  (t
	   (format "%s.wav" (chess-index-to-coord ch))))))
    (funcall chess-sound-play-function
	     (expand-file-name file chess-sound-directory))))

(defun chess-sound-play (file)
  (apply 'call-process chess-sound-program
	 nil nil nil (append chess-sound-args (list file))))

(defun chess-sound-handler (game ignore event &rest args)
  "This display module presents a standard chessboard.
See `chess-display-type' for the different kinds of displays."
  (cond
   ((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))
	  (chess-sound "tap")
	(let* ((source (chess-ply-source ply))
	       (target (chess-ply-target ply))
	       (s-piece (chess-pos-piece pos source))
	       (t-piece (chess-pos-piece pos target))
	       text)
	  (cond
	   ((chess-ply-has-keyword :castle)
	    (chess-sound "O-O"))
	   ((chess-ply-has-keyword :long-castle)
	    (chess-sound "O-O-O"))
	   ((= t-piece ? )
	    (chess-sound (downcase s-piece))
	    (chess-sound target))
	   (t
	    (chess-sound (downcase s-piece))
	    (chess-sound ?x)
	    (chess-sound (downcase t-piece))
	    (chess-sound target)))
	  (if (chess-ply-has-keyword :check)
	      (chess-sound ?+))
	  (if (chess-ply-has-keyword :checkmate)
	      (chess-sound ?#))
	  (if (chess-ply-has-keyword :stalemate)
	      (chess-sound "smate")))))
    nil)))

(provide 'chess-sound)

;;; chess-sound.el ends here