Merge change 3949 into donut

* changes:
  TextToSpeech class cleanups - harmonized private member variable names - added success / failure codes (used for now in initialization) - synchronized access to speech completed listener.
This commit is contained in:
Android (Google) Code Review
2009-06-11 15:07:58 -07:00

View File

@@ -39,17 +39,28 @@ import java.util.HashMap;
//TODO #TTS# review + complete javadoc //TODO #TTS# review + complete javadoc
public class TextToSpeech { public class TextToSpeech {
/**
* Denotes a successful operation.
*/
public static final int TTS_SUCCESS = 0;
/**
* Denotes a generic operation failure.
*/
public static final int TTS_ERROR = -1;
/**
* Denotes a failure due to a missing resource.
*/
public static final int TTS_ERROR_MISSING_RESOURCE = -2;
/** /**
* Called when the TTS has initialized * Called when the TTS has initialized
* *
* The InitListener must implement the onInit function. onInit is passed the * The InitListener must implement the onInit function. onInit is passed a
* version number of the TTS library that the user has installed; since this * status code indicating the result of the TTS initialization.
* is called when the TTS has started, it is a good time to make sure that
* the user's TTS library is up to date.
*/ */
public interface OnInitListener { public interface OnInitListener {
public void onInit(int version); public void onInit(int status);
} }
/** /**
@@ -66,15 +77,14 @@ public class TextToSpeech {
*/ */
private ServiceConnection serviceConnection; private ServiceConnection serviceConnection;
private ITts itts = null; private ITts mITts = null;
private Context ctx = null; private Context mContext = null;
private OnInitListener cb = null; private OnInitListener mInitListener = null;
private int version = -1; private boolean mStarted = false;
private boolean started = false; private final Object mStartLock = new Object();
private final Object startLock = new Object(); private ITtsCallback mITtsCallback;
private boolean showInstaller = false; private OnSpeechCompletedListener mSpeechCompListener = null;
private ITtsCallback ittscallback; private final Object mSpeechCompListenerLock = new Object();
private OnSpeechCompletedListener speechCompletedCallback = null;
@@ -83,23 +93,22 @@ public class TextToSpeech {
* *
* @param context * @param context
* The context * The context
* @param callback * @param listener
* The InitListener that should be called when the TTS has * The InitListener that will be called when the TTS has
* initialized successfully. * initialized successfully.
*/ */
public TextToSpeech(Context context, OnInitListener callback) { public TextToSpeech(Context context, OnInitListener listener) {
// TODO #TTS# support TtsVersionAlert mContext = context;
// showInstaller = true; mInitListener = listener;
// versionAlert = alert;
ctx = context;
cb = callback;
initTts(); initTts();
} }
public void setOnSpeechCompletedListener( public void setOnSpeechCompletedListener(
final OnSpeechCompletedListener listener) { final OnSpeechCompletedListener listener) {
speechCompletedCallback = listener; synchronized(mSpeechCompListenerLock) {
mSpeechCompListener = listener;
}
} }
@@ -114,54 +123,61 @@ public class TextToSpeech {
private void initTts() { private void initTts() {
started = false; mStarted = false;
// Initialize the TTS, run the callback after the binding is successful // Initialize the TTS, run the callback after the binding is successful
serviceConnection = new ServiceConnection() { serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName name, IBinder service) { public void onServiceConnected(ComponentName name, IBinder service) {
synchronized(startLock) { synchronized(mStartLock) {
itts = ITts.Stub.asInterface(service); mITts = ITts.Stub.asInterface(service);
try { try {
ittscallback = new ITtsCallback.Stub() { mITtsCallback = new ITtsCallback.Stub() {
//@Override
public void markReached(String mark) public void markReached(String mark)
throws RemoteException { throws RemoteException {
if (speechCompletedCallback != null) { // call the listener of that event, but not
speechCompletedCallback.onSpeechCompleted(); // while locked.
OnSpeechCompletedListener listener = null;
synchronized(mSpeechCompListenerLock) {
listener = mSpeechCompListener;
}
if (listener != null) {
listener.onSpeechCompleted();
} }
} }
}; };
itts.registerCallback(ittscallback); mITts.registerCallback(mITtsCallback);
} catch (RemoteException e) { } catch (RemoteException e) {
initTts(); initTts();
return; return;
} }
started = true; mStarted = true;
// The callback can become null if the Android OS decides to // The callback can become null if the Android OS decides to
// restart the TTS process as well as whatever is using it. // restart the TTS process as well as whatever is using it.
// In such cases, do nothing - the error handling from the // In such cases, do nothing - the error handling from the
// speaking calls will kick in and force a proper restart of // speaking calls will kick in and force a proper restart of
// the TTS. // the TTS.
if (cb != null) { if (mInitListener != null) {
cb.onInit(version); // TODO manage failures and missing resources
mInitListener.onInit(TTS_SUCCESS);
} }
} }
} }
public void onServiceDisconnected(ComponentName name) { public void onServiceDisconnected(ComponentName name) {
synchronized(startLock) { synchronized(mStartLock) {
itts = null; mITts = null;
cb = null; mInitListener = null;
started = false; mStarted = false;
} }
} }
}; };
Intent intent = new Intent("android.intent.action.USE_TTS"); Intent intent = new Intent("android.intent.action.USE_TTS");
intent.addCategory("android.intent.category.TTS"); intent.addCategory("android.intent.category.TTS");
ctx.bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); mContext.bindService(intent, serviceConnection,
Context.BIND_AUTO_CREATE);
// TODO handle case where the binding works (should always work) but // TODO handle case where the binding works (should always work) but
// the plugin fails // the plugin fails
} }
@@ -174,7 +190,7 @@ public class TextToSpeech {
*/ */
public void shutdown() { public void shutdown() {
try { try {
ctx.unbindService(serviceConnection); mContext.unbindService(serviceConnection);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
// Do nothing and fail silently since an error here indicates that // Do nothing and fail silently since an error here indicates that
// binding never succeeded in the first place. // binding never succeeded in the first place.
@@ -208,23 +224,23 @@ public class TextToSpeech {
* Example: <b><code>R.raw.south_south_east</code></b> * Example: <b><code>R.raw.south_south_east</code></b>
*/ */
public void addSpeech(String text, String packagename, int resourceId) { public void addSpeech(String text, String packagename, int resourceId) {
synchronized(startLock) { synchronized(mStartLock) {
if (!started) { if (!mStarted) {
return; return;
} }
try { try {
itts.addSpeech(text, packagename, resourceId); mITts.addSpeech(text, packagename, resourceId);
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (NullPointerException e) { } catch (NullPointerException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
} }
@@ -242,23 +258,23 @@ public class TextToSpeech {
* "/sdcard/mysounds/hello.wav") * "/sdcard/mysounds/hello.wav")
*/ */
public void addSpeech(String text, String filename) { public void addSpeech(String text, String filename) {
synchronized (startLock) { synchronized (mStartLock) {
if (!started) { if (!mStarted) {
return; return;
} }
try { try {
itts.addSpeechFile(text, filename); mITts.addSpeechFile(text, filename);
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (NullPointerException e) { } catch (NullPointerException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
} }
@@ -282,25 +298,25 @@ public class TextToSpeech {
*/ */
public void speak(String text, int queueMode, HashMap<String,String> params) public void speak(String text, int queueMode, HashMap<String,String> params)
{ {
synchronized (startLock) { synchronized (mStartLock) {
Log.i("TTS received: ", text); Log.i("TTS received: ", text);
if (!started) { if (!mStarted) {
return; return;
} }
try { try {
// TODO support extra parameters, passing null for the moment // TODO support extra parameters, passing null for the moment
itts.speak(text, queueMode, null); mITts.speak(text, queueMode, null);
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (NullPointerException e) { } catch (NullPointerException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
} }
@@ -320,24 +336,24 @@ public class TextToSpeech {
*/ */
public void playEarcon(String earcon, int queueMode, public void playEarcon(String earcon, int queueMode,
HashMap<String,String> params) { HashMap<String,String> params) {
synchronized (startLock) { synchronized (mStartLock) {
if (!started) { if (!mStarted) {
return; return;
} }
try { try {
// TODO support extra parameters, passing null for the moment // TODO support extra parameters, passing null for the moment
itts.playEarcon(earcon, queueMode, null); mITts.playEarcon(earcon, queueMode, null);
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (NullPointerException e) { } catch (NullPointerException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
} }
@@ -355,23 +371,23 @@ public class TextToSpeech {
* @return Whether or not the TTS is busy speaking. * @return Whether or not the TTS is busy speaking.
*/ */
public boolean isSpeaking() { public boolean isSpeaking() {
synchronized (startLock) { synchronized (mStartLock) {
if (!started) { if (!mStarted) {
return false; return false;
} }
try { try {
return itts.isSpeaking(); return mITts.isSpeaking();
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (NullPointerException e) { } catch (NullPointerException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
return false; return false;
@@ -383,23 +399,23 @@ public class TextToSpeech {
* Stops speech from the TTS. * Stops speech from the TTS.
*/ */
public void stop() { public void stop() {
synchronized (startLock) { synchronized (mStartLock) {
if (!started) { if (!mStarted) {
return; return;
} }
try { try {
itts.stop(); mITts.stop();
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (NullPointerException e) { } catch (NullPointerException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
} }
@@ -421,15 +437,15 @@ public class TextToSpeech {
* The speech rate for the TTS engine. * The speech rate for the TTS engine.
*/ */
public void setSpeechRate(int speechRate) { public void setSpeechRate(int speechRate) {
synchronized (startLock) { synchronized (mStartLock) {
if (!started) { if (!mStarted) {
return; return;
} }
try { try {
itts.setSpeechRate(speechRate); mITts.setSpeechRate(speechRate);
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
} }
@@ -453,15 +469,15 @@ public class TextToSpeech {
* http://en.wikipedia.org/wiki/IETF_language_tag * http://en.wikipedia.org/wiki/IETF_language_tag
*/ */
public void setLanguage(String language) { public void setLanguage(String language) {
synchronized (startLock) { synchronized (mStartLock) {
if (!started) { if (!mStarted) {
return; return;
} }
try { try {
itts.setLanguage(language); mITts.setLanguage(language);
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
} }
@@ -482,24 +498,24 @@ public class TextToSpeech {
*/ */
public boolean synthesizeToFile(String text, HashMap<String,String> params, public boolean synthesizeToFile(String text, HashMap<String,String> params,
String filename) { String filename) {
synchronized (startLock) { synchronized (mStartLock) {
if (!started) { if (!mStarted) {
return false; return false;
} }
try { try {
// TODO support extra parameters, passing null for the moment // TODO support extra parameters, passing null for the moment
return itts.synthesizeToFile(text, null, filename); return mITts.synthesizeToFile(text, null, filename);
} catch (RemoteException e) { } catch (RemoteException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (NullPointerException e) { } catch (NullPointerException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
// TTS died; restart it. // TTS died; restart it.
started = false; mStarted = false;
initTts(); initTts();
} }
return false; return false;