diff options
3 files changed, 101 insertions, 4 deletions
diff --git a/src/plugins/tts/android/jar/src/org/qtproject/qt5/android/speech/QtTextToSpeech.java b/src/plugins/tts/android/jar/src/org/qtproject/qt5/android/speech/QtTextToSpeech.java index a6e6091..83332fc 100644 --- a/src/plugins/tts/android/jar/src/org/qtproject/qt5/android/speech/QtTextToSpeech.java +++ b/src/plugins/tts/android/jar/src/org/qtproject/qt5/android/speech/QtTextToSpeech.java @@ -50,6 +50,8 @@ import android.util.Log; import java.lang.Float; import java.util.HashMap; import java.util.Locale; +import java.util.List; +import java.util.ArrayList; public class QtTextToSpeech { @@ -60,6 +62,7 @@ public class QtTextToSpeech private TextToSpeech mTts; private final long mId; + private boolean mInitialized = false; private float mPitch = 1.0f; private float mRate = 1.0f; private float mVolume = 1.0f; @@ -70,8 +73,10 @@ public class QtTextToSpeech public void onInit(int status) { Log.w("QtTextToSpeech", "tts initialized"); if (status == TextToSpeech.SUCCESS) { + mInitialized = true; notifyReady(mId); } else { + mInitialized = false; notifyError(mId); } } @@ -206,4 +211,54 @@ public class QtTextToSpeech return (result != TextToSpeech.LANG_NOT_SUPPORTED) && (result != TextToSpeech.LANG_MISSING_DATA); } + public List<Object> getAvailableVoices() + { + if (mInitialized && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + //Log.d("QtTextToSpeech", "Voices: " + mTts.getVoices()); + return new ArrayList<Object>(mTts.getVoices()); + } + return new ArrayList<Object>(); + } + + public List<Locale> getAvailableLocales() + { + if (mInitialized && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + //Log.d("QtTextToSpeech", "Locales: " + mTts.getAvailableLanguages()); + return new ArrayList<Locale>(mTts.getAvailableLanguages()); + } + return new ArrayList<Locale>(); + } + + public Locale getLocale() + { + //Log.d("QtTextToSpeech", "getLocale: " + mLocale); + return mTts.getLanguage(); + } + + public Object getVoice() + { + if (mInitialized && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + return mTts.getVoice(); + } + return null; + } + + public boolean setVoice(String voiceName) + { + if (!mInitialized) + return false; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + for (android.speech.tts.Voice voice : mTts.getVoices()) { + if (voice.getName().equals(voiceName)) { + int result = mTts.setVoice(voice); + if (result == TextToSpeech.SUCCESS) { + //Log.d("QtTextToSpeech", "setVoice: " + voice); + return true; + } + break; + } + } + } + return false; + } } diff --git a/src/plugins/tts/android/src/qtexttospeech_android.cpp b/src/plugins/tts/android/src/qtexttospeech_android.cpp index a3cac58..b4bb006 100644 --- a/src/plugins/tts/android/src/qtexttospeech_android.cpp +++ b/src/plugins/tts/android/src/qtexttospeech_android.cpp @@ -250,7 +250,16 @@ bool QTextToSpeechEngineAndroid::setVolume(double volume) QVector<QLocale> QTextToSpeechEngineAndroid::availableLocales() const { - return QVector<QLocale>(); + auto locales = m_speech.callObjectMethod("getAvailableLocales", "()Ljava/util/List;"); + int count = locales.callMethod<jint>("size"); + QVector<QLocale> result; + result.reserve(count); + for (int i = 0; i < count; ++i) { + auto locale = locales.callObjectMethod("get", "(I)Ljava/lang/Object;", i); + auto localeName = locale.callObjectMethod<jstring>("toString").toString(); + result << QLocale(localeName); + } + return result; } bool QTextToSpeechEngineAndroid::setLocale(const QLocale &locale) @@ -272,21 +281,53 @@ bool QTextToSpeechEngineAndroid::setLocale(const QLocale &locale) QLocale QTextToSpeechEngineAndroid::locale() const { + auto locale = m_speech.callObjectMethod("getLocale", "()Ljava/util/Locale;"); + if (locale.isValid()) { + auto localeName = locale.callObjectMethod<jstring>("toString").toString(); + return QLocale(localeName); + } return QLocale(); } +QVoice QTextToSpeechEngineAndroid::javaVoiceObjectToQVoice(QJNIObjectPrivate &obj) const +{ + auto voiceName = obj.callObjectMethod<jstring>("getName").toString(); + QVoice::Gender gender; + if (voiceName.contains(QStringLiteral("#male"))) { + gender = QVoice::Male; + } else if (voiceName.contains(QStringLiteral("#female"))) { + gender = QVoice::Female; + } else { + gender = QVoice::Unknown; + } + return createVoice(voiceName, gender, QVoice::Other, voiceName); +} + QVector<QVoice> QTextToSpeechEngineAndroid::availableVoices() const { - return QVector<QVoice>(); + auto voices = m_speech.callObjectMethod("getAvailableVoices", "()Ljava/util/List;"); + int count = voices.callMethod<jint>("size"); + QVector<QVoice> result; + result.reserve(count); + for (int i = 0; i < count; ++i) { + auto voice = voices.callObjectMethod("get", "(I)Ljava/lang/Object;", i); + result << javaVoiceObjectToQVoice(voice); + } + return result; } -bool QTextToSpeechEngineAndroid::setVoice(const QVoice & /* voice */) +bool QTextToSpeechEngineAndroid::setVoice(const QVoice &voice) { - return false; + return m_speech.callMethod<jboolean>("setVoice", "(Ljava/lang/String;)Z", + QJNIObjectPrivate::fromString(voiceData(voice).toString()).object()); } QVoice QTextToSpeechEngineAndroid::voice() const { + auto voice = m_speech.callObjectMethod("getVoice", "()Ljava/lang/Object;"); + if (voice.isValid()) { + return javaVoiceObjectToQVoice(voice); + } return QVoice(); } diff --git a/src/plugins/tts/android/src/qtexttospeech_android.h b/src/plugins/tts/android/src/qtexttospeech_android.h index 60cb32d..94c59f5 100644 --- a/src/plugins/tts/android/src/qtexttospeech_android.h +++ b/src/plugins/tts/android/src/qtexttospeech_android.h @@ -81,6 +81,7 @@ public Q_SLOTS: private: void setState(QTextToSpeech::State state); + QVoice javaVoiceObjectToQVoice(QJNIObjectPrivate &obj) const; QJNIObjectPrivate m_speech; QTextToSpeech::State m_state; |