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]
command = "adb"
args = ["logcat", "RustStdoutStderr:D", "*:S"]

View File

@ -1,15 +1,24 @@
package rs.tts;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
@androidx.annotation.Keep
public class Bridge implements TextToSpeech.OnInitListener {
public class Bridge extends UtteranceProgressListener implements TextToSpeech.OnInitListener {
public int backendId;
public Bridge(int 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();
if utterance_callbacks {
tts.on_utterance_begin(Some(Box::new(|utterance| {
/*tts.on_utterance_begin(Some(Box::new(|utterance| {
println!("Started speaking {:?}", utterance)
})))?;
})))?;*/
tts.on_utterance_end(Some(Box::new(|utterance| {
println!("Finished speaking {:?}", utterance)
})))?;

View File

@ -1,11 +1,12 @@
#[cfg(target_os = "android")]
use std::collections::HashSet;
use std::ffi::{CStr, CString};
use std::os::raw::c_void;
use std::sync::{Mutex, RwLock};
use std::thread;
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::{JNIEnv, JavaVM};
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)]
pub(crate) struct Android {
id: BackendId,
@ -77,6 +168,12 @@ impl Android {
"(Landroid/content/Context;Landroid/speech/tts/TextToSpeech$OnInitListener;)V",
&[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();
(*pending).insert(bid);
@ -122,7 +219,7 @@ impl Backend for Android {
pitch: true,
volume: false,
is_speaking: true,
utterance_callbacks: false,
utterance_callbacks: true,
}
}

View File

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