2018-12-14 19:35:49 +00:00
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
use std::u8;
|
|
|
|
|
|
|
|
use log::{info, trace};
|
|
|
|
use speech_dispatcher::*;
|
|
|
|
|
2019-03-24 21:30:45 +00:00
|
|
|
use crate::{Backend, Error, Features};
|
2018-12-14 19:35:49 +00:00
|
|
|
|
|
|
|
pub struct SpeechDispatcher(Connection);
|
|
|
|
|
|
|
|
impl SpeechDispatcher {
|
|
|
|
pub fn new() -> impl Backend {
|
|
|
|
info!("Initializing SpeechDispatcher backend");
|
|
|
|
let connection = speech_dispatcher::Connection::open("tts", "tts", "tts", Mode::Single);
|
|
|
|
SpeechDispatcher(connection)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-15 15:56:13 +00:00
|
|
|
fn u8_to_i32(v: u8) -> i32 {
|
2019-01-03 16:16:54 +00:00
|
|
|
let ratio: f32 = v as f32 / u8::MAX as f32;
|
2018-12-15 15:56:13 +00:00
|
|
|
(ratio * 200. - 100.) as i32
|
|
|
|
}
|
|
|
|
|
|
|
|
fn i32_to_u8(v: i32) -> u8 {
|
|
|
|
let v = v as f32;
|
|
|
|
let ratio: f32 = (v + 100.) / 200.;
|
|
|
|
let v = ratio * u8::MAX as f32;
|
|
|
|
v as u8
|
|
|
|
}
|
|
|
|
|
2018-12-14 19:35:49 +00:00
|
|
|
impl Backend for SpeechDispatcher {
|
2019-03-24 21:30:45 +00:00
|
|
|
fn supported_features(&self) -> Features {
|
|
|
|
Features {
|
|
|
|
stop: true,
|
|
|
|
rate: true,
|
|
|
|
pitch: true,
|
|
|
|
volume: true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-30 17:13:48 +00:00
|
|
|
fn speak(&self, text: &str, interrupt: bool) -> Result<(), Error> {
|
2018-12-14 19:35:49 +00:00
|
|
|
trace!("speak({}, {})", text, interrupt);
|
|
|
|
if interrupt {
|
2018-12-30 17:13:48 +00:00
|
|
|
self.stop()?;
|
2018-12-14 19:35:49 +00:00
|
|
|
}
|
2019-09-30 15:36:51 +00:00
|
|
|
let single_char = text.to_string().capacity() == 1;
|
|
|
|
if single_char {
|
|
|
|
self.0.set_punctuation(Punctuation::All);
|
|
|
|
}
|
2018-12-14 19:35:49 +00:00
|
|
|
self.0.say(Priority::Important, text);
|
2019-09-30 15:36:51 +00:00
|
|
|
if single_char {
|
|
|
|
self.0.set_punctuation(Punctuation::None);
|
|
|
|
}
|
2018-12-30 17:13:48 +00:00
|
|
|
Ok(())
|
2018-12-14 19:35:49 +00:00
|
|
|
}
|
|
|
|
|
2018-12-30 17:13:48 +00:00
|
|
|
fn stop(&self) -> Result<(), Error> {
|
2018-12-28 14:49:02 +00:00
|
|
|
trace!("stop()");
|
|
|
|
self.0.cancel();
|
2018-12-30 17:13:48 +00:00
|
|
|
Ok(())
|
2018-12-28 14:49:02 +00:00
|
|
|
}
|
|
|
|
|
2018-12-30 17:13:48 +00:00
|
|
|
fn get_rate(&self) -> Result<u8, Error> {
|
|
|
|
Ok(i32_to_u8(self.0.get_voice_rate()))
|
2018-12-14 19:35:49 +00:00
|
|
|
}
|
|
|
|
|
2018-12-30 17:13:48 +00:00
|
|
|
fn set_rate(&mut self, rate: u8) -> Result<(), Error> {
|
2018-12-15 15:56:13 +00:00
|
|
|
self.0.set_voice_rate(u8_to_i32(rate));
|
2018-12-30 17:13:48 +00:00
|
|
|
Ok(())
|
2018-12-15 15:56:13 +00:00
|
|
|
}
|
|
|
|
|
2018-12-30 17:13:48 +00:00
|
|
|
fn get_pitch(&self) -> Result<u8, Error> {
|
|
|
|
Ok(i32_to_u8(self.0.get_voice_pitch()))
|
2018-12-15 15:56:13 +00:00
|
|
|
}
|
|
|
|
|
2018-12-30 17:13:48 +00:00
|
|
|
fn set_pitch(&mut self, pitch: u8) -> Result<(), Error> {
|
2018-12-15 15:56:13 +00:00
|
|
|
self.0.set_voice_pitch(u8_to_i32(pitch));
|
2018-12-30 17:13:48 +00:00
|
|
|
Ok(())
|
2018-12-15 15:56:13 +00:00
|
|
|
}
|
|
|
|
|
2018-12-30 17:13:48 +00:00
|
|
|
fn get_volume(&self) -> Result<u8, Error> {
|
|
|
|
Ok(i32_to_u8(self.0.get_volume()))
|
2018-12-15 15:56:13 +00:00
|
|
|
}
|
|
|
|
|
2018-12-30 17:13:48 +00:00
|
|
|
fn set_volume(&mut self, volume: u8) -> Result<(), Error> {
|
2018-12-15 15:56:13 +00:00
|
|
|
self.0.set_volume(u8_to_i32(volume));
|
2018-12-30 17:13:48 +00:00
|
|
|
Ok(())
|
2018-12-14 19:35:49 +00:00
|
|
|
}
|
|
|
|
}
|