7171#include " utils/unicode.h"
7272#include " speech.h"
7373
74+ #ifdef __ANDROID__
75+ #include < jni.h>
76+ #include " SDL.h"
77+ #include " SDL_system.h"
78+
79+ static JNIEnv* env = nullptr ;
80+ static jclass tts_manager = nullptr ;
81+ static jmethodID tts_speak = nullptr , tts_stop = nullptr , tts_pause = nullptr , tts_resume = nullptr , tts_isSpeaking = nullptr , tts_shutdown = nullptr ;
82+
83+ // Ask SDL for the JniEnviroment and get the name and path
84+ // of the external TTSManager on the android side of things
85+ // Then assign all methods ids for later use
86+ bool android_tts_init ()
87+ {
88+ mprintf ((" Speech : Init JNI TTSManager...\n " ));
89+ env = (JNIEnv*)SDL_AndroidGetJNIEnv ();
90+ if (env == nullptr ) {
91+ mprintf ((" Speech : Unable to get JNI environment!\n " ));
92+ return false ;
93+ }
94+ tts_manager = env->FindClass (" com/shivansps/fsowrapper/tts/TTSManager" );
95+ if (tts_manager == nullptr ) {
96+ mprintf ((" Speech : Unable to find the TTSManager class!\n " ));
97+ return false ;
98+ }
99+
100+ tts_speak = env->GetStaticMethodID (tts_manager, " speak" , " (Ljava/lang/String;)Z" );
101+ tts_stop = env->GetStaticMethodID (tts_manager, " stop" , " ()Z" );
102+ tts_pause = env->GetStaticMethodID (tts_manager, " pause" , " ()Z" );
103+ tts_resume = env->GetStaticMethodID (tts_manager, " resume" , " ()Z" );
104+ tts_isSpeaking = env->GetStaticMethodID (tts_manager, " isSpeaking" , " ()Z" );
105+ tts_shutdown = env->GetStaticMethodID (tts_manager, " shutdown" , " ()V" );
106+
107+ if (!tts_speak || !tts_stop || !tts_pause || !tts_resume || !tts_isSpeaking || !tts_shutdown) {
108+ mprintf ((" Speech : Unable to map at least one TTS method!\n " ));
109+ return false ;
110+ }
111+ mprintf ((" Speech : Init Completed!\n " ));
112+ return true ;
113+ }
114+
115+
116+ bool android_tts_play (const char * text)
117+ {
118+ if (env == nullptr || tts_manager == nullptr || tts_speak == nullptr )
119+ return false ;
120+ jstring j_txt = env->NewStringUTF (text != nullptr ? text : " " );
121+ mprintf ((" Speech : Playing TTS string: %s!\n " ,text ));
122+ jboolean ok = env->CallStaticBooleanMethod (tts_manager, tts_speak, j_txt);
123+ env->DeleteLocalRef (j_txt);
124+ if (ok != JNI_TRUE) {
125+ mprintf ((" Speech : Error playing TTS string!\n " ));
126+ return false ;
127+ }
128+ return true ;
129+ }
130+
131+ bool android_tts_stop ()
132+ {
133+ return env->CallStaticBooleanMethod (tts_manager, tts_stop) == JNI_TRUE;
134+ }
135+
136+ bool android_tts_pause ()
137+ {
138+ return env->CallStaticBooleanMethod (tts_manager, tts_pause) == JNI_TRUE;
139+ }
140+
141+ bool android_tts_resume ()
142+ {
143+ return env->CallStaticBooleanMethod (tts_manager, tts_resume) == JNI_TRUE;
144+ }
145+
146+ bool android_tts_is_speaking ()
147+ {
148+ return env->CallStaticBooleanMethod (tts_manager, tts_isSpeaking) == JNI_TRUE;
149+ }
150+
151+ void android_tts_deinit ()
152+ {
153+ env->CallStaticVoidMethod (tts_manager, tts_shutdown);
154+ }
155+ #endif
156+
74157
75158bool Speech_init = false ;
76159
@@ -85,8 +168,9 @@ bool speech_init()
85168 (void **)&Voice_device);
86169
87170 Speech_init = SUCCEEDED (hr);
171+ #elif defined(__ANDROID__)
172+ Speech_init = android_tts_init ();
88173#else
89-
90174 speech_dev = open (" /dev/speech" , O_WRONLY | O_DIRECT);
91175// speech_dev = fopen("/dev/speech", "w");
92176
@@ -109,6 +193,8 @@ void speech_deinit()
109193
110194#ifdef _WIN32
111195 Voice_device->Release ();
196+ #elif defined(__ANDROID__)
197+ android_tts_deinit ();
112198#else
113199 close (speech_dev);
114200// fclose(speech_dev);
@@ -161,6 +247,9 @@ bool speech_play(const char *text)
161247
162248 speech_stop ();
163249 return SUCCEEDED (Voice_device->Speak (wide_string.c_str (), SPF_ASYNC, NULL ));
250+ #elif defined(__ANDROID__)
251+ speech_stop ();
252+ return android_tts_play (text);
164253#else
165254 int len = strlen (text);
166255 char Conversion_buffer[MAX_SPEECH_CHAR_LEN];
@@ -198,6 +287,8 @@ bool speech_pause()
198287 if (Speech_init == false ) return true ;
199288#ifdef _WIN32
200289 return SUCCEEDED (Voice_device->Pause ());
290+ #elif defined(__ANDROID__)
291+ return android_tts_pause ();
201292#else
202293 STUB_FUNCTION;
203294
@@ -210,6 +301,8 @@ bool speech_resume()
210301 if (Speech_init == false ) return true ;
211302#ifdef _WIN32
212303 return SUCCEEDED (Voice_device->Resume ());
304+ #elif defined(__ANDROID__)
305+ return android_tts_resume ();
213306#else
214307 STUB_FUNCTION;
215308
@@ -222,6 +315,8 @@ bool speech_stop()
222315 if (Speech_init == false ) return true ;
223316#ifdef _WIN32
224317 return SUCCEEDED (Voice_device->Speak ( NULL , SPF_PURGEBEFORESPEAK, NULL ));
318+ #elif defined(__ANDROID__)
319+ return android_tts_stop ();
225320#else
226321 STUB_FUNCTION;
227322
@@ -233,6 +328,9 @@ bool speech_set_volume(unsigned short volume)
233328{
234329#ifdef _WIN32
235330 return SUCCEEDED (Voice_device->SetVolume (volume));
331+ #elif defined(__ANDROID__)
332+ (void )volume;
333+ return true ;
236334#else
237335 STUB_FUNCTION;
238336
@@ -276,6 +374,9 @@ bool speech_set_voice(int voice)
276374 count++;
277375 }
278376 return false ;
377+ #elif defined(__ANDROID__)
378+ (void )voice;
379+ return true ;
279380#else
280381 STUB_FUNCTION;
281382
@@ -294,6 +395,8 @@ bool speech_is_speaking()
294395 if (FAILED (hr)) return false ;
295396
296397 return (pStatus.dwRunningState != SPRS_DONE);
398+ #elif defined(__ANDROID__)
399+ return android_tts_is_speaking ();
297400#else
298401 STUB_FUNCTION;
299402
0 commit comments