1#!/usr/bin/env python
2
3# Copyright (C) 2003, 2006, 2007 Brailcom, o.p.s.
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU Lesser General Public License as published by
7# the Free Software Foundation; either version 2.1 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU Lesser General Public License for more details.
14#
15# You should have received a copy of the GNU Lesser General Public License
16# along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
18import unittest
19import time
20
21from .client import PunctuationMode, CallbackType, SSIPClient, Scope, Speaker
22
23
24class _SSIPClientTest(unittest.TestCase):
25
26    def setUp(self):
27        self._client = SSIPClient('test')
28        self._client.set_language('en')
29        self._client.set_rate(30)
30
31    def tearDown(self):
32        self._client.close()
33
34class AutomaticTest(_SSIPClientTest):
35    """A set of tests which may be evaluated automatically.
36
37    Please put all tests which require a user to listen to their output to the
38    VoiceTest below.
39
40    """
41    def test_callbacks(self):
42        # TODO: This needs to be fixed. There is no guarantee that
43        # the message will start in one second nor is there any
44        # guarantee that it will start at all. It can be interrupted
45        # by other applications etc. Also there is no guarantee that
46        # the cancel will arrive on time and the end callback will be
47        # received on time. Also the combination cancel/end does not have
48        # to work as expected and SD and the interface can still be ok.
49        # -- Hynek Hanke
50        self._client.set_output_module('flite')
51        called = {CallbackType.BEGIN: [],
52                  CallbackType.CANCEL: [],
53                  CallbackType.END: []}
54        self._client.speak("This message should get interrupted.  It is "
55                           "hopefully long enough to last more than 1 second.",
56                           callback=lambda type: called[type].append('msg1'))
57        self._client.speak("This second message should not be spoken at all.",
58                           callback=lambda type: called[type].append('msg2'))
59        time.sleep(1)
60        self._client.cancel()
61        self._client.speak("Hi.",
62                           callback=lambda type: called[type].append('msg3'))
63        # Wait for pending events...
64        time.sleep(3)
65        started, canceled, ended = [called[t] for t in (CallbackType.BEGIN,
66                                                        CallbackType.CANCEL,
67                                                        CallbackType.END)]
68        assert started == ['msg1', 'msg3'] and ended == ['msg3'] and \
69               'msg1' in canceled and 'msg2' in canceled and \
70               'msg3' not in canceled, \
71               (called,
72                "This failure only indicates a possible error.  The test "
73                "depends on proper timing and results may warry depending "
74                "on the used output module and other conditions.  See the "
75                "code of this test method if you want to investigate "
76                "further.")
77
78
79
80class VoiceTest(_SSIPClientTest):
81    """This set of tests requires a user to listen to it.
82
83    The success or failure of the tests defined here can not be detected
84    automatically.
85
86    """
87
88    def test_escapes(self):
89        c = self._client
90        c.speak("Testing data escapes:")
91        c.set_punctuation(PunctuationMode.ALL)
92        c.speak(".")
93        c.speak("Marker at the end.\r\n.\r\n")
94        c.speak(".\r\nMarker at the beginning.")
95
96    def test_voice_properties(self):
97        c = self._client
98        c.speak("Testing voice properties:")
99        c.set_pitch(-100)
100        c.speak("I am fat Billy")
101        c.set_pitch(100)
102        c.speak("I am slim Willy")
103        c.set_pitch(0)
104        c.set_rate(100)
105        c.speak("I am quick Dick.")
106        c.set_rate(-80)
107        c.speak("I am slow Joe.")
108        c.set_rate(0)
109        c.set_pitch(100)
110        c.set_volume(-50)
111        c.speak("I am quiet Mariette.")
112        c.set_volume(100)
113        c.speak("I am noisy Daisy.")
114
115    def test_other_commands(self):
116        c = self._client
117        c.speak("Testing other commands:")
118        c.char("a")
119        c.key("shift_b")
120        c.sound_icon("empty")
121
122    def test_lists(self):
123         c = self._client
124         for module in  c.list_output_modules():
125             c.set_output_module(module)
126             print("**", module)
127             c.speak(module +"using default voice")
128             for name, lang, dialect in c.list_synthesis_voices():
129                 print(" -", module, name, lang, dialect)
130                 c.set_synthesis_voice(name)
131                 c.speak(module +" using voice "+ name)
132
133
134if __name__ == '__main__':
135    unittest.main()
136