From 1a2712ce2a18eba6809d984d2f7443fbdccaa7ed Mon Sep 17 00:00:00 2001 From: Charles Chen Date: Thu, 1 Apr 2010 17:16:28 -0700 Subject: [PATCH] Fix for bug 2564771 - pitch setting between apps can interfere with one another. Root cause was not caching all the params that were needed. This change fixes that bug as well as related bugs for remembering the default engine and for making sure that the right engine is loaded when checking for language availability. Change-Id: I2a76da8faec8112036e68d27539db444c53a1509 --- core/java/android/speech/tts/ITts.aidl | 2 +- .../java/android/speech/tts/TextToSpeech.java | 80 +++++++++++++------ .../src/android/tts/TtsService.java | 32 +++++++- 3 files changed, 87 insertions(+), 27 deletions(-) diff --git a/core/java/android/speech/tts/ITts.aidl b/core/java/android/speech/tts/ITts.aidl index 2fd367208b697..c1051c49e02d8 100755 --- a/core/java/android/speech/tts/ITts.aidl +++ b/core/java/android/speech/tts/ITts.aidl @@ -43,7 +43,7 @@ interface ITts { String[] getLanguage(); - int isLanguageAvailable(in String language, in String country, in String variant); + int isLanguageAvailable(in String language, in String country, in String variant, in String[] params); int setLanguage(in String callingApp, in String language, in String country, in String variant); diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index eeb42c42596a2..e7c6432b5fe66 100755 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -314,6 +314,10 @@ public class TextToSpeech { * {@hide} */ public static final String KEY_PARAM_ENGINE = "engine"; + /** + * {@hide} + */ + public static final String KEY_PARAM_PITCH = "pitch"; /** * Parameter key to specify the audio stream type to be used when speaking text * or playing back a file. @@ -365,7 +369,12 @@ public class TextToSpeech { /** * {@hide} */ - protected static final int NB_CACHED_PARAMS = 7; + protected static final int PARAM_POSITION_PITCH = 14; + + /** + * {@hide} + */ + protected static final int NB_CACHED_PARAMS = 8; } /** @@ -409,9 +418,10 @@ public class TextToSpeech { mCachedParams[Engine.PARAM_POSITION_STREAM] = Engine.KEY_PARAM_STREAM; mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID; mCachedParams[Engine.PARAM_POSITION_ENGINE] = Engine.KEY_PARAM_ENGINE; + mCachedParams[Engine.PARAM_POSITION_PITCH] = Engine.KEY_PARAM_PITCH; - // Leave all defaults that are shown in Settings uninitialized so that - // the values set in Settings will take effect if the application does + // Leave all defaults that are shown in Settings uninitialized/at the default + // so that the values set in Settings will take effect if the application does // not try to change these settings itself. mCachedParams[Engine.PARAM_POSITION_RATE + 1] = ""; mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = ""; @@ -421,6 +431,7 @@ public class TextToSpeech { String.valueOf(Engine.DEFAULT_STREAM); mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = ""; mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = ""; + mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = "100"; initTts(); } @@ -435,6 +446,9 @@ public class TextToSpeech { synchronized(mStartLock) { mITts = ITts.Stub.asInterface(service); mStarted = true; + // Cache the default engine and current language + setEngineByPackageName(getDefaultEngine()); + setLanguage(getLanguage()); if (mInitListener != null) { // TODO manage failures and missing resources mInitListener.onInit(SUCCESS); @@ -1008,15 +1022,13 @@ public class TextToSpeech { return result; } try { + // the pitch is not set here, instead it is cached so it will be associated + // with all upcoming utterances. if (pitch > 0) { - result = mITts.setPitch(mPackageName, (int)(pitch*100)); + int p = (int)(pitch*100); + mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = String.valueOf(p); + result = SUCCESS; } - } catch (RemoteException e) { - // TTS died; restart it. - Log.e("TextToSpeech.java - setPitch", "RemoteException"); - e.printStackTrace(); - mStarted = false; - initTts(); } catch (NullPointerException e) { // TTS died; restart it. Log.e("TextToSpeech.java - setPitch", "NullPointerException"); @@ -1057,16 +1069,27 @@ public class TextToSpeech { return result; } try { - mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language(); - mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country(); - mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = loc.getVariant(); - // the language is not set here, instead it is cached so it will be associated - // with all upcoming utterances. But we still need to report the language support, - // which is achieved by calling isLanguageAvailable() - result = mITts.isLanguageAvailable( - mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1], - mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1], - mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] ); + String language = loc.getISO3Language(); + String country = loc.getISO3Country(); + String variant = loc.getVariant(); + // Check if the language, country, variant are available, and cache + // the available parts. + // Note that the language is not actually set here, instead it is cached so it + // will be associated with all upcoming utterances. + result = mITts.isLanguageAvailable(language, country, variant, mCachedParams); + if (result >= LANG_AVAILABLE){ + mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = language; + if (result >= LANG_COUNTRY_AVAILABLE){ + mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = country; + } else { + mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = ""; + } + if (result >= LANG_COUNTRY_VAR_AVAILABLE){ + mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = variant; + } else { + mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = ""; + } + } } catch (RemoteException e) { // TTS died; restart it. Log.e("TextToSpeech.java - setLanguage", "RemoteException"); @@ -1104,11 +1127,18 @@ public class TextToSpeech { return null; } try { - String[] locStrings = mITts.getLanguage(); - if ((locStrings != null) && (locStrings.length == 3)) { - return new Locale(locStrings[0], locStrings[1], locStrings[2]); + // Only do a call to the native synth if there is nothing in the cached params + if (mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1].length() < 1){ + String[] locStrings = mITts.getLanguage(); + if ((locStrings != null) && (locStrings.length == 3)) { + return new Locale(locStrings[0], locStrings[1], locStrings[2]); + } else { + return null; + } } else { - return null; + return new Locale(mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1], + mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1], + mCachedParams[Engine.PARAM_POSITION_VARIANT + 1]); } } catch (RemoteException e) { // TTS died; restart it. @@ -1151,7 +1181,7 @@ public class TextToSpeech { } try { result = mITts.isLanguageAvailable(loc.getISO3Language(), - loc.getISO3Country(), loc.getVariant()); + loc.getISO3Country(), loc.getVariant(), mCachedParams); } catch (RemoteException e) { // TTS died; restart it. Log.e("TextToSpeech.java - isLanguageAvailable", "RemoteException"); diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java index 530ca5773e62c..c977ba3dac518 100755 --- a/packages/TtsService/src/android/tts/TtsService.java +++ b/packages/TtsService/src/android/tts/TtsService.java @@ -321,6 +321,10 @@ public class TtsService extends Service implements OnCompletionListener { TextToSpeech.Engine.DEFAULT_RATE); } + private int getDefaultPitch() { + // Pitch is not user settable; the default pitch is always 100. + return 100; + } private String getDefaultLanguage() { String defaultLang = android.provider.Settings.Secure.getString(mResolver, @@ -786,6 +790,7 @@ public class TtsService extends Service implements OnCompletionListener { String variant = ""; String speechRate = ""; String engine = ""; + String pitch = ""; if (speechItem.mParams != null){ for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){ String param = speechItem.mParams.get(i); @@ -809,6 +814,8 @@ public class TtsService extends Service implements OnCompletionListener { } } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_ENGINE)) { engine = speechItem.mParams.get(i + 1); + } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_PITCH)) { + pitch = speechItem.mParams.get(i + 1); } } } @@ -831,6 +838,11 @@ public class TtsService extends Service implements OnCompletionListener { } else { setSpeechRate("", getDefaultRate()); } + if (pitch.length() > 0){ + setPitch("", Integer.parseInt(pitch)); + } else { + setPitch("", getDefaultPitch()); + } try { sNativeSynth.speak(speechItem.mText, streamType); } catch (NullPointerException e) { @@ -885,6 +897,7 @@ public class TtsService extends Service implements OnCompletionListener { String variant = ""; String speechRate = ""; String engine = ""; + String pitch = ""; if (speechItem.mParams != null){ for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){ String param = speechItem.mParams.get(i); @@ -901,6 +914,8 @@ public class TtsService extends Service implements OnCompletionListener { utteranceId = speechItem.mParams.get(i+1); } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_ENGINE)) { engine = speechItem.mParams.get(i + 1); + } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_PITCH)) { + pitch = speechItem.mParams.get(i + 1); } } } @@ -923,6 +938,11 @@ public class TtsService extends Service implements OnCompletionListener { } else { setSpeechRate("", getDefaultRate()); } + if (pitch.length() > 0){ + setPitch("", Integer.parseInt(pitch)); + } else { + setPitch("", getDefaultPitch()); + } try { sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename); } catch (NullPointerException e) { @@ -1377,7 +1397,17 @@ public class TtsService extends Service implements OnCompletionListener { * TTS_LANG_COUNTRY_AVAILABLE, TTS_LANG_COUNTRY_VAR_AVAILABLE as defined in * android.speech.tts.TextToSpeech. */ - public int isLanguageAvailable(String lang, String country, String variant) { + public int isLanguageAvailable(String lang, String country, String variant, + String[] params) { + for (int i = 0; i < params.length - 1; i = i + 2){ + String param = params[i]; + if (param != null) { + if (param.equals(TextToSpeech.Engine.KEY_PARAM_ENGINE)) { + mSelf.setEngine(params[i + 1]); + break; + } + } + } return mSelf.isLanguageAvailable(lang, country, variant); }