Merge change 4398 into donut
* changes: Using Locale to specify language and country for a TTS language to load, rather than a String. Cleanup in doc for TextToSpeech, and addition of queue mode constants.
This commit is contained in:
@@ -39,7 +39,7 @@ interface ITts {
|
|||||||
|
|
||||||
void addSpeechFile(in String text, in String filename);
|
void addSpeechFile(in String text, in String filename);
|
||||||
|
|
||||||
void setLanguage(in String language);
|
void setLanguage(in String language, in String country, in String variant);
|
||||||
|
|
||||||
boolean synthesizeToFile(in String text, in String[] params, in String outputDirectory);
|
boolean synthesizeToFile(in String text, in String[] params, in String outputDirectory);
|
||||||
|
|
||||||
|
|||||||
@@ -22,13 +22,12 @@ import android.content.ComponentName;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.content.pm.ResolveInfo;
|
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -36,7 +35,7 @@ import java.util.HashMap;
|
|||||||
*
|
*
|
||||||
* {@hide}
|
* {@hide}
|
||||||
*/
|
*/
|
||||||
//TODO #TTS# review + complete javadoc
|
//TODO #TTS# review + complete javadoc + add links to constants
|
||||||
public class TextToSpeech {
|
public class TextToSpeech {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -52,9 +51,18 @@ public class TextToSpeech {
|
|||||||
*/
|
*/
|
||||||
public static final int TTS_ERROR_MISSING_RESOURCE = -2;
|
public static final int TTS_ERROR_MISSING_RESOURCE = -2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue mode where all entries in the playback queue (media to be played
|
||||||
|
* and text to be synthesized) are dropped and replaced by the new entry.
|
||||||
|
*/
|
||||||
|
public static final int TTS_QUEUE_FLUSH = 0;
|
||||||
|
/**
|
||||||
|
* Queue mode where the new entry is added at the end of the playback queue.
|
||||||
|
*/
|
||||||
|
public static final int TTS_QUEUE_ADD = 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called when the TTS has initialized
|
* Called when the TTS has initialized.
|
||||||
*
|
*
|
||||||
* The InitListener must implement the onInit function. onInit is passed a
|
* The InitListener must implement the onInit function. onInit is passed a
|
||||||
* status code indicating the result of the TTS initialization.
|
* status code indicating the result of the TTS initialization.
|
||||||
@@ -73,9 +81,9 @@ public class TextToSpeech {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Connection needed for the TTS
|
* Connection needed for the TTS.
|
||||||
*/
|
*/
|
||||||
private ServiceConnection serviceConnection;
|
private ServiceConnection mServiceConnection;
|
||||||
|
|
||||||
private ITts mITts = null;
|
private ITts mITts = null;
|
||||||
private Context mContext = null;
|
private Context mContext = null;
|
||||||
@@ -104,8 +112,7 @@ public class TextToSpeech {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void setOnSpeechCompletedListener(
|
public void setOnSpeechCompletedListener(final OnSpeechCompletedListener listener) {
|
||||||
final OnSpeechCompletedListener listener) {
|
|
||||||
synchronized(mSpeechCompListenerLock) {
|
synchronized(mSpeechCompListenerLock) {
|
||||||
mSpeechCompListener = listener;
|
mSpeechCompListener = listener;
|
||||||
}
|
}
|
||||||
@@ -126,7 +133,7 @@ public class TextToSpeech {
|
|||||||
mStarted = 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() {
|
mServiceConnection = new ServiceConnection() {
|
||||||
public void onServiceConnected(ComponentName name, IBinder service) {
|
public void onServiceConnected(ComponentName name, IBinder service) {
|
||||||
synchronized(mStartLock) {
|
synchronized(mStartLock) {
|
||||||
mITts = ITts.Stub.asInterface(service);
|
mITts = ITts.Stub.asInterface(service);
|
||||||
@@ -176,7 +183,7 @@ public class TextToSpeech {
|
|||||||
|
|
||||||
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");
|
||||||
mContext.bindService(intent, serviceConnection,
|
mContext.bindService(intent, mServiceConnection,
|
||||||
Context.BIND_AUTO_CREATE);
|
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
|
||||||
@@ -190,7 +197,7 @@ public class TextToSpeech {
|
|||||||
*/
|
*/
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
try {
|
try {
|
||||||
mContext.unbindService(serviceConnection);
|
mContext.unbindService(mServiceConnection);
|
||||||
} 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.
|
||||||
@@ -291,8 +298,8 @@ public class TextToSpeech {
|
|||||||
* @param text
|
* @param text
|
||||||
* The string of text to be spoken.
|
* The string of text to be spoken.
|
||||||
* @param queueMode
|
* @param queueMode
|
||||||
* The queuing strategy to use. Use 0 for no queuing, and 1 for
|
* The queuing strategy to use.
|
||||||
* queuing.
|
* See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
|
||||||
* @param params
|
* @param params
|
||||||
* The hashmap of speech parameters to be used.
|
* The hashmap of speech parameters to be used.
|
||||||
*/
|
*/
|
||||||
@@ -329,8 +336,7 @@ public class TextToSpeech {
|
|||||||
* @param earcon
|
* @param earcon
|
||||||
* The earcon that should be played
|
* The earcon that should be played
|
||||||
* @param queueMode
|
* @param queueMode
|
||||||
* 0 for no queue (interrupts all previous utterances), 1 for
|
* See TTS_QUEUE_ADD and TTS_QUEUE_FLUSH.
|
||||||
* queued
|
|
||||||
* @param params
|
* @param params
|
||||||
* The hashmap of parameters to be used.
|
* The hashmap of parameters to be used.
|
||||||
*/
|
*/
|
||||||
@@ -429,20 +435,22 @@ public class TextToSpeech {
|
|||||||
* Note that the speech rate is not universally supported by all engines and
|
* Note that the speech rate is not universally supported by all engines and
|
||||||
* will be treated as a hint. The TTS library will try to use the specified
|
* will be treated as a hint. The TTS library will try to use the specified
|
||||||
* speech rate, but there is no guarantee.
|
* speech rate, but there is no guarantee.
|
||||||
*
|
* This has no effect on any pre-recorded speech.
|
||||||
* Currently, this will change the speech rate for the espeak engine, but it
|
|
||||||
* has no effect on any pre-recorded speech.
|
|
||||||
*
|
*
|
||||||
* @param speechRate
|
* @param speechRate
|
||||||
* The speech rate for the TTS engine.
|
* The speech rate for the TTS engine. 1 is the normal speed,
|
||||||
|
* lower values slow down the speech (0.5 is half the normal speech rate),
|
||||||
|
* greater values accelerate it (2 is twice the normal speech rate).
|
||||||
*/
|
*/
|
||||||
public void setSpeechRate(int speechRate) {
|
public void setSpeechRate(float speechRate) {
|
||||||
synchronized (mStartLock) {
|
synchronized (mStartLock) {
|
||||||
if (!mStarted) {
|
if (!mStarted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mITts.setSpeechRate(speechRate);
|
if (speechRate > 0) {
|
||||||
|
mITts.setSpeechRate((int)(speechRate*100));
|
||||||
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// TTS died; restart it.
|
// TTS died; restart it.
|
||||||
mStarted = false;
|
mStarted = false;
|
||||||
@@ -457,24 +465,18 @@ public class TextToSpeech {
|
|||||||
*
|
*
|
||||||
* Note that the language is not universally supported by all engines and
|
* Note that the language is not universally supported by all engines and
|
||||||
* will be treated as a hint. The TTS library will try to use the specified
|
* will be treated as a hint. The TTS library will try to use the specified
|
||||||
* language, but there is no guarantee.
|
* language as represented by the Locale, but there is no guarantee.
|
||||||
*
|
*
|
||||||
* Currently, this will change the language for the espeak engine, but it
|
* @param loc
|
||||||
* has no effect on any pre-recorded speech.
|
* The locale describing the language to be used.
|
||||||
*
|
|
||||||
* @param language
|
|
||||||
* The language to be used. The languages are specified by their
|
|
||||||
* IETF language tags as defined by BCP 47. This is the same
|
|
||||||
* standard used for the lang attribute in HTML. See:
|
|
||||||
* http://en.wikipedia.org/wiki/IETF_language_tag
|
|
||||||
*/
|
*/
|
||||||
public void setLanguage(String language) {
|
public void setLanguage(Locale loc) {
|
||||||
synchronized (mStartLock) {
|
synchronized (mStartLock) {
|
||||||
if (!mStarted) {
|
if (!mStarted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
mITts.setLanguage(language);
|
mITts.setLanguage(loc.getISO3Language(), loc.getISO3Country(), loc.getVariant());
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
// TTS died; restart it.
|
// TTS died; restart it.
|
||||||
mStarted = false;
|
mStarted = false;
|
||||||
|
|||||||
@@ -269,10 +269,10 @@ android_tts_SynthProxy_native_finalize(JNIEnv *env, jobject thiz, jint jniData)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO update to use language, country, variant
|
|
||||||
static void
|
static void
|
||||||
android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData,
|
android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData,
|
||||||
jstring language)
|
jstring language, jstring country, jstring variant)
|
||||||
{
|
{
|
||||||
if (jniData == 0) {
|
if (jniData == 0) {
|
||||||
LOGE("android_tts_SynthProxy_setLanguage(): invalid JNI data");
|
LOGE("android_tts_SynthProxy_setLanguage(): invalid JNI data");
|
||||||
@@ -281,14 +281,16 @@ android_tts_SynthProxy_setLanguage(JNIEnv *env, jobject thiz, jint jniData,
|
|||||||
|
|
||||||
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
|
SynthProxyJniStorage* pSynthData = (SynthProxyJniStorage*)jniData;
|
||||||
const char *langNativeString = env->GetStringUTFChars(language, 0);
|
const char *langNativeString = env->GetStringUTFChars(language, 0);
|
||||||
|
const char *countryNativeString = env->GetStringUTFChars(country, 0);
|
||||||
|
const char *variantNativeString = env->GetStringUTFChars(variant, 0);
|
||||||
// TODO check return codes
|
// TODO check return codes
|
||||||
if (pSynthData->mNativeSynthInterface) {
|
if (pSynthData->mNativeSynthInterface) {
|
||||||
// TODO update to use language, country, variant
|
pSynthData->mNativeSynthInterface->setLanguage(langNativeString, countryNativeString,
|
||||||
// commented out to not break the build
|
variantNativeString);
|
||||||
//pSynthData->mNativeSynthInterface->setLanguage(langNativeString,
|
|
||||||
// strlen(langNativeString));
|
|
||||||
}
|
}
|
||||||
env->ReleaseStringUTFChars(language, langNativeString);
|
env->ReleaseStringUTFChars(language, langNativeString);
|
||||||
|
env->ReleaseStringUTFChars(language, countryNativeString);
|
||||||
|
env->ReleaseStringUTFChars(language, variantNativeString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -496,6 +498,7 @@ android_tts_SynthProxy_getLanguage(JNIEnv *env, jobject thiz, jint jniData)
|
|||||||
return env->NewStringUTF(buf);
|
return env->NewStringUTF(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
JNIEXPORT int JNICALL
|
JNIEXPORT int JNICALL
|
||||||
android_tts_SynthProxy_getRate(JNIEnv *env, jobject thiz, jint jniData)
|
android_tts_SynthProxy_getRate(JNIEnv *env, jobject thiz, jint jniData)
|
||||||
{
|
{
|
||||||
@@ -531,7 +534,7 @@ static JNINativeMethod gMethods[] = {
|
|||||||
(void*)android_tts_SynthProxy_synthesizeToFile
|
(void*)android_tts_SynthProxy_synthesizeToFile
|
||||||
},
|
},
|
||||||
{ "native_setLanguage",
|
{ "native_setLanguage",
|
||||||
"(ILjava/lang/String;)V",
|
"(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;)V",
|
||||||
(void*)android_tts_SynthProxy_setLanguage
|
(void*)android_tts_SynthProxy_setLanguage
|
||||||
},
|
},
|
||||||
{ "native_setSpeechRate",
|
{ "native_setSpeechRate",
|
||||||
@@ -567,7 +570,6 @@ static JNINativeMethod gMethods[] = {
|
|||||||
#define SP_JNIDATA_FIELD_NAME "mJniData"
|
#define SP_JNIDATA_FIELD_NAME "mJniData"
|
||||||
#define SP_POSTSPEECHSYNTHESIZED_METHOD_NAME "postNativeSpeechSynthesizedInJava"
|
#define SP_POSTSPEECHSYNTHESIZED_METHOD_NAME "postNativeSpeechSynthesizedInJava"
|
||||||
|
|
||||||
// TODO: verify this is the correct path
|
|
||||||
static const char* const kClassPathName = "android/tts/SynthProxy";
|
static const char* const kClassPathName = "android/tts/SynthProxy";
|
||||||
|
|
||||||
jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
jint JNI_OnLoad(JavaVM* vm, void* reserved)
|
||||||
|
|||||||
@@ -70,8 +70,8 @@ public class SynthProxy {
|
|||||||
/**
|
/**
|
||||||
* Sets the language
|
* Sets the language
|
||||||
*/
|
*/
|
||||||
public void setLanguage(String language) {
|
public void setLanguage(String language, String country, String variant) {
|
||||||
native_setLanguage(mJniData, language);
|
native_setLanguage(mJniData, language, country, variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -141,7 +141,8 @@ public class SynthProxy {
|
|||||||
|
|
||||||
private native final void native_synthesizeToFile(int jniData, String text, String filename);
|
private native final void native_synthesizeToFile(int jniData, String text, String filename);
|
||||||
|
|
||||||
private native final void native_setLanguage(int jniData, String language);
|
private native final void native_setLanguage(int jniData, String language, String country,
|
||||||
|
String variant);
|
||||||
|
|
||||||
private native final void native_setSpeechRate(int jniData, int speechRate);
|
private native final void native_setSpeechRate(int jniData, int speechRate);
|
||||||
|
|
||||||
|
|||||||
@@ -129,7 +129,9 @@ public class TtsService extends Service implements OnCompletionListener {
|
|||||||
mSpeechQueue = new ArrayList<SpeechItem>();
|
mSpeechQueue = new ArrayList<SpeechItem>();
|
||||||
mPlayer = null;
|
mPlayer = null;
|
||||||
|
|
||||||
setLanguage(prefs.getString("lang_pref", "en-rUS"));
|
// TODO set default settings
|
||||||
|
//setLanguage(prefs.getString("lang_pref", "en-rUS"));
|
||||||
|
setLanguage("eng", "USA", "");
|
||||||
setSpeechRate(Integer.parseInt(prefs.getString("rate_pref", "140")));
|
setSpeechRate(Integer.parseInt(prefs.getString("rate_pref", "140")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,7 +157,7 @@ public class TtsService extends Service implements OnCompletionListener {
|
|||||||
nativeSynth.setSpeechRate(rate);
|
nativeSynth.setSpeechRate(rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setLanguage(String lang) {
|
private void setLanguage(String lang, String country, String variant) {
|
||||||
if (prefs.getBoolean("override_pref", false)) {
|
if (prefs.getBoolean("override_pref", false)) {
|
||||||
// This is set to the default here so that the preview in the prefs
|
// This is set to the default here so that the preview in the prefs
|
||||||
// activity will show the change without a restart, even if apps are
|
// activity will show the change without a restart, even if apps are
|
||||||
@@ -163,7 +165,8 @@ public class TtsService extends Service implements OnCompletionListener {
|
|||||||
// allowed to change the defaults.
|
// allowed to change the defaults.
|
||||||
lang = prefs.getString("lang_pref", "en-rUS");
|
lang = prefs.getString("lang_pref", "en-rUS");
|
||||||
}
|
}
|
||||||
nativeSynth.setLanguage(lang);
|
Log.v("TTS", "TtsService.setLanguage("+lang+", "+country+", "+variant+")");
|
||||||
|
nativeSynth.setLanguage(lang, country, variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -683,20 +686,14 @@ public class TtsService extends Service implements OnCompletionListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the speech rate for the TTS. Note that this will only have an
|
* Sets the speech rate for the TTS, which affects the synthesized voice.
|
||||||
* effect on synthesized speech; it will not affect pre-recorded speech.
|
|
||||||
*
|
*
|
||||||
* @param language
|
* @param lang the three letter ISO language code.
|
||||||
* Language values are based on the Android conventions for
|
* @param country the three letter ISO country code.
|
||||||
* localization as described in the Android platform
|
* @param variant the variant code associated with the country and language pair.
|
||||||
* documentation on internationalization. This implies that
|
|
||||||
* language data is specified in the format xx-rYY, where xx
|
|
||||||
* is a two letter ISO 639-1 language code in lowercase and
|
|
||||||
* rYY is a two letter ISO 3166-1-alpha-2 language code in
|
|
||||||
* uppercase preceded by a lowercase "r".
|
|
||||||
*/
|
*/
|
||||||
public void setLanguage(String language) {
|
public void setLanguage(String lang, String country, String variant) {
|
||||||
mSelf.setLanguage(language);
|
mSelf.setLanguage(lang, country, variant);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user