Partially implement callbacks. Unfinished due to lazy_static inconsistencies.

This commit is contained in:
Nolan Darilek 2020-12-30 11:37:46 -06:00
parent c92b67127c
commit 0ea46b29b2
5 changed files with 120 additions and 6 deletions

View File

@ -1,3 +1,9 @@
[tasks.run-android]
script = [
"cd examples/android",
"./gradlew runDebug",
]
[tasks.log-android] [tasks.log-android]
command = "adb" command = "adb"
args = ["logcat", "RustStdoutStderr:D", "*:S"] args = ["logcat", "RustStdoutStderr:D", "*:S"]

View File

@ -1,15 +1,24 @@
package rs.tts; package rs.tts;
import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
@androidx.annotation.Keep @androidx.annotation.Keep
public class Bridge implements TextToSpeech.OnInitListener { public class Bridge extends UtteranceProgressListener implements TextToSpeech.OnInitListener {
public int backendId; public int backendId;
public Bridge(int backendId) { public Bridge(int backendId) {
this.backendId = backendId; this.backendId = backendId;
} }
public native void onInit(int status); public native void onInit(int status);
public native void onStart(String utteranceId);
public native void onStop(String utteranceId, Boolean interrupted);
public native void onDone(String utteranceId);
public native void onError(String utteranceId) ;
} }

View File

@ -7,9 +7,9 @@ fn run() -> Result<(), Error> {
.. ..
} = tts.supported_features(); } = tts.supported_features();
if utterance_callbacks { if utterance_callbacks {
tts.on_utterance_begin(Some(Box::new(|utterance| { /*tts.on_utterance_begin(Some(Box::new(|utterance| {
println!("Started speaking {:?}", utterance) println!("Started speaking {:?}", utterance)
})))?; })))?;*/
tts.on_utterance_end(Some(Box::new(|utterance| { tts.on_utterance_end(Some(Box::new(|utterance| {
println!("Finished speaking {:?}", utterance) println!("Finished speaking {:?}", utterance)
})))?; })))?;

View File

@ -1,11 +1,12 @@
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
use std::collections::HashSet; use std::collections::HashSet;
use std::ffi::{CStr, CString};
use std::os::raw::c_void; use std::os::raw::c_void;
use std::sync::{Mutex, RwLock}; use std::sync::{Mutex, RwLock};
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use jni::objects::{GlobalRef, JObject}; use jni::objects::{GlobalRef, JObject, JString};
use jni::sys::{jfloat, jint, JNI_VERSION_1_6}; use jni::sys::{jfloat, jint, JNI_VERSION_1_6};
use jni::{JNIEnv, JavaVM}; use jni::{JNIEnv, JavaVM};
use lazy_static::lazy_static; use lazy_static::lazy_static;
@ -50,6 +51,96 @@ pub unsafe extern "C" fn Java_rs_tts_Bridge_onInit(env: JNIEnv, obj: JObject, st
} }
} }
#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn Java_rs_tts_Bridge_onStart(
env: JNIEnv,
obj: JObject,
utterance_id: JString,
) {
let backend_id = env
.get_field(obj, "backendId", "I")
.expect("Failed to get backend ID")
.i()
.expect("Failed to cast to int") as u64;
let backend_id = BackendId::Android(backend_id);
let utterance_id = CString::from(CStr::from_ptr(
env.get_string(utterance_id).unwrap().as_ptr(),
))
.into_string()
.unwrap();
let utterance_id = utterance_id.parse::<u64>().unwrap();
let utterance_id = UtteranceId::Android(utterance_id);
println!("Retrieving callbacks for {:?}", backend_id);
let mut callbacks = CALLBACKS.lock().unwrap();
println!("Callback keys: {:?}", callbacks.keys());
if let Some(cb) = callbacks.get_mut(&backend_id) {
if let Some(f) = cb.utterance_begin.as_mut() {
f(utterance_id);
}
}
}
#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn Java_rs_tts_Bridge_onStop(
env: JNIEnv,
obj: JObject,
utterance_id: JString,
) {
let id = env
.get_field(obj, "backendId", "I")
.expect("Failed to get backend ID")
.i()
.expect("Failed to cast to int") as u64;
let utterance_id = CString::from(CStr::from_ptr(
env.get_string(utterance_id).unwrap().as_ptr(),
))
.into_string()
.unwrap();
//println!("Call stop for {}", utterance_id);
}
#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn Java_rs_tts_Bridge_onDone(
env: JNIEnv,
obj: JObject,
utterance_id: JString,
) {
let id = env
.get_field(obj, "backendId", "I")
.expect("Failed to get backend ID")
.i()
.expect("Failed to cast to int") as u64;
let utterance_id = CString::from(CStr::from_ptr(
env.get_string(utterance_id).unwrap().as_ptr(),
))
.into_string()
.unwrap();
//println!("Call done for {}", utterance_id);
}
#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "C" fn Java_rs_tts_Bridge_onError(
env: JNIEnv,
obj: JObject,
utterance_id: JString,
) {
let id = env
.get_field(obj, "backendId", "I")
.expect("Failed to get backend ID")
.i()
.expect("Failed to cast to int") as u64;
let utterance_id = CString::from(CStr::from_ptr(
env.get_string(utterance_id).unwrap().as_ptr(),
))
.into_string()
.unwrap();
//println!("Call error for {}", utterance_id);
}
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct Android { pub(crate) struct Android {
id: BackendId, id: BackendId,
@ -77,6 +168,12 @@ impl Android {
"(Landroid/content/Context;Landroid/speech/tts/TextToSpeech$OnInitListener;)V", "(Landroid/content/Context;Landroid/speech/tts/TextToSpeech$OnInitListener;)V",
&[native_activity.activity().into(), bridge.into()], &[native_activity.activity().into(), bridge.into()],
)?; )?;
env.call_method(
tts,
"setOnUtteranceProgressListener",
"(Landroid/speech/tts/UtteranceProgressListener;)I",
&[bridge.into()],
)?;
{ {
let mut pending = PENDING_INITIALIZATIONS.write().unwrap(); let mut pending = PENDING_INITIALIZATIONS.write().unwrap();
(*pending).insert(bid); (*pending).insert(bid);
@ -122,7 +219,7 @@ impl Backend for Android {
pitch: true, pitch: true,
volume: false, volume: false,
is_speaking: true, is_speaking: true,
utterance_callbacks: false, utterance_callbacks: true,
} }
} }

View File

@ -213,7 +213,9 @@ impl TTS {
if let Ok(backend) = backend { if let Ok(backend) = backend {
if let Some(id) = backend.0.id() { if let Some(id) = backend.0.id() {
let mut callbacks = CALLBACKS.lock().unwrap(); let mut callbacks = CALLBACKS.lock().unwrap();
println!("Initializing callbacks for {:?}", id);
callbacks.insert(id, Callbacks::default()); callbacks.insert(id, Callbacks::default());
println!("Keys after: {:?}", callbacks.keys());
} }
Ok(backend) Ok(backend)
} else { } else {