AI2 Component  (Version nb184)
InternalTextToSpeech.java
Go to the documentation of this file.
1 // -*- mode: java; c-basic-offset: 2; -*-
2 // Copyright 2009-2011 Google, All Rights reserved
3 // Copyright 2011-2012 MIT, All rights reserved
4 // Released under the Apache License, Version 2.0
5 // http://www.apache.org/licenses/LICENSE-2.0
6 package com.google.appinventor.components.runtime.util;
7 
8 import android.app.Activity;
9 import android.content.Intent;
10 import android.speech.tts.TextToSpeech;
11 
12 import java.util.ArrayList;
13 import java.util.HashMap;
14 import java.util.Locale;
15 
16 import android.util.Log;
17 
18 import android.os.Handler;
19 
34 public class InternalTextToSpeech implements ITextToSpeech {
35 
36  private static final String LOG_TAG = "InternalTTS";
37 
38  private final Activity activity;
39  private final TextToSpeechCallback callback;
40  private TextToSpeech tts;
41  private volatile boolean isTtsInitialized;
42 
43  private Handler mHandler = new Handler();
44 
45  private int nextUtteranceId = 1;
46 
47  // time (ms) to delay before retrying speak when tts not yet initialized
48  private int ttsRetryDelay = 500;
49 
50  // max number of retries waiting for initialization before speak fails
51  // This is very long, but it's better to get a long delay than simply have
52  // no speech in the case of initialization slowness
53  private int ttsMaxRetries = 20;
54 
55  public InternalTextToSpeech(Activity activity, TextToSpeechCallback callback) {
56  this.activity = activity;
57  this.callback = callback;
58  initializeTts();
59  }
60 
61  private void initializeTts() {
62  if (tts == null) {
63  Log.d(LOG_TAG, "INTERNAL TTS is reinitializing");
64  tts = new TextToSpeech(activity, new TextToSpeech.OnInitListener() {
65  @Override
66  public void onInit(int status) {
67  if (status == TextToSpeech.SUCCESS) {
68  isTtsInitialized = true;
69  }
70  }
71  });
72  }
73  }
74 
75  @Override
76  public void speak(final String message, final Locale loc) {
77  Log.d(LOG_TAG, "Internal TTS got speak");
78  speak(message, loc, 0);
79  }
80 
81  public boolean isInitialized() {
82  return isTtsInitialized;
83  }
84 
85 
86  private void speak(final String message, final Locale loc, final int retries) {
87  Log.d(LOG_TAG, "InternalTTS speak called, message = " + message);
88  if (retries > ttsMaxRetries) {
89  Log.d(LOG_TAG, "max number of speak retries exceeded: speak will fail");
90  callback.onFailure();
91  }
92  // If speak was called before initialization was complete, we retry after a delay.
93  // Keep track of the number of retries and fail if there are too many.
94  if (isTtsInitialized) {
95  Log.d(LOG_TAG, "TTS initialized after " + retries + " retries.");
96  tts.setLanguage(loc);
97  tts.setOnUtteranceCompletedListener(
98  new TextToSpeech.OnUtteranceCompletedListener() {
99  @Override
100  public void onUtteranceCompleted(String utteranceId) {
101  // onUtteranceCompleted is not called on the UI thread, so we use
102  // Activity.runOnUiThread() to call callback.onSuccess().
103  activity.runOnUiThread(new Runnable() {
104  public void run() {
105  callback.onSuccess();
106  }
107  });
108  }
109  });
110  // We need to provide an utterance id. Otherwise onUtteranceCompleted won't be called.
111  HashMap<String, String> params = new HashMap<String, String>();
112  params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, Integer.toString(nextUtteranceId++));
113  int result = tts.speak(message, tts.QUEUE_FLUSH, params);
114  if (result == TextToSpeech.ERROR) {
115  Log.d(LOG_TAG, "speak called and tts.speak result was an error");
116  callback.onFailure();
117  }
118  } else {
119  Log.d(LOG_TAG, "speak called when TTS not initialized");
120  mHandler.postDelayed(new Runnable() {
121  public void run() {
122  Log.d(LOG_TAG,
123  "delaying call to speak. Retries is: " + retries + " Message is: " + message);
124  speak(message, loc, retries + 1);
125  }
126  }, ttsRetryDelay);
127  }
128  }
129 
130  @Override
131  public void onStop() {
132  Log.d(LOG_TAG, "Internal TTS got onStop");
133  // do nothing. Resources will be cleaned up in onDestroy
134  }
135 
136  @Override
137  public void onDestroy() {
138  Log.d(LOG_TAG, "Internal TTS got onDestroy");
139  if (tts != null) {
140  tts.shutdown();
141  isTtsInitialized = false;
142  tts = null;
143  }
144  }
145 
146  @Override
147  public void onResume() {
148  Log.d(LOG_TAG, "Internal TTS got onResume");
149  initializeTts();
150  }
151 
152  @Override
153  public void setPitch(float pitch) {
154  tts.setPitch(pitch);
155  }
156 
157  @Override
158  public void setSpeechRate(float speechRate) {
159  tts.setSpeechRate(speechRate);
160  }
161 
162  // This is for use by the higher level TextToSpeech component
163  public int isLanguageAvailable(Locale loc) {
164  return tts.isLanguageAvailable(loc);
165  }
166 
167 }
168 
com.google.appinventor.components.runtime.util.InternalTextToSpeech.speak
void speak(final String message, final Locale loc)
Definition: InternalTextToSpeech.java:76
com.google.appinventor.components.runtime.util.InternalTextToSpeech.onResume
void onResume()
Definition: InternalTextToSpeech.java:147
com.google.appinventor.components.runtime.util.InternalTextToSpeech.InternalTextToSpeech
InternalTextToSpeech(Activity activity, TextToSpeechCallback callback)
Definition: InternalTextToSpeech.java:55
com.google.appinventor.components.runtime.util.ITextToSpeech.TextToSpeechCallback
Definition: ITextToSpeech.java:24
com.google.appinventor.components.runtime.util.InternalTextToSpeech.onStop
void onStop()
Definition: InternalTextToSpeech.java:131
com.google.appinventor.components.runtime.util.InternalTextToSpeech.isInitialized
boolean isInitialized()
Definition: InternalTextToSpeech.java:81
com.google.appinventor.components.runtime.util.ITextToSpeech
Definition: ITextToSpeech.java:19
com.google.appinventor.components.runtime.util.InternalTextToSpeech.setSpeechRate
void setSpeechRate(float speechRate)
Definition: InternalTextToSpeech.java:158
com.google.appinventor.components.runtime.util.InternalTextToSpeech.onDestroy
void onDestroy()
Definition: InternalTextToSpeech.java:137
com.google.appinventor.components.runtime.util.InternalTextToSpeech.setPitch
void setPitch(float pitch)
Definition: InternalTextToSpeech.java:153
com.google.appinventor.components.runtime.util.ITextToSpeech.TextToSpeechCallback.onFailure
void onFailure()
com.google.appinventor.components.runtime.TextToSpeech
Definition: TextToSpeech.java:71
com.google.appinventor.components.runtime.util.InternalTextToSpeech.isLanguageAvailable
int isLanguageAvailable(Locale loc)
Definition: InternalTextToSpeech.java:163
com.google.appinventor.components.runtime.util.ITextToSpeech.TextToSpeechCallback.onSuccess
void onSuccess()
com.google.appinventor.components.runtime.util.InternalTextToSpeech
Definition: InternalTextToSpeech.java:34