Coder Social home page Coder Social logo

tts-rs's Introduction

TTS-RS

This library provides a high-level Text-To-Speech (TTS) interface supporting various backends. Currently supported backends are:

  • Windows
    • Screen readers/SAPI via Tolk (requires tolk Cargo feature)
    • WinRT
  • Linux via Speech Dispatcher
  • MacOS/iOS
    • AppKit on MacOS 10.13 and below
    • AVFoundation on MacOS 10.14 and above, and iOS
  • Android
  • WebAssembly

Android Setup

On most platforms, this library is plug-and-play. Because of JNI's complexity, Android setup is a bit more involved. In general, look to the Android example for guidance. Here are some rough steps to get going:

  • Set up Cargo.toml as the example does. Be sure to depend on ndk-glue.
  • Place Bridge.java appropriately in your app. This is needed to support various Android TTS callbacks.
  • Create a main activity similar to MainActivity.kt. In particular, you need to derive android.app.NativeActivity, and you need a System.loadLibrary(...) call appropriate for your app. System.loadLibrary(...) is needed to trigger JNI_OnLoad.
    • Even though you've loaded the library in your main activity, add a metadata tag to your activity in AndroidManifest.xml referencing it. Yes, this is redundant but necessary.
  • Set if your various build.gradle scripts to reference the plugins, dependencies, etc. from the example. In particular, you'll want to set up cargo-ndk-android-gradle and either depend on androidx.annotation or otherwise configure your app to keep the class rs.tts.Bridge.

And I think that should about do it. Good luck!

tts-rs's People

Contributors

alters-mit avatar alyoshavasilieva avatar bear-03 avatar enyium avatar francois-caddet avatar helgoboss avatar marijns95 avatar ndarilek avatar ninjaboy avatar saona-raimundo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tts-rs's Issues

Awesome Crate. Need help in using it as a wasm pkg. An example code will help.

Hi @ndarilek,

Good to see this crate. Awesome work there. I am trying to integrate this crate to my web app using wasm. I am passing the text caught through the speech recognition API of browser, want to send this text to TTS to process and speak the text. Just an experimental approach.

FYI - I am new to Rust lang and WASM. Thus, an example code of how to use it with WASM (using wasm-bindgen) will be of great help, thank you.

Regards
MS

respecting default speach preferences on mac OS

Given how little we can configure the tts on the mac (based on the examples provided) there should be an option where it just pulls the default tts settings for the mac OS system voice.
Is this possible?
I'm using another project that's using this crate and the tts is defaulting to Samantha no matter what we do.
Thanks!

Making Backend trait public

Hi! I know this could be a major rework and this is not a feature request, but a question if you would be up to review such PR.

I wanted to ask about the possibility of making the Backend trait public.

Pros

People could implement their own backend. So the following things would be possible;

  • If I am not mistaken, espeakng-sys could implement a new backend... or any other ffi to TTS systems.
  • People could implement their own in-house backend (for example: based on a dictionary, play some audio)

Cons

The cost of changing the API?

  • Tts would take anything that implements the trait (for example Box<dyn Backend>), instead of Backends.

MacOS: Only first phrase is being pronounced

Tried using it my macos console app and noticed that only first occurence of tts.speak produces sound.
Retried with simple example and the problem is reproducible

image

use std::{thread, time};

use tts::*;

fn main() -> Result<(), Error> {
    // env_logger::init();
    let mut tts = Tts::default()?;
    let mut phrase = 1;
    loop {
        println!("{phrase}");
        tts.speak(format!("Phrase {}", phrase), false)?;
        let time = time::Duration::from_secs(5);
        thread::sleep(time);
        phrase += 1;
    }
}

On an Android emulator with no TTS, Tts::new() hangs forever

The code tries to initialize the backend, enters this loop:

// This hack makes my brain bleed.
loop {
{
let pending = PENDING_INITIALIZATIONS.read().unwrap();
if !(*pending).contains(&bid) {
break;
}
}
thread::sleep(Duration::from_millis(5));
}

and never exits it. I suspect this can happen on a real Android device* but maybe not, I don't do Android development.

*: The emulator with no TTS is one with no Play Store, while the emulator that works has the Play Store (and where I made sure Speech Services is updated).

Feature request: Ability to select audio output

Pretty self-explanatory. Just an ability to select where the output of the speech synthesizer is would be nice. My motivation is because I'm trying to pipe it into the microphone using Virtual Audio Cable.

Thanks!

Cloning `Tts` causes a double free

Hello! Thanks again for this crate!

I noticed that cloning a Tts instance causes a double free error for me on Linux.

Given the following example:

use futures::task::{LocalSpawn, LocalSpawnExt, Spawn};
use std::cell::RefCell;
use std::ops::DerefMut;
use std::pin::Pin;
use std::rc::Rc;
use std::{
    future::Future,
    task::{Context, Poll},
};
use tts::{Backends, Tts};

/// Trait to implement async support for [`Tts`].
trait TtsExt {
    fn speak_async<'a>(&mut self, text: &'a str, interrupt: bool) -> SpeakAsync<'a>;
}

impl TtsExt for Tts {
    fn speak_async<'a>(&mut self, text: &'a str, interrupt: bool) -> SpeakAsync<'a> {
        SpeakAsync {
            tts: self.clone(),
            text,
            interrupt,
            first_call: Rc::new(RefCell::new(true)),
        }
    }
}

/// Struct which allows awaiting an utterance.
pub struct SpeakAsync<'a> {
    tts: Tts,
    text: &'a str,
    interrupt: bool,
    first_call: Rc<RefCell<bool>>,
}

impl<'a> Future for SpeakAsync<'a> {
    type Output = Result<(), tts::Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        // If this is our first time being polled, register the callback
        if *self.first_call.borrow() {
            let waker = cx.waker().to_owned();
            let first_call = self.first_call.clone();

            self.tts
                .on_utterance_end(Some(Box::new(move |_| {
                    *first_call.borrow_mut() = false;

                    // We want to wake by ref to avoid consuming waker,
                    // or cloning it
                    waker.wake_by_ref()
                })))
                .expect("Failed to register `on_utterance_end` callback");

            // We need to move these items out of `self` to avoid
            // having a mutable borrow in the same scope as
            // immutable borrows
            let text = self.text;
            let interrupt = self.interrupt;

            match self.tts.speak(text, interrupt) {
                Ok(_) => Poll::Pending,
                Err(err) => Poll::Ready(Err(err)),
            }
        }
        // Otherwise, this means we have been woken up by an
        // utterence ended event, and are therefore done
        else {
            Poll::Ready(Ok(()))
        }
    }
}

pub fn speak(text: &str) {
    // Specify the TTS backend that will be used
    #[cfg(target_os = "android")]
    let backend = Backends::Android;
    #[cfg(any(target_os = "macos", target_os = "ios"))]
    let backend = Backends::AvFoundation;
    #[cfg(target_os = "linux")]
    let backend = Backends::SpeechDispatcher;
    #[cfg(all(windows, feature = "tolk"))]
    let backend = Backends::Tolk;
    #[cfg(target_arch = "wasm32")]
    let backend = Backends::Web;
    #[cfg(windows)]
    let backend = Backends::WinRt;

    // Create Tts instance
    let mut tts = Tts::new(backend).expect("Failed to initialize TTS");

    // Speak text
    futures::executor::block_on(tts.speak_async(text, false))
        .unwrap_or_else(|_| panic!(r#"Failed to speak "{}""#, text));

    println!(r#"Done speaking "{}""#, text);
}


fn main() {
    speak("Hello, this is a test");
}

results in a double free error and aborts.

Crash on macOS- InvalidSubtag for voice language

There's a default voice on macOS Ventura that causes a crash because its language description has an unsupported subtag. The voice is Fiona, with a language of en-GB-u-sd-gbsct. This is may be an upstream problem in unic_langid, but I have not confirmed that.

Observed behaviour:

thread 'main' panicked at 'called Result::unwrap() on an Err value: ParserError(InvalidSubtag)', src/backends/av_foundation.rs:315:72

How to reproduce:

cargo run --example hello_world

My system:

mac OS 13.0.1 (22A400)
rustc 1.65.0 (897e37553 2022-11-02)

Temporary workaround

The unwrap() that crashes can be replaced with this as a temporary workaround to avoid the crash:

let language = LanguageIdentifier::from_str(&language).unwrap_or_default();

Add support for SAPI on Windows through COM

Hi,
Can you add SAPI via COM on Windows?
The WinRT bindings are only available on windows 10 I think. Also it can take quite a while to compile, as far as I can tell it generates literally 12 MB worth of bindings.

Hello World example works but then hangs on macOS

Thanks so much for making this crate - it's very useful! ๐Ÿ˜ƒ

I noticed that when I run the Hello World example on macOS (specifically Monterey 12.2.1 running on an M1 machine), it successfully speaks everything, but then hangs after the last one finishes speaking; the process never terminates.

I wonder if maybe a thread is blocking on something that never finishes maybe?

Can't compile on Ubuntu (still)

I'm starting a new issue because I don't have an option to re-open the previous issue: #47

Having set speech_dispatcher_0_9, I still get errors. Tested on Ubuntu 18 this time, not Ubuntu 20.

Cargo.toml:

[dependencies.tts]
version = "0.25.1"
features = ["speech_dispatcher_0_9"]

Result:

Compiling speech-dispatcher v0.16.0
error[E0425]: cannot find value `SPD_PUNCT_MOST` in module `SPDPunctuation`
    --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:103:28
     |
103  |     Most = SPDPunctuation::SPD_PUNCT_MOST,
     |                            ^^^^^^^^^^^^^^ help: a constant with a similar name exists: `SPD_PUNCT_NONE`
     |
    ::: /home/esther/cacophony/target/debug/build/speech-dispatcher-sys-d9157396e7a58d6d/out/speech_dispatcher_sys.rs:1849:5
     |
1849 |     pub const SPD_PUNCT_NONE: Type = 1;
     |     ------------------------------ similarly named constant `SPD_PUNCT_NONE` defined here

error[E0425]: cannot find value `v` in this scope
   --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:421:25
    |
421 |         c_int_to_result(v)
    |                         ^ not found in this scope

error[E0425]: cannot find value `v` in this scope
   --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:429:25
    |
429 |         c_int_to_result(v)
    |                         ^ not found in this scope

error[E0425]: cannot find value `v` in this scope
   --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:437:25
    |
437 |         c_int_to_result(v)
    |                         ^ not found in this scope

error[E0081]: discriminant value `1` assigned more than once
   --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:100:1
    |
100 | pub enum Punctuation {
    | ^^^^^^^^^^^^^^^^^^^^
...
103 |     Most = SPDPunctuation::SPD_PUNCT_MOST,
    |            ------------------------------ `1` assigned here
104 |     Some = SPDPunctuation::SPD_PUNCT_SOME,
105 |     None = SPDPunctuation::SPD_PUNCT_NONE,
    |            ------------------------------ `1` assigned here

Some errors have detailed explanations: E0081, E0425.
For more information about an error, try `rustc --explain E0081`.
error: could not compile `speech-dispatcher` (lib) due to 5 previous errors

Strange behavior setting voices with WinRT

When I run this snippet, even though I changed the voice, Microsoft David is still being used when I call Tts::speak.

let mut tts = Tts::default().unwrap();
let voice_names: Vec<_> = tts
            .voices()
            .unwrap()
            .into_iter()
            .map(|v| v.name())
            .collect();

println!("{:?}", voice_names);

tts.set_voice(&tts.voices().unwrap()[1]).unwrap();
tts.speak("hello", false).unwrap();

stdout:

["Microsoft David", "Microsoft Zira", "Microsoft Mark"]

Looking at the output of the program, "hello" should be said by Zira, not David. Interestingly enough, everything works fine with the following change:

// ... (same as before)

tts.speak("", false).unwrap(); // Fixes voices
tts.set_voice(&tts.voices().unwrap()[1]).unwrap();
tts.speak("hello", false).unwrap(); // Now this will be said by Zira

This makes me think Tts::speak performs some kind of initialization that allows changing the voices afterwards.

Q: Speech as Vec<u8> or &[u8]

Hi there,

Silly question, maybe, but is it possible to get the produced speech as a Vec or a &[u8]? I have not been able to find a way to get it.

Thanks!

Unable to successfully run the Android example for tts-rs.

I cloned the latest tts-rs and opened tts rs/examples/android using IntelliJ IDEA. After clicking "Run", an error occurred:

AndroidRuntime          pid-30765                            E  FATAL EXCEPTION: main
                                                                Process: rs.tts, PID: 30765
                                                                java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{rs.tts/rs.tts.MainActivity}: java.lang.ClassNotFoundException: Didn't find class "rs.tts.MainActivity" on path: DexPathList[[zip file "/data/app/~~B-wOeNZbu9ABdP5z-uMpUQ==/rs.tts-MwtIDebz15srfv5yRxuPlA==/base.apk"],nativeLibraryDirectories=[/data/app/~~B-wOeNZbu9ABdP5z-uMpUQ==/rs.tts-MwtIDebz15srfv5yRxuPlA==/lib/arm64, /system/lib64, /system_ext/lib64]]
                                                                	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3806)
                                                                	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4049)
                                                                	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)
                                                                	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
                                                                	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
                                                                	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)
                                                                	at android.os.Handler.dispatchMessage(Handler.java:106)
                                                                	at android.os.Looper.loopOnce(Looper.java:211)
                                                                	at android.os.Looper.loop(Looper.java:300)
                                                                	at android.app.ActivityThread.main(ActivityThread.java:8348)
                                                                	at java.lang.reflect.Method.invoke(Native Method)
                                                                	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:582)
                                                                	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)
                                                                Caused by: java.lang.ClassNotFoundException: Didn't find class "rs.tts.MainActivity" on path: DexPathList[[zip file "/data/app/~~B-wOeNZbu9ABdP5z-uMpUQ==/rs.tts-MwtIDebz15srfv5yRxuPlA==/base.apk"],nativeLibraryDirectories=[/data/app/~~B-wOeNZbu9ABdP5z-uMpUQ==/rs.tts-MwtIDebz15srfv5yRxuPlA==/lib/arm64, /system/lib64, /system_ext/lib64]]
                                                                	at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:259)
                                                                	at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
                                                                	at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
                                                                	at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
                                                                	at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
                                                                	at android.app.Instrumentation.newActivity(Instrumentation.java:1359)
                                                                	at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3791)
                                                                	at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4049)ย 
                                                                	at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:101)ย 
                                                                	at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)ย 
                                                                	at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)ย 
                                                                	at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2443)ย 
                                                                	at android.os.Handler.dispatchMessage(Handler.java:106)ย 
                                                                	at android.os.Looper.loopOnce(Looper.java:211)ย 
                                                                	at android.os.Looper.loop(Looper.java:300)ย 
                                                                	at android.app.ActivityThread.main(ActivityThread.java:8348)ย 
                                                                	at java.lang.reflect.Method.invoke(Native Method)ย 
                                                                	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:582)ย 
                                                                	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1028)ย 

AVFoundation backend crash when getting voices in macOS desktop application

First, thanks for making this crate! Very useful. I tried to integrate it into a desktop application and it crashes with a SIGSEGV when calling Tts::voices with the AVFoundation backend (in the hello_world example it doesn't crash):

Crashed Thread:        0  reaper  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BREAKPOINT (SIGTRAP)
Exception Codes:       0x0000000000000001, 0x000000018eda5438
Exception Note:        EXC_CORPSE_NOTIFY

Termination Reason:    Namespace SIGNAL, Code 5 Trace/BPT trap: 5
Terminating Process:   exc handler [13354]

Thread 0 Crashed:: reaper Dispatch queue: com.apple.main-thread
0   CoreFoundation                	       0x18eda5438 _CFRelease.cold.3 + 92
1   CoreFoundation                	       0x18eda5430 _CFRelease.cold.3 + 84
2   CoreFoundation                	       0x18ed2b21c _CFRelease + 1496
3   libobjc.A.dylib               	       0x18ea112b4 AutoreleasePoolPage::releaseUntil(objc_object**) + 196
4   libobjc.A.dylib               	       0x18ea0db34 objc_autoreleasePoolPop + 212
...

I think it's because the code for getting the voices and voice attributes doesn't follow the Objective-C memory management rules (explained here in the context of Rust: https://stackoverflow.com/a/43148508, I also didn't know about these rules).

I'm going to create a PR for this.

Crash on initiailizing with AVFoundation backend

Using version 0.22.1 on Mac OS 12.4, a crash occurs. Details, and the relevant part of the backtrace are below:

thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', /Users/lee/.cargo/registry/src/github.com-1ecc6299db9ec823/tts-0.22.1/src/backends/av_foundation.rs:34:90
stack backtrace:
   0: rust_begin_unwind
             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/std/src/panicking.rs:584:5
   1: core::panicking::panic_fmt
             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panicking.rs:143:14
   2: core::panicking::panic
             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/panicking.rs:48:5
   3: core::option::Option<T>::unwrap
             at /rustc/fe5b13d681f25ee6474be29d748c65adcd91f69e/library/core/src/option.rs:755:21
   4: tts::backends::av_foundation::AvFoundation::new
             at /Users/lee/.cargo/registry/src/github.com-1ecc6299db9ec823/tts-0.22.1/src/backends/av_foundation.rs:34:24
   5: tts::Tts::new
             at /Users/lee/.cargo/registry/src/github.com-1ecc6299db9ec823/tts-0.22.1/src/lib.rs:305:17
   6: tts::Tts::default
             at /Users/lee/.cargo/registry/src/github.com-1ecc6299db9ec823/tts-0.22.1/src/lib.rs:351:17

Documenting some additional prerequisites on Linux.

Quick list of prerequisites I seemed to need in order to build hello_world.rs (within a fresh project).

This was a relatively fresh Elementary OS Linux install (based on Ubuntu 18.04) so it's likely clang would be necessary for most wrapper crates so many people would already have it installed,

(In connection with emilk/egui#167 (comment) and https://gitlab.com/RancidBacon/egui-and-tts).

Hope to write up more later but hopefully this might be useful to others as is.

1. libclang1

Needed:

$ pkcon install   libclang1

to avoid:

   Compiling speech-dispatcher-sys v0.5.2
error: failed to run custom build command for `speech-dispatcher-sys v0.5.2`

Caused by:
  process didn't exit successfully: `/home/philip/Projects/rust-related/egui-and-tts/target/debug/build/speech-dispatcher-sys-24c24f7d3c015663/build-script-build` (exit code: 101)
  --- stdout
  cargo:rustc-link-lib=speechd

  --- stderr
  thread 'main' panicked at 'Unable to find libclang: "couldn\'t find any valid shared libraries matching: [\'libclang.so\', \'libclang-*.so\', \'libclang.so.*\', \'libclang-*.so.*\'], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: [])"', /home/philip/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.57.0/src/lib.rs:1975:31

2. libspeechd-dev

Needed:

$ pkcon install libspeechd-dev

to avoid:

$ cargo run
   Compiling speech-dispatcher-sys v0.5.2
error: failed to run custom build command for `speech-dispatcher-sys v0.5.2`

Caused by:
  process didn't exit successfully: `/home/philip/Projects/rust-related/egui-and-tts/target/debug/build/speech-dispatcher-sys-24c24f7d3c015663/build-script-build` (exit code: 101)
  --- stdout
  cargo:rustc-link-lib=speechd

  --- stderr
  wrapper.h:1:10: fatal error: 'speech-dispatcher/libspeechd.h' file not found
  wrapper.h:1:10: fatal error: 'speech-dispatcher/libspeechd.h' file not found, err: true
  thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ()', /home/philip/.cargo/registry/src/github.com-1ecc6299db9ec823/speech-dispatcher-sys-0.5.2/build.rs:22:10
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

3. clang

Needed:

$ pkcon install clang

to avoid (probably would solve first issue also):

$ cargo run
   Compiling speech-dispatcher-sys v0.5.2
error: failed to run custom build command for `speech-dispatcher-sys v0.5.2`

Caused by:
  process didn't exit successfully: `/home/philip/Projects/rust-related/egui-and-tts/target/debug/build/speech-dispatcher-sys-24c24f7d3c015663/build-script-build` (exit code: 101)
  --- stdout
  cargo:rustc-link-lib=speechd

  --- stderr
  /usr/include/stdio.h:33:10: fatal error: 'stddef.h' file not found
  /usr/include/stdio.h:33:10: fatal error: 'stddef.h' file not found, err: true
  thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: ()', /home/philip/.cargo/registry/src/github.com-1ecc6299db9ec823/speech-dispatcher-sys-0.5.2/build.rs:22:10
  note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

4. env_logger (or removing line)

Needed:

//    env_logger::init();

To avoid:

$ cargo run
   Compiling egui-and-tts v0.1.0 (/home/philip/Projects/rust-related/egui-and-tts)
error[E0433]: failed to resolve: use of undeclared crate or module `env_logger`
  --> src/main.rs:14:5
   |
14 |     env_logger::init();
   |     ^^^^^^^^^^ use of undeclared crate or module `env_logger`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0433`.
error: could not compile `egui-and-tts`

To learn more, run the command again with --verbose.

Help: why does the hello_world.rs example work

The code is after stripping the macos parts

use tts::*;

fn main() -> Result<(), Error> {
    let mut tts = Tts::default()?;
    if Tts::screen_reader_available() {
        println!("A screen reader is available on this platform.");
    } else {
        println!("No screen reader is available on this platform.");
    }
    let Features {
        utterance_callbacks,
        ..
    } = tts.supported_features();
    if utterance_callbacks {
        tts.on_utterance_begin(Some(Box::new(|utterance| {
            println!("Started speaking {:?}", utterance)
        })))?;
        tts.on_utterance_end(Some(Box::new(|utterance| {
            println!("Finished speaking {:?}", utterance)
        })))?;
        tts.on_utterance_stop(Some(Box::new(|utterance| {
            println!("Stopped speaking {:?}", utterance)
        })))?;
    }
    let Features { is_speaking, .. } = tts.supported_features();
    if is_speaking {
        println!("Are we speaking? {}", tts.is_speaking()?);
    }
    tts.speak("Hello, world.", false)?;
    let Features { rate, .. } = tts.supported_features();
    if rate {
        let original_rate = tts.get_rate()?;
        tts.speak(format!("Current rate: {}", original_rate), false)?;
        tts.set_rate(tts.max_rate())?;
        tts.speak("This is very fast.", false)?;
        tts.set_rate(tts.min_rate())?;
        tts.speak("This is very slow.", false)?;
        tts.set_rate(tts.normal_rate())?;
        tts.speak("This is the normal rate.", false)?;
        tts.set_rate(original_rate)?;
    }
    let Features { pitch, .. } = tts.supported_features();
    if pitch {
        let original_pitch = tts.get_pitch()?;
        tts.set_pitch(tts.max_pitch())?;
        tts.speak("This is high-pitch.", false)?;
        tts.set_pitch(tts.min_pitch())?;
        tts.speak("This is low pitch.", false)?;
        tts.set_pitch(tts.normal_pitch())?;
        tts.speak("This is normal pitch.", false)?;
        tts.set_pitch(original_pitch)?;
    }
    let Features { volume, .. } = tts.supported_features();
    if volume {
        let original_volume = tts.get_volume()?;
        tts.set_volume(tts.max_volume())?;
        tts.speak("This is loud!", false)?;
        tts.set_volume(tts.min_volume())?;
        tts.speak("This is quiet.", false)?;
        tts.set_volume(tts.normal_volume())?;
        tts.speak("This is normal volume.", false)?;
        tts.set_volume(original_volume)?;
    }
    let Features { voice, .. } = tts.supported_features();
    if voice {
        let voices = tts.voices()?;
        println!("Available voices:\n===");
        for v in &voices {
            println!("{:?}", v);
        }
        let Features { get_voice, .. } = tts.supported_features();
        let original_voice = if get_voice { tts.voice()? } else { None };
        for v in &voices {
            tts.set_voice(v)?;
            tts.speak(format!("This is {}.", v.name()), false)?;
        }
        if let Some(original_voice) = original_voice {
            tts.set_voice(&original_voice)?;
        }
    }
    tts.speak("Goodbye.", false)?;
    Ok(())
}

but when i strip it down to

use tts::*;

fn main() -> Result<(), Error> {
    let mut tts = Tts::default()?;
    tts.speak("Hello, world.", false)?;
    tts.speak("Goodbye.", false)?;
    Ok(())
}

No sound is generated
NOTE: I have speechd installed on Linux.

Docs are failing and so is my build for Linux

cargo add tts --no-default-features --features speech_dispatcher_0_10 is required for me to get it to run on Debian/WSL.

I get the same error as on docs.rs but this fixes it for me.

It's annoying that you can't have both features without the error though, makes it impossible to distribute 1 executable that works regardless of version.

Missing CHANGELOG.md

When updating a dependency I look for CHANGELOG.md as a guide to how to fix upgrade issues (such as "could not find TTS in tts").

It is also nice to track progress :)

WinRT doesn't correctly drop resources

Hi there,

I've been using the TTS crate in one of my projects, and noticed that whenever a Tts object is dropped, it leaves behind MediaPlayer instances, seemingly not cleaning them up.

Example code to trigger:

fn main() {
    for _ in 0..5 {
        let mut tts = Tts::default().unwrap();
        let _ = tts.speak("Hello", false);
        sleep(Duration::from_secs(2));
        drop(tts);
    }

    sleep(Duration::from_secs(20));
}

The result is 5 MediaPlayer SMTC windows being left behind until the application exists:
image

Tested on 0.26.0

Fails to build on arm linux

Expected Behaviour: Project builds and runs successfully after adding tts to the dependencies list

Actual Behaviour: Project fails to run despite not using the library anywhere in code

error: failed to run custom build command for `speech-dispatcher-sys v0.5.2`

Caused by:
  process didn't exit successfully: `/share/lightbox_rs/target/debug/build/speech-dispatcher-sys-92155df6d9f2566e/build-script-build` (exit code: 101)
--- stdout
cargo:rustc-link-lib=speechd

--- stderr
thread 'main' panicked at 'Unable to find libclang: "couldn\'t find any valid shared libraries matching: [\'libclang.so\', \'libclang-*.so\', \'libclang.so.*\', \'libclang-*.so.*\'], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: [])"', /home/benjamin.mcgaw/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.56.0/src/lib.rs:1922:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

warning: build failed, waiting for other jobs to finish...
error: build failed

running with a backtrace yields the following:

error: failed to run custom build command for `speech-dispatcher-sys v0.5.2`

Caused by:
  process didn't exit successfully: `/share/lightbox_rs/target/debug/build/speech-dispatcher-sys-92155df6d9f2566e/build-script-build` (exit code: 101)
--- stdout
cargo:rustc-link-lib=speechd

--- stderr
thread 'main' panicked at 'Unable to find libclang: "couldn\'t find any valid shared libraries matching: [\'libclang.so\', \'libclang-*.so\', \'libclang.so.*\', \'libclang-*.so.*\'], set the `LIBCLANG_PATH` environment variable to a path where one of these files can be found (invalid: [])"', /home/benjamin.mcgaw/.cargo/registry/src/github.com-1ecc6299db9ec823/bindgen-0.56.0/src/lib.rs:1922:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

warning: build failed, waiting for other jobs to finish...
error: build failed

speech-dispatcher-rs writes to null pointer if speech-dispatcher fails to start

Copied from https://gitlab.com/ndarilek/speech-dispatcher-rs/-/issues/1


spd_open and spd_open2 both return null on error1 instead of a valid pointer, but this library doesn't check for that and immediately writes to the pointer:

This does happen in practice; I added an explicit panic on null there and eventually managed to trigger it by repeatedly re-running a basic program. I'd previously been seeing rare segmentation faults. (I have no idea why speech-dispatcher failed to work, but it did.)

Those methods should probably return some form of Result<Self, Error>.

1: See spd-say code or speech-dispatcher's code


More recently I no longer have access to a working Linux system. But my Windows system has Ubuntu via WSL2 with a broken audio configuration, so speech-dispatcher always fails, leading to the speech-dispatcher-rs backend to always segfault:

malloc@L:~/tts-rs$ cargo run --example hello_world
   Compiling speech-dispatcher-sys v0.5.2
   Compiling speech-dispatcher v0.7.0
   Compiling tts v0.18.3 (/home/malloc/tts-rs)
    Finished dev [unoptimized + debuginfo] target(s) in 2.43s
     Running `target/debug/examples/hello_world`
Segmentation fault

Provide function to wait until the voice finished speaking

In a use case (like automated UI tests to be monitored by a human) where you want to start the TTS, then perform actions, and then wait for the TTS to finish, there should be a waiting function Tts::wait().

You can incorporate the significant parts of this type into the Tts type:

struct SyncableTts {
    tts: Tts,
    last_utterance_id_with_condvar: Arc<(Mutex<Option<UtteranceId>>, Condvar)>,
}

impl SyncableTts {
    fn new() -> Result<Self> {
        let mut tts = Tts::default()?;

        let last_utterance_id_with_condvar = Arc::new((Mutex::new(None), Condvar::new()));
        let last_utterance_id_with_condvar_in_cb = last_utterance_id_with_condvar.clone();

        tts.on_utterance_end(Some(Box::new(move |utterance_id| {
            let (last_utterance_id, condvar) = &*last_utterance_id_with_condvar_in_cb;
            let mut last_utterance_id = last_utterance_id.lock().unwrap();
            if Some(utterance_id) == *last_utterance_id {
                *last_utterance_id = None;
                condvar.notify_all();
            }
        })))?;

        Ok(Self {
            tts,
            last_utterance_id_with_condvar,
        })
    }

    fn speak<S: Into<String>>(&mut self, text: S) -> Result<()> {
        let mut last_utterance_id = self.last_utterance_id_with_condvar.0.lock().unwrap();
        *last_utterance_id = Some(
            self.tts
                .speak(text, false)?
                .ok_or_else(|| anyhow!("got `None` utterance ID"))?,
        );

        Ok(())
    }

    fn wait(&self) {
        let (last_utterance_id, condvar) = &*self.last_utterance_id_with_condvar;
        let _guard = condvar
            .wait_while(last_utterance_id.lock().unwrap(), |last_utterance_id| {
                last_utterance_id.is_some()
            })
            .unwrap();
    }
}

Alternatively, the API could use async/await.

Unable to detect NVDA on windows.

I tried to run the examples provided in the repo. It was unable to detect NVDA and it was not able to default to SAPI. Running the 99 bottle example just loop with no output.
On windows 10.

Can't compile on Ubuntu

Crate version: 0.25.1
Ubuntu 20
CPU: x64

I have installed: clang, libclang1, libspeechd-dev

When I cargo run, I get:

   Compiling speech-dispatcher v0.16.0
error[E0425]: cannot find value `SPD_PUNCT_MOST` in module `SPDPunctuation`
    --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:103:28
     |
103  |     Most = SPDPunctuation::SPD_PUNCT_MOST,
     |                            ^^^^^^^^^^^^^^ help: a constant with a similar name exists: `SPD_PUNCT_NONE`
     |
    ::: /home/esther/cacophony/target/debug/build/speech-dispatcher-sys-8b03c54eadb0c1c7/out/speech_dispatcher_sys.rs:1710:5
     |
1710 |     pub const SPD_PUNCT_NONE: Type = 1;
     |     ------------------------------ similarly named constant `SPD_PUNCT_NONE` defined here

error[E0081]: discriminant value `1` assigned more than once
   --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:100:1
    |
100 | pub enum Punctuation {
    | ^^^^^^^^^^^^^^^^^^^^
...
103 |     Most = SPDPunctuation::SPD_PUNCT_MOST,
    |            ------------------------------ `1` assigned here
104 |     Some = SPDPunctuation::SPD_PUNCT_SOME,
105 |     None = SPDPunctuation::SPD_PUNCT_NONE,
    |            ------------------------------ `1` assigned here

error[E0308]: mismatched types
    --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:420:54
     |
420  | ...unsafe { spd_set_voice_type(*self.0, voice_type as i32) };
     |             ------------------          ^^^^^^^^^^^^^^^^^ expected `u32`, found `i32`
     |             |
     |             arguments to this function are incorrect
     |
note: function defined here
    --> /home/esther/cacophony/target/debug/build/speech-dispatcher-sys-8b03c54eadb0c1c7/out/speech_dispatcher_sys.rs:1960:12
     |
1960 |     pub fn spd_set_voice_type(
     |            ^^^^^^^^^^^^^^^^^^
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
     |
420  |         let v = unsafe { spd_set_voice_type(*self.0, (voice_type as i32).try_into().unwrap()) };
     |                                                      +                 +++++++++++++++++++++

error[E0308]: mismatched types
    --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:428:58
     |
428  | ...safe { spd_set_voice_type_all(*self.0, voice_type as i32) };
     |           ----------------------          ^^^^^^^^^^^^^^^^^ expected `u32`, found `i32`
     |           |
     |           arguments to this function are incorrect
     |
note: function defined here
    --> /home/esther/cacophony/target/debug/build/speech-dispatcher-sys-8b03c54eadb0c1c7/out/speech_dispatcher_sys.rs:1966:12
     |
1966 |     pub fn spd_set_voice_type_all(
     |            ^^^^^^^^^^^^^^^^^^^^^^
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
     |
428  |         let v = unsafe { spd_set_voice_type_all(*self.0, (voice_type as i32).try_into().unwrap()) };
     |                                                          +                 +++++++++++++++++++++

error[E0308]: mismatched types
    --> /home/esther/.cargo/registry/src/index.crates.io-6f17d22bba15001f/speech-dispatcher-0.16.0/src/lib.rs:436:58
     |
436  | ...safe { spd_set_voice_type_uid(*self.0, voice_type as i32, target_ui...
     |           ----------------------          ^^^^^^^^^^^^^^^^^ expected `u32`, found `i32`
     |           |
     |           arguments to this function are incorrect
     |
note: function defined here
    --> /home/esther/cacophony/target/debug/build/speech-dispatcher-sys-8b03c54eadb0c1c7/out/speech_dispatcher_sys.rs:1972:12
     |
1972 |     pub fn spd_set_voice_type_uid(
     |            ^^^^^^^^^^^^^^^^^^^^^^
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
     |
436  |         let v = unsafe { spd_set_voice_type_uid(*self.0, (voice_type as i32).try_into().unwrap(), target_uid) };
     |                                                          +                 +++++++++++++++++++++

Some errors have detailed explanations: E0081, E0308, E0425.
For more information about an error, try `rustc --explain E0081`.
error: could not compile `speech-dispatcher` (lib) due to 5 previous errors
warning: build failed, waiting for other jobs to finish...

Ability to list voices, and select one

Most of the backends should have the ability to list available voices on the system, and select the one to be used in the current session. I didn't see this functionality present, is this planned for this crate? It would be very handy to have.

Looks like some work was done in PR #2, but it seems to have stalled.

[Feature] add support for the new NVDA Controller Client

Hello there,

i'm using this crate through bevy_tts right now. One thing that came to mind was to support the new NVDA Controller Client which recently got support for feedback on e.g. when speech stopped. They do have a dedicated Rust example in the repo too: https://github.com/nvaccess/nvda/tree/master/extras/controllerClient/examples/example_rust

I think it could be really neat to have support in here too so that everyone could use the advanced features of the new NVDA Controller Client through tts-rs.

Failed to build on Linux due to dependency speech dispatcher rs

Compiling speech-dispatcher v0.15.1
error[E0308]: mismatched types
   --> /home/jacob/.cargo/registry/src/github.com-1ecc6299db9ec823/speech-dispatcher-0.15.1/src/lib.rs:273:36
    |
273 |         (*c).callback_begin = Some(cb);
    |                               ---- ^^ expected `u64`, found `usize`
    |                               |
    |                               arguments to this enum variant are incorrect
    |
    = note: expected fn pointer `unsafe extern "C" fn(u64, u64, _)`
                  found fn item `unsafe extern "C" fn(usize, usize, _) {cb}`
note: tuple variant defined here
   --> /home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:526:5
    |
526 |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^^^

error[E0308]: mismatched types
   --> /home/jacob/.cargo/registry/src/github.com-1ecc6299db9ec823/speech-dispatcher-0.15.1/src/lib.rs:274:34
    |
274 |         (*c).callback_end = Some(cb);
    |                             ---- ^^ expected `u64`, found `usize`
    |                             |
    |                             arguments to this enum variant are incorrect
    |
    = note: expected fn pointer `unsafe extern "C" fn(u64, u64, _)`
                  found fn item `unsafe extern "C" fn(usize, usize, _) {cb}`
note: tuple variant defined here
   --> /home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:526:5
    |
526 |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^^^

error[E0308]: mismatched types
   --> /home/jacob/.cargo/registry/src/github.com-1ecc6299db9ec823/speech-dispatcher-0.15.1/src/lib.rs:275:37
    |
275 |         (*c).callback_cancel = Some(cb);
    |                                ---- ^^ expected `u64`, found `usize`
    |                                |
    |                                arguments to this enum variant are incorrect
    |
    = note: expected fn pointer `unsafe extern "C" fn(u64, u64, _)`
                  found fn item `unsafe extern "C" fn(usize, usize, _) {cb}`
note: tuple variant defined here
   --> /home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:526:5
    |
526 |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^^^

error[E0308]: mismatched types
   --> /home/jacob/.cargo/registry/src/github.com-1ecc6299db9ec823/speech-dispatcher-0.15.1/src/lib.rs:276:36
    |
276 |         (*c).callback_pause = Some(cb);
    |                               ---- ^^ expected `u64`, found `usize`
    |                               |
    |                               arguments to this enum variant are incorrect
    |
    = note: expected fn pointer `unsafe extern "C" fn(u64, u64, _)`
                  found fn item `unsafe extern "C" fn(usize, usize, _) {cb}`
note: tuple variant defined here
   --> /home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:526:5
    |
526 |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^^^

error[E0308]: mismatched types
   --> /home/jacob/.cargo/registry/src/github.com-1ecc6299db9ec823/speech-dispatcher-0.15.1/src/lib.rs:277:37
    |
277 |         (*c).callback_resume = Some(cb);
    |                                ---- ^^ expected `u64`, found `usize`
    |                                |
    |                                arguments to this enum variant are incorrect
    |
    = note: expected fn pointer `unsafe extern "C" fn(u64, u64, _)`
                  found fn item `unsafe extern "C" fn(usize, usize, _) {cb}`
note: tuple variant defined here
   --> /home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:526:5
    |
526 |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^^^

error[E0308]: mismatched types
   --> /home/jacob/.cargo/registry/src/github.com-1ecc6299db9ec823/speech-dispatcher-0.15.1/src/lib.rs:278:33
    |
278 |         (*c).callback_im = Some(cb_im);
    |                            ---- ^^^^^ expected `u64`, found `usize`
    |                            |
    |                            arguments to this enum variant are incorrect
    |
    = note: expected fn pointer `unsafe extern "C" fn(u64, u64, _, _)`
                  found fn item `unsafe extern "C" fn(usize, usize, _, _) {cb_im}`
note: tuple variant defined here
   --> /home/jacob/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/option.rs:526:5
    |
526 |     Some(#[stable(feature = "rust1", since = "1.0.0")] T),
    |     ^^^^

error: aborting due to 6 previous errors

For more information about this error, try `rustc --explain E0308`.
error: could not compile `speech-dispatcher` due to 7 previous errors

Debian: sid/unstable

speech-dispatcher: 0.11.3

https://gitlab.com/ndarilek/speech-dispatcher-rs/-/issues/7

Fails to build on latest x64 macos.

Hi, great library, unfortunately I am not able to build it on macos due to:

objc_exception v0.1.2

This seems to be needed, because the following feature is enabled:

objc = { version = "0.2", features = ["exception"] }

Is there any chance to disable that feature, or does this need to be fixed upstream?
Thanks in advance.

This is the log:

Compiling objc_exception v0.1.2
   Compiling malloc_buf v0.0.6
   Compiling core-foundation v0.9.1
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-m64" "-arch" "x86_64" "-L" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.build_script_build.735axgxd-cgu.0.rcgu.o" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.build_script_build.735axgxd-cgu.1.rcgu.o" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.build_script_build.735axgxd-cgu.2.rcgu.o" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.build_script_build.735axgxd-cgu.3.rcgu.o" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.build_script_build.735axgxd-cgu.4.rcgu.o" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.build_script_build.735axgxd-cgu.5.rcgu.o" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.build_script_build.735axgxd-cgu.6.rcgu.o" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.build_script_build.735axgxd-cgu.7.rcgu.o" "-o" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68" "/Users/me/Development/Rust/tts/basic_example/target/debug/build/objc_exception-eecd4f6a65aabc68/build_script_build-eecd4f6a65aabc68.ai25uaehhuri6bv.rcgu.o" "-Wl,-dead_strip" "-nodefaultlibs" "-L" "/Users/me/Development/Rust/tts/basic_example/target/debug/deps" "-L" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib" "/Users/me/Development/Rust/tts/basic_example/target/debug/deps/libcc-7560b1db13a03cf8.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libstd-349f286494d73b18.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libpanic_unwind-0c9fcc24a503d489.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libobject-70419d92d1ba4b1d.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libaddr2line-65e88774cb68bd46.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgimli-3849b3781a19a398.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_demangle-0dbb03fa66ca6d84.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libhashbrown-65edff8661311c85.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_alloc-599e707cd7ee7216.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libunwind-40cb05f6c516791a.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcfg_if-7a0a923a4d37a048.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liblibc-7e047938e88325ef.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/liballoc-02542d835be27c0f.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/librustc_std_workspace_core-63712b18a1365082.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcore-1196a2a060497e71.rlib" "/Users/me/.rustup/toolchains/stable-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libcompiler_builtins-10db70d883838cbc.rlib" "-lSystem" "-lresolv" "-lc" "-lm"
  = note: Undefined symbols for architecture x86_64:
            "hashbrown::raw::RawTable$LT$T$GT$::find::he8090a1d69077876", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::hf69552a051eb945b in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::insert::hbbe63e4d89eab6cb", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::hf69552a051eb945b in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::find::h25cfcb9cf54a8646", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::hd33cfd3b46acdb57 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::find::h97c3520b600e98d8", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::h712f4038383a129d in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "_$LT$hashbrown..raw..RawTable$LT$T$GT$$u20$as$u20$core..ops..drop..Drop$GT$::drop::h57f7ec4e55830473", referenced from:
                core::ptr::drop_in_place$LT$hashbrown..raw..RawTable$LT$$LP$alloc..string..String$C$std..ffi..os_str..OsString$RP$$GT$$GT$::h67e51172e00a95c7 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.13.rcgu.o)
            "hashbrown::raw::Bucket$LT$T$GT$::as_ref::hd8aeddb3d8f75850", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::get_key_value::hcc07acf2a98b70e3 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::new::hbd4e17ce6f231bcb", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::with_hasher::h3aab56af9ead24fe in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::new::h62cadb52a8882d21", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::with_hasher::h7cbb5a88e7224a32 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::find::h0b7300015e387705", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::get_key_value::hac32d5233cb9eea0 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::insert::hc3963cc33750cc31", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::hd33cfd3b46acdb57 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::new::h3b5c197859b10526", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::with_hasher::h1f6e371ead49c5a8 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::Bucket$LT$T$GT$::as_ref::h79837e0149a2a17e", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::get_key_value::hac32d5233cb9eea0 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::Bucket$LT$T$GT$::as_mut::h2f9e778eb6521987", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::hf69552a051eb945b in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::Bucket$LT$T$GT$::as_mut::h1f79e50bc31f03dc", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::h712f4038383a129d in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::find::ha5c2c81ffe3283e7", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::get_key_value::hcc07acf2a98b70e3 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::find::h92ecf69a875b3ee4", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::get_key_value::h2dbac2627cc907b3 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::Bucket$LT$T$GT$::as_ref::h39e2c7f072c88930", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::get_key_value::h2dbac2627cc907b3 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::Bucket$LT$T$GT$::as_mut::h8cddf622cf8c6533", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::hd33cfd3b46acdb57 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "hashbrown::raw::RawTable$LT$T$GT$::insert::h3485c7d3dd32566b", referenced from:
                hashbrown::map::HashMap$LT$K$C$V$C$S$GT$::insert::h712f4038383a129d in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.5.rcgu.o)
            "_$LT$hashbrown..raw..RawTable$LT$T$GT$$u20$as$u20$core..ops..drop..Drop$GT$::drop::hd51e8c81e3fd645b", referenced from:
                core::ptr::drop_in_place$LT$hashbrown..raw..RawTable$LT$$LP$alloc..string..String$C$bool$RP$$GT$$GT$::haff0c5c298408d12 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.13.rcgu.o)
            "_$LT$hashbrown..raw..RawTable$LT$T$GT$$u20$as$u20$core..ops..drop..Drop$GT$::drop::h2d0a93cbc8e36b55", referenced from:
                core::ptr::drop_in_place$LT$hashbrown..raw..RawTable$LT$$LP$alloc..string..String$C$core..option..Option$LT$alloc..string..String$GT$$RP$$GT$$GT$::hb791bdcb498bedd4 in libcc-7560b1db13a03cf8.rlib(cc-7560b1db13a03cf8.cc.3oiexmgb-cgu.13.rcgu.o)
          ld: symbol(s) not found for architecture x86_64
          clang: error: linker command failed with exit code 1 (use -v to see invocation)
          

error: aborting due to previous error

error: could not compile `objc_exception`

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed

on macOS Big Sur 11.2.3

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.