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:
commit
9ab38f550f
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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(())
|
||||||
},
|
},
|
||||||
))?;
|
))?;
|
||||||
|
|
12
src/lib.rs
12
src/lib.rs
|
@ -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);
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
include!(concat!(env!("OUT_DIR"), "/winrt.rs"));
|
::windows::include_bindings!();
|
||||||
|
|
Loading…
Reference in New Issue
Block a user