Disable TTS "Listen to the example" if not supported

If current TTS locale (most of the cases same as device locale) is
not supported by the TTS engine, field for setting synthesis speed
and "Listen to the example" will be disabled.

Added new field, "Default language status" to indicate level of support
for currently selected language. It can take one of three messages:
%s is fully supported
%s requires network connection
%s is not supported
Where %s is locale display name.

Added example string that will provide a fallback for example text
if not provided by Settings or TTS engine.

Change-Id: Ia2a920a71197a85d3812fc8df9dfed4ebe6b515f
Bug: 9982002
This commit is contained in:
Przemyslaw Szczepaniak
2013-08-02 17:06:41 +01:00
parent 2500f7a3f5
commit 4c85c1d6f4
3 changed files with 116 additions and 46 deletions

View File

@@ -3560,6 +3560,21 @@
<!-- Warning message about required internet conectivity for TTS synthesis, displayed as a dialog <!-- Warning message about required internet conectivity for TTS synthesis, displayed as a dialog
message when the user selects to play an example for network only locale and there's no internet connectivity. --> message when the user selects to play an example for network only locale and there's no internet connectivity. -->
<string name="tts_engine_network_required">This language requires a working network connection for text-to-speech output.</string> <string name="tts_engine_network_required">This language requires a working network connection for text-to-speech output.</string>
<!-- Text spoken by the TTS engine as an example if the engine doesn't provide sample text [CHAR LIMIT=100] -->
<string name="tts_default_sample_string">This is an example of speech synthesis</string>
<!-- On main TTS Settings screen, title of a field explaining current TTS engine status for
current default language [CHAR LIMIT=50] -->
<string name="tts_status_title">Default language status</string>
<!-- On main TTS Settings screen, current TTS engine status for the current default language,
selected language is fully supported by the engine [CHAR LIMIT=150]-->
<string name="tts_status_ok"><xliff:g id="locale" example="English (United States)">%1$s</xliff:g> is fully supported</string>
<!-- On main TTS Settings screen, current TTS engine status for the current default language,
selected language is supported by the engine only if there's a working network connection
[CHAR LIMIT=150]-->
<string name="tts_status_requires_network"><xliff:g id="locale" example="English (United States)">%1$s</xliff:g> requires network connection</string>
<!-- On main TTS Settings screen, current TTS engine status for the current default language,
selected language is not supported by the engine [CHAR LIMIT=150]-->
<string name="tts_status_not_supported"><xliff:g id="locale" example="English (United States)">%1$s</xliff:g> is not supported</string>
<!-- On main TTS Settings screen, text for divider under which all TTS engines are listed --> <!-- On main TTS Settings screen, text for divider under which all TTS engines are listed -->
<string name="tts_engines_section">Engines</string> <string name="tts_engines_section">Engines</string>
<!-- On main TTS Settings screen, text preceded by the TTS engine name, clicking this button will launch the engine settings --> <!-- On main TTS Settings screen, text preceded by the TTS engine name, clicking this button will launch the engine settings -->

View File

@@ -37,4 +37,9 @@
android:persistent="false" android:persistent="false"
android:title="@string/tts_play_example_title" android:title="@string/tts_play_example_title"
android:summary="@string/tts_play_example_summary" /> android:summary="@string/tts_play_example_summary" />
<Preference android:key="tts_status"
style="?android:attr/preferenceInformationStyle"
android:persistent="false"
android:title="@string/tts_status_title"/>
</PreferenceScreen> </PreferenceScreen>

View File

@@ -60,6 +60,9 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
/** Preference key for the TTS rate selection dialog. */ /** Preference key for the TTS rate selection dialog. */
private static final String KEY_DEFAULT_RATE = "tts_default_rate"; 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. * Preference key for the engine selection preference.
*/ */
@@ -75,6 +78,7 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
private PreferenceCategory mEnginePreferenceCategory; private PreferenceCategory mEnginePreferenceCategory;
private ListPreference mDefaultRatePref; private ListPreference mDefaultRatePref;
private Preference mPlayExample; private Preference mPlayExample;
private Preference mEngineStatus;
private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE; private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
@@ -98,6 +102,9 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
private TextToSpeech mTts = null; private TextToSpeech mTts = null;
private TtsEngines mEnginesHelper = null; private TtsEngines mEnginesHelper = null;
private String mSampleText = "";
private Locale mCurrentDefaultLocale;
/** /**
* The initialization listener used when we are initalizing the settings * The initialization listener used when we are initalizing the settings
* screen for the first time (as opposed to when a user changes his choice * 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); KEY_ENGINE_PREFERENCE_SECTION);
mDefaultRatePref = (ListPreference) findPreference(KEY_DEFAULT_RATE); mDefaultRatePref = (ListPreference) findPreference(KEY_DEFAULT_RATE);
mEngineStatus = findPreference(KEY_STATUS);
mTts = new TextToSpeech(getActivity().getApplicationContext(), mInitListener); mTts = new TextToSpeech(getActivity().getApplicationContext(), mInitListener);
mEnginesHelper = new TtsEngines(getActivity().getApplicationContext()); mEnginesHelper = new TtsEngines(getActivity().getApplicationContext());
@@ -143,6 +152,20 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
initSettings(); 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() { private void setTtsUtteranceProgressListener() {
if (mTts == null) { if (mTts == null) {
return; return;
@@ -205,6 +228,46 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
checkVoiceData(mCurrentEngine); 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 * Ask the current default engine to return a string of sample text to be
* spoken to the user. * spoken to the user.
@@ -214,23 +277,15 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
if (TextUtils.isEmpty(currentEngine)) currentEngine = mTts.getDefaultEngine(); 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 // 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 // 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 // a public API. We fall back to using a canned set of strings if this
// doesn't work. // doesn't work.
Intent intent = new Intent(TextToSpeech.Engine.ACTION_GET_SAMPLE_TEXT); Intent intent = new Intent(TextToSpeech.Engine.ACTION_GET_SAMPLE_TEXT);
intent.putExtra("language", defaultLocale.getLanguage()); intent.putExtra("language", mCurrentDefaultLocale.getLanguage());
intent.putExtra("country", defaultLocale.getCountry()); intent.putExtra("country", mCurrentDefaultLocale.getCountry());
intent.putExtra("variant", defaultLocale.getVariant()); intent.putExtra("variant", mCurrentDefaultLocale.getVariant());
intent.setPackage(currentEngine); intent.setPackage(currentEngine);
try { 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 * 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() { private boolean isNetworkRequiredForSynthesis() {
Set<String> features = mTts.getFeatures(mTts.getLanguage()); Set<String> features = mTts.getFeatures(mCurrentDefaultLocale);
return features.contains(TextToSpeech.Engine.KEY_FEATURE_NETWORK_SYNTHESIS) && return features.contains(TextToSpeech.Engine.KEY_FEATURE_NETWORK_SYNTHESIS) &&
!features.contains(TextToSpeech.Engine.KEY_FEATURE_EMBEDDED_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 (DBG) Log.d(TAG, "Using default sample text :" + sample);
} }
if (sample != null && mTts != null) { mSampleText = sample;
// The engine is guaranteed to have been initialized here if (mSampleText != null) {
// because this preference is not enabled otherwise. updateWidgetState(true);
final boolean networkRequired = isNetworkRequiredForSynthesis();
if (!networkRequired || networkRequired &&
(mTts.isLanguageAvailable(mTts.getLanguage()) >= TextToSpeech.LANG_AVAILABLE)) {
HashMap<String, String> params = new HashMap<String, String>();
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();
}
} else { } else {
// TODO: Display an error here to the user. Log.e(TAG, "Did not have a sample string for the requested language. Using default");
Log.e(TAG, "Did not have a sample string for the requested language"); }
}
private void speakSampleText() {
final boolean networkRequired = isNetworkRequiredForSynthesis();
if (!networkRequired || networkRequired &&
(mTts.isLanguageAvailable(mCurrentDefaultLocale) >= TextToSpeech.LANG_AVAILABLE)) {
HashMap<String, String> params = new HashMap<String, String>();
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) { if (preference == mPlayExample) {
// Get the sample text from the TTS engine; onActivityResult will do // Get the sample text from the TTS engine; onActivityResult will do
// the actual speaking // the actual speaking
getSampleText(); speakSampleText();
return true; return true;
} }
@@ -359,6 +402,15 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
private void updateWidgetState(boolean enable) { private void updateWidgetState(boolean enable) {
mPlayExample.setEnabled(enable); mPlayExample.setEnabled(enable);
mDefaultRatePref.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() { private void displayNetworkAlert() {
@@ -474,8 +526,6 @@ public class TextToSpeechSettings extends SettingsPreferenceFragment implements
} }
} }
} }
updateWidgetState(true);
} }
@Override @Override