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