TextToSpeech.java revision 708b47d1ecf62dbf2faf0b42aae880f719b42963
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 * Total number of cached speech parameters. 418 * This number should be equal to (max param position/2) + 1. 419 */ 420 protected static final int NB_CACHED_PARAMS = 10; 421 } 422 423 /** 424 * Connection needed for the TTS. 425 */ 426 private ServiceConnection mServiceConnection; 427 428 private ITts mITts = null; 429 private ITtsCallback mITtscallback = null; 430 private Context mContext = null; 431 private String mPackageName = ""; 432 private OnInitListener mInitListener = null; 433 private boolean mStarted = false; 434 private final Object mStartLock = new Object(); 435 /** 436 * Used to store the cached parameters sent along with each synthesis request to the 437 * TTS service. 438 */ 439 private String[] mCachedParams; 440 441 /** 442 * The constructor for the TextToSpeech class. 443 * This will also initialize the associated TextToSpeech engine if it isn't already running. 444 * 445 * @param context 446 * The context this instance is running in. 447 * @param listener 448 * The {@link TextToSpeech.OnInitListener} that will be called when the 449 * TextToSpeech engine has initialized. 450 */ 451 public TextToSpeech(Context context, OnInitListener listener) { 452 mContext = context; 453 mPackageName = mContext.getPackageName(); 454 mInitListener = listener; 455 456 mCachedParams = new String[2*Engine.NB_CACHED_PARAMS]; // store key and value 457 mCachedParams[Engine.PARAM_POSITION_RATE] = Engine.KEY_PARAM_RATE; 458 mCachedParams[Engine.PARAM_POSITION_LANGUAGE] = Engine.KEY_PARAM_LANGUAGE; 459 mCachedParams[Engine.PARAM_POSITION_COUNTRY] = Engine.KEY_PARAM_COUNTRY; 460 mCachedParams[Engine.PARAM_POSITION_VARIANT] = Engine.KEY_PARAM_VARIANT; 461 mCachedParams[Engine.PARAM_POSITION_STREAM] = Engine.KEY_PARAM_STREAM; 462 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID] = Engine.KEY_PARAM_UTTERANCE_ID; 463 mCachedParams[Engine.PARAM_POSITION_ENGINE] = Engine.KEY_PARAM_ENGINE; 464 mCachedParams[Engine.PARAM_POSITION_PITCH] = Engine.KEY_PARAM_PITCH; 465 mCachedParams[Engine.PARAM_POSITION_VOLUME] = Engine.KEY_PARAM_VOLUME; 466 mCachedParams[Engine.PARAM_POSITION_PAN] = Engine.KEY_PARAM_PAN; 467 468 // Leave all defaults that are shown in Settings uninitialized/at the default 469 // so that the values set in Settings will take effect if the application does 470 // not try to change these settings itself. 471 mCachedParams[Engine.PARAM_POSITION_RATE + 1] = ""; 472 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = ""; 473 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = ""; 474 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = ""; 475 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = 476 String.valueOf(Engine.DEFAULT_STREAM); 477 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID + 1] = ""; 478 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = ""; 479 mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = "100"; 480 mCachedParams[Engine.PARAM_POSITION_VOLUME + 1] = Engine.DEFAULT_VOLUME_STRING; 481 mCachedParams[Engine.PARAM_POSITION_PAN + 1] = Engine.DEFAULT_PAN_STRING; 482 483 initTts(); 484 } 485 486 487 private void initTts() { 488 mStarted = false; 489 490 // Initialize the TTS, run the callback after the binding is successful 491 mServiceConnection = new ServiceConnection() { 492 public void onServiceConnected(ComponentName name, IBinder service) { 493 synchronized(mStartLock) { 494 mITts = ITts.Stub.asInterface(service); 495 mStarted = true; 496 // Cache the default engine and current language 497 setEngineByPackageName(getDefaultEngine()); 498 setLanguage(getLanguage()); 499 if (mInitListener != null) { 500 // TODO manage failures and missing resources 501 mInitListener.onInit(SUCCESS); 502 } 503 } 504 } 505 506 public void onServiceDisconnected(ComponentName name) { 507 synchronized(mStartLock) { 508 mITts = null; 509 mInitListener = null; 510 mStarted = false; 511 } 512 } 513 }; 514 515 Intent intent = new Intent("android.intent.action.START_TTS_SERVICE"); 516 intent.addCategory("android.intent.category.TTS"); 517 boolean bound = mContext.bindService(intent, mServiceConnection, Context.BIND_AUTO_CREATE); 518 if (!bound) { 519 Log.e("TextToSpeech.java", "initTts() failed to bind to service"); 520 if (mInitListener != null) { 521 mInitListener.onInit(ERROR); 522 } 523 } else { 524 // initialization listener will be called inside ServiceConnection 525 Log.i("TextToSpeech.java", "initTts() successfully bound to service"); 526 } 527 // TODO handle plugin failures 528 } 529 530 531 /** 532 * Releases the resources used by the TextToSpeech engine. 533 * It is good practice for instance to call this method in the onDestroy() method of an Activity 534 * so the TextToSpeech engine can be cleanly stopped. 535 */ 536 public void shutdown() { 537 try { 538 mContext.unbindService(mServiceConnection); 539 } catch (IllegalArgumentException e) { 540 // Do nothing and fail silently since an error here indicates that 541 // binding never succeeded in the first place. 542 } 543 } 544 545 546 /** 547 * Adds a mapping between a string of text and a sound resource in a 548 * package. After a call to this method, subsequent calls to 549 * {@link #speak(String, int, HashMap)} will play the specified sound resource 550 * if it is available, or synthesize the text it is missing. 551 * 552 * @param text 553 * The string of text. Example: <code>"south_south_east"</code> 554 * 555 * @param packagename 556 * Pass the packagename of the application that contains the 557 * resource. If the resource is in your own application (this is 558 * the most common case), then put the packagename of your 559 * application here.<br/> 560 * Example: <b>"com.google.marvin.compass"</b><br/> 561 * The packagename can be found in the AndroidManifest.xml of 562 * your application. 563 * <p> 564 * <code><manifest xmlns:android="..." 565 * package="<b>com.google.marvin.compass</b>"></code> 566 * </p> 567 * 568 * @param resourceId 569 * Example: <code>R.raw.south_south_east</code> 570 * 571 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 572 */ 573 public int addSpeech(String text, String packagename, int resourceId) { 574 synchronized(mStartLock) { 575 if (!mStarted) { 576 return ERROR; 577 } 578 try { 579 mITts.addSpeech(mPackageName, text, packagename, resourceId); 580 return SUCCESS; 581 } catch (RemoteException e) { 582 // TTS died; restart it. 583 Log.e("TextToSpeech.java - addSpeech", "RemoteException"); 584 e.printStackTrace(); 585 mStarted = false; 586 initTts(); 587 } catch (NullPointerException e) { 588 // TTS died; restart it. 589 Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); 590 e.printStackTrace(); 591 mStarted = false; 592 initTts(); 593 } catch (IllegalStateException e) { 594 // TTS died; restart it. 595 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); 596 e.printStackTrace(); 597 mStarted = false; 598 initTts(); 599 } 600 return ERROR; 601 } 602 } 603 604 605 /** 606 * Adds a mapping between a string of text and a sound file. Using this, it 607 * is possible to add custom pronounciations for a string of text. 608 * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)} 609 * will play the specified sound resource if it is available, or synthesize the text it is 610 * missing. 611 * 612 * @param text 613 * The string of text. Example: <code>"south_south_east"</code> 614 * @param filename 615 * The full path to the sound file (for example: 616 * "/sdcard/mysounds/hello.wav") 617 * 618 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 619 */ 620 public int addSpeech(String text, String filename) { 621 synchronized (mStartLock) { 622 if (!mStarted) { 623 return ERROR; 624 } 625 try { 626 mITts.addSpeechFile(mPackageName, text, filename); 627 return SUCCESS; 628 } catch (RemoteException e) { 629 // TTS died; restart it. 630 Log.e("TextToSpeech.java - addSpeech", "RemoteException"); 631 e.printStackTrace(); 632 mStarted = false; 633 initTts(); 634 } catch (NullPointerException e) { 635 // TTS died; restart it. 636 Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); 637 e.printStackTrace(); 638 mStarted = false; 639 initTts(); 640 } catch (IllegalStateException e) { 641 // TTS died; restart it. 642 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); 643 e.printStackTrace(); 644 mStarted = false; 645 initTts(); 646 } 647 return ERROR; 648 } 649 } 650 651 652 /** 653 * Adds a mapping between a string of text and a sound resource in a 654 * package. Use this to add custom earcons. 655 * 656 * @see #playEarcon(String, int, HashMap) 657 * 658 * @param earcon The name of the earcon. 659 * Example: <code>"[tick]"</code><br/> 660 * 661 * @param packagename 662 * the package name of the application that contains the 663 * resource. This can for instance be the package name of your own application. 664 * Example: <b>"com.google.marvin.compass"</b><br/> 665 * The package name can be found in the AndroidManifest.xml of 666 * the application containing the resource. 667 * <p> 668 * <code><manifest xmlns:android="..." 669 * package="<b>com.google.marvin.compass</b>"></code> 670 * </p> 671 * 672 * @param resourceId 673 * Example: <code>R.raw.tick_snd</code> 674 * 675 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 676 */ 677 public int addEarcon(String earcon, String packagename, int resourceId) { 678 synchronized(mStartLock) { 679 if (!mStarted) { 680 return ERROR; 681 } 682 try { 683 mITts.addEarcon(mPackageName, earcon, packagename, resourceId); 684 return SUCCESS; 685 } catch (RemoteException e) { 686 // TTS died; restart it. 687 Log.e("TextToSpeech.java - addEarcon", "RemoteException"); 688 e.printStackTrace(); 689 mStarted = false; 690 initTts(); 691 } catch (NullPointerException e) { 692 // TTS died; restart it. 693 Log.e("TextToSpeech.java - addEarcon", "NullPointerException"); 694 e.printStackTrace(); 695 mStarted = false; 696 initTts(); 697 } catch (IllegalStateException e) { 698 // TTS died; restart it. 699 Log.e("TextToSpeech.java - addEarcon", "IllegalStateException"); 700 e.printStackTrace(); 701 mStarted = false; 702 initTts(); 703 } 704 return ERROR; 705 } 706 } 707 708 709 /** 710 * Adds a mapping between a string of text and a sound file. 711 * Use this to add custom earcons. 712 * 713 * @see #playEarcon(String, int, HashMap) 714 * 715 * @param earcon 716 * The name of the earcon. 717 * Example: <code>"[tick]"</code> 718 * @param filename 719 * The full path to the sound file (for example: 720 * "/sdcard/mysounds/tick.wav") 721 * 722 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 723 */ 724 public int addEarcon(String earcon, String filename) { 725 synchronized (mStartLock) { 726 if (!mStarted) { 727 return ERROR; 728 } 729 try { 730 mITts.addEarconFile(mPackageName, earcon, filename); 731 return SUCCESS; 732 } catch (RemoteException e) { 733 // TTS died; restart it. 734 Log.e("TextToSpeech.java - addEarcon", "RemoteException"); 735 e.printStackTrace(); 736 mStarted = false; 737 initTts(); 738 } catch (NullPointerException e) { 739 // TTS died; restart it. 740 Log.e("TextToSpeech.java - addEarcon", "NullPointerException"); 741 e.printStackTrace(); 742 mStarted = false; 743 initTts(); 744 } catch (IllegalStateException e) { 745 // TTS died; restart it. 746 Log.e("TextToSpeech.java - addEarcon", "IllegalStateException"); 747 e.printStackTrace(); 748 mStarted = false; 749 initTts(); 750 } 751 return ERROR; 752 } 753 } 754 755 756 /** 757 * Speaks the string using the specified queuing strategy and speech 758 * parameters. 759 * 760 * @param text 761 * The string of text to be spoken. 762 * @param queueMode 763 * The queuing strategy to use. 764 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 765 * @param params 766 * The list of parameters to be used. Can be null if no parameters are given. 767 * They are specified using a (key, value) pair, where the key can be 768 * {@link Engine#KEY_PARAM_STREAM} or 769 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 770 * 771 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 772 */ 773 public int speak(String text, int queueMode, HashMap<String,String> params) 774 { 775 synchronized (mStartLock) { 776 int result = ERROR; 777 Log.i("TextToSpeech.java - speak", "speak text of length " + text.length()); 778 if (!mStarted) { 779 Log.e("TextToSpeech.java - speak", "service isn't started"); 780 return result; 781 } 782 try { 783 if ((params != null) && (!params.isEmpty())) { 784 setCachedParam(params, Engine.KEY_PARAM_STREAM, Engine.PARAM_POSITION_STREAM); 785 setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID, 786 Engine.PARAM_POSITION_UTTERANCE_ID); 787 setCachedParam(params, Engine.KEY_PARAM_ENGINE, Engine.PARAM_POSITION_ENGINE); 788 setCachedParam(params, Engine.KEY_PARAM_VOLUME, Engine.PARAM_POSITION_VOLUME); 789 setCachedParam(params, Engine.KEY_PARAM_PAN, Engine.PARAM_POSITION_PAN); 790 } 791 result = mITts.speak(mPackageName, text, queueMode, mCachedParams); 792 } catch (RemoteException e) { 793 // TTS died; restart it. 794 Log.e("TextToSpeech.java - speak", "RemoteException"); 795 e.printStackTrace(); 796 mStarted = false; 797 initTts(); 798 } catch (NullPointerException e) { 799 // TTS died; restart it. 800 Log.e("TextToSpeech.java - speak", "NullPointerException"); 801 e.printStackTrace(); 802 mStarted = false; 803 initTts(); 804 } catch (IllegalStateException e) { 805 // TTS died; restart it. 806 Log.e("TextToSpeech.java - speak", "IllegalStateException"); 807 e.printStackTrace(); 808 mStarted = false; 809 initTts(); 810 } finally { 811 resetCachedParams(); 812 return result; 813 } 814 } 815 } 816 817 818 /** 819 * Plays the earcon using the specified queueing mode and parameters. 820 * 821 * @param earcon 822 * The earcon that should be played 823 * @param queueMode 824 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 825 * @param params 826 * The list of parameters to be used. Can be null if no parameters are given. 827 * They are specified using a (key, value) pair, where the key can be 828 * {@link Engine#KEY_PARAM_STREAM} or 829 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 830 * 831 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 832 */ 833 public int playEarcon(String earcon, int queueMode, 834 HashMap<String,String> params) { 835 synchronized (mStartLock) { 836 int result = ERROR; 837 if (!mStarted) { 838 return result; 839 } 840 try { 841 if ((params != null) && (!params.isEmpty())) { 842 String extra = params.get(Engine.KEY_PARAM_STREAM); 843 if (extra != null) { 844 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = extra; 845 } 846 setCachedParam(params, Engine.KEY_PARAM_STREAM, Engine.PARAM_POSITION_STREAM); 847 setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID, 848 Engine.PARAM_POSITION_UTTERANCE_ID); 849 } 850 result = mITts.playEarcon(mPackageName, earcon, queueMode, null); 851 } catch (RemoteException e) { 852 // TTS died; restart it. 853 Log.e("TextToSpeech.java - playEarcon", "RemoteException"); 854 e.printStackTrace(); 855 mStarted = false; 856 initTts(); 857 } catch (NullPointerException e) { 858 // TTS died; restart it. 859 Log.e("TextToSpeech.java - playEarcon", "NullPointerException"); 860 e.printStackTrace(); 861 mStarted = false; 862 initTts(); 863 } catch (IllegalStateException e) { 864 // TTS died; restart it. 865 Log.e("TextToSpeech.java - playEarcon", "IllegalStateException"); 866 e.printStackTrace(); 867 mStarted = false; 868 initTts(); 869 } finally { 870 resetCachedParams(); 871 return result; 872 } 873 } 874 } 875 876 /** 877 * Plays silence for the specified amount of time using the specified 878 * queue mode. 879 * 880 * @param durationInMs 881 * A long that indicates how long the silence should last. 882 * @param queueMode 883 * {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. 884 * @param params 885 * The list of parameters to be used. Can be null if no parameters are given. 886 * They are specified using a (key, value) pair, where the key can be 887 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 888 * 889 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 890 */ 891 public int playSilence(long durationInMs, int queueMode, HashMap<String,String> params) { 892 synchronized (mStartLock) { 893 int result = ERROR; 894 if (!mStarted) { 895 return result; 896 } 897 try { 898 if ((params != null) && (!params.isEmpty())) { 899 setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID, 900 Engine.PARAM_POSITION_UTTERANCE_ID); 901 } 902 result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams); 903 } catch (RemoteException e) { 904 // TTS died; restart it. 905 Log.e("TextToSpeech.java - playSilence", "RemoteException"); 906 e.printStackTrace(); 907 mStarted = false; 908 initTts(); 909 } catch (NullPointerException e) { 910 // TTS died; restart it. 911 Log.e("TextToSpeech.java - playSilence", "NullPointerException"); 912 e.printStackTrace(); 913 mStarted = false; 914 initTts(); 915 } catch (IllegalStateException e) { 916 // TTS died; restart it. 917 Log.e("TextToSpeech.java - playSilence", "IllegalStateException"); 918 e.printStackTrace(); 919 mStarted = false; 920 initTts(); 921 } finally { 922 resetCachedParams(); 923 return result; 924 } 925 } 926 } 927 928 929 /** 930 * Returns whether or not the TextToSpeech engine is busy speaking. 931 * 932 * @return Whether or not the TextToSpeech engine is busy speaking. 933 */ 934 public boolean isSpeaking() { 935 synchronized (mStartLock) { 936 if (!mStarted) { 937 return false; 938 } 939 try { 940 return mITts.isSpeaking(); 941 } catch (RemoteException e) { 942 // TTS died; restart it. 943 Log.e("TextToSpeech.java - isSpeaking", "RemoteException"); 944 e.printStackTrace(); 945 mStarted = false; 946 initTts(); 947 } catch (NullPointerException e) { 948 // TTS died; restart it. 949 Log.e("TextToSpeech.java - isSpeaking", "NullPointerException"); 950 e.printStackTrace(); 951 mStarted = false; 952 initTts(); 953 } catch (IllegalStateException e) { 954 // TTS died; restart it. 955 Log.e("TextToSpeech.java - isSpeaking", "IllegalStateException"); 956 e.printStackTrace(); 957 mStarted = false; 958 initTts(); 959 } 960 return false; 961 } 962 } 963 964 965 /** 966 * Interrupts the current utterance (whether played or rendered to file) and discards other 967 * utterances in the queue. 968 * 969 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 970 */ 971 public int stop() { 972 synchronized (mStartLock) { 973 int result = ERROR; 974 if (!mStarted) { 975 return result; 976 } 977 try { 978 result = mITts.stop(mPackageName); 979 } catch (RemoteException e) { 980 // TTS died; restart it. 981 Log.e("TextToSpeech.java - stop", "RemoteException"); 982 e.printStackTrace(); 983 mStarted = false; 984 initTts(); 985 } catch (NullPointerException e) { 986 // TTS died; restart it. 987 Log.e("TextToSpeech.java - stop", "NullPointerException"); 988 e.printStackTrace(); 989 mStarted = false; 990 initTts(); 991 } catch (IllegalStateException e) { 992 // TTS died; restart it. 993 Log.e("TextToSpeech.java - stop", "IllegalStateException"); 994 e.printStackTrace(); 995 mStarted = false; 996 initTts(); 997 } finally { 998 return result; 999 } 1000 } 1001 } 1002 1003 1004 /** 1005 * Sets the speech rate for the TextToSpeech engine. 1006 * 1007 * This has no effect on any pre-recorded speech. 1008 * 1009 * @param speechRate 1010 * The speech rate for the TextToSpeech engine. 1 is the normal speed, 1011 * lower values slow down the speech (0.5 is half the normal speech rate), 1012 * greater values accelerate it (2 is twice the normal speech rate). 1013 * 1014 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1015 */ 1016 public int setSpeechRate(float speechRate) { 1017 synchronized (mStartLock) { 1018 int result = ERROR; 1019 if (!mStarted) { 1020 return result; 1021 } 1022 try { 1023 if (speechRate > 0) { 1024 int rate = (int)(speechRate*100); 1025 mCachedParams[Engine.PARAM_POSITION_RATE + 1] = String.valueOf(rate); 1026 // the rate is not set here, instead it is cached so it will be associated 1027 // with all upcoming utterances. 1028 if (speechRate > 0.0f) { 1029 result = SUCCESS; 1030 } else { 1031 result = ERROR; 1032 } 1033 } 1034 } catch (NullPointerException e) { 1035 // TTS died; restart it. 1036 Log.e("TextToSpeech.java - setSpeechRate", "NullPointerException"); 1037 e.printStackTrace(); 1038 mStarted = false; 1039 initTts(); 1040 } catch (IllegalStateException e) { 1041 // TTS died; restart it. 1042 Log.e("TextToSpeech.java - setSpeechRate", "IllegalStateException"); 1043 e.printStackTrace(); 1044 mStarted = false; 1045 initTts(); 1046 } finally { 1047 return result; 1048 } 1049 } 1050 } 1051 1052 1053 /** 1054 * Sets the speech pitch for the TextToSpeech engine. 1055 * 1056 * This has no effect on any pre-recorded speech. 1057 * 1058 * @param pitch 1059 * The pitch for the TextToSpeech engine. 1 is the normal pitch, 1060 * lower values lower the tone of the synthesized voice, 1061 * greater values increase it. 1062 * 1063 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1064 */ 1065 public int setPitch(float pitch) { 1066 synchronized (mStartLock) { 1067 int result = ERROR; 1068 if (!mStarted) { 1069 return result; 1070 } 1071 try { 1072 // the pitch is not set here, instead it is cached so it will be associated 1073 // with all upcoming utterances. 1074 if (pitch > 0) { 1075 int p = (int)(pitch*100); 1076 mCachedParams[Engine.PARAM_POSITION_PITCH + 1] = String.valueOf(p); 1077 result = SUCCESS; 1078 } 1079 } catch (NullPointerException e) { 1080 // TTS died; restart it. 1081 Log.e("TextToSpeech.java - setPitch", "NullPointerException"); 1082 e.printStackTrace(); 1083 mStarted = false; 1084 initTts(); 1085 } catch (IllegalStateException e) { 1086 // TTS died; restart it. 1087 Log.e("TextToSpeech.java - setPitch", "IllegalStateException"); 1088 e.printStackTrace(); 1089 mStarted = false; 1090 initTts(); 1091 } finally { 1092 return result; 1093 } 1094 } 1095 } 1096 1097 1098 /** 1099 * Sets the language for the TextToSpeech engine. 1100 * The TextToSpeech engine will try to use the closest match to the specified 1101 * language as represented by the Locale, but there is no guarantee that the exact same Locale 1102 * will be used. Use {@link #isLanguageAvailable(Locale)} to check the level of support 1103 * before choosing the language to use for the next utterances. 1104 * 1105 * @param loc 1106 * The locale describing the language to be used. 1107 * 1108 * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE}, 1109 * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE}, 1110 * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}. 1111 */ 1112 public int setLanguage(Locale loc) { 1113 synchronized (mStartLock) { 1114 int result = LANG_NOT_SUPPORTED; 1115 if (!mStarted) { 1116 return result; 1117 } 1118 if (loc == null) { 1119 return result; 1120 } 1121 try { 1122 String language = loc.getISO3Language(); 1123 String country = loc.getISO3Country(); 1124 String variant = loc.getVariant(); 1125 // Check if the language, country, variant are available, and cache 1126 // the available parts. 1127 // Note that the language is not actually set here, instead it is cached so it 1128 // will be associated with all upcoming utterances. 1129 result = mITts.isLanguageAvailable(language, country, variant, mCachedParams); 1130 if (result >= LANG_AVAILABLE){ 1131 mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1] = language; 1132 if (result >= LANG_COUNTRY_AVAILABLE){ 1133 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = country; 1134 } else { 1135 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1] = ""; 1136 } 1137 if (result >= LANG_COUNTRY_VAR_AVAILABLE){ 1138 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = variant; 1139 } else { 1140 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1] = ""; 1141 } 1142 } 1143 } catch (RemoteException e) { 1144 // TTS died; restart it. 1145 Log.e("TextToSpeech.java - setLanguage", "RemoteException"); 1146 e.printStackTrace(); 1147 mStarted = false; 1148 initTts(); 1149 } catch (NullPointerException e) { 1150 // TTS died; restart it. 1151 Log.e("TextToSpeech.java - setLanguage", "NullPointerException"); 1152 e.printStackTrace(); 1153 mStarted = false; 1154 initTts(); 1155 } catch (IllegalStateException e) { 1156 // TTS died; restart it. 1157 Log.e("TextToSpeech.java - setLanguage", "IllegalStateException"); 1158 e.printStackTrace(); 1159 mStarted = false; 1160 initTts(); 1161 } finally { 1162 return result; 1163 } 1164 } 1165 } 1166 1167 1168 /** 1169 * Returns a Locale instance describing the language currently being used by the TextToSpeech 1170 * engine. 1171 * @return language, country (if any) and variant (if any) used by the engine stored in a Locale 1172 * instance, or null is the TextToSpeech engine has failed. 1173 */ 1174 public Locale getLanguage() { 1175 synchronized (mStartLock) { 1176 if (!mStarted) { 1177 return null; 1178 } 1179 try { 1180 // Only do a call to the native synth if there is nothing in the cached params 1181 if (mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1].length() < 1){ 1182 String[] locStrings = mITts.getLanguage(); 1183 if ((locStrings != null) && (locStrings.length == 3)) { 1184 return new Locale(locStrings[0], locStrings[1], locStrings[2]); 1185 } else { 1186 return null; 1187 } 1188 } else { 1189 return new Locale(mCachedParams[Engine.PARAM_POSITION_LANGUAGE + 1], 1190 mCachedParams[Engine.PARAM_POSITION_COUNTRY + 1], 1191 mCachedParams[Engine.PARAM_POSITION_VARIANT + 1]); 1192 } 1193 } catch (RemoteException e) { 1194 // TTS died; restart it. 1195 Log.e("TextToSpeech.java - getLanguage", "RemoteException"); 1196 e.printStackTrace(); 1197 mStarted = false; 1198 initTts(); 1199 } catch (NullPointerException e) { 1200 // TTS died; restart it. 1201 Log.e("TextToSpeech.java - getLanguage", "NullPointerException"); 1202 e.printStackTrace(); 1203 mStarted = false; 1204 initTts(); 1205 } catch (IllegalStateException e) { 1206 // TTS died; restart it. 1207 Log.e("TextToSpeech.java - getLanguage", "IllegalStateException"); 1208 e.printStackTrace(); 1209 mStarted = false; 1210 initTts(); 1211 } 1212 return null; 1213 } 1214 } 1215 1216 /** 1217 * Checks if the specified language as represented by the Locale is available and supported. 1218 * 1219 * @param loc 1220 * The Locale describing the language to be used. 1221 * 1222 * @return code indicating the support status for the locale. See {@link #LANG_AVAILABLE}, 1223 * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE}, 1224 * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}. 1225 */ 1226 public int isLanguageAvailable(Locale loc) { 1227 synchronized (mStartLock) { 1228 int result = LANG_NOT_SUPPORTED; 1229 if (!mStarted) { 1230 return result; 1231 } 1232 try { 1233 result = mITts.isLanguageAvailable(loc.getISO3Language(), 1234 loc.getISO3Country(), loc.getVariant(), mCachedParams); 1235 } catch (RemoteException e) { 1236 // TTS died; restart it. 1237 Log.e("TextToSpeech.java - isLanguageAvailable", "RemoteException"); 1238 e.printStackTrace(); 1239 mStarted = false; 1240 initTts(); 1241 } catch (NullPointerException e) { 1242 // TTS died; restart it. 1243 Log.e("TextToSpeech.java - isLanguageAvailable", "NullPointerException"); 1244 e.printStackTrace(); 1245 mStarted = false; 1246 initTts(); 1247 } catch (IllegalStateException e) { 1248 // TTS died; restart it. 1249 Log.e("TextToSpeech.java - isLanguageAvailable", "IllegalStateException"); 1250 e.printStackTrace(); 1251 mStarted = false; 1252 initTts(); 1253 } finally { 1254 return result; 1255 } 1256 } 1257 } 1258 1259 1260 /** 1261 * Synthesizes the given text to a file using the specified parameters. 1262 * 1263 * @param text 1264 * The String of text that should be synthesized 1265 * @param params 1266 * The list of parameters to be used. Can be null if no parameters are given. 1267 * They are specified using a (key, value) pair, where the key can be 1268 * {@link Engine#KEY_PARAM_UTTERANCE_ID}. 1269 * @param filename 1270 * The string that gives the full output filename; it should be 1271 * something like "/sdcard/myappsounds/mysound.wav". 1272 * 1273 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1274 */ 1275 public int synthesizeToFile(String text, HashMap<String,String> params, 1276 String filename) { 1277 Log.i("TextToSpeech.java", "synthesizeToFile()"); 1278 synchronized (mStartLock) { 1279 int result = ERROR; 1280 Log.i("TextToSpeech.java - synthesizeToFile", "synthesizeToFile text of length " 1281 + text.length()); 1282 if (!mStarted) { 1283 Log.e("TextToSpeech.java - synthesizeToFile", "service isn't started"); 1284 return result; 1285 } 1286 try { 1287 if ((params != null) && (!params.isEmpty())) { 1288 // no need to read the stream type here 1289 setCachedParam(params, Engine.KEY_PARAM_UTTERANCE_ID, 1290 Engine.PARAM_POSITION_UTTERANCE_ID); 1291 setCachedParam(params, Engine.KEY_PARAM_ENGINE, Engine.PARAM_POSITION_ENGINE); 1292 } 1293 result = mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename) ? 1294 SUCCESS : ERROR; 1295 } catch (RemoteException e) { 1296 // TTS died; restart it. 1297 Log.e("TextToSpeech.java - synthesizeToFile", "RemoteException"); 1298 e.printStackTrace(); 1299 mStarted = false; 1300 initTts(); 1301 } catch (NullPointerException e) { 1302 // TTS died; restart it. 1303 Log.e("TextToSpeech.java - synthesizeToFile", "NullPointerException"); 1304 e.printStackTrace(); 1305 mStarted = false; 1306 initTts(); 1307 } catch (IllegalStateException e) { 1308 // TTS died; restart it. 1309 Log.e("TextToSpeech.java - synthesizeToFile", "IllegalStateException"); 1310 e.printStackTrace(); 1311 mStarted = false; 1312 initTts(); 1313 } finally { 1314 resetCachedParams(); 1315 return result; 1316 } 1317 } 1318 } 1319 1320 1321 /** 1322 * Convenience method to reset the cached parameters to the current default values 1323 * if they are not persistent between calls to the service. 1324 */ 1325 private void resetCachedParams() { 1326 mCachedParams[Engine.PARAM_POSITION_STREAM + 1] = 1327 String.valueOf(Engine.DEFAULT_STREAM); 1328 mCachedParams[Engine.PARAM_POSITION_UTTERANCE_ID+ 1] = ""; 1329 mCachedParams[Engine.PARAM_POSITION_VOLUME + 1] = Engine.DEFAULT_VOLUME_STRING; 1330 mCachedParams[Engine.PARAM_POSITION_PAN + 1] = Engine.DEFAULT_PAN_STRING; 1331 } 1332 1333 /** 1334 * Convenience method to save a parameter in the cached parameter array, at the given index, 1335 * for a property saved in the given hashmap. 1336 */ 1337 private void setCachedParam(HashMap<String,String> params, String key, int keyIndex) { 1338 String extra = params.get(key); 1339 if (extra != null) { 1340 mCachedParams[keyIndex+1] = extra; 1341 } 1342 } 1343 1344 /** 1345 * Sets the OnUtteranceCompletedListener that will fire when an utterance completes. 1346 * 1347 * @param listener 1348 * The OnUtteranceCompletedListener 1349 * 1350 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1351 */ 1352 public int setOnUtteranceCompletedListener( 1353 final OnUtteranceCompletedListener listener) { 1354 synchronized (mStartLock) { 1355 int result = ERROR; 1356 if (!mStarted) { 1357 return result; 1358 } 1359 mITtscallback = new ITtsCallback.Stub() { 1360 public void utteranceCompleted(String utteranceId) throws RemoteException { 1361 if (listener != null) { 1362 listener.onUtteranceCompleted(utteranceId); 1363 } 1364 } 1365 }; 1366 try { 1367 result = mITts.registerCallback(mPackageName, mITtscallback); 1368 } catch (RemoteException e) { 1369 // TTS died; restart it. 1370 Log.e("TextToSpeech.java - registerCallback", "RemoteException"); 1371 e.printStackTrace(); 1372 mStarted = false; 1373 initTts(); 1374 } catch (NullPointerException e) { 1375 // TTS died; restart it. 1376 Log.e("TextToSpeech.java - registerCallback", "NullPointerException"); 1377 e.printStackTrace(); 1378 mStarted = false; 1379 initTts(); 1380 } catch (IllegalStateException e) { 1381 // TTS died; restart it. 1382 Log.e("TextToSpeech.java - registerCallback", "IllegalStateException"); 1383 e.printStackTrace(); 1384 mStarted = false; 1385 initTts(); 1386 } finally { 1387 return result; 1388 } 1389 } 1390 } 1391 1392 /** 1393 * Sets the speech synthesis engine to be used by its packagename. 1394 * 1395 * @param enginePackageName 1396 * The packagename for the synthesis engine (ie, "com.svox.pico") 1397 * 1398 * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. 1399 */ 1400 public int setEngineByPackageName(String enginePackageName) { 1401 synchronized (mStartLock) { 1402 int result = TextToSpeech.ERROR; 1403 if (!mStarted) { 1404 return result; 1405 } 1406 try { 1407 result = mITts.setEngineByPackageName(enginePackageName); 1408 if (result == TextToSpeech.SUCCESS){ 1409 mCachedParams[Engine.PARAM_POSITION_ENGINE + 1] = enginePackageName; 1410 } 1411 } catch (RemoteException e) { 1412 // TTS died; restart it. 1413 Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException"); 1414 e.printStackTrace(); 1415 mStarted = false; 1416 initTts(); 1417 } catch (NullPointerException e) { 1418 // TTS died; restart it. 1419 Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException"); 1420 e.printStackTrace(); 1421 mStarted = false; 1422 initTts(); 1423 } catch (IllegalStateException e) { 1424 // TTS died; restart it. 1425 Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException"); 1426 e.printStackTrace(); 1427 mStarted = false; 1428 initTts(); 1429 } finally { 1430 return result; 1431 } 1432 } 1433 } 1434 1435 1436 /** 1437 * Gets the packagename of the default speech synthesis engine. 1438 * 1439 * @return Packagename of the TTS engine that the user has chosen as their default. 1440 */ 1441 public String getDefaultEngine() { 1442 synchronized (mStartLock) { 1443 String engineName = ""; 1444 if (!mStarted) { 1445 return engineName; 1446 } 1447 try { 1448 engineName = mITts.getDefaultEngine(); 1449 } catch (RemoteException e) { 1450 // TTS died; restart it. 1451 Log.e("TextToSpeech.java - setEngineByPackageName", "RemoteException"); 1452 e.printStackTrace(); 1453 mStarted = false; 1454 initTts(); 1455 } catch (NullPointerException e) { 1456 // TTS died; restart it. 1457 Log.e("TextToSpeech.java - setEngineByPackageName", "NullPointerException"); 1458 e.printStackTrace(); 1459 mStarted = false; 1460 initTts(); 1461 } catch (IllegalStateException e) { 1462 // TTS died; restart it. 1463 Log.e("TextToSpeech.java - setEngineByPackageName", "IllegalStateException"); 1464 e.printStackTrace(); 1465 mStarted = false; 1466 initTts(); 1467 } finally { 1468 return engineName; 1469 } 1470 } 1471 } 1472 1473 1474 /** 1475 * Returns whether or not the user is forcing their defaults to override the 1476 * Text-To-Speech settings set by applications. 1477 * 1478 * @return Whether or not defaults are enforced. 1479 */ 1480 public boolean areDefaultsEnforced() { 1481 synchronized (mStartLock) { 1482 boolean defaultsEnforced = false; 1483 if (!mStarted) { 1484 return defaultsEnforced; 1485 } 1486 try { 1487 defaultsEnforced = mITts.areDefaultsEnforced(); 1488 } catch (RemoteException e) { 1489 // TTS died; restart it. 1490 Log.e("TextToSpeech.java - areDefaultsEnforced", "RemoteException"); 1491 e.printStackTrace(); 1492 mStarted = false; 1493 initTts(); 1494 } catch (NullPointerException e) { 1495 // TTS died; restart it. 1496 Log.e("TextToSpeech.java - areDefaultsEnforced", "NullPointerException"); 1497 e.printStackTrace(); 1498 mStarted = false; 1499 initTts(); 1500 } catch (IllegalStateException e) { 1501 // TTS died; restart it. 1502 Log.e("TextToSpeech.java - areDefaultsEnforced", "IllegalStateException"); 1503 e.printStackTrace(); 1504 mStarted = false; 1505 initTts(); 1506 } finally { 1507 return defaultsEnforced; 1508 } 1509 } 1510 } 1511} 1512