Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2291)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java

Issue 15012027: Android implementation of text-to-speech code for Web Speech Synthesis API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@tts_multivoice
Patch Set: Fix clang error Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | chrome/browser/android/chrome_jni_registrar.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java
new file mode 100644
index 0000000000000000000000000000000000000000..9f1966a751c788bd8bd72587331f593fdf5ce4fe
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/TtsPlatformImpl.java
@@ -0,0 +1,235 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser;
+
+import android.content.Context;
+import android.speech.tts.TextToSpeech;
+import android.speech.tts.UtteranceProgressListener;
+import java.lang.Double;
+import java.lang.Integer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Locale;
+import org.chromium.base.CalledByNative;
+import org.chromium.base.ThreadUtils;
+
+/**
+ * This class is the Java counterpart to the C++ TtsPlatformImplAndroid class.
+ * It implements the Android-native text-to-speech code to support the web
+ * speech synthesis API.
+ *
+ * Threading model note: all calls from C++ must happen on the UI thread.
+ * Callbacks from Android may happen on a different thread, so we always
+ * use ThreadUtils.runOnUiThread when calling back to C++.
+ */
+class TtsPlatformImpl {
+ private static class TtsVoice {
+ private TtsVoice(String name, String language) {
+ mName = name;
+ mLanguage = language;
+ }
+ private final String mName;
+ private final String mLanguage;
+ };
+
+ private int mNativeTtsPlatformImplAndroid;
+ private final TextToSpeech mTextToSpeech;
+ private boolean mInitialized;
+ private ArrayList<TtsVoice> mVoices;
+ private String mCurrentLanguage;
+
+ private TtsPlatformImpl(int nativeTtsPlatformImplAndroid, Context context) {
+ mInitialized = false;
+ mNativeTtsPlatformImplAndroid = nativeTtsPlatformImplAndroid;
+ mTextToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
+ public void onInit(int status) {
+ if (status == TextToSpeech.SUCCESS) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ initialize();
+ }
+ });
+ }
+ }
+ });
+ mTextToSpeech.setOnUtteranceProgressListener(new UtteranceProgressListener() {
+ public void onDone(final String utteranceId) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mNativeTtsPlatformImplAndroid != 0) {
+ nativeOnEndEvent(mNativeTtsPlatformImplAndroid,
+ Integer.parseInt(utteranceId));
+ }
+ }
+ });
+ }
+
+ public void onError(final String utteranceId) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mNativeTtsPlatformImplAndroid != 0) {
+ nativeOnErrorEvent(mNativeTtsPlatformImplAndroid,
+ Integer.parseInt(utteranceId));
+ }
+ }
+ });
+ }
+
+ public void onStart(final String utteranceId) {
+ ThreadUtils.runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mNativeTtsPlatformImplAndroid != 0) {
+ nativeOnStartEvent(mNativeTtsPlatformImplAndroid,
+ Integer.parseInt(utteranceId));
+ }
+ }
+ });
+ }
+ });
+ };
+
+ /**
+ * Create a TtsPlatformImpl object, which is owned by TtsPlatformImplAndroid
+ * on the C++ side.
+ *
+ * @param nativeTtsPlatformImplAndroid The C++ object that owns us.
+ * @param context The app context.
+ */
+ @CalledByNative
+ private static TtsPlatformImpl create(int nativeTtsPlatformImplAndroid,
+ Context context) {
+ return new TtsPlatformImpl(nativeTtsPlatformImplAndroid, context);
+ }
+
+ /**
+ * Called when our C++ counterpoint is deleted. Clear the handle to our
+ * native C++ object, ensuring it's never called.
+ */
+ @CalledByNative
+ private void destroy() {
+ mNativeTtsPlatformImplAndroid = 0;
+ }
+
+ /**
+ * @return true if our TextToSpeech object is initialized and we've
+ * finished scanning the list of voices.
+ */
+ @CalledByNative
+ private boolean isInitialized() {
+ return mInitialized;
+ }
+
+ /**
+ * @return the number of voices.
+ */
+ @CalledByNative
+ private int getVoiceCount() {
+ assert mInitialized == true;
+ return mVoices.size();
+ }
+
+ /**
+ * @return the name of the voice at a given index.
+ */
+ @CalledByNative
+ private String getVoiceName(int voiceIndex) {
+ assert mInitialized == true;
+ return mVoices.get(voiceIndex).mName;
+ }
+
+ /**
+ * @return the language of the voice at a given index.
+ */
+ @CalledByNative
+ private String getVoiceLanguage(int voiceIndex) {
+ assert mInitialized == true;
+ return mVoices.get(voiceIndex).mLanguage;
+ }
+
+ /**
+ * Attempt to start speaking an utterance. If it returns true, will call back on
+ * start and end.
+ *
+ * @param utteranceId A unique id for this utterance so that callbacks can be tied
+ * to a particular utterance.
+ * @param text The text to speak.
+ * @param lang The language code for the text (e.g., "en-US").
+ * @param rate The speech rate, in the units expected by Android TextToSpeech.
+ * @param pitch The speech pitch, in the units expected by Android TextToSpeech.
+ * @param volume The speech volume, in the units expected by Android TextToSpeech.
+ * @return true on success.
+ */
+ @CalledByNative
+ private boolean speak(int utteranceId, String text, String lang,
+ float rate, float pitch, float volume) {
+ assert mInitialized == true;
+ if (!lang.equals(mCurrentLanguage)) {
+ mTextToSpeech.setLanguage(new Locale(lang));
+ mCurrentLanguage = lang;
+ }
+
+ mTextToSpeech.setSpeechRate(rate);
+ mTextToSpeech.setPitch(pitch);
+ HashMap<String, String> params = new HashMap<String, String>();
+ if (volume != 1.0) {
+ params.put(TextToSpeech.Engine.KEY_PARAM_VOLUME, Double.toString(volume));
+ }
+ params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, Integer.toString(utteranceId));
+ int result = mTextToSpeech.speak(text, TextToSpeech.QUEUE_FLUSH, params);
+ return (result == TextToSpeech.SUCCESS);
+ }
+
+ /**
+ * Stop the current utterance.
+ */
+ @CalledByNative
+ private void stop() {
+ assert mInitialized == true;
+ mTextToSpeech.stop();
+ }
+
+ /**
+ * Note: we enforce that this method is called on the UI thread, so
+ * we can call nativeVoicesChanged directly.
+ */
+ private void initialize() {
+ assert mNativeTtsPlatformImplAndroid != 0;
+
+ // Note: Android supports multiple speech engines, but querying the
+ // metadata about all of them is expensive. So we deliberately only
+ // support the default speech engine, and expose the different
+ // supported languages for the default engine as different voices.
+ String defaultEngineName = mTextToSpeech.getDefaultEngine();
+ String engineLabel = defaultEngineName;
+ for (TextToSpeech.EngineInfo info : mTextToSpeech.getEngines()) {
+ if (info.name.equals(defaultEngineName)) engineLabel = info.label;
+ }
+ Locale[] locales = Locale.getAvailableLocales();
+ mVoices = new ArrayList<TtsVoice>();
+ for (int i = 0; i < locales.length; ++i) {
+ if (!locales[i].getVariant().isEmpty()) continue;
+ if (mTextToSpeech.isLanguageAvailable(locales[i]) > 0) {
+ String name = locales[i].getDisplayLanguage();
+ if (!locales[i].getCountry().isEmpty()) {
+ name += " " + locales[i].getDisplayCountry();
+ }
+ TtsVoice voice = new TtsVoice(name, locales[i].toString());
+ mVoices.add(voice);
+ }
+ }
+
+ mInitialized = true;
+ nativeVoicesChanged(mNativeTtsPlatformImplAndroid);
+ }
+
+ private native void nativeVoicesChanged(int nativeTtsPlatformImplAndroid);
+ private native void nativeOnEndEvent(int nativeTtsPlatformImplAndroid, int utteranceId);
+ private native void nativeOnStartEvent(int nativeTtsPlatformImplAndroid, int utteranceId);
+ private native void nativeOnErrorEvent(int nativeTtsPlatformImplAndroid, int utteranceId);
+}
« no previous file with comments | « no previous file | chrome/browser/android/chrome_jni_registrar.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698