mirror of https://github.com/ndarilek/tts-rs.git
Make speak calls return an utterance ID, where possible.
This commit is contained in:
parent
d6508edd12
commit
4816ec575c
|
@ -6,7 +6,7 @@ use lazy_static::*;
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
use speech_dispatcher::*;
|
use speech_dispatcher::*;
|
||||||
|
|
||||||
use crate::{Backend, Error, Features};
|
use crate::{Backend, Error, Features, UtteranceId};
|
||||||
|
|
||||||
pub struct SpeechDispatcher(Connection);
|
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);
|
trace!("speak({}, {})", text, interrupt);
|
||||||
if interrupt {
|
if interrupt {
|
||||||
self.stop()?;
|
self.stop()?;
|
||||||
|
@ -68,11 +68,15 @@ impl Backend for SpeechDispatcher {
|
||||||
if single_char {
|
if single_char {
|
||||||
self.0.set_punctuation(Punctuation::All);
|
self.0.set_punctuation(Punctuation::All);
|
||||||
}
|
}
|
||||||
self.0.say(Priority::Important, text);
|
let id = self.0.say(Priority::Important, text);
|
||||||
if single_char {
|
if single_char {
|
||||||
self.0.set_punctuation(Punctuation::None);
|
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> {
|
fn stop(&mut self) -> Result<(), Error> {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
use tolk::Tolk as TolkPtr;
|
use tolk::Tolk as TolkPtr;
|
||||||
|
|
||||||
use crate::{Backend, Error, Features};
|
use crate::{Backend, Error, Features, UtteranceId};
|
||||||
|
|
||||||
pub struct Tolk(TolkPtr);
|
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);
|
trace!("speak({}, {})", text, interrupt);
|
||||||
self.0.speak(text, interrupt);
|
self.0.speak(text, interrupt);
|
||||||
Ok(())
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn stop(&mut self) -> Result<(), Error> {
|
fn stop(&mut self) -> Result<(), Error> {
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
use web_sys::SpeechSynthesisUtterance;
|
use web_sys::SpeechSynthesisUtterance;
|
||||||
|
|
||||||
use crate::{Backend, Error, Features};
|
use crate::{Backend, Error, Features, UtteranceId};
|
||||||
|
|
||||||
pub struct Web {
|
pub struct Web {
|
||||||
rate: f32,
|
rate: f32,
|
||||||
|
@ -10,6 +13,10 @@ pub struct Web {
|
||||||
volume: f32,
|
volume: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref NEXT_UTTERANCE_ID: Mutex<u64> = Mutex::new(0);
|
||||||
|
}
|
||||||
|
|
||||||
impl Web {
|
impl Web {
|
||||||
pub fn new() -> Result<Self, Error> {
|
pub fn new() -> Result<Self, Error> {
|
||||||
info!("Initializing Web backend");
|
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);
|
trace!("speak({}, {})", text, interrupt);
|
||||||
let utterance = SpeechSynthesisUtterance::new_with_text(text).unwrap();
|
let utterance = SpeechSynthesisUtterance::new_with_text(text).unwrap();
|
||||||
utterance.set_rate(self.rate);
|
utterance.set_rate(self.rate);
|
||||||
|
@ -44,8 +51,12 @@ impl Backend for Web {
|
||||||
if let Some(window) = web_sys::window() {
|
if let Some(window) = web_sys::window() {
|
||||||
let speech_synthesis = window.speech_synthesis().unwrap();
|
let speech_synthesis = window.speech_synthesis().unwrap();
|
||||||
speech_synthesis.speak(&utterance);
|
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> {
|
fn stop(&mut self) -> Result<(), Error> {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use lazy_static::lazy_static;
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
|
|
||||||
use tts_winrt_bindings::windows::media::core::MediaSource;
|
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 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 {
|
impl From<winrt::Error> for Error {
|
||||||
fn from(e: winrt::Error) -> Self {
|
fn from(e: winrt::Error) -> Self {
|
||||||
|
@ -21,6 +24,10 @@ pub struct WinRT {
|
||||||
playback_list: MediaPlaybackList,
|
playback_list: MediaPlaybackList,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref NEXT_UTTERANCE_ID: Mutex<u64> = Mutex::new(0);
|
||||||
|
}
|
||||||
|
|
||||||
impl WinRT {
|
impl WinRT {
|
||||||
pub fn new() -> std::result::Result<Self, Error> {
|
pub fn new() -> std::result::Result<Self, Error> {
|
||||||
info!("Initializing WinRT backend");
|
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);
|
trace!("speak({}, {})", text, interrupt);
|
||||||
if interrupt {
|
if interrupt {
|
||||||
self.stop()?;
|
self.stop()?;
|
||||||
|
@ -76,7 +87,9 @@ impl Backend for WinRT {
|
||||||
if !self.is_speaking()? {
|
if !self.is_speaking()? {
|
||||||
self.player.play()?;
|
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> {
|
fn stop(&mut self) -> std::result::Result<(), Error> {
|
||||||
|
|
21
src/lib.rs
21
src/lib.rs
|
@ -40,6 +40,16 @@ pub enum Backends {
|
||||||
AvFoundation,
|
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 struct Features {
|
||||||
pub stop: bool,
|
pub stop: bool,
|
||||||
pub rate: bool,
|
pub rate: bool,
|
||||||
|
@ -80,7 +90,7 @@ pub enum Error {
|
||||||
|
|
||||||
pub trait Backend {
|
pub trait Backend {
|
||||||
fn supported_features(&self) -> Features;
|
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 stop(&mut self) -> Result<(), Error>;
|
||||||
fn min_rate(&self) -> f32;
|
fn min_rate(&self) -> f32;
|
||||||
fn max_rate(&self) -> f32;
|
fn max_rate(&self) -> f32;
|
||||||
|
@ -184,9 +194,12 @@ impl TTS {
|
||||||
/**
|
/**
|
||||||
* Speaks the specified text, optionally interrupting current speech.
|
* Speaks the specified text, optionally interrupting current speech.
|
||||||
*/
|
*/
|
||||||
pub fn speak<S: Into<String>>(&mut self, text: S, interrupt: bool) -> Result<&Self, Error> {
|
pub fn speak<S: Into<String>>(
|
||||||
self.0.speak(text.into().as_str(), interrupt)?;
|
&mut self,
|
||||||
Ok(self)
|
text: S,
|
||||||
|
interrupt: bool,
|
||||||
|
) -> Result<Option<UtteranceId>, Error> {
|
||||||
|
self.0.speak(text.into().as_str(), interrupt)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue