tts/backends/
speech_dispatcher.rs1#[cfg(target_os = "linux")]
2use std::{collections::HashMap, sync::Mutex};
3
4use lazy_static::*;
5use log::{info, trace};
6use oxilangtag::LanguageTag;
7use speech_dispatcher::*;
8
9use crate::{Backend, BackendId, Error, Features, UtteranceId, Voice, CALLBACKS};
10
11#[derive(Clone, Debug)]
12pub(crate) struct SpeechDispatcher(Connection);
13
14lazy_static! {
15 static ref SPEAKING: Mutex<HashMap<usize, bool>> = {
16 let m: HashMap<usize, bool> = HashMap::new();
17 Mutex::new(m)
18 };
19}
20
21impl SpeechDispatcher {
22 pub(crate) fn new() -> std::result::Result<Self, Error> {
23 info!("Initializing SpeechDispatcher backend");
24 let connection = speech_dispatcher::Connection::open("tts", "tts", "tts", Mode::Threaded)?;
25 let sd = SpeechDispatcher(connection);
26 let mut speaking = SPEAKING.lock().unwrap();
27 speaking.insert(sd.0.client_id(), false);
28 sd.0.on_begin(Some(Box::new(|msg_id, client_id| {
29 let mut speaking = SPEAKING.lock().unwrap();
30 speaking.insert(client_id, true);
31 let mut callbacks = CALLBACKS.lock().unwrap();
32 let backend_id = BackendId::SpeechDispatcher(client_id);
33 let cb = callbacks.get_mut(&backend_id).unwrap();
34 let utterance_id = UtteranceId::SpeechDispatcher(msg_id as u64);
35 if let Some(f) = cb.utterance_begin.as_mut() {
36 f(utterance_id);
37 }
38 })));
39 sd.0.on_end(Some(Box::new(|msg_id, client_id| {
40 let mut speaking = SPEAKING.lock().unwrap();
41 speaking.insert(client_id, false);
42 let mut callbacks = CALLBACKS.lock().unwrap();
43 let backend_id = BackendId::SpeechDispatcher(client_id);
44 let cb = callbacks.get_mut(&backend_id).unwrap();
45 let utterance_id = UtteranceId::SpeechDispatcher(msg_id as u64);
46 if let Some(f) = cb.utterance_end.as_mut() {
47 f(utterance_id);
48 }
49 })));
50 sd.0.on_cancel(Some(Box::new(|msg_id, client_id| {
51 let mut speaking = SPEAKING.lock().unwrap();
52 speaking.insert(client_id, false);
53 let mut callbacks = CALLBACKS.lock().unwrap();
54 let backend_id = BackendId::SpeechDispatcher(client_id);
55 let cb = callbacks.get_mut(&backend_id).unwrap();
56 let utterance_id = UtteranceId::SpeechDispatcher(msg_id as u64);
57 if let Some(f) = cb.utterance_stop.as_mut() {
58 f(utterance_id);
59 }
60 })));
61 sd.0.on_pause(Some(Box::new(|_msg_id, client_id| {
62 let mut speaking = SPEAKING.lock().unwrap();
63 speaking.insert(client_id, false);
64 })));
65 sd.0.on_resume(Some(Box::new(|_msg_id, client_id| {
66 let mut speaking = SPEAKING.lock().unwrap();
67 speaking.insert(client_id, true);
68 })));
69 Ok(sd)
70 }
71}
72
73impl Backend for SpeechDispatcher {
74 fn id(&self) -> Option<BackendId> {
75 Some(BackendId::SpeechDispatcher(self.0.client_id()))
76 }
77
78 fn supported_features(&self) -> Features {
79 Features {
80 stop: true,
81 rate: true,
82 pitch: true,
83 volume: true,
84 is_speaking: true,
85 voice: true,
86 get_voice: false,
87 utterance_callbacks: true,
88 }
89 }
90
91 fn speak(&mut self, text: &str, interrupt: bool) -> Result<Option<UtteranceId>, Error> {
92 trace!("speak({}, {})", text, interrupt);
93 if interrupt {
94 self.stop()?;
95 }
96 let single_char = text.to_string().capacity() == 1;
97 if single_char {
98 self.0.set_punctuation(Punctuation::All)?;
99 }
100 let id = self.0.say(Priority::Important, text);
101 if single_char {
102 self.0.set_punctuation(Punctuation::None)?;
103 }
104 if let Some(id) = id {
105 Ok(Some(UtteranceId::SpeechDispatcher(id)))
106 } else {
107 Err(Error::NoneError)
108 }
109 }
110
111 fn stop(&mut self) -> Result<(), Error> {
112 trace!("stop()");
113 self.0.cancel()?;
114 Ok(())
115 }
116
117 fn min_rate(&self) -> f32 {
118 -100.
119 }
120
121 fn max_rate(&self) -> f32 {
122 100.
123 }
124
125 fn normal_rate(&self) -> f32 {
126 0.
127 }
128
129 fn get_rate(&self) -> Result<f32, Error> {
130 Ok(self.0.get_voice_rate() as f32)
131 }
132
133 fn set_rate(&mut self, rate: f32) -> Result<(), Error> {
134 self.0.set_voice_rate(rate as i32)?;
135 Ok(())
136 }
137
138 fn min_pitch(&self) -> f32 {
139 -100.
140 }
141
142 fn max_pitch(&self) -> f32 {
143 100.
144 }
145
146 fn normal_pitch(&self) -> f32 {
147 0.
148 }
149
150 fn get_pitch(&self) -> Result<f32, Error> {
151 Ok(self.0.get_voice_pitch() as f32)
152 }
153
154 fn set_pitch(&mut self, pitch: f32) -> Result<(), Error> {
155 self.0.set_voice_pitch(pitch as i32)?;
156 Ok(())
157 }
158
159 fn min_volume(&self) -> f32 {
160 -100.
161 }
162
163 fn max_volume(&self) -> f32 {
164 100.
165 }
166
167 fn normal_volume(&self) -> f32 {
168 100.
169 }
170
171 fn get_volume(&self) -> Result<f32, Error> {
172 Ok(self.0.get_volume() as f32)
173 }
174
175 fn set_volume(&mut self, volume: f32) -> Result<(), Error> {
176 self.0.set_volume(volume as i32)?;
177 Ok(())
178 }
179
180 fn is_speaking(&self) -> Result<bool, Error> {
181 let speaking = SPEAKING.lock().unwrap();
182 let is_speaking = speaking.get(&self.0.client_id()).unwrap();
183 Ok(*is_speaking)
184 }
185
186 fn voices(&self) -> Result<Vec<Voice>, Error> {
187 let rv = self
188 .0
189 .list_synthesis_voices()?
190 .iter()
191 .filter(|v| LanguageTag::parse(v.language.clone()).is_ok())
192 .map(|v| Voice {
193 id: v.name.clone(),
194 name: v.name.clone(),
195 gender: None,
196 language: LanguageTag::parse(v.language.clone()).unwrap(),
197 })
198 .collect::<Vec<Voice>>();
199 Ok(rv)
200 }
201
202 fn voice(&self) -> Result<Option<Voice>, Error> {
203 unimplemented!()
204 }
205
206 fn set_voice(&mut self, voice: &Voice) -> Result<(), Error> {
207 for v in self.0.list_synthesis_voices()? {
208 if v.name == voice.name {
209 self.0.set_synthesis_voice(&v)?;
210 return Ok(());
211 }
212 }
213 Err(Error::OperationFailed)
214 }
215}
216
217impl Drop for SpeechDispatcher {
218 fn drop(&mut self) {
219 let mut speaking = SPEAKING.lock().unwrap();
220 speaking.remove(&self.0.client_id());
221 }
222}