From 1c1d7823b28916a59707fbbeb731f382d63ce3c0 Mon Sep 17 00:00:00 2001
From: Menyadar <>
Date: Sun, 25 Sep 2022 06:32:14 +0200
Subject: [PATCH] TextToSpeechAPI: list voices & select voice to use selecting
 voice directly overrides language + region + variant

---
 .../com/termux/api/apis/TextToSpeechAPI.java  | 41 +++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/app/src/main/java/com/termux/api/apis/TextToSpeechAPI.java b/app/src/main/java/com/termux/api/apis/TextToSpeechAPI.java
index 2dae2dd1c..7b7a41fa6 100644
--- a/app/src/main/java/com/termux/api/apis/TextToSpeechAPI.java
+++ b/app/src/main/java/com/termux/api/apis/TextToSpeechAPI.java
@@ -9,6 +9,7 @@
 import android.speech.tts.TextToSpeech.Engine;
 import android.speech.tts.TextToSpeech.EngineInfo;
 import android.speech.tts.UtteranceProgressListener;
+import android.speech.tts.Voice;
 import android.util.JsonWriter;
 
 import com.termux.api.util.ResultReturner;
@@ -22,6 +23,7 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.Set;
 
 public class TextToSpeechAPI {
 
@@ -64,6 +66,7 @@ protected void onHandleIntent(final Intent intent) {
             Logger.logDebug(LOG_TAG, "onHandleIntent:\n" + IntentUtils.getIntentString(intent));
 
             final String speechLanguage = intent.getStringExtra("language");
+            final String speechVoice = intent.getStringExtra("voice");
             final String speechRegion = intent.getStringExtra("region");
             final String speechVariant = intent.getStringExtra("variant");
             final String speechEngine = intent.getStringExtra("engine");
@@ -139,6 +142,28 @@ public void writeResult(PrintWriter out) {
                             return;
                         }
 
+                        Set<Voice> availableVoices = mTts.getVoices();
+
+                        if ("LIST_AVAILABLE".equals(speechVoice)) {
+                            try (JsonWriter writer = new JsonWriter(out)) {
+                                writer.setIndent("  ");
+                                String defaultVoiceName = mTts.getDefaultVoice().getName();
+                                writer.beginArray();
+                                for (Voice info : availableVoices) {
+                                    writer.beginObject();
+                                    writer.name("name").value(info.getName());
+                                    writer.name("locale").value(info.getLocale().getLanguage() + "-" + info.getLocale().getCountry());
+                                    writer.name("requiresNetworkConnection").value(info.isNetworkConnectionRequired());
+                                    writer.name("installed").value(!info.getFeatures().contains("notInstalled"));
+                                    writer.name("default").value(defaultVoiceName.equals(info.getName()));
+                                    writer.endObject();
+                                }
+                                writer.endArray();
+                            }
+                            out.println();
+                            return;
+                        }
+
                         final AtomicInteger ttsDoneUtterancesCount = new AtomicInteger();
 
                         mTts.setOnUtteranceProgressListener(new UtteranceProgressListener() {
@@ -177,6 +202,22 @@ public void onDone(String utteranceId) {
 
                         String utteranceId = "utterance_id";
                         Bundle params = new Bundle();
+                        if (speechVoice != null) {
+                            for (Voice voice : availableVoices) {
+                                if (speechVoice.equals(voice.getName())) {
+                                    int setVoiceResult = mTts.setVoice(voice);
+                                    if (setVoiceResult == TextToSpeech.LANG_NOT_SUPPORTED) {
+                                        Logger.logError(LOG_TAG, "tts.setVoice('" + speechVoice +"') returned " + setVoiceResult);
+                                    }
+                                    break;
+                                }
+                            }
+                        } else if (speechLanguage != null) {
+                            int setLanguageResult = mTts.setLanguage(getLocale(speechLanguage, speechRegion, speechVariant));
+                            if (setLanguageResult != TextToSpeech.LANG_AVAILABLE) {
+                                Logger.logError(LOG_TAG, "tts.setLanguage('" + speechLanguage + "') returned " + setLanguageResult);
+                            }
+                        }
                         params.putInt(Engine.KEY_PARAM_STREAM, streamToUse);
                         params.putString(Engine.KEY_PARAM_UTTERANCE_ID, utteranceId);