diff --git a/Cargo.toml b/Cargo.toml index cf649b6..9bce264 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.7.0" +version = "0.8.0" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface" @@ -25,7 +25,7 @@ winrt = "0.7" tts_winrt_bindings = { version = "0.1", path="winrt_bindings" } [target.'cfg(target_os = "linux")'.dependencies] -speech-dispatcher = "0.6" +speech-dispatcher = "0.7" [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] cocoa-foundation = "0.1" diff --git a/examples/hello_world.rs b/examples/hello_world.rs index 4d7accd..d21fe9d 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -17,12 +17,12 @@ fn main() -> Result<(), Error> { .. } = tts.supported_features(); if utterance_callbacks { - tts.on_utterance_begin(Some(|utterance| { + tts.on_utterance_begin(Some(Box::new(|utterance| { println!("Started speaking {:?}", utterance) - }))?; - tts.on_utterance_end(Some(|utterance| { + })))?; + tts.on_utterance_end(Some(Box::new(|utterance| { println!("Finished speaking {:?}", utterance) - }))?; + })))?; } tts.speak("Hello, world.", false)?; let Features { rate, .. } = tts.supported_features(); diff --git a/src/backends/speech_dispatcher.rs b/src/backends/speech_dispatcher.rs index 2b9d6b5..8ad6020 100644 --- a/src/backends/speech_dispatcher.rs +++ b/src/backends/speech_dispatcher.rs @@ -28,22 +28,22 @@ impl SpeechDispatcher { sd.0.on_begin(Some(|msg_id, client_id| { let mut speaking = SPEAKING.lock().unwrap(); speaking.insert(client_id, true); - let callbacks = CALLBACKS.lock().unwrap(); + let mut callbacks = CALLBACKS.lock().unwrap(); let backend_id = BackendId::SpeechDispatcher(client_id); - let cb = callbacks.get(&backend_id).unwrap(); + let cb = callbacks.get_mut(&backend_id).unwrap(); let utterance_id = UtteranceId::SpeechDispatcher(msg_id); - if let Some(f) = cb.utterance_begin { + if let Some(f) = cb.utterance_begin.as_mut() { f(utterance_id); } })); sd.0.on_end(Some(|msg_id, client_id| { let mut speaking = SPEAKING.lock().unwrap(); speaking.insert(client_id, false); - let callbacks = CALLBACKS.lock().unwrap(); + let mut callbacks = CALLBACKS.lock().unwrap(); let backend_id = BackendId::SpeechDispatcher(client_id); - let cb = callbacks.get(&backend_id).unwrap(); + let cb = callbacks.get_mut(&backend_id).unwrap(); let utterance_id = UtteranceId::SpeechDispatcher(msg_id); - if let Some(f) = cb.utterance_end { + if let Some(f) = cb.utterance_end.as_mut() { f(utterance_id); } })); diff --git a/src/backends/web.rs b/src/backends/web.rs index 619a350..32be8f7 100644 --- a/src/backends/web.rs +++ b/src/backends/web.rs @@ -60,18 +60,18 @@ impl Backend for Web { let id = self.id().unwrap(); let utterance_id = UtteranceId::Web(utterance.clone()); let callback = Closure::wrap(Box::new(move |evt: SpeechSynthesisEvent| { - let callbacks = CALLBACKS.lock().unwrap(); - let callback = callbacks.get(&id).unwrap(); - if let Some(f) = callback.utterance_begin { + let mut callbacks = CALLBACKS.lock().unwrap(); + let callback = callbacks.get_mut(&id).unwrap(); + if let Some(f) = callback.utterance_begin.as_mut() { let utterance_id = UtteranceId::Web(evt.utterance()); f(utterance_id); } }) as Box); utterance.set_onstart(Some(callback.as_ref().unchecked_ref())); let callback = Closure::wrap(Box::new(move |evt: SpeechSynthesisEvent| { - let callbacks = CALLBACKS.lock().unwrap(); - let callback = callbacks.get(&id).unwrap(); - if let Some(f) = callback.utterance_end { + let mut callbacks = CALLBACKS.lock().unwrap(); + let callback = callbacks.get_mut(&id).unwrap(); + if let Some(f) = callback.utterance_end.as_mut() { let utterance_id = UtteranceId::Web(evt.utterance()); f(utterance_id); } diff --git a/src/backends/winrt.rs b/src/backends/winrt.rs index 815607a..1625040 100644 --- a/src/backends/winrt.rs +++ b/src/backends/winrt.rs @@ -83,9 +83,9 @@ impl WinRT { let id = backend_to_media_player.iter().find(|v| v.1 == sender); if let Some(id) = id { let id = id.0; - let callbacks = CALLBACKS.lock().unwrap(); - let callbacks = callbacks.get(&id).unwrap(); - if let Some(callback) = callbacks.utterance_end { + let mut callbacks = CALLBACKS.lock().unwrap(); + let callbacks = callbacks.get_mut(&id).unwrap(); + if let Some(callback) = callbacks.utterance_end.as_mut() { let last_spoken_utterance = LAST_SPOKEN_UTTERANCE.lock().unwrap(); if let Some(utterance_id) = last_spoken_utterance.get(&id) { callback(utterance_id.clone()); @@ -103,20 +103,20 @@ impl WinRT { let id = backend_to_playback_list.iter().find(|v| v.1 == sender); if let Some(id) = id { let id = id.0; - let callbacks = CALLBACKS.lock().unwrap(); - let callbacks = callbacks.get(&id).unwrap(); + let mut callbacks = CALLBACKS.lock().unwrap(); + let callbacks = callbacks.get_mut(&id).unwrap(); let old_item = args.old_item()?; if !old_item.is_null() { - if let Some(callback) = callbacks.utterance_end { + if let Some(callback) = callbacks.utterance_end.as_mut() { callback(UtteranceId::WinRT(old_item)); } } let new_item = args.new_item()?; if !new_item.is_null() { - let utterance_id = UtteranceId::WinRT(new_item); let mut last_spoken_utterance = LAST_SPOKEN_UTTERANCE.lock().unwrap(); + let utterance_id = UtteranceId::WinRT(new_item); last_spoken_utterance.insert(*id, utterance_id.clone()); - if let Some(callback) = callbacks.utterance_begin { + if let Some(callback) = callbacks.utterance_begin.as_mut() { callback(utterance_id); } } diff --git a/src/lib.rs b/src/lib.rs index 5560ed1..853a69c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -137,10 +137,14 @@ pub trait Backend { #[derive(Default)] struct Callbacks { - utterance_begin: Option, - utterance_end: Option, + utterance_begin: Option>, + utterance_end: Option>, } +unsafe impl Send for Callbacks {} + +unsafe impl Sync for Callbacks {} + lazy_static! { static ref CALLBACKS: Mutex> = { let m: HashMap = HashMap::new(); @@ -436,7 +440,10 @@ impl TTS { /** * Called when this speech synthesizer begins speaking an utterance. */ - pub fn on_utterance_begin(&self, callback: Option) -> Result<(), Error> { + pub fn on_utterance_begin( + &self, + callback: Option>, + ) -> Result<(), Error> { let Features { utterance_callbacks, .. @@ -455,7 +462,10 @@ impl TTS { /** * Called when this speech synthesizer finishes speaking an utterance. */ - pub fn on_utterance_end(&self, callback: Option) -> Result<(), Error> { + pub fn on_utterance_end( + &self, + callback: Option>, + ) -> Result<(), Error> { let Features { utterance_callbacks, ..