From bac4b7555fb76f5cd6950f5c1776848c53e7bcaf Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 14 Dec 2018 19:35:49 +0000 Subject: [PATCH] Initial commit. --- Cargo.toml | 14 ++++++++++ examples/hello_world.rs | 15 ++++++++++ src/backends/mod.rs | 5 ++++ src/backends/speech_dispatcher.rs | 45 ++++++++++++++++++++++++++++++ src/lib.rs | 46 +++++++++++++++++++++++++++++++ 5 files changed, 125 insertions(+) create mode 100644 Cargo.toml create mode 100644 examples/hello_world.rs create mode 100644 src/backends/mod.rs create mode 100644 src/backends/speech_dispatcher.rs create mode 100644 src/lib.rs diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..12cd376 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "tts" +version = "0.1.0" +authors = ["Nolan Darilek "] +edition = "2018" + +[dependencies] +log = "0.4" + +[dev-dependencies] +env_logger = "0.6" + +[target.'cfg(target_os = "linux")'.dependencies] +speech-dispatcher = "0.2" diff --git a/examples/hello_world.rs b/examples/hello_world.rs new file mode 100644 index 0000000..d09bbdb --- /dev/null +++ b/examples/hello_world.rs @@ -0,0 +1,15 @@ +use tts::TTS; + +fn main() { + env_logger::init(); + let tts: TTS = Default::default(); + tts.speak("Hello, world.", false); + let original_rate = tts.get_rate(); + tts.speak(format!("Current rate: {}", original_rate), false); + tts.set_rate(std::u8::MAX); + tts.speak("This is very fast.", false); + tts.set_rate(0); + tts.speak("This is very slow.", false); + tts.set_rate(original_rate); + tts.speak("Goodbye.", false); +} diff --git a/src/backends/mod.rs b/src/backends/mod.rs new file mode 100644 index 0000000..6500e27 --- /dev/null +++ b/src/backends/mod.rs @@ -0,0 +1,5 @@ +#[cfg(target_os = "linux")] +mod speech_dispatcher; + +#[cfg(target_os = "linux")] +pub use self::speech_dispatcher::*; diff --git a/src/backends/speech_dispatcher.rs b/src/backends/speech_dispatcher.rs new file mode 100644 index 0000000..1e667e6 --- /dev/null +++ b/src/backends/speech_dispatcher.rs @@ -0,0 +1,45 @@ +#[cfg(target_os = "linux")] + +use std::u8; + +use log::{info, trace}; +use speech_dispatcher::*; + +use crate::Backend; + +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) + } +} + +impl Backend for SpeechDispatcher { + fn speak(&self, text: &str, interrupt: bool) { + trace!("speak({}, {})", text, interrupt); + if interrupt { + self.0.cancel(); + } + self.0.say(Priority::Important, text); + } + + fn get_rate(&self) -> u8 { + let rate = self.0.get_voice_rate() as f32; + trace!("get_voice_rate() = {}", rate); + let ratio: f32 = (rate + 100.) / 200.; + trace!("ratio = {}", ratio); + let rate = ratio * u8::MAX as f32; + trace!("rate = {}", rate); + rate as u8 + } + + fn set_rate(&self, rate: u8) { + trace!("set_rate({})", rate); + let ratio: f32 = rate as f32/u8::MAX as f32; + let rate = ratio * 200. - 100.; + self.0.set_voice_rate(rate as i32); + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..302be6e --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,46 @@ +use std::boxed::Box; + +mod backends; + +pub enum Backends { + #[cfg(target_os = "linux")] + SpeechDispatcher, +} + +trait Backend { + fn speak(&self, text: &str, interrupt: bool); + fn get_rate(&self) -> u8; + fn set_rate(&self, rate: u8); +} + +pub struct TTS(Box); + +impl TTS { + pub fn new(backend: Backends) -> TTS { + match backend { + #[cfg(target_os = "linux")] + Backends::SpeechDispatcher => TTS(Box::new(backends::SpeechDispatcher::new())), + } + } + + pub fn speak>(&self, text: S, interrupt: bool) -> &Self { + self.0.speak(text.into().as_str(), interrupt); + self + } + + pub fn get_rate(&self) -> u8 { + self.0.get_rate() + } + + pub fn set_rate(&self, rate: u8) -> &Self { + self.0.set_rate(rate); + self + } +} + +impl Default for TTS { + fn default() -> TTS { + #[cfg(target_os = "linux")] + TTS::new(Backends::SpeechDispatcher) + } +}