| [13390] | 1 | ;;; speech-controller.lisp
|
|---|
| 2 |
|
|---|
| 3 | #|
|
|---|
| 4 | The MIT license.
|
|---|
| 5 |
|
|---|
| 6 | Copyright (c) 2009 Paul L. Krueger
|
|---|
| 7 |
|
|---|
| 8 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software
|
|---|
| 9 | and associated documentation files (the "Software"), to deal in the Software without restriction,
|
|---|
| 10 | including without limitation the rights to use, copy, modify, merge, publish, distribute,
|
|---|
| 11 | sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
|
|---|
| 12 | furnished to do so, subject to the following conditions:
|
|---|
| 13 |
|
|---|
| 14 | The above copyright notice and this permission notice shall be included in all copies or substantial
|
|---|
| 15 | portions of the Software.
|
|---|
| 16 |
|
|---|
| 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
|---|
| 18 | LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|---|
| 19 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|---|
| 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|---|
| 21 | SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|---|
| 22 |
|
|---|
| 23 | |#
|
|---|
| 24 |
|
|---|
| 25 | ;;; Sample lisp/Cocoa interface that uses a NIB file defined with interface builder;
|
|---|
| 26 | ;;; A definition is provided for the "SpeechController" class that was specified to interface builder
|
|---|
| 27 | ;;; as the class of the NIB file owner.
|
|---|
| 28 | ;;; We manually create an instance of SpeechController and specify it as the owner for the NIB file.
|
|---|
| 29 |
|
|---|
| [13646] | 30 | (eval-when (:compile-toplevel :load-toplevel :execute)
|
|---|
| 31 | (require :nib))
|
|---|
| [13390] | 32 |
|
|---|
| 33 | (defpackage :speech-controller
|
|---|
| 34 | (:nicknames :spc)
|
|---|
| 35 | (:use :iu :ccl :common-lisp)
|
|---|
| 36 | (:export test-speech))
|
|---|
| 37 |
|
|---|
| 38 | (in-package :spc)
|
|---|
| 39 |
|
|---|
| 40 | (defclass speech-controller (ns:ns-object)
|
|---|
| 41 | ((speech-text :foreign-type :id :accessor speech-text)
|
|---|
| 42 | (button-matrix :foreign-type :id :accessor button-matrix)
|
|---|
| 43 | (speech-synth :accessor speech-synth
|
|---|
| 44 | :initform (make-instance ns:ns-speech-synthesizer))
|
|---|
| 45 | (voices :accessor voices
|
|---|
| 46 | :initform (#/retain (#/availableVoices ns:ns-speech-synthesizer)))
|
|---|
| 47 | (nib-objects :accessor nib-objects :initform nil))
|
|---|
| 48 | (:metaclass ns:+ns-object))
|
|---|
| 49 |
|
|---|
| 50 | (defmethod initialize-instance :after ((self speech-controller)
|
|---|
| 51 | &key &allow-other-keys)
|
|---|
| 52 | (setf (nib-objects self)
|
|---|
| 53 | (load-nibfile
|
|---|
| 54 | (truename "ip:Speech;SpeechView.nib")
|
|---|
| 55 | :nib-owner self
|
|---|
| 56 | :retain-top-objs t))
|
|---|
| 57 | ;; get all of the voice strings and set the names of the radio buttons
|
|---|
| 58 | (dotimes (i (#/count (voices self)))
|
|---|
| 59 | (multiple-value-bind (col row) (floor i 6)
|
|---|
| 60 | (#/setTitle: (#/cellAtRow:column: (button-matrix self) row col)
|
|---|
| 61 | (#/objectForKey:
|
|---|
| 62 | (#/attributesForVoice: ns:ns-speech-synthesizer
|
|---|
| 63 | (#/objectAtIndex: (voices self) i))
|
|---|
| 64 | #&NSVoiceName))))
|
|---|
| 65 | ;; Make sure that the initial voice selected for the speech syntesizer matches
|
|---|
| 66 | ;; the radio button that is selected at startup. To do that we'll just call our
|
|---|
| 67 | ;; own buttonPushed: method.
|
|---|
| 68 | (#/buttonPushed: self (button-matrix self))
|
|---|
| 69 | ;; we do the following so that ccl:terminate will be called before we are
|
|---|
| 70 | ;; garbage collected and we can release the top-level objects from the NIB
|
|---|
| 71 | ;; that we retained when loaded
|
|---|
| 72 | (ccl:terminate-when-unreachable self))
|
|---|
| 73 |
|
|---|
| 74 | (defmethod ccl:terminate ((self speech-controller))
|
|---|
| 75 | (when (speech-synth self)
|
|---|
| 76 | (#/release (speech-synth self)))
|
|---|
| 77 | (when (voices self)
|
|---|
| 78 | (#/release (voices self)))
|
|---|
| 79 | (dolist (top-obj (nib-objects self))
|
|---|
| 80 | (unless (eql top-obj (%null-ptr))
|
|---|
| 81 | (#/release top-obj))))
|
|---|
| 82 |
|
|---|
| 83 | ;; Action methods called as a result of pushing some button
|
|---|
| 84 |
|
|---|
| 85 | (objc:defmethod (#/startSpeaking: :void)
|
|---|
| 86 | ((self speech-controller) (s :id))
|
|---|
| 87 | (declare (ignore s))
|
|---|
| 88 | (with-slots (speech-text speech-synth) self
|
|---|
| 89 | (let ((stxt (#/stringValue speech-text)))
|
|---|
| 90 | (when (zerop (#/length stxt))
|
|---|
| 91 | (setf stxt #@"I have nothing to say"))
|
|---|
| 92 | (#/startSpeakingString: speech-synth stxt))))
|
|---|
| 93 |
|
|---|
| 94 | (objc:defmethod (#/stopSpeaking: :void)
|
|---|
| 95 | ((self speech-controller) (s :id))
|
|---|
| 96 | (declare (ignore s))
|
|---|
| 97 | (with-slots (speech-synth) self
|
|---|
| 98 | (#/stopSpeaking speech-synth)))
|
|---|
| 99 |
|
|---|
| 100 | (objc:defmethod (#/buttonPushed: :void)
|
|---|
| 101 | ((self speech-controller) (button-matrix :id))
|
|---|
| 102 | (let ((row (#/selectedRow button-matrix))
|
|---|
| 103 | (col (#/selectedColumn button-matrix)))
|
|---|
| 104 | (#/setVoice: (speech-synth self)
|
|---|
| 105 | (#/objectAtIndex: (voices self) (+ row (* col 6))))))
|
|---|
| 106 |
|
|---|
| 107 | ;; test funtion
|
|---|
| 108 |
|
|---|
| 109 | (defun test-speech ()
|
|---|
| 110 | (make-instance 'speech-controller))
|
|---|
| 111 |
|
|---|
| 112 | (provide :speech-controller)
|
|---|