1
0
mirror of https://github.com/ndarilek/tts-rs.git synced 2024-11-25 12:19:38 +00:00

Merge branch 'master' into c-ffi

This commit is contained in:
mcb2003 2021-03-06 08:59:25 +00:00
commit 9ab38f550f
9 changed files with 59 additions and 76 deletions

View File

@ -1,6 +1,6 @@
[package] [package]
name = "tts" name = "tts"
version = "0.13.1" version = "0.14.0"
authors = ["Nolan Darilek <nolan@thewordnerd.info>"] authors = ["Nolan Darilek <nolan@thewordnerd.info>"]
repository = "https://github.com/ndarilek/tts-rs" repository = "https://github.com/ndarilek/tts-rs"
description = "High-level Text-To-Speech (TTS) interface" description = "High-level Text-To-Speech (TTS) interface"
@ -27,8 +27,8 @@ env_logger = "0.8"
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
tolk = { version = "0.3", optional = true } tolk = { version = "0.3", optional = true }
winrt = "0.7" windows = "0.2"
tts_winrt_bindings = { version = "0.2", path="winrt_bindings" } tts_winrt_bindings = { version = "0.3", path="winrt_bindings" }
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
speech-dispatcher = "0.7" speech-dispatcher = "0.7"
@ -44,4 +44,4 @@ web-sys = { version = "0.3", features = ["EventTarget", "SpeechSynthesis", "Spee
[target.'cfg(target_os="android")'.dependencies] [target.'cfg(target_os="android")'.dependencies]
jni = "0.18" jni = "0.18"
ndk-glue = "0.2" ndk-glue = "0.2"

View File

@ -3,7 +3,7 @@
This library provides a high-level Text-To-Speech (TTS) interface supporting various backends. Currently supported backends are: This library provides a high-level Text-To-Speech (TTS) interface supporting various backends. Currently supported backends are:
* Windows * Windows
* Screen readers/SAPI via Tolk (requires `use_tolk` Cargo feature) * Screen readers/SAPI via Tolk (requires `tolk` Cargo feature)
* WinRT * WinRT
* Linux via [Speech Dispatcher](https://freebsoft.org/speechd) * Linux via [Speech Dispatcher](https://freebsoft.org/speechd)
* MacOS/iOS * MacOS/iOS

View File

@ -1,7 +1,7 @@
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
mod speech_dispatcher; mod speech_dispatcher;
#[cfg(all(windows, feature = "use_tolk"))] #[cfg(all(windows, feature = "tolk"))]
mod tolk; mod tolk;
#[cfg(windows)] #[cfg(windows)]
@ -23,7 +23,7 @@ mod android;
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
pub(crate) use self::speech_dispatcher::*; pub(crate) use self::speech_dispatcher::*;
#[cfg(all(windows, feature = "use_tolk"))] #[cfg(all(windows, feature = "tolk"))]
pub(crate) use self::tolk::*; pub(crate) use self::tolk::*;
#[cfg(windows)] #[cfg(windows)]

View File

@ -1,4 +1,4 @@
#[cfg(all(windows, feature = "use_tolk"))] #[cfg(all(windows, feature = "tolk"))]
use log::{info, trace}; use log::{info, trace};
use tolk::Tolk as TolkPtr; use tolk::Tolk as TolkPtr;

View File

@ -13,8 +13,8 @@ use tts_winrt_bindings::windows::{foundation::TypedEventHandler, media::core::Me
use crate::{Backend, BackendId, Error, Features, UtteranceId, CALLBACKS}; use crate::{Backend, BackendId, Error, Features, UtteranceId, CALLBACKS};
impl From<winrt::Error> for Error { impl From<windows::Error> for Error {
fn from(e: winrt::Error) -> Self { fn from(e: windows::Error) -> Self {
Error::WinRT(e) Error::WinRT(e)
} }
} }
@ -77,60 +77,48 @@ impl WinRT {
drop(backend_to_speech_synthesizer); drop(backend_to_speech_synthesizer);
let bid_clone = bid; let bid_clone = bid;
player.media_ended(TypedEventHandler::new( player.media_ended(TypedEventHandler::new(
move |sender: &MediaPlayer, _args| { move |sender: &Option<MediaPlayer>, _args| {
let backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap(); if let Some(sender) = sender {
let id = backend_to_media_player.iter().find(|v| v.1 == sender); let backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap();
if let Some((id, _)) = id { let id = backend_to_media_player.iter().find(|v| v.1 == sender);
let mut utterances = UTTERANCES.lock().unwrap(); if let Some((id, _)) = id {
if let Some(utterances) = utterances.get_mut(id) { let mut utterances = UTTERANCES.lock().unwrap();
if let Some(utterance) = utterances.pop_front() { if let Some(utterances) = utterances.get_mut(id) {
let mut callbacks = CALLBACKS.lock().unwrap(); if let Some(utterance) = utterances.pop_front() {
let callbacks = callbacks.get_mut(id).unwrap(); let mut callbacks = CALLBACKS.lock().unwrap();
if let Some(callback) = callbacks.utterance_end.as_mut() { let callbacks = callbacks.get_mut(id).unwrap();
callback(utterance.id); if let Some(callback) = callbacks.utterance_end.as_mut() {
} callback(utterance.id);
if let Some(utterance) = utterances.front() { }
let backend_to_speech_synthesizer = if let Some(utterance) = utterances.front() {
BACKEND_TO_SPEECH_SYNTHESIZER.lock().unwrap(); let backend_to_speech_synthesizer =
let id = backend_to_speech_synthesizer BACKEND_TO_SPEECH_SYNTHESIZER.lock().unwrap();
.iter() let id = backend_to_speech_synthesizer
.find(|v| *v.0 == bid_clone); .iter()
if let Some((_, tts)) = id { .find(|v| *v.0 == bid_clone);
tts.options()?.set_speaking_rate(utterance.rate.into())?; if let Some((_, tts)) = id {
tts.options()?.set_audio_pitch(utterance.pitch.into())?; tts.options()?.set_speaking_rate(utterance.rate.into())?;
tts.options()?.set_audio_volume(utterance.volume.into())?; tts.options()?.set_audio_pitch(utterance.pitch.into())?;
let stream = tts tts.options()?.set_audio_volume(utterance.volume.into())?;
.synthesize_text_to_stream_async(utterance.text.as_str())? let stream = tts
.get()?; .synthesize_text_to_stream_async(
let content_type = stream.content_type()?; utterance.text.as_str(),
let source = )?
MediaSource::create_from_stream(stream, content_type)?; .get()?;
sender.set_source(source)?; let content_type = stream.content_type()?;
sender.play()?; let source =
if let Some(callback) = callbacks.utterance_begin.as_mut() { MediaSource::create_from_stream(stream, content_type)?;
callback(utterance.id); sender.set_source(source)?;
sender.play()?;
if let Some(callback) = callbacks.utterance_begin.as_mut() {
callback(utterance.id);
}
} }
} }
} }
} }
} }
} }
/*let source = sender.source()?;
let source: MediaPlaybackList = source.try_into()?;
source.items()?.clear()?;
let backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap();
let id = backend_to_media_player.iter().find(|v| v.1 == sender);
if let Some(id) = id {
let id = id.0;
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);
}
}
}*/
Ok(()) Ok(())
}, },
))?; ))?;

View File

@ -2,7 +2,7 @@
* a Text-To-Speech (TTS) library providing high-level interfaces to a variety of backends. * a Text-To-Speech (TTS) library providing high-level interfaces to a variety of backends.
* Currently supported backends are: * Currently supported backends are:
* * Windows * * Windows
* * Screen readers/SAPI via Tolk (requires `use_tolk` Cargo feature) * * Screen readers/SAPI via Tolk (requires `tolk` Cargo feature)
* * WinRT * * WinRT
* * Linux via [Speech Dispatcher](https://freebsoft.org/speechd) * * Linux via [Speech Dispatcher](https://freebsoft.org/speechd)
* * MacOS/iOS * * MacOS/iOS
@ -39,7 +39,7 @@ pub enum Backends {
SpeechDispatcher, SpeechDispatcher,
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
Web, Web,
#[cfg(all(windows, feature = "use_tolk"))] #[cfg(all(windows, feature = "tolk"))]
Tolk, Tolk,
#[cfg(windows)] #[cfg(windows)]
WinRT, WinRT,
@ -119,7 +119,7 @@ pub enum Error {
JavaScriptError(wasm_bindgen::JsValue), JavaScriptError(wasm_bindgen::JsValue),
#[cfg(windows)] #[cfg(windows)]
#[error("WinRT error")] #[error("WinRT error")]
WinRT(winrt::Error), WinRT(windows::Error),
#[error("Unsupported feature")] #[error("Unsupported feature")]
UnsupportedFeature, UnsupportedFeature,
#[error("Out of range")] #[error("Out of range")]
@ -191,7 +191,7 @@ impl TTS {
let tts = backends::Web::new()?; let tts = backends::Web::new()?;
Ok(TTS(Box::new(tts))) Ok(TTS(Box::new(tts)))
} }
#[cfg(all(windows, feature = "use_tolk"))] #[cfg(all(windows, feature = "tolk"))]
Backends::Tolk => { Backends::Tolk => {
let tts = backends::Tolk::new(); let tts = backends::Tolk::new();
if let Some(tts) = tts { if let Some(tts) = tts {
@ -229,13 +229,13 @@ impl TTS {
pub fn default() -> Result<TTS, Error> { pub fn default() -> Result<TTS, Error> {
#[cfg(target_os = "linux")] #[cfg(target_os = "linux")]
let tts = TTS::new(Backends::SpeechDispatcher); let tts = TTS::new(Backends::SpeechDispatcher);
#[cfg(all(windows, feature = "use_tolk"))] #[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) Ok(tts)
} else { } else {
TTS::new(Backends::WinRT) TTS::new(Backends::WinRT)
}; };
#[cfg(all(windows, not(feature = "use_tolk")))] #[cfg(all(windows, not(feature = "tolk")))]
let tts = TTS::new(Backends::WinRT); let tts = TTS::new(Backends::WinRT);
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
let tts = TTS::new(Backends::Web); let tts = TTS::new(Backends::Web);

View File

@ -1,13 +1,13 @@
[package] [package]
name = "tts_winrt_bindings" name = "tts_winrt_bindings"
version = "0.2.0" version = "0.3.0"
authors = ["Nolan Darilek <nolan@thewordnerd.info>"] authors = ["Nolan Darilek <nolan@thewordnerd.info>"]
description = "Internal crate used by `tts`" description = "Internal crate used by `tts`"
license = "MIT" license = "MIT"
edition = "2018" edition = "2018"
[dependencies] [dependencies]
winrt = "0.7" windows = "0.2"
[build-dependencies] [build-dependencies]
winrt = "0.7" windows = "0.2"

View File

@ -1,12 +1,7 @@
winrt::build!( fn main() {
dependencies windows::build!(
os
types
windows::media::core::MediaSource windows::media::core::MediaSource
windows::media::playback::{MediaPlaybackState, MediaPlayer} windows::media::playback::{MediaPlaybackState, MediaPlayer}
windows::media::speech_synthesis::SpeechSynthesizer windows::media::speech_synthesis::SpeechSynthesizer
); );
fn main() {
build();
} }

View File

@ -1 +1 @@
include!(concat!(env!("OUT_DIR"), "/winrt.rs")); ::windows::include_bindings!();