mirror of https://github.com/ndarilek/tts-rs.git
Merge branch 'master' of https://github.com/ndarilek/tts-rs
This commit is contained in:
commit
dac58539c9
|
@ -6,7 +6,6 @@ on:
|
||||||
- "v*"
|
- "v*"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build_linux:
|
build_linux:
|
||||||
name: Build Linux
|
name: Build Linux
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -15,6 +14,7 @@ jobs:
|
||||||
- run: |
|
- run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libspeechd-dev
|
sudo apt-get install -y libspeechd-dev
|
||||||
|
rustup update
|
||||||
cargo build --release
|
cargo build --release
|
||||||
rustup target add wasm32-unknown-unknown
|
rustup target add wasm32-unknown-unknown
|
||||||
cargo build --release --target wasm32-unknown-unknown
|
cargo build --release --target wasm32-unknown-unknown
|
||||||
|
@ -26,6 +26,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: |
|
- run: |
|
||||||
choco install -y llvm
|
choco install -y llvm
|
||||||
|
rustup update
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
build_macos:
|
build_macos:
|
||||||
|
@ -34,8 +35,20 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: |
|
- run: |
|
||||||
|
rustup update
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
|
build_ios:
|
||||||
|
name: Build iOS
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: |
|
||||||
|
rustup update
|
||||||
|
rustup target add aarch64-apple-ios x86_64-apple-ios
|
||||||
|
cargo install cargo-lipo
|
||||||
|
cargo lipo --release
|
||||||
|
|
||||||
publish_winrt_bindings:
|
publish_winrt_bindings:
|
||||||
name: Publish winrt_bindings
|
name: Publish winrt_bindings
|
||||||
runs-on: windows-latest
|
runs-on: windows-latest
|
||||||
|
@ -46,10 +59,11 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: |
|
- run: |
|
||||||
choco install -y llvm
|
choco install -y llvm
|
||||||
|
rustup update
|
||||||
cargo login $CARGO_TOKEN
|
cargo login $CARGO_TOKEN
|
||||||
cd winrt_bindings
|
cd winrt_bindings
|
||||||
cargo package
|
cargo package
|
||||||
cargo publish
|
cargo publish || true
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
name: Publish
|
name: Publish
|
||||||
|
@ -62,5 +76,6 @@ jobs:
|
||||||
- run: |
|
- run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libspeechd-dev
|
sudo apt-get install -y libspeechd-dev
|
||||||
|
rustup update
|
||||||
cargo login $CARGO_TOKEN
|
cargo login $CARGO_TOKEN
|
||||||
cargo publish
|
cargo publish
|
||||||
|
|
|
@ -5,7 +5,6 @@ on:
|
||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|
||||||
build_linux:
|
build_linux:
|
||||||
name: Build Linux
|
name: Build Linux
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -14,6 +13,7 @@ jobs:
|
||||||
- run: |
|
- run: |
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
sudo apt-get install -y libspeechd-dev
|
sudo apt-get install -y libspeechd-dev
|
||||||
|
rustup update
|
||||||
cargo build --release
|
cargo build --release
|
||||||
rustup target add wasm32-unknown-unknown
|
rustup target add wasm32-unknown-unknown
|
||||||
cargo build --release --target wasm32-unknown-unknown
|
cargo build --release --target wasm32-unknown-unknown
|
||||||
|
@ -25,6 +25,7 @@ jobs:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: |
|
- run: |
|
||||||
choco install -y llvm
|
choco install -y llvm
|
||||||
|
rustup update
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
build_macos:
|
build_macos:
|
||||||
|
@ -33,7 +34,16 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- run: |
|
- run: |
|
||||||
|
rustup update
|
||||||
cargo build --release
|
cargo build --release
|
||||||
|
|
||||||
|
build_ios:
|
||||||
|
name: Build iOS
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- run: |
|
||||||
|
rustup update
|
||||||
|
rustup target add aarch64-apple-ios x86_64-apple-ios
|
||||||
cargo install cargo-lipo
|
cargo install cargo-lipo
|
||||||
rustup target add aarch64-apple-ios armv7-apple-ios armv7s-apple-ios
|
|
||||||
cargo lipo --release
|
cargo lipo --release
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "tts"
|
name = "tts"
|
||||||
version = "0.5.0"
|
version = "0.6.2"
|
||||||
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"
|
||||||
|
@ -12,6 +12,7 @@ edition = "2018"
|
||||||
crate-type = ["lib", "staticlib"]
|
crate-type = ["lib", "staticlib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
lazy_static = "1"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
|
|
||||||
|
@ -24,7 +25,7 @@ winrt = "0.7"
|
||||||
tts_winrt_bindings = { version = "0.1", path="winrt_bindings" }
|
tts_winrt_bindings = { version = "0.1", path="winrt_bindings" }
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
speech-dispatcher = "0.4"
|
speech-dispatcher = "0.6"
|
||||||
|
|
||||||
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
|
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
|
||||||
cocoa-foundation = "0.1"
|
cocoa-foundation = "0.1"
|
||||||
|
|
|
@ -8,5 +8,5 @@ This library provides a high-level Text-To-Speech (TTS) interface supporting var
|
||||||
* Linux via [Speech Dispatcher](https://freebsoft.org/speechd)
|
* Linux via [Speech Dispatcher](https://freebsoft.org/speechd)
|
||||||
* MacOS
|
* MacOS
|
||||||
* AppKit on MacOS 10.13 and below
|
* AppKit on MacOS 10.13 and below
|
||||||
* AVFoundation on MacOS 10.14 and, eventually, iDevices
|
* AVFoundation on MacOS 10.14 and above, and iOS
|
||||||
* WebAssembly
|
* WebAssembly
|
||||||
|
|
|
@ -95,9 +95,9 @@ impl Backend for AppKit {
|
||||||
Features {
|
Features {
|
||||||
stop: true,
|
stop: true,
|
||||||
rate: true,
|
rate: true,
|
||||||
pitch: false,
|
|
||||||
volume: true,
|
volume: true,
|
||||||
is_speaking: true,
|
is_speaking: true,
|
||||||
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::Mutex;
|
||||||
|
|
||||||
|
use lazy_static::*;
|
||||||
use log::{info, trace};
|
use log::{info, trace};
|
||||||
use speech_dispatcher::*;
|
use speech_dispatcher::*;
|
||||||
|
|
||||||
|
@ -6,11 +10,41 @@ use crate::{Backend, Error, Features};
|
||||||
|
|
||||||
pub struct SpeechDispatcher(Connection);
|
pub struct SpeechDispatcher(Connection);
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref SPEAKING: Mutex<HashMap<u64, bool>> = {
|
||||||
|
let m: HashMap<u64, bool> = HashMap::new();
|
||||||
|
Mutex::new(m)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
impl SpeechDispatcher {
|
impl SpeechDispatcher {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
info!("Initializing SpeechDispatcher backend");
|
info!("Initializing SpeechDispatcher backend");
|
||||||
let connection = speech_dispatcher::Connection::open("tts", "tts", "tts", Mode::Single);
|
let connection = speech_dispatcher::Connection::open("tts", "tts", "tts", Mode::Threaded);
|
||||||
SpeechDispatcher(connection)
|
let sd = SpeechDispatcher(connection);
|
||||||
|
let mut speaking = SPEAKING.lock().unwrap();
|
||||||
|
speaking.insert(sd.0.client_id(), false);
|
||||||
|
sd.0.on_begin(Some(|_msg_id, client_id| {
|
||||||
|
let mut speaking = SPEAKING.lock().unwrap();
|
||||||
|
speaking.insert(client_id, true);
|
||||||
|
}));
|
||||||
|
sd.0.on_end(Some(|_msg_id, client_id| {
|
||||||
|
let mut speaking = SPEAKING.lock().unwrap();
|
||||||
|
speaking.insert(client_id, false);
|
||||||
|
}));
|
||||||
|
sd.0.on_cancel(Some(|_msg_id, client_id| {
|
||||||
|
let mut speaking = SPEAKING.lock().unwrap();
|
||||||
|
speaking.insert(client_id, false);
|
||||||
|
}));
|
||||||
|
sd.0.on_pause(Some(|_msg_id, client_id| {
|
||||||
|
let mut speaking = SPEAKING.lock().unwrap();
|
||||||
|
speaking.insert(client_id, false);
|
||||||
|
}));
|
||||||
|
sd.0.on_resume(Some(|_msg_id, client_id| {
|
||||||
|
let mut speaking = SPEAKING.lock().unwrap();
|
||||||
|
speaking.insert(client_id, true);
|
||||||
|
}));
|
||||||
|
sd
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +55,7 @@ impl Backend for SpeechDispatcher {
|
||||||
rate: true,
|
rate: true,
|
||||||
pitch: true,
|
pitch: true,
|
||||||
volume: true,
|
volume: true,
|
||||||
is_speaking: false,
|
is_speaking: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,7 +132,7 @@ impl Backend for SpeechDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normal_volume(&self) -> f32 {
|
fn normal_volume(&self) -> f32 {
|
||||||
0.
|
100.
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_volume(&self) -> Result<f32, Error> {
|
fn get_volume(&self) -> Result<f32, Error> {
|
||||||
|
@ -111,6 +145,15 @@ impl Backend for SpeechDispatcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_speaking(&self) -> Result<bool, Error> {
|
fn is_speaking(&self) -> Result<bool, Error> {
|
||||||
unimplemented!()
|
let speaking = SPEAKING.lock().unwrap();
|
||||||
|
let is_speaking = speaking.get(&self.0.client_id()).unwrap();
|
||||||
|
Ok(*is_speaking)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for SpeechDispatcher {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
let mut speaking = SPEAKING.lock().unwrap();
|
||||||
|
speaking.remove(&self.0.client_id());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,31 @@ impl Backend for Tolk {
|
||||||
fn supported_features(&self) -> Features {
|
fn supported_features(&self) -> Features {
|
||||||
Features {
|
Features {
|
||||||
stop: true,
|
stop: true,
|
||||||
rate: false,
|
..Default::default()
|
||||||
pitch: false,
|
|
||||||
volume: false,
|
|
||||||
is_speaking: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn speak(&mut self, text: &str, interrupt: bool) -> Result<(), Error> {
|
fn speak(&mut self, text: &str, interrupt: bool) -> Result<(), Error> {
|
||||||
trace!("speak({}, {})", text, interrupt);
|
trace!("speak({}, {})", text, interrupt);
|
||||||
self.0.speak(text, interrupt);
|
const BUFFER_LENGTH: usize = 300;
|
||||||
|
if text.len() <= BUFFER_LENGTH {
|
||||||
|
self.0.speak(text, interrupt);
|
||||||
|
} else {
|
||||||
|
if interrupt {
|
||||||
|
self.stop()?;
|
||||||
|
}
|
||||||
|
let tokens = text.split_whitespace();
|
||||||
|
let mut buffer = String::new();
|
||||||
|
for token in tokens {
|
||||||
|
if buffer.len() + token.len() > BUFFER_LENGTH {
|
||||||
|
self.0.speak(buffer, false);
|
||||||
|
buffer = String::new();
|
||||||
|
} else {
|
||||||
|
buffer.push_str(token);
|
||||||
|
buffer.push(' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
src/lib.rs
14
src/lib.rs
|
@ -7,7 +7,7 @@
|
||||||
* * Linux via [Speech Dispatcher](https://freebsoft.org/speechd)
|
* * Linux via [Speech Dispatcher](https://freebsoft.org/speechd)
|
||||||
* * MacOS
|
* * MacOS
|
||||||
* * AppKit on MacOS 10.13 and below
|
* * AppKit on MacOS 10.13 and below
|
||||||
* * AVFoundation on MacOS 10.14 and, eventually, iDevices
|
* * AVFoundation on MacOS 10.14 and above, and iOS
|
||||||
* * WebAssembly
|
* * WebAssembly
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -48,6 +48,18 @@ pub struct Features {
|
||||||
pub is_speaking: bool,
|
pub is_speaking: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for Features {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
stop: false,
|
||||||
|
rate: false,
|
||||||
|
pitch: false,
|
||||||
|
volume: false,
|
||||||
|
is_speaking: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Error)]
|
#[derive(Debug, Error)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error("IO error: {0}")]
|
#[error("IO error: {0}")]
|
||||||
|
|
Loading…
Reference in New Issue