Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 1 | /* |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 2 | * Copyright (C) 2009 The Android Open Source Project |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| 5 | * use this file except in compliance with the License. You may obtain a copy of |
| 6 | * the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 12 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 13 | * License for the specific language governing permissions and limitations under |
| 14 | * the License. |
| 15 | */ |
Jean-Michel Trivi | 21a6a6d | 2009-06-08 15:21:46 -0700 | [diff] [blame] | 16 | package android.speech.tts; |
| 17 | |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 18 | import android.annotation.SdkConstant; |
| 19 | import android.annotation.SdkConstant.SdkConstantType; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 20 | import android.content.ComponentName; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 21 | import android.content.ContentResolver; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 22 | import android.content.Context; |
| 23 | import android.content.Intent; |
| 24 | import android.content.ServiceConnection; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 25 | import android.content.pm.PackageManager; |
| 26 | import android.content.pm.ResolveInfo; |
| 27 | import android.content.pm.ServiceInfo; |
Jean-Michel Trivi | a981013 | 2009-07-10 12:08:59 -0700 | [diff] [blame] | 28 | import android.media.AudioManager; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 29 | import android.net.Uri; |
| 30 | import android.os.Bundle; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 31 | import android.os.IBinder; |
| 32 | import android.os.RemoteException; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 33 | import android.provider.Settings; |
| 34 | import android.text.TextUtils; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 35 | import android.util.Log; |
| 36 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 37 | import java.util.ArrayList; |
| 38 | import java.util.Collections; |
Jean-Michel Trivi | a8518c1 | 2009-06-10 17:33:34 -0700 | [diff] [blame] | 39 | import java.util.HashMap; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 40 | import java.util.List; |
Jean-Michel Trivi | 679d728 | 2009-06-16 15:36:28 -0700 | [diff] [blame] | 41 | import java.util.Locale; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 42 | import java.util.Map; |
Jean-Michel Trivi | a8518c1 | 2009-06-10 17:33:34 -0700 | [diff] [blame] | 43 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 44 | /** |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 45 | * |
Jean-Michel Trivi | 62788e9 | 2009-07-02 16:29:30 -0700 | [diff] [blame] | 46 | * Synthesizes speech from text for immediate playback or to create a sound file. |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 47 | * <p>A TextToSpeech instance can only be used to synthesize text once it has completed its |
| 48 | * initialization. Implement the {@link TextToSpeech.OnInitListener} to be |
| 49 | * notified of the completion of the initialization.<br> |
| 50 | * When you are done using the TextToSpeech instance, call the {@link #shutdown()} method |
| 51 | * to release the native resources used by the TextToSpeech engine. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 52 | * |
| 53 | */ |
Jean-Michel Trivi | a8518c1 | 2009-06-10 17:33:34 -0700 | [diff] [blame] | 54 | public class TextToSpeech { |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 55 | |
Bjorn Bringert | 2cad2cc | 2011-03-08 11:53:12 +0000 | [diff] [blame] | 56 | private static final String TAG = "TextToSpeech"; |
| 57 | |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 58 | /** |
| 59 | * Denotes a successful operation. |
| 60 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 61 | public static final int SUCCESS = 0; |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 62 | /** |
| 63 | * Denotes a generic operation failure. |
| 64 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 65 | public static final int ERROR = -1; |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 66 | |
Jean-Michel Trivi | 679d728 | 2009-06-16 15:36:28 -0700 | [diff] [blame] | 67 | /** |
| 68 | * Queue mode where all entries in the playback queue (media to be played |
| 69 | * and text to be synthesized) are dropped and replaced by the new entry. |
| 70 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 71 | public static final int QUEUE_FLUSH = 0; |
Jean-Michel Trivi | 679d728 | 2009-06-16 15:36:28 -0700 | [diff] [blame] | 72 | /** |
| 73 | * Queue mode where the new entry is added at the end of the playback queue. |
| 74 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 75 | public static final int QUEUE_ADD = 1; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 76 | |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 77 | /** |
Jean-Michel Trivi | 9f5eadd | 2009-08-14 15:44:31 -0700 | [diff] [blame] | 78 | * Denotes the language is available exactly as specified by the locale. |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 79 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 80 | public static final int LANG_COUNTRY_VAR_AVAILABLE = 2; |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 81 | |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 82 | /** |
| 83 | * Denotes the language is available for the language and country specified |
| 84 | * by the locale, but not the variant. |
| 85 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 86 | public static final int LANG_COUNTRY_AVAILABLE = 1; |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 87 | |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 88 | /** |
| 89 | * Denotes the language is available for the language by the locale, |
| 90 | * but not the country and variant. |
| 91 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 92 | public static final int LANG_AVAILABLE = 0; |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 93 | |
| 94 | /** |
| 95 | * Denotes the language data is missing. |
| 96 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 97 | public static final int LANG_MISSING_DATA = -1; |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 98 | |
| 99 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 100 | * Denotes the language is not supported. |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 101 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 102 | public static final int LANG_NOT_SUPPORTED = -2; |
| 103 | |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 104 | /** |
| 105 | * Broadcast Action: The TextToSpeech synthesizer has completed processing |
| 106 | * of all the text in the speech queue. |
| 107 | */ |
| 108 | @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) |
| 109 | public static final String ACTION_TTS_QUEUE_PROCESSING_COMPLETED = |
| 110 | "android.speech.tts.TTS_QUEUE_PROCESSING_COMPLETED"; |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 111 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 112 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 113 | * Interface definition of a callback to be invoked indicating the completion of the |
| 114 | * TextToSpeech engine initialization. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 115 | */ |
| 116 | public interface OnInitListener { |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 117 | /** |
| 118 | * Called to signal the completion of the TextToSpeech engine initialization. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 119 | * |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 120 | * @param status {@link TextToSpeech#SUCCESS} or {@link TextToSpeech#ERROR}. |
| 121 | */ |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 122 | public void onInit(int status); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 123 | } |
| 124 | |
| 125 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 126 | * Listener that will be called when the TTS service has |
| 127 | * completed synthesizing an utterance. This is only called if the utterance |
| 128 | * has an utterance ID (see {@link TextToSpeech.Engine#KEY_PARAM_UTTERANCE_ID}). |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 129 | */ |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 130 | public interface OnUtteranceCompletedListener { |
| 131 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 132 | * Called when an utterance has been synthesized. |
| 133 | * |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 134 | * @param utteranceId the identifier of the utterance. |
Charles Chen | 60dd360 | 2010-01-07 18:56:24 -0800 | [diff] [blame] | 135 | */ |
| 136 | public void onUtteranceCompleted(String utteranceId); |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 137 | } |
| 138 | |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 139 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 140 | * Constants and parameter names for controlling text-to-speech. |
Jean-Michel Trivi | d146874 | 2009-06-18 14:41:41 -0700 | [diff] [blame] | 141 | */ |
| 142 | public class Engine { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 143 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 144 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 145 | * Default speech rate. |
| 146 | * @hide |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 147 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 148 | public static final int DEFAULT_RATE = 100; |
| 149 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 150 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 151 | * Default pitch. |
| 152 | * @hide |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 153 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 154 | public static final int DEFAULT_PITCH = 100; |
| 155 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 156 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 157 | * Default volume. |
| 158 | * @hide |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 159 | */ |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 160 | public static final float DEFAULT_VOLUME = 1.0f; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 161 | |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 162 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 163 | * Default pan (centered). |
| 164 | * @hide |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 165 | */ |
| 166 | public static final float DEFAULT_PAN = 0.0f; |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 167 | |
| 168 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 169 | * Default value for {@link Settings.Secure#TTS_USE_DEFAULTS}. |
| 170 | * @hide |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 171 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 172 | public static final int USE_DEFAULTS = 0; // false |
Jean-Michel Trivi | d146874 | 2009-06-18 14:41:41 -0700 | [diff] [blame] | 173 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 174 | /** |
| 175 | * Package name of the default TTS engine. |
| 176 | * |
| 177 | * TODO: This should come from a system property |
| 178 | * |
| 179 | * @hide |
| 180 | */ |
| 181 | public static final String DEFAULT_ENGINE = "com.svox.pico"; |
| 182 | |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 183 | /** |
| 184 | * Default audio stream used when playing synthesized speech. |
| 185 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 186 | public static final int DEFAULT_STREAM = AudioManager.STREAM_MUSIC; |
Jean-Michel Trivi | a981013 | 2009-07-10 12:08:59 -0700 | [diff] [blame] | 187 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 188 | /** |
| 189 | * Indicates success when checking the installation status of the resources used by the |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 190 | * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 191 | */ |
Jean-Michel Trivi | d146874 | 2009-06-18 14:41:41 -0700 | [diff] [blame] | 192 | public static final int CHECK_VOICE_DATA_PASS = 1; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 193 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 194 | /** |
| 195 | * Indicates failure when checking the installation status of the resources used by the |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 196 | * TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 197 | */ |
Jean-Michel Trivi | d146874 | 2009-06-18 14:41:41 -0700 | [diff] [blame] | 198 | public static final int CHECK_VOICE_DATA_FAIL = 0; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 199 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 200 | /** |
| 201 | * Indicates erroneous data when checking the installation status of the resources used by |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 202 | * the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 203 | */ |
Jean-Michel Trivi | d146874 | 2009-06-18 14:41:41 -0700 | [diff] [blame] | 204 | public static final int CHECK_VOICE_DATA_BAD_DATA = -1; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 205 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 206 | /** |
| 207 | * Indicates missing resources when checking the installation status of the resources used |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 208 | * by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 209 | */ |
Jean-Michel Trivi | d146874 | 2009-06-18 14:41:41 -0700 | [diff] [blame] | 210 | public static final int CHECK_VOICE_DATA_MISSING_DATA = -2; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 211 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 212 | /** |
| 213 | * Indicates missing storage volume when checking the installation status of the resources |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 214 | * used by the TextToSpeech engine with the {@link #ACTION_CHECK_TTS_DATA} intent. |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 215 | */ |
| 216 | public static final int CHECK_VOICE_DATA_MISSING_VOLUME = -3; |
Charles Chen | 99a0fee | 2009-07-02 10:41:51 -0700 | [diff] [blame] | 217 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 218 | /** |
| 219 | * Intent for starting a TTS service. Services that handle this intent must |
| 220 | * extend {@link TextToSpeechService}. Normal applications should not use this intent |
| 221 | * directly, instead they should talk to the TTS service using the the methods in this |
| 222 | * class. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 223 | */ |
| 224 | @SdkConstant(SdkConstantType.SERVICE_ACTION) |
| 225 | public static final String INTENT_ACTION_TTS_SERVICE = |
| 226 | "android.intent.action.TTS_SERVICE"; |
| 227 | |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 228 | // intents to ask engine to install data or check its data |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 229 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 230 | * Activity Action: Triggers the platform TextToSpeech engine to |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 231 | * start the activity that installs the resource files on the device |
| 232 | * that are required for TTS to be operational. Since the installation |
| 233 | * of the data can be interrupted or declined by the user, the application |
| 234 | * shouldn't expect successful installation upon return from that intent, |
| 235 | * and if need be, should check installation status with |
| 236 | * {@link #ACTION_CHECK_TTS_DATA}. |
| 237 | */ |
Jean-Michel Trivi | 9f5eadd | 2009-08-14 15:44:31 -0700 | [diff] [blame] | 238 | @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 239 | public static final String ACTION_INSTALL_TTS_DATA = |
| 240 | "android.speech.tts.engine.INSTALL_TTS_DATA"; |
| 241 | |
| 242 | /** |
Jean-Michel Trivi | 9f5eadd | 2009-08-14 15:44:31 -0700 | [diff] [blame] | 243 | * Broadcast Action: broadcast to signal the completion of the installation of |
| 244 | * the data files used by the synthesis engine. Success or failure is indicated in the |
| 245 | * {@link #EXTRA_TTS_DATA_INSTALLED} extra. |
Jean-Michel Trivi | 77a5d39 | 2009-08-07 17:26:36 -0700 | [diff] [blame] | 246 | */ |
| 247 | @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) |
| 248 | public static final String ACTION_TTS_DATA_INSTALLED = |
| 249 | "android.speech.tts.engine.TTS_DATA_INSTALLED"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 250 | |
Jean-Michel Trivi | 77a5d39 | 2009-08-07 17:26:36 -0700 | [diff] [blame] | 251 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 252 | * Activity Action: Starts the activity from the platform TextToSpeech |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 253 | * engine to verify the proper installation and availability of the |
| 254 | * resource files on the system. Upon completion, the activity will |
| 255 | * return one of the following codes: |
| 256 | * {@link #CHECK_VOICE_DATA_PASS}, |
| 257 | * {@link #CHECK_VOICE_DATA_FAIL}, |
| 258 | * {@link #CHECK_VOICE_DATA_BAD_DATA}, |
| 259 | * {@link #CHECK_VOICE_DATA_MISSING_DATA}, or |
| 260 | * {@link #CHECK_VOICE_DATA_MISSING_VOLUME}. |
| 261 | * <p> Moreover, the data received in the activity result will contain the following |
| 262 | * fields: |
| 263 | * <ul> |
| 264 | * <li>{@link #EXTRA_VOICE_DATA_ROOT_DIRECTORY} which |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 265 | * indicates the path to the location of the resource files,</li> |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 266 | * <li>{@link #EXTRA_VOICE_DATA_FILES} which contains |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 267 | * the list of all the resource files,</li> |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 268 | * <li>and {@link #EXTRA_VOICE_DATA_FILES_INFO} which |
| 269 | * contains, for each resource file, the description of the language covered by |
| 270 | * the file in the xxx-YYY format, where xxx is the 3-letter ISO language code, |
| 271 | * and YYY is the 3-letter ISO country code.</li> |
| 272 | * </ul> |
| 273 | */ |
Jean-Michel Trivi | 9f5eadd | 2009-08-14 15:44:31 -0700 | [diff] [blame] | 274 | @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 275 | public static final String ACTION_CHECK_TTS_DATA = |
| 276 | "android.speech.tts.engine.CHECK_TTS_DATA"; |
| 277 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 278 | /** |
| 279 | * Activity intent for getting some sample text to use for demonstrating TTS. |
| 280 | * |
| 281 | * @hide This intent was used by engines written against the old API. |
| 282 | * Not sure if it should be exposed. |
| 283 | */ |
| 284 | @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION) |
| 285 | public static final String ACTION_GET_SAMPLE_TEXT = |
| 286 | "android.speech.tts.engine.GET_SAMPLE_TEXT"; |
| 287 | |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 288 | // extras for a TTS engine's check data activity |
| 289 | /** |
| 290 | * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 291 | * the TextToSpeech engine specifies the path to its resources. |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 292 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 293 | public static final String EXTRA_VOICE_DATA_ROOT_DIRECTORY = "dataRoot"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 294 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 295 | /** |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 296 | * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 297 | * the TextToSpeech engine specifies the file names of its resources under the |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 298 | * resource path. |
| 299 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 300 | public static final String EXTRA_VOICE_DATA_FILES = "dataFiles"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 301 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 302 | /** |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 303 | * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 304 | * the TextToSpeech engine specifies the locale associated with each resource file. |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 305 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 306 | public static final String EXTRA_VOICE_DATA_FILES_INFO = "dataFilesInfo"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 307 | |
Charles Chen | 76d9c3c | 2010-02-11 16:44:45 -0800 | [diff] [blame] | 308 | /** |
| 309 | * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where |
| 310 | * the TextToSpeech engine returns an ArrayList<String> of all the available voices. |
| 311 | * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are |
| 312 | * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). |
| 313 | */ |
| 314 | public static final String EXTRA_AVAILABLE_VOICES = "availableVoices"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 315 | |
Charles Chen | 76d9c3c | 2010-02-11 16:44:45 -0800 | [diff] [blame] | 316 | /** |
| 317 | * Extra information received with the {@link #ACTION_CHECK_TTS_DATA} intent where |
| 318 | * the TextToSpeech engine returns an ArrayList<String> of all the unavailable voices. |
| 319 | * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are |
| 320 | * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). |
| 321 | */ |
| 322 | public static final String EXTRA_UNAVAILABLE_VOICES = "unavailableVoices"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 323 | |
Charles Chen | 76d9c3c | 2010-02-11 16:44:45 -0800 | [diff] [blame] | 324 | /** |
| 325 | * Extra information sent with the {@link #ACTION_CHECK_TTS_DATA} intent where the |
| 326 | * caller indicates to the TextToSpeech engine which specific sets of voice data to |
| 327 | * check for by sending an ArrayList<String> of the voices that are of interest. |
| 328 | * The format of each voice is: lang-COUNTRY-variant where COUNTRY and variant are |
| 329 | * optional (ie, "eng" or "eng-USA" or "eng-USA-FEMALE"). |
| 330 | */ |
| 331 | public static final String EXTRA_CHECK_VOICE_DATA_FOR = "checkVoiceDataFor"; |
Charles Chen | 99a0fee | 2009-07-02 10:41:51 -0700 | [diff] [blame] | 332 | |
Jean-Michel Trivi | 77a5d39 | 2009-08-07 17:26:36 -0700 | [diff] [blame] | 333 | // extras for a TTS engine's data installation |
| 334 | /** |
Jean-Michel Trivi | 9f5eadd | 2009-08-14 15:44:31 -0700 | [diff] [blame] | 335 | * Extra information received with the {@link #ACTION_TTS_DATA_INSTALLED} intent. |
| 336 | * It indicates whether the data files for the synthesis engine were successfully |
| 337 | * installed. The installation was initiated with the {@link #ACTION_INSTALL_TTS_DATA} |
| 338 | * intent. The possible values for this extra are |
| 339 | * {@link TextToSpeech#SUCCESS} and {@link TextToSpeech#ERROR}. |
Jean-Michel Trivi | 77a5d39 | 2009-08-07 17:26:36 -0700 | [diff] [blame] | 340 | */ |
| 341 | public static final String EXTRA_TTS_DATA_INSTALLED = "dataInstalled"; |
| 342 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 343 | // keys for the parameters passed with speak commands. Hidden keys are used internally |
| 344 | // to maintain engine state for each TextToSpeech instance. |
| 345 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 346 | * @hide |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 347 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 348 | public static final String KEY_PARAM_RATE = "rate"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 349 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 350 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 351 | * @hide |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 352 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 353 | public static final String KEY_PARAM_LANGUAGE = "language"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 354 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 355 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 356 | * @hide |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 357 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 358 | public static final String KEY_PARAM_COUNTRY = "country"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 359 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 360 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 361 | * @hide |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 362 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 363 | public static final String KEY_PARAM_VARIANT = "variant"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 364 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 365 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 366 | * @hide |
Charles Chen | 60dd360 | 2010-01-07 18:56:24 -0800 | [diff] [blame] | 367 | */ |
| 368 | public static final String KEY_PARAM_ENGINE = "engine"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 369 | |
Charles Chen | 60dd360 | 2010-01-07 18:56:24 -0800 | [diff] [blame] | 370 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 371 | * @hide |
Charles Chen | 1a2712c | 2010-04-01 17:16:28 -0700 | [diff] [blame] | 372 | */ |
| 373 | public static final String KEY_PARAM_PITCH = "pitch"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 374 | |
Charles Chen | 1a2712c | 2010-04-01 17:16:28 -0700 | [diff] [blame] | 375 | /** |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 376 | * Parameter key to specify the audio stream type to be used when speaking text |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 377 | * or playing back a file. The value should be one of the STREAM_ constants |
| 378 | * defined in {@link AudioManager}. |
| 379 | * |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 380 | * @see TextToSpeech#speak(String, int, HashMap) |
| 381 | * @see TextToSpeech#playEarcon(String, int, HashMap) |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 382 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 383 | public static final String KEY_PARAM_STREAM = "streamType"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 384 | |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 385 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 386 | * Parameter key to identify an utterance in the |
| 387 | * {@link TextToSpeech.OnUtteranceCompletedListener} after text has been |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 388 | * spoken, a file has been played back or a silence duration has elapsed. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 389 | * |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 390 | * @see TextToSpeech#speak(String, int, HashMap) |
| 391 | * @see TextToSpeech#playEarcon(String, int, HashMap) |
| 392 | * @see TextToSpeech#synthesizeToFile(String, HashMap, String) |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 393 | */ |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 394 | public static final String KEY_PARAM_UTTERANCE_ID = "utteranceId"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 395 | |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 396 | /** |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 397 | * Parameter key to specify the speech volume relative to the current stream type |
| 398 | * volume used when speaking text. Volume is specified as a float ranging from 0 to 1 |
Jean-Michel Trivi | 9011ec8 | 2011-01-11 11:55:00 -0800 | [diff] [blame] | 399 | * where 0 is silence, and 1 is the maximum volume (the default behavior). |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 400 | * |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 401 | * @see TextToSpeech#speak(String, int, HashMap) |
| 402 | * @see TextToSpeech#playEarcon(String, int, HashMap) |
| 403 | */ |
| 404 | public static final String KEY_PARAM_VOLUME = "volume"; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 405 | |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 406 | /** |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 407 | * Parameter key to specify how the speech is panned from left to right when speaking text. |
| 408 | * Pan is specified as a float ranging from -1 to +1 where -1 maps to a hard-left pan, |
Jean-Michel Trivi | 9011ec8 | 2011-01-11 11:55:00 -0800 | [diff] [blame] | 409 | * 0 to center (the default behavior), and +1 to hard-right. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 410 | * |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 411 | * @see TextToSpeech#speak(String, int, HashMap) |
| 412 | * @see TextToSpeech#playEarcon(String, int, HashMap) |
| 413 | */ |
| 414 | public static final String KEY_PARAM_PAN = "pan"; |
Jean-Michel Trivi | 62253a3 | 2009-07-14 13:55:19 -0700 | [diff] [blame] | 415 | |
Jean-Michel Trivi | d146874 | 2009-06-18 14:41:41 -0700 | [diff] [blame] | 416 | } |
| 417 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 418 | private final Context mContext; |
| 419 | private Connection mServiceConnection; |
| 420 | private OnInitListener mInitListener; |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 421 | private final Object mStartLock = new Object(); |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 422 | |
| 423 | private String mRequestedEngine; |
| 424 | private final Map<String, Uri> mEarcons; |
| 425 | private final Map<String, Uri> mUtterances; |
| 426 | private final Bundle mParams = new Bundle(); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 427 | |
| 428 | /** |
Bjorn Bringert | 4bbca88 | 2011-04-19 18:45:25 +0100 | [diff] [blame] | 429 | * The constructor for the TextToSpeech class, using the default TTS engine. |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 430 | * This will also initialize the associated TextToSpeech engine if it isn't already running. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 431 | * |
| 432 | * @param context |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 433 | * The context this instance is running in. |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 434 | * @param listener |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 435 | * The {@link TextToSpeech.OnInitListener} that will be called when the |
| 436 | * TextToSpeech engine has initialized. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 437 | */ |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 438 | public TextToSpeech(Context context, OnInitListener listener) { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 439 | this(context, listener, null); |
| 440 | } |
| 441 | |
| 442 | /** |
Bjorn Bringert | 4bbca88 | 2011-04-19 18:45:25 +0100 | [diff] [blame] | 443 | * The constructor for the TextToSpeech class, using the given TTS engine. |
| 444 | * This will also initialize the associated TextToSpeech engine if it isn't already running. |
| 445 | * |
| 446 | * @param context |
| 447 | * The context this instance is running in. |
| 448 | * @param listener |
| 449 | * The {@link TextToSpeech.OnInitListener} that will be called when the |
| 450 | * TextToSpeech engine has initialized. |
| 451 | * @param engine Package name of the TTS engine to use. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 452 | */ |
| 453 | public TextToSpeech(Context context, OnInitListener listener, String engine) { |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 454 | mContext = context; |
| 455 | mInitListener = listener; |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 456 | mRequestedEngine = engine; |
Jean-Michel Trivi | 87c9684 | 2009-06-25 14:29:15 -0700 | [diff] [blame] | 457 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 458 | mEarcons = new HashMap<String, Uri>(); |
| 459 | mUtterances = new HashMap<String, Uri>(); |
Jean-Michel Trivi | a981013 | 2009-07-10 12:08:59 -0700 | [diff] [blame] | 460 | |
Jean-Michel Trivi | a8518c1 | 2009-06-10 17:33:34 -0700 | [diff] [blame] | 461 | initTts(); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 462 | } |
| 463 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 464 | private String getPackageName() { |
| 465 | return mContext.getPackageName(); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 466 | } |
| 467 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 468 | private <R> R runActionNoReconnect(Action<R> action, R errorResult, String method) { |
| 469 | return runAction(action, errorResult, method, false); |
| 470 | } |
| 471 | |
| 472 | private <R> R runAction(Action<R> action, R errorResult, String method) { |
| 473 | return runAction(action, errorResult, method, true); |
| 474 | } |
| 475 | |
| 476 | private <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) { |
| 477 | synchronized (mStartLock) { |
| 478 | if (mServiceConnection == null) { |
| 479 | Log.w(TAG, method + " failed: not bound to TTS engine"); |
| 480 | return errorResult; |
| 481 | } |
| 482 | return mServiceConnection.runAction(action, errorResult, method, reconnect); |
| 483 | } |
| 484 | } |
| 485 | |
| 486 | private int initTts() { |
| 487 | String defaultEngine = getDefaultEngine(); |
| 488 | String engine = defaultEngine; |
| 489 | if (!areDefaultsEnforced() && !TextUtils.isEmpty(mRequestedEngine) |
| 490 | && isEngineEnabled(engine)) { |
| 491 | engine = mRequestedEngine; |
| 492 | } |
| 493 | |
| 494 | // Try requested engine |
| 495 | if (connectToEngine(engine)) { |
| 496 | return SUCCESS; |
| 497 | } |
| 498 | |
| 499 | // Fall back to user's default engine if different from the already tested one |
| 500 | if (!engine.equals(defaultEngine)) { |
| 501 | if (connectToEngine(defaultEngine)) { |
| 502 | return SUCCESS; |
| 503 | } |
| 504 | } |
| 505 | |
| 506 | // Fall back to the hardcoded default if different from the two above |
| 507 | if (!defaultEngine.equals(Engine.DEFAULT_ENGINE) |
| 508 | && !engine.equals(Engine.DEFAULT_ENGINE)) { |
| 509 | if (connectToEngine(Engine.DEFAULT_ENGINE)) { |
| 510 | return SUCCESS; |
| 511 | } |
| 512 | } |
| 513 | |
| 514 | return ERROR; |
| 515 | } |
| 516 | |
| 517 | private boolean connectToEngine(String engine) { |
| 518 | Connection connection = new Connection(); |
| 519 | Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE); |
| 520 | intent.setPackage(engine); |
| 521 | boolean bound = mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE); |
| 522 | if (!bound) { |
| 523 | Log.e(TAG, "Failed to bind to " + engine); |
| 524 | dispatchOnInit(ERROR); |
| 525 | return false; |
| 526 | } else { |
| 527 | return true; |
| 528 | } |
| 529 | } |
| 530 | |
| 531 | private void dispatchOnInit(int result) { |
| 532 | synchronized (mStartLock) { |
| 533 | if (mInitListener != null) { |
| 534 | mInitListener.onInit(result); |
| 535 | mInitListener = null; |
| 536 | } |
| 537 | } |
| 538 | } |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 539 | |
| 540 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 541 | * Releases the resources used by the TextToSpeech engine. |
| 542 | * It is good practice for instance to call this method in the onDestroy() method of an Activity |
| 543 | * so the TextToSpeech engine can be cleanly stopped. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 544 | */ |
| 545 | public void shutdown() { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 546 | runActionNoReconnect(new Action<Void>() { |
| 547 | @Override |
| 548 | public Void run(ITextToSpeechService service) throws RemoteException { |
| 549 | service.setCallback(getPackageName(), null); |
| 550 | service.stop(getPackageName()); |
| 551 | mServiceConnection.disconnect(); |
| 552 | return null; |
| 553 | } |
| 554 | }, null, "shutdown"); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 555 | } |
| 556 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 557 | /** |
| 558 | * Adds a mapping between a string of text and a sound resource in a |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 559 | * package. After a call to this method, subsequent calls to |
| 560 | * {@link #speak(String, int, HashMap)} will play the specified sound resource |
| 561 | * if it is available, or synthesize the text it is missing. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 562 | * |
| 563 | * @param text |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 564 | * The string of text. Example: <code>"south_south_east"</code> |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 565 | * |
| 566 | * @param packagename |
| 567 | * Pass the packagename of the application that contains the |
| 568 | * resource. If the resource is in your own application (this is |
| 569 | * the most common case), then put the packagename of your |
| 570 | * application here.<br/> |
| 571 | * Example: <b>"com.google.marvin.compass"</b><br/> |
| 572 | * The packagename can be found in the AndroidManifest.xml of |
| 573 | * your application. |
| 574 | * <p> |
| 575 | * <code><manifest xmlns:android="..." |
| 576 | * package="<b>com.google.marvin.compass</b>"></code> |
| 577 | * </p> |
| 578 | * |
| 579 | * @param resourceId |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 580 | * Example: <code>R.raw.south_south_east</code> |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 581 | * |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 582 | * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 583 | */ |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 584 | public int addSpeech(String text, String packagename, int resourceId) { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 585 | synchronized (mStartLock) { |
| 586 | mUtterances.put(text, makeResourceUri(packagename, resourceId)); |
| 587 | return SUCCESS; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 588 | } |
| 589 | } |
| 590 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 591 | /** |
| 592 | * Adds a mapping between a string of text and a sound file. Using this, it |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 593 | * is possible to add custom pronounciations for a string of text. |
| 594 | * After a call to this method, subsequent calls to {@link #speak(String, int, HashMap)} |
| 595 | * will play the specified sound resource if it is available, or synthesize the text it is |
| 596 | * missing. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 597 | * |
| 598 | * @param text |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 599 | * The string of text. Example: <code>"south_south_east"</code> |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 600 | * @param filename |
| 601 | * The full path to the sound file (for example: |
| 602 | * "/sdcard/mysounds/hello.wav") |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 603 | * |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 604 | * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 605 | */ |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 606 | public int addSpeech(String text, String filename) { |
Jean-Michel Trivi | 91bf30a | 2009-06-11 14:35:48 -0700 | [diff] [blame] | 607 | synchronized (mStartLock) { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 608 | mUtterances.put(text, Uri.parse(filename)); |
| 609 | return SUCCESS; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 610 | } |
| 611 | } |
| 612 | |
| 613 | |
| 614 | /** |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 615 | * Adds a mapping between a string of text and a sound resource in a |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 616 | * package. Use this to add custom earcons. |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 617 | * |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 618 | * @see #playEarcon(String, int, HashMap) |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 619 | * |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 620 | * @param earcon The name of the earcon. |
| 621 | * Example: <code>"[tick]"</code><br/> |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 622 | * |
| 623 | * @param packagename |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 624 | * the package name of the application that contains the |
| 625 | * resource. This can for instance be the package name of your own application. |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 626 | * Example: <b>"com.google.marvin.compass"</b><br/> |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 627 | * The package name can be found in the AndroidManifest.xml of |
| 628 | * the application containing the resource. |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 629 | * <p> |
| 630 | * <code><manifest xmlns:android="..." |
| 631 | * package="<b>com.google.marvin.compass</b>"></code> |
| 632 | * </p> |
| 633 | * |
| 634 | * @param resourceId |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 635 | * Example: <code>R.raw.tick_snd</code> |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 636 | * |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 637 | * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 638 | */ |
| 639 | public int addEarcon(String earcon, String packagename, int resourceId) { |
| 640 | synchronized(mStartLock) { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 641 | mEarcons.put(earcon, makeResourceUri(packagename, resourceId)); |
| 642 | return SUCCESS; |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 643 | } |
| 644 | } |
| 645 | |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 646 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 647 | * Adds a mapping between a string of text and a sound file. |
| 648 | * Use this to add custom earcons. |
| 649 | * |
| 650 | * @see #playEarcon(String, int, HashMap) |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 651 | * |
| 652 | * @param earcon |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 653 | * The name of the earcon. |
| 654 | * Example: <code>"[tick]"</code> |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 655 | * @param filename |
| 656 | * The full path to the sound file (for example: |
| 657 | * "/sdcard/mysounds/tick.wav") |
| 658 | * |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 659 | * @return Code indicating success or failure. See {@link #ERROR} and {@link #SUCCESS}. |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 660 | */ |
| 661 | public int addEarcon(String earcon, String filename) { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 662 | synchronized(mStartLock) { |
| 663 | mEarcons.put(earcon, Uri.parse(filename)); |
| 664 | return SUCCESS; |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 665 | } |
| 666 | } |
| 667 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 668 | private Uri makeResourceUri(String packageName, int resourceId) { |
| 669 | return new Uri.Builder() |
| 670 | .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) |
| 671 | .encodedAuthority(packageName) |
| 672 | .appendEncodedPath(String.valueOf(resourceId)) |
| 673 | .build(); |
| 674 | } |
Charles Chen | 904dfa5 | 2009-07-15 10:44:41 -0700 | [diff] [blame] | 675 | |
| 676 | /** |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 677 | * Speaks the string using the specified queuing strategy and speech |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 678 | * parameters. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 679 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 680 | * @param text The string of text to be spoken. |
| 681 | * @param queueMode The queuing strategy to use, {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. |
| 682 | * @param params Parameters for the request. Can be null. |
| 683 | * Supported parameter names: |
| 684 | * {@link Engine#KEY_PARAM_STREAM}, |
| 685 | * {@link Engine#KEY_PARAM_UTTERANCE_ID}, |
| 686 | * {@link Engine#KEY_PARAM_VOLUME}, |
| 687 | * {@link Engine#KEY_PARAM_PAN}. |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 688 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 689 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 690 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 691 | public int speak(final String text, final int queueMode, final HashMap<String, String> params) { |
| 692 | return runAction(new Action<Integer>() { |
| 693 | @Override |
| 694 | public Integer run(ITextToSpeechService service) throws RemoteException { |
| 695 | Uri utteranceUri = mUtterances.get(text); |
| 696 | if (utteranceUri != null) { |
| 697 | return service.playAudio(getPackageName(), utteranceUri, queueMode, |
| 698 | getParams(params)); |
| 699 | } else { |
| 700 | return service.speak(getPackageName(), text, queueMode, getParams(params)); |
Jean-Michel Trivi | a981013 | 2009-07-10 12:08:59 -0700 | [diff] [blame] | 701 | } |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 702 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 703 | }, ERROR, "speak"); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 704 | } |
| 705 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 706 | /** |
| 707 | * Plays the earcon using the specified queueing mode and parameters. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 708 | * The earcon must already have been added with {@link #addEarcon(String, String)} or |
| 709 | * {@link #addEarcon(String, String, int)}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 710 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 711 | * @param earcon The earcon that should be played |
| 712 | * @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. |
| 713 | * @param params Parameters for the request. Can be null. |
| 714 | * Supported parameter names: |
| 715 | * {@link Engine#KEY_PARAM_STREAM}, |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 716 | * {@link Engine#KEY_PARAM_UTTERANCE_ID}. |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 717 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 718 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 719 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 720 | public int playEarcon(final String earcon, final int queueMode, |
| 721 | final HashMap<String, String> params) { |
| 722 | return runAction(new Action<Integer>() { |
| 723 | @Override |
| 724 | public Integer run(ITextToSpeechService service) throws RemoteException { |
| 725 | Uri earconUri = mEarcons.get(earcon); |
| 726 | if (earconUri == null) { |
| 727 | return ERROR; |
Jean-Michel Trivi | a981013 | 2009-07-10 12:08:59 -0700 | [diff] [blame] | 728 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 729 | return service.playAudio(getPackageName(), earconUri, queueMode, |
| 730 | getParams(params)); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 731 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 732 | }, ERROR, "playEarcon"); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 733 | } |
Jean-Michel Trivi | 679d728 | 2009-06-16 15:36:28 -0700 | [diff] [blame] | 734 | |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 735 | /** |
| 736 | * Plays silence for the specified amount of time using the specified |
| 737 | * queue mode. |
| 738 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 739 | * @param durationInMs The duration of the silence. |
| 740 | * @param queueMode {@link #QUEUE_ADD} or {@link #QUEUE_FLUSH}. |
| 741 | * @param params Parameters for the request. Can be null. |
| 742 | * Supported parameter names: |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 743 | * {@link Engine#KEY_PARAM_UTTERANCE_ID}. |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 744 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 745 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 746 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 747 | public int playSilence(final long durationInMs, final int queueMode, |
| 748 | final HashMap<String, String> params) { |
| 749 | return runAction(new Action<Integer>() { |
| 750 | @Override |
| 751 | public Integer run(ITextToSpeechService service) throws RemoteException { |
| 752 | return service.playSilence(getPackageName(), durationInMs, queueMode, |
| 753 | getParams(params)); |
Charles Chen | f032bc7 | 2009-06-26 14:41:55 -0700 | [diff] [blame] | 754 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 755 | }, ERROR, "playSilence"); |
Jean-Michel Trivi | a8518c1 | 2009-06-10 17:33:34 -0700 | [diff] [blame] | 756 | } |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 757 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 758 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 759 | * Checks whether the TTS engine is busy speaking. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 760 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 761 | * @return {@code true} if the TTS engine is speaking. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 762 | */ |
| 763 | public boolean isSpeaking() { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 764 | return runAction(new Action<Boolean>() { |
| 765 | @Override |
| 766 | public Boolean run(ITextToSpeechService service) throws RemoteException { |
| 767 | return service.isSpeaking(); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 768 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 769 | }, false, "isSpeaking"); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 770 | } |
| 771 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 772 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 773 | * Interrupts the current utterance (whether played or rendered to file) and discards other |
| 774 | * utterances in the queue. |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 775 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 776 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 777 | */ |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 778 | public int stop() { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 779 | return runAction(new Action<Integer>() { |
| 780 | @Override |
| 781 | public Integer run(ITextToSpeechService service) throws RemoteException { |
| 782 | return service.stop(getPackageName()); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 783 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 784 | }, ERROR, "stop"); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 785 | } |
| 786 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 787 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 788 | * Sets the speech rate. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 789 | * |
Jean-Michel Trivi | 679d728 | 2009-06-16 15:36:28 -0700 | [diff] [blame] | 790 | * This has no effect on any pre-recorded speech. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 791 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 792 | * @param speechRate Speech rate. {@code 1.0} is the normal speech rate, |
| 793 | * lower values slow down the speech ({@code 0.5} is half the normal speech rate), |
| 794 | * greater values accelerate it ({@code 2.0} is twice the normal speech rate). |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 795 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 796 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 797 | */ |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 798 | public int setSpeechRate(float speechRate) { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 799 | if (speechRate > 0.0f) { |
| 800 | int intRate = (int)(speechRate * 100); |
| 801 | if (intRate > 0) { |
| 802 | synchronized (mStartLock) { |
| 803 | mParams.putInt(Engine.KEY_PARAM_RATE, intRate); |
Jean-Michel Trivi | 679d728 | 2009-06-16 15:36:28 -0700 | [diff] [blame] | 804 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 805 | return SUCCESS; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 806 | } |
| 807 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 808 | return ERROR; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 809 | } |
| 810 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 811 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 812 | * Sets the speech pitch for the TextToSpeech engine. |
Jean-Michel Trivi | 2ea5349 | 2009-06-23 13:44:40 -0700 | [diff] [blame] | 813 | * |
Jean-Michel Trivi | 2ea5349 | 2009-06-23 13:44:40 -0700 | [diff] [blame] | 814 | * This has no effect on any pre-recorded speech. |
| 815 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 816 | * @param pitch Speech pitch. {@code 1.0} is the normal pitch, |
Jean-Michel Trivi | 2ea5349 | 2009-06-23 13:44:40 -0700 | [diff] [blame] | 817 | * lower values lower the tone of the synthesized voice, |
| 818 | * greater values increase it. |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 819 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 820 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Jean-Michel Trivi | 2ea5349 | 2009-06-23 13:44:40 -0700 | [diff] [blame] | 821 | */ |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 822 | public int setPitch(float pitch) { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 823 | if (pitch > 0.0f) { |
| 824 | int intPitch = (int)(pitch * 100); |
| 825 | if (intPitch > 0) { |
| 826 | synchronized (mStartLock) { |
| 827 | mParams.putInt(Engine.KEY_PARAM_PITCH, intPitch); |
Jean-Michel Trivi | 2ea5349 | 2009-06-23 13:44:40 -0700 | [diff] [blame] | 828 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 829 | return SUCCESS; |
Jean-Michel Trivi | 2ea5349 | 2009-06-23 13:44:40 -0700 | [diff] [blame] | 830 | } |
| 831 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 832 | return ERROR; |
Jean-Michel Trivi | 2ea5349 | 2009-06-23 13:44:40 -0700 | [diff] [blame] | 833 | } |
| 834 | |
Jean-Michel Trivi | 2ea5349 | 2009-06-23 13:44:40 -0700 | [diff] [blame] | 835 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 836 | * Sets the text-to-speech language. |
| 837 | * The TTS engine will try to use the closest match to the specified |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 838 | * language as represented by the Locale, but there is no guarantee that the exact same Locale |
| 839 | * will be used. Use {@link #isLanguageAvailable(Locale)} to check the level of support |
| 840 | * before choosing the language to use for the next utterances. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 841 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 842 | * @param loc The locale describing the language to be used. |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 843 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 844 | * @return Code indicating the support status for the locale. See {@link #LANG_AVAILABLE}, |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 845 | * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE}, |
| 846 | * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 847 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 848 | public int setLanguage(final Locale loc) { |
| 849 | return runAction(new Action<Integer>() { |
| 850 | @Override |
| 851 | public Integer run(ITextToSpeechService service) throws RemoteException { |
| 852 | if (loc == null) { |
| 853 | return LANG_NOT_SUPPORTED; |
| 854 | } |
Charles Chen | 1a2712c | 2010-04-01 17:16:28 -0700 | [diff] [blame] | 855 | String language = loc.getISO3Language(); |
| 856 | String country = loc.getISO3Country(); |
| 857 | String variant = loc.getVariant(); |
| 858 | // Check if the language, country, variant are available, and cache |
| 859 | // the available parts. |
| 860 | // Note that the language is not actually set here, instead it is cached so it |
| 861 | // will be associated with all upcoming utterances. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 862 | int result = service.loadLanguage(language, country, variant); |
Charles Chen | 1a2712c | 2010-04-01 17:16:28 -0700 | [diff] [blame] | 863 | if (result >= LANG_AVAILABLE){ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 864 | if (result < LANG_COUNTRY_VAR_AVAILABLE) { |
| 865 | variant = ""; |
| 866 | if (result < LANG_COUNTRY_AVAILABLE) { |
| 867 | country = ""; |
| 868 | } |
Charles Chen | 1a2712c | 2010-04-01 17:16:28 -0700 | [diff] [blame] | 869 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 870 | mParams.putString(Engine.KEY_PARAM_LANGUAGE, language); |
| 871 | mParams.putString(Engine.KEY_PARAM_COUNTRY, country); |
| 872 | mParams.putString(Engine.KEY_PARAM_VARIANT, variant); |
Charles Chen | 1a2712c | 2010-04-01 17:16:28 -0700 | [diff] [blame] | 873 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 874 | return result; |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 875 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 876 | }, LANG_NOT_SUPPORTED, "setLanguage"); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 877 | } |
| 878 | |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 879 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 880 | * Returns a Locale instance describing the language currently being used by the TextToSpeech |
| 881 | * engine. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 882 | * |
Jean-Michel Trivi | ddb0a80 | 2009-06-29 16:38:47 -0700 | [diff] [blame] | 883 | * @return language, country (if any) and variant (if any) used by the engine stored in a Locale |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 884 | * instance, or {@code null} on error. |
Jean-Michel Trivi | ddb0a80 | 2009-06-29 16:38:47 -0700 | [diff] [blame] | 885 | */ |
| 886 | public Locale getLanguage() { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 887 | return runAction(new Action<Locale>() { |
| 888 | @Override |
| 889 | public Locale run(ITextToSpeechService service) throws RemoteException { |
| 890 | String[] locStrings = service.getLanguage(); |
| 891 | if (locStrings != null && locStrings.length == 3) { |
| 892 | return new Locale(locStrings[0], locStrings[1], locStrings[2]); |
| 893 | } |
Jean-Michel Trivi | ddb0a80 | 2009-06-29 16:38:47 -0700 | [diff] [blame] | 894 | return null; |
| 895 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 896 | }, null, "getLanguage"); |
Jean-Michel Trivi | ddb0a80 | 2009-06-29 16:38:47 -0700 | [diff] [blame] | 897 | } |
| 898 | |
| 899 | /** |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 900 | * Checks if the specified language as represented by the Locale is available and supported. |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 901 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 902 | * @param loc The Locale describing the language to be used. |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 903 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 904 | * @return Code indicating the support status for the locale. See {@link #LANG_AVAILABLE}, |
Jean-Michel Trivi | ed06578 | 2009-07-28 14:31:48 -0700 | [diff] [blame] | 905 | * {@link #LANG_COUNTRY_AVAILABLE}, {@link #LANG_COUNTRY_VAR_AVAILABLE}, |
| 906 | * {@link #LANG_MISSING_DATA} and {@link #LANG_NOT_SUPPORTED}. |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 907 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 908 | public int isLanguageAvailable(final Locale loc) { |
| 909 | return runAction(new Action<Integer>() { |
| 910 | @Override |
| 911 | public Integer run(ITextToSpeechService service) throws RemoteException { |
| 912 | return service.isLanguageAvailable(loc.getISO3Language(), |
| 913 | loc.getISO3Country(), loc.getVariant()); |
Jean-Michel Trivi | ddb0a80 | 2009-06-29 16:38:47 -0700 | [diff] [blame] | 914 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 915 | }, LANG_NOT_SUPPORTED, "isLanguageAvailable"); |
Charles Chen | aaf842e | 2009-06-25 11:59:29 -0700 | [diff] [blame] | 916 | } |
| 917 | |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 918 | /** |
Charles Chen | d498909 | 2009-06-26 15:32:46 -0700 | [diff] [blame] | 919 | * Synthesizes the given text to a file using the specified parameters. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 920 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 921 | * @param text Thetext that should be synthesized |
| 922 | * @param params Parameters for the request. Can be null. |
| 923 | * Supported parameter names: |
Jean-Michel Trivi | a9b417e | 2009-09-11 18:34:02 -0700 | [diff] [blame] | 924 | * {@link Engine#KEY_PARAM_UTTERANCE_ID}. |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 925 | * @param filename Absolute file filename to write the generated audio data to.It should be |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 926 | * something like "/sdcard/myappsounds/mysound.wav". |
Charles Chen | 5c22f51 | 2009-06-29 15:52:47 -0700 | [diff] [blame] | 927 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 928 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 929 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 930 | public int synthesizeToFile(final String text, final HashMap<String, String> params, |
| 931 | final String filename) { |
| 932 | return runAction(new Action<Integer>() { |
| 933 | @Override |
| 934 | public Integer run(ITextToSpeechService service) throws RemoteException { |
| 935 | return service.synthesizeToFile(getPackageName(), text, filename, |
| 936 | getParams(params)); |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 937 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 938 | }, ERROR, "synthesizeToFile"); |
| 939 | } |
| 940 | |
| 941 | private Bundle getParams(HashMap<String, String> params) { |
| 942 | if (params != null && !params.isEmpty()) { |
| 943 | Bundle bundle = new Bundle(mParams); |
| 944 | copyIntParam(bundle, params, Engine.KEY_PARAM_STREAM); |
| 945 | copyStringParam(bundle, params, Engine.KEY_PARAM_UTTERANCE_ID); |
| 946 | copyFloatParam(bundle, params, Engine.KEY_PARAM_VOLUME); |
| 947 | copyFloatParam(bundle, params, Engine.KEY_PARAM_PAN); |
| 948 | return bundle; |
| 949 | } else { |
| 950 | return mParams; |
| 951 | } |
| 952 | } |
| 953 | |
| 954 | private void copyStringParam(Bundle bundle, HashMap<String, String> params, String key) { |
| 955 | String value = params.get(key); |
| 956 | if (value != null) { |
| 957 | bundle.putString(key, value); |
| 958 | } |
| 959 | } |
| 960 | |
| 961 | private void copyIntParam(Bundle bundle, HashMap<String, String> params, String key) { |
| 962 | String valueString = params.get(key); |
| 963 | if (!TextUtils.isEmpty(valueString)) { |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 964 | try { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 965 | int value = Integer.parseInt(valueString); |
| 966 | bundle.putInt(key, value); |
| 967 | } catch (NumberFormatException ex) { |
| 968 | // don't set the value in the bundle |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 969 | } |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 970 | } |
| 971 | } |
| 972 | |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 973 | private void copyFloatParam(Bundle bundle, HashMap<String, String> params, String key) { |
| 974 | String valueString = params.get(key); |
| 975 | if (!TextUtils.isEmpty(valueString)) { |
| 976 | try { |
| 977 | float value = Float.parseFloat(valueString); |
| 978 | bundle.putFloat(key, value); |
| 979 | } catch (NumberFormatException ex) { |
| 980 | // don't set the value in the bundle |
| 981 | } |
Jean-Michel Trivi | 9d2d26a | 2011-01-05 16:08:21 -0800 | [diff] [blame] | 982 | } |
Jean-Michel Trivi | a981013 | 2009-07-10 12:08:59 -0700 | [diff] [blame] | 983 | } |
| 984 | |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 985 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 986 | * Sets the listener that will be notified when synthesis of an utterance completes. |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 987 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 988 | * @param listener The listener to use. |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 989 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 990 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 991 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 992 | public int setOnUtteranceCompletedListener(final OnUtteranceCompletedListener listener) { |
| 993 | return runAction(new Action<Integer>() { |
| 994 | @Override |
| 995 | public Integer run(ITextToSpeechService service) throws RemoteException { |
| 996 | ITextToSpeechCallback.Stub callback = new ITextToSpeechCallback.Stub() { |
| 997 | public void utteranceCompleted(String utteranceId) { |
| 998 | if (listener != null) { |
| 999 | listener.onUtteranceCompleted(utteranceId); |
| 1000 | } |
Charles Chen | 60dd360 | 2010-01-07 18:56:24 -0800 | [diff] [blame] | 1001 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1002 | }; |
| 1003 | service.setCallback(getPackageName(), callback); |
| 1004 | return SUCCESS; |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 1005 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1006 | }, ERROR, "setOnUtteranceCompletedListener"); |
Charles Chen | 78c9d0d | 2009-07-13 16:22:41 -0700 | [diff] [blame] | 1007 | } |
| 1008 | |
Charles Chen | b4fbe76 | 2009-11-18 16:34:32 -0800 | [diff] [blame] | 1009 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1010 | * Sets the TTS engine to use. |
Charles Chen | b4fbe76 | 2009-11-18 16:34:32 -0800 | [diff] [blame] | 1011 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1012 | * @param enginePackageName The package name for the synthesis engine (e.g. "com.svox.pico") |
Charles Chen | b4fbe76 | 2009-11-18 16:34:32 -0800 | [diff] [blame] | 1013 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1014 | * @return {@link #ERROR} or {@link #SUCCESS}. |
Charles Chen | b4fbe76 | 2009-11-18 16:34:32 -0800 | [diff] [blame] | 1015 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1016 | // TODO: add @Deprecated{This method does not tell the caller when the new engine |
| 1017 | // has been initialized. You should create a new TextToSpeech object with the new |
| 1018 | // engine instead.} |
Charles Chen | 60dd360 | 2010-01-07 18:56:24 -0800 | [diff] [blame] | 1019 | public int setEngineByPackageName(String enginePackageName) { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1020 | mRequestedEngine = enginePackageName; |
| 1021 | return initTts(); |
Charles Chen | b4fbe76 | 2009-11-18 16:34:32 -0800 | [diff] [blame] | 1022 | } |
| 1023 | |
Charles Chen | def7185 | 2010-03-25 19:59:50 -0700 | [diff] [blame] | 1024 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1025 | * Gets the package name of the default speech synthesis engine. |
Charles Chen | def7185 | 2010-03-25 19:59:50 -0700 | [diff] [blame] | 1026 | * |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1027 | * @return Package name of the TTS engine that the user has chosen as their default. |
Charles Chen | def7185 | 2010-03-25 19:59:50 -0700 | [diff] [blame] | 1028 | */ |
| 1029 | public String getDefaultEngine() { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1030 | String engine = Settings.Secure.getString(mContext.getContentResolver(), |
| 1031 | Settings.Secure.TTS_DEFAULT_SYNTH); |
| 1032 | return engine != null ? engine : Engine.DEFAULT_ENGINE; |
Charles Chen | def7185 | 2010-03-25 19:59:50 -0700 | [diff] [blame] | 1033 | } |
Charles Chen | 4222925 | 2010-03-29 18:30:30 -0700 | [diff] [blame] | 1034 | |
Charles Chen | 4222925 | 2010-03-29 18:30:30 -0700 | [diff] [blame] | 1035 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1036 | * Checks whether the user's settings should override settings requested by the calling |
| 1037 | * application. |
Charles Chen | 4222925 | 2010-03-29 18:30:30 -0700 | [diff] [blame] | 1038 | */ |
| 1039 | public boolean areDefaultsEnforced() { |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1040 | return Settings.Secure.getInt(mContext.getContentResolver(), |
| 1041 | Settings.Secure.TTS_USE_DEFAULTS, Engine.USE_DEFAULTS) == 1; |
| 1042 | } |
| 1043 | |
| 1044 | private boolean isEngineEnabled(String engine) { |
| 1045 | if (Engine.DEFAULT_ENGINE.equals(engine)) { |
| 1046 | return true; |
Charles Chen | 4222925 | 2010-03-29 18:30:30 -0700 | [diff] [blame] | 1047 | } |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1048 | for (String enabled : getEnabledEngines()) { |
| 1049 | if (engine.equals(enabled)) { |
| 1050 | return true; |
| 1051 | } |
| 1052 | } |
| 1053 | return false; |
| 1054 | } |
| 1055 | |
| 1056 | private String[] getEnabledEngines() { |
| 1057 | String str = Settings.Secure.getString(mContext.getContentResolver(), |
| 1058 | Settings.Secure.TTS_ENABLED_PLUGINS); |
| 1059 | if (TextUtils.isEmpty(str)) { |
| 1060 | return new String[0]; |
| 1061 | } |
| 1062 | return str.split(" "); |
Charles Chen | 4222925 | 2010-03-29 18:30:30 -0700 | [diff] [blame] | 1063 | } |
Bjorn Bringert | 2cad2cc | 2011-03-08 11:53:12 +0000 | [diff] [blame] | 1064 | |
| 1065 | /** |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1066 | * Gets a list of all installed TTS engines. |
| 1067 | * |
| 1068 | * @return A list of engine info objects. The list can be empty, but will never by {@code null}. |
Bjorn Bringert | 2cad2cc | 2011-03-08 11:53:12 +0000 | [diff] [blame] | 1069 | */ |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1070 | public List<EngineInfo> getEngines() { |
| 1071 | PackageManager pm = mContext.getPackageManager(); |
| 1072 | Intent intent = new Intent(Engine.INTENT_ACTION_TTS_SERVICE); |
Bjorn Bringert | fe6ea01 | 2011-04-18 19:19:31 +0100 | [diff] [blame] | 1073 | List<ResolveInfo> resolveInfos = |
| 1074 | pm.queryIntentServices(intent, PackageManager.MATCH_DEFAULT_ONLY); |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1075 | if (resolveInfos == null) return Collections.emptyList(); |
| 1076 | List<EngineInfo> engines = new ArrayList<EngineInfo>(resolveInfos.size()); |
| 1077 | for (ResolveInfo resolveInfo : resolveInfos) { |
| 1078 | ServiceInfo service = resolveInfo.serviceInfo; |
| 1079 | if (service != null) { |
| 1080 | EngineInfo engine = new EngineInfo(); |
| 1081 | // Using just the package name isn't great, since it disallows having |
| 1082 | // multiple engines in the same package, but that's what the existing API does. |
| 1083 | engine.name = service.packageName; |
| 1084 | CharSequence label = service.loadLabel(pm); |
| 1085 | engine.label = TextUtils.isEmpty(label) ? engine.name : label.toString(); |
| 1086 | engine.icon = service.getIconResource(); |
| 1087 | engines.add(engine); |
| 1088 | } |
| 1089 | } |
| 1090 | return engines; |
| 1091 | } |
| 1092 | |
| 1093 | private class Connection implements ServiceConnection { |
| 1094 | private ITextToSpeechService mService; |
| 1095 | |
| 1096 | public void onServiceConnected(ComponentName name, IBinder service) { |
| 1097 | Log.i(TAG, "Connected to " + name); |
| 1098 | synchronized(mStartLock) { |
| 1099 | if (mServiceConnection != null) { |
| 1100 | // Disconnect any previous service connection |
| 1101 | mServiceConnection.disconnect(); |
| 1102 | } |
| 1103 | mServiceConnection = this; |
| 1104 | mService = ITextToSpeechService.Stub.asInterface(service); |
| 1105 | dispatchOnInit(SUCCESS); |
| 1106 | } |
| 1107 | } |
| 1108 | |
| 1109 | public void onServiceDisconnected(ComponentName name) { |
| 1110 | synchronized(mStartLock) { |
| 1111 | mService = null; |
| 1112 | // If this is the active connection, clear it |
| 1113 | if (mServiceConnection == this) { |
| 1114 | mServiceConnection = null; |
| 1115 | } |
| 1116 | } |
| 1117 | } |
| 1118 | |
| 1119 | public void disconnect() { |
| 1120 | mContext.unbindService(this); |
| 1121 | } |
| 1122 | |
| 1123 | public <R> R runAction(Action<R> action, R errorResult, String method, boolean reconnect) { |
| 1124 | try { |
| 1125 | synchronized (mStartLock) { |
| 1126 | if (mService == null) { |
| 1127 | Log.w(TAG, method + " failed: not connected to TTS engine"); |
| 1128 | return errorResult; |
| 1129 | } |
| 1130 | return action.run(mService); |
| 1131 | } |
| 1132 | } catch (RemoteException ex) { |
| 1133 | Log.e(TAG, method + " failed", ex); |
| 1134 | if (reconnect) { |
| 1135 | disconnect(); |
| 1136 | initTts(); |
| 1137 | } |
| 1138 | return errorResult; |
| 1139 | } |
| 1140 | } |
| 1141 | } |
| 1142 | |
| 1143 | private interface Action<R> { |
| 1144 | R run(ITextToSpeechService service) throws RemoteException; |
| 1145 | } |
| 1146 | |
| 1147 | /** |
| 1148 | * Information about an installed text-to-speech engine. |
| 1149 | * |
| 1150 | * @see TextToSpeech#getEngines |
Bjorn Bringert | 50e657b | 2011-03-08 16:00:40 +0000 | [diff] [blame] | 1151 | */ |
| 1152 | public static class EngineInfo { |
| 1153 | /** |
| 1154 | * Engine package name.. |
| 1155 | */ |
| 1156 | public String name; |
| 1157 | /** |
| 1158 | * Localized label for the engine. |
| 1159 | */ |
| 1160 | public String label; |
| 1161 | /** |
| 1162 | * Icon for the engine. |
| 1163 | */ |
| 1164 | public int icon; |
| 1165 | |
| 1166 | @Override |
| 1167 | public String toString() { |
| 1168 | return "EngineInfo{name=" + name + "}"; |
| 1169 | } |
| 1170 | |
Bjorn Bringert | 2cad2cc | 2011-03-08 11:53:12 +0000 | [diff] [blame] | 1171 | } |
Jean-Michel Trivi | e74d507 | 2009-05-26 10:43:08 -0700 | [diff] [blame] | 1172 | } |