TextToSpeech.java revision 9011ec832d78982d017b1cef55a54af44ba2a447
1/* 2 * Copyright (C) 2009 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy of 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations under 14 * the License. 15 */ 16package android.speech.tts; 17 18import android.speech.tts.ITts; 19import android.speech.tts.ITtsCallback; 20 21import android.annotation.SdkConstant; 22import android.annotation.SdkConstant.SdkConstantType; 23import android.content.ComponentName; 24import android.content.Context; 25import android.content.Intent; 26import android.content.ServiceConnection; 27import android.media.AudioManager; 28import android.os.IBinder; 29import android.os.RemoteException; 30import android.util.Log; 31 32import java.util.HashMap; 33import java.util.Locale; 34 35/** 36 * 37 * Synthesizes speech from text for immediate playback or to create a sound file. 38 * <p>A TextToSpeech instance can only be used to synthesize text once it has completed its 39 * initialization. Implement the {@link TextToSpeech.OnInitListener} to be 40 * notified of the completion of the initialization.<br> 41 * When you are done using the TextToSpeech instance, call the {@link #shutdown()} method 42 * to release the native resources used by the TextToSpeech engine. 43 * 44 */ 45public class TextToSpeech { 46 47 /** 48 * Denotes a successful operation. 49 */ 50 public static final int SUCCESS = 0; 51 /** 52 * Denotes a generic operation failure. 53 */ 54 public static final int ERROR = -1; 55 56 /** 57 * Queue mode where all entries in the playback queue (media to be played 58 * and text to be synthesized) are dropped and replaced by the new entry. 59 */ 60 public static final int QUEUE_FLUSH = 0; 61 /** 62 * Queue mode where the new entry is added at the end of the playback queue. 63 */ 64 public static final int QUEUE_ADD = 1; 65 66 67 /** 68 * Denotes the language is available exactly as specified by the locale. 69 */ 70 public static final int LANG_COUNTRY_VAR_AVAILABLE = 2; 71 72 73 /** 74 * Denotes the language is available for the language and country specified 75 * by the locale, but not the variant. 76 */ 77 public static final int LANG_COUNTRY_AVAILABLE = 1; 78 79 80 /** 81 * Denotes the language is available for the language by the locale, 82 * but not the country and variant. 83 */ 84 public static final int LANG_AVAILABLE = 0; 85 86 /** 87 * Denotes the language data is missing. 88 */ 89 public static final int LANG_MISSING_DATA = -1; 90 91 /** 92 * Denotes the language is not supported. 93 */ 94 public static final int LANG_NOT_SUPPORTED = -2; 95 96 97 /** 98 * Broadcast Action: The TextToSpeech synthesizer has completed processing 99 * of all the text in the speech queue. 100 */ 101 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 102 public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = 103 "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED"; 104 105 106 /** 107 * Interface definition of a callback to be invoked indicating the completion of the 108 * TextToSpeech engine initialization. 109 */ 110 public interface OnInitListener { 111 /** 112 * Called to signal the completion of the TextToSpeech engine initialization. 113 * @param status {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}. 114 */ 115 public void onInit(int status); 116 } 117 118 /** 119 * Interface definition of a callback to be invoked indicating the TextToSpeech engine has 120 * completed synthesizing an utterance with an utterance ID set. 121 * 122 */ 123 public interface OnUtteranceCompletedListener { 124 /** 125 * Called to signal the completion of the synthesis of the utterance that was identified 126 * with the string parameter. This identifier is the one originally passed in the 127 * parameter hashmap of the synthesis request in 128 * {@link TextToSpeech#speak(String, int, HashMap)} or 129 * {@link TextToSpeech#synthesizeToFile(String, HashMap, String)} with the 130 * {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID} key. 131 * @param utteranceId the identifier of the utterance. 132 */ 133 public void onUtteranceCompleted(String utteranceId); 134 } 135 136 137 /** 138 * Internal constants for the TextToSpeech functionality 139 * 140 */ 141 public class Engine { 142 // default values for a TTS engine when settings are not found in the provider 143 /** 144 * {@hide} 145 */ 146 public static final int DEFAULT_RATE = 100; // 1x 147 /** 148 * {@hide} 149 */ 150 public static final int DEFAULT_PITCH = 100;// 1x 151 /** 152 * {@hide} 153 */ 154 public static final float DEFAULT_VOLUME = 1.0f; 155 /** 156 * {@hide} 157 */ 158 protected static final String DEFAULT_VOLUME_STRING = "1.0"; 159 /** 160 * {@hide} 161 */ 162 public static final float DEFAULT_PAN = 0.0f; 163 /** 164 * {@hide} 165 */ 166 protected static final String DEFAULT_PAN_STRING = "0.0"; 167 168 /** 169 * {@hide} 170 */ 171 public static final int USE_DEFAULTS = 0; // false 172 /** 173 * {@hide} 174 */ 175 public static final String DEFAULT_SYNTH = "com.svox.pico"; 176 177 // default values for rendering 178 /** 179 * Default audio stream used when playing synthesized speech. 180 */ 181 public static final int DEFAULT_STREAM = AudioManager.STREAM_MUSIC; 182 183 // return codes for a TTS engine's check data activity 184 /** 185 * Indicates success when checking the installation status of the resources used by the 186 * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 187 */ 188 public static final int CHECK_VOICE_DATA_PASS = 1; 189 /** 190 * Indicates failure when checking the installation status of the resources used by the 191 * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 192 */ 193 public static final int CHECK_VOICE_DATA_FAIL = 0; 194 /** 195 * Indicates erroneous data when checking the installation status of the resources used by 196 * the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 197 */ 198 public static final int CHECK_VOICE_DATA_BAD_DATA = -1; 199 /** 200 * Indicates missing resources when checking the installation status of the resources used 201 * by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 202 */ 203 public static final int CHECK_VOICE_DATA_MISSING_DATA = -2; 204 /** 205 * Indicates missing storage volume when checking the installation status of the resources 206 * used by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. 207 */ 208 public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3; 209 210 // intents to ask engine to install data or check its data 211 /** 212 * Activity Action: Triggers the platform TextToSpeech engine to 213 * start the activity that installs the resource files on the device 214 * that are required for TTS to be operational. Since the installation 215 * of the data can be interrupted or declined by the user, the application 216 * shouldn't expect successful installation upon return from that intent, 217 * and if need be, should check installation status with 218 * {@link #ACTION_CHECK_TTS_DATA}. 219 */ 220 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 221 public static final String ACTION_INSTALL_TTS_DATA = 222 "android.speech.tts.engine.INSTALL_TTS_DATA"; 223 224 /** 225 * Broadcast Action: broadcast to signal the completion of the installation of 226 * the data files used by the synthesis engine. Success or failure is indicated in the 227 * {@link #EXTRA_TTS_DATA_INSTALLED} extra. 228 */ 229 @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) 230 public static final String ACTION_TTS_DATA_INSTALLED = 231 "android.speech.tts.engine.TTS_DATA_INSTALLED"; 232 /** 233 * Activity Action: Starts the activity from the platform TextToSpeech 234 * engine to verify the proper installation and availability of the 235 * resource files on the system. Upon completion, the activity will 236 * return one of the following codes: 237 * {@link #CHECK_VOICE_DATA_PASS}, 238 * {@link #CHECK_VOICE_DATA_FAIL}, 239 * {@link #CHECK_VOICE_DATA_BAD_DATA}, 240 * {@link #CHECK_VOICE_DATA_MISSING_DATA}, or 241 * {@link #CHECK_VOICE_DATA_MISSING_VOLUME}. 242 * <p> Moreover, the data received in the activity result will contain the following 243 * fields: 244 * <ul> 245 * <li>{@link #EXTRA_VOICE_DATA_ROOT_DIRECTORY} which 246 * indicates the path to the location of the resource files,</li> 247 * <li>{@link #EXTRA_VOICE_DATA_FILES} which contains 248 * the list of all the resource files,</li> 249 * <li>and {@link #EXTRA_VOICE_DATA_FILES_INFO} which 250 * contains, for each resource file, the description of the language covered by 251 * the file in the xxx-YYY format, where xxx is the 3-letter ISO language code, 252 * and YYY is the 3-letter ISO country code.</li> 253 * </ul> 254 */ 255 @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) 256 public static final String ACTION_CHECK_TTS_DATA = 257 "android.speech.tts.engine.CHECK_TTS_DATA"; 258 259 // extras for a TTS engine's check data activity 260 /** 261 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 262 * the TextToSpeech engine specifies the path to its resources. 263 */ 264 public static final String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot"; 265 /** 266 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 267 * the TextToSpeech engine specifies the file names of its resources under the 268 * resource path. 269 */ 270 public static final String EXTRA_VOICE_DATA_FILES = "dataFiles"; 271 /** 272 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 273 * the TextToSpeech engine specifies the locale associated with each resource file. 274 */ 275 public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo"; 276 /** 277 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 278 * the TextToSpeech engine returns an ArrayList<String> of all the available voices. 279 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are 280 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). 281 */ 282 public static final String EXTRA_AVAILABLE_VOICES = "availableVoices"; 283 /** 284 * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where 285 * the TextToSpeech engine returns an ArrayList<String> of all the unavailable voices. 286 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are 287 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). 288 */ 289 public static final String EXTRA_UNAVAILABLE_VOICES = "unavailableVoices"; 290 /** 291 * Extra information sent with the {@link #ACTION_CHECK_TTS_DATA} intent where the 292 * caller indicates to the TextToSpeech engine which specific sets of voice data to 293 * check for by sending an ArrayList<String> of the voices that are of interest. 294 * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are 295 * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). 296 */ 297 public static final String EXTRA_CHECK_VOICE_DATA_FOR = "checkVoiceDataFor"; 298 299 // extras for a TTS engine's data installation 300 /** 301 * Extra information received with the {@link #ACTION_TTS_DATA_INSTALLED} intent. 302 * It indicates whether the data files for the synthesis engine were successfully 303 * installed. The installation was initiated with the {@link #ACTION_INSTALL_TTS_DATA} 304 * intent. The possible values for this extra are 305 * {@link TextToSpeech#SUCCESS} and {@link TextToSpeech#ERROR}. 306 */ 307 public static final String EXTRA_TTS_DATA_INSTALLED = "dataInstalled"; 308 309 // keys for the parameters passed with speak commands. Hidden keys are used internally 310 // to maintain engine state for each TextToSpeech instance. 311 /** 312 * {@hide} 313 */ 314 public static final String KEY_PARAM_RATE = "rate"; 315 /** 316 * {@hide} 317 */ 318 public static final String KEY_PARAM_LANGUAGE = "language"; 319 /** 320 * {@hide} 321 */ 322 public static final String KEY_PARAM_COUNTRY = "country"; 323 /** 324 * {@hide} 325 */ 326 public static final String KEY_PARAM_VARIANT = "variant"; 327 /** 328 * {@hide} 329 */ 330 public static final String KEY_PARAM_ENGINE = "engine"; 331 /** 332 * {@hide} 333 */ 334 public static final String KEY_PARAM_PITCH = "pitch"; 335 /** 336 * Parameter key to specify the audio stream type to be used when speaking text 337 * or playing back a file. 338 * @see TextToSpeech#speak(String, int, HashMap) 339 * @see TextToSpeech#playEarcon(String, int, HashMap) 340 */ 341 public static final String KEY_PARAM_STREAM = "streamType"; 342 /** 343 * Parameter key to identify an utterance in the 344 * {@link TextToSpeech.OnUtteranceCompletedListener} after text has been 345 * spoken, a file has been played back or a silence duration has elapsed. 346 * @see TextToSpeech#speak(String, int, HashMap) 347 * @see TextToSpeech#playEarcon(String, int, HashMap) 348 * @see TextToSpeech#synthesizeToFile(String, HashMap, String) 349 */ 350 public static final String KEY_PARAM_UTTERANCE_ID = "utteranceId"; 351 /** 352 * Parameter key to specify the speech volume relative to the current stream type 353 * volume used when speaking text. Volume is specified as a float ranging from 0 to 1 354 * where 0 is silence, and 1 is the maximum volume (the default behavior). 355 * @see TextToSpeech#speak(String, int, HashMap) 356 * @see TextToSpeech#playEarcon(String, int, HashMap) 357 */ 358 public static final String KEY_PARAM_VOLUME = "volume"; 359 /** 360 * Parameter key to specify how the speech is panned from left to right when speaking text. 361 * Pan is specified as a float ranging from -1 to +1 where -1 maps to a hard-left pan, 362 * 0 to center (the default behavior), and +1 to hard-right. 363 * @see TextToSpeech#speak(String, int, HashMap) 364 * @see TextToSpeech#playEarcon(String, int, HashMap) 365 */ 366 public static final String KEY_PARAM_PAN = "pan"; 367 368 // key positions in the array of cached parameters 369 /** 370 * {@hide} 371 */ 372 protected static final int PARAM_POSITION_RATE = 0; 373 /** 374 * {@hide} 375 */ 376 protected static final int PARAM_POSITION_LANGUAGE = 2; 377 /** 378 * {@hide} 379 */ 380 protected static final int PARAM_POSITION_COUNTRY = 4; 381 /** 382 * {@hide} 383 */ 384 protected static final int PARAM_POSITION_VARIANT = 6; 385 /** 386 * {@hide} 387 */ 388 protected static final int PARAM_POSITION_STREAM = 8; 389 /** 390 * {@hide} 391 */ 392 protected static final int PARAM_POSITION_UTTERANCE_ID = 10; 393 394 /** 395 * {@hide} 396 */ 397 protected static final int PARAM_POSITION_ENGINE = 12; 398 399 /** 400 * {@hide} 401 */ 402 protected static final int PARAM_POSITION_PITCH = 14; 403 404 /** 405 * {@hide} 406 */ 407 protected static final int PARAM_POSITION_VOLUME = 16; 408 409 /** 410 * {@hide} 411 */ 412 protected static final int PARAM_POSITION_PAN = 18; 413 414 415 /** 416 * {@hide} 417 */ 418 protected static final int NB_CACHED_PARAMS = 20; 419 } 420 421 /** 422 * Connection needed for the TTS. 423 */ 424 private ServiceConnection mServiceConnection; 425 426 private ITts mITts = null; 427 private ITtsCallback mITtscallback = null; 428 private Context mContext = null; 429 private String mPackageName = ""; 430 private OnInitListener mInitListener = null; 431 private boolean mStarted = false; 432 private final Object mStartLock = new Object(); 433 /** 434 * Used to store the cached parameters sent along with each synthesis request to the 435 * TTS service. 436 */ 437 private String[] mCachedParams; 438 439 /** 440 * The constructor for the TextToSpeech class. 441 * This will also initialize the associated TextToSpeech engine if it isn't already running. 442 * 443 * @param context 444 * The context this instance is running in. 445 * @param listener 446 * The {@link TextToSpeech.OnInitListener} that will be called when the 447 * TextToSpeech engine has initialized. 448 */ 449 public TextToSpeech(Context context, OnInitListener listener) { 450 mContext = context; 451 mPackageName = mContext.getPackageName(); 452 mInitListener = listener; 453 454 mCachedParams = new String[2*Engine.NB_CACHED_PARAMS]; // store key and value 455 mCachedParams[Engine.PARAM_POSITION_RATE] = Engine.KEY_PARAM_RATE; 456 mCachedParams[Engine.PARAM_POSITION_LANGUAGE] = Engine.KEY_PARAM_LANGUAGE; 457 mCachedParams[Engine.PARAM_POSITION_COUNTRY] = Engine.KEY_PARAM_COUNTRY; 458 mCachedParams[Engine.PARAM_POSITION_VARIANT] = Engine.KEY_PARAM_VARIANT; 459 mCachedParams[Engine.PARAM_POSITION_STREAM] = Engine.KEY_PARAM_STREAM; 460 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID; 461 mCachedParams[Engine.PARAM_POSITION_ENGINE] = Engine.KEY_PARAM_ENGINE; 462 mCachedParams[Engine.PARAM_POSITION_PITCH] = Engine.KEY_PARAM_PITCH; 463 mCachedParams[Engine.PARAM_POSITION_VOLUME] = Engine.KEY_PARAM_VOLUME; 464 mCachedParams[Engine.PARAM_POSITION_PAN] = Engine.KEY_PARAM_PAN; 465 466 // Leave all defaults that are shown in Settings uninitialized/at the default 467 // so that the values set in Settings will take effect if the application does 468 // not try to change these settings itself. 469 mCachedParams[Engine.PARAM_POSITION_RATE + 1] = ""; 470 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = ""; 471 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = ""; 472 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = ""; 473 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = 474 String.valueOf(Engine.DEFAULT_STREAM); 475 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = ""; 476 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = ""; 477 mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = "100"; 478 mCachedParams[Engine.PARAM_POSITION_VOLUME + 1] = Engine.DEFAULT_VOLUME_STRING; 479 mCachedParams[Engine.PARAM_POSITION_PAN + 1] = Engine.DEFAULT_PAN_STRING; 480 481 initTts(); 482 } 483 484 485 private void initTts() { 486 mStarted = false; 487 488 // Initialize the TTS, run the callback after the binding is successful 489 mServiceConnection = new ServiceConnection() { 490 public void onServiceConnected(ComponentName name, IBinder service) { 491 synchronized(mStartLock) { 492 mITts = ITts.Stub.asInterface(service); 493 mStarted = true; 494 // Cache the default engine and current language 495 setEngineByPackageName(getDefaultEngine()); 496 setLanguage(getLanguage()); 497 if (mInitListener != null) { 498 // TODO manage failures and missing resources 499 mInitListener.onInit(SUCCESS); 500 } 501 } 502 } 503 504 public void onServiceDisconnected(ComponentName name) { 505 synchronized(mStartLock) { 506 mITts = null; 507 mInitListener = null; 508 mStarted = false; 509 } 510 } 511 }; 512 513 Intent intent = new Intent("android.intent.action.START_TTS_SERVICE"); 514 intent.addCategory("android.intent.category.TTS"); 515 mContext.bindService(intent, mServiceConnection, 516 Context.BIND_AUTO_CREATE); 517 // TODO handle case where the binding works (should always work) but 518 // the plugin fails 519 } 520 521 522 /** 523 * Releases the resources used by the TextToSpeech engine. 524 * It is good practice for instance to call this method in the onDestroy() method of an Activity 525 * so the TextToSpeech engine can be cleanly stopped. 526 */ 527 public void shutdown() { 528 try { 529 mContext.unbindService(mServiceConnection); 530 } catch (IllegalArgumentException e) { 531 // Do nothing and fail silently since an error here indicates that 532 // binding never succeeded in the first place. 533 } 534 } 535 536 537 /** 538 * Adds a mapping between a string of text and a sound resource in a 539 * package. After a call to this method, subsequent calls to 540 * {@link #speak(String, int, HashMap)} will play the specified sound resource 541 * if it is available, or synthesize the text it is missing. 542 * 543 * @param text 544 * The string of text. Example: <code>"south_south_east"</code> 545 * 546 * @param packagename 547 * Pass the packagename of the application that contains the 548 * resource. If the resource is in your own application (this is 549 * the most common case), then put the packagename of your 550 * application here.<br/> 551 * Example: <b>"com.google.marvin.compass"</b><br/> 552 * The packagename can be found in the AndroidManifest.xml of 553 * your application. 554 * <p> 555 * <code><manifest xmlns:android="..." 556 * package="<b>com.google.marvin.compass</b>"></code> 557 * </p> 558 * 559 * @param resourceId 560 * Example: <code>R.raw.south_south_east</code> 561 * 562 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 563 */ 564 public int addSpeech(String text, String packagename, int resourceId) { 565 synchronized(mStartLock) { 566 if (!mStarted) { 567 return ERROR; 568 } 569 try { 570 mITts.addSpeech(mPackageName, text, packagename, resourceId); 571 return SUCCESS; 572 } catch (RemoteException e) { 573 // TTS died; restart it. 574 Log.e("TextToSpeech.java - addSpeech", "RemoteException"); 575 e.printStackTrace(); 576 mStarted = false; 577 initTts(); 578 } catch (NullPointerException e) { 579 // TTS died; restart it. 580 Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); 581 e.printStackTrace(); 582 mStarted = false; 583 initTts(); 584 } catch (IllegalStateException e) { 585 // TTS died; restart it. 586 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); 587 e.printStackTrace(); 588 mStarted = false; 589 initTts(); 590 } 591 return ERROR; 592 } 593 } 594 595 596 /** 597 * Adds a mapping between a string of text and a sound file. Using this, it 598 * is possible to add custom pronounciations for a string of text. 599 * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)} 600 * will play the specified sound resource if it is available, or synthesize the text it is 601 * missing. 602 * 603 * @param text 604 * The string of text. Example: <code>"south_south_east"</code> 605 * @param filename 606 * The full path to the sound file (for example: 607 * "/sdcard/mysounds/hello.wav") 608 * 609 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 610 */ 611 public int addSpeech(String text, String filename) { 612 synchronized (mStartLock) { 613 if (!mStarted) { 614 return ERROR; 615 } 616 try { 617 mITts.addSpeechFile(mPackageName, text, filename); 618 return SUCCESS; 619 } catch (RemoteException e) { 620 // TTS died; restart it. 621 Log.e("TextToSpeech.java - addSpeech", "RemoteException"); 622 e.printStackTrace(); 623 mStarted = false; 624 initTts(); 625 } catch (NullPointerException e) { 626 // TTS died; restart it. 627 Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); 628 e.printStackTrace(); 629 mStarted = false; 630 initTts(); 631 } catch (IllegalStateException e) { 632 // TTS died; restart it. 633 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); 634 e.printStackTrace(); 635 mStarted = false; 636 initTts(); 637 } 638 return ERROR; 639 } 640 } 641 642 643 /** 644 * Adds a mapping between a string of text and a sound resource in a 645 * package. Use this to add custom earcons. 646 * 647 * @see #playEarcon(String, int, HashMap) 648 * 649 * @param earcon The name of the earcon. 650 * Example: <code>"[tick]"</code><br/> 651 * 652 * @param packagename 653 * the package name of the application that contains the 654 * resource. This can for instance be the package name of your own application. 655 * Example: <b>"com.google.marvin.compass"</b><br/> 656 * The package name can be found in the AndroidManifest.xml of 657 * the application containing the resource. 658 * <p> 659 * <code><manifest xmlns:android="..." 660 * package="<b>com.google.marvin.compass</b>"></code> 661 * </p> 662 * 663 * @param resourceId 664 * Example: <code>R.raw.tick_snd</code> 665 * 666 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 667 */ 668 public int addEarcon(String earcon, String packagename, int resourceId) { 669 synchronized(mStartLock) { 670 if (!mStarted) { 671 return ERROR; 672 } 673 try { 674 mITts.addEarcon(mPackageName, earcon, packagename, resourceId); 675 return SUCCESS; 676 } catch (RemoteException e) { 677 // TTS died; restart it. 678 Log.e("TextToSpeech.java - addEarcon", "RemoteException"); 679 e.printStackTrace(); 680 mStarted = false; 681 initTts(); 682 } catch (NullPointerException e) { 683 // TTS died; restart it. 684 Log.e("TextToSpeech.java - addEarcon", "NullPointerException"); 685 e.printStackTrace(); 686 mStarted = false; 687 initTts(); 688 } catch (IllegalStateException e) { 689 // TTS died; restart it. 690 Log.e("TextToSpeech.java - addEarcon", "IllegalStateException"); 691 e.printStackTrace(); 692 mStarted = false; 693 initTts(); 694 } 695 return ERROR; 696 } 697 } 698 699 700 /** 701 * Adds a mapping between a string of text and a sound file. 702 * Use this to add custom earcons. 703 * 704 * @see #playEarcon(String, int, HashMap) 705 * 706 * @param earcon 707 * The name of the earcon. 708 * Example: <code>"[tick]"</code> 709 * @param filename 710 * The full path to the sound file (for example: 711 * "/sdcard/mysounds/tick.wav") 712 * 713 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 714 */ 715 public int addEarcon(String earcon, String filename) { 716 synchronized (mStartLock) { 717 if (!mStarted) { 718 return ERROR; 719 } 720 try { 721 mITts.addEarconFile(mPackageName, earcon, filename); 722 return SUCCESS; 723 } catch (RemoteException e) { 724 // TTS died; restart it. 725 Log.e("TextToSpeech.java - addEarcon", "RemoteException"); 726 e.printStackTrace(); 727 mStarted = false; 728 initTts(); 729 } catch (NullPointerException e) { 730 // TTS died; restart it. 731 Log.e("TextToSpeech.java - addEarcon", "NullPointerException"); 732 e.printStackTrace(); 733 mStarted = false; 734 initTts(); 735 } catch (IllegalStateException e) { 736 // TTS died; restart it. 737 Log.e("TextToSpeech.java - addEarcon", "IllegalStateException"); 738 e.printStackTrace(); 739 mStarted = false; 740 initTts(); 741 } 742 return ERROR; 743 } 744 } 745 746 747 /** 748 * Speaks the string using the specified queuing strategy and speech 749 * parameters. 750 * 751 * @param text 752 * The string of text to be spoken. 753 * @param queueMode 754 * The queuing strategy to use. 755 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 756 * @param params 757 * The list of parameters to be used. Can be null if no parameters are given. 758 * They are specified using a (key, value) pair, where the key can be 759 * {@link Engine#KEY_PARAM_STREAM} or 760 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 761 * 762 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 763 */ 764 public int speak(String text, int queueMode, HashMap<String,String> params) 765 { 766 synchronized (mStartLock) { 767 int result = ERROR; 768 Log.i("TTS", "speak() queueMode=" + queueMode); 769 if (!mStarted) { 770 return result; 771 } 772 try { 773 if ((params != null) && (!params.isEmpty())) { 774 setCachedParam(params, Engine.KEY_PARAM_STREAM, Engine.PARAM_POSITION_STREAM); 775 setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID, 776 Engine.PARAM_POSITION_UTTERANCE_ID); 777 setCachedParam(params, Engine.KEY_PARAM_ENGINE, Engine.PARAM_POSITION_ENGINE); 778 setCachedParam(params, Engine.KEY_PARAM_VOLUME, Engine.PARAM_POSITION_VOLUME); 779 setCachedParam(params, Engine.KEY_PARAM_PAN, Engine.PARAM_POSITION_PAN); 780 } 781 result = mITts.speak(mPackageName, text, queueMode, mCachedParams); 782 } catch (RemoteException e) { 783 // TTS died; restart it. 784 Log.e("TextToSpeech.java - speak", "RemoteException"); 785 e.printStackTrace(); 786 mStarted = false; 787 initTts(); 788 } catch (NullPointerException e) { 789 // TTS died; restart it. 790 Log.e("TextToSpeech.java - speak", "NullPointerException"); 791 e.printStackTrace(); 792 mStarted = false; 793 initTts(); 794 } catch (IllegalStateException e) { 795 // TTS died; restart it. 796 Log.e("TextToSpeech.java - speak", "IllegalStateException"); 797 e.printStackTrace(); 798 mStarted = false; 799 initTts(); 800 } finally { 801 resetCachedParams(); 802 return result; 803 } 804 } 805 } 806 807 808 /** 809 * Plays the earcon using the specified queueing mode and parameters. 810 * 811 * @param earcon 812 * The earcon that should be played 813 * @param queueMode 814 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 815 * @param params 816 * The list of parameters to be used. Can be null if no parameters are given. 817 * They are specified using a (key, value) pair, where the key can be 818 * {@link Engine#KEY_PARAM_STREAM} or 819 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 820 * 821 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 822 */ 823 public int playEarcon(String earcon, int queueMode, 824 HashMap<String,String> params) { 825 synchronized (mStartLock) { 826 int result = ERROR; 827 if (!mStarted) { 828 return result; 829 } 830 try { 831 if ((params != null) && (!params.isEmpty())) { 832 String extra = params.get(Engine.KEY_PARAM_STREAM); 833 if (extra != null) { 834 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra; 835 } 836 setCachedParam(params, Engine.KEY_PARAM_STREAM, Engine.PARAM_POSITION_STREAM); 837 setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID, 838 Engine.PARAM_POSITION_UTTERANCE_ID); 839 } 840 result = mITts.playEarcon(mPackageName, earcon, queueMode, null); 841 } catch (RemoteException e) { 842 // TTS died; restart it. 843 Log.e("TextToSpeech.java - playEarcon", "RemoteException"); 844 e.printStackTrace(); 845 mStarted = false; 846 initTts(); 847 } catch (NullPointerException e) { 848 // TTS died; restart it. 849 Log.e("TextToSpeech.java - playEarcon", "NullPointerException"); 850 e.printStackTrace(); 851 mStarted = false; 852 initTts(); 853 } catch (IllegalStateException e) { 854 // TTS died; restart it. 855 Log.e("TextToSpeech.java - playEarcon", "IllegalStateException"); 856 e.printStackTrace(); 857 mStarted = false; 858 initTts(); 859 } finally { 860 resetCachedParams(); 861 return result; 862 } 863 } 864 } 865 866 /** 867 * Plays silence for the specified amount of time using the specified 868 * queue mode. 869 * 870 * @param durationInMs 871 * A long that indicates how long the silence should last. 872 * @param queueMode 873 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 874 * @param params 875 * The list of parameters to be used. Can be null if no parameters are given. 876 * They are specified using a (key, value) pair, where the key can be 877 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 878 * 879 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 880 */ 881 public int playSilence(long durationInMs, int queueMode, HashMap<String,String> params) { 882 synchronized (mStartLock) { 883 int result = ERROR; 884 if (!mStarted) { 885 return result; 886 } 887 try { 888 if ((params != null) && (!params.isEmpty())) { 889 setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID, 890 Engine.PARAM_POSITION_UTTERANCE_ID); 891 } 892 result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams); 893 } catch (RemoteException e) { 894 // TTS died; restart it. 895 Log.e("TextToSpeech.java - playSilence", "RemoteException"); 896 e.printStackTrace(); 897 mStarted = false; 898 initTts(); 899 } catch (NullPointerException e) { 900 // TTS died; restart it. 901 Log.e("TextToSpeech.java - playSilence", "NullPointerException"); 902 e.printStackTrace(); 903 mStarted = false; 904 initTts(); 905 } catch (IllegalStateException e) { 906 // TTS died; restart it. 907 Log.e("TextToSpeech.java - playSilence", "IllegalStateException"); 908 e.printStackTrace(); 909 mStarted = false; 910 initTts(); 911 } finally { 912 resetCachedParams(); 913 return result; 914 } 915 } 916 } 917 918 919 /** 920 * Returns whether or not the TextToSpeech engine is busy speaking. 921 * 922 * @return Whether or not the TextToSpeech engine is busy speaking. 923 */ 924 public boolean isSpeaking() { 925 synchronized (mStartLock) { 926 if (!mStarted) { 927 return false; 928 } 929 try { 930 return mITts.isSpeaking(); 931 } catch (RemoteException e) { 932 // TTS died; restart it. 933 Log.e("TextToSpeech.java - isSpeaking", "RemoteException"); 934 e.printStackTrace(); 935 mStarted = false; 936 initTts(); 937 } catch (NullPointerException e) { 938 // TTS died; restart it. 939 Log.e("TextToSpeech.java - isSpeaking", "NullPointerException"); 940 e.printStackTrace(); 941 mStarted = false; 942 initTts(); 943 } catch (IllegalStateException e) { 944 // TTS died; restart it. 945 Log.e("TextToSpeech.java - isSpeaking", "IllegalStateException"); 946 e.printStackTrace(); 947 mStarted = false; 948 initTts(); 949 } 950 return false; 951 } 952 } 953 954 955 /** 956 * Interrupts the current utterance (whether played or rendered to file) and discards other 957 * utterances in the queue. 958 * 959 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 960 */ 961 public int stop() { 962 synchronized (mStartLock) { 963 int result = ERROR; 964 if (!mStarted) { 965 return result; 966 } 967 try { 968 result = mITts.stop(mPackageName); 969 } catch (RemoteException e) { 970 // TTS died; restart it. 971 Log.e("TextToSpeech.java - stop", "RemoteException"); 972 e.printStackTrace(); 973 mStarted = false; 974 initTts(); 975 } catch (NullPointerException e) { 976 // TTS died; restart it. 977 Log.e("TextToSpeech.java - stop", "NullPointerException"); 978 e.printStackTrace(); 979 mStarted = false; 980 initTts(); 981 } catch (IllegalStateException e) { 982 // TTS died; restart it. 983 Log.e("TextToSpeech.java - stop", "IllegalStateException"); 984 e.printStackTrace(); 985 mStarted = false; 986 initTts(); 987 } finally { 988 return result; 989 } 990 } 991 } 992 993 994 /** 995 * Sets the speech rate for the TextToSpeech engine. 996 * 997 * This has no effect on any pre-recorded speech. 998 * 999 * @param speechRate 1000 * The speech rate for the TextToSpeech engine. 1 is the normal speed, 1001 * lower values slow down the speech (0.5 is half the normal speech rate), 1002 * greater values accelerate it (2 is twice the normal speech rate). 1003 * 1004 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1005 */ 1006 public int setSpeechRate(float speechRate) { 1007 synchronized (mStartLock) { 1008 int result = ERROR; 1009 if (!mStarted) { 1010 return result; 1011 } 1012 try { 1013 if (speechRate > 0) { 1014 int rate = (int)(speechRate*100); 1015 mCachedParams[Engine.PARAM_POSITION_RATE + 1] = String.valueOf(rate); 1016 // the rate is not set here, instead it is cached so it will be associated 1017 // with all upcoming utterances. 1018 if (speechRate > 0.0f) { 1019 result = SUCCESS; 1020 } else { 1021 result = ERROR; 1022 } 1023 } 1024 } catch (NullPointerException e) { 1025 // TTS died; restart it. 1026 Log.e("TextToSpeech.java - setSpeechRate", "NullPointerException"); 1027 e.printStackTrace(); 1028 mStarted = false; 1029 initTts(); 1030 } catch (IllegalStateException e) { 1031 // TTS died; restart it. 1032 Log.e("TextToSpeech.java - setSpeechRate", "IllegalStateException"); 1033 e.printStackTrace(); 1034 mStarted = false; 1035 initTts(); 1036 } finally { 1037 return result; 1038 } 1039 } 1040 } 1041 1042 1043 /** 1044 * Sets the speech pitch for the TextToSpeech engine. 1045 * 1046 * This has no effect on any pre-recorded speech. 1047 * 1048 * @param pitch 1049 * The pitch for the TextToSpeech engine. 1 is the normal pitch, 1050 * lower values lower the tone of the synthesized voice, 1051 * greater values increase it. 1052 * 1053 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1054 */ 1055 public int setPitch(float pitch) { 1056 synchronized (mStartLock) { 1057 int result = ERROR; 1058 if (!mStarted) { 1059 return result; 1060 } 1061 try { 1062 // the pitch is not set here, instead it is cached so it will be associated 1063 // with all upcoming utterances. 1064 if (pitch > 0) { 1065 int p = (int)(pitch*100); 1066 mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = String.valueOf(p); 1067 result = SUCCESS; 1068 } 1069 } catch (NullPointerException e) { 1070 // TTS died; restart it. 1071 Log.e("TextToSpeech.java - setPitch", "NullPointerException"); 1072 e.printStackTrace(); 1073 mStarted = false; 1074 initTts(); 1075 } catch (IllegalStateException e) { 1076 // TTS died; restart it. 1077 Log.e("TextToSpeech.java - setPitch", "IllegalStateException"); 1078 e.printStackTrace(); 1079 mStarted = false; 1080 initTts(); 1081 } finally { 1082 return result; 1083 } 1084 } 1085 } 1086 1087 1088 /** 1089 * Sets the language for the TextToSpeech engine. 1090 * The TextToSpeech engine will try to use the closest match to the specified 1091 * language as represented by the Locale, but there is no guarantee that the exact same Locale 1092 * will be used. Use {@link #isLanguageAvailable(Locale)} to check the level of support 1093 * before choosing the language to use for the next utterances. 1094 * 1095 * @param loc 1096 * The locale describing the language to be used. 1097 * 1098 * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE}, 1099 * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE}, 1100 * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}. 1101 */ 1102 public int setLanguage(Locale loc) { 1103 synchronized (mStartLock) { 1104 int result = LANG_NOT_SUPPORTED; 1105 if (!mStarted) { 1106 return result; 1107 } 1108 if (loc == null) { 1109 return result; 1110 } 1111 try { 1112 String language = loc.getISO3Language(); 1113 String country = loc.getISO3Country(); 1114 String variant = loc.getVariant(); 1115 // Check if the language, country, variant are available, and cache 1116 // the available parts. 1117 // Note that the language is not actually set here, instead it is cached so it 1118 // will be associated with all upcoming utterances. 1119 result = mITts.isLanguageAvailable(language, country, variant, mCachedParams); 1120 if (result >= LANG_AVAILABLE){ 1121 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = language; 1122 if (result >= LANG_COUNTRY_AVAILABLE){ 1123 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = country; 1124 } else { 1125 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = ""; 1126 } 1127 if (result >= LANG_COUNTRY_VAR_AVAILABLE){ 1128 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = variant; 1129 } else { 1130 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = ""; 1131 } 1132 } 1133 } catch (RemoteException e) { 1134 // TTS died; restart it. 1135 Log.e("TextToSpeech.java - setLanguage", "RemoteException"); 1136 e.printStackTrace(); 1137 mStarted = false; 1138 initTts(); 1139 } catch (NullPointerException e) { 1140 // TTS died; restart it. 1141 Log.e("TextToSpeech.java - setLanguage", "NullPointerException"); 1142 e.printStackTrace(); 1143 mStarted = false; 1144 initTts(); 1145 } catch (IllegalStateException e) { 1146 // TTS died; restart it. 1147 Log.e("TextToSpeech.java - setLanguage", "IllegalStateException"); 1148 e.printStackTrace(); 1149 mStarted = false; 1150 initTts(); 1151 } finally { 1152 return result; 1153 } 1154 } 1155 } 1156 1157 1158 /** 1159 * Returns a Locale instance describing the language currently being used by the TextToSpeech 1160 * engine. 1161 * @return language, country (if any) and variant (if any) used by the engine stored in a Locale 1162 * instance, or null is the TextToSpeech engine has failed. 1163 */ 1164 public Locale getLanguage() { 1165 synchronized (mStartLock) { 1166 if (!mStarted) { 1167 return null; 1168 } 1169 try { 1170 // Only do a call to the native synth if there is nothing in the cached params 1171 if (mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1].length() < 1){ 1172 String[] locStrings = mITts.getLanguage(); 1173 if ((locStrings != null) && (locStrings.length == 3)) { 1174 return new Locale(locStrings[0], locStrings[1], locStrings[2]); 1175 } else { 1176 return null; 1177 } 1178 } else { 1179 return new Locale(mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1], 1180 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1], 1181 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1]); 1182 } 1183 } catch (RemoteException e) { 1184 // TTS died; restart it. 1185 Log.e("TextToSpeech.java - getLanguage", "RemoteException"); 1186 e.printStackTrace(); 1187 mStarted = false; 1188 initTts(); 1189 } catch (NullPointerException e) { 1190 // TTS died; restart it. 1191 Log.e("TextToSpeech.java - getLanguage", "NullPointerException"); 1192 e.printStackTrace(); 1193 mStarted = false; 1194 initTts(); 1195 } catch (IllegalStateException e) { 1196 // TTS died; restart it. 1197 Log.e("TextToSpeech.java - getLanguage", "IllegalStateException"); 1198 e.printStackTrace(); 1199 mStarted = false; 1200 initTts(); 1201 } 1202 return null; 1203 } 1204 } 1205 1206 /** 1207 * Checks if the specified language as represented by the Locale is available and supported. 1208 * 1209 * @param loc 1210 * The Locale describing the language to be used. 1211 * 1212 * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE}, 1213 * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE}, 1214 * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}. 1215 */ 1216 public int isLanguageAvailable(Locale loc) { 1217 synchronized (mStartLock) { 1218 int result = LANG_NOT_SUPPORTED; 1219 if (!mStarted) { 1220 return result; 1221 } 1222 try { 1223 result = mITts.isLanguageAvailable(loc.getISO3Language(), 1224 loc.getISO3Country(), loc.getVariant(), mCachedParams); 1225 } catch (RemoteException e) { 1226 // TTS died; restart it. 1227 Log.e("TextToSpeech.java - isLanguageAvailable", "RemoteException"); 1228 e.printStackTrace(); 1229 mStarted = false; 1230 initTts(); 1231 } catch (NullPointerException e) { 1232 // TTS died; restart it. 1233 Log.e("TextToSpeech.java - isLanguageAvailable", "NullPointerException"); 1234 e.printStackTrace(); 1235 mStarted = false; 1236 initTts(); 1237 } catch (IllegalStateException e) { 1238 // TTS died; restart it. 1239 Log.e("TextToSpeech.java - isLanguageAvailable", "IllegalStateException"); 1240 e.printStackTrace(); 1241 mStarted = false; 1242 initTts(); 1243 } finally { 1244 return result; 1245 } 1246 } 1247 } 1248 1249 1250 /** 1251 * Synthesizes the given text to a file using the specified parameters. 1252 * 1253 * @param text 1254 * The String of text that should be synthesized 1255 * @param params 1256 * The list of parameters to be used. Can be null if no parameters are given. 1257 * They are specified using a (key, value) pair, where the key can be 1258 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 1259 * @param filename 1260 * The string that gives the full output filename; it should be 1261 * something like "/sdcard/myappsounds/mysound.wav". 1262 * 1263 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1264 */ 1265 public int synthesizeToFile(String text, HashMap<String,String> params, 1266 String filename) { 1267 Log.i("TTS", "synthesizeToFile()"); 1268 synchronized (mStartLock) { 1269 int result = ERROR; 1270 if (!mStarted) { 1271 return result; 1272 } 1273 try { 1274 if ((params != null) && (!params.isEmpty())) { 1275 // no need to read the stream type here 1276 setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID, 1277 Engine.PARAM_POSITION_UTTERANCE_ID); 1278 setCachedParam(params, Engine.KEY_PARAM_ENGINE, Engine.PARAM_POSITION_ENGINE); 1279 } 1280 result = mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename) ? 1281 SUCCESS : ERROR; 1282 } catch (RemoteException e) { 1283 // TTS died; restart it. 1284 Log.e("TextToSpeech.java - synthesizeToFile", "RemoteException"); 1285 e.printStackTrace(); 1286 mStarted = false; 1287 initTts(); 1288 } catch (NullPointerException e) { 1289 // TTS died; restart it. 1290 Log.e("TextToSpeech.java - synthesizeToFile", "NullPointerException"); 1291 e.printStackTrace(); 1292 mStarted = false; 1293 initTts(); 1294 } catch (IllegalStateException e) { 1295 // TTS died; restart it. 1296 Log.e("TextToSpeech.java - synthesizeToFile", "IllegalStateException"); 1297 e.printStackTrace(); 1298 mStarted = false; 1299 initTts(); 1300 } finally { 1301 resetCachedParams(); 1302 return result; 1303 } 1304 } 1305 } 1306 1307 1308 /** 1309 * Convenience method to reset the cached parameters to the current default values 1310 * if they are not persistent between calls to the service. 1311 */ 1312 private void resetCachedParams() { 1313 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = 1314 String.valueOf(Engine.DEFAULT_STREAM); 1315 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID+ 1] = ""; 1316 mCachedParams[Engine.PARAM_POSITION_VOLUME + 1] = Engine.DEFAULT_VOLUME_STRING; 1317 mCachedParams[Engine.PARAM_POSITION_PAN + 1] = Engine.DEFAULT_PAN_STRING; 1318 } 1319 1320 /** 1321 * Convenience method to save a parameter in the cached parameter array, at the given index, 1322 * for a property saved in the given hashmap. 1323 */ 1324 private void setCachedParam(HashMap<String,String> params, String key, int keyIndex) { 1325 String extra = params.get(key); 1326 if (extra != null) { 1327 mCachedParams[keyIndex+1] = extra; 1328 } 1329 } 1330 1331 /** 1332 * Sets the OnUtteranceCompletedListener that will fire when an utterance completes. 1333 * 1334 * @param listener 1335 * The OnUtteranceCompletedListener 1336 * 1337 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1338 */ 1339 public int setOnUtteranceCompletedListener( 1340 final OnUtteranceCompletedListener listener) { 1341 synchronized (mStartLock) { 1342 int result = ERROR; 1343 if (!mStarted) { 1344 return result; 1345 } 1346 mITtscallback = new ITtsCallback.Stub() { 1347 public void utteranceCompleted(String utteranceId) throws RemoteException { 1348 if (listener != null) { 1349 listener.onUtteranceCompleted(utteranceId); 1350 } 1351 } 1352 }; 1353 try { 1354 result = mITts.registerCallback(mPackageName, mITtscallback); 1355 } catch (RemoteException e) { 1356 // TTS died; restart it. 1357 Log.e("TextToSpeech.java - registerCallback", "RemoteException"); 1358 e.printStackTrace(); 1359 mStarted = false; 1360 initTts(); 1361 } catch (NullPointerException e) { 1362 // TTS died; restart it. 1363 Log.e("TextToSpeech.java - registerCallback", "NullPointerException"); 1364 e.printStackTrace(); 1365 mStarted = false; 1366 initTts(); 1367 } catch (IllegalStateException e) { 1368 // TTS died; restart it. 1369 Log.e("TextToSpeech.java - registerCallback", "IllegalStateException"); 1370 e.printStackTrace(); 1371 mStarted = false; 1372 initTts(); 1373 } finally { 1374 return result; 1375 } 1376 } 1377 } 1378 1379 /** 1380 * Sets the speech synthesis engine to be used by its packagename. 1381 * 1382 * @param enginePackageName 1383 * The packagename for the synthesis engine (ie, "com.svox.pico") 1384 * 1385 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1386 */ 1387 public int setEngineByPackageName(String enginePackageName) { 1388 synchronized (mStartLock) { 1389 int result = TextToSpeech.ERROR; 1390 if (!mStarted) { 1391 return result; 1392 } 1393 try { 1394 result = mITts.setEngineByPackageName(enginePackageName); 1395 if (result == TextToSpeech.SUCCESS){ 1396 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = enginePackageName; 1397 } 1398 } catch (RemoteException e) { 1399 // TTS died; restart it. 1400 Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException"); 1401 e.printStackTrace(); 1402 mStarted = false; 1403 initTts(); 1404 } catch (NullPointerException e) { 1405 // TTS died; restart it. 1406 Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException"); 1407 e.printStackTrace(); 1408 mStarted = false; 1409 initTts(); 1410 } catch (IllegalStateException e) { 1411 // TTS died; restart it. 1412 Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException"); 1413 e.printStackTrace(); 1414 mStarted = false; 1415 initTts(); 1416 } finally { 1417 return result; 1418 } 1419 } 1420 } 1421 1422 1423 /** 1424 * Gets the packagename of the default speech synthesis engine. 1425 * 1426 * @return Packagename of the TTS engine that the user has chosen as their default. 1427 */ 1428 public String getDefaultEngine() { 1429 synchronized (mStartLock) { 1430 String engineName = ""; 1431 if (!mStarted) { 1432 return engineName; 1433 } 1434 try { 1435 engineName = mITts.getDefaultEngine(); 1436 } catch (RemoteException e) { 1437 // TTS died; restart it. 1438 Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException"); 1439 e.printStackTrace(); 1440 mStarted = false; 1441 initTts(); 1442 } catch (NullPointerException e) { 1443 // TTS died; restart it. 1444 Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException"); 1445 e.printStackTrace(); 1446 mStarted = false; 1447 initTts(); 1448 } catch (IllegalStateException e) { 1449 // TTS died; restart it. 1450 Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException"); 1451 e.printStackTrace(); 1452 mStarted = false; 1453 initTts(); 1454 } finally { 1455 return engineName; 1456 } 1457 } 1458 } 1459 1460 1461 /** 1462 * Returns whether or not the user is forcing their defaults to override the 1463 * Text-To-Speech settings set by applications. 1464 * 1465 * @return Whether or not defaults are enforced. 1466 */ 1467 public boolean areDefaultsEnforced() { 1468 synchronized (mStartLock) { 1469 boolean defaultsEnforced = false; 1470 if (!mStarted) { 1471 return defaultsEnforced; 1472 } 1473 try { 1474 defaultsEnforced = mITts.areDefaultsEnforced(); 1475 } catch (RemoteException e) { 1476 // TTS died; restart it. 1477 Log.e("TextToSpeech.java - areDefaultsEnforced", "RemoteException"); 1478 e.printStackTrace(); 1479 mStarted = false; 1480 initTts(); 1481 } catch (NullPointerException e) { 1482 // TTS died; restart it. 1483 Log.e("TextToSpeech.java - areDefaultsEnforced", "NullPointerException"); 1484 e.printStackTrace(); 1485 mStarted = false; 1486 initTts(); 1487 } catch (IllegalStateException e) { 1488 // TTS died; restart it. 1489 Log.e("TextToSpeech.java - areDefaultsEnforced", "IllegalStateException"); 1490 e.printStackTrace(); 1491 mStarted = false; 1492 initTts(); 1493 } finally { 1494 return defaultsEnforced; 1495 } 1496 } 1497 } 1498} 1499