tts/backends/
speech_dispatcher.rs

1#[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}