diff --git a/res/values/strings.xml b/res/values/strings.xml index b7973408e58..49a888bea4e 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -3560,6 +3560,21 @@ This language requires a working network connection for text-to-speech output. + + This is an example of speech synthesis + + Default language status + + %1$s is fully supported + + %1$s requires network connection + + %1$s is not supported Engines diff --git a/res/xml/tts_settings.xml b/res/xml/tts_settings.xml index 2b145d18828..ab132df9e3d 100644 --- a/res/xml/tts_settings.xml +++ b/res/xml/tts_settings.xml @@ -37,4 +37,9 @@ android:persistent="false" android:title="@string/tts_play_example_title" android:summary="@string/tts_play_example_summary" /> + + diff --git a/src/com/android/settings/tts/TextToSpeechSettings.java b/src/com/android/settings/tts/TextToSpeechSettings.java index 8f83bbc77b6..10ac575971b 100644 --- a/src/com/android/settings/tts/TextToSpeechSettings.java +++ b/src/com/android/settings/tts/TextToSpeechSettings.java @@ -60,6 +60,9 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements /** Preference key for the TTS rate selection dialog. */ private static final String KEY_DEFAULT_RATE = "tts_default_rate"; + /** Preference key for the TTS status field. */ + private static final String KEY_STATUS = "tts_status"; + /** * Preference key for the engine selection preference. */ @@ -75,6 +78,7 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements private PreferenceCategory mEnginePreferenceCategory; private ListPreference mDefaultRatePref; private Preference mPlayExample; + private Preference mEngineStatus; private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE; @@ -98,6 +102,9 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements private TextToSpeech mTts = null; private TtsEngines mEnginesHelper = null; + private String mSampleText = ""; + private Locale mCurrentDefaultLocale; + /** * The initialization listener used when we are initalizing the settings * screen for the first time (as opposed to when a user changes his choice @@ -136,6 +143,8 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements KEY_ENGINE_PREFERENCE_SECTION); mDefaultRatePref = (ListPreference) findPreference(KEY_DEFAULT_RATE); + mEngineStatus = findPreference(KEY_STATUS); + mTts = new TextToSpeech(getActivity().getApplicationContext(), mInitListener); mEnginesHelper = new TtsEngines(getActivity().getApplicationContext()); @@ -143,6 +152,20 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements initSettings(); } + @Override + public void onResume() { + super.onResume(); + + if (mTts == null || mCurrentDefaultLocale == null) { + return; + } + Locale ttsDefaultLocale = mTts.getDefaultLanguage(); + if (mCurrentDefaultLocale != null && !mCurrentDefaultLocale.equals(ttsDefaultLocale)) { + updateWidgetState(false); + checkDefaultLocale(); + } + } + private void setTtsUtteranceProgressListener() { if (mTts == null) { return; @@ -205,6 +228,46 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements checkVoiceData(mCurrentEngine); } + /** + * Called when the TTS engine is initialized. + */ + public void onInitEngine(int status) { + if (status == TextToSpeech.SUCCESS) { + if (DBG) Log.d(TAG, "TTS engine for settings screen initialized."); + checkDefaultLocale(); + } else { + if (DBG) Log.d(TAG, "TTS engine for settings screen failed to initialize successfully."); + updateWidgetState(false); + } + } + + private void checkDefaultLocale() { + Locale defaultLocale = mTts.getDefaultLanguage(); + if (defaultLocale == null) { + Log.e(TAG, "Failed to get default language from engine " + mCurrentEngine); + updateWidgetState(false); + updateEngineStatus(R.string.tts_status_not_supported); + return; + } + + mCurrentDefaultLocale = defaultLocale; + + int defaultAvailable = mTts.setLanguage(defaultLocale); + if (defaultAvailable == TextToSpeech.LANG_NOT_SUPPORTED) { + if (DBG) Log.d(TAG, "Default locale for this TTS engine is not supported."); + updateWidgetState(false); + updateEngineStatus(R.string.tts_status_not_supported); + } else { + if (isNetworkRequiredForSynthesis()) { + updateEngineStatus(R.string.tts_status_requires_network); + } else { + updateEngineStatus(R.string.tts_status_ok); + } + getSampleText(); + } + } + + /** * Ask the current default engine to return a string of sample text to be * spoken to the user. @@ -214,23 +277,15 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements if (TextUtils.isEmpty(currentEngine)) currentEngine = mTts.getDefaultEngine(); - - Locale defaultLocale = mTts.getDefaultLanguage(); - if (defaultLocale == null) { - Log.e(TAG, "Failed to get default language from engine " + currentEngine); - return; - } - mTts.setLanguage(defaultLocale); - // TODO: This is currently a hidden private API. The intent extras // and the intent action should be made public if we intend to make this // a public API. We fall back to using a canned set of strings if this // doesn't work. Intent intent = new Intent(TextToSpeech.Engine.ACTION_GET_SAMPLE_TEXT); - intent.putExtra("language", defaultLocale.getLanguage()); - intent.putExtra("country", defaultLocale.getCountry()); - intent.putExtra("variant", defaultLocale.getVariant()); + intent.putExtra("language", mCurrentDefaultLocale.getLanguage()); + intent.putExtra("country", mCurrentDefaultLocale.getCountry()); + intent.putExtra("variant", mCurrentDefaultLocale.getVariant()); intent.setPackage(currentEngine); try { @@ -241,19 +296,6 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements } } - /** - * Called when the TTS engine is initialized. - */ - public void onInitEngine(int status) { - if (status == TextToSpeech.SUCCESS) { - updateWidgetState(true); - if (DBG) Log.d(TAG, "TTS engine for settings screen initialized."); - } else { - if (DBG) Log.d(TAG, "TTS engine for settings screen failed to initialize successfully."); - updateWidgetState(false); - } - } - /** * Called when voice data integrity check returns */ @@ -280,11 +322,11 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements } } } - return null; + return getString(R.string.tts_default_sample_string); } private boolean isNetworkRequiredForSynthesis() { - Set features = mTts.getFeatures(mTts.getLanguage()); + Set features = mTts.getFeatures(mCurrentDefaultLocale); return features.contains(TextToSpeech.Engine.KEY_FEATURE_NETWORK_SYNTHESIS) && !features.contains(TextToSpeech.Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS); } @@ -301,24 +343,25 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements if (DBG) Log.d(TAG, "Using default sample text :" + sample); } - if (sample != null && mTts != null) { - // The engine is guaranteed to have been initialized here - // because this preference is not enabled otherwise. - - final boolean networkRequired = isNetworkRequiredForSynthesis(); - if (!networkRequired || networkRequired && - (mTts.isLanguageAvailable(mTts.getLanguage()) >= TextToSpeech.LANG_AVAILABLE)) { - HashMap params = new HashMap(); - params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "Sample"); - - mTts.speak(sample, TextToSpeech.QUEUE_FLUSH, params); - } else { - Log.w(TAG, "Network required for sample synthesis for requested language"); - displayNetworkAlert(); - } + mSampleText = sample; + if (mSampleText != null) { + updateWidgetState(true); } else { - // TODO: Display an error here to the user. - Log.e(TAG, "Did not have a sample string for the requested language"); + Log.e(TAG, "Did not have a sample string for the requested language. Using default"); + } + } + + private void speakSampleText() { + final boolean networkRequired = isNetworkRequiredForSynthesis(); + if (!networkRequired || networkRequired && + (mTts.isLanguageAvailable(mCurrentDefaultLocale) >= TextToSpeech.LANG_AVAILABLE)) { + HashMap params = new HashMap(); + params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "Sample"); + + mTts.speak(mSampleText, TextToSpeech.QUEUE_FLUSH, params); + } else { + Log.w(TAG, "Network required for sample synthesis for requested language"); + displayNetworkAlert(); } } @@ -349,7 +392,7 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements if (preference == mPlayExample) { // Get the sample text from the TTS engine; onActivityResult will do // the actual speaking - getSampleText(); + speakSampleText(); return true; } @@ -359,6 +402,15 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements private void updateWidgetState(boolean enable) { mPlayExample.setEnabled(enable); mDefaultRatePref.setEnabled(enable); + mEngineStatus.setEnabled(enable); + } + + private void updateEngineStatus(int resourceId) { + Locale locale = mCurrentDefaultLocale; + if (locale == null) { + locale = Locale.getDefault(); + } + mEngineStatus.setSummary(getString(resourceId, locale.getDisplayName())); } private void displayNetworkAlert() { @@ -474,8 +526,6 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements } } } - - updateWidgetState(true); } @Override