1
0
mirror of https://github.com/ndarilek/tts-rs.git synced 2024-11-17 11:29:37 +00:00

Make speak calls return an utterance ID, where possible.

This commit is contained in:
Nolan Darilek 2020-09-22 12:40:03 -05:00
parent d6508edd12
commit 4816ec575c
5 changed files with 58 additions and 17 deletions

View File

@ -6,7 +6,7 @@ use lazy_static::*;
use log::{info, trace};
use speech_dispatcher::*;
use crate::{Backend, Error, Features};
use crate::{Backend, Error, Features, UtteranceId};
pub struct SpeechDispatcher(Connection);
@ -59,7 +59,7 @@ impl Backend for SpeechDispatcher {
}
}
fn speak(&mut self, text: &str, interrupt: bool) -> Result<(), Error> {
fn speak(&mut self, text: &str, interrupt: bool) -> Result<Option<UtteranceId>, Error> {
trace!("speak({}, {})", text, interrupt);
if interrupt {
self.stop()?;
@ -68,11 +68,15 @@ impl Backend for SpeechDispatcher {
if single_char {
self.0.set_punctuation(Punctuation::All);
}
self.0.say(Priority::Important, text);
let id = self.0.say(Priority::Important, text);
if single_char {
self.0.set_punctuation(Punctuation::None);
}
Ok(())
if let Some(id) = id {
Ok(Some(UtteranceId::SpeechDispatcher(id)))
} else {
Err(Error::NoneError)
}
}
fn stop(&mut self) -> Result<(), Error> {

View File

@ -2,7 +2,7 @@
use log::{info, trace};
use tolk::Tolk as TolkPtr;
use crate::{Backend, Error, Features};
use crate::{Backend, Error, Features, UtteranceId};
pub struct Tolk(TolkPtr);
@ -26,10 +26,10 @@ impl Backend for Tolk {
}
}
fn speak(&mut self, text: &str, interrupt: bool) -> Result<(), Error> {
fn speak(&mut self, text: &str, interrupt: bool) -> Result<Option<UtteranceId>, Error> {
trace!("speak({}, {})", text, interrupt);
self.0.speak(text, interrupt);
Ok(())
Ok(None)
}
fn stop(&mut self) -> Result<(), Error> {

View File

@ -1,8 +1,11 @@
#[cfg(target_arch = "wasm32")]
use std::sync::Mutex;
use lazy_static::lazy_static;
use log::{info, trace};
use web_sys::SpeechSynthesisUtterance;
use crate::{Backend, Error, Features};
use crate::{Backend, Error, Features, UtteranceId};
pub struct Web {
rate: f32,
@ -10,6 +13,10 @@ pub struct Web {
volume: f32,
}
lazy_static! {
static ref NEXT_UTTERANCE_ID: Mutex<u64> = Mutex::new(0);
}
impl Web {
pub fn new() -> Result<Self, Error> {
info!("Initializing Web backend");
@ -32,7 +39,7 @@ impl Backend for Web {
}
}
fn speak(&mut self, text: &str, interrupt: bool) -> Result<(), Error> {
fn speak(&mut self, text: &str, interrupt: bool) -> Result<Option<UtteranceId>, Error> {
trace!("speak({}, {})", text, interrupt);
let utterance = SpeechSynthesisUtterance::new_with_text(text).unwrap();
utterance.set_rate(self.rate);
@ -44,8 +51,12 @@ impl Backend for Web {
if let Some(window) = web_sys::window() {
let speech_synthesis = window.speech_synthesis().unwrap();
speech_synthesis.speak(&utterance);
let mut utterance_id = NEXT_UTTERANCE_ID.lock().unwrap();
*utterance_id += 1;
Ok(Some(UtteranceId::Web(*utterance_id)))
} else {
Err(Error::NoneError)
}
Ok(())
}
fn stop(&mut self) -> Result<(), Error> {

View File

@ -1,4 +1,7 @@
#[cfg(windows)]
use std::sync::Mutex;
use lazy_static::lazy_static;
use log::{info, trace};
use tts_winrt_bindings::windows::media::core::MediaSource;
@ -7,7 +10,7 @@ use tts_winrt_bindings::windows::media::playback::{
};
use tts_winrt_bindings::windows::media::speech_synthesis::SpeechSynthesizer;
use crate::{Backend, Error, Features};
use crate::{Backend, Error, Features, UtteranceId};
impl From<winrt::Error> for Error {
fn from(e: winrt::Error) -> Self {
@ -21,6 +24,10 @@ pub struct WinRT {
playback_list: MediaPlaybackList,
}
lazy_static! {
static ref NEXT_UTTERANCE_ID: Mutex<u64> = Mutex::new(0);
}
impl WinRT {
pub fn new() -> std::result::Result<Self, Error> {
info!("Initializing WinRT backend");
@ -55,7 +62,11 @@ impl Backend for WinRT {
}
}
fn speak(&mut self, text: &str, interrupt: bool) -> std::result::Result<(), Error> {
fn speak(
&mut self,
text: &str,
interrupt: bool,
) -> std::result::Result<Option<UtteranceId>, Error> {
trace!("speak({}, {})", text, interrupt);
if interrupt {
self.stop()?;
@ -76,7 +87,9 @@ impl Backend for WinRT {
if !self.is_speaking()? {
self.player.play()?;
}
Ok(())
let mut utterance_id = NEXT_UTTERANCE_ID.lock().unwrap();
*utterance_id += 1;
Ok(Some(UtteranceId::WinRT(*utterance_id)))
}
fn stop(&mut self) -> std::result::Result<(), Error> {

View File

@ -40,6 +40,16 @@ pub enum Backends {
AvFoundation,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum UtteranceId {
#[cfg(target_os = "linux")]
SpeechDispatcher(i32),
#[cfg(target_arch = "wasm32")]
Web(u64),
#[cfg(windows)]
WinRT(u64),
}
pub struct Features {
pub stop: bool,
pub rate: bool,
@ -80,7 +90,7 @@ pub enum Error {
pub trait Backend {
fn supported_features(&self) -> Features;
fn speak(&mut self, text: &str, interrupt: bool) -> Result<(), Error>;
fn speak(&mut self, text: &str, interrupt: bool) -> Result<Option<UtteranceId>, Error>;
fn stop(&mut self) -> Result<(), Error>;
fn min_rate(&self) -> f32;
fn max_rate(&self) -> f32;
@ -184,9 +194,12 @@ impl TTS {
/**
* Speaks the specified text, optionally interrupting current speech.
*/
pub fn speak<S: Into<String>>(&mut self, text: S, interrupt: bool) -> Result<&Self, Error> {
self.0.speak(text.into().as_str(), interrupt)?;
Ok(self)
pub fn speak<S: Into<String>>(
&mut self,
text: S,
interrupt: bool,
) -> Result<Option<UtteranceId>, Error> {
self.0.speak(text.into().as_str(), interrupt)
}
/**