TextToSpeech.java revision 630a8de44fa0ca855c4a87d939432f831e8ed531
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.content.ComponentName; 22import android.content.Context; 23import android.content.Intent; 24import android.content.ServiceConnection; 25import android.media.AudioManager; 26import android.os.IBinder; 27import android.os.RemoteException; 28import android.util.Log; 29 30import java.util.HashMap; 31import java.util.Locale; 32 33/** 34 * 35 * Synthesizes speech from text for immediate playback or to create a sound file. 36 * 37 */ 38//TODO complete javadoc + add links to constants 39public class TextToSpeech { 40 41 /** 42 * Denotes a successful operation. 43 */ 44 public static final int TTS_SUCCESS = 0; 45 /** 46 * Denotes a generic operation failure. 47 */ 48 public static final int TTS_ERROR = -1; 49 50 /** 51 * Queue mode where all entries in the playback queue (media to be played 52 * and text to be synthesized) are dropped and replaced by the new entry. 53 */ 54 public static final int TTS_QUEUE_FLUSH = 0; 55 /** 56 * Queue mode where the new entry is added at the end of the playback queue. 57 */ 58 public static final int TTS_QUEUE_ADD = 1; 59 60 61 /** 62 * Denotes the language is available exactly as specified by the locale 63 */ 64 public static final int TTS_LANG_COUNTRY_VAR_AVAILABLE = 2; 65 66 67 /** 68 * Denotes the language is available for the language and country specified 69 * by the locale, but not the variant. 70 */ 71 public static final int TTS_LANG_COUNTRY_AVAILABLE = 1; 72 73 74 /** 75 * Denotes the language is available for the language by the locale, 76 * but not the country and variant. 77 */ 78 public static final int TTS_LANG_AVAILABLE = 0; 79 80 /** 81 * Denotes the language data is missing. 82 */ 83 public static final int TTS_LANG_MISSING_DATA = -1; 84 85 /** 86 * Denotes the language is not supported by the current TTS engine. 87 */ 88 public static final int TTS_LANG_NOT_SUPPORTED = -2; 89 90 91 /** 92 * Called when the TTS has initialized. 93 * 94 * The InitListener must implement the onInit function. onInit is passed a 95 * status code indicating the result of the TTS initialization. 96 */ 97 public interface OnInitListener { 98 public void onInit(int status); 99 } 100 101 /** 102 * Internal constants for the TTS functionality 103 * 104 * {@hide} 105 */ 106 public class Engine { 107 // default values for a TTS engine when settings are not found in the provider 108 public static final int FALLBACK_TTS_DEFAULT_RATE = 100; // 1x 109 public static final int FALLBACK_TTS_DEFAULT_PITCH = 100;// 1x 110 public static final int FALLBACK_TTS_USE_DEFAULTS = 0; // false 111 public static final String FALLBACK_TTS_DEFAULT_SYNTH = "com.svox.pico"; 112 113 // default values for rendering 114 public static final int TTS_DEFAULT_STREAM = AudioManager.STREAM_MUSIC; 115 116 // return codes for a TTS engine's check data activity 117 public static final int CHECK_VOICE_DATA_PASS = 1; 118 public static final int CHECK_VOICE_DATA_FAIL = 0; 119 public static final int CHECK_VOICE_DATA_BAD_DATA = -1; 120 public static final int CHECK_VOICE_DATA_MISSING_DATA = -2; 121 public static final int CHECK_VOICE_DATA_MISSING_DATA_NO_SDCARD = -3; 122 123 // return codes for a TTS engine's check data activity 124 public static final String VOICE_DATA_ROOT_DIRECTORY = "dataRoot"; 125 public static final String VOICE_DATA_FILES = "dataFiles"; 126 public static final String VOICE_DATA_FILES_INFO = "dataFilesInfo"; 127 128 // keys for the parameters passed with speak commands 129 public static final String TTS_KEY_PARAM_RATE = "rate"; 130 public static final String TTS_KEY_PARAM_LANGUAGE = "language"; 131 public static final String TTS_KEY_PARAM_COUNTRY = "country"; 132 public static final String TTS_KEY_PARAM_VARIANT = "variant"; 133 public static final String TTS_KEY_PARAM_STREAM = "streamType"; 134 public static final String TTS_KEY_PARAM_UTTERANCE_ID = "utteranceId"; 135 protected static final int TTS_PARAM_POSITION_RATE = 0; 136 protected static final int TTS_PARAM_POSITION_LANGUAGE = 2; 137 protected static final int TTS_PARAM_POSITION_COUNTRY = 4; 138 protected static final int TTS_PARAM_POSITION_VARIANT = 6; 139 protected static final int TTS_PARAM_POSITION_STREAM = 8; 140 protected static final int TTS_PARAM_POSITION_UTTERANCE_ID = 10; 141 protected static final int TTS_NB_CACHED_PARAMS = 6; 142 } 143 144 /** 145 * Connection needed for the TTS. 146 */ 147 private ServiceConnection mServiceConnection; 148 149 private ITts mITts = null; 150 private Context mContext = null; 151 private String mPackageName = ""; 152 private OnInitListener mInitListener = null; 153 private boolean mStarted = false; 154 private final Object mStartLock = new Object(); 155 /** 156 * Used to store the cached parameters sent along with each synthesis request to the 157 * TTS service. 158 */ 159 private String[] mCachedParams; 160 161 /** 162 * The constructor for the TTS. 163 * 164 * @param context 165 * The context 166 * @param listener 167 * The InitListener that will be called when the TTS has 168 * initialized successfully. 169 */ 170 public TextToSpeech(Context context, OnInitListener listener) { 171 mContext = context; 172 mPackageName = mContext.getPackageName(); 173 mInitListener = listener; 174 175 mCachedParams = new String[2*Engine.TTS_NB_CACHED_PARAMS]; // store key and value 176 mCachedParams[Engine.TTS_PARAM_POSITION_RATE] = Engine.TTS_KEY_PARAM_RATE; 177 mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE] = Engine.TTS_KEY_PARAM_LANGUAGE; 178 mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY] = Engine.TTS_KEY_PARAM_COUNTRY; 179 mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT] = Engine.TTS_KEY_PARAM_VARIANT; 180 mCachedParams[Engine.TTS_PARAM_POSITION_STREAM] = Engine.TTS_KEY_PARAM_STREAM; 181 182 mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = 183 String.valueOf(Engine.FALLBACK_TTS_DEFAULT_RATE); 184 // initialize the language cached parameters with the current Locale 185 Locale defaultLoc = Locale.getDefault(); 186 mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = defaultLoc.getISO3Language(); 187 mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = defaultLoc.getISO3Country(); 188 mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = defaultLoc.getVariant(); 189 190 mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = 191 String.valueOf(Engine.TTS_DEFAULT_STREAM); 192 mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID+ 1] = ""; 193 194 initTts(); 195 } 196 197 198 private void initTts() { 199 mStarted = false; 200 201 // Initialize the TTS, run the callback after the binding is successful 202 mServiceConnection = new ServiceConnection() { 203 public void onServiceConnected(ComponentName name, IBinder service) { 204 synchronized(mStartLock) { 205 mITts = ITts.Stub.asInterface(service); 206 mStarted = true; 207 if (mInitListener != null) { 208 // TODO manage failures and missing resources 209 mInitListener.onInit(TTS_SUCCESS); 210 } 211 } 212 } 213 214 public void onServiceDisconnected(ComponentName name) { 215 synchronized(mStartLock) { 216 mITts = null; 217 mInitListener = null; 218 mStarted = false; 219 } 220 } 221 }; 222 223 Intent intent = new Intent("android.intent.action.START_TTS_SERVICE"); 224 intent.addCategory("android.intent.category.TTS"); 225 mContext.bindService(intent, mServiceConnection, 226 Context.BIND_AUTO_CREATE); 227 // TODO handle case where the binding works (should always work) but 228 // the plugin fails 229 } 230 231 232 /** 233 * Shuts down the TTS. It is good practice to call this in the onDestroy 234 * method of the Activity that is using the TTS so that the TTS is stopped 235 * cleanly. 236 */ 237 public void shutdown() { 238 try { 239 mContext.unbindService(mServiceConnection); 240 } catch (IllegalArgumentException e) { 241 // Do nothing and fail silently since an error here indicates that 242 // binding never succeeded in the first place. 243 } 244 } 245 246 247 /** 248 * Adds a mapping between a string of text and a sound resource in a 249 * package. 250 * 251 * @see #TTS.speak(String text, int queueMode, String[] params) 252 * 253 * @param text 254 * Example: <b><code>"south_south_east"</code></b><br/> 255 * 256 * @param packagename 257 * Pass the packagename of the application that contains the 258 * resource. If the resource is in your own application (this is 259 * the most common case), then put the packagename of your 260 * application here.<br/> 261 * Example: <b>"com.google.marvin.compass"</b><br/> 262 * The packagename can be found in the AndroidManifest.xml of 263 * your application. 264 * <p> 265 * <code><manifest xmlns:android="..." 266 * package="<b>com.google.marvin.compass</b>"></code> 267 * </p> 268 * 269 * @param resourceId 270 * Example: <b><code>R.raw.south_south_east</code></b> 271 * 272 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 273 */ 274 public int addSpeech(String text, String packagename, int resourceId) { 275 synchronized(mStartLock) { 276 if (!mStarted) { 277 return TTS_ERROR; 278 } 279 try { 280 mITts.addSpeech(mPackageName, text, packagename, resourceId); 281 return TTS_SUCCESS; 282 } catch (RemoteException e) { 283 // TTS died; restart it. 284 Log.e("TextToSpeech.java - addSpeech", "RemoteException"); 285 e.printStackTrace(); 286 mStarted = false; 287 initTts(); 288 } catch (NullPointerException e) { 289 // TTS died; restart it. 290 Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); 291 e.printStackTrace(); 292 mStarted = false; 293 initTts(); 294 } catch (IllegalStateException e) { 295 // TTS died; restart it. 296 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); 297 e.printStackTrace(); 298 mStarted = false; 299 initTts(); 300 } 301 return TTS_ERROR; 302 } 303 } 304 305 306 /** 307 * Adds a mapping between a string of text and a sound file. Using this, it 308 * is possible to add custom pronounciations for text. 309 * 310 * @param text 311 * The string of text 312 * @param filename 313 * The full path to the sound file (for example: 314 * "/sdcard/mysounds/hello.wav") 315 * 316 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 317 */ 318 public int addSpeech(String text, String filename) { 319 synchronized (mStartLock) { 320 if (!mStarted) { 321 return TTS_ERROR; 322 } 323 try { 324 mITts.addSpeechFile(mPackageName, text, filename); 325 return TTS_SUCCESS; 326 } catch (RemoteException e) { 327 // TTS died; restart it. 328 Log.e("TextToSpeech.java - addSpeech", "RemoteException"); 329 e.printStackTrace(); 330 mStarted = false; 331 initTts(); 332 } catch (NullPointerException e) { 333 // TTS died; restart it. 334 Log.e("TextToSpeech.java - addSpeech", "NullPointerException"); 335 e.printStackTrace(); 336 mStarted = false; 337 initTts(); 338 } catch (IllegalStateException e) { 339 // TTS died; restart it. 340 Log.e("TextToSpeech.java - addSpeech", "IllegalStateException"); 341 e.printStackTrace(); 342 mStarted = false; 343 initTts(); 344 } 345 return TTS_ERROR; 346 } 347 } 348 349 350 /** 351 * Speaks the string using the specified queuing strategy and speech 352 * parameters. Note that the speech parameters are not universally supported 353 * by all engines and will be treated as a hint. The TTS library will try to 354 * fulfill these parameters as much as possible, but there is no guarantee 355 * that the voice used will have the properties specified. 356 * 357 * @param text 358 * The string of text to be spoken. 359 * @param queueMode 360 * The queuing strategy to use. 361 * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH. 362 * @param params 363 * The hashmap of speech parameters to be used. 364 * 365 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 366 */ 367 public int speak(String text, int queueMode, HashMap<String,String> params) 368 { 369 synchronized (mStartLock) { 370 int result = TTS_ERROR; 371 Log.i("TTS received: ", text); 372 if (!mStarted) { 373 return result; 374 } 375 try { 376 if ((params != null) && (!params.isEmpty())) { 377 String extra = params.get(Engine.TTS_KEY_PARAM_STREAM); 378 if (extra != null) { 379 mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = extra; 380 } 381 extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); 382 if (extra != null) { 383 mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra; 384 } 385 } 386 result = mITts.speak(mPackageName, text, queueMode, mCachedParams); 387 } catch (RemoteException e) { 388 // TTS died; restart it. 389 Log.e("TextToSpeech.java - speak", "RemoteException"); 390 e.printStackTrace(); 391 mStarted = false; 392 initTts(); 393 } catch (NullPointerException e) { 394 // TTS died; restart it. 395 Log.e("TextToSpeech.java - speak", "NullPointerException"); 396 e.printStackTrace(); 397 mStarted = false; 398 initTts(); 399 } catch (IllegalStateException e) { 400 // TTS died; restart it. 401 Log.e("TextToSpeech.java - speak", "IllegalStateException"); 402 e.printStackTrace(); 403 mStarted = false; 404 initTts(); 405 } finally { 406 resetCachedParams(); 407 return result; 408 } 409 } 410 } 411 412 413 /** 414 * Plays the earcon using the specified queueing mode and parameters. 415 * 416 * @param earcon 417 * The earcon that should be played 418 * @param queueMode 419 * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH. 420 * @param params 421 * The hashmap of parameters to be used. 422 * 423 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 424 */ 425 public int playEarcon(String earcon, int queueMode, 426 HashMap<String,String> params) { 427 synchronized (mStartLock) { 428 int result = TTS_ERROR; 429 if (!mStarted) { 430 return result; 431 } 432 try { 433 if ((params != null) && (!params.isEmpty())) { 434 String extra = params.get(Engine.TTS_KEY_PARAM_STREAM); 435 if (extra != null) { 436 mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = extra; 437 } 438 extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); 439 if (extra != null) { 440 mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra; 441 } 442 } 443 result = mITts.playEarcon(mPackageName, earcon, queueMode, null); 444 } catch (RemoteException e) { 445 // TTS died; restart it. 446 Log.e("TextToSpeech.java - playEarcon", "RemoteException"); 447 e.printStackTrace(); 448 mStarted = false; 449 initTts(); 450 } catch (NullPointerException e) { 451 // TTS died; restart it. 452 Log.e("TextToSpeech.java - playEarcon", "NullPointerException"); 453 e.printStackTrace(); 454 mStarted = false; 455 initTts(); 456 } catch (IllegalStateException e) { 457 // TTS died; restart it. 458 Log.e("TextToSpeech.java - playEarcon", "IllegalStateException"); 459 e.printStackTrace(); 460 mStarted = false; 461 initTts(); 462 } finally { 463 resetCachedParams(); 464 return result; 465 } 466 } 467 } 468 469 /** 470 * Plays silence for the specified amount of time using the specified 471 * queue mode. 472 * 473 * @param durationInMs 474 * A long that indicates how long the silence should last. 475 * @param queueMode 476 * See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH. 477 * 478 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 479 */ 480 public int playSilence(long durationInMs, int queueMode) { 481 synchronized (mStartLock) { 482 int result = TTS_ERROR; 483 if (!mStarted) { 484 return result; 485 } 486 try { 487 result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams); 488 } catch (RemoteException e) { 489 // TTS died; restart it. 490 Log.e("TextToSpeech.java - playSilence", "RemoteException"); 491 e.printStackTrace(); 492 mStarted = false; 493 initTts(); 494 } catch (NullPointerException e) { 495 // TTS died; restart it. 496 Log.e("TextToSpeech.java - playSilence", "NullPointerException"); 497 e.printStackTrace(); 498 mStarted = false; 499 initTts(); 500 } catch (IllegalStateException e) { 501 // TTS died; restart it. 502 Log.e("TextToSpeech.java - playSilence", "IllegalStateException"); 503 e.printStackTrace(); 504 mStarted = false; 505 initTts(); 506 } finally { 507 return result; 508 } 509 } 510 } 511 512 513 /** 514 * Returns whether or not the TTS is busy speaking. 515 * 516 * @return Whether or not the TTS is busy speaking. 517 */ 518 public boolean isSpeaking() { 519 synchronized (mStartLock) { 520 if (!mStarted) { 521 return false; 522 } 523 try { 524 return mITts.isSpeaking(); 525 } catch (RemoteException e) { 526 // TTS died; restart it. 527 Log.e("TextToSpeech.java - isSpeaking", "RemoteException"); 528 e.printStackTrace(); 529 mStarted = false; 530 initTts(); 531 } catch (NullPointerException e) { 532 // TTS died; restart it. 533 Log.e("TextToSpeech.java - isSpeaking", "NullPointerException"); 534 e.printStackTrace(); 535 mStarted = false; 536 initTts(); 537 } catch (IllegalStateException e) { 538 // TTS died; restart it. 539 Log.e("TextToSpeech.java - isSpeaking", "IllegalStateException"); 540 e.printStackTrace(); 541 mStarted = false; 542 initTts(); 543 } 544 return false; 545 } 546 } 547 548 549 /** 550 * Stops speech from the TTS. 551 * 552 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 553 */ 554 public int stop() { 555 synchronized (mStartLock) { 556 int result = TTS_ERROR; 557 if (!mStarted) { 558 return result; 559 } 560 try { 561 result = mITts.stop(mPackageName); 562 } catch (RemoteException e) { 563 // TTS died; restart it. 564 Log.e("TextToSpeech.java - stop", "RemoteException"); 565 e.printStackTrace(); 566 mStarted = false; 567 initTts(); 568 } catch (NullPointerException e) { 569 // TTS died; restart it. 570 Log.e("TextToSpeech.java - stop", "NullPointerException"); 571 e.printStackTrace(); 572 mStarted = false; 573 initTts(); 574 } catch (IllegalStateException e) { 575 // TTS died; restart it. 576 Log.e("TextToSpeech.java - stop", "IllegalStateException"); 577 e.printStackTrace(); 578 mStarted = false; 579 initTts(); 580 } finally { 581 return result; 582 } 583 } 584 } 585 586 587 /** 588 * Sets the speech rate for the TTS engine. 589 * 590 * Note that the speech rate is not universally supported by all engines and 591 * will be treated as a hint. The TTS library will try to use the specified 592 * speech rate, but there is no guarantee. 593 * This has no effect on any pre-recorded speech. 594 * 595 * @param speechRate 596 * The speech rate for the TTS engine. 1 is the normal speed, 597 * lower values slow down the speech (0.5 is half the normal speech rate), 598 * greater values accelerate it (2 is twice the normal speech rate). 599 * 600 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 601 */ 602 public int setSpeechRate(float speechRate) { 603 synchronized (mStartLock) { 604 int result = TTS_ERROR; 605 if (!mStarted) { 606 return result; 607 } 608 try { 609 if (speechRate > 0) { 610 int rate = (int)(speechRate*100); 611 mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = String.valueOf(rate); 612 result = mITts.setSpeechRate(mPackageName, rate); 613 } 614 } catch (RemoteException e) { 615 // TTS died; restart it. 616 Log.e("TextToSpeech.java - setSpeechRate", "RemoteException"); 617 e.printStackTrace(); 618 mStarted = false; 619 initTts(); 620 } catch (NullPointerException e) { 621 // TTS died; restart it. 622 Log.e("TextToSpeech.java - setSpeechRate", "NullPointerException"); 623 e.printStackTrace(); 624 mStarted = false; 625 initTts(); 626 } catch (IllegalStateException e) { 627 // TTS died; restart it. 628 Log.e("TextToSpeech.java - setSpeechRate", "IllegalStateException"); 629 e.printStackTrace(); 630 mStarted = false; 631 initTts(); 632 } finally { 633 return result; 634 } 635 } 636 } 637 638 639 /** 640 * Sets the speech pitch for the TTS engine. 641 * 642 * Note that the pitch is not universally supported by all engines and 643 * will be treated as a hint. The TTS library will try to use the specified 644 * pitch, but there is no guarantee. 645 * This has no effect on any pre-recorded speech. 646 * 647 * @param pitch 648 * The pitch for the TTS engine. 1 is the normal pitch, 649 * lower values lower the tone of the synthesized voice, 650 * greater values increase it. 651 * 652 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 653 */ 654 public int setPitch(float pitch) { 655 synchronized (mStartLock) { 656 int result = TTS_ERROR; 657 if (!mStarted) { 658 return result; 659 } 660 try { 661 if (pitch > 0) { 662 result = mITts.setPitch(mPackageName, (int)(pitch*100)); 663 } 664 } catch (RemoteException e) { 665 // TTS died; restart it. 666 Log.e("TextToSpeech.java - setPitch", "RemoteException"); 667 e.printStackTrace(); 668 mStarted = false; 669 initTts(); 670 } catch (NullPointerException e) { 671 // TTS died; restart it. 672 Log.e("TextToSpeech.java - setPitch", "NullPointerException"); 673 e.printStackTrace(); 674 mStarted = false; 675 initTts(); 676 } catch (IllegalStateException e) { 677 // TTS died; restart it. 678 Log.e("TextToSpeech.java - setPitch", "IllegalStateException"); 679 e.printStackTrace(); 680 mStarted = false; 681 initTts(); 682 } finally { 683 return result; 684 } 685 } 686 } 687 688 689 /** 690 * Sets the language for the TTS engine. 691 * 692 * Note that the language is not universally supported by all engines and 693 * will be treated as a hint. The TTS library will try to use the specified 694 * language as represented by the Locale, but there is no guarantee. 695 * 696 * @param loc 697 * The locale describing the language to be used. 698 * 699 * @return Code indicating the support status for the locale. See the TTS_LANG_ codes. 700 */ 701 public int setLanguage(Locale loc) { 702 synchronized (mStartLock) { 703 int result = TTS_LANG_NOT_SUPPORTED; 704 if (!mStarted) { 705 return result; 706 } 707 try { 708 mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1] = loc.getISO3Language(); 709 mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1] = loc.getISO3Country(); 710 mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] = loc.getVariant(); 711 result = mITts.setLanguage(mPackageName, 712 mCachedParams[Engine.TTS_PARAM_POSITION_LANGUAGE + 1], 713 mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY + 1], 714 mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT + 1] ); 715 } catch (RemoteException e) { 716 // TTS died; restart it. 717 Log.e("TextToSpeech.java - setLanguage", "RemoteException"); 718 e.printStackTrace(); 719 mStarted = false; 720 initTts(); 721 } catch (NullPointerException e) { 722 // TTS died; restart it. 723 Log.e("TextToSpeech.java - setLanguage", "NullPointerException"); 724 e.printStackTrace(); 725 mStarted = false; 726 initTts(); 727 } catch (IllegalStateException e) { 728 // TTS died; restart it. 729 Log.e("TextToSpeech.java - setLanguage", "IllegalStateException"); 730 e.printStackTrace(); 731 mStarted = false; 732 initTts(); 733 } finally { 734 return result; 735 } 736 } 737 } 738 739 740 /** 741 * Returns a Locale instance describing the language currently being used by the TTS engine. 742 * @return language, country (if any) and variant (if any) used by the engine stored in a Locale 743 * instance, or null is the TTS engine has failed. 744 */ 745 public Locale getLanguage() { 746 synchronized (mStartLock) { 747 if (!mStarted) { 748 return null; 749 } 750 try { 751 String[] locStrings = mITts.getLanguage(); 752 if (locStrings.length == 3) { 753 return new Locale(locStrings[0], locStrings[1], locStrings[2]); 754 } else { 755 return null; 756 } 757 } catch (RemoteException e) { 758 // TTS died; restart it. 759 Log.e("TextToSpeech.java - getLanguage", "RemoteException"); 760 e.printStackTrace(); 761 mStarted = false; 762 initTts(); 763 } catch (NullPointerException e) { 764 // TTS died; restart it. 765 Log.e("TextToSpeech.java - getLanguage", "NullPointerException"); 766 e.printStackTrace(); 767 mStarted = false; 768 initTts(); 769 } catch (IllegalStateException e) { 770 // TTS died; restart it. 771 Log.e("TextToSpeech.java - getLanguage", "IllegalStateException"); 772 e.printStackTrace(); 773 mStarted = false; 774 initTts(); 775 } 776 return null; 777 } 778 } 779 780 /** 781 * Checks if the specified language as represented by the Locale is available. 782 * 783 * @param loc 784 * The Locale describing the language to be used. 785 * 786 * @return one of TTS_LANG_NOT_SUPPORTED, TTS_LANG_MISSING_DATA, TTS_LANG_AVAILABLE, 787 * TTS_LANG_COUNTRY_AVAILABLE, TTS_LANG_COUNTRY_VAR_AVAILABLE. 788 */ 789 public int isLanguageAvailable(Locale loc) { 790 synchronized (mStartLock) { 791 int result = TTS_LANG_NOT_SUPPORTED; 792 if (!mStarted) { 793 return result; 794 } 795 try { 796 result = mITts.isLanguageAvailable(loc.getISO3Language(), 797 loc.getISO3Country(), loc.getVariant()); 798 } catch (RemoteException e) { 799 // TTS died; restart it. 800 Log.e("TextToSpeech.java - isLanguageAvailable", "RemoteException"); 801 e.printStackTrace(); 802 mStarted = false; 803 initTts(); 804 } catch (NullPointerException e) { 805 // TTS died; restart it. 806 Log.e("TextToSpeech.java - isLanguageAvailable", "NullPointerException"); 807 e.printStackTrace(); 808 mStarted = false; 809 initTts(); 810 } catch (IllegalStateException e) { 811 // TTS died; restart it. 812 Log.e("TextToSpeech.java - isLanguageAvailable", "IllegalStateException"); 813 e.printStackTrace(); 814 mStarted = false; 815 initTts(); 816 } finally { 817 return result; 818 } 819 } 820 } 821 822 823 /** 824 * Synthesizes the given text to a file using the specified parameters. 825 * 826 * @param text 827 * The String of text that should be synthesized 828 * @param params 829 * A hashmap of parameters. 830 * @param filename 831 * The string that gives the full output filename; it should be 832 * something like "/sdcard/myappsounds/mysound.wav". 833 * 834 * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. 835 */ 836 public int synthesizeToFile(String text, HashMap<String,String> params, 837 String filename) { 838 synchronized (mStartLock) { 839 int result = TTS_ERROR; 840 if (!mStarted) { 841 return result; 842 } 843 try { 844 if ((params != null) && (!params.isEmpty())) { 845 // no need to read the stream type here 846 String extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); 847 if (extra != null) { 848 mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra; 849 } 850 } 851 if (mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename)){ 852 result = TTS_SUCCESS; 853 } 854 } catch (RemoteException e) { 855 // TTS died; restart it. 856 Log.e("TextToSpeech.java - synthesizeToFile", "RemoteException"); 857 e.printStackTrace(); 858 mStarted = false; 859 initTts(); 860 } catch (NullPointerException e) { 861 // TTS died; restart it. 862 Log.e("TextToSpeech.java - synthesizeToFile", "NullPointerException"); 863 e.printStackTrace(); 864 mStarted = false; 865 initTts(); 866 } catch (IllegalStateException e) { 867 // TTS died; restart it. 868 Log.e("TextToSpeech.java - synthesizeToFile", "IllegalStateException"); 869 e.printStackTrace(); 870 mStarted = false; 871 initTts(); 872 } finally { 873 resetCachedParams(); 874 return result; 875 } 876 } 877 } 878 879 880 /** 881 * Convenience method to reset the cached parameters to the current default values 882 * if they are not persistent between calls to the service. 883 */ 884 private void resetCachedParams() { 885 mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = 886 String.valueOf(Engine.TTS_DEFAULT_STREAM); 887 mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID+ 1] = ""; 888 } 889 890} 891