blob: 2182894ca3df52bb8e62e732ea27270a35b51551 [file] [log] [blame]
Jean-Michel Trivied29a652009-06-05 18:37:29 -07001/*
2 * Copyright (C) 2009 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings;
18
19import static android.provider.Settings.Secure.TTS_USE_DEFAULTS;
20import static android.provider.Settings.Secure.TTS_DEFAULT_RATE;
Jean-Michel Trivi80368622009-06-09 19:29:27 -070021import static android.provider.Settings.Secure.TTS_DEFAULT_LANG;
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070022import static android.provider.Settings.Secure.TTS_DEFAULT_COUNTRY;
23import static android.provider.Settings.Secure.TTS_DEFAULT_VARIANT;
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -070024import static android.provider.Settings.Secure.TTS_DEFAULT_SYNTH;
Jean-Michel Trivied29a652009-06-05 18:37:29 -070025
26import android.content.ContentResolver;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070027import android.content.Intent;
28import android.content.pm.ActivityInfo;
29import android.content.pm.PackageManager;
30import android.content.pm.ResolveInfo;
Jean-Michel Trivied29a652009-06-05 18:37:29 -070031import android.os.Bundle;
32import android.preference.ListPreference;
33import android.preference.Preference;
34import android.preference.PreferenceActivity;
35import android.preference.CheckBoxPreference;
36import android.provider.Settings;
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070037import android.provider.Settings.SettingNotFoundException;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070038import android.speech.tts.TextToSpeech;
Jean-Michel Trivied29a652009-06-05 18:37:29 -070039import android.util.Log;
40
Charles Chenc8298712010-02-10 13:58:23 -080041import java.util.ArrayList;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070042import java.util.List;
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -070043import java.util.Locale;
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070044import java.util.StringTokenizer;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070045
Jean-Michel Trivied29a652009-06-05 18:37:29 -070046public class TextToSpeechSettings extends PreferenceActivity implements
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070047 Preference.OnPreferenceChangeListener, Preference.OnPreferenceClickListener,
48 TextToSpeech.OnInitListener {
Jean-Michel Trivied29a652009-06-05 18:37:29 -070049
50 private static final String TAG = "TextToSpeechSettings";
Jean-Michel Trivied29a652009-06-05 18:37:29 -070051
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070052 private static final String KEY_TTS_PLAY_EXAMPLE = "tts_play_example";
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070053 private static final String KEY_TTS_INSTALL_DATA = "tts_install_data";
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070054 private static final String KEY_TTS_USE_DEFAULT = "toggle_use_default_tts_settings";
Jean-Michel Trivied29a652009-06-05 18:37:29 -070055 private static final String KEY_TTS_DEFAULT_RATE = "tts_default_rate";
Jean-Michel Trivi80368622009-06-09 19:29:27 -070056 private static final String KEY_TTS_DEFAULT_LANG = "tts_default_lang";
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070057 private static final String KEY_TTS_DEFAULT_COUNTRY = "tts_default_country";
58 private static final String KEY_TTS_DEFAULT_VARIANT = "tts_default_variant";
Charles Chen5dbc74a2009-12-07 12:08:13 -080059 private static final String KEY_TTS_DEFAULT_SYNTH = "tts_default_synth";
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -070060 // TODO move default Locale values to TextToSpeech.Engine
61 private static final String DEFAULT_LANG_VAL = "eng";
62 private static final String DEFAULT_COUNTRY_VAL = "USA";
63 private static final String DEFAULT_VARIANT_VAL = "";
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070064
65 private static final String LOCALE_DELIMITER = "-";
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070066
Jean-Michel Trivi628431d2009-07-17 16:52:54 -070067 private static final String FALLBACK_TTS_DEFAULT_SYNTH =
Jean-Michel Trivi387dc0c2009-07-28 15:13:35 -070068 TextToSpeech.Engine.DEFAULT_SYNTH;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070069
70 private Preference mPlayExample = null;
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070071 private Preference mInstallData = null;
Jean-Michel Trivied29a652009-06-05 18:37:29 -070072 private CheckBoxPreference mUseDefaultPref = null;
73 private ListPreference mDefaultRatePref = null;
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070074 private ListPreference mDefaultLocPref = null;
Charles Chen5dbc74a2009-12-07 12:08:13 -080075 private ListPreference mDefaultSynthPref = null;
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -070076 private String mDefaultLanguage = null;
77 private String mDefaultCountry = null;
78 private String mDefaultLocVariant = null;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070079 private String mDefaultEng = "";
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -070080 private int mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
81
82 // Array of strings used to demonstrate TTS in the different languages.
83 private String[] mDemoStrings;
84 // Index of the current string to use for the demo.
85 private int mDemoStringIndex = 0;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070086
87 private boolean mEnableDemo = false;
Charles Chenc8298712010-02-10 13:58:23 -080088 private boolean mVoicesMissing = false;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070089
90 private TextToSpeech mTts = null;
91
92 /**
93 * Request code (arbitrary value) for voice data check through
94 * startActivityForResult.
95 */
96 private static final int VOICE_DATA_INTEGRITY_CHECK = 1977;
Charles Chen4df6c792010-01-22 11:17:40 -080097 private static final int GET_SAMPLE_TEXT = 1983;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -070098
Jean-Michel Trivied29a652009-06-05 18:37:29 -070099 @Override
100 protected void onCreate(Bundle savedInstanceState) {
101 super.onCreate(savedInstanceState);
102
103 addPreferencesFromResource(R.xml.tts_settings);
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700104
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700105 mDemoStrings = getResources().getStringArray(R.array.tts_demo_strings);
106
Jean-Michel Trivi6dde8962009-08-11 09:06:58 -0700107 setVolumeControlStream(TextToSpeech.Engine.DEFAULT_STREAM);
108
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700109 mEnableDemo = false;
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700110 initClickers();
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700111 initDefaultSettings();
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700112 }
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -0700113
114
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700115 @Override
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700116 protected void onStart() {
117 super.onStart();
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700118 // whenever we return to this screen, we don't know the state of the
119 // system, so we have to recheck that we can play the demo, or it must be disabled.
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -0700120 // TODO make the TTS service listen to "changes in the system", i.e. sd card un/mount
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700121 initClickers();
122 updateWidgetState();
123 checkVoiceData();
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700124 }
125
126
127 @Override
128 protected void onDestroy() {
129 super.onDestroy();
130 if (mTts != null) {
131 mTts.shutdown();
132 }
133 }
134
135
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700136 private void initClickers() {
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700137 mPlayExample = findPreference(KEY_TTS_PLAY_EXAMPLE);
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700138 mPlayExample.setOnPreferenceClickListener(this);
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700139
140 mInstallData = findPreference(KEY_TTS_INSTALL_DATA);
141 mInstallData.setOnPreferenceClickListener(this);
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700142 }
143
144
145 private void initDefaultSettings() {
146 ContentResolver resolver = getContentResolver();
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700147
148 // Find the default TTS values in the settings, initialize and store the
149 // settings if they are not found.
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700150
151 // "Use Defaults"
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700152 int useDefault = 0;
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700153 mUseDefaultPref = (CheckBoxPreference) findPreference(KEY_TTS_USE_DEFAULT);
154 try {
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700155 useDefault = Settings.Secure.getInt(resolver, TTS_USE_DEFAULTS);
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700156 } catch (SettingNotFoundException e) {
157 // "use default" setting not found, initialize it
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700158 useDefault = TextToSpeech.Engine.USE_DEFAULTS;
159 Settings.Secure.putInt(resolver, TTS_USE_DEFAULTS, useDefault);
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700160 }
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700161 mUseDefaultPref.setChecked(useDefault == 1);
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700162 mUseDefaultPref.setOnPreferenceChangeListener(this);
163
Charles Chen5dbc74a2009-12-07 12:08:13 -0800164 // Default synthesis engine
165 mDefaultSynthPref = (ListPreference) findPreference(KEY_TTS_DEFAULT_SYNTH);
166 loadEngines();
167 mDefaultSynthPref.setOnPreferenceChangeListener(this);
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700168 String engine = Settings.Secure.getString(resolver, TTS_DEFAULT_SYNTH);
169 if (engine == null) {
170 // TODO move FALLBACK_TTS_DEFAULT_SYNTH to TextToSpeech
171 engine = FALLBACK_TTS_DEFAULT_SYNTH;
172 Settings.Secure.putString(resolver, TTS_DEFAULT_SYNTH, engine);
173 }
174 mDefaultEng = engine;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700175
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700176 // Default rate
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700177 mDefaultRatePref = (ListPreference) findPreference(KEY_TTS_DEFAULT_RATE);
178 try {
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700179 mDefaultRate = Settings.Secure.getInt(resolver, TTS_DEFAULT_RATE);
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700180 } catch (SettingNotFoundException e) {
181 // default rate setting not found, initialize it
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700182 mDefaultRate = TextToSpeech.Engine.DEFAULT_RATE;
183 Settings.Secure.putInt(resolver, TTS_DEFAULT_RATE, mDefaultRate);
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700184 }
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700185 mDefaultRatePref.setValue(String.valueOf(mDefaultRate));
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700186 mDefaultRatePref.setOnPreferenceChangeListener(this);
187
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700188 // Default language / country / variant : these three values map to a single ListPref
189 // representing the matching Locale
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700190 mDefaultLocPref = (ListPreference) findPreference(KEY_TTS_DEFAULT_LANG);
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700191 initDefaultLang();
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700192 mDefaultLocPref.setOnPreferenceChangeListener(this);
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700193 }
194
195
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700196 /**
197 * Ask the current default engine to launch the matching CHECK_TTS_DATA activity
198 * to check the required TTS files are properly installed.
199 */
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700200 private void checkVoiceData() {
201 PackageManager pm = getPackageManager();
202 Intent intent = new Intent();
Jean-Michel Trivi387dc0c2009-07-28 15:13:35 -0700203 intent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700204 List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
205 // query only the package that matches that of the default engine
206 for (int i = 0; i < resolveInfos.size(); i++) {
207 ActivityInfo currentActivityInfo = resolveInfos.get(i).activityInfo;
208 if (mDefaultEng.equals(currentActivityInfo.packageName)) {
209 intent.setClassName(mDefaultEng, currentActivityInfo.name);
210 this.startActivityForResult(intent, VOICE_DATA_INTEGRITY_CHECK);
211 }
212 }
213 }
214
215
216 /**
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700217 * Ask the current default engine to launch the matching INSTALL_TTS_DATA activity
218 * so the required TTS files are properly installed.
219 */
220 private void installVoiceData() {
221 PackageManager pm = getPackageManager();
222 Intent intent = new Intent();
Jean-Michel Trivi387dc0c2009-07-28 15:13:35 -0700223 intent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
Jean-Michel Trivi58ea43a2009-09-09 15:13:38 -0700224 intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700225 List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
226 // query only the package that matches that of the default engine
227 for (int i = 0; i < resolveInfos.size(); i++) {
228 ActivityInfo currentActivityInfo = resolveInfos.get(i).activityInfo;
229 if (mDefaultEng.equals(currentActivityInfo.packageName)) {
230 intent.setClassName(mDefaultEng, currentActivityInfo.name);
Jean-Michel Trivi58ea43a2009-09-09 15:13:38 -0700231 this.startActivity(intent);
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700232 }
233 }
234 }
235
Charles Chen4df6c792010-01-22 11:17:40 -0800236 /**
237 * Ask the current default engine to return a string of sample text to be
238 * spoken to the user.
239 */
240 private void getSampleText() {
241 PackageManager pm = getPackageManager();
242 Intent intent = new Intent();
243 // TODO (clchen): Replace Intent string with the actual
244 // Intent defined in the list of platform Intents.
245 intent.setAction("android.speech.tts.engine.GET_SAMPLE_TEXT");
246 intent.putExtra("language", mDefaultLanguage);
247 intent.putExtra("country", mDefaultCountry);
248 intent.putExtra("variant", mDefaultLocVariant);
249 List<ResolveInfo> resolveInfos = pm.queryIntentActivities(intent, 0);
250 // query only the package that matches that of the default engine
251 for (int i = 0; i < resolveInfos.size(); i++) {
252 ActivityInfo currentActivityInfo = resolveInfos.get(i).activityInfo;
253 if (mDefaultEng.equals(currentActivityInfo.packageName)) {
254 intent.setClassName(mDefaultEng, currentActivityInfo.name);
255 this.startActivityForResult(intent, GET_SAMPLE_TEXT);
256 }
257 }
258 }
259
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700260
261 /**
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700262 * Called when the TTS engine is initialized.
263 */
264 public void onInit(int status) {
Jean-Michel Trivi387dc0c2009-07-28 15:13:35 -0700265 if (status == TextToSpeech.SUCCESS) {
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700266 Log.v(TAG, "TTS engine for settings screen initialized.");
267 mEnableDemo = true;
Jean-Michel Trivi7330a882010-02-17 12:50:44 -0800268 if (mDefaultLanguage == null) {
Charles Chencf3998b2010-02-11 18:13:42 -0800269 mDefaultLanguage = Locale.getDefault().getISO3Language();
270 }
Jean-Michel Trivi7330a882010-02-17 12:50:44 -0800271 if (mDefaultCountry == null) {
272 mDefaultCountry = Locale.getDefault().getISO3Country();
273 }
274 if (mDefaultLocVariant == null) {
275 mDefaultLocVariant = new String();
276 }
Charles Chencf3998b2010-02-11 18:13:42 -0800277 mTts.setLanguage(new Locale(mDefaultLanguage, mDefaultCountry, mDefaultLocVariant));
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700278 mTts.setSpeechRate((float)(mDefaultRate/100.0f));
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700279 } else {
280 Log.v(TAG, "TTS engine for settings screen failed to initialize successfully.");
281 mEnableDemo = false;
282 }
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700283 updateWidgetState();
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700284 }
285
286
287 /**
288 * Called when voice data integrity check returns
289 */
290 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
291 if (requestCode == VOICE_DATA_INTEGRITY_CHECK) {
Charles Chend5f013a2010-02-18 10:11:25 -0800292 if (data == null){
293 // The CHECK_TTS_DATA activity for the plugin did not run properly;
294 // disable the preview and install controls and return.
295 mEnableDemo = false;
296 mVoicesMissing = false;
297 updateWidgetState();
298 return;
299 }
Charles Chenc8298712010-02-10 13:58:23 -0800300 // TODO (clchen): Add these extras to TextToSpeech.Engine
301 ArrayList<String> available =
302 data.getStringArrayListExtra("TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES");
303 ArrayList<String> unavailable =
304 data.getStringArrayListExtra("TextToSpeech.Engine.EXTRA_UNAVAILABLE_VOICES");
Charles Chend5f013a2010-02-18 10:11:25 -0800305 if ((available == null) || (unavailable == null)){
306 // The CHECK_TTS_DATA activity for the plugin did not run properly;
307 // disable the preview and install controls and return.
308 mEnableDemo = false;
309 mVoicesMissing = false;
310 updateWidgetState();
311 return;
312 }
Charles Chenc8298712010-02-10 13:58:23 -0800313 if (available.size() > 0){
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700314 if (mTts == null) {
315 mTts = new TextToSpeech(this, this);
316 }
Charles Chenc8298712010-02-10 13:58:23 -0800317 ListPreference ttsLanguagePref =
318 (ListPreference) findPreference("tts_default_lang");
319 CharSequence[] entries = new CharSequence[available.size()];
320 CharSequence[] entryValues = new CharSequence[available.size()];
321 for (int i=0; i<available.size(); i++){
322 String[] langCountryVariant = available.get(i).split("-");
323 Locale loc = null;
324 if (langCountryVariant.length == 1){
325 loc = new Locale(langCountryVariant[0]);
326 } else if (langCountryVariant.length == 2){
327 loc = new Locale(langCountryVariant[0], langCountryVariant[1]);
328 } else if (langCountryVariant.length == 3){
329 loc = new Locale(langCountryVariant[0], langCountryVariant[1],
330 langCountryVariant[2]);
331 }
332 if (loc != null){
333 entries[i] = loc.getDisplayName();
334 entryValues[i] = available.get(i);
335 }
336 }
337 ttsLanguagePref.setEntries(entries);
338 ttsLanguagePref.setEntryValues(entryValues);
339 mEnableDemo = true;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700340 } else {
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700341 mEnableDemo = false;
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700342 }
Charles Chenc8298712010-02-10 13:58:23 -0800343
344 if (unavailable.size() > 0){
345 mVoicesMissing = true;
346 } else {
347 mVoicesMissing = false;
348 }
349
350 updateWidgetState();
Charles Chen4df6c792010-01-22 11:17:40 -0800351 } else if (requestCode == GET_SAMPLE_TEXT) {
352 if (resultCode == TextToSpeech.LANG_AVAILABLE) {
Charles Chend5f013a2010-02-18 10:11:25 -0800353 if (data == null){
354 // The GET_SAMPLE_TEXT activity for the plugin did not run properly;
355 // return without doing anything.
356 return;
357 }
Charles Chen4df6c792010-01-22 11:17:40 -0800358 if (mTts != null) {
Charles Chend5f013a2010-02-18 10:11:25 -0800359 String sample = data.getStringExtra("sampleText");
360 if (sample == null){
361 // The GET_SAMPLE_TEXT activity for the plugin did not run properly;
362 // return without doing anything.
363 return;
364 }
Charles Chen4df6c792010-01-22 11:17:40 -0800365 mTts.speak(sample, TextToSpeech.QUEUE_FLUSH, null);
366 }
367 } else {
368 // TODO: Display an error here to the user.
369 Log.e(TAG, "Did not have a sample string for the requested language");
370 }
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700371 }
372 }
373
374
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700375 public boolean onPreferenceChange(Preference preference, Object objValue) {
376 if (KEY_TTS_USE_DEFAULT.equals(preference.getKey())) {
377 // "Use Defaults"
378 int value = (Boolean)objValue ? 1 : 0;
Jean-Michel Trivi80368622009-06-09 19:29:27 -0700379 Settings.Secure.putInt(getContentResolver(), TTS_USE_DEFAULTS,
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700380 value);
381 Log.i(TAG, "TTS use default settings is "+objValue.toString());
382 } else if (KEY_TTS_DEFAULT_RATE.equals(preference.getKey())) {
383 // Default rate
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700384 mDefaultRate = Integer.parseInt((String) objValue);
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700385 try {
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -0700386 Settings.Secure.putInt(getContentResolver(),
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700387 TTS_DEFAULT_RATE, mDefaultRate);
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700388 if (mTts != null) {
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700389 mTts.setSpeechRate((float)(mDefaultRate/100.0f));
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700390 }
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700391 Log.i(TAG, "TTS default rate is " + mDefaultRate);
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700392 } catch (NumberFormatException e) {
393 Log.e(TAG, "could not persist default TTS rate setting", e);
394 }
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700395 } else if (KEY_TTS_DEFAULT_LANG.equals(preference.getKey())) {
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700396 // Default locale
397 ContentResolver resolver = getContentResolver();
398 parseLocaleInfo((String) objValue);
399 Settings.Secure.putString(resolver, TTS_DEFAULT_LANG, mDefaultLanguage);
400 Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, mDefaultCountry);
401 Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, mDefaultLocVariant);
402 Log.v(TAG, "TTS default lang/country/variant set to "
403 + mDefaultLanguage + "/" + mDefaultCountry + "/" + mDefaultLocVariant);
Jean-Michel Trivi628431d2009-07-17 16:52:54 -0700404 if (mTts != null) {
Charles Chencf3998b2010-02-11 18:13:42 -0800405 mTts.setLanguage(new Locale(mDefaultLanguage, mDefaultCountry, mDefaultLocVariant));
Jean-Michel Trivi628431d2009-07-17 16:52:54 -0700406 }
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700407 int newIndex = mDefaultLocPref.findIndexOfValue((String)objValue);
408 Log.v("Settings", " selected is " + newIndex);
409 mDemoStringIndex = newIndex > -1 ? newIndex : 0;
Charles Chen5dbc74a2009-12-07 12:08:13 -0800410 } else if (KEY_TTS_DEFAULT_SYNTH.equals(preference.getKey())) {
Charles Chen5dbc74a2009-12-07 12:08:13 -0800411 mDefaultEng = objValue.toString();
412 Settings.Secure.putString(getContentResolver(), TTS_DEFAULT_SYNTH, mDefaultEng);
413 if (mTts != null) {
414 mTts.setEngineByPackageName(mDefaultEng);
Charles Chencf3998b2010-02-11 18:13:42 -0800415 mEnableDemo = false;
416 mVoicesMissing = false;
417 updateWidgetState();
418 checkVoiceData();
Charles Chen5dbc74a2009-12-07 12:08:13 -0800419 }
420 Log.v("Settings", "The default synth is: " + objValue.toString());
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700421 }
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -0700422
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700423 return true;
424 }
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -0700425
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700426
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700427 /**
428 * Called when mPlayExample or mInstallData is clicked
429 */
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700430 public boolean onPreferenceClick(Preference preference) {
431 if (preference == mPlayExample) {
Charles Chen4df6c792010-01-22 11:17:40 -0800432 // Get the sample text from the TTS engine; onActivityResult will do
433 // the actual speaking
434 getSampleText();
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700435 return true;
436 }
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700437 if (preference == mInstallData) {
Jean-Michel Trivi2acc02e2009-06-25 10:03:43 -0700438 installVoiceData();
439 // quit this activity so it needs to be restarted after installation of the voice data
440 finish();
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700441 return true;
442 }
Jean-Michel Trivi74e565d2009-06-18 18:44:52 -0700443 return false;
444 }
445
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700446
447 private void updateWidgetState() {
448 mPlayExample.setEnabled(mEnableDemo);
449 mUseDefaultPref.setEnabled(mEnableDemo);
450 mDefaultRatePref.setEnabled(mEnableDemo);
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700451 mDefaultLocPref.setEnabled(mEnableDemo);
452
Charles Chenc8298712010-02-10 13:58:23 -0800453 mInstallData.setEnabled(mVoicesMissing);
Jean-Michel Trivi1e6a45a2009-06-22 16:03:40 -0700454 }
455
456
457 private void parseLocaleInfo(String locale) {
458 StringTokenizer tokenizer = new StringTokenizer(locale, LOCALE_DELIMITER);
459 mDefaultLanguage = "";
460 mDefaultCountry = "";
461 mDefaultLocVariant = "";
462 if (tokenizer.hasMoreTokens()) {
463 mDefaultLanguage = tokenizer.nextToken().trim();
464 }
465 if (tokenizer.hasMoreTokens()) {
466 mDefaultCountry = tokenizer.nextToken().trim();
467 }
468 if (tokenizer.hasMoreTokens()) {
469 mDefaultLocVariant = tokenizer.nextToken().trim();
470 }
471 }
472
473
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700474 /**
475 * Initialize the default language in the UI and in the preferences.
476 * After this method has been invoked, the default language is a supported Locale.
477 */
478 private void initDefaultLang() {
479 // if there isn't already a default language preference
480 if (!hasLangPref()) {
481 // if the current Locale is supported
482 if (isCurrentLocSupported()) {
483 // then use the current Locale as the default language
484 useCurrentLocAsDefault();
485 } else {
486 // otherwise use a default supported Locale as the default language
487 useSupportedLocAsDefault();
488 }
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -0700489 }
490
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700491 // Update the language preference list with the default language and the matching
492 // demo string (at this stage there is a default language pref)
493 ContentResolver resolver = getContentResolver();
494 mDefaultLanguage = Settings.Secure.getString(resolver, TTS_DEFAULT_LANG);
495 mDefaultCountry = Settings.Secure.getString(resolver, KEY_TTS_DEFAULT_COUNTRY);
496 mDefaultLocVariant = Settings.Secure.getString(resolver, KEY_TTS_DEFAULT_VARIANT);
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -0700497
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700498 // update the demo string
499 mDemoStringIndex = mDefaultLocPref.findIndexOfValue(mDefaultLanguage + LOCALE_DELIMITER
500 + mDefaultCountry);
Charles Chen8a37e612010-02-04 15:52:30 -0800501 if (mDemoStringIndex > -1){
502 mDefaultLocPref.setValueIndex(mDemoStringIndex);
503 }
Jean-Michel Trivie8e23db2009-09-02 15:15:33 -0700504 }
505
506 /**
507 * (helper function for initDefaultLang() )
508 * Returns whether there is a default language in the TTS settings.
509 */
510 private boolean hasLangPref() {
511 String language = Settings.Secure.getString(getContentResolver(), TTS_DEFAULT_LANG);
512 return (language != null);
513 }
514
515 /**
516 * (helper function for initDefaultLang() )
517 * Returns whether the current Locale is supported by this Settings screen
518 */
519 private boolean isCurrentLocSupported() {
520 String currentLocID = Locale.getDefault().getISO3Language() + LOCALE_DELIMITER
521 + Locale.getDefault().getISO3Country();
522 return (mDefaultLocPref.findIndexOfValue(currentLocID) > -1);
523 }
524
525 /**
526 * (helper function for initDefaultLang() )
527 * Sets the default language in TTS settings to be the current Locale.
528 * This should only be used after checking that the current Locale is supported.
529 */
530 private void useCurrentLocAsDefault() {
531 Locale currentLocale = Locale.getDefault();
532 ContentResolver resolver = getContentResolver();
533 Settings.Secure.putString(resolver, TTS_DEFAULT_LANG, currentLocale.getISO3Language());
534 Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, currentLocale.getISO3Country());
535 Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, currentLocale.getVariant());
536 }
537
538 /**
539 * (helper function for initDefaultLang() )
540 * Sets the default language in TTS settings to be one known to be supported
541 */
542 private void useSupportedLocAsDefault() {
543 ContentResolver resolver = getContentResolver();
544 Settings.Secure.putString(resolver, TTS_DEFAULT_LANG, DEFAULT_LANG_VAL);
545 Settings.Secure.putString(resolver, TTS_DEFAULT_COUNTRY, DEFAULT_COUNTRY_VAL);
546 Settings.Secure.putString(resolver, TTS_DEFAULT_VARIANT, DEFAULT_VARIANT_VAL);
Jean-Michel Trivi44fbbea2009-07-06 14:04:54 -0700547 }
548
Charles Chen5dbc74a2009-12-07 12:08:13 -0800549
550 private void loadEngines() {
551 ListPreference enginesPref = (ListPreference) findPreference(KEY_TTS_DEFAULT_SYNTH);
552
553 Intent intent = new Intent("android.intent.action.START_TTS_ENGINE");
554
555 ResolveInfo[] enginesArray = new ResolveInfo[0];
556 PackageManager pm = getPackageManager();
557 enginesArray = pm.queryIntentActivities(intent, 0).toArray(enginesArray);
558 CharSequence entries[] = new CharSequence[enginesArray.length];
559 CharSequence values[] = new CharSequence[enginesArray.length];
560 for (int i = 0; i < enginesArray.length; i++) {
561 entries[i] = enginesArray[i].loadLabel(pm);
562 values[i] = enginesArray[i].activityInfo.packageName;
563 }
564 enginesPref.setEntries(entries);
565 enginesPref.setEntryValues(values);
566 }
567
Jean-Michel Trivied29a652009-06-05 18:37:29 -0700568}