Various improvements.

* Add ability to detect when speaking. Doesn't yet work under Linux or WinRT.
* Add signal to indicate when speaking is done.
* Refine screen reader detection under Android.
This commit is contained in:
Nolan Darilek 2020-06-02 16:23:45 -05:00
parent c7d827da93
commit 0d7ba71769
3 changed files with 78 additions and 10 deletions

41
TTS.gd
View File

@ -5,6 +5,8 @@ var TTS
var tts var tts
signal done
func _ready(): func _ready():
if OS.get_name() == "Server" or OS.has_feature("JavaScript"): if OS.get_name() == "Server" or OS.has_feature("JavaScript"):
@ -150,6 +152,32 @@ func get_is_rate_supported():
var is_rate_supported setget , get_is_rate_supported var is_rate_supported setget , get_is_rate_supported
func _get_can_detect_is_speaking():
if Engine.has_singleton("AndroidTTS"):
return true
elif OS.has_feature('JavaScript'):
return true
elif tts != null:
return tts.can_detect_is_speaking
return false
var can_detect_is_speaking setget , _get_can_detect_is_speaking
func _get_is_speaking():
if Engine.has_singleton("AndroidTTS"):
return tts.is_speaking()
elif OS.has_feature('JavaScript'):
return JavaScript.eval("window.speechSynthesis.speaking")
elif tts != null:
return tts.is_speaking
return false
var is_speaking setget , _get_is_speaking
func _get_can_detect_screen_reader(): func _get_can_detect_screen_reader():
if Engine.has_singleton("AndroidTTS"): if Engine.has_singleton("AndroidTTS"):
return true return true
@ -183,6 +211,19 @@ func singular_or_plural(count, singular, plural):
return plural return plural
var _was_speaking = false
func _process(delta):
if self.is_speaking:
print("xxx Speaking")
_was_speaking = true
elif _was_speaking:
print("xxx Done")
emit_signal("done")
_was_speaking = false
func _exit_tree(): func _exit_tree():
if not tts or not TTS: if not tts or not TTS:
return return

View File

@ -2,18 +2,14 @@ package games.lightsout.godot.tts;
import java.util.List; import java.util.List;
import org.godotengine.godot.Godot;
import android.accessibilityservice.AccessibilityServiceInfo; import android.accessibilityservice.AccessibilityServiceInfo;
import android.app.Activity; import android.app.Activity;
import android.content.Intent;
import android.content.Context; import android.content.Context;
import android.speech.tts.TextToSpeech; import android.speech.tts.TextToSpeech;
import android.util.Log;
import android.view.accessibility.AccessibilityManager; import android.view.accessibility.AccessibilityManager;
import com.godot.game.R;
import javax.microedition.khronos.opengles.GL10;
import org.godotengine.godot.Godot;
public class TTS extends Godot.SingletonBase implements TextToSpeech.OnInitListener { public class TTS extends Godot.SingletonBase implements TextToSpeech.OnInitListener {
protected Activity appActivity; protected Activity appActivity;
@ -48,14 +44,20 @@ public class TTS extends Godot.SingletonBase implements TextToSpeech.OnInitListe
tts.setSpeechRate(rate); tts.setSpeechRate(rate);
} }
public boolean is_speaking() {
return tts.isSpeaking();
}
public boolean has_screen_reader() { public boolean has_screen_reader() {
AccessibilityManager accessibilityManager = (AccessibilityManager) appContext AccessibilityManager accessibilityManager = (AccessibilityManager) appContext
.getSystemService(Context.ACCESSIBILITY_SERVICE); .getSystemService(Context.ACCESSIBILITY_SERVICE);
if (accessibilityManager != null) { if (accessibilityManager != null) {
List<AccessibilityServiceInfo> screenReaders =accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN); List<AccessibilityServiceInfo> screenReaders = accessibilityManager
.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_SPOKEN);
return screenReaders.size() != 0; return screenReaders.size() != 0;
} else } else {
return false; return false;
}
} }
public void getInstanceId(int pInstanceId) { public void getInstanceId(int pInstanceId) {
@ -74,7 +76,8 @@ public class TTS extends Godot.SingletonBase implements TextToSpeech.OnInitListe
this.appContext = appActivity.getApplicationContext(); this.appContext = appActivity.getApplicationContext();
this.tts = new TextToSpeech(this.appContext, this); this.tts = new TextToSpeech(this.appContext, this);
// Register class name and functions to bind. // Register class name and functions to bind.
registerClass("AndroidTTS", new String[] { "speak", "stop", "get_rate", "set_rate", "getInstanceId" }); registerClass("AndroidTTS", new String[] { "speak", "stop", "get_rate", "set_rate", "has_screen_reader",
"is_speaking", "getInstanceId" });
this.activity.runOnUiThread(new Runnable() { this.activity.runOnUiThread(new Runnable() {
public void run() { public void run() {
} }

View File

@ -93,11 +93,35 @@ impl TTS {
#[cfg(windows)] #[cfg(windows)]
{ {
let tolk = tolk::Tolk::new(); let tolk = tolk::Tolk::new();
return tolk.detect_screen_reader().is_some() return tolk.detect_screen_reader().is_some();
} }
return false; return false;
}) })
.done(); .done();
builder
.add_property("can_detect_is_speaking")
.with_getter(|this: &TTS, _| {
let Features {
is_speaking: is_speaking_supported,
..
} = this.0.supported_features();
return is_speaking_supported;
})
.done();
builder
.add_property("is_speaking")
.with_getter(|this: &TTS, _| {
let Features {
is_speaking: is_speaking_supported,
..
} = this.0.supported_features();
if is_speaking_supported {
return this.0.is_speaking().unwrap();
} else {
return false;
}
})
.done();
} }
#[export] #[export]