Open ninjaboy opened 1 year ago
Please see the hello_world example for macOS-specific changes, specifically:
// The below is only needed to make the example run on MacOS because there is no NSRunLoop in this context.
// It shouldn't be needed in an app or game that almost certainly has one already.
#[cfg(target_os = "macos")]
{
let run_loop: id = unsafe { NSRunLoop::currentRunLoop() };
unsafe {
let _: () = msg_send![run_loop, run];
}
}
Please re-open if that doesn't work, or submit a PR if you know how to integrate that into the library itself.
Thanks.
Yeah, I tried that and it hangs indefinitely after the first phrase
#[cfg(target_os = "macos")]
use cocoa_foundation::base::id;
#[cfg(target_os = "macos")]
use cocoa_foundation::foundation::NSRunLoop;
#[cfg(target_os = "macos")]
use objc::{msg_send, sel, sel_impl};
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;
#[cfg(target_os = "macos")]
{
let run_loop: id = unsafe { NSRunLoop::currentRunLoop() };
unsafe {
let _: () = msg_send![run_loop, run];
}
}
}
}
Sorry, I can't reopen this. Please let me know if the above integration of the quick fix is not correct. Thanks in advance
Sorry, not sure how to fix this and it works for what I need it to do under macOS.
I'll leave it open for folks with more macOS experience to help.
Ok, I think what needs to be done is to call something like this:
let _: () = msg_send![run_loop, runMode:NSDefaultRunLoopMode beforeDate:NSDate::distantFuture()];
https://developer.apple.com/documentation/foundation/nsrunloop/1411525-runmode?language=objc
I am very new to Rust so, not sure of what to pass here: NSDate::distantFuture()
Any idea? I can try to proceed further :)
@ndarilek
Ok, I got it working
#[cfg(target_os = "macos")]
use cocoa_foundation::base::id;
#[cfg(target_os = "macos")]
use cocoa_foundation::foundation::NSRunLoop;
use cocoa_foundation::foundation::{NSDate, NSDefaultRunLoopMode};
use objc::{
class,
runtime::{self, Object},
};
#[cfg(target_os = "macos")]
use objc::{msg_send, sel, sel_impl};
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), true)
.expect("Failed");
#[cfg(target_os = "macos")]
{
let run_loop: id = unsafe { NSRunLoop::currentRunLoop() };
unsafe {
let date: id = msg_send![class!(NSDate), distantFuture];
let _: () = msg_send![run_loop, runMode:NSDefaultRunLoopMode beforeDate:date];
}
}
let time = time::Duration::from_secs(1);
thread::sleep(time);
phrase += 1;
}
}
Need to see how to include this call into the library after each call to speak.
@ndarilek , https://github.com/ndarilek/tts-rs/pull/41 at least for an example
I'm currently facing this problem. In a multithreaded environment (not sure if it matters), invoking TTS and then using the above solution will not work. Also, applying the above solution to the main thread will hang the main thread's loop. The expected behaviour is for on_utterance_end() to be called, but it is not.
But as far as I know, using opencv-rust's highgui works as expected without writing an NSRunLoop. This is probably because highgui already has code for cocoa_foundation.
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