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