mirror of https://github.com/ndarilek/tts-rs.git
Bump Windows dependency and update accordingly. Also, fix an acronym Clippy warning.
This commit is contained in:
parent
acccdfeada
commit
ef96042b12
|
@ -22,10 +22,10 @@ env_logger = "0.8"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
tolk = { version = "0.3", optional = true }
|
tolk = { version = "0.3", optional = true }
|
||||||
windows = "0.4"
|
windows = "0.7"
|
||||||
|
|
||||||
[target.'cfg(windows)'.build-dependencies]
|
[target.'cfg(windows)'.build-dependencies]
|
||||||
windows = "0.4"
|
windows = "0.7"
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
speech-dispatcher = "0.7"
|
speech-dispatcher = "0.7"
|
||||||
|
|
10
build.rs
10
build.rs
|
@ -2,11 +2,11 @@ fn main() {
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
if std::env::var("TARGET").unwrap().contains("windows") {
|
if std::env::var("TARGET").unwrap().contains("windows") {
|
||||||
windows::build!(
|
windows::build!(
|
||||||
windows::foundation::{EventRegistrationToken, IAsyncOperation, TypedEventHandler},
|
Windows::Foundation::{EventRegistrationToken, IAsyncOperation, TypedEventHandler},
|
||||||
windows::media::core::MediaSource,
|
Windows::Media::Core::MediaSource,
|
||||||
windows::media::playback::{MediaPlaybackSession, MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory},
|
Windows::Media::Playback::{MediaPlaybackSession, MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory},
|
||||||
windows::media::speech_synthesis::{SpeechSynthesisStream, SpeechSynthesizer, SpeechSynthesizerOptions},
|
Windows::Media::SpeechSynthesis::{SpeechSynthesisStream, SpeechSynthesizer, SpeechSynthesizerOptions},
|
||||||
windows::storage::streams::IRandomAccessStream,
|
Windows::Storage::Streams::IRandomAccessStream,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if std::env::var("TARGET").unwrap().contains("-apple") {
|
if std::env::var("TARGET").unwrap().contains("-apple") {
|
||||||
|
|
|
@ -7,12 +7,12 @@ use log::{info, trace};
|
||||||
|
|
||||||
mod bindings;
|
mod bindings;
|
||||||
|
|
||||||
use bindings::windows::{
|
use bindings::Windows::{
|
||||||
foundation::TypedEventHandler,
|
Foundation::TypedEventHandler,
|
||||||
media::{
|
Media::{
|
||||||
core::MediaSource,
|
Core::MediaSource,
|
||||||
playback::{MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory},
|
Playback::{MediaPlaybackState, MediaPlayer, MediaPlayerAudioCategory},
|
||||||
speech_synthesis::SpeechSynthesizer,
|
SpeechSynthesis::SpeechSynthesizer,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -20,12 +20,12 @@ use crate::{Backend, BackendId, Error, Features, UtteranceId, CALLBACKS};
|
||||||
|
|
||||||
impl From<windows::Error> for Error {
|
impl From<windows::Error> for Error {
|
||||||
fn from(e: windows::Error) -> Self {
|
fn from(e: windows::Error) -> Self {
|
||||||
Error::WinRT(e)
|
Error::WinRt(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct WinRT {
|
pub struct WinRt {
|
||||||
id: BackendId,
|
id: BackendId,
|
||||||
synth: SpeechSynthesizer,
|
synth: SpeechSynthesizer,
|
||||||
player: MediaPlayer,
|
player: MediaPlayer,
|
||||||
|
@ -59,15 +59,15 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinRT {
|
impl WinRt {
|
||||||
pub fn new() -> std::result::Result<Self, Error> {
|
pub fn new() -> std::result::Result<Self, Error> {
|
||||||
info!("Initializing WinRT backend");
|
info!("Initializing WinRT backend");
|
||||||
let synth = SpeechSynthesizer::new()?;
|
let synth = SpeechSynthesizer::new()?;
|
||||||
let player = MediaPlayer::new()?;
|
let player = MediaPlayer::new()?;
|
||||||
player.set_real_time_playback(true)?;
|
player.SetRealTimePlayback(true)?;
|
||||||
player.set_audio_category(MediaPlayerAudioCategory::Speech)?;
|
player.SetAudioCategory(MediaPlayerAudioCategory::Speech)?;
|
||||||
let mut backend_id = NEXT_BACKEND_ID.lock().unwrap();
|
let mut backend_id = NEXT_BACKEND_ID.lock().unwrap();
|
||||||
let bid = BackendId::WinRT(*backend_id);
|
let bid = BackendId::WinRt(*backend_id);
|
||||||
*backend_id += 1;
|
*backend_id += 1;
|
||||||
drop(backend_id);
|
drop(backend_id);
|
||||||
{
|
{
|
||||||
|
@ -81,7 +81,7 @@ impl WinRT {
|
||||||
backend_to_speech_synthesizer.insert(bid, synth.clone());
|
backend_to_speech_synthesizer.insert(bid, synth.clone());
|
||||||
drop(backend_to_speech_synthesizer);
|
drop(backend_to_speech_synthesizer);
|
||||||
let bid_clone = bid;
|
let bid_clone = bid;
|
||||||
player.media_ended(TypedEventHandler::new(
|
player.MediaEnded(TypedEventHandler::new(
|
||||||
move |sender: &Option<MediaPlayer>, _args| {
|
move |sender: &Option<MediaPlayer>, _args| {
|
||||||
if let Some(sender) = sender {
|
if let Some(sender) = sender {
|
||||||
let backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap();
|
let backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap();
|
||||||
|
@ -102,19 +102,17 @@ impl WinRT {
|
||||||
.iter()
|
.iter()
|
||||||
.find(|v| *v.0 == bid_clone);
|
.find(|v| *v.0 == bid_clone);
|
||||||
if let Some((_, tts)) = id {
|
if let Some((_, tts)) = id {
|
||||||
tts.options()?.set_speaking_rate(utterance.rate.into())?;
|
tts.Options()?.SetSpeakingRate(utterance.rate.into())?;
|
||||||
tts.options()?.set_audio_pitch(utterance.pitch.into())?;
|
tts.Options()?.SetAudioPitch(utterance.pitch.into())?;
|
||||||
tts.options()?.set_audio_volume(utterance.volume.into())?;
|
tts.Options()?.SetAudioVolume(utterance.volume.into())?;
|
||||||
let stream = tts
|
let stream = tts
|
||||||
.synthesize_text_to_stream_async(
|
.SynthesizeTextToStreamAsync(utterance.text.as_str())?
|
||||||
utterance.text.as_str(),
|
|
||||||
)?
|
|
||||||
.get()?;
|
.get()?;
|
||||||
let content_type = stream.content_type()?;
|
let content_type = stream.ContentType()?;
|
||||||
let source =
|
let source =
|
||||||
MediaSource::create_from_stream(stream, content_type)?;
|
MediaSource::CreateFromStream(stream, content_type)?;
|
||||||
sender.set_source(source)?;
|
sender.SetSource(source)?;
|
||||||
sender.play()?;
|
sender.Play()?;
|
||||||
if let Some(callback) = callbacks.utterance_begin.as_mut() {
|
if let Some(callback) = callbacks.utterance_begin.as_mut() {
|
||||||
callback(utterance.id);
|
callback(utterance.id);
|
||||||
}
|
}
|
||||||
|
@ -138,7 +136,7 @@ impl WinRT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend for WinRT {
|
impl Backend for WinRt {
|
||||||
fn id(&self) -> Option<BackendId> {
|
fn id(&self) -> Option<BackendId> {
|
||||||
Some(self.id)
|
Some(self.id)
|
||||||
}
|
}
|
||||||
|
@ -164,7 +162,7 @@ impl Backend for WinRT {
|
||||||
}
|
}
|
||||||
let utterance_id = {
|
let utterance_id = {
|
||||||
let mut uid = NEXT_UTTERANCE_ID.lock().unwrap();
|
let mut uid = NEXT_UTTERANCE_ID.lock().unwrap();
|
||||||
let utterance_id = UtteranceId::WinRT(*uid);
|
let utterance_id = UtteranceId::WinRt(*uid);
|
||||||
*uid += 1;
|
*uid += 1;
|
||||||
utterance_id
|
utterance_id
|
||||||
};
|
};
|
||||||
|
@ -184,16 +182,16 @@ impl Backend for WinRT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if no_utterances
|
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()?.SetSpeakingRate(self.rate.into())?;
|
||||||
self.synth.options()?.set_audio_pitch(self.pitch.into())?;
|
self.synth.Options()?.SetAudioPitch(self.pitch.into())?;
|
||||||
self.synth.options()?.set_audio_volume(self.volume.into())?;
|
self.synth.Options()?.SetAudioVolume(self.volume.into())?;
|
||||||
let stream = self.synth.synthesize_text_to_stream_async(text)?.get()?;
|
let stream = self.synth.SynthesizeTextToStreamAsync(text)?.get()?;
|
||||||
let content_type = stream.content_type()?;
|
let content_type = stream.ContentType()?;
|
||||||
let source = MediaSource::create_from_stream(stream, content_type)?;
|
let source = MediaSource::CreateFromStream(stream, content_type)?;
|
||||||
self.player.set_source(source)?;
|
self.player.SetSource(source)?;
|
||||||
self.player.play()?;
|
self.player.Play()?;
|
||||||
let mut callbacks = CALLBACKS.lock().unwrap();
|
let mut callbacks = CALLBACKS.lock().unwrap();
|
||||||
let callbacks = callbacks.get_mut(&self.id).unwrap();
|
let callbacks = callbacks.get_mut(&self.id).unwrap();
|
||||||
if let Some(callback) = callbacks.utterance_begin.as_mut() {
|
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) {
|
if let Some(utterances) = utterances.get_mut(&self.id) {
|
||||||
utterances.clear();
|
utterances.clear();
|
||||||
}
|
}
|
||||||
self.player.pause()?;
|
self.player.Pause()?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,7 +236,7 @@ impl Backend for WinRT {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_rate(&self) -> std::result::Result<f32, Error> {
|
fn get_rate(&self) -> std::result::Result<f32, Error> {
|
||||||
let rate = self.synth.options()?.speaking_rate()?;
|
let rate = self.synth.Options()?.SpeakingRate()?;
|
||||||
Ok(rate as f32)
|
Ok(rate as f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +258,7 @@ impl Backend for WinRT {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pitch(&self) -> std::result::Result<f32, Error> {
|
fn get_pitch(&self) -> std::result::Result<f32, Error> {
|
||||||
let pitch = self.synth.options()?.audio_pitch()?;
|
let pitch = self.synth.Options()?.AudioPitch()?;
|
||||||
Ok(pitch as f32)
|
Ok(pitch as f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +280,7 @@ impl Backend for WinRT {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_volume(&self) -> std::result::Result<f32, Error> {
|
fn get_volume(&self) -> std::result::Result<f32, Error> {
|
||||||
let volume = self.synth.options()?.audio_volume()?;
|
let volume = self.synth.Options()?.AudioVolume()?;
|
||||||
Ok(volume as f32)
|
Ok(volume as f32)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,7 +296,7 @@ impl Backend for WinRT {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for WinRT {
|
impl Drop for WinRt {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let id = self.id;
|
let id = self.id;
|
||||||
let mut backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap();
|
let mut backend_to_media_player = BACKEND_TO_MEDIA_PLAYER.lock().unwrap();
|
||||||
|
|
18
src/lib.rs
18
src/lib.rs
|
@ -39,7 +39,7 @@ pub enum Backends {
|
||||||
#[cfg(all(windows, feature = "tolk"))]
|
#[cfg(all(windows, feature = "tolk"))]
|
||||||
Tolk,
|
Tolk,
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
WinRT,
|
WinRt,
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
AppKit,
|
AppKit,
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
|
@ -55,7 +55,7 @@ pub enum BackendId {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
Web(u64),
|
Web(u64),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
WinRT(u64),
|
WinRt(u64),
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
AvFoundation(u64),
|
AvFoundation(u64),
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
|
@ -69,7 +69,7 @@ pub enum UtteranceId {
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
Web(u64),
|
Web(u64),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
WinRT(u64),
|
WinRt(u64),
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
AvFoundation(id),
|
AvFoundation(id),
|
||||||
#[cfg(target_os = "android")]
|
#[cfg(target_os = "android")]
|
||||||
|
@ -105,7 +105,7 @@ impl Default for Features {
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("IO error: {0}")]
|
#[error("IO error: {0}")]
|
||||||
IO(#[from] std::io::Error),
|
Io(#[from] std::io::Error),
|
||||||
#[error("Value not received")]
|
#[error("Value not received")]
|
||||||
NoneError,
|
NoneError,
|
||||||
#[error("Operation failed")]
|
#[error("Operation failed")]
|
||||||
|
@ -115,7 +115,7 @@ pub enum Error {
|
||||||
JavaScriptError(wasm_bindgen::JsValue),
|
JavaScriptError(wasm_bindgen::JsValue),
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
#[error("WinRT error")]
|
#[error("WinRT error")]
|
||||||
WinRT(windows::Error),
|
WinRt(windows::Error),
|
||||||
#[error("Unsupported feature")]
|
#[error("Unsupported feature")]
|
||||||
UnsupportedFeature,
|
UnsupportedFeature,
|
||||||
#[error("Out of range")]
|
#[error("Out of range")]
|
||||||
|
@ -197,8 +197,8 @@ impl TTS {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
Backends::WinRT => {
|
Backends::WinRt => {
|
||||||
let tts = backends::WinRT::new()?;
|
let tts = backends::WinRt::new()?;
|
||||||
Ok(TTS(Box::new(tts)))
|
Ok(TTS(Box::new(tts)))
|
||||||
}
|
}
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
@ -229,10 +229,10 @@ impl TTS {
|
||||||
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 = "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);
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
|
|
Loading…
Reference in New Issue