diff options
-rw-r--r-- | api/current.xml | 36 | ||||
-rwxr-xr-x | core/java/android/speech/tts/ITts.aidl | 4 | ||||
-rwxr-xr-x | core/java/android/speech/tts/ITtsCallback.aidl | 2 | ||||
-rwxr-xr-x[-rw-r--r--] | core/java/android/speech/tts/TextToSpeech.java | 78 | ||||
-rwxr-xr-x | packages/TtsService/src/android/tts/TtsService.java | 66 |
5 files changed, 155 insertions, 31 deletions
diff --git a/api/current.xml b/api/current.xml index 88e5025..a5c4e68 100644 --- a/api/current.xml +++ b/api/current.xml @@ -115058,6 +115058,8 @@ </parameter> <parameter name="queueMode" type="int"> </parameter> +<parameter name="params" type="java.util.HashMap<java.lang.String, java.lang.String>"> +</parameter> </method> <method name="setLanguage" return="int" @@ -115072,6 +115074,19 @@ <parameter name="loc" type="java.util.Locale"> </parameter> </method> +<method name="setOnUtteranceCompletedListener" + return="int" + abstract="false" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="listener" type="android.speech.tts.TextToSpeech.OnUtteranceCompletedListener"> +</parameter> +</method> <method name="setPitch" return="int" abstract="false" @@ -115275,6 +115290,27 @@ </parameter> </method> </interface> +<interface name="TextToSpeech.OnUtteranceCompletedListener" + abstract="true" + static="true" + final="false" + deprecated="not deprecated" + visibility="public" +> +<method name="onUtteranceCompleted" + return="void" + abstract="true" + native="false" + synchronized="false" + static="false" + final="false" + deprecated="not deprecated" + visibility="public" +> +<parameter name="utteranceId" type="java.lang.String"> +</parameter> +</method> +</interface> </package> <package name="android.telephony" > diff --git a/core/java/android/speech/tts/ITts.aidl b/core/java/android/speech/tts/ITts.aidl index 5b18b5d..1812188 100755 --- a/core/java/android/speech/tts/ITts.aidl +++ b/core/java/android/speech/tts/ITts.aidl @@ -55,9 +55,9 @@ interface ITts { void addEarconFile(in String callingApp, in String earcon, in String filename);
- void registerCallback(ITtsCallback cb);
+ int registerCallback(in String callingApp, ITtsCallback cb);
- void unregisterCallback(ITtsCallback cb);
+ int unregisterCallback(in String callingApp, ITtsCallback cb);
int playSilence(in String callingApp, in long duration, in int queueMode, in String[] params);
}
diff --git a/core/java/android/speech/tts/ITtsCallback.aidl b/core/java/android/speech/tts/ITtsCallback.aidl index 48ed73e..c9898eb 100755 --- a/core/java/android/speech/tts/ITtsCallback.aidl +++ b/core/java/android/speech/tts/ITtsCallback.aidl @@ -23,5 +23,5 @@ package android.speech.tts; * {@hide} */ oneway interface ITtsCallback { - void markReached(String mark); + void utteranceCompleted(String utteranceId); } diff --git a/core/java/android/speech/tts/TextToSpeech.java b/core/java/android/speech/tts/TextToSpeech.java index 2369535..a2e70b8 100644..100755 --- a/core/java/android/speech/tts/TextToSpeech.java +++ b/core/java/android/speech/tts/TextToSpeech.java @@ -99,6 +99,18 @@ public class TextToSpeech { } /** + * Called when the TTS has completed saying something that has an utterance ID set. + * + * The OnUtteranceCompletedListener must implement the onUtteranceCompleted function. + * onUtteranceCompleted is passed a String that is the utteranceId given in + * the original speak call. + */ + public interface OnUtteranceCompletedListener {
+ public void onUtteranceCompleted(String utteranceId);
+ } + + + /** * Internal constants for the TTS functionality * * {@hide} @@ -147,6 +159,7 @@ public class TextToSpeech { private ServiceConnection mServiceConnection; private ITts mITts = null; + private ITtsCallback mITtscallback = null; private Context mContext = null; private String mPackageName = ""; private OnInitListener mInitListener = null; @@ -178,6 +191,7 @@ public class TextToSpeech { mCachedParams[Engine.TTS_PARAM_POSITION_COUNTRY] = Engine.TTS_KEY_PARAM_COUNTRY; mCachedParams[Engine.TTS_PARAM_POSITION_VARIANT] = Engine.TTS_KEY_PARAM_VARIANT; mCachedParams[Engine.TTS_PARAM_POSITION_STREAM] = Engine.TTS_KEY_PARAM_STREAM; + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = Engine.TTS_KEY_PARAM_UTTERANCE_ID; mCachedParams[Engine.TTS_PARAM_POSITION_RATE + 1] = String.valueOf(Engine.FALLBACK_TTS_DEFAULT_RATE); @@ -189,7 +203,7 @@ public class TextToSpeech { mCachedParams[Engine.TTS_PARAM_POSITION_STREAM + 1] = String.valueOf(Engine.TTS_DEFAULT_STREAM); - mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID+ 1] = ""; + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = ""; initTts(); } @@ -380,7 +394,7 @@ public class TextToSpeech { } extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); if (extra != null) { - mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra; + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra; } } result = mITts.speak(mPackageName, text, queueMode, mCachedParams); @@ -437,7 +451,7 @@ public class TextToSpeech { } extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); if (extra != null) { - mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra; + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra; } } result = mITts.playEarcon(mPackageName, earcon, queueMode, null); @@ -477,13 +491,19 @@ public class TextToSpeech { * * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. */ - public int playSilence(long durationInMs, int queueMode) { + public int playSilence(long durationInMs, int queueMode, HashMap<String,String> params) { synchronized (mStartLock) { int result = TTS_ERROR; if (!mStarted) { return result; } try { + if ((params != null) && (!params.isEmpty())) { + String extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); + if (extra != null) { + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra; + } + } result = mITts.playSilence(mPackageName, durationInMs, queueMode, mCachedParams); } catch (RemoteException e) { // TTS died; restart it. @@ -845,7 +865,7 @@ public class TextToSpeech { // no need to read the stream type here String extra = params.get(Engine.TTS_KEY_PARAM_UTTERANCE_ID); if (extra != null) { - mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID] = extra; + mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID + 1] = extra; } } if (mITts.synthesizeToFile(mPackageName, text, mCachedParams, filename)){ @@ -887,4 +907,52 @@ public class TextToSpeech { mCachedParams[Engine.TTS_PARAM_POSITION_UTTERANCE_ID+ 1] = ""; } + /** + * Sets the OnUtteranceCompletedListener that will fire when an utterance completes. + * + * @param listener + * The OnUtteranceCompletedListener + * + * @return Code indicating success or failure. See TTS_ERROR and TTS_SUCCESS. + */ + public int setOnUtteranceCompletedListener(
+ final OnUtteranceCompletedListener listener) {
+ synchronized (mStartLock) { + int result = TTS_ERROR; + if (!mStarted) { + return result; + } + mITtscallback = new ITtsCallback.Stub() { + public void utteranceCompleted(String utteranceId) throws RemoteException {
+ if (listener != null) {
+ listener.onUtteranceCompleted(utteranceId);
+ }
+ }
+ }; + try { + result = mITts.registerCallback(mPackageName, mITtscallback); + } catch (RemoteException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - registerCallback", "RemoteException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (NullPointerException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - registerCallback", "NullPointerException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } catch (IllegalStateException e) { + // TTS died; restart it. + Log.e("TextToSpeech.java - registerCallback", "IllegalStateException"); + e.printStackTrace(); + mStarted = false; + initTts(); + } finally { + return result; + } + }
+ } + } diff --git a/packages/TtsService/src/android/tts/TtsService.java b/packages/TtsService/src/android/tts/TtsService.java index 949dfae..09bb8f9 100755 --- a/packages/TtsService/src/android/tts/TtsService.java +++ b/packages/TtsService/src/android/tts/TtsService.java @@ -60,19 +60,19 @@ public class TtsService extends Service implements OnCompletionListener { public int mType = TEXT; public long mDuration = 0; public String mFilename = null; - public String callingApp = ""; + public String mCallingApp = ""; public SpeechItem(String source, String text, ArrayList<String> params, int itemType) { mText = text; mParams = params; mType = itemType; - callingApp = source; + mCallingApp = source; } public SpeechItem(String source, long silenceTime) { mDuration = silenceTime; mType = SILENCE; - callingApp = source; + mCallingApp = source; } public SpeechItem(String source, String text, ArrayList<String> params, int itemType, String filename) { @@ -80,7 +80,7 @@ public class TtsService extends Service implements OnCompletionListener { mParams = params; mType = itemType; mFilename = filename; - callingApp = source; + mCallingApp = source; } } @@ -117,7 +117,8 @@ public class TtsService extends Service implements OnCompletionListener { private static final String CATEGORY = "android.intent.category.TTS"; private static final String PKGNAME = "android.tts"; - final RemoteCallbackList<android.speech.tts.ITtsCallback> mCallbacks = new RemoteCallbackList<ITtsCallback>(); + private final RemoteCallbackList<android.speech.tts.ITtsCallback> mCallbacks = new RemoteCallbackList<ITtsCallback>(); + private HashMap<String, android.speech.tts.ITtsCallback> mCallbacksMap; private Boolean mIsSpeaking; private ArrayList<SpeechItem> mSpeechQueue; @@ -147,6 +148,7 @@ public class TtsService extends Service implements OnCompletionListener { mEarcons = new HashMap<String, SoundResource>(); mUtterances = new HashMap<String, SoundResource>(); + mCallbacksMap = new HashMap<String, android.speech.tts.ITtsCallback>(); mSpeechQueue = new ArrayList<SpeechItem>(); mPlayer = null; @@ -377,7 +379,7 @@ public class TtsService extends Service implements OnCompletionListener { if (speechQueueAvailable) { Log.i("TTS", "Stopping"); for (int i = mSpeechQueue.size() - 1; i > -1; i--){ - if (mSpeechQueue.get(i).callingApp.equals(callingApp)){ + if (mSpeechQueue.get(i).mCallingApp.equals(callingApp)){ mSpeechQueue.remove(i); } } @@ -439,11 +441,14 @@ public class TtsService extends Service implements OnCompletionListener { slnc.start(); } - private void speakInternalOnly(final String text, - final ArrayList<String> params) { + private void speakInternalOnly(final SpeechItem speechItem) { class SynthThread implements Runnable { public void run() { + String text = speechItem.mText; + ArrayList<String> params = speechItem.mParams; + String callingApp = speechItem.mCallingApp; boolean synthAvailable = false; + String utteranceId = ""; try { synthAvailable = synthesizerLock.tryLock(); if (!synthAvailable) { @@ -469,6 +474,8 @@ public class TtsService extends Service implements OnCompletionListener { country = params.get(i+1); } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_VARIANT)){ variant = params.get(i+1); + } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_UTTERANCE_ID)){ + utteranceId = params.get(i+1); } else if (param.equals(TextToSpeech.Engine.TTS_KEY_PARAM_STREAM)) { try { streamType = Integer.parseInt(params.get(i + 1)); @@ -493,6 +500,9 @@ public class TtsService extends Service implements OnCompletionListener { if (synthAvailable) { synthesizerLock.unlock(); } + if (utteranceId.length() > 0){ + dispatchUtteranceCompletedCallback(utteranceId, callingApp); + } processSpeechQueue(); } } @@ -577,17 +587,20 @@ public class TtsService extends Service implements OnCompletionListener { sendBroadcast(i); } - private void dispatchSpeechCompletedCallbacks(String mark) { + + private void dispatchUtteranceCompletedCallback(String utteranceId, String packageName) { + ITtsCallback cb = mCallbacksMap.get(packageName); + if (cb == null){ + return; + } Log.i("TTS callback", "dispatch started"); // Broadcast to all clients the new value. final int N = mCallbacks.beginBroadcast(); - for (int i = 0; i < N; i++) { - try { - mCallbacks.getBroadcastItem(i).markReached(mark); - } catch (RemoteException e) { - // The RemoteCallbackList will take care of removing - // the dead object for us. - } + try { + cb.utteranceCompleted(utteranceId); + } catch (RemoteException e) { + // The RemoteCallbackList will take care of removing + // the dead object for us. } mCallbacks.finishBroadcast(); Log.i("TTS callback", "dispatch completed to " + N); @@ -597,7 +610,7 @@ public class TtsService extends Service implements OnCompletionListener { if (currentSpeechItem.mText.length() < MAX_SPEECH_ITEM_CHAR_LENGTH){ return currentSpeechItem; } else { - String callingApp = currentSpeechItem.callingApp; + String callingApp = currentSpeechItem.mCallingApp; ArrayList<SpeechItem> splitItems = new ArrayList<SpeechItem>(); int start = 0; int end = start + MAX_SPEECH_ITEM_CHAR_LENGTH - 1; @@ -643,8 +656,7 @@ public class TtsService extends Service implements OnCompletionListener { if (sr == null) { if (currentSpeechItem.mType == SpeechItem.TEXT) { currentSpeechItem = splitCurrentTextIfNeeded(currentSpeechItem); - speakInternalOnly(currentSpeechItem.mText, - currentSpeechItem.mParams); + speakInternalOnly(currentSpeechItem); } else if (currentSpeechItem.mType == SpeechItem.TEXT_TO_FILE) { synthToFileInternalOnly(currentSpeechItem.mText, currentSpeechItem.mParams, currentSpeechItem.mFilename); @@ -775,14 +787,22 @@ public class TtsService extends Service implements OnCompletionListener { private final android.speech.tts.ITts.Stub mBinder = new Stub() { - public void registerCallback(ITtsCallback cb) { - if (cb != null) + public int registerCallback(String packageName, ITtsCallback cb) { + if (cb != null) { mCallbacks.register(cb); + mCallbacksMap.put(packageName, cb); + return TextToSpeech.TTS_SUCCESS; + } + return TextToSpeech.TTS_ERROR; } - public void unregisterCallback(ITtsCallback cb) { - if (cb != null) + public int unregisterCallback(String packageName, ITtsCallback cb) { + if (cb != null) { + mCallbacksMap.remove(packageName); mCallbacks.unregister(cb); + return TextToSpeech.TTS_SUCCESS; + } + return TextToSpeech.TTS_ERROR; } /** |