Merge pull request #5912 from osmandapp/js_voice_routing
JS TTS refactoring
This commit is contained in:
commit
3dc93e3c15
5 changed files with 41 additions and 469 deletions
|
@ -588,11 +588,12 @@ public class AppInitializer implements IProgress {
|
|||
boolean useJs = app.getSettings().USE_JS_VOICE_GUIDANCE.get();
|
||||
if (useJs && JSTTSCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return new JSTTSCommandPlayerImpl(ctx, applicationMode, osmandApplication.getRoutingHelper().getVoiceRouter(), voiceProvider);
|
||||
} else if (MediaCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return useJs && JSMediaCommandPlayerImpl.isMyData(voiceDir) ? new JSMediaCommandPlayerImpl(osmandApplication, applicationMode, osmandApplication.getRoutingHelper().getVoiceRouter(), voiceProvider)
|
||||
: new MediaCommandPlayerImpl(osmandApplication, applicationMode, osmandApplication.getRoutingHelper().getVoiceRouter(), voiceProvider);
|
||||
} else if (useJs && JSMediaCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return new JSMediaCommandPlayerImpl(osmandApplication, applicationMode, osmandApplication.getRoutingHelper().getVoiceRouter(), voiceProvider);
|
||||
} else if (TTSCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return new TTSCommandPlayerImpl(ctx, applicationMode, osmandApplication.getRoutingHelper().getVoiceRouter(), voiceProvider);
|
||||
} else if (MediaCommandPlayerImpl.isMyData((voiceDir))) {
|
||||
return new MediaCommandPlayerImpl(osmandApplication, applicationMode, osmandApplication.getRoutingHelper().getVoiceRouter(), voiceProvider);
|
||||
}
|
||||
throw new CommandPlayerException(ctx.getString(R.string.voice_data_not_supported));
|
||||
}
|
||||
|
|
|
@ -1,164 +0,0 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
import net.osmand.StateChangedListener;
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.api.AudioFocusHelper;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import alice.tuprolog.InvalidLibraryException;
|
||||
import alice.tuprolog.Prolog;
|
||||
import alice.tuprolog.Struct;
|
||||
import alice.tuprolog.Term;
|
||||
import alice.tuprolog.Var;
|
||||
|
||||
public abstract class AbstractJSCommandPlayer implements CommandPlayer, StateChangedListener<ApplicationMode> {
|
||||
private static final Log log = PlatformUtil.getLog(AbstractJSCommandPlayer.class);
|
||||
|
||||
protected String language = "";
|
||||
protected OsmandApplication ctx;
|
||||
protected int streamType;
|
||||
private ApplicationMode applicationMode;
|
||||
|
||||
public static boolean btScoStatus = false;
|
||||
private static AudioFocusHelper mAudioFocusHelper;
|
||||
public static String btScoInit = "";
|
||||
|
||||
protected AbstractJSCommandPlayer(OsmandApplication ctx, ApplicationMode applicationMode,
|
||||
String voiceProvider) {
|
||||
this.ctx = ctx;
|
||||
this.applicationMode = applicationMode;
|
||||
long time = System.currentTimeMillis();
|
||||
this.ctx = ctx;
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing prolog system : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
|
||||
}
|
||||
this.streamType = ctx.getSettings().AUDIO_STREAM_GUIDANCE.getModeValue(applicationMode);
|
||||
language = voiceProvider.substring(0, voiceProvider.indexOf("-tts"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentVoice() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandBuilder newCommandBuilder() {
|
||||
JSCommandBuilder commandBuilder = new JSCommandBuilder(this);
|
||||
commandBuilder.setParameters("km-m", true);
|
||||
return commandBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playCommands(CommandBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
if(ctx != null && ctx.getSettings() != null) {
|
||||
ctx.getSettings().APPLICATION_MODE.removeListener(this);
|
||||
}
|
||||
abandonAudioFocus();
|
||||
ctx = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> execute(List<Struct> listStruct) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAudioStream(int streamType) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return "en";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsStructuredStreetNames() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
|
||||
protected synchronized void abandonAudioFocus() {
|
||||
log.debug("abandonAudioFocus");
|
||||
if ((ctx != null && ctx.getSettings().AUDIO_STREAM_GUIDANCE.getModeValue(applicationMode) == 0) || (btScoStatus == true)) {
|
||||
toggleBtSco(false);
|
||||
}
|
||||
if (ctx != null && mAudioFocusHelper != null) {
|
||||
mAudioFocusHelper.abandonFocus(ctx, applicationMode, streamType);
|
||||
}
|
||||
mAudioFocusHelper = null;
|
||||
}
|
||||
|
||||
private synchronized boolean toggleBtSco(boolean on) {
|
||||
// Hardy, 2016-07-03: Establish a low quality BT SCO (Synchronous Connection-Oriented) link to interrupt e.g. a car stereo FM radio
|
||||
if (on) {
|
||||
try {
|
||||
AudioManager mAudioManager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (mAudioManager == null || !mAudioManager.isBluetoothScoAvailableOffCall()) {
|
||||
btScoInit = "Reported not available.";
|
||||
return false;
|
||||
}
|
||||
mAudioManager.setMode(0);
|
||||
mAudioManager.startBluetoothSco();
|
||||
mAudioManager.setBluetoothScoOn(true);
|
||||
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
|
||||
btScoStatus = true;
|
||||
} catch (Exception e) {
|
||||
System.out.println("Exception starting BT SCO " + e.getMessage() );
|
||||
btScoStatus = false;
|
||||
btScoInit = "Available, but not initializad.\n(" + e.getMessage() + ")";
|
||||
return false;
|
||||
}
|
||||
btScoInit = "Available, initialized OK.";
|
||||
return true;
|
||||
} else {
|
||||
AudioManager mAudioManager = (AudioManager) ctx.getSystemService(Context.AUDIO_SERVICE);
|
||||
if (mAudioManager == null) {
|
||||
return false;
|
||||
}
|
||||
mAudioManager.setBluetoothScoOn(false);
|
||||
mAudioManager.stopBluetoothSco();
|
||||
mAudioManager.setMode(AudioManager.MODE_NORMAL);
|
||||
btScoStatus = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationMode getApplicationMode() {
|
||||
return applicationMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(ApplicationMode change) {
|
||||
//
|
||||
// if(prologSystem != null) {
|
||||
// try {
|
||||
// prologSystem.getTheoryManager().retract(new Struct("appMode", new Var()));
|
||||
// } catch (Exception e) {
|
||||
// log.error("Retract error: ", e);
|
||||
// }
|
||||
// prologSystem.getTheoryManager()
|
||||
// .assertA(
|
||||
// new Struct("appMode", new Struct(ctx.getSettings().APPLICATION_MODE.get().getStringKey()
|
||||
// .toLowerCase())), true, "", true);
|
||||
// }
|
||||
}
|
||||
}
|
|
@ -75,21 +75,27 @@ public abstract class AbstractPrologCommandPlayer implements CommandPlayer, Stat
|
|||
this.sortedVoiceVersions = sortedVoiceVersions;
|
||||
this.applicationMode = applicationMode;
|
||||
long time = System.currentTimeMillis();
|
||||
try {
|
||||
this.ctx = ctx;
|
||||
prologSystem = new Prolog(getLibraries());
|
||||
} catch (InvalidLibraryException e) {
|
||||
log.error("Initializing error", e); //$NON-NLS-1$
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing prolog system : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
|
||||
}
|
||||
this.ctx = ctx;
|
||||
|
||||
this.streamType = ctx.getSettings().AUDIO_STREAM_GUIDANCE.getModeValue(applicationMode);
|
||||
init(voiceProvider, ctx.getSettings(), configFile);
|
||||
final Term langVal = solveSimplePredicate("language");
|
||||
if (langVal instanceof Struct) {
|
||||
language = ((Struct) langVal).getName();
|
||||
if (!ctx.getSettings().USE_JS_VOICE_GUIDANCE.get()) {
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing prolog system : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
|
||||
}
|
||||
try {
|
||||
prologSystem = new Prolog(getLibraries());
|
||||
} catch (InvalidLibraryException e) {
|
||||
log.error("Initializing error", e); //$NON-NLS-1$
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
init(voiceProvider, ctx.getSettings(), configFile);
|
||||
final Term langVal = solveSimplePredicate("language");
|
||||
if (langVal instanceof Struct) {
|
||||
language = ((Struct) langVal).getName();
|
||||
}
|
||||
} else if (voiceProvider != null) {
|
||||
initVoiceDir(voiceProvider);
|
||||
language = voiceProvider.replace("-tts", "").replace("-formal", "");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,15 +147,7 @@ public abstract class AbstractPrologCommandPlayer implements CommandPlayer, Stat
|
|||
private void init(String voiceProvider, OsmandSettings settings, String configFile) throws CommandPlayerException {
|
||||
prologSystem.clearTheory();
|
||||
voiceDir = null;
|
||||
if (voiceProvider != null) {
|
||||
File parent = ctx.getAppPath(IndexConstants.VOICE_INDEX_DIR);
|
||||
voiceDir = new File(parent, voiceProvider);
|
||||
if (!voiceDir.exists()) {
|
||||
voiceDir = null;
|
||||
throw new CommandPlayerException(
|
||||
ctx.getString(R.string.voice_data_unavailable));
|
||||
}
|
||||
}
|
||||
initVoiceDir(voiceProvider);
|
||||
|
||||
// see comments below why it is impossible to read from zip (don't know
|
||||
// how to play file from zip)
|
||||
|
@ -201,6 +199,18 @@ public abstract class AbstractPrologCommandPlayer implements CommandPlayer, Stat
|
|||
}
|
||||
}
|
||||
|
||||
private void initVoiceDir(String voiceProvider) throws CommandPlayerException {
|
||||
if (voiceProvider != null) {
|
||||
File parent = ctx.getAppPath(IndexConstants.VOICE_INDEX_DIR);
|
||||
voiceDir = new File(parent, voiceProvider);
|
||||
if (!voiceDir.exists()) {
|
||||
voiceDir = null;
|
||||
throw new CommandPlayerException(
|
||||
ctx.getString(R.string.voice_data_unavailable));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected Term solveSimplePredicate(String predicate) {
|
||||
Term val = null;
|
||||
Var v = new Var("MyVariable"); //$NON-NLS-1$
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import android.media.MediaPlayer;
|
||||
import android.system.Os;
|
||||
|
||||
import net.osmand.IndexConstants;
|
||||
import net.osmand.PlatformUtil;
|
||||
|
@ -9,7 +7,6 @@ import net.osmand.plus.ApplicationMode;
|
|||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.routing.VoiceRouter;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.mozilla.javascript.ScriptableObject;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -18,12 +15,8 @@ import java.io.FileReader;
|
|||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import static net.osmand.plus.voice.AbstractPrologCommandPlayer.DELAY_CONST;
|
||||
|
||||
public class JSMediaCommandPlayerImpl extends MediaCommandPlayerImpl {
|
||||
|
||||
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(JSMediaCommandPlayerImpl.class);
|
||||
|
@ -34,7 +27,6 @@ public class JSMediaCommandPlayerImpl extends MediaCommandPlayerImpl {
|
|||
public JSMediaCommandPlayerImpl(OsmandApplication ctx, ApplicationMode applicationMode, VoiceRouter vrt, String voiceProvider) throws CommandPlayerException {
|
||||
super(ctx, applicationMode, vrt, voiceProvider);
|
||||
app = ctx;
|
||||
|
||||
org.mozilla.javascript.Context context = org.mozilla.javascript.Context.enter();
|
||||
context.setOptimizationLevel(-1);
|
||||
jsScope = context.initSafeStandardObjects();
|
||||
|
|
|
@ -28,78 +28,22 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class JSTTSCommandPlayerImpl extends AbstractJSCommandPlayer {
|
||||
public class JSTTSCommandPlayerImpl extends TTSCommandPlayerImpl {
|
||||
private static final org.apache.commons.logging.Log log = PlatformUtil.getLog(JSTTSCommandPlayerImpl.class);
|
||||
|
||||
private static final String TAG = JSTTSCommandPlayerImpl.class.getSimpleName();
|
||||
private static TextToSpeech mTts;
|
||||
private static String ttsVoiceStatus = "";
|
||||
private static String ttsVoiceUsed = "";
|
||||
|
||||
private boolean speechAllowed = false;
|
||||
private Context mTtsContext;
|
||||
|
||||
private ScriptableObject jsScope;
|
||||
|
||||
private float cSpeechRate = 1;
|
||||
|
||||
private static final class IntentStarter implements
|
||||
DialogInterface.OnClickListener {
|
||||
private final Context ctx;
|
||||
private final String intentAction;
|
||||
private final Uri intentData;
|
||||
|
||||
private IntentStarter(Context ctx, String intentAction) {
|
||||
this(ctx,intentAction, null);
|
||||
}
|
||||
|
||||
private IntentStarter(Context ctx, String intentAction, Uri intentData) {
|
||||
this.ctx = ctx;
|
||||
this.intentAction = intentAction;
|
||||
this.intentData = intentData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent installIntent = new Intent();
|
||||
installIntent.setAction(intentAction);
|
||||
if (intentData != null) {
|
||||
installIntent.setData(intentData);
|
||||
}
|
||||
ctx.startActivity(installIntent);
|
||||
}
|
||||
}
|
||||
private OsmandApplication app;
|
||||
private ApplicationMode appMode;
|
||||
private VoiceRouter vrt;
|
||||
|
||||
private HashMap<String, String> params = new HashMap<String, String>();
|
||||
|
||||
private static int ttsRequests = 0;
|
||||
|
||||
public JSTTSCommandPlayerImpl(Activity ctx, ApplicationMode applicationMode, VoiceRouter vrt, String voiceProvider) throws CommandPlayerException {
|
||||
super((OsmandApplication) ctx.getApplication(), applicationMode, voiceProvider);
|
||||
this.app = (OsmandApplication) ctx.getApplicationContext();
|
||||
this.appMode = applicationMode;
|
||||
this.vrt = vrt;
|
||||
if (Algorithms.isEmpty(language)) {
|
||||
throw new CommandPlayerException(
|
||||
ctx.getString(R.string.voice_data_corrupted));
|
||||
}
|
||||
OsmandApplication app = (OsmandApplication) ctx.getApplicationContext();
|
||||
if(app.accessibilityEnabled()) {
|
||||
cSpeechRate = app.getSettings().SPEECH_RATE.get();
|
||||
}
|
||||
initializeEngine(app, ctx);
|
||||
params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, app.getSettings().AUDIO_STREAM_GUIDANCE
|
||||
.getModeValue(getApplicationMode()).toString());
|
||||
super(ctx, applicationMode, vrt, voiceProvider);
|
||||
this.app = (OsmandApplication) ctx.getApplication();
|
||||
org.mozilla.javascript.Context context = org.mozilla.javascript.Context.enter();
|
||||
context.setOptimizationLevel(-1);
|
||||
jsScope = context.initSafeStandardObjects();
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new FileReader(new File(
|
||||
app.getAppPath(IndexConstants.VOICE_INDEX_DIR).getAbsolutePath() +
|
||||
"/" + voiceProvider + "/" + language + "_tts.js")));
|
||||
"/" + voiceProvider + "/" + voiceProvider.replace("-tts", "_tts") + ".js")));
|
||||
context.evaluateReader(jsScope, br, "JS", 1, null);
|
||||
br.close();
|
||||
} catch (IOException e) {
|
||||
|
@ -109,129 +53,6 @@ public class JSTTSCommandPlayerImpl extends AbstractJSCommandPlayer {
|
|||
}
|
||||
}
|
||||
|
||||
private void initializeEngine(final Context ctx, final Activity act) {
|
||||
if (mTtsContext != ctx) {
|
||||
internalClear();
|
||||
}
|
||||
if (mTts == null) {
|
||||
mTtsContext = ctx;
|
||||
ttsVoiceStatus = "";
|
||||
ttsVoiceUsed = "";
|
||||
ttsRequests = 0;
|
||||
final float speechRate = cSpeechRate;
|
||||
|
||||
final String[] lsplit = (language.replaceAll("-formal", "") + "____.").split("[_\\-]");
|
||||
// constructor supports lang_country_variant
|
||||
Locale newLocale0 = new Locale(lsplit[0], lsplit[1], lsplit[2]);
|
||||
// #3344: Try Locale builder instead of constructor (only available from API 21). Also supports script (for now supported as trailing x_x_x_Scrp)
|
||||
if (android.os.Build.VERSION.SDK_INT >= 21) {
|
||||
try {
|
||||
newLocale0 = new Locale.Builder().setLanguage(lsplit[0]).setScript(lsplit[3]).setRegion(lsplit[1]).setVariant(lsplit[2]).build();
|
||||
} catch (RuntimeException e) {
|
||||
// Falls back to constructor
|
||||
}
|
||||
}
|
||||
final Locale newLocale = newLocale0;
|
||||
|
||||
mTts = new TextToSpeech(ctx, new TextToSpeech.OnInitListener() {
|
||||
@Override
|
||||
public void onInit(int status) {
|
||||
if (status != TextToSpeech.SUCCESS) {
|
||||
ttsVoiceStatus = "NO INIT SUCCESS";
|
||||
internalClear();
|
||||
} else if (mTts != null) {
|
||||
speechAllowed = true;
|
||||
switch (mTts.isLanguageAvailable(newLocale)) {
|
||||
case TextToSpeech.LANG_MISSING_DATA:
|
||||
if (isSettingsActivity(act)) {
|
||||
AlertDialog.Builder builder = createAlertDialog(
|
||||
R.string.tts_missing_language_data_title,
|
||||
R.string.tts_missing_language_data,
|
||||
new JSTTSCommandPlayerImpl.IntentStarter(
|
||||
act,
|
||||
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA),
|
||||
act);
|
||||
builder.show();
|
||||
}
|
||||
ttsVoiceStatus = newLocale.getDisplayName() + ": LANG_MISSING_DATA";
|
||||
ttsVoiceUsed = getVoiceUsed();
|
||||
break;
|
||||
case TextToSpeech.LANG_AVAILABLE:
|
||||
ttsVoiceStatus = newLocale.getDisplayName() + ": LANG_AVAILABLE";
|
||||
case TextToSpeech.LANG_COUNTRY_AVAILABLE:
|
||||
ttsVoiceStatus = "".equals(ttsVoiceStatus) ? newLocale.getDisplayName() + ": LANG_COUNTRY_AVAILABLE" : ttsVoiceStatus;
|
||||
case TextToSpeech.LANG_COUNTRY_VAR_AVAILABLE:
|
||||
try {
|
||||
mTts.setLanguage(newLocale);
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
mTts.setLanguage(Locale.getDefault());
|
||||
}
|
||||
if(speechRate != 1) {
|
||||
mTts.setSpeechRate(speechRate);
|
||||
}
|
||||
ttsVoiceStatus = "".equals(ttsVoiceStatus) ? newLocale.getDisplayName() + ": LANG_COUNTRY_VAR_AVAILABLE" : ttsVoiceStatus;
|
||||
ttsVoiceUsed = getVoiceUsed();
|
||||
break;
|
||||
case TextToSpeech.LANG_NOT_SUPPORTED:
|
||||
//maybe weird, but I didn't want to introduce parameter in around 5 methods just to do this if condition
|
||||
if (isSettingsActivity(act)) {
|
||||
AlertDialog.Builder builder = createAlertDialog(
|
||||
R.string.tts_language_not_supported_title,
|
||||
R.string.tts_language_not_supported,
|
||||
new JSTTSCommandPlayerImpl.IntentStarter(
|
||||
act,
|
||||
Intent.ACTION_VIEW, Uri.parse("market://search?q=text to speech engine"
|
||||
)),
|
||||
act);
|
||||
builder.show();
|
||||
}
|
||||
ttsVoiceStatus = newLocale.getDisplayName() + ": LANG_NOT_SUPPORTED";
|
||||
ttsVoiceUsed = getVoiceUsed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSettingsActivity(final Context ctx) {
|
||||
return ctx instanceof SettingsActivity;
|
||||
}
|
||||
|
||||
private String getVoiceUsed() {
|
||||
try {
|
||||
if (android.os.Build.VERSION.SDK_INT >= 21) {
|
||||
if (mTts.getVoice() != null) {
|
||||
return mTts.getVoice().toString() + " (API " + android.os.Build.VERSION.SDK_INT + ")";
|
||||
}
|
||||
} else {
|
||||
return mTts.getLanguage() + " (API " + android.os.Build.VERSION.SDK_INT + " only reports language)";
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
// mTts.getVoice() might throw NPE
|
||||
}
|
||||
return "-";
|
||||
}
|
||||
});
|
||||
mTts.setOnUtteranceCompletedListener(new TextToSpeech.OnUtteranceCompletedListener() {
|
||||
// The call back is on a binder thread.
|
||||
@Override
|
||||
public synchronized void onUtteranceCompleted(String utteranceId) {
|
||||
if (--ttsRequests <= 0)
|
||||
abandonAudioFocus();
|
||||
log.debug("ttsRequests="+ttsRequests);
|
||||
if (ttsRequests < 0) {
|
||||
ttsRequests = 0;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentVoice() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSCommandBuilder newCommandBuilder() {
|
||||
JSCommandBuilder commandBuilder = new JSCommandBuilder(this);
|
||||
|
@ -240,88 +61,11 @@ public class JSTTSCommandPlayerImpl extends AbstractJSCommandPlayer {
|
|||
return commandBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playCommands(CommandBuilder builder) {
|
||||
final List<String> execute = builder.execute(); //list of strings, the speech text, play it
|
||||
StringBuilder bld = new StringBuilder();
|
||||
for (String s : execute) {
|
||||
bld.append(s).append(' ');
|
||||
}
|
||||
if (mTts != null && !vrt.isMute() && speechAllowed) {
|
||||
if (ttsRequests++ == 0) {
|
||||
// Delay first prompt of each batch to allow BT SCO connection being established
|
||||
if (app.getSettings().AUDIO_STREAM_GUIDANCE.getModeValue(appMode) == 0) {
|
||||
ttsRequests++;
|
||||
if (android.os.Build.VERSION.SDK_INT < 21) {
|
||||
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,""+System.currentTimeMillis());
|
||||
mTts.playSilence(app.getSettings().BT_SCO_DELAY.get(), TextToSpeech.QUEUE_ADD, params);
|
||||
} else {
|
||||
mTts.playSilentUtterance(app.getSettings().BT_SCO_DELAY.get(), TextToSpeech.QUEUE_ADD, ""+System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "ttsRequests= "+ttsRequests);
|
||||
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,""+System.currentTimeMillis());
|
||||
mTts.speak(bld.toString(), TextToSpeech.QUEUE_ADD, params);
|
||||
// Audio focus will be released when onUtteranceCompleted() completed is called by the TTS engine.
|
||||
} else if (app != null && vrt.isMute()) {
|
||||
// sendAlertToAndroidWear(ctx, bld.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop(){
|
||||
ttsRequests = 0;
|
||||
if (mTts != null){
|
||||
mTts.stop();
|
||||
}
|
||||
abandonAudioFocus();
|
||||
}
|
||||
|
||||
public static String getTtsVoiceStatus() {
|
||||
return ttsVoiceStatus;
|
||||
}
|
||||
|
||||
public static String getTtsVoiceUsed() {
|
||||
return ttsVoiceUsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
internalClear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAudioStream(int streamType) {
|
||||
super.updateAudioStream(streamType);
|
||||
params.put(TextToSpeech.Engine.KEY_PARAM_STREAM, streamType+"");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return language;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsStructuredStreetNames() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private void internalClear() {
|
||||
ttsRequests = 0;
|
||||
speechAllowed = false;
|
||||
if (mTts != null) {
|
||||
mTts.shutdown();
|
||||
mTts = null;
|
||||
}
|
||||
abandonAudioFocus();
|
||||
mTtsContext = null;
|
||||
ttsVoiceStatus = "";
|
||||
ttsVoiceUsed = "";
|
||||
}
|
||||
|
||||
public static boolean isMyData(File voiceDir) {
|
||||
if (!voiceDir.getName().contains("tts")) {
|
||||
return false;
|
||||
|
@ -333,15 +77,4 @@ public class JSTTSCommandPlayerImpl extends AbstractJSCommandPlayer {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private AlertDialog.Builder createAlertDialog(int titleResID, int messageResID,
|
||||
JSTTSCommandPlayerImpl.IntentStarter intentStarter, final Activity ctx) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
|
||||
builder.setCancelable(true);
|
||||
builder.setNegativeButton(R.string.shared_string_no, null);
|
||||
builder.setPositiveButton(R.string.shared_string_yes, intentStarter);
|
||||
builder.setTitle(titleResID);
|
||||
builder.setMessage(messageResID);
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue