1a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen/* 2a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * Copyright (C) 2009 Google Inc. 3a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 4a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * use this file except in compliance with the License. You may obtain a copy of 6a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * the License at 7a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 8a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * http://www.apache.org/licenses/LICENSE-2.0 9a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 10a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * Unless required by applicable law or agreed to in writing, software 11a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * License for the specific language governing permissions and limitations under 14a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * the License. 15a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 16a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenpackage android.tts; 17a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 18a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.app.Service; 19605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Triviimport android.content.ContentResolver; 20a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.content.Context; 21a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.content.Intent; 22a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.content.SharedPreferences; 23a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.content.pm.PackageManager; 24a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.content.pm.PackageManager.NameNotFoundException; 259440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Triviimport android.media.AudioManager; 26a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.media.MediaPlayer; 27a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.media.MediaPlayer.OnCompletionListener; 28a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.net.Uri; 29a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.os.IBinder; 30a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.os.RemoteCallbackList; 31a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.os.RemoteException; 32a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.preference.PreferenceManager; 33d146874d7341bc9602c93719582b4209e7b81f01Jean-Michel Triviimport android.speech.tts.ITts.Stub; 34d146874d7341bc9602c93719582b4209e7b81f01Jean-Michel Triviimport android.speech.tts.ITtsCallback; 35d146874d7341bc9602c93719582b4209e7b81f01Jean-Michel Triviimport android.speech.tts.TextToSpeech; 36a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport android.util.Log; 37a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi 38a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Triviimport java.io.File; 39a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport java.util.ArrayList; 40a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport java.util.Arrays; 41a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport java.util.HashMap; 42d478cf09dff93015bc332f2707068f08bf603cfdJean-Michel Triviimport java.util.Locale; 43a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenimport java.util.concurrent.locks.ReentrantLock; 440a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chenimport java.util.concurrent.TimeUnit; 450a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen 46a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 47a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen/** 48a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @hide Synthesizes speech from text. This is implemented as a service so that 49a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * other applications can call the TTS without needing to bundle the TTS 50a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * in the build. 51a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 52a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 53a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chenpublic class TtsService extends Service implements OnCompletionListener { 54a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 5578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private static class SpeechItem { 56741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen public static final int TEXT = 0; 574bca97ecaf04c50d5ed49920d119f9ffa6c29402Charles Chen public static final int EARCON = 1; 584bca97ecaf04c50d5ed49920d119f9ffa6c29402Charles Chen public static final int SILENCE = 2; 594bca97ecaf04c50d5ed49920d119f9ffa6c29402Charles Chen public static final int TEXT_TO_FILE = 3; 60b02ced7e454ae195c53993fe310ee38de6452dedCharles Chen public String mText = ""; 6178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public ArrayList<String> mParams = null; 62741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen public int mType = TEXT; 6378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public long mDuration = 0; 64ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen public String mFilename = null; 6578c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen public String mCallingApp = ""; 6678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 67a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public SpeechItem(String source, String text, ArrayList<String> params, int itemType) { 6878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mText = text; 6978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mParams = params; 7078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mType = itemType; 7178c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen mCallingApp = source; 7278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 73a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 743ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen public SpeechItem(String source, long silenceTime, ArrayList<String> params) { 7578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mDuration = silenceTime; 763ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen mParams = params; 77b02ced7e454ae195c53993fe310ee38de6452dedCharles Chen mType = SILENCE; 7878c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen mCallingApp = source; 7978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 80ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen 81edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen public SpeechItem(String source, String text, ArrayList<String> params, 82edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen int itemType, String filename) { 83ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen mText = text; 84ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen mParams = params; 85ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen mType = itemType; 86ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen mFilename = filename; 8778c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen mCallingApp = source; 88ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 89ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen 90a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 91a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 9278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 9378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Contains the information needed to access a sound resource; the name of 9478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * the package that contains the resource and the resID of the resource 9578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * within that package. 9678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 9778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private static class SoundResource { 9878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public String mSourcePackageName = null; 9978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public int mResId = -1; 10078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public String mFilename = null; 10178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 10278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public SoundResource(String packageName, int id) { 10378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mSourcePackageName = packageName; 10478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mResId = id; 10578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mFilename = null; 10678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 107a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 10878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public SoundResource(String file) { 10978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mSourcePackageName = null; 11078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mResId = -1; 11178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mFilename = file; 11278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 11378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 1140dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen // If the speech queue is locked for more than 5 seconds, something has gone 1150dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen // very wrong with processSpeechQueue. 1160dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen private static final int SPEECHQUEUELOCK_TIMEOUT = 5000; 1171aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen private static final int MAX_SPEECH_ITEM_CHAR_LENGTH = 4000; 11803454f8932b7fd79471ae6f95f2de7b75b0ded8aCharles Chen private static final int MAX_FILENAME_LENGTH = 250; 1199440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi // TODO use the TTS stream type when available 1209440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi private static final int DEFAULT_STREAM_TYPE = AudioManager.STREAM_MUSIC; 1211aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen 12252ae06521a8d4c48757b126cff233f037d0a16baCharles Chen private static final String ACTION = "android.intent.action.START_TTS_SERVICE"; 12378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private static final String CATEGORY = "android.intent.category.TTS"; 12478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private static final String PKGNAME = "android.tts"; 125b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi protected static final String SERVICE_TAG = "TtsService"; 126a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 127edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen private final RemoteCallbackList<ITtsCallback> mCallbacks 128edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen = new RemoteCallbackList<ITtsCallback>(); 129edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen 130edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen private HashMap<String, ITtsCallback> mCallbacksMap; 131a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 13278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private Boolean mIsSpeaking; 13378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private ArrayList<SpeechItem> mSpeechQueue; 13478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private HashMap<String, SoundResource> mEarcons; 13578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private HashMap<String, SoundResource> mUtterances; 13678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private MediaPlayer mPlayer; 1373ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen private SpeechItem mCurrentSpeechItem; 138c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen private HashMap<SpeechItem, Boolean> mKillList; // Used to ensure that in-flight synth calls 139c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen // are killed when stop is used. 14078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private TtsService mSelf; 141a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 142605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi private ContentResolver mResolver; 143a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 144a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi // lock for the speech queue (mSpeechQueue) and the current speech item (mCurrentSpeechItem) 14578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private final ReentrantLock speechQueueLock = new ReentrantLock(); 14678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private final ReentrantLock synthesizerLock = new ReentrantLock(); 147a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 148a73d5cd05550310c3e6cedf0759210c255f4a6aaJean-Michel Trivi private static SynthProxy sNativeSynth = null; 14978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi @Override 15078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public void onCreate() { 15178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi super.onCreate(); 152ab6ed2c2b9cebd97cb501da58d386f59e4a99103Jean-Michel Trivi Log.v("TtsService", "TtsService.onCreate()"); 153a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 154605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi mResolver = getContentResolver(); 155a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 156b3c5a8785bc643843117752d37769a1edfe9a9e2Jean-Michel Trivi String soLibPath = "/system/lib/libttspico.so"; 157a73d5cd05550310c3e6cedf0759210c255f4a6aaJean-Michel Trivi if (sNativeSynth == null) { 158a73d5cd05550310c3e6cedf0759210c255f4a6aaJean-Michel Trivi sNativeSynth = new SynthProxy(soLibPath); 159a73d5cd05550310c3e6cedf0759210c255f4a6aaJean-Michel Trivi } 160a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 16178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mSelf = this; 16278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mIsSpeaking = false; 163a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 16478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mEarcons = new HashMap<String, SoundResource>(); 16578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mUtterances = new HashMap<String, SoundResource>(); 16678c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen mCallbacksMap = new HashMap<String, android.speech.tts.ITtsCallback>(); 167a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 16878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mSpeechQueue = new ArrayList<SpeechItem>(); 16978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mPlayer = null; 1703ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen mCurrentSpeechItem = null; 171c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen mKillList = new HashMap<SpeechItem, Boolean>(); 172a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 173605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi setDefaultSettings(); 174a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 175a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 17678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi @Override 17778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public void onDestroy() { 17878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi super.onDestroy(); 17969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi 180a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi killAllUtterances(); 18169e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi 18278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Don't hog the media player 18378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi cleanUpPlayer(); 184a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 18569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi if (sNativeSynth != null) { 18669e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi sNativeSynth.shutdown(); 18769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 188cee3bd4d68bf40d36fee3f0f5ce03f9edae87b51Jean-Michel Trivi sNativeSynth = null; 189a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 19078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Unregister all callbacks. 19178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mCallbacks.kill(); 19209f8db7ad3963f5fa15f2b99880b2f70e89c30aeJean-Michel Trivi 193b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "onDestroy() completed"); 194a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 195a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 196605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi 197605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi private void setDefaultSettings() { 198a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen setLanguage("", this.getDefaultLanguage(), getDefaultCountry(), getDefaultLocVariant()); 199605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi 200605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi // speech rate 201a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen setSpeechRate("", getDefaultRate()); 202605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi } 203605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi 204605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi 205605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi private boolean isDefaultEnforced() { 206605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi return (android.provider.Settings.Secure.getInt(mResolver, 207d146874d7341bc9602c93719582b4209e7b81f01Jean-Michel Trivi android.provider.Settings.Secure.TTS_USE_DEFAULTS, 208ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi TextToSpeech.Engine.USE_DEFAULTS) 209605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi == 1 ); 210605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi } 211605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi 212605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi 213605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi private int getDefaultRate() { 214605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi return android.provider.Settings.Secure.getInt(mResolver, 215d146874d7341bc9602c93719582b4209e7b81f01Jean-Michel Trivi android.provider.Settings.Secure.TTS_DEFAULT_RATE, 216ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi TextToSpeech.Engine.DEFAULT_RATE); 217605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi } 218605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi 219605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi 2206a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi private String getDefaultLanguage() { 2216a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi String defaultLang = android.provider.Settings.Secure.getString(mResolver, 2226a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi android.provider.Settings.Secure.TTS_DEFAULT_LANG); 2236a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi if (defaultLang == null) { 224d478cf09dff93015bc332f2707068f08bf603cfdJean-Michel Trivi // no setting found, use the current Locale to determine the default language 225d478cf09dff93015bc332f2707068f08bf603cfdJean-Michel Trivi return Locale.getDefault().getISO3Language(); 2266a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } else { 2276a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi return defaultLang; 2286a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } 2296a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } 2306a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi 2316a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi 2326a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi private String getDefaultCountry() { 2336a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi String defaultCountry = android.provider.Settings.Secure.getString(mResolver, 2346a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi android.provider.Settings.Secure.TTS_DEFAULT_COUNTRY); 2356a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi if (defaultCountry == null) { 236d478cf09dff93015bc332f2707068f08bf603cfdJean-Michel Trivi // no setting found, use the current Locale to determine the default country 237d478cf09dff93015bc332f2707068f08bf603cfdJean-Michel Trivi return Locale.getDefault().getISO3Country(); 2386a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } else { 2396a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi return defaultCountry; 2406a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } 2416a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } 2426a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi 2436a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi 2446a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi private String getDefaultLocVariant() { 2456a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi String defaultVar = android.provider.Settings.Secure.getString(mResolver, 2466a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi android.provider.Settings.Secure.TTS_DEFAULT_VARIANT); 2476a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi if (defaultVar == null) { 248d478cf09dff93015bc332f2707068f08bf603cfdJean-Michel Trivi // no setting found, use the current Locale to determine the default variant 249d478cf09dff93015bc332f2707068f08bf603cfdJean-Michel Trivi return Locale.getDefault().getVariant(); 2506a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } else { 2516a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi return defaultVar; 2526a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } 2536a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi } 2546a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi 2556a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi 256a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private int setSpeechRate(String callingApp, int rate) { 25769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi int res = TextToSpeech.ERROR; 25869e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 25969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi if (isDefaultEnforced()) { 26069e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = sNativeSynth.setSpeechRate(getDefaultRate()); 26169e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } else { 26269e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = sNativeSynth.setSpeechRate(rate); 26369e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 26469e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (NullPointerException e) { 26569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi // synth will become null during onDestroy() 26669e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = TextToSpeech.ERROR; 267a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 26869e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi return res; 269a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 270a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 2712ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi 272a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private int setPitch(String callingApp, int pitch) { 27369e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi int res = TextToSpeech.ERROR; 27469e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 27569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = sNativeSynth.setPitch(pitch); 27669e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (NullPointerException e) { 27769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi // synth will become null during onDestroy() 27869e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = TextToSpeech.ERROR; 27969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 28069e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi return res; 2812ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi } 2822ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi 2832ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi 284ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi private int isLanguageAvailable(String lang, String country, String variant) { 28569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi int res = TextToSpeech.LANG_NOT_SUPPORTED; 28669e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 28769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = sNativeSynth.isLanguageAvailable(lang, country, variant); 28869e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (NullPointerException e) { 28969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi // synth will become null during onDestroy() 29069e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = TextToSpeech.LANG_NOT_SUPPORTED; 29169e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 29269e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi return res; 293ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi } 294ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi 295ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi 296ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi private String[] getLanguage() { 29769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 29869e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi return sNativeSynth.getLanguage(); 29969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (Exception e) { 30069e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi return null; 30169e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 302ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi } 303ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi 304ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi 305a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private int setLanguage(String callingApp, String lang, String country, String variant) { 306b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "TtsService.setLanguage(" + lang + ", " + country + ", " + variant + ")"); 30769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi int res = TextToSpeech.ERROR; 30869e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 30969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi if (isDefaultEnforced()) { 31069e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = sNativeSynth.setLanguage(getDefaultLanguage(), getDefaultCountry(), 31169e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi getDefaultLocVariant()); 31269e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } else { 31369e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = sNativeSynth.setLanguage(lang, country, variant); 31469e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 31569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (NullPointerException e) { 31669e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi // synth will become null during onDestroy() 31769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi res = TextToSpeech.ERROR; 318605a66bd56f01713f240ee8bc1435512500498e0Jean-Michel Trivi } 31969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi return res; 320a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 321a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 3226a0e293c84de02e819c1b402141bd3f7684ea164Jean-Michel Trivi 323a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen /** 324a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * Adds a sound resource to the TTS. 325a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 326a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param text 327a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The text that should be associated with the sound resource 328a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param packageName 329a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The name of the package which has the sound resource 330a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param resId 331a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The resource ID of the sound within its package 332a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 333a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private void addSpeech(String callingApp, String text, String packageName, int resId) { 33478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mUtterances.put(text, new SoundResource(packageName, resId)); 335a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 336a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 337a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen /** 338a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * Adds a sound resource to the TTS. 339a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 340a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param text 341a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The text that should be associated with the sound resource 342a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param filename 34378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The filename of the sound resource. This must be a complete 34478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * path like: (/sdcard/mysounds/mysoundbite.mp3). 345a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 346a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private void addSpeech(String callingApp, String text, String filename) { 34778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mUtterances.put(text, new SoundResource(filename)); 348a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 349a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 350a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen /** 351a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * Adds a sound resource to the TTS as an earcon. 352a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 353a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param earcon 354a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The text that should be associated with the sound resource 355a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param packageName 356a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The name of the package which has the sound resource 357a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param resId 358a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The resource ID of the sound within its package 359a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 360a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private void addEarcon(String callingApp, String earcon, String packageName, int resId) { 36178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mEarcons.put(earcon, new SoundResource(packageName, resId)); 362a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 363a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 364a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen /** 365a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * Adds a sound resource to the TTS as an earcon. 366a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 367a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param earcon 368a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The text that should be associated with the sound resource 369a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param filename 37078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The filename of the sound resource. This must be a complete 37178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * path like: (/sdcard/mysounds/mysoundbite.mp3). 372a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 373a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private void addEarcon(String callingApp, String earcon, String filename) { 37478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mEarcons.put(earcon, new SoundResource(filename)); 375a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 376a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 377a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen /** 37878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Speaks the given text using the specified queueing mode and parameters. 379a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 38078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param text 38178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The text that should be spoken 38278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param queueMode 383d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances), 384d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_ADD for queued 38578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param params 38678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * An ArrayList of parameters. This is not implemented for all 38778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * engines. 388a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 389a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private int speak(String callingApp, String text, int queueMode, ArrayList<String> params) { 390b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "TTS service received " + text); 391ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi if (queueMode == TextToSpeech.QUEUE_FLUSH) { 392a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen stop(callingApp); 3936f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } else if (queueMode == 2) { 3946f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen stopAll(callingApp); 39578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 396a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen mSpeechQueue.add(new SpeechItem(callingApp, text, params, SpeechItem.TEXT)); 397741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen if (!mIsSpeaking) { 398741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen processSpeechQueue(); 399741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen } 400ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi return TextToSpeech.SUCCESS; 401741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen } 402741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen 403741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen /** 40478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Plays the earcon using the specified queueing mode and parameters. 405a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 40678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param earcon 40778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The earcon that should be played 40878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param queueMode 409d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances), 410d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_ADD for queued 41178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param params 41278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * An ArrayList of parameters. This is not implemented for all 41378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * engines. 414a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 415a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private int playEarcon(String callingApp, String earcon, int queueMode, 41678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi ArrayList<String> params) { 417ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi if (queueMode == TextToSpeech.QUEUE_FLUSH) { 418a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen stop(callingApp); 4196f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } else if (queueMode == 2) { 4206f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen stopAll(callingApp); 42178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 422a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen mSpeechQueue.add(new SpeechItem(callingApp, earcon, params, SpeechItem.EARCON)); 42378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (!mIsSpeaking) { 42478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi processSpeechQueue(); 42578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 426ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi return TextToSpeech.SUCCESS; 42778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 42878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 42978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 4306f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen * Stops all speech output and removes any utterances still in the queue for the calling app. 43178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 432a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private int stop(String callingApp) { 433ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi int result = TextToSpeech.ERROR; 4340a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen boolean speechQueueAvailable = false; 4350a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen try{ 4360dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen speechQueueAvailable = 4370dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS); 4380a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen if (speechQueueAvailable) { 439b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.i(SERVICE_TAG, "Stopping"); 440a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen for (int i = mSpeechQueue.size() - 1; i > -1; i--){ 44178c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen if (mSpeechQueue.get(i).mCallingApp.equals(callingApp)){ 442a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen mSpeechQueue.remove(i); 443a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen } 444a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen } 4456f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if ((mCurrentSpeechItem != null) && 4466f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mCurrentSpeechItem.mCallingApp.equals(callingApp)) { 44769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 44869e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi result = sNativeSynth.stop(); 44969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (NullPointerException e1) { 45069e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi // synth will become null during onDestroy() 45169e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi result = TextToSpeech.ERROR; 45269e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 453c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen mKillList.put(mCurrentSpeechItem, true); 4546f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if (mPlayer != null) { 4556f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen try { 4566f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mPlayer.stop(); 4576f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } catch (IllegalStateException e) { 4586f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen // Do nothing, the player is already stopped. 4596f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 4600a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen } 4616f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mIsSpeaking = false; 4626f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mCurrentSpeechItem = null; 4636f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } else { 464ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi result = TextToSpeech.SUCCESS; 4650a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen } 466b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.i(SERVICE_TAG, "Stopped"); 467ab6ed2c2b9cebd97cb501da58d386f59e4a99103Jean-Michel Trivi } else { 468b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS stop(): queue locked longer than expected"); 469ab6ed2c2b9cebd97cb501da58d386f59e4a99103Jean-Michel Trivi result = TextToSpeech.ERROR; 4700a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen } 4710a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen } catch (InterruptedException e) { 472b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS stop: tryLock interrupted"); 4730a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen e.printStackTrace(); 4740a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen } finally { 4750a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen // This check is needed because finally will always run; even if the 4760a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen // method returns somewhere in the try block. 4776f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if (speechQueueAvailable) { 4786f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen speechQueueLock.unlock(); 4796f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 4806f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen return result; 4816f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 4826f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 4836f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen 4846f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen 485a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi /** 486a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi * Stops all speech output, both rendered to a file and directly spoken, and removes any 487a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi * utterances still in the queue globally. Files that were being written are deleted. 488a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi */ 489a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi @SuppressWarnings("finally") 490a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi private int killAllUtterances() { 491a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi int result = TextToSpeech.ERROR; 492a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi boolean speechQueueAvailable = false; 493a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi 494a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi try { 495a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi speechQueueAvailable = speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, 496a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi TimeUnit.MILLISECONDS); 497a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi if (speechQueueAvailable) { 498a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi // remove every single entry in the speech queue 499a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi mSpeechQueue.clear(); 500a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi 501a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi // clear the current speech item 502a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi if (mCurrentSpeechItem != null) { 50309f8db7ad3963f5fa15f2b99880b2f70e89c30aeJean-Michel Trivi result = sNativeSynth.stopSync(); 504a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi mKillList.put(mCurrentSpeechItem, true); 505a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi mIsSpeaking = false; 506a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi 507a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi // was the engine writing to a file? 508a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi if (mCurrentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) { 509a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi // delete the file that was being written 510a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi if (mCurrentSpeechItem.mFilename != null) { 511a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi File tempFile = new File(mCurrentSpeechItem.mFilename); 512b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "Leaving behind " + mCurrentSpeechItem.mFilename); 513a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi if (tempFile.exists()) { 514b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "About to delete " 515a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi + mCurrentSpeechItem.mFilename); 516a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi if (tempFile.delete()) { 517b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "file successfully deleted"); 518a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 519a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 520a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 521a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 522a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi 523a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi mCurrentSpeechItem = null; 524a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 525a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } else { 526b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS killAllUtterances(): queue locked longer than expected"); 527a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi result = TextToSpeech.ERROR; 528a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 529a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } catch (InterruptedException e) { 530b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS killAllUtterances(): tryLock interrupted"); 531a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi result = TextToSpeech.ERROR; 532a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } finally { 533a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi // This check is needed because finally will always run, even if the 534a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi // method returns somewhere in the try block. 535a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi if (speechQueueAvailable) { 536a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi speechQueueLock.unlock(); 537a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 538a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi return result; 539a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 540a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi } 541a3046b6f7f81cc16afeba9aee880c2ed643ccfbfJean-Michel Trivi 5426f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen 5436f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen /** 54469e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi * Stops all speech output and removes any utterances still in the queue globally, except 54569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi * those intended to be synthesized to file. 5466f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen */ 5476f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen private int stopAll(String callingApp) { 548ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi int result = TextToSpeech.ERROR; 5496f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen boolean speechQueueAvailable = false; 5506f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen try{ 5510dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen speechQueueAvailable = 5520dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS); 5536f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if (speechQueueAvailable) { 5546f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen for (int i = mSpeechQueue.size() - 1; i > -1; i--){ 5556f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if (mSpeechQueue.get(i).mType != SpeechItem.TEXT_TO_FILE){ 5566f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mSpeechQueue.remove(i); 5576f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 5586f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 5596f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if ((mCurrentSpeechItem != null) && 5606f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen ((mCurrentSpeechItem.mType != SpeechItem.TEXT_TO_FILE) || 5616f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mCurrentSpeechItem.mCallingApp.equals(callingApp))) { 56269e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 56369e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi result = sNativeSynth.stop(); 56469e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (NullPointerException e1) { 56569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi // synth will become null during onDestroy() 56669e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi result = TextToSpeech.ERROR; 56769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 568c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen mKillList.put(mCurrentSpeechItem, true); 5696f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if (mPlayer != null) { 5706f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen try { 5716f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mPlayer.stop(); 5726f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } catch (IllegalStateException e) { 5736f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen // Do nothing, the player is already stopped. 5746f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 5756f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 5766f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mIsSpeaking = false; 5776f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen mCurrentSpeechItem = null; 5786f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } else { 579ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi result = TextToSpeech.SUCCESS; 5806f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 581b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.i(SERVICE_TAG, "Stopped all"); 582ab6ed2c2b9cebd97cb501da58d386f59e4a99103Jean-Michel Trivi } else { 583b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS stopAll(): queue locked longer than expected"); 584ab6ed2c2b9cebd97cb501da58d386f59e4a99103Jean-Michel Trivi result = TextToSpeech.ERROR; 5856f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 5866f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } catch (InterruptedException e) { 587b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS stopAll: tryLock interrupted"); 5886f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen e.printStackTrace(); 5896f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } finally { 5906f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen // This check is needed because finally will always run; even if the 5916f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen // method returns somewhere in the try block. 5920a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen if (speechQueueAvailable) { 5930a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen speechQueueLock.unlock(); 59478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 5950a3d8744feb8ef5714b6c341ebcaa7ce326de908Charles Chen return result; 59678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 59778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 59878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 59978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public void onCompletion(MediaPlayer arg0) { 6003ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen String callingApp = mCurrentSpeechItem.mCallingApp; 6013ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen ArrayList<String> params = mCurrentSpeechItem.mParams; 6023ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen String utteranceId = ""; 6033ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen if (params != null){ 6043ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen for (int i = 0; i < params.size() - 1; i = i + 2){ 6053ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen String param = params.get(i); 606ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)){ 6073ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen utteranceId = params.get(i+1); 6083ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 6093ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 6103ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 6113ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen if (utteranceId.length() > 0){ 6123ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen dispatchUtteranceCompletedCallback(utteranceId, callingApp); 6133ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 61478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi processSpeechQueue(); 61578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 61678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 617a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private int playSilence(String callingApp, long duration, int queueMode, 61878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi ArrayList<String> params) { 619ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi if (queueMode == TextToSpeech.QUEUE_FLUSH) { 620a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen stop(callingApp); 62178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 6223ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen mSpeechQueue.add(new SpeechItem(callingApp, duration, params)); 62378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (!mIsSpeaking) { 62478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi processSpeechQueue(); 62578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 626ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi return TextToSpeech.SUCCESS; 62778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 62878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 6293ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen private void silence(final SpeechItem speechItem) { 63078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi class SilenceThread implements Runnable { 63178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public void run() { 6323ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen String utteranceId = ""; 633edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen if (speechItem.mParams != null){ 634edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){ 635edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen String param = speechItem.mParams.get(i); 636ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)){ 637edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen utteranceId = speechItem.mParams.get(i+1); 6383ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 6393ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 6403ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 64178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi try { 642edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen Thread.sleep(speechItem.mDuration); 64378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } catch (InterruptedException e) { 64478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi e.printStackTrace(); 64578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } finally { 6463ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen if (utteranceId.length() > 0){ 647edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp); 6483ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 64978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi processSpeechQueue(); 65078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 65178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 65278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 65378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi Thread slnc = (new Thread(new SilenceThread())); 65478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi slnc.setPriority(Thread.MIN_PRIORITY); 65578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi slnc.start(); 65678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 65778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 65878c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen private void speakInternalOnly(final SpeechItem speechItem) { 65978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi class SynthThread implements Runnable { 66078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public void run() { 66178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi boolean synthAvailable = false; 66278c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen String utteranceId = ""; 66378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi try { 66478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi synthAvailable = synthesizerLock.tryLock(); 66578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (!synthAvailable) { 66678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi Thread.sleep(100); 66778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi Thread synth = (new Thread(new SynthThread())); 6685e11a6ad00b062d604b30578e0fb412ae4586989Jean-Michel Trivi //synth.setPriority(Thread.MIN_PRIORITY); 66978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi synth.start(); 67078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return; 67178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 6729440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi int streamType = DEFAULT_STREAM_TYPE; 673b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen String language = ""; 674b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen String country = ""; 675b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen String variant = ""; 676b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen String speechRate = ""; 677edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen if (speechItem.mParams != null){ 678edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){ 679edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen String param = speechItem.mParams.get(i); 6809440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi if (param != null) { 681ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi if (param.equals(TextToSpeech.Engine.KEY_PARAM_RATE)) { 682b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen speechRate = speechItem.mParams.get(i+1); 683ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_LANGUAGE)){ 684edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen language = speechItem.mParams.get(i+1); 685ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_COUNTRY)){ 686edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen country = speechItem.mParams.get(i+1); 687ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_VARIANT)){ 688edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen variant = speechItem.mParams.get(i+1); 689ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)){ 690edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen utteranceId = speechItem.mParams.get(i+1); 691ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_STREAM)) { 6929440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi try { 693edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen streamType 694edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen = Integer.parseInt(speechItem.mParams.get(i + 1)); 6959440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi } catch (NumberFormatException e) { 6969440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi streamType = DEFAULT_STREAM_TYPE; 6979440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi } 698630a8de44fa0ca855c4a87d939432f831e8ed531Charles Chen } 69903454f8932b7fd79471ae6f95f2de7b75b0ded8aCharles Chen } 70003454f8932b7fd79471ae6f95f2de7b75b0ded8aCharles Chen } 701b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen } 702b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen // Only do the synthesis if it has not been killed by a subsequent utterance. 703b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen if (mKillList.get(speechItem) == null) { 70403454f8932b7fd79471ae6f95f2de7b75b0ded8aCharles Chen if (language.length() > 0){ 705a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen setLanguage("", language, country, variant); 70603454f8932b7fd79471ae6f95f2de7b75b0ded8aCharles Chen } 707b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen if (speechRate.length() > 0){ 708b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen setSpeechRate("", Integer.parseInt(speechRate)); 709b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen } 71069e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 71169e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi sNativeSynth.speak(speechItem.mText, streamType); 71269e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (NullPointerException e) { 71369e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi // synth will become null during onDestroy() 714b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, " null synth, can't speak"); 71569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 716c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen } 71778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } catch (InterruptedException e) { 718b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS speakInternalOnly(): tryLock interrupted"); 71978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi e.printStackTrace(); 72078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } finally { 72178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // This check is needed because finally will always run; 72278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // even if the 72378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // method returns somewhere in the try block. 72478c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen if (utteranceId.length() > 0){ 725edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp); 72678c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen } 7276f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if (synthAvailable) { 7286f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen synthesizerLock.unlock(); 7296f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 7307af9e196a33ac1d7fe3d5030fa42bbcaf2038020Charles Chen processSpeechQueue(); 73178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 73278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 73378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 73478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi Thread synth = (new Thread(new SynthThread())); 735ab6ed2c2b9cebd97cb501da58d386f59e4a99103Jean-Michel Trivi synth.setPriority(Thread.MAX_PRIORITY); 73678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi synth.start(); 73778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 73878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 7393ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen private void synthToFileInternalOnly(final SpeechItem speechItem) { 740ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen class SynthThread implements Runnable { 741ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen public void run() { 742ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen boolean synthAvailable = false; 7433ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen String utteranceId = ""; 744b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.i(SERVICE_TAG, "Synthesizing to " + speechItem.mFilename); 745ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen try { 746ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen synthAvailable = synthesizerLock.tryLock(); 747ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen if (!synthAvailable) { 748ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen Thread.sleep(100); 749ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen Thread synth = (new Thread(new SynthThread())); 7505e11a6ad00b062d604b30578e0fb412ae4586989Jean-Michel Trivi //synth.setPriority(Thread.MIN_PRIORITY); 751ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen synth.start(); 752ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen return; 753ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 754b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen String language = ""; 755b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen String country = ""; 756b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen String variant = ""; 757b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen String speechRate = ""; 758edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen if (speechItem.mParams != null){ 759edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen for (int i = 0; i < speechItem.mParams.size() - 1; i = i + 2){ 760edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen String param = speechItem.mParams.get(i); 761b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen if (param != null) { 762ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi if (param.equals(TextToSpeech.Engine.KEY_PARAM_RATE)) { 763b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen speechRate = speechItem.mParams.get(i+1); 764ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_LANGUAGE)){ 765edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen language = speechItem.mParams.get(i+1); 766ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_COUNTRY)){ 767edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen country = speechItem.mParams.get(i+1); 768ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_VARIANT)){ 769edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen variant = speechItem.mParams.get(i+1); 770ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi } else if (param.equals(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID)){ 771edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen utteranceId = speechItem.mParams.get(i+1); 772630a8de44fa0ca855c4a87d939432f831e8ed531Charles Chen } 773ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 774ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 775ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 776c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen // Only do the synthesis if it has not been killed by a subsequent utterance. 777c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen if (mKillList.get(speechItem) == null){ 778b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen if (language.length() > 0){ 779b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen setLanguage("", language, country, variant); 780b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen } 781b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen if (speechRate.length() > 0){ 782b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen setSpeechRate("", Integer.parseInt(speechRate)); 783b79370aad730949543bccf01b2c3d9ed64f493f5Charles Chen } 78469e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi try { 78569e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi sNativeSynth.synthesizeToFile(speechItem.mText, speechItem.mFilename); 78669e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } catch (NullPointerException e) { 78769e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi // synth will become null during onDestroy() 788b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, " null synth, can't synthesize to file"); 78969e67a3e2e863fa8828151ef3a488bfcaa504f7aJean-Michel Trivi } 790c231fd0fe7814a025aeb05796542048a51d0236bCharles Chen } 791ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } catch (InterruptedException e) { 792b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS synthToFileInternalOnly(): tryLock interrupted"); 793ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen e.printStackTrace(); 794ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } finally { 795ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen // This check is needed because finally will always run; 796ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen // even if the 797ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen // method returns somewhere in the try block. 7983ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen if (utteranceId.length() > 0){ 799edb4fc3076622393ac25fafda24e4bbe78ec44e4Charles Chen dispatchUtteranceCompletedCallback(utteranceId, speechItem.mCallingApp); 8003ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } 8016f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen if (synthAvailable) { 8026f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen synthesizerLock.unlock(); 8036f624239dc6c62ac9f18c4c8c65c2fbf1c78bdbdCharles Chen } 804ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen processSpeechQueue(); 805ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 806ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 807ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 808ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen Thread synth = (new Thread(new SynthThread())); 809ab6ed2c2b9cebd97cb501da58d386f59e4a99103Jean-Michel Trivi synth.setPriority(Thread.MAX_PRIORITY); 810ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen synth.start(); 811ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 812ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen 81378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private SoundResource getSoundResource(SpeechItem speechItem) { 81478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi SoundResource sr = null; 81578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi String text = speechItem.mText; 81678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (speechItem.mType == SpeechItem.SILENCE) { 81778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Do nothing if this is just silence 81878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } else if (speechItem.mType == SpeechItem.EARCON) { 81978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi sr = mEarcons.get(text); 82078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } else { 82178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi sr = mUtterances.get(text); 82278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 82378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return sr; 82478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 82578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 82628dbae7df43ee683ba1bf468ad9924092bb9c569Charles Chen private void broadcastTtsQueueProcessingCompleted(){ 827ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi Intent i = new Intent(TextToSpeech.ACTION_TTS_QUEUE_PROCESSING_COMPLETED); 82828dbae7df43ee683ba1bf468ad9924092bb9c569Charles Chen sendBroadcast(i); 82928dbae7df43ee683ba1bf468ad9924092bb9c569Charles Chen } 83028dbae7df43ee683ba1bf468ad9924092bb9c569Charles Chen 83178c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen 83278c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen private void dispatchUtteranceCompletedCallback(String utteranceId, String packageName) { 83378c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen ITtsCallback cb = mCallbacksMap.get(packageName); 83478c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen if (cb == null){ 83578c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen return; 83678c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen } 837b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "TTS callback: dispatch started"); 83878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Broadcast to all clients the new value. 83978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi final int N = mCallbacks.beginBroadcast(); 84078c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen try { 84178c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen cb.utteranceCompleted(utteranceId); 84278c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen } catch (RemoteException e) { 84378c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen // The RemoteCallbackList will take care of removing 84478c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen // the dead object for us. 84578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 84678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mCallbacks.finishBroadcast(); 847b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "TTS callback: dispatch completed to " + N); 84878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 84978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 8501aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen private SpeechItem splitCurrentTextIfNeeded(SpeechItem currentSpeechItem){ 8511aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen if (currentSpeechItem.mText.length() < MAX_SPEECH_ITEM_CHAR_LENGTH){ 8521aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen return currentSpeechItem; 8531aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen } else { 85478c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen String callingApp = currentSpeechItem.mCallingApp; 8551aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen ArrayList<SpeechItem> splitItems = new ArrayList<SpeechItem>(); 8561aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen int start = 0; 8571aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen int end = start + MAX_SPEECH_ITEM_CHAR_LENGTH - 1; 8581aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen String splitText; 8591aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen SpeechItem splitItem; 8601aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen while (end < currentSpeechItem.mText.length()){ 8611aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen splitText = currentSpeechItem.mText.substring(start, end); 862a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen splitItem = new SpeechItem(callingApp, splitText, null, SpeechItem.TEXT); 8631aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen splitItems.add(splitItem); 8641aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen start = end; 8651aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen end = start + MAX_SPEECH_ITEM_CHAR_LENGTH - 1; 8661aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen } 8671aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen splitText = currentSpeechItem.mText.substring(start); 868a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen splitItem = new SpeechItem(callingApp, splitText, null, SpeechItem.TEXT); 8691aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen splitItems.add(splitItem); 8701aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen mSpeechQueue.remove(0); 8711aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen for (int i = splitItems.size() - 1; i >= 0; i--){ 8721aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen mSpeechQueue.add(0, splitItems.get(i)); 8731aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen } 8741aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen return mSpeechQueue.get(0); 8751aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen } 8761aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen } 8771aacdcfaa9233995fe78017c2a342258a69123a4Charles Chen 87878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private void processSpeechQueue() { 87978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi boolean speechQueueAvailable = false; 88078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi try { 8810dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen speechQueueAvailable = 8820dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen speechQueueLock.tryLock(SPEECHQUEUELOCK_TIMEOUT, TimeUnit.MILLISECONDS); 88378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (!speechQueueAvailable) { 884b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "processSpeechQueue - Speech queue is unavailable."); 88578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return; 88678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 88778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (mSpeechQueue.size() < 1) { 88878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mIsSpeaking = false; 88909f8db7ad3963f5fa15f2b99880b2f70e89c30aeJean-Michel Trivi mKillList.clear(); 89028dbae7df43ee683ba1bf468ad9924092bb9c569Charles Chen broadcastTtsQueueProcessingCompleted(); 89178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return; 89278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 89378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 8943ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen mCurrentSpeechItem = mSpeechQueue.get(0); 89578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mIsSpeaking = true; 8963ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen SoundResource sr = getSoundResource(mCurrentSpeechItem); 89778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Synth speech as needed - synthesizer should call 89878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // processSpeechQueue to continue running the queue 899b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.v(SERVICE_TAG, "TTS processing: " + mCurrentSpeechItem.mText); 90078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (sr == null) { 9013ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen if (mCurrentSpeechItem.mType == SpeechItem.TEXT) { 9023ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen mCurrentSpeechItem = splitCurrentTextIfNeeded(mCurrentSpeechItem); 9033ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen speakInternalOnly(mCurrentSpeechItem); 9043ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen } else if (mCurrentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) { 9053ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen synthToFileInternalOnly(mCurrentSpeechItem); 90678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } else { 90778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // This is either silence or an earcon that was missing 9083ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen silence(mCurrentSpeechItem); 90978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 91078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } else { 91178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi cleanUpPlayer(); 91278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (sr.mSourcePackageName == PKGNAME) { 91378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Utterance is part of the TTS library 91478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mPlayer = MediaPlayer.create(this, sr.mResId); 91578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } else if (sr.mSourcePackageName != null) { 91678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Utterance is part of the app calling the library 91778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi Context ctx; 91878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi try { 9199440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi ctx = this.createPackageContext(sr.mSourcePackageName, 0); 92078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } catch (NameNotFoundException e) { 92178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi e.printStackTrace(); 92278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mSpeechQueue.remove(0); // Remove it from the queue and 92378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // move on 92478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mIsSpeaking = false; 92578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return; 92678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 92778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mPlayer = MediaPlayer.create(ctx, sr.mResId); 92878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } else { 92978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Utterance is coming from a file 93078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mPlayer = MediaPlayer.create(this, Uri.parse(sr.mFilename)); 93178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 93278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 93378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // Check if Media Server is dead; if it is, clear the queue and 93478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // give up for now - hopefully, it will recover itself. 93578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (mPlayer == null) { 93678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mSpeechQueue.clear(); 93778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mIsSpeaking = false; 93878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return; 93978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 94078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mPlayer.setOnCompletionListener(this); 94178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi try { 9423ab2076d65b86a69f6c5de220082c2fbace575e2Charles Chen mPlayer.setAudioStreamType(getStreamTypeFromParams(mCurrentSpeechItem.mParams)); 94378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mPlayer.start(); 94478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } catch (IllegalStateException e) { 94578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mSpeechQueue.clear(); 94678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mIsSpeaking = false; 94778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi cleanUpPlayer(); 94878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return; 94978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 95078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 95178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (mSpeechQueue.size() > 0) { 95278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mSpeechQueue.remove(0); 95378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 9540dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen } catch (InterruptedException e) { 955b00941804890858ddc3b680c7a8e171c7dfdfb5fJean-Michel Trivi Log.e(SERVICE_TAG, "TTS processSpeechQueue: tryLock interrupted"); 9560dbc6a44bb76631911552bc5b356391dac6f38a4Charles Chen e.printStackTrace(); 95778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } finally { 95878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // This check is needed because finally will always run; even if the 95978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi // method returns somewhere in the try block. 96078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (speechQueueAvailable) { 96178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi speechQueueLock.unlock(); 96278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 96378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 96478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 96578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 9669440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi private int getStreamTypeFromParams(ArrayList<String> paramList) { 9679440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi int streamType = DEFAULT_STREAM_TYPE; 9689440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi if (paramList == null) { 9699440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi return streamType; 9709440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi } 9719440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi for (int i = 0; i < paramList.size() - 1; i = i + 2) { 9729440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi String param = paramList.get(i); 973ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi if ((param != null) && (param.equals(TextToSpeech.Engine.KEY_PARAM_STREAM))) { 9749440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi try { 9759440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi streamType = Integer.parseInt(paramList.get(i + 1)); 9769440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi } catch (NumberFormatException e) { 9779440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi streamType = DEFAULT_STREAM_TYPE; 9789440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi } 9799440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi } 9809440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi } 9819440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi return streamType; 9829440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi } 9839440bce8553a82e420e06ded3fcccc6971d1ff79Jean-Michel Trivi 98478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi private void cleanUpPlayer() { 98578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (mPlayer != null) { 98678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mPlayer.release(); 98778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mPlayer = null; 98878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 989a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 990a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 991a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen /** 992741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen * Synthesizes the given text to a file using the specified parameters. 993a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * 994a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param text 995a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * The String of text that should be synthesized 996a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param params 99778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * An ArrayList of parameters. The first element of this array 99878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * controls the type of voice to use. 999a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @param filename 100078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The string that gives the full output filename; it should be 100178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * something like "/sdcard/myappsounds/mysound.wav". 1002a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen * @return A boolean that indicates if the synthesis succeeded 1003a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen */ 1004a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen private boolean synthesizeToFile(String callingApp, String text, ArrayList<String> params, 1005ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen String filename) { 1006ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen // Don't allow a filename that is too long 1007ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen if (filename.length() > MAX_FILENAME_LENGTH) { 1008ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen return false; 100978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 1010ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen // Don't allow anything longer than the max text length; since this 1011ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen // is synthing to a file, don't even bother splitting it. 1012ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen if (text.length() >= MAX_SPEECH_ITEM_CHAR_LENGTH){ 1013ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen return false; 1014ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen } 1015a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen mSpeechQueue.add(new SpeechItem(callingApp, text, params, SpeechItem.TEXT_TO_FILE, filename)); 1016ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen if (!mIsSpeaking) { 1017ebb814bbaeacbdc04faa5683f25b12d40609548cCharles Chen processSpeechQueue(); 101878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 101978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return true; 102078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 102178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 102278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi @Override 102378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public IBinder onBind(Intent intent) { 102478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (ACTION.equals(intent.getAction())) { 102578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi for (String category : intent.getCategories()) { 102678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (category.equals(CATEGORY)) { 102778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return mBinder; 102878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 102978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 103078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 103178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return null; 1032a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen } 103378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 1034f85aa5a4d4e6f1ef7e07638568e27d709b8085c6Charles Chen private final android.speech.tts.ITts.Stub mBinder = new Stub() { 103578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 103678c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen public int registerCallback(String packageName, ITtsCallback cb) { 103778c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen if (cb != null) { 103878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mCallbacks.register(cb); 103978c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen mCallbacksMap.put(packageName, cb); 1040ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi return TextToSpeech.SUCCESS; 104178c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen } 1042ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi return TextToSpeech.ERROR; 104378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 104478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 104578c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen public int unregisterCallback(String packageName, ITtsCallback cb) { 104678c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen if (cb != null) { 104778c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen mCallbacksMap.remove(packageName); 104878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi mCallbacks.unregister(cb); 1049ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi return TextToSpeech.SUCCESS; 105078c9d0d2c5eb4d5687ae7cbe41155159329ad68fCharles Chen } 1051ed06578eddde07abe325fa4c92910bb7246cd49fJean-Michel Trivi return TextToSpeech.ERROR; 105278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 105378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 105478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 105578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Speaks the given text using the specified queueing mode and 105678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * parameters. 105778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 105878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param text 105978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The text that should be spoken 106078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param queueMode 1061d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances) 1062d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_ADD for queued 106378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param params 106478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * An ArrayList of parameters. The first element of this 106578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * array controls the type of voice to use. 106678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1067a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public int speak(String callingApp, String text, int queueMode, String[] params) { 106878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi ArrayList<String> speakingParams = new ArrayList<String>(); 106978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (params != null) { 107078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi speakingParams = new ArrayList<String>(Arrays.asList(params)); 107178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 1072a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen return mSelf.speak(callingApp, text, queueMode, speakingParams); 107378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 107478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 107578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 107678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Plays the earcon using the specified queueing mode and parameters. 107778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 107878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param earcon 107978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The earcon that should be played 108078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param queueMode 1081d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances) 1082d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_ADD for queued 108378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param params 108478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * An ArrayList of parameters. 108578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1086a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public int playEarcon(String callingApp, String earcon, int queueMode, String[] params) { 108778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi ArrayList<String> speakingParams = new ArrayList<String>(); 108878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (params != null) { 108978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi speakingParams = new ArrayList<String>(Arrays.asList(params)); 109078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 1091a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen return mSelf.playEarcon(callingApp, earcon, queueMode, speakingParams); 109278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 109378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 109478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 109578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Plays the silence using the specified queueing mode and parameters. 109678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 109778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param duration 109878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The duration of the silence that should be played 109978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param queueMode 1100d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_FLUSH for no queue (interrupts all previous utterances) 1101d48ca22b9fcea38b112aedb4126f3d030594af47Jean-Michel Trivi * TextToSpeech.TTS_QUEUE_ADD for queued 110278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param params 110378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * An ArrayList of parameters. 110478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1105a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public int playSilence(String callingApp, long duration, int queueMode, String[] params) { 110678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi ArrayList<String> speakingParams = new ArrayList<String>(); 110778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (params != null) { 110878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi speakingParams = new ArrayList<String>(Arrays.asList(params)); 110978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 1110a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen return mSelf.playSilence(callingApp, duration, queueMode, speakingParams); 111178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 111278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 111378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 111478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Stops all speech output and removes any utterances still in the 111578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * queue. 111678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1117a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public int stop(String callingApp) { 1118a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen return mSelf.stop(callingApp); 111978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 112078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 112178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 112278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Returns whether or not the TTS is speaking. 112378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 112478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @return Boolean to indicate whether or not the TTS is speaking 112578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 112678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi public boolean isSpeaking() { 112778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi return (mSelf.mIsSpeaking && (mSpeechQueue.size() < 1)); 112878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 112978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 113078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 113178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Adds a sound resource to the TTS. 113278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 113378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param text 113478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The text that should be associated with the sound resource 113578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param packageName 113678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The name of the package which has the sound resource 113778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param resId 113878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The resource ID of the sound within its package 113978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1140a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public void addSpeech(String callingApp, String text, String packageName, int resId) { 1141a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen mSelf.addSpeech(callingApp, text, packageName, resId); 114278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 114378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 114478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 114578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Adds a sound resource to the TTS. 114678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 114778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param text 114878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The text that should be associated with the sound resource 114978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param filename 115078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The filename of the sound resource. This must be a 115178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * complete path like: (/sdcard/mysounds/mysoundbite.mp3). 115278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1153a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public void addSpeechFile(String callingApp, String text, String filename) { 1154a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen mSelf.addSpeech(callingApp, text, filename); 115578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 115678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 115778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 115878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Adds a sound resource to the TTS as an earcon. 115978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 116078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param earcon 116178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The text that should be associated with the sound resource 116278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param packageName 116378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The name of the package which has the sound resource 116478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param resId 116578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The resource ID of the sound within its package 116678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1167a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public void addEarcon(String callingApp, String earcon, String packageName, int resId) { 1168a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen mSelf.addEarcon(callingApp, earcon, packageName, resId); 116978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 117078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 117178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 117278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Adds a sound resource to the TTS as an earcon. 117378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 117478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param earcon 117578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The text that should be associated with the sound resource 117678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param filename 117778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The filename of the sound resource. This must be a 117878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * complete path like: (/sdcard/mysounds/mysoundbite.mp3). 117978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1180a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public void addEarconFile(String callingApp, String earcon, String filename) { 1181a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen mSelf.addEarcon(callingApp, earcon, filename); 118278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 118378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 118478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 118578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * Sets the speech rate for the TTS. Note that this will only have an 118678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * effect on synthesized speech; it will not affect pre-recorded speech. 118778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 118878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param speechRate 118978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The speech rate that should be used 119078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1191a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public int setSpeechRate(String callingApp, int speechRate) { 1192a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen return mSelf.setSpeechRate(callingApp, speechRate); 119378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 119478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 119578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 11962ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi * Sets the pitch for the TTS. Note that this will only have an 11972ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi * effect on synthesized speech; it will not affect pre-recorded speech. 11982ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi * 11992ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi * @param pitch 12002ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi * The pitch that should be used for the synthesized voice 12012ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi */ 1202a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public int setPitch(String callingApp, int pitch) { 1203a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen return mSelf.setPitch(callingApp, pitch); 12042ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi } 12052ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi 12062ea5349583de4a505501530d04133524bb6d5d38Jean-Michel Trivi /** 1207ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * Returns the level of support for the specified language. 1208ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * 1209ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * @param lang the three letter ISO language code. 1210ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * @param country the three letter ISO country code. 1211ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * @param variant the variant code associated with the country and language pair. 1212ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * @return one of TTS_LANG_NOT_SUPPORTED, TTS_LANG_MISSING_DATA, TTS_LANG_AVAILABLE, 1213ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * TTS_LANG_COUNTRY_AVAILABLE, TTS_LANG_COUNTRY_VAR_AVAILABLE as defined in 1214ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * android.speech.tts.TextToSpeech. 1215ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi */ 1216ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi public int isLanguageAvailable(String lang, String country, String variant) { 1217ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi return mSelf.isLanguageAvailable(lang, country, variant); 1218ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi } 1219ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi 1220ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi /** 1221ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * Returns the currently set language / country / variant strings representing the 1222ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * language used by the TTS engine. 1223ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * @return null is no language is set, or an array of 3 string containing respectively 1224ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi * the language, country and variant. 1225ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi */ 1226ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi public String[] getLanguage() { 1227ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi return mSelf.getLanguage(); 1228ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi } 1229ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi 1230ddb0a803fd353fbaf0139cc8804499bc9dce7403Jean-Michel Trivi /** 1231679d728f09eeab2f8b882e42f6e081db1ac74996Jean-Michel Trivi * Sets the speech rate for the TTS, which affects the synthesized voice. 123278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 1233679d728f09eeab2f8b882e42f6e081db1ac74996Jean-Michel Trivi * @param lang the three letter ISO language code. 1234679d728f09eeab2f8b882e42f6e081db1ac74996Jean-Michel Trivi * @param country the three letter ISO country code. 1235679d728f09eeab2f8b882e42f6e081db1ac74996Jean-Michel Trivi * @param variant the variant code associated with the country and language pair. 123678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1237a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public int setLanguage(String callingApp, String lang, String country, String variant) { 1238a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen return mSelf.setLanguage(callingApp, lang, country, variant); 123978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 124078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi 124178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi /** 1242741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen * Synthesizes the given text to a file using the specified 124378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * parameters. 124478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * 124578ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param text 124678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The String of text that should be synthesized 124778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param params 124878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * An ArrayList of parameters. The first element of this 124978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * array controls the type of voice to use. 125078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @param filename 125178ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * The string that gives the full output filename; it should 125278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * be something like "/sdcard/myappsounds/mysound.wav". 125378ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi * @return A boolean that indicates if the synthesis succeeded 125478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi */ 1255a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen public boolean synthesizeToFile(String callingApp, String text, String[] params, 125678ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi String filename) { 125778ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi ArrayList<String> speakingParams = new ArrayList<String>(); 125878ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi if (params != null) { 125978ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi speakingParams = new ArrayList<String>(Arrays.asList(params)); 126078ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 1261a9c5e4bf2639f8f09be8bace4230613b7b689f0eCharles Chen return mSelf.synthesizeToFile(callingApp, text, speakingParams, filename); 126278ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi } 1263741c25b164d132ddc6ef662ddf854ebedcd0e389Charles Chen 126478ebbabfe18f2c6fb4825e4bdbb1613e0901f0f3Jean-Michel Trivi }; 1265a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen 1266a042a740d37453a1974147ebe6ee206bbd85f17dCharles Chen} 1267