mirror of https://github.com/ndarilek/tts-rs.git
Use plain 'ol struct.
This commit is contained in:
parent
1e55c43153
commit
142f2e6b3a
|
@ -1,15 +1,12 @@
|
||||||
use std::str::FromStr;
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use std::{collections::HashMap, sync::Mutex};
|
use std::{collections::HashMap, str::FromStr, sync::Mutex};
|
||||||
|
|
||||||
use lazy_static::*;
|
use lazy_static::*;
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
use speech_dispatcher::{Voice as SpdVoice, *};
|
use speech_dispatcher::*;
|
||||||
use unic_langid::{LanguageIdentifier, LanguageIdentifierError};
|
use unic_langid::LanguageIdentifier;
|
||||||
|
|
||||||
use crate::{
|
use crate::{Backend, BackendId, Error, Features, Gender, UtteranceId, Voice, CALLBACKS};
|
||||||
Backend, BackendId, Error, Features, Gender, UtteranceId, Voice, VoiceImpl, CALLBACKS,
|
|
||||||
};
|
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct SpeechDispatcher(Connection);
|
pub(crate) struct SpeechDispatcher(Connection);
|
||||||
|
@ -21,24 +18,6 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VoiceImpl for SpdVoice {
|
|
||||||
fn id(self) -> String {
|
|
||||||
self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(self) -> String {
|
|
||||||
self.name
|
|
||||||
}
|
|
||||||
|
|
||||||
fn gender(self) -> Gender {
|
|
||||||
Gender::Other
|
|
||||||
}
|
|
||||||
|
|
||||||
fn language(self) -> Result<LanguageIdentifier, LanguageIdentifierError> {
|
|
||||||
LanguageIdentifier::from_str(&self.language)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl SpeechDispatcher {
|
impl SpeechDispatcher {
|
||||||
pub(crate) fn new() -> std::result::Result<Self, Error> {
|
pub(crate) fn new() -> std::result::Result<Self, Error> {
|
||||||
info!("Initializing SpeechDispatcher backend");
|
info!("Initializing SpeechDispatcher backend");
|
||||||
|
@ -91,7 +70,7 @@ impl SpeechDispatcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Backend<SpdVoice> for SpeechDispatcher {
|
impl Backend for SpeechDispatcher {
|
||||||
fn id(&self) -> Option<BackendId> {
|
fn id(&self) -> Option<BackendId> {
|
||||||
Some(BackendId::SpeechDispatcher(self.0.client_id()))
|
Some(BackendId::SpeechDispatcher(self.0.client_id()))
|
||||||
}
|
}
|
||||||
|
@ -203,14 +182,18 @@ impl Backend<SpdVoice> for SpeechDispatcher {
|
||||||
Ok(*is_speaking)
|
Ok(*is_speaking)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn voices(&self) -> Result<Vec<Voice<SpdVoice>>, Error> {
|
fn voices(&self) -> Result<Vec<Voice>, Error> {
|
||||||
let rv = self
|
let rv = self
|
||||||
.0
|
.0
|
||||||
.list_synthesis_voices()?
|
.list_synthesis_voices()?
|
||||||
.iter()
|
.iter()
|
||||||
.cloned()
|
.map(|v| Voice {
|
||||||
.map(|v| Voice(Box::new(v)))
|
id: v.name.clone(),
|
||||||
.collect::<Vec<Voice<SpdVoice>>>();
|
name: v.name.clone(),
|
||||||
|
gender: Gender::Unspecified,
|
||||||
|
language: LanguageIdentifier::from_str(&v.language).unwrap(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<Voice>>();
|
||||||
Ok(rv)
|
Ok(rv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
38
src/lib.rs
38
src/lib.rs
|
@ -16,7 +16,6 @@ use std::collections::HashMap;
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
use std::ffi::CStr;
|
use std::ffi::CStr;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::{boxed::Box, sync::RwLock};
|
use std::{boxed::Box, sync::RwLock};
|
||||||
|
|
||||||
|
@ -34,7 +33,6 @@ use thiserror::Error;
|
||||||
#[cfg(all(windows, feature = "tolk"))]
|
#[cfg(all(windows, feature = "tolk"))]
|
||||||
use tolk::Tolk;
|
use tolk::Tolk;
|
||||||
pub use unic_langid::LanguageIdentifier;
|
pub use unic_langid::LanguageIdentifier;
|
||||||
use unic_langid::LanguageIdentifierError;
|
|
||||||
|
|
||||||
mod backends;
|
mod backends;
|
||||||
|
|
||||||
|
@ -211,7 +209,7 @@ pub enum Error {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[clonable]
|
#[clonable]
|
||||||
pub trait Backend<T: VoiceImpl>: Clone {
|
pub trait Backend: Clone {
|
||||||
fn id(&self) -> Option<BackendId>;
|
fn id(&self) -> Option<BackendId>;
|
||||||
fn supported_features(&self) -> Features;
|
fn supported_features(&self) -> Features;
|
||||||
fn speak(&mut self, text: &str, interrupt: bool) -> Result<Option<UtteranceId>, Error>;
|
fn speak(&mut self, text: &str, interrupt: bool) -> Result<Option<UtteranceId>, Error>;
|
||||||
|
@ -232,7 +230,7 @@ pub trait Backend<T: VoiceImpl>: Clone {
|
||||||
fn get_volume(&self) -> Result<f32, Error>;
|
fn get_volume(&self) -> Result<f32, Error>;
|
||||||
fn set_volume(&mut self, volume: f32) -> Result<(), Error>;
|
fn set_volume(&mut self, volume: f32) -> Result<(), Error>;
|
||||||
fn is_speaking(&self) -> Result<bool, Error>;
|
fn is_speaking(&self) -> Result<bool, Error>;
|
||||||
fn voices(&self) -> Result<Vec<Voice<T>>, Error>;
|
fn voices(&self) -> Result<Vec<Voice>, Error>;
|
||||||
fn voice(&self) -> Result<String, Error>;
|
fn voice(&self) -> Result<String, Error>;
|
||||||
fn set_voice(&mut self, voice: &str) -> Result<(), Error>;
|
fn set_voice(&mut self, voice: &str) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
@ -256,22 +254,22 @@ lazy_static! {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Tts<T: VoiceImpl>(Arc<RwLock<Box<dyn Backend<T>>>>, PhantomData<T>);
|
pub struct Tts(Arc<RwLock<Box<dyn Backend>>>);
|
||||||
|
|
||||||
unsafe impl<T: VoiceImpl> Send for Tts<T> {}
|
unsafe impl Send for Tts {}
|
||||||
|
|
||||||
unsafe impl<T: VoiceImpl> Sync for Tts<T> {}
|
unsafe impl Sync for Tts {}
|
||||||
|
|
||||||
impl<T: VoiceImpl> Tts<T> {
|
impl Tts {
|
||||||
/**
|
/**
|
||||||
* Create a new `TTS` instance with the specified backend.
|
* Create a new `TTS` instance with the specified backend.
|
||||||
*/
|
*/
|
||||||
pub fn new(backend: Backends) -> Result<Tts<T>, Error> {
|
pub fn new(backend: Backends) -> Result<Tts, Error> {
|
||||||
let backend = match backend {
|
let backend = match backend {
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
Backends::SpeechDispatcher => {
|
Backends::SpeechDispatcher => {
|
||||||
let tts = backends::SpeechDispatcher::new()?;
|
let tts = backends::SpeechDispatcher::new()?;
|
||||||
Ok(Tts(Arc::new(RwLock::new(Box::new(tts))), PhantomData))
|
Ok(Tts(Arc::new(RwLock::new(Box::new(tts)))))
|
||||||
}
|
}
|
||||||
#[cfg(target_arch = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
Backends::Web => {
|
Backends::Web => {
|
||||||
|
@ -317,7 +315,7 @@ impl<T: VoiceImpl> Tts<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default() -> Result<Tts<T>, 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 = "tolk"))]
|
#[cfg(all(windows, feature = "tolk"))]
|
||||||
|
@ -566,7 +564,7 @@ impl<T: VoiceImpl> Tts<T> {
|
||||||
/**
|
/**
|
||||||
* Returns list of available voices.
|
* Returns list of available voices.
|
||||||
*/
|
*/
|
||||||
pub fn voices(&self) -> Result<Vec<Voice<T>>, Error> {
|
pub fn voices(&self) -> Result<Vec<Voice>, Error> {
|
||||||
self.0.read().unwrap().voices()
|
self.0.read().unwrap().voices()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +680,7 @@ impl<T: VoiceImpl> Tts<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: VoiceImpl> Drop for Tts<T> {
|
impl Drop for Tts {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if Arc::strong_count(&self.0) <= 1 {
|
if Arc::strong_count(&self.0) <= 1 {
|
||||||
if let Some(id) = self.0.read().unwrap().id() {
|
if let Some(id) = self.0.read().unwrap().id() {
|
||||||
|
@ -694,16 +692,14 @@ impl<T: VoiceImpl> Drop for Tts<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Gender {
|
pub enum Gender {
|
||||||
Other,
|
Unspecified,
|
||||||
Male,
|
Male,
|
||||||
Female,
|
Female,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait VoiceImpl: Sized {
|
pub struct Voice {
|
||||||
fn id(self) -> String;
|
pub id: String,
|
||||||
fn name(self) -> String;
|
pub name: String,
|
||||||
fn gender(self) -> Gender;
|
pub gender: Gender,
|
||||||
fn language(self) -> Result<LanguageIdentifier, LanguageIdentifierError>;
|
pub language: LanguageIdentifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Voice<T: VoiceImpl + Sized>(Box<T>);
|
|
||||||
|
|
Loading…
Reference in New Issue