From d9ca83ca15ccf5ecd598e5995a6cfa8750bceda6 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 12:33:31 -0600 Subject: [PATCH 01/49] WIP: Bump dependencies. Currently broken. --- Cargo.toml | 6 +++--- winrt_bindings/Cargo.toml | 4 ++-- winrt_bindings/build.rs | 7 ++++--- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 258aa5f..8325028 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ env_logger = "0.8" [target.'cfg(windows)'.dependencies] tolk = { version = "0.3", optional = true } -windows = "0.2" +windows = "0.4" tts_winrt_bindings = { version = "0.3", path="winrt_bindings" } [target.'cfg(target_os = "linux")'.dependencies] @@ -38,5 +38,5 @@ wasm-bindgen = "0.2" web-sys = { version = "0.3", features = ["EventTarget", "SpeechSynthesis", "SpeechSynthesisErrorCode", "SpeechSynthesisErrorEvent", "SpeechSynthesisEvent", "SpeechSynthesisUtterance", "Window", ] } [target.'cfg(target_os="android")'.dependencies] -jni = "0.18" -ndk-glue = "0.2" \ No newline at end of file +jni = "0.19" +ndk-glue = "0.3" \ No newline at end of file diff --git a/winrt_bindings/Cargo.toml b/winrt_bindings/Cargo.toml index eaf4bb2..da14f55 100644 --- a/winrt_bindings/Cargo.toml +++ b/winrt_bindings/Cargo.toml @@ -7,7 +7,7 @@ license = "MIT" edition = "2018" [dependencies] -windows = "0.2" +windows = "0.4" [build-dependencies] -windows = "0.2" +windows = "0.4" diff --git a/winrt_bindings/build.rs b/winrt_bindings/build.rs index 654291a..6a4341e 100644 --- a/winrt_bindings/build.rs +++ b/winrt_bindings/build.rs @@ -1,7 +1,8 @@ fn main() { windows::build!( - windows::media::core::MediaSource - windows::media::playback::{MediaPlaybackState, MediaPlayer} - windows::media::speech_synthesis::SpeechSynthesizer + windows::foundation::TypedEventHandler, + windows::media::core::MediaSource, + windows::media::playback::{MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, + windows::media::speech_synthesis::SpeechSynthesizer, ); } From 00a16c5dd5167aac353e991ec4264ade936d5189 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 12:54:50 -0600 Subject: [PATCH 02/49] Add missing types. --- winrt_bindings/build.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/winrt_bindings/build.rs b/winrt_bindings/build.rs index 6a4341e..3080588 100644 --- a/winrt_bindings/build.rs +++ b/winrt_bindings/build.rs @@ -1,8 +1,9 @@ fn main() { windows::build!( - windows::foundation::TypedEventHandler, + windows::foundation::{EventRegistrationToken, IAsyncOperation, TypedEventHandler}, windows::media::core::MediaSource, - windows::media::playback::{MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, - windows::media::speech_synthesis::SpeechSynthesizer, + windows::media::playback::{MediaPlaybackSession, MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, + windows::media::speech_synthesis::{SpeechSynthesisStream, SpeechSynthesizer, SpeechSynthesizerOptions}, + windows::storage::streams::IRandomAccessStream, ); } From c21d4a6a38de84048124e8768f9c63b20cf7d3bd Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 13:21:41 -0600 Subject: [PATCH 03/49] Eliminate separate winrt_bindings crate since it no longer seems necessary for fast builds. --- Cargo.toml | 4 +++- build.rs | 10 +++++++++- .../src/lib.rs => src/backends/winrt/bindings.rs | 2 +- src/backends/{winrt.rs => winrt/mod.rs} | 13 +++++++++---- winrt_bindings/Cargo.toml | 13 ------------- winrt_bindings/build.rs | 9 --------- 6 files changed, 22 insertions(+), 29 deletions(-) rename winrt_bindings/src/lib.rs => src/backends/winrt/bindings.rs (96%) rename src/backends/{winrt.rs => winrt/mod.rs} (97%) delete mode 100644 winrt_bindings/Cargo.toml delete mode 100644 winrt_bindings/build.rs diff --git a/Cargo.toml b/Cargo.toml index 8325028..3502664 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,9 @@ env_logger = "0.8" [target.'cfg(windows)'.dependencies] tolk = { version = "0.3", optional = true } windows = "0.4" -tts_winrt_bindings = { version = "0.3", path="winrt_bindings" } + +[target.'cfg(windows)'.build-dependencies] +windows = "0.4" [target.'cfg(target_os = "linux")'.dependencies] speech-dispatcher = "0.7" diff --git a/build.rs b/build.rs index 8b1edc2..6df6312 100644 --- a/build.rs +++ b/build.rs @@ -1,5 +1,13 @@ fn main() { - if std::env::var("TARGET").unwrap().contains("-apple") { + if std::env::var("TARGET").unwrap().contains("windows") { + windows::build!( + windows::foundation::{EventRegistrationToken, IAsyncOperation, TypedEventHandler}, + windows::media::core::MediaSource, + windows::media::playback::{MediaPlaybackSession, MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, + windows::media::speech_synthesis::{SpeechSynthesisStream, SpeechSynthesizer, SpeechSynthesizerOptions}, + windows::storage::streams::IRandomAccessStream, + ); + } else if std::env::var("TARGET").unwrap().contains("-apple") { println!("cargo:rustc-link-lib=framework=AVFoundation"); if !std::env::var("CARGO_CFG_TARGET_OS") .unwrap() diff --git a/winrt_bindings/src/lib.rs b/src/backends/winrt/bindings.rs similarity index 96% rename from winrt_bindings/src/lib.rs rename to src/backends/winrt/bindings.rs index 42af6ba..7915760 100644 --- a/winrt_bindings/src/lib.rs +++ b/src/backends/winrt/bindings.rs @@ -1 +1 @@ -::windows::include_bindings!(); +::windows::include_bindings!(); diff --git a/src/backends/winrt.rs b/src/backends/winrt/mod.rs similarity index 97% rename from src/backends/winrt.rs rename to src/backends/winrt/mod.rs index d9b7704..5aec81d 100644 --- a/src/backends/winrt.rs +++ b/src/backends/winrt/mod.rs @@ -5,11 +5,16 @@ use std::sync::Mutex; use lazy_static::lazy_static; use log::{info, trace}; -use tts_winrt_bindings::windows::media::playback::{ - MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory, +mod bindings; + +use bindings::windows::{ + foundation::TypedEventHandler, + media::{ + core::MediaSource, + playback::{MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, + speech_synthesis::SpeechSynthesizer, + }, }; -use tts_winrt_bindings::windows::media::speech_synthesis::SpeechSynthesizer; -use tts_winrt_bindings::windows::{foundation::TypedEventHandler, media::core::MediaSource}; use crate::{Backend, BackendId, Error, Features, UtteranceId, CALLBACKS}; diff --git a/winrt_bindings/Cargo.toml b/winrt_bindings/Cargo.toml deleted file mode 100644 index da14f55..0000000 --- a/winrt_bindings/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "tts_winrt_bindings" -version = "0.3.0" -authors = ["Nolan Darilek "] -description = "Internal crate used by `tts`" -license = "MIT" -edition = "2018" - -[dependencies] -windows = "0.4" - -[build-dependencies] -windows = "0.4" diff --git a/winrt_bindings/build.rs b/winrt_bindings/build.rs deleted file mode 100644 index 3080588..0000000 --- a/winrt_bindings/build.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - windows::build!( - windows::foundation::{EventRegistrationToken, IAsyncOperation, TypedEventHandler}, - windows::media::core::MediaSource, - windows::media::playback::{MediaPlaybackSession, MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, - windows::media::speech_synthesis::{SpeechSynthesisStream, SpeechSynthesizer, SpeechSynthesizerOptions}, - windows::storage::streams::IRandomAccessStream, - ); -} From 6784bb8861780e373098155306774aeba25f7b9d Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 13:23:08 -0600 Subject: [PATCH 04/49] Remove bindings publish from CI. --- .github/workflows/release.yml | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 87f292d..6bdc02d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -62,27 +62,6 @@ jobs: token: ${{ secrets.GITHUB_TOKEN }} args: --all-features --target wasm32-unknown-unknown - publish_winrt_bindings: - name: Publish winrt_bindings - runs-on: windows-latest - needs: [check] - env: - CARGO_TOKEN: ${{ secrets.CARGO_TOKEN }} - steps: - - uses: actions/checkout@v2 - - uses: Swatinem/rust-cache@v1 - - uses: actions-rs/toolchain@v1 - with: - target: wasm32-unknown-unknown - profile: minimal - toolchain: stable - components: rustfmt, clippy - override: true - - run: | - cargo login $CARGO_TOKEN - cd winrt_bindings - cargo publish || true - publish: name: Publish runs-on: ubuntu-latest From 2fd98c0a52528f64adcfcb84cb18e621d2936ac5 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 13:28:30 -0600 Subject: [PATCH 05/49] Add windows crate to generic build-dependencies so the build script works everywhere. --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3502664..358fff2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,9 @@ lazy_static = "1" log = "0.4" thiserror = "1" +[build-dependencies] +windows = "0.4" + [dev-dependencies] env_logger = "0.8" @@ -24,9 +27,6 @@ env_logger = "0.8" tolk = { version = "0.3", optional = true } windows = "0.4" -[target.'cfg(windows)'.build-dependencies] -windows = "0.4" - [target.'cfg(target_os = "linux")'.dependencies] speech-dispatcher = "0.7" From 6664ca89e3b002a7c881443c4727ebfa1e4ffcc2 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 13:38:44 -0600 Subject: [PATCH 06/49] Revert "Add windows crate to generic build-dependencies so the build script works everywhere." This reverts commit 2fd98c0a52528f64adcfcb84cb18e621d2936ac5. --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 358fff2..3502664 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,6 @@ lazy_static = "1" log = "0.4" thiserror = "1" -[build-dependencies] -windows = "0.4" - [dev-dependencies] env_logger = "0.8" @@ -27,6 +24,9 @@ env_logger = "0.8" tolk = { version = "0.3", optional = true } windows = "0.4" +[target.'cfg(windows)'.build-dependencies] +windows = "0.4" + [target.'cfg(target_os = "linux")'.dependencies] speech-dispatcher = "0.7" From c9279804b759c3dbf7a126fdd4c5a731b6d88997 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 13:41:03 -0600 Subject: [PATCH 07/49] Different approach. --- build.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 6df6312..889acf1 100644 --- a/build.rs +++ b/build.rs @@ -1,4 +1,5 @@ fn main() { + #[cfg(windows)] if std::env::var("TARGET").unwrap().contains("windows") { windows::build!( windows::foundation::{EventRegistrationToken, IAsyncOperation, TypedEventHandler}, @@ -7,7 +8,8 @@ fn main() { windows::media::speech_synthesis::{SpeechSynthesisStream, SpeechSynthesizer, SpeechSynthesizerOptions}, windows::storage::streams::IRandomAccessStream, ); - } else if std::env::var("TARGET").unwrap().contains("-apple") { + } + if std::env::var("TARGET").unwrap().contains("-apple") { println!("cargo:rustc-link-lib=framework=AVFoundation"); if !std::env::var("CARGO_CFG_TARGET_OS") .unwrap() From 8ba1f91617d242de7e9c106a89ada367b7257630 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 13:41:26 -0600 Subject: [PATCH 08/49] Ignore DLL files. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fa8d85a..ea81e28 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Cargo.lock target +*.dll \ No newline at end of file From 2bd324b08b9aa9d56effb97dbc622d69269c23d1 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 11 Mar 2021 13:44:00 -0600 Subject: [PATCH 09/49] Bump version. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 3502664..9015098 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.14.0" +version = "0.15.0" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface" From a22ee537275170362173cca65107b6844865007c Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 12 Mar 2021 05:48:14 -0600 Subject: [PATCH 10/49] Fix Clippy warnings. --- src/backends/av_foundation.rs | 2 +- src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index dbca640..a87bf69 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -116,7 +116,7 @@ impl AvFoundation { AvFoundation { id: BackendId::AvFoundation(*backend_id), delegate: delegate_obj, - synth: synth, + synth, rate: 0.5, volume: 1., pitch: 1., diff --git a/src/lib.rs b/src/lib.rs index d2b80d1..89a1136 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -243,9 +243,9 @@ impl TTS { let str: *const c_char = msg_send![version, UTF8String]; let str = CStr::from_ptr(str); let str = str.to_string_lossy(); - let version: Vec<&str> = str.split(" ").collect(); + let version: Vec<&str> = str.split(' ').collect(); let version = version[1]; - let version_parts: Vec<&str> = version.split(".").collect(); + let version_parts: Vec<&str> = version.split('.').collect(); let major_version: i8 = version_parts[0].parse().unwrap(); let minor_version: i8 = version_parts[1].parse().unwrap(); if major_version >= 11 || minor_version >= 14 { From 1d075f7ececc3a153bf23111014a798e7d82dbbe Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 12 Mar 2021 05:50:08 -0600 Subject: [PATCH 11/49] When speech is interrupted on AVFoundation, only stop if already speaking. May address a possible deadlock. --- src/backends/av_foundation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index a87bf69..6e5f38d 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -145,7 +145,7 @@ impl Backend for AvFoundation { fn speak(&mut self, text: &str, interrupt: bool) -> Result, Error> { trace!("speak({}, {})", text, interrupt); - if interrupt { + if interrupt && self.is_speaking()? { self.stop()?; } let utterance: id; From 1f510120a57083f2baecbd2b6aad37988399b1b1 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 12 Mar 2021 05:58:30 -0600 Subject: [PATCH 12/49] Add trace logging in AVFoundation backend. --- src/backends/av_foundation.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index 6e5f38d..3dcc7dc 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -37,16 +37,22 @@ impl AvFoundation { _synth: *const Object, utterance: id, ) { + trace!("speech_synthesizer_did_start_speech_utterance"); unsafe { let backend_id: u64 = *this.get_ivar("backend_id"); let backend_id = BackendId::AvFoundation(backend_id); + trace!("Locking callbacks"); let mut callbacks = CALLBACKS.lock().unwrap(); + trace!("Locked"); let callbacks = callbacks.get_mut(&backend_id).unwrap(); if let Some(callback) = callbacks.utterance_begin.as_mut() { + trace!("Calling utterance_begin"); let utterance_id = UtteranceId::AvFoundation(utterance); callback(utterance_id); + trace!("Called"); } } + trace!("Done speech_synthesizer_did_start_speech_utterance"); } extern "C" fn speech_synthesizer_did_finish_speech_utterance( @@ -55,16 +61,22 @@ impl AvFoundation { _synth: *const Object, utterance: id, ) { + trace!("speech_synthesizer_did_finish_speech_utterance"); unsafe { let backend_id: u64 = *this.get_ivar("backend_id"); let backend_id = BackendId::AvFoundation(backend_id); + trace!("Locking callbacks"); let mut callbacks = CALLBACKS.lock().unwrap(); + trace!("Locked"); let callbacks = callbacks.get_mut(&backend_id).unwrap(); if let Some(callback) = callbacks.utterance_end.as_mut() { + trace!("Calling utterance_end"); let utterance_id = UtteranceId::AvFoundation(utterance); callback(utterance_id); + trace!("Called"); } } + trace!("Done speech_synthesizer_did_finish_speech_utterance"); } extern "C" fn speech_synthesizer_did_cancel_speech_utterance( @@ -73,16 +85,22 @@ impl AvFoundation { _synth: *const Object, utterance: id, ) { + trace!("speech_synthesizer_did_cancel_speech_utterance"); unsafe { let backend_id: u64 = *this.get_ivar("backend_id"); let backend_id = BackendId::AvFoundation(backend_id); + trace!("Locking callbacks"); let mut callbacks = CALLBACKS.lock().unwrap(); + trace!("Locked"); let callbacks = callbacks.get_mut(&backend_id).unwrap(); if let Some(callback) = callbacks.utterance_stop.as_mut() { + trace!("Calling utterance_stop"); let utterance_id = UtteranceId::AvFoundation(utterance); callback(utterance_id); + trace!("Called"); } } + trace!("Done speech_synthesizer_did_cancel_speech_utterance"); } unsafe { From 81eba9959458295590a8bf48d2a886df8b82a035 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 12 Mar 2021 06:20:05 -0600 Subject: [PATCH 13/49] Add cast to (hopefully) get AppKit compiling on M1 macs. --- src/backends/appkit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/appkit.rs b/src/backends/appkit.rs index 97f6cb4..8035e26 100644 --- a/src/backends/appkit.rs +++ b/src/backends/appkit.rs @@ -198,7 +198,7 @@ impl Backend for AppKit { fn is_speaking(&self) -> Result { let is_speaking: i8 = unsafe { msg_send![self.0, isSpeaking] }; - Ok(is_speaking == YES) + Ok(is_speaking == YES as i8) } } From e91637a67cbd908d922e16e0b462dfa0cc3c834c Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 12 Mar 2021 06:28:02 -0600 Subject: [PATCH 14/49] Add even more trace logging. --- src/backends/av_foundation.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index 3dcc7dc..b071370 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -226,6 +226,7 @@ impl Backend for AvFoundation { } fn set_pitch(&mut self, pitch: f32) -> Result<(), Error> { + trace!("set_pitch({})", pitch); self.pitch = pitch; Ok(()) } @@ -247,11 +248,13 @@ impl Backend for AvFoundation { } fn set_volume(&mut self, volume: f32) -> Result<(), Error> { + trace!("set_volume({})", volume); self.volume = volume; Ok(()) } fn is_speaking(&self) -> Result { + trace!("is_speaking()"); let is_speaking: i8 = unsafe { msg_send![self.synth, isSpeaking] }; Ok(is_speaking == 1) } From 290eb06d02ae9cc880b09467448a89293b17dc40 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 12 Mar 2021 06:38:46 -0600 Subject: [PATCH 15/49] Even more trace logging. --- src/backends/av_foundation.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index b071370..5f93394 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -168,13 +168,21 @@ impl Backend for AvFoundation { } let utterance: id; unsafe { + trace!("Allocating utterance string"); let str = NSString::alloc(nil).init_str(text); + trace!("Allocating utterance"); utterance = msg_send![class!(AVSpeechUtterance), alloc]; + trace!("Initializing utterance"); let _: () = msg_send![utterance, initWithString: str]; + trace!("Setting rate to {}", self.rate); let _: () = msg_send![utterance, setRate: self.rate]; + trace!("Setting volume to {}", self.volume); let _: () = msg_send![utterance, setVolume: self.volume]; + trace!("Setting pitch to {}", self.pitch); let _: () = msg_send![utterance, setPitchMultiplier: self.pitch]; + trace!("Enqueuing"); let _: () = msg_send![self.synth, speakUtterance: utterance]; + trace!("Done queuing"); } Ok(Some(UtteranceId::AvFoundation(utterance))) } From cdfb7ddb7782f0faa00f23a8074da1571b114b32 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 12 Mar 2021 06:59:49 -0600 Subject: [PATCH 16/49] Even more bloody logging. --- src/backends/av_foundation.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index 5f93394..d7a747b 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -125,12 +125,16 @@ impl AvFoundation { let delegate_obj: *mut Object = unsafe { msg_send![delegate_class, new] }; let mut backend_id = NEXT_BACKEND_ID.lock().unwrap(); let rv = unsafe { + trace!("Creating synth"); let synth: *mut Object = msg_send![class!(AVSpeechSynthesizer), new]; + trace!("Allocated {:?}", synth); delegate_obj .as_mut() .unwrap() .set_ivar("backend_id", *backend_id); + trace!("Set backend ID in delegate"); let _: () = msg_send![synth, setDelegate: delegate_obj]; + trace!("Assigned delegate: {:?}", delegate_obj); AvFoundation { id: BackendId::AvFoundation(*backend_id), delegate: delegate_obj, From 00485d6cd8eda67ea66527be8de38d7b243a9309 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Fri, 12 Mar 2021 08:36:52 -0600 Subject: [PATCH 17/49] Enable 'exception' feature to hopefully catch and surface ObjC exceptions. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 9015098..ed29fcd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ speech-dispatcher = "0.7" [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies] cocoa-foundation = "0.1" libc = "0.2" -objc = "0.2" +objc = { version = "0.2", features = ["exception"] } [target.wasm32-unknown-unknown.dependencies] wasm-bindgen = "0.2" From bd8e2ee20a17d786dd7fd2b858d29c065be2310f Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 15 Mar 2021 13:02:32 -0500 Subject: [PATCH 18/49] Compare against ObjC NO to ensure correctness. --- src/backends/appkit.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/appkit.rs b/src/backends/appkit.rs index 8035e26..2a07450 100644 --- a/src/backends/appkit.rs +++ b/src/backends/appkit.rs @@ -198,7 +198,7 @@ impl Backend for AppKit { fn is_speaking(&self) -> Result { let is_speaking: i8 = unsafe { msg_send![self.0, isSpeaking] }; - Ok(is_speaking == YES as i8) + Ok(is_speaking != NO as i8) } } From c65c0022d821ae8ce65617c72dcfa701e166a726 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 15 Mar 2021 13:03:41 -0500 Subject: [PATCH 19/49] (Hopefully) initialize utterances correctly. --- src/backends/av_foundation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index d7a747b..a10830d 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -177,7 +177,7 @@ impl Backend for AvFoundation { trace!("Allocating utterance"); utterance = msg_send![class!(AVSpeechUtterance), alloc]; trace!("Initializing utterance"); - let _: () = msg_send![utterance, initWithString: str]; + utterance = msg_send![utterance, initWithString: str]; trace!("Setting rate to {}", self.rate); let _: () = msg_send![utterance, setRate: self.rate]; trace!("Setting volume to {}", self.volume); From 45255a804973d62cf78e5d389423aa3d70ff180c Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 15 Mar 2021 13:04:38 -0500 Subject: [PATCH 20/49] Fix another possibly broken comparison. --- src/backends/av_foundation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index a10830d..98c7870 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -268,7 +268,7 @@ impl Backend for AvFoundation { fn is_speaking(&self) -> Result { trace!("is_speaking()"); let is_speaking: i8 = unsafe { msg_send![self.synth, isSpeaking] }; - Ok(is_speaking == 1) + Ok(is_speaking != 0) } } From ed2d2e76c33f5c17e5eb10cc73fd9d12a31d739a Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 15 Mar 2021 13:06:49 -0500 Subject: [PATCH 21/49] And this is what happens when I don't test on actual hardware. --- src/backends/av_foundation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index 98c7870..566bc66 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -170,7 +170,7 @@ impl Backend for AvFoundation { if interrupt && self.is_speaking()? { self.stop()?; } - let utterance: id; + let mut utterance: id; unsafe { trace!("Allocating utterance string"); let str = NSString::alloc(nil).init_str(text); From 8c2aae7afd6fe4497e628389d8af235d56ab9c10 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 15 Mar 2021 13:46:22 -0500 Subject: [PATCH 22/49] Try another initialization fix. --- src/backends/av_foundation.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index 566bc66..b9a8888 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -173,7 +173,8 @@ impl Backend for AvFoundation { let mut utterance: id; unsafe { trace!("Allocating utterance string"); - let str = NSString::alloc(nil).init_str(text); + let mut str = NSString::alloc(nil); + str = str.init_str(text); trace!("Allocating utterance"); utterance = msg_send![class!(AVSpeechUtterance), alloc]; trace!("Initializing utterance"); From 50528ce2d1e1e1e8f0e80e2e6a43e0cc950bbb17 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 15 Mar 2021 13:47:17 -0500 Subject: [PATCH 23/49] Another comparison check fix. --- src/backends/av_foundation.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index b9a8888..45a6fbe 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -2,7 +2,7 @@ #[link(name = "AVFoundation", kind = "framework")] use std::sync::Mutex; -use cocoa_foundation::base::{id, nil}; +use cocoa_foundation::base::{id, nil, NO}; use cocoa_foundation::foundation::NSString; use lazy_static::lazy_static; use log::{info, trace}; @@ -269,7 +269,7 @@ impl Backend for AvFoundation { fn is_speaking(&self) -> Result { trace!("is_speaking()"); let is_speaking: i8 = unsafe { msg_send![self.synth, isSpeaking] }; - Ok(is_speaking != 0) + Ok(is_speaking != NO) } } From fb7f1dddfcf9d734e4d6eeadaf0589135ee5193d Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 15 Mar 2021 14:02:05 -0500 Subject: [PATCH 24/49] *sigh* Fix stupid M1/ARM casting issue. I hate Apple. --- src/backends/av_foundation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/av_foundation.rs b/src/backends/av_foundation.rs index 45a6fbe..68f95c9 100644 --- a/src/backends/av_foundation.rs +++ b/src/backends/av_foundation.rs @@ -269,7 +269,7 @@ impl Backend for AvFoundation { fn is_speaking(&self) -> Result { trace!("is_speaking()"); let is_speaking: i8 = unsafe { msg_send![self.synth, isSpeaking] }; - Ok(is_speaking != NO) + Ok(is_speaking != NO as i8) } } From 25f8211661acaef7c41c80ae0e8a6d68df5bcb30 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 16 Mar 2021 14:18:49 -0500 Subject: [PATCH 25/49] Bump version. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ed29fcd..e37f780 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.15.0" +version = "0.15.1" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface" From 153075ebab7e620410b3d0c367652c52e091e25a Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 16 Mar 2021 17:33:01 -0500 Subject: [PATCH 26/49] Add web example Closes #1 --- Makefile.toml | 14 ++++- examples/web/.cargo/config | 2 + examples/web/.gitignore | 1 + examples/web/Cargo.toml | 11 ++++ examples/web/index.html | 12 ++++ examples/web/src/main.rs | 111 +++++++++++++++++++++++++++++++++++++ 6 files changed, 150 insertions(+), 1 deletion(-) create mode 100644 examples/web/.cargo/config create mode 100644 examples/web/.gitignore create mode 100644 examples/web/Cargo.toml create mode 100644 examples/web/index.html create mode 100644 examples/web/src/main.rs diff --git a/Makefile.toml b/Makefile.toml index 6697f15..d5cda6b 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -12,4 +12,16 @@ script = [ [tasks.log-android] command = "adb" -args = ["logcat", "RustStdoutStderr:D", "*:S"] \ No newline at end of file +args = ["logcat", "RustStdoutStderr:D", "*:S"] + +[tasks.install-trunk] +install_crate = { crate_name = "trunk", binary = "trunk", test_arg = "--help" } + +[tasks.install-wasm-bindgen-cli] +install_crate = { crate_name = "wasm-bindgen-cli", binary = "wasm-bindgen", test_arg = "--help" } + +[tasks.run-web-example] +dependencies = ["install-trunk", "install-wasm-bindgen-cli"] +cwd = "examples/web" +command = "trunk" +args = ["serve"] \ No newline at end of file diff --git a/examples/web/.cargo/config b/examples/web/.cargo/config new file mode 100644 index 0000000..435ed75 --- /dev/null +++ b/examples/web/.cargo/config @@ -0,0 +1,2 @@ +[build] +target = "wasm32-unknown-unknown" \ No newline at end of file diff --git a/examples/web/.gitignore b/examples/web/.gitignore new file mode 100644 index 0000000..53c37a1 --- /dev/null +++ b/examples/web/.gitignore @@ -0,0 +1 @@ +dist \ No newline at end of file diff --git a/examples/web/Cargo.toml b/examples/web/Cargo.toml new file mode 100644 index 0000000..e93d316 --- /dev/null +++ b/examples/web/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "web" +version = "0.1.0" +authors = ["Nolan Darilek "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +seed = "0.8" +tts = { path = "../.." } \ No newline at end of file diff --git a/examples/web/index.html b/examples/web/index.html new file mode 100644 index 0000000..15e486f --- /dev/null +++ b/examples/web/index.html @@ -0,0 +1,12 @@ + + + + + Example + + + +
+ + + \ No newline at end of file diff --git a/examples/web/src/main.rs b/examples/web/src/main.rs new file mode 100644 index 0000000..5f35742 --- /dev/null +++ b/examples/web/src/main.rs @@ -0,0 +1,111 @@ +#![allow(clippy::wildcard_imports)] +use seed::{prelude::*, *}; + +use tts::TTS; + +#[derive(Clone)] +struct Model { + text: String, + tts: TTS, +} + +#[derive(Clone)] +enum Msg { + TextChanged(String), + RateChanged(String), + PitchChanged(String), + VolumeChanged(String), + Speak, +} + +fn init(_: Url, _: &mut impl Orders) -> Model { + let tts = TTS::default().unwrap(); + Model { + text: Default::default(), + tts, + } +} + +fn update(msg: Msg, model: &mut Model, _: &mut impl Orders) { + use Msg::*; + match msg { + TextChanged(text) => model.text = text, + RateChanged(rate) => { + let rate = rate.parse::().unwrap(); + model.tts.set_rate(rate).unwrap(); + } + PitchChanged(pitch) => { + let pitch = pitch.parse::().unwrap(); + model.tts.set_pitch(pitch).unwrap(); + } + VolumeChanged(volume) => { + let volume = volume.parse::().unwrap(); + model.tts.set_volume(volume).unwrap(); + } + Speak => { + model.tts.speak(&model.text, false).unwrap(); + } + } +} + +fn view(model: &Model) -> Node { + form![ + div![label![ + "Text to speak", + input![ + attrs! { + At::Value => model.text, + At::AutoFocus => AtValue::None, + }, + input_ev(Ev::Input, Msg::TextChanged) + ], + ],], + div![label![ + "Rate", + input![ + attrs! { + At::Type => "number", + At::Value => model.tts.get_rate().unwrap(), + At::Min => model.tts.min_rate(), + At::Max => model.tts.max_rate() + }, + input_ev(Ev::Input, Msg::RateChanged) + ], + ],], + div![label![ + "Pitch", + input![ + attrs! { + At::Type => "number", + At::Value => model.tts.get_pitch().unwrap(), + At::Min => model.tts.min_pitch(), + At::Max => model.tts.max_pitch() + }, + input_ev(Ev::Input, Msg::PitchChanged) + ], + ],], + div![label![ + "Volume", + input![ + attrs! { + At::Type => "number", + At::Value => model.tts.get_volume().unwrap(), + At::Min => model.tts.min_volume(), + At::Max => model.tts.max_volume() + }, + input_ev(Ev::Input, Msg::VolumeChanged) + ], + ],], + button![ + "Speak", + ev(Ev::Click, |e| { + e.prevent_default(); + Msg::Speak + }), + ], + ] +} + +fn main() { + App::start("app", init, update, view); +} From acccdfeadae72bc92348e9680a124123711b154a Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 16 Mar 2021 17:36:29 -0500 Subject: [PATCH 27/49] Bump version. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index e37f780..532af58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.15.1" +version = "0.15.2" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface" From ef96042b1265b8bd68f92f8b4b4f43247c29bd31 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Wed, 31 Mar 2021 10:38:32 -0500 Subject: [PATCH 28/49] Bump Windows dependency and update accordingly. Also, fix an acronym Clippy warning. --- Cargo.toml | 4 +-- build.rs | 10 +++--- src/backends/winrt/mod.rs | 76 +++++++++++++++++++-------------------- src/lib.rs | 18 +++++----- 4 files changed, 53 insertions(+), 55 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 532af58..74f24fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ env_logger = "0.8" [target.'cfg(windows)'.dependencies] tolk = { version = "0.3", optional = true } -windows = "0.4" +windows = "0.7" [target.'cfg(windows)'.build-dependencies] -windows = "0.4" +windows = "0.7" [target.'cfg(target_os = "linux")'.dependencies] speech-dispatcher = "0.7" diff --git a/build.rs b/build.rs index 889acf1..e2e2035 100644 --- a/build.rs +++ b/build.rs @@ -2,11 +2,11 @@ fn main() { #[cfg(windows)] if std::env::var("TARGET").unwrap().contains("windows") { windows::build!( - windows::foundation::{EventRegistrationToken, IAsyncOperation, TypedEventHandler}, - windows::media::core::MediaSource, - windows::media::playback::{MediaPlaybackSession, MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, - windows::media::speech_synthesis::{SpeechSynthesisStream, SpeechSynthesizer, SpeechSynthesizerOptions}, - windows::storage::streams::IRandomAccessStream, + Windows::Foundation::{EventRegistrationToken, IAsyncOperation, TypedEventHandler}, + Windows::Media::Core::MediaSource, + Windows::Media::Playback::{MediaPlaybackSession, MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, + Windows::Media::SpeechSynthesis::{SpeechSynthesisStream, SpeechSynthesizer, SpeechSynthesizerOptions}, + Windows::Storage::Streams::IRandomAccessStream, ); } if std::env::var("TARGET").unwrap().contains("-apple") { diff --git a/src/backends/winrt/mod.rs b/src/backends/winrt/mod.rs index 5aec81d..9b2d0f0 100644 --- a/src/backends/winrt/mod.rs +++ b/src/backends/winrt/mod.rs @@ -7,12 +7,12 @@ use log::{info, trace}; mod bindings; -use bindings::windows::{ - foundation::TypedEventHandler, - media::{ - core::MediaSource, - playback::{MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, - speech_synthesis::SpeechSynthesizer, +use bindings::Windows::{ + Foundation::TypedEventHandler, + Media::{ + Core::MediaSource, + Playback::{MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, + SpeechSynthesis::SpeechSynthesizer, }, }; @@ -20,12 +20,12 @@ use crate::{Backend, BackendId, Error, Features, UtteranceId, CALLBACKS}; impl From for Error { fn from(e: windows::Error) -> Self { - Error::WinRT(e) + Error::WinRt(e) } } #[derive(Clone, Debug)] -pub struct WinRT { +pub struct WinRt { id: BackendId, synth: SpeechSynthesizer, player: MediaPlayer, @@ -59,15 +59,15 @@ lazy_static! { }; } -impl WinRT { +impl WinRt { pub fn new() -> std::result::Result { info!("Initializing WinRT backend"); let synth = SpeechSynthesizer::new()?; let player = MediaPlayer::new()?; - player.set_real_time_playback(true)?; - player.set_audio_category(MediaPlayerAudioCategory::Speech)?; + player.SetRealTimePlayback(true)?; + player.SetAudioCategory(MediaPlayerAudioCategory::Speech)?; let mut backend_id = NEXT_BACKEND_ID.lock().unwrap(); - let bid = BackendId::WinRT(*backend_id); + let bid = BackendId::WinRt(*backend_id); *backend_id += 1; drop(backend_id); { @@ -81,7 +81,7 @@ impl WinRT { backend_to_speech_synthesizer.insert(bid, synth.clone()); drop(backend_to_speech_synthesizer); let bid_clone = bid; - player.media_ended(TypedEventHandler::new( + player.MediaEnded(TypedEventHandler::new( move |sender: &Option, _args| { if let Some(sender) = sender { let backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap(); @@ -102,19 +102,17 @@ impl WinRT { .iter() .find(|v| *v.0 == bid_clone); if let Some((_, tts)) = id { - tts.options()?.set_speaking_rate(utterance.rate.into())?; - tts.options()?.set_audio_pitch(utterance.pitch.into())?; - tts.options()?.set_audio_volume(utterance.volume.into())?; + tts.Options()?.SetSpeakingRate(utterance.rate.into())?; + tts.Options()?.SetAudioPitch(utterance.pitch.into())?; + tts.Options()?.SetAudioVolume(utterance.volume.into())?; let stream = tts - .synthesize_text_to_stream_async( - utterance.text.as_str(), - )? + .SynthesizeTextToStreamAsync(utterance.text.as_str())? .get()?; - let content_type = stream.content_type()?; + let content_type = stream.ContentType()?; let source = - MediaSource::create_from_stream(stream, content_type)?; - sender.set_source(source)?; - sender.play()?; + MediaSource::CreateFromStream(stream, content_type)?; + sender.SetSource(source)?; + sender.Play()?; if let Some(callback) = callbacks.utterance_begin.as_mut() { callback(utterance.id); } @@ -138,7 +136,7 @@ impl WinRT { } } -impl Backend for WinRT { +impl Backend for WinRt { fn id(&self) -> Option { Some(self.id) } @@ -164,7 +162,7 @@ impl Backend for WinRT { } let utterance_id = { let mut uid = NEXT_UTTERANCE_ID.lock().unwrap(); - let utterance_id = UtteranceId::WinRT(*uid); + let utterance_id = UtteranceId::WinRt(*uid); *uid += 1; utterance_id }; @@ -184,16 +182,16 @@ impl Backend for WinRT { } } if no_utterances - && self.player.playback_session()?.playback_state()? != MediaPlaybackState::Playing + && self.player.PlaybackSession()?.PlaybackState()? != MediaPlaybackState::Playing { - self.synth.options()?.set_speaking_rate(self.rate.into())?; - self.synth.options()?.set_audio_pitch(self.pitch.into())?; - self.synth.options()?.set_audio_volume(self.volume.into())?; - let stream = self.synth.synthesize_text_to_stream_async(text)?.get()?; - let content_type = stream.content_type()?; - let source = MediaSource::create_from_stream(stream, content_type)?; - self.player.set_source(source)?; - self.player.play()?; + self.synth.Options()?.SetSpeakingRate(self.rate.into())?; + self.synth.Options()?.SetAudioPitch(self.pitch.into())?; + self.synth.Options()?.SetAudioVolume(self.volume.into())?; + let stream = self.synth.SynthesizeTextToStreamAsync(text)?.get()?; + let content_type = stream.ContentType()?; + let source = MediaSource::CreateFromStream(stream, content_type)?; + self.player.SetSource(source)?; + self.player.Play()?; let mut callbacks = CALLBACKS.lock().unwrap(); let callbacks = callbacks.get_mut(&self.id).unwrap(); if let Some(callback) = callbacks.utterance_begin.as_mut() { @@ -221,7 +219,7 @@ impl Backend for WinRT { if let Some(utterances) = utterances.get_mut(&self.id) { utterances.clear(); } - self.player.pause()?; + self.player.Pause()?; Ok(()) } @@ -238,7 +236,7 @@ impl Backend for WinRT { } fn get_rate(&self) -> std::result::Result { - let rate = self.synth.options()?.speaking_rate()?; + let rate = self.synth.Options()?.SpeakingRate()?; Ok(rate as f32) } @@ -260,7 +258,7 @@ impl Backend for WinRT { } fn get_pitch(&self) -> std::result::Result { - let pitch = self.synth.options()?.audio_pitch()?; + let pitch = self.synth.Options()?.AudioPitch()?; Ok(pitch as f32) } @@ -282,7 +280,7 @@ impl Backend for WinRT { } fn get_volume(&self) -> std::result::Result { - let volume = self.synth.options()?.audio_volume()?; + let volume = self.synth.Options()?.AudioVolume()?; Ok(volume as f32) } @@ -298,7 +296,7 @@ impl Backend for WinRT { } } -impl Drop for WinRT { +impl Drop for WinRt { fn drop(&mut self) { let id = self.id; let mut backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap(); diff --git a/src/lib.rs b/src/lib.rs index 89a1136..998fd02 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,7 +39,7 @@ pub enum Backends { #[cfg(all(windows, feature = "tolk"))] Tolk, #[cfg(windows)] - WinRT, + WinRt, #[cfg(target_os = "macos")] AppKit, #[cfg(any(target_os = "macos", target_os = "ios"))] @@ -55,7 +55,7 @@ pub enum BackendId { #[cfg(target_arch = "wasm32")] Web(u64), #[cfg(windows)] - WinRT(u64), + WinRt(u64), #[cfg(any(target_os = "macos", target_os = "ios"))] AvFoundation(u64), #[cfg(target_os = "android")] @@ -69,7 +69,7 @@ pub enum UtteranceId { #[cfg(target_arch = "wasm32")] Web(u64), #[cfg(windows)] - WinRT(u64), + WinRt(u64), #[cfg(any(target_os = "macos", target_os = "ios"))] AvFoundation(id), #[cfg(target_os = "android")] @@ -105,7 +105,7 @@ impl Default for Features { #[derive(Debug, Error)] pub enum Error { #[error("IO error: {0}")] - IO(#[from] std::io::Error), + Io(#[from] std::io::Error), #[error("Value not received")] NoneError, #[error("Operation failed")] @@ -115,7 +115,7 @@ pub enum Error { JavaScriptError(wasm_bindgen::JsValue), #[cfg(windows)] #[error("WinRT error")] - WinRT(windows::Error), + WinRt(windows::Error), #[error("Unsupported feature")] UnsupportedFeature, #[error("Out of range")] @@ -197,8 +197,8 @@ impl TTS { } } #[cfg(windows)] - Backends::WinRT => { - let tts = backends::WinRT::new()?; + Backends::WinRt => { + let tts = backends::WinRt::new()?; Ok(TTS(Box::new(tts))) } #[cfg(target_os = "macos")] @@ -229,10 +229,10 @@ impl TTS { let tts = if let Ok(tts) = TTS::new(Backends::Tolk) { Ok(tts) } else { - TTS::new(Backends::WinRT) + TTS::new(Backends::WinRt) }; #[cfg(all(windows, not(feature = "tolk")))] - let tts = TTS::new(Backends::WinRT); + let tts = TTS::new(Backends::WinRt); #[cfg(target_arch = "wasm32")] let tts = TTS::new(Backends::Web); #[cfg(target_os = "macos")] From 57f91105ec7bc86d0eedb09e8d82a46c8e6cc093 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Wed, 31 Mar 2021 10:40:42 -0500 Subject: [PATCH 29/49] s/TTS/Tts/ as per Clippy's acronym warnings. --- examples/99bottles.rs | 2 +- examples/hello_world.rs | 2 +- examples/latency.rs | 2 +- examples/ramble.rs | 2 +- src/lib.rs | 36 ++++++++++++++++++------------------ 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/examples/99bottles.rs b/examples/99bottles.rs index 9371b82..ff3f130 100644 --- a/examples/99bottles.rs +++ b/examples/99bottles.rs @@ -12,7 +12,7 @@ use tts::*; fn main() -> Result<(), Error> { env_logger::init(); - let mut tts = TTS::default()?; + let mut tts = Tts::default()?; let mut bottles = 99; while bottles > 0 { tts.speak(format!("{} bottles of beer on the wall,", bottles), false)?; diff --git a/examples/hello_world.rs b/examples/hello_world.rs index f3fa7a8..f737f3f 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -11,7 +11,7 @@ use tts::*; fn main() -> Result<(), Error> { env_logger::init(); - let mut tts = TTS::default()?; + let mut tts = Tts::default()?; let Features { utterance_callbacks, .. diff --git a/examples/latency.rs b/examples/latency.rs index 819becc..d6d998e 100644 --- a/examples/latency.rs +++ b/examples/latency.rs @@ -4,7 +4,7 @@ use tts::*; fn main() -> Result<(), Error> { env_logger::init(); - let mut tts = TTS::default()?; + let mut tts = Tts::default()?; println!("Press Enter and wait for speech."); loop { let mut _input = String::new(); diff --git a/examples/ramble.rs b/examples/ramble.rs index 85bde46..e327374 100644 --- a/examples/ramble.rs +++ b/examples/ramble.rs @@ -4,7 +4,7 @@ use tts::*; fn main() -> Result<(), Error> { env_logger::init(); - let mut tts = TTS::default()?; + let mut tts = Tts::default()?; let mut phrase = 1; loop { tts.speak(format!("Phrase {}", phrase), false)?; diff --git a/src/lib.rs b/src/lib.rs index 998fd02..fc50015 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -168,17 +168,17 @@ lazy_static! { } #[derive(Clone)] -pub struct TTS(Box); +pub struct Tts(Box); -unsafe impl Send for TTS {} +unsafe impl Send for Tts {} -unsafe impl Sync for TTS {} +unsafe impl Sync for Tts {} -impl TTS { +impl Tts { /** * Create a new `TTS` instance with the specified backend. */ - pub fn new(backend: Backends) -> Result { + pub fn new(backend: Backends) -> Result { let backend = match backend { #[cfg(target_os = "linux")] Backends::SpeechDispatcher => Ok(TTS(Box::new(backends::SpeechDispatcher::new()))), @@ -191,7 +191,7 @@ impl TTS { Backends::Tolk => { let tts = backends::Tolk::new(); if let Some(tts) = tts { - Ok(TTS(Box::new(tts))) + Ok(Tts(Box::new(tts))) } else { Err(Error::NoneError) } @@ -199,7 +199,7 @@ impl TTS { #[cfg(windows)] Backends::WinRt => { let tts = backends::WinRt::new()?; - Ok(TTS(Box::new(tts))) + Ok(Tts(Box::new(tts))) } #[cfg(target_os = "macos")] Backends::AppKit => Ok(TTS(Box::new(backends::AppKit::new()))), @@ -222,19 +222,19 @@ impl TTS { } } - pub fn default() -> Result { + pub fn default() -> Result { #[cfg(target_os = "linux")] - let tts = TTS::new(Backends::SpeechDispatcher); + let tts = Tts::new(Backends::SpeechDispatcher); #[cfg(all(windows, feature = "tolk"))] - let tts = if let Ok(tts) = TTS::new(Backends::Tolk) { + let tts = if let Ok(tts) = Tts::new(Backends::Tolk) { Ok(tts) } else { - TTS::new(Backends::WinRt) + Tts::new(Backends::WinRt) }; #[cfg(all(windows, not(feature = "tolk")))] - let tts = TTS::new(Backends::WinRt); + let tts = Tts::new(Backends::WinRt); #[cfg(target_arch = "wasm32")] - let tts = TTS::new(Backends::Web); + let tts = Tts::new(Backends::Web); #[cfg(target_os = "macos")] let tts = unsafe { // Needed because the Rust NSProcessInfo structs report bogus values, and I don't want to pull in a full bindgen stack. @@ -249,15 +249,15 @@ impl TTS { let major_version: i8 = version_parts[0].parse().unwrap(); let minor_version: i8 = version_parts[1].parse().unwrap(); if major_version >= 11 || minor_version >= 14 { - TTS::new(Backends::AvFoundation) + Tts::new(Backends::AvFoundation) } else { - TTS::new(Backends::AppKit) + Tts::new(Backends::AppKit) } }; #[cfg(target_os = "ios")] - let tts = TTS::new(Backends::AvFoundation); + let tts = Tts::new(Backends::AvFoundation); #[cfg(target_os = "android")] - let tts = TTS::new(Backends::Android); + let tts = Tts::new(Backends::Android); tts } @@ -529,7 +529,7 @@ impl TTS { } } -impl Drop for TTS { +impl Drop for Tts { fn drop(&mut self) { if let Some(id) = self.0.id() { let mut callbacks = CALLBACKS.lock().unwrap(); From 336c266ed47927eab8b574b03c396bc906935ef7 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Wed, 31 Mar 2021 10:53:08 -0500 Subject: [PATCH 30/49] Missed a few... --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fc50015..d67ad48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -181,11 +181,11 @@ impl Tts { pub fn new(backend: Backends) -> Result { let backend = match backend { #[cfg(target_os = "linux")] - Backends::SpeechDispatcher => Ok(TTS(Box::new(backends::SpeechDispatcher::new()))), + Backends::SpeechDispatcher => Ok(Tts(Box::new(backends::SpeechDispatcher::new()))), #[cfg(target_arch = "wasm32")] Backends::Web => { let tts = backends::Web::new()?; - Ok(TTS(Box::new(tts))) + Ok(Tts(Box::new(tts))) } #[cfg(all(windows, feature = "tolk"))] Backends::Tolk => { From 6dbf9b7ddce8f5af968f7ebf58f99f1ebd6feaa0 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Wed, 31 Mar 2021 11:01:26 -0500 Subject: [PATCH 31/49] Find/replace is failing me today. --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d67ad48..3cc5e67 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -202,9 +202,9 @@ impl Tts { Ok(Tts(Box::new(tts))) } #[cfg(target_os = "macos")] - Backends::AppKit => Ok(TTS(Box::new(backends::AppKit::new()))), + Backends::AppKit => Ok(Tts(Box::new(backends::AppKit::new()))), #[cfg(any(target_os = "macos", target_os = "ios"))] - Backends::AvFoundation => Ok(TTS(Box::new(backends::AvFoundation::new()))), + Backends::AvFoundation => Ok(Tts(Box::new(backends::AvFoundation::new()))), #[cfg(target_os = "android")] Backends::Android => { let tts = backends::Android::new()?; From d9639c049bdcafc8d4d36ca86223bd7f1a4bf1bd Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Wed, 31 Mar 2021 11:03:14 -0500 Subject: [PATCH 32/49] S/TTS/Tts/ here as well. --- examples/android/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/android/src/lib.rs b/examples/android/src/lib.rs index 6bf79d6..a8e4677 100644 --- a/examples/android/src/lib.rs +++ b/examples/android/src/lib.rs @@ -4,7 +4,7 @@ use tts::*; // Without it, the `TTS` instance gets dropped before callbacks can run. #[allow(unreachable_code)] fn run() -> Result<(), Error> { - let mut tts = TTS::default()?; + let mut tts = Tts::default()?; let Features { utterance_callbacks, .. From 1011704b824f955a57f61170ccf63cb41fb8f8d3 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Wed, 31 Mar 2021 11:12:42 -0500 Subject: [PATCH 33/49] And again, VSCode's find/replace didn't catch this. *grumble* --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 3cc5e67..1901556 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -208,7 +208,7 @@ impl Tts { #[cfg(target_os = "android")] Backends::Android => { let tts = backends::Android::new()?; - Ok(TTS(Box::new(tts))) + Ok(Tts(Box::new(tts))) } }; if let Ok(backend) = backend { From debab7de17ea2cb8eb60cccaa1de3550387531a5 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Sat, 3 Apr 2021 11:11:37 -0500 Subject: [PATCH 34/49] Bump version. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 74f24fb..4c57063 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.15.2" +version = "0.16.0" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface" From f7239366f0278ffb0cd7ce7dead9ffa06cff6de0 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Sat, 3 Apr 2021 11:49:44 -0500 Subject: [PATCH 35/49] Add command to build the web example. --- Makefile.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Makefile.toml b/Makefile.toml index d5cda6b..97655f3 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -20,6 +20,12 @@ install_crate = { crate_name = "trunk", binary = "trunk", test_arg = "--help" } [tasks.install-wasm-bindgen-cli] install_crate = { crate_name = "wasm-bindgen-cli", binary = "wasm-bindgen", test_arg = "--help" } +[tasks.build-web-example] +dependencies = ["install-trunk", "install-wasm-bindgen-cli"] +cwd = "examples/web" +command = "trunk" +args = ["build"] + [tasks.run-web-example] dependencies = ["install-trunk", "install-wasm-bindgen-cli"] cwd = "examples/web" From d5a692008a52edaa366828e3d992843a8eab6105 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Sat, 3 Apr 2021 11:50:11 -0500 Subject: [PATCH 36/49] Add action to ensure that web example compiles. --- .github/workflows/test.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 50d9534..65df44c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -82,3 +82,24 @@ jobs: with: command: apk args: build + + check_web_example: + name: Check Web Example + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: Swatinem/rust-cache@v1 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + components: rustfmt, clippy + override: true + - uses: actions-rs/install@v0.1 + with: + crate: cargo-make + - run: rustup target add wasm32-unknown-unknown + - uses: actions-rs/cargo@v1 + with: + command: make + args: From a879b3dca3696821781c7de96751b5192895aada Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Sat, 3 Apr 2021 11:58:23 -0500 Subject: [PATCH 37/49] Get web example compiling. --- examples/web/src/main.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/web/src/main.rs b/examples/web/src/main.rs index 5f35742..fb03c38 100644 --- a/examples/web/src/main.rs +++ b/examples/web/src/main.rs @@ -1,12 +1,12 @@ #![allow(clippy::wildcard_imports)] use seed::{prelude::*, *}; -use tts::TTS; +use tts::Tts; #[derive(Clone)] struct Model { text: String, - tts: TTS, + tts: Tts, } #[derive(Clone)] @@ -19,7 +19,7 @@ enum Msg { } fn init(_: Url, _: &mut impl Orders) -> Model { - let tts = TTS::default().unwrap(); + let tts = Tts::default().unwrap(); Model { text: Default::default(), tts, From 26d06fc635078aabc500b7e65100883529e9438f Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Sat, 3 Apr 2021 12:11:53 -0500 Subject: [PATCH 38/49] No really, build the web example. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 65df44c..699673a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -102,4 +102,4 @@ jobs: - uses: actions-rs/cargo@v1 with: command: make - args: + args: [build-web-example] From 316b1bceec72589b5953fbddddafe2750bb263b4 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Sat, 3 Apr 2021 12:58:19 -0500 Subject: [PATCH 39/49] Use target as part of toolchain installation. --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 699673a..550378b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -91,6 +91,7 @@ jobs: - uses: Swatinem/rust-cache@v1 - uses: actions-rs/toolchain@v1 with: + target: wasm32-unknown-unknown profile: minimal toolchain: stable components: rustfmt, clippy @@ -98,7 +99,6 @@ jobs: - uses: actions-rs/install@v0.1 with: crate: cargo-make - - run: rustup target add wasm32-unknown-unknown - uses: actions-rs/cargo@v1 with: command: make From e4b53d17aaf0f91cc48f90bf37173bd68c5ee929 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Sat, 3 Apr 2021 12:59:32 -0500 Subject: [PATCH 40/49] Check web example as part of release process. --- .github/workflows/release.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6bdc02d..2b0ea83 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -61,6 +61,13 @@ jobs: with: token: ${{ secrets.GITHUB_TOKEN }} args: --all-features --target wasm32-unknown-unknown + - uses: actions-rs/install@v0.1 + with: + crate: cargo-make + - uses: actions-rs/cargo@v1 + with: + command: make + args: [build-web-example] publish: name: Publish From 7b8da53d812d042cc7f445b0a521282a9764989e Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Mon, 5 Apr 2021 07:45:08 -0500 Subject: [PATCH 41/49] Args shouldn't be a list. --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2b0ea83..06b847b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -67,7 +67,7 @@ jobs: - uses: actions-rs/cargo@v1 with: command: make - args: [build-web-example] + args: build-web-example publish: name: Publish diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 550378b..ff68b02 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -102,4 +102,4 @@ jobs: - uses: actions-rs/cargo@v1 with: command: make - args: [build-web-example] + args: build-web-example From 4088eb12a172a70e581f5fb627e505bacbe34029 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 11 May 2021 19:37:56 -0500 Subject: [PATCH 42/49] Add ability to detect screen readers. Windows-only for now, and requires the `tolk` feature. --- examples/hello_world.rs | 5 +++++ src/lib.rs | 17 +++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/examples/hello_world.rs b/examples/hello_world.rs index f737f3f..1db3ed3 100644 --- a/examples/hello_world.rs +++ b/examples/hello_world.rs @@ -12,6 +12,11 @@ use tts::*; fn main() -> Result<(), Error> { env_logger::init(); let mut tts = Tts::default()?; + if Tts::screen_reader_available() { + println!("A screen reader is available on this platform."); + } else { + println!("No screen reader is available on this platform."); + } let Features { utterance_callbacks, .. diff --git a/src/lib.rs b/src/lib.rs index 1901556..50af8ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -527,6 +527,23 @@ impl Tts { Err(Error::UnsupportedFeature) } } + + /* + * Returns `true` if a screen reader is available to provide speech. + */ + pub fn screen_reader_available() -> bool { + if cfg!(target_os = "windows") { + #[cfg(feature = "tolk")] + { + let tolk = tolk::Tolk::new(); + return tolk.detect_screen_reader().is_some(); + } + #[cfg(not(feature = "tolk"))] + return false; + } else { + false + } + } } impl Drop for Tts { From 86b2e07f156e67bc591e0be24379d59395b9f132 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 11 May 2021 19:38:39 -0500 Subject: [PATCH 43/49] Bump version. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4c57063..0749349 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.16.0" +version = "0.17.0" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface" From 8f5f58028ac367ac4565e9b89c0e7b85da3d2dba Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 11 May 2021 20:18:14 -0500 Subject: [PATCH 44/49] Use attributes instead. --- src/lib.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 50af8ac..9b742a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -531,8 +531,10 @@ impl Tts { /* * Returns `true` if a screen reader is available to provide speech. */ + #[allow(unreachable_code)] pub fn screen_reader_available() -> bool { - if cfg!(target_os = "windows") { + #[cfg(target_os = "windows")] + { #[cfg(feature = "tolk")] { let tolk = tolk::Tolk::new(); @@ -540,9 +542,8 @@ impl Tts { } #[cfg(not(feature = "tolk"))] return false; - } else { - false } + false } } From d67bf8344a24ac233258186e0ec2dd96b06981dd Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 11 May 2021 20:21:03 -0500 Subject: [PATCH 45/49] Bump dependencies. --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0749349..496e772 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,10 +22,10 @@ env_logger = "0.8" [target.'cfg(windows)'.dependencies] tolk = { version = "0.3", optional = true } -windows = "0.7" +windows = "0.9" [target.'cfg(windows)'.build-dependencies] -windows = "0.7" +windows = "0.9" [target.'cfg(target_os = "linux")'.dependencies] speech-dispatcher = "0.7" From d85d56c3eeed548832cf3806b1e23e40e63814db Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Tue, 11 May 2021 23:53:15 -0500 Subject: [PATCH 46/49] Bump version to work around Tolk crash. --- Cargo.toml | 4 ++-- src/backends/tolk.rs | 2 +- src/lib.rs | 3 +-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 496e772..229c438 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.17.0" +version = "0.17.1" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface" @@ -21,7 +21,7 @@ thiserror = "1" env_logger = "0.8" [target.'cfg(windows)'.dependencies] -tolk = { version = "0.3", optional = true } +tolk = { version = "0.4", optional = true } windows = "0.9" [target.'cfg(windows)'.build-dependencies] diff --git a/src/backends/tolk.rs b/src/backends/tolk.rs index ae16e4f..9b93a5e 100644 --- a/src/backends/tolk.rs +++ b/src/backends/tolk.rs @@ -11,7 +11,7 @@ impl Tolk { pub(crate) fn new() -> Option { info!("Initializing Tolk backend"); let tolk = TolkPtr::new(); - if tolk.detect_screen_reader().is_some() { + if tolk::Tolk::detect_screen_reader().is_some() { Some(Tolk(tolk)) } else { None diff --git a/src/lib.rs b/src/lib.rs index 9b742a7..6c0b5f8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -537,8 +537,7 @@ impl Tts { { #[cfg(feature = "tolk")] { - let tolk = tolk::Tolk::new(); - return tolk.detect_screen_reader().is_some(); + return tolk::Tolk::detect_screen_reader().is_some(); } #[cfg(not(feature = "tolk"))] return false; From ca7789f157fa96ce06ffced8309e6ef043dfee23 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 20 May 2021 13:59:02 -0500 Subject: [PATCH 47/49] Bump version and Tolk dependency. --- Cargo.toml | 4 ++-- src/backends/tolk.rs | 6 ++++-- src/lib.rs | 5 ++++- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 229c438..bc3795d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.17.1" +version = "0.17.2" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface" @@ -21,7 +21,7 @@ thiserror = "1" env_logger = "0.8" [target.'cfg(windows)'.dependencies] -tolk = { version = "0.4", optional = true } +tolk = { version = "0.5", optional = true } windows = "0.9" [target.'cfg(windows)'.build-dependencies] diff --git a/src/backends/tolk.rs b/src/backends/tolk.rs index 9b93a5e..51431a8 100644 --- a/src/backends/tolk.rs +++ b/src/backends/tolk.rs @@ -1,17 +1,19 @@ #[cfg(all(windows, feature = "tolk"))] +use std::sync::Arc; + use log::{info, trace}; use tolk::Tolk as TolkPtr; use crate::{Backend, BackendId, Error, Features, UtteranceId}; #[derive(Clone, Debug)] -pub(crate) struct Tolk(TolkPtr); +pub(crate) struct Tolk(Arc); impl Tolk { pub(crate) fn new() -> Option { info!("Initializing Tolk backend"); let tolk = TolkPtr::new(); - if tolk::Tolk::detect_screen_reader().is_some() { + if tolk.detect_screen_reader().is_some() { Some(Tolk(tolk)) } else { None diff --git a/src/lib.rs b/src/lib.rs index 6c0b5f8..d62c245 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -27,6 +27,8 @@ use libc::c_char; #[cfg(target_os = "macos")] use objc::{class, msg_send, sel, sel_impl}; use thiserror::Error; +#[cfg(all(windows, feature = "tolk"))] +use tolk::Tolk; mod backends; @@ -537,7 +539,8 @@ impl Tts { { #[cfg(feature = "tolk")] { - return tolk::Tolk::detect_screen_reader().is_some(); + let tolk = Tolk::new(); + return tolk.detect_screen_reader().is_some(); } #[cfg(not(feature = "tolk"))] return false; From c4038149a8b561ec72fd7f36de01772afa9737bc Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 20 May 2021 17:07:55 -0500 Subject: [PATCH 48/49] Remove a conditional that blocked playback in some circumstances on the WinRT backend. --- src/backends/winrt/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/backends/winrt/mod.rs b/src/backends/winrt/mod.rs index 9b2d0f0..af9ca34 100644 --- a/src/backends/winrt/mod.rs +++ b/src/backends/winrt/mod.rs @@ -11,7 +11,7 @@ use bindings::Windows::{ Foundation::TypedEventHandler, Media::{ Core::MediaSource, - Playback::{MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory}, + Playback::{MediaPlayer, MediaPlayerAudioCategory}, SpeechSynthesis::SpeechSynthesizer, }, }; @@ -181,9 +181,7 @@ impl Backend for WinRt { utterances.push_back(utterance); } } - if no_utterances - && self.player.PlaybackSession()?.PlaybackState()? != MediaPlaybackState::Playing - { + if no_utterances { self.synth.Options()?.SetSpeakingRate(self.rate.into())?; self.synth.Options()?.SetAudioPitch(self.pitch.into())?; self.synth.Options()?.SetAudioVolume(self.volume.into())?; From dc3129b79c917f509d81495ade1b27f6f0cf8e03 Mon Sep 17 00:00:00 2001 From: Nolan Darilek Date: Thu, 20 May 2021 17:08:23 -0500 Subject: [PATCH 49/49] Bump version. --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index bc3795d..fcf5bfd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tts" -version = "0.17.2" +version = "0.17.3" authors = ["Nolan Darilek "] repository = "https://github.com/ndarilek/tts-rs" description = "High-level Text-To-Speech (TTS) interface"