work in progress on TTS, needs more changes
This commit is contained in:
parent
932e0dc96b
commit
45002d3a77
14 changed files with 815 additions and 443 deletions
|
@ -49,6 +49,7 @@
|
|||
<intent-filter><action android:name="net.osmand.plus.NavigationService"></action></intent-filter>
|
||||
</service>
|
||||
<receiver android:name=".OnNavigationServiceAlarmReceiver"/>
|
||||
<activity android:name=".activities.InitTTSActivity"></activity>
|
||||
</application>
|
||||
|
||||
|
||||
|
|
67
OsmAnd/src/net/osmand/plus/activities/InitTTSActivity.java
Normal file
67
OsmAnd/src/net/osmand/plus/activities/InitTTSActivity.java
Normal file
|
@ -0,0 +1,67 @@
|
|||
package net.osmand.plus.activities;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.plus.voice.TTSOsmand;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.speech.tts.TextToSpeech.OnInitListener;
|
||||
|
||||
public class InitTTSActivity extends Activity implements OnInitListener {
|
||||
|
||||
private static final Log log = LogUtil
|
||||
.getLog(InitTTSActivity.class);
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mTts = new TextToSpeech(this, this);
|
||||
final int languageAvailable = mTts.isLanguageAvailable(Locale.FRANCE);
|
||||
log.info("Language availbility:" + languageAvailable);
|
||||
}
|
||||
|
||||
private TextToSpeech mTts;
|
||||
|
||||
@Override
|
||||
public void onInit(int status) {
|
||||
if (status == TextToSpeech.SUCCESS) {
|
||||
// success, create the TTS instance
|
||||
int result = mTts.setLanguage(Locale.US);
|
||||
TTSOsmand.mTts = mTts;
|
||||
// Try this someday for some interesting results.
|
||||
// int result mTts.setLanguage(Locale.FRANCE);
|
||||
if (result == TextToSpeech.LANG_MISSING_DATA ||
|
||||
result == TextToSpeech.LANG_NOT_SUPPORTED) {
|
||||
//TODO
|
||||
}
|
||||
} else {
|
||||
// missing data, install it
|
||||
if (mTts != null) {
|
||||
mTts.speak("Needs to install data!", TextToSpeech.QUEUE_ADD, null);
|
||||
Intent installIntent = new Intent();
|
||||
installIntent
|
||||
.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
|
||||
startActivity(installIntent);
|
||||
} else {
|
||||
log.info("onInit called again with status: " + status);
|
||||
}
|
||||
}
|
||||
finish();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (mTts != null) {
|
||||
mTts.shutdown();
|
||||
mTts = null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -24,10 +24,12 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.voice.CommandPlayerException;
|
||||
import net.osmand.plus.voice.CommandPlayerFactory;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Application;
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
|
@ -211,30 +213,35 @@ public class OsmandApplication extends Application {
|
|||
|
||||
}
|
||||
|
||||
private void initVoiceDataInDifferentThread(Context uiContext) {
|
||||
final ProgressDialog dlg = ProgressDialog.show(uiContext, getString(R.string.loading_data), getString(R.string.voice_data_initializing));
|
||||
private void initVoiceDataInDifferentThread(final Context uiContext) {
|
||||
// final ProgressDialog dlg = ProgressDialog.show(uiContext,
|
||||
// getString(R.string.loading_data),
|
||||
// getString(R.string.voice_data_initializing));
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String w = null;
|
||||
try {
|
||||
w = initCommandPlayer();
|
||||
} finally {
|
||||
dlg.dismiss();
|
||||
}
|
||||
if(w != null){
|
||||
showWarning(dlg.getContext(), w);
|
||||
initCommandPlayer();
|
||||
// dlg.dismiss();
|
||||
} catch (CommandPlayerException e) {
|
||||
// dlg.dismiss();
|
||||
showWarning(uiContext, e.getError());
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public String initCommandPlayer() {
|
||||
if (player == null) {
|
||||
player = new CommandPlayer(OsmandApplication.this);
|
||||
public void initCommandPlayer()
|
||||
throws CommandPlayerException
|
||||
{
|
||||
final String voiceProvider = osmandSettings.VOICE_PROVIDER.get();
|
||||
if (player == null || !Algoritms.objectEquals(voiceProvider, player.getCurrentVoice())) {
|
||||
if (player != null) {
|
||||
player.clear();
|
||||
}
|
||||
player = CommandPlayerFactory.createCommandPlayer(voiceProvider,OsmandApplication.this, getApplicationContext());
|
||||
routingHelper.getVoiceRouter().setPlayer(player);
|
||||
}
|
||||
return player.init(osmandSettings.VOICE_PROVIDER.get());
|
||||
}
|
||||
|
||||
public NavigationService getNavigationService() {
|
||||
|
|
|
@ -396,7 +396,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
values[ki] = MORE_VALUE;
|
||||
fill(tileSourcePreference, entries, values, value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void fill(ListPreference component, String[] list, String[] values, String selected) {
|
||||
component.setEntries(list);
|
||||
component.setEntryValues(values);
|
||||
|
@ -435,7 +436,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
// Specific actions after list preference changed
|
||||
if (changed) {
|
||||
if (listPref.getId().equals(osmandSettings.VOICE_PROVIDER.getId())) {
|
||||
getMyApplication().initCommandPlayer();
|
||||
getMyApplication().showDialogInitializingCommandPlayer(this);
|
||||
} else if (listPref.getId().equals(osmandSettings.APPLICATION_MODE.getId())) {
|
||||
updateAllSettings();
|
||||
} else if (listPref.getId().equals(osmandSettings.PREFERRED_LOCALE.getId())) {
|
||||
|
|
|
@ -2,8 +2,9 @@ package net.osmand.plus.activities;
|
|||
|
||||
import net.osmand.plus.activities.RoutingHelper.RouteDirectionInfo;
|
||||
import net.osmand.plus.activities.RoutingHelper.TurnType;
|
||||
import net.osmand.plus.voice.AbstractPrologCommandPlayer;
|
||||
import net.osmand.plus.voice.CommandBuilder;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.voice.CommandPlayer.CommandBuilder;
|
||||
|
||||
|
||||
public class VoiceRouter {
|
||||
|
@ -227,17 +228,17 @@ public class VoiceRouter {
|
|||
|
||||
private String getTurnType(TurnType t){
|
||||
if(TurnType.TL.equals(t.getValue())){
|
||||
return CommandPlayer.A_LEFT;
|
||||
return AbstractPrologCommandPlayer.A_LEFT;
|
||||
} else if(TurnType.TSHL.equals(t.getValue())){
|
||||
return CommandPlayer.A_LEFT_SH;
|
||||
return AbstractPrologCommandPlayer.A_LEFT_SH;
|
||||
} else if(TurnType.TSLL.equals(t.getValue())){
|
||||
return CommandPlayer.A_LEFT_SL;
|
||||
return AbstractPrologCommandPlayer.A_LEFT_SL;
|
||||
} else if(TurnType.TR.equals(t.getValue())){
|
||||
return CommandPlayer.A_RIGHT;
|
||||
return AbstractPrologCommandPlayer.A_RIGHT;
|
||||
} else if(TurnType.TSHR.equals(t.getValue())){
|
||||
return CommandPlayer.A_RIGHT_SH;
|
||||
return AbstractPrologCommandPlayer.A_RIGHT_SH;
|
||||
} else if(TurnType.TSLR.equals(t.getValue())){
|
||||
return CommandPlayer.A_RIGHT_SL;
|
||||
return AbstractPrologCommandPlayer.A_RIGHT_SL;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.data.IndexConstants;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import alice.tuprolog.InvalidLibraryException;
|
||||
import alice.tuprolog.InvalidTheoryException;
|
||||
import alice.tuprolog.NoSolutionException;
|
||||
import alice.tuprolog.Number;
|
||||
import alice.tuprolog.Prolog;
|
||||
import alice.tuprolog.SolveInfo;
|
||||
import alice.tuprolog.Struct;
|
||||
import alice.tuprolog.Term;
|
||||
import alice.tuprolog.Theory;
|
||||
import alice.tuprolog.Var;
|
||||
import android.content.Context;
|
||||
|
||||
public abstract class AbstractPrologCommandPlayer implements CommandPlayer {
|
||||
|
||||
private static final Log log = LogUtil
|
||||
.getLog(AbstractPrologCommandPlayer.class);
|
||||
|
||||
protected Context ctx;
|
||||
protected File voiceDir;
|
||||
protected Prolog prologSystem;
|
||||
protected static final String P_VERSION = "version";
|
||||
protected static final String P_RESOLVE = "resolve";
|
||||
public static final String A_LEFT = "left";
|
||||
public static final String A_LEFT_SH = "left_sh";
|
||||
public static final String A_LEFT_SL = "left_sl";
|
||||
public static final String A_RIGHT = "right";
|
||||
public static final String A_RIGHT_SH = "right_sh";
|
||||
public static final String A_RIGHT_SL = "right_sl";
|
||||
protected static final String DELAY_CONST = "delay_";
|
||||
|
||||
protected AbstractPrologCommandPlayer(Context ctx, String voiceProvider, String configFile)
|
||||
throws CommandPlayerException
|
||||
{
|
||||
long time = System.currentTimeMillis();
|
||||
try {
|
||||
this.ctx = ctx;
|
||||
prologSystem = new Prolog(
|
||||
new String[] { "alice.tuprolog.lib.BasicLibrary" }); //$NON-NLS-1$
|
||||
} 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$
|
||||
}
|
||||
init(voiceProvider, configFile);
|
||||
}
|
||||
|
||||
private void init(String voiceProvider, String configFile) throws CommandPlayerException {
|
||||
prologSystem.clearTheory();
|
||||
voiceDir = null;
|
||||
if (voiceProvider != null) {
|
||||
File parent = OsmandSettings.getOsmandSettings(ctx).extendOsmandPath(ResourceManager.VOICE_PATH);
|
||||
voiceDir = new File(parent, voiceProvider);
|
||||
if (!voiceDir.exists()) {
|
||||
voiceDir = null;
|
||||
throw new CommandPlayerException(
|
||||
ctx.getString(R.string.voice_data_unavailable));
|
||||
}
|
||||
}
|
||||
|
||||
// see comments below why it is impossible to read from zip (don't know
|
||||
// how to play file from zip)
|
||||
// voiceZipFile = null;
|
||||
if (voiceDir != null) {
|
||||
long time = System.currentTimeMillis();
|
||||
boolean wrong = false;
|
||||
try {
|
||||
InputStream config;
|
||||
// if (voiceDir.getName().endsWith(".zip")) { //$NON-NLS-1$
|
||||
// voiceZipFile = new ZipFile(voiceDir);
|
||||
// config = voiceZipFile.getInputStream(voiceZipFile.getEntry("_config.p")); //$NON-NLS-1$
|
||||
// } else {
|
||||
config = new FileInputStream(new File(voiceDir, configFile)); //$NON-NLS-1$
|
||||
// }
|
||||
if (!wrong) {
|
||||
prologSystem.setTheory(new Theory(config));
|
||||
}
|
||||
} catch (InvalidTheoryException e) {
|
||||
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
|
||||
wrong = true;
|
||||
} catch (IOException e) {
|
||||
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
|
||||
wrong = true;
|
||||
}
|
||||
if (wrong) {
|
||||
throw new CommandPlayerException(
|
||||
ctx.getString(R.string.voice_data_corrupted));
|
||||
} else {
|
||||
boolean versionSupported = false;
|
||||
Var v = new Var("VERSION"); //$NON-NLS-1$
|
||||
SolveInfo s = prologSystem.solve(new Struct(P_VERSION, v));
|
||||
if (s.isSuccess()) {
|
||||
prologSystem.solveEnd();
|
||||
try {
|
||||
Term val = s.getVarValue(v.getName());
|
||||
if (val instanceof Number) {
|
||||
versionSupported = ((Number) val).intValue() == IndexConstants.VOICE_VERSION;
|
||||
}
|
||||
} catch (NoSolutionException e) {
|
||||
}
|
||||
}
|
||||
if (!versionSupported) {
|
||||
throw new CommandPlayerException(
|
||||
ctx.getString(R.string.voice_data_not_supported));
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing voice subsystem " + voiceProvider + " : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> execute(List<Struct> listCmd){
|
||||
Struct list = new Struct(listCmd.toArray(new Term[listCmd.size()]));
|
||||
Var result = new Var("RESULT"); //$NON-NLS-1$
|
||||
List<String> files = new ArrayList<String>();
|
||||
SolveInfo res = prologSystem.solve(new Struct(P_RESOLVE, list, result));
|
||||
|
||||
if (res.isSuccess()) {
|
||||
try {
|
||||
prologSystem.solveEnd();
|
||||
Term solution = res.getVarValue(result.getName());
|
||||
|
||||
Iterator<?> listIterator = ((Struct) solution).listIterator();
|
||||
while(listIterator.hasNext()){
|
||||
Object term = listIterator.next();
|
||||
if(term instanceof Struct){
|
||||
files.add(((Struct) term).getName());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NoSolutionException e) {
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentVoice() {
|
||||
if (voiceDir == null) {
|
||||
return null;
|
||||
}
|
||||
return voiceDir.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandBuilder newCommandBuilder() {
|
||||
return new CommandBuilder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ctx = null;
|
||||
prologSystem = null;
|
||||
}
|
||||
|
||||
}
|
179
OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java
Normal file
179
OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java
Normal file
|
@ -0,0 +1,179 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import alice.tuprolog.Struct;
|
||||
import alice.tuprolog.Term;
|
||||
|
||||
public class CommandBuilder {
|
||||
|
||||
private static final Log log = LogUtil.getLog(CommandBuilder.class);
|
||||
|
||||
protected static final String C_PREPARE_TURN = "prepare_turn"; //$NON-NLS-1$
|
||||
protected static final String C_PREPARE_ROUNDABOUT = "prepare_roundabout"; //$NON-NLS-1$
|
||||
protected static final String C_PREPARE_MAKE_UT = "prepare_make_ut"; //$NON-NLS-1$
|
||||
protected static final String C_ROUNDABOUT = "roundabout"; //$NON-NLS-1$
|
||||
protected static final String C_GO_AHEAD = "go_ahead"; //$NON-NLS-1$
|
||||
protected static final String C_TURN = "turn"; //$NON-NLS-1$
|
||||
protected static final String C_MAKE_UT = "make_ut"; //$NON-NLS-1$
|
||||
protected static final String C_PREAMBLE = "preamble"; //$NON-NLS-1$
|
||||
protected static final String C_AND_ARRIVE_DESTINATION = "and_arrive_destination"; //$NON-NLS-1$
|
||||
protected static final String C_THEN = "then"; //$NON-NLS-1$
|
||||
protected static final String C_REACHED_DESTINATION = "reached_destination"; //$NON-NLS-1$
|
||||
protected static final String C_BEAR_LEFT = "bear_left"; //$NON-NLS-1$
|
||||
protected static final String C_BEAR_RIGHT = "bear_right"; //$NON-NLS-1$
|
||||
protected static final String C_ROUTE_RECALC = "route_recalc"; //$NON-NLS-1$
|
||||
protected static final String C_ROUTE_NEW_CALC = "route_new_calc"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final CommandPlayer commandPlayer;
|
||||
private boolean alreadyExecuted = false;
|
||||
private List<Struct> listStruct = new ArrayList<Struct>();
|
||||
|
||||
public CommandBuilder(CommandPlayer commandPlayer){
|
||||
this(commandPlayer, true);
|
||||
}
|
||||
|
||||
public CommandBuilder(CommandPlayer commandPlayer, boolean preamble) {
|
||||
this.commandPlayer = commandPlayer;
|
||||
if (preamble) {
|
||||
addCommand(C_PREAMBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkState(){
|
||||
if(alreadyExecuted){
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private CommandBuilder addCommand(String name, Object... args){
|
||||
checkState();
|
||||
Term[] list = new Term[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object o = args[i];
|
||||
if(o instanceof java.lang.Number){
|
||||
if(o instanceof java.lang.Double){
|
||||
list[i] = new alice.tuprolog.Double((Double) o);
|
||||
} else if(o instanceof java.lang.Float){
|
||||
list[i] = new alice.tuprolog.Float((Float) o);
|
||||
} else if(o instanceof java.lang.Long){
|
||||
list[i] = new alice.tuprolog.Long((Long) o);
|
||||
} else {
|
||||
list[i] = new alice.tuprolog.Int(((java.lang.Number)o).intValue());
|
||||
}
|
||||
} else if(o instanceof String){
|
||||
list[i] = new Struct((String) o);
|
||||
}
|
||||
if(list[i]== null){
|
||||
throw new NullPointerException(name +" " + o); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
Struct struct = new Struct(name, list);
|
||||
if(log.isDebugEnabled()){
|
||||
log.debug("Adding command : " + name + " " + Arrays.toString(args)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
listStruct.add(struct);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandBuilder goAhead(){
|
||||
return addCommand(C_GO_AHEAD);
|
||||
}
|
||||
|
||||
public CommandBuilder goAhead(double dist){
|
||||
return addCommand(C_GO_AHEAD, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder makeUT(){
|
||||
return addCommand(C_MAKE_UT);
|
||||
}
|
||||
|
||||
public CommandBuilder makeUT(double dist){
|
||||
return addCommand(C_MAKE_UT, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder prepareMakeUT(double dist){
|
||||
return addCommand(C_PREPARE_MAKE_UT, dist);
|
||||
}
|
||||
|
||||
|
||||
public CommandBuilder turn(String param){
|
||||
return addCommand(C_TURN, param);
|
||||
}
|
||||
|
||||
public CommandBuilder turn(String param, double dist){
|
||||
return addCommand(C_TURN, param, dist);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param param A_LEFT, A_RIGHT, ...
|
||||
* @param dist
|
||||
* @return
|
||||
*/
|
||||
public CommandBuilder prepareTurn(String param, double dist){
|
||||
return addCommand(C_PREPARE_TURN, param, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder prepareRoundAbout(double dist){
|
||||
return addCommand(C_PREPARE_ROUNDABOUT, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder roundAbout(double dist, double angle, int exit){
|
||||
return addCommand(C_ROUNDABOUT, dist, angle, exit);
|
||||
}
|
||||
|
||||
public CommandBuilder roundAbout(double angle, int exit){
|
||||
return addCommand(C_ROUNDABOUT, angle, exit);
|
||||
}
|
||||
|
||||
public CommandBuilder andArriveAtDestination(){
|
||||
return addCommand(C_AND_ARRIVE_DESTINATION);
|
||||
}
|
||||
|
||||
public CommandBuilder arrivedAtDestination(){
|
||||
return addCommand(C_REACHED_DESTINATION);
|
||||
}
|
||||
|
||||
public CommandBuilder bearLeft(){
|
||||
return addCommand(C_BEAR_LEFT);
|
||||
}
|
||||
|
||||
public CommandBuilder bearRight(){
|
||||
return addCommand(C_BEAR_RIGHT);
|
||||
}
|
||||
|
||||
public CommandBuilder then(){
|
||||
return addCommand(C_THEN);
|
||||
}
|
||||
|
||||
public CommandBuilder newRouteCalculated(double dist){
|
||||
return addCommand(C_ROUTE_NEW_CALC, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder routeRecalculated(double dist){
|
||||
return addCommand(C_ROUTE_RECALC, dist);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void play(){
|
||||
this.commandPlayer.playCommands(this);
|
||||
}
|
||||
|
||||
protected List<String> execute(){
|
||||
alreadyExecuted = true;
|
||||
return this.commandPlayer.execute(listStruct);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,420 +1,19 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.data.IndexConstants;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import alice.tuprolog.InvalidLibraryException;
|
||||
import alice.tuprolog.InvalidTheoryException;
|
||||
import alice.tuprolog.NoSolutionException;
|
||||
import alice.tuprolog.Number;
|
||||
import alice.tuprolog.Prolog;
|
||||
import alice.tuprolog.SolveInfo;
|
||||
import alice.tuprolog.Struct;
|
||||
import alice.tuprolog.Term;
|
||||
import alice.tuprolog.Theory;
|
||||
import alice.tuprolog.Var;
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
|
||||
/**
|
||||
* That class represents command player.
|
||||
* It gets commands from input, analyze what files should be played and play
|
||||
* them using media player
|
||||
*/
|
||||
public class CommandPlayer {
|
||||
|
||||
private static final Log log = LogUtil.getLog(CommandPlayer.class);
|
||||
|
||||
protected Context ctx;
|
||||
// or zip file
|
||||
private File voiceDir;
|
||||
// private ZipFile voiceZipFile;
|
||||
|
||||
// resolving commands to play
|
||||
private Prolog prologSystem;
|
||||
|
||||
// playing media
|
||||
private MediaPlayer mediaPlayer;
|
||||
// indicates that player is ready to play first file
|
||||
private boolean playNext = true;
|
||||
private List<String> filesToPlay = Collections.synchronizedList(new ArrayList<String>());
|
||||
|
||||
|
||||
public CommandPlayer(Context ctx){
|
||||
long time = System.currentTimeMillis();
|
||||
try {
|
||||
this.ctx = ctx;
|
||||
prologSystem = new Prolog(new String[]{"alice.tuprolog.lib.BasicLibrary"}); //$NON-NLS-1$
|
||||
} catch (InvalidLibraryException e) {
|
||||
log.error("Initializing error", e); //$NON-NLS-1$
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
mediaPlayer = new MediaPlayer();
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing prolog system : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getCurrentVoice(){
|
||||
if(voiceDir == null){
|
||||
return null;
|
||||
}
|
||||
return voiceDir.getName();
|
||||
}
|
||||
|
||||
public String init(String voiceProvider){
|
||||
prologSystem.clearTheory();
|
||||
voiceDir = null;
|
||||
if(voiceProvider != null){
|
||||
File parent = OsmandSettings.getOsmandSettings(ctx).extendOsmandPath(ResourceManager.VOICE_PATH);
|
||||
voiceDir = new File(parent, voiceProvider);
|
||||
if(!voiceDir.exists()){
|
||||
voiceDir = null;
|
||||
return ctx.getString(R.string.voice_data_unavailable);
|
||||
}
|
||||
}
|
||||
|
||||
// see comments below why it is impossible to read from zip (don't know how to play file from zip)
|
||||
// voiceZipFile = null;
|
||||
if(voiceDir != null) {
|
||||
long time = System.currentTimeMillis();
|
||||
boolean wrong = false;
|
||||
try {
|
||||
InputStream config;
|
||||
// if (voiceDir.getName().endsWith(".zip")) { //$NON-NLS-1$
|
||||
// voiceZipFile = new ZipFile(voiceDir);
|
||||
// config = voiceZipFile.getInputStream(voiceZipFile.getEntry("_config.p")); //$NON-NLS-1$
|
||||
// } else {
|
||||
config = new FileInputStream(new File(voiceDir, "_config.p")); //$NON-NLS-1$
|
||||
// }
|
||||
if (!wrong) {
|
||||
prologSystem.setTheory(new Theory(config));
|
||||
}
|
||||
} catch (InvalidTheoryException e) {
|
||||
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
|
||||
wrong = true;
|
||||
} catch (IOException e) {
|
||||
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
|
||||
wrong = true;
|
||||
}
|
||||
if(wrong){
|
||||
return ctx.getString(R.string.voice_data_corrupted);
|
||||
} else {
|
||||
boolean versionSupported = false;
|
||||
Var v = new Var("VERSION"); //$NON-NLS-1$
|
||||
SolveInfo s = prologSystem.solve(new Struct(P_VERSION, v));
|
||||
if(s.isSuccess()){
|
||||
prologSystem.solveEnd();
|
||||
try {
|
||||
Term val = s.getVarValue(v.getName());
|
||||
if(val instanceof Number){
|
||||
versionSupported = ((Number) val).intValue() == IndexConstants.VOICE_VERSION;
|
||||
}
|
||||
} catch (NoSolutionException e) {
|
||||
}
|
||||
}
|
||||
if(!versionSupported){
|
||||
return ctx.getString(R.string.voice_data_not_supported);
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing voice subsystem " + voiceProvider + " : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public CommandBuilder newCommandBuilder(){
|
||||
return new CommandBuilder();
|
||||
}
|
||||
|
||||
|
||||
protected List<String> execute(List<Struct> listCmd){
|
||||
Struct list = new Struct(listCmd.toArray(new Term[listCmd.size()]));
|
||||
Var result = new Var("RESULT"); //$NON-NLS-1$
|
||||
List<String> files = new ArrayList<String>();
|
||||
SolveInfo res = prologSystem.solve(new Struct(P_RESOLVE, list, result));
|
||||
|
||||
if (res.isSuccess()) {
|
||||
try {
|
||||
prologSystem.solveEnd();
|
||||
Term solution = res.getVarValue(result.getName());
|
||||
|
||||
Iterator<?> listIterator = ((Struct) solution).listIterator();
|
||||
while(listIterator.hasNext()){
|
||||
Object term = listIterator.next();
|
||||
if(term instanceof Struct){
|
||||
files.add(((Struct) term).getName());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NoSolutionException e) {
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
public void playCommands(CommandBuilder builder){
|
||||
filesToPlay.addAll(builder.execute());
|
||||
playQueue();
|
||||
}
|
||||
|
||||
private synchronized void playQueue() {
|
||||
while (!filesToPlay.isEmpty() && playNext) {
|
||||
String f = filesToPlay.remove(0);
|
||||
if (f != null && voiceDir != null) {
|
||||
boolean exists = false;
|
||||
// if(voiceZipFile != null){
|
||||
// ZipEntry entry = voiceZipFile.getEntry(f);
|
||||
// exists = entry != null;
|
||||
// voiceZipFile.getInputStream(entry);
|
||||
//
|
||||
// } else {
|
||||
File file = new File(voiceDir, f);
|
||||
exists = file.exists();
|
||||
// }
|
||||
if (exists) {
|
||||
log.debug("Playing file : " + f); //$NON-NLS-1$
|
||||
playNext = false;
|
||||
try {
|
||||
// Can't play sound file from zip it seams to be impossible only unpack and play!!!
|
||||
mediaPlayer.setDataSource(file.getAbsolutePath());
|
||||
mediaPlayer.prepare();
|
||||
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mp.release();
|
||||
mediaPlayer = new MediaPlayer();
|
||||
int sleep = 60;
|
||||
boolean delay = true;
|
||||
while (!filesToPlay.isEmpty() && delay) {
|
||||
delay = filesToPlay.get(0).startsWith(DELAY_CONST);
|
||||
if (delay) {
|
||||
String s = filesToPlay.remove(0).substring(DELAY_CONST.length());
|
||||
try {
|
||||
sleep += Integer.parseInt(s);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(sleep);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
playNext = true;
|
||||
playQueue();
|
||||
}
|
||||
});
|
||||
|
||||
mediaPlayer.start();
|
||||
} catch (Exception e) {
|
||||
log.error("Error while playing voice command", e); //$NON-NLS-1$
|
||||
playNext = true;
|
||||
|
||||
}
|
||||
} else {
|
||||
log.info("Play file not found : " + f); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static final String P_VERSION = "version"; //$NON-NLS-1$
|
||||
protected static final String P_RESOLVE = "resolve"; //$NON-NLS-1$
|
||||
|
||||
public static final String A_LEFT = "left"; //$NON-NLS-1$
|
||||
public static final String A_LEFT_SH = "left_sh"; //$NON-NLS-1$
|
||||
public static final String A_LEFT_SL = "left_sl"; //$NON-NLS-1$
|
||||
public static final String A_RIGHT = "right"; //$NON-NLS-1$
|
||||
public static final String A_RIGHT_SH = "right_sh"; //$NON-NLS-1$
|
||||
public static final String A_RIGHT_SL = "right_sl"; //$NON-NLS-1$
|
||||
|
||||
protected static final String C_PREPARE_TURN = "prepare_turn"; //$NON-NLS-1$
|
||||
protected static final String C_PREPARE_ROUNDABOUT = "prepare_roundabout"; //$NON-NLS-1$
|
||||
protected static final String C_PREPARE_MAKE_UT = "prepare_make_ut"; //$NON-NLS-1$
|
||||
protected static final String C_ROUNDABOUT = "roundabout"; //$NON-NLS-1$
|
||||
protected static final String C_GO_AHEAD = "go_ahead"; //$NON-NLS-1$
|
||||
protected static final String C_TURN = "turn"; //$NON-NLS-1$
|
||||
protected static final String C_MAKE_UT = "make_ut"; //$NON-NLS-1$
|
||||
protected static final String C_PREAMBLE = "preamble"; //$NON-NLS-1$
|
||||
protected static final String C_AND_ARRIVE_DESTINATION = "and_arrive_destination"; //$NON-NLS-1$
|
||||
protected static final String C_THEN = "then"; //$NON-NLS-1$
|
||||
protected static final String C_REACHED_DESTINATION = "reached_destination"; //$NON-NLS-1$
|
||||
protected static final String C_BEAR_LEFT = "bear_left"; //$NON-NLS-1$
|
||||
protected static final String C_BEAR_RIGHT = "bear_right"; //$NON-NLS-1$
|
||||
protected static final String C_ROUTE_RECALC = "route_recalc"; //$NON-NLS-1$
|
||||
protected static final String C_ROUTE_NEW_CALC = "route_new_calc"; //$NON-NLS-1$
|
||||
|
||||
|
||||
protected static final String DELAY_CONST = "delay_"; //$NON-NLS-1$
|
||||
|
||||
public class CommandBuilder {
|
||||
|
||||
|
||||
private boolean alreadyExecuted = false;
|
||||
private List<Struct> listStruct = new ArrayList<Struct>();
|
||||
|
||||
public CommandBuilder(){
|
||||
this(true);
|
||||
}
|
||||
|
||||
public CommandBuilder(boolean preamble) {
|
||||
if (preamble) {
|
||||
addCommand(C_PREAMBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkState(){
|
||||
if(alreadyExecuted){
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private CommandBuilder addCommand(String name, Object... args){
|
||||
checkState();
|
||||
Term[] list = new Term[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object o = args[i];
|
||||
if(o instanceof java.lang.Number){
|
||||
if(o instanceof java.lang.Double){
|
||||
list[i] = new alice.tuprolog.Double((Double) o);
|
||||
} else if(o instanceof java.lang.Float){
|
||||
list[i] = new alice.tuprolog.Float((Float) o);
|
||||
} else if(o instanceof java.lang.Long){
|
||||
list[i] = new alice.tuprolog.Long((Long) o);
|
||||
} else {
|
||||
list[i] = new alice.tuprolog.Int(((java.lang.Number)o).intValue());
|
||||
}
|
||||
} else if(o instanceof String){
|
||||
list[i] = new Struct((String) o);
|
||||
}
|
||||
if(list[i]== null){
|
||||
throw new NullPointerException(name +" " + o); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
Struct struct = new Struct(name, list);
|
||||
if(log.isDebugEnabled()){
|
||||
log.debug("Adding command : " + name + " " + Arrays.toString(args)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
listStruct.add(struct);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandBuilder goAhead(){
|
||||
return addCommand(C_GO_AHEAD);
|
||||
}
|
||||
|
||||
public CommandBuilder goAhead(double dist){
|
||||
return addCommand(C_GO_AHEAD, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder makeUT(){
|
||||
return addCommand(C_MAKE_UT);
|
||||
}
|
||||
|
||||
public CommandBuilder makeUT(double dist){
|
||||
return addCommand(C_MAKE_UT, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder prepareMakeUT(double dist){
|
||||
return addCommand(C_PREPARE_MAKE_UT, dist);
|
||||
}
|
||||
|
||||
|
||||
public CommandBuilder turn(String param){
|
||||
return addCommand(C_TURN, param);
|
||||
}
|
||||
|
||||
public CommandBuilder turn(String param, double dist){
|
||||
return addCommand(C_TURN, param, dist);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param param A_LEFT, A_RIGHT, ...
|
||||
* @param dist
|
||||
* @return
|
||||
*/
|
||||
public CommandBuilder prepareTurn(String param, double dist){
|
||||
return addCommand(C_PREPARE_TURN, param, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder prepareRoundAbout(double dist){
|
||||
return addCommand(C_PREPARE_ROUNDABOUT, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder roundAbout(double dist, double angle, int exit){
|
||||
return addCommand(C_ROUNDABOUT, dist, angle, exit);
|
||||
}
|
||||
|
||||
public CommandBuilder roundAbout(double angle, int exit){
|
||||
return addCommand(C_ROUNDABOUT, angle, exit);
|
||||
}
|
||||
|
||||
public CommandBuilder andArriveAtDestination(){
|
||||
return addCommand(C_AND_ARRIVE_DESTINATION);
|
||||
}
|
||||
|
||||
public CommandBuilder arrivedAtDestination(){
|
||||
return addCommand(C_REACHED_DESTINATION);
|
||||
}
|
||||
|
||||
public CommandBuilder bearLeft(){
|
||||
return addCommand(C_BEAR_LEFT);
|
||||
}
|
||||
|
||||
public CommandBuilder bearRight(){
|
||||
return addCommand(C_BEAR_RIGHT);
|
||||
}
|
||||
|
||||
public CommandBuilder then(){
|
||||
return addCommand(C_THEN);
|
||||
}
|
||||
|
||||
public CommandBuilder newRouteCalculated(double dist){
|
||||
return addCommand(C_ROUTE_NEW_CALC, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder routeRecalculated(double dist){
|
||||
return addCommand(C_ROUTE_RECALC, dist);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void play(){
|
||||
CommandPlayer.this.playCommands(this);
|
||||
}
|
||||
|
||||
protected List<String> execute(){
|
||||
alreadyExecuted = true;
|
||||
return CommandPlayer.this.execute(listStruct);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
package net.osmand.plus.voice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import alice.tuprolog.Struct;
|
||||
|
||||
public interface CommandPlayer {
|
||||
|
||||
public abstract String getCurrentVoice();
|
||||
|
||||
public abstract CommandBuilder newCommandBuilder();
|
||||
|
||||
public abstract void playCommands(CommandBuilder builder);
|
||||
|
||||
public abstract void clear();
|
||||
|
||||
public abstract List<String> execute(List<Struct> listStruct);
|
||||
|
||||
}
|
20
OsmAnd/src/net/osmand/plus/voice/CommandPlayerException.java
Normal file
20
OsmAnd/src/net/osmand/plus/voice/CommandPlayerException.java
Normal file
|
@ -0,0 +1,20 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
/**
|
||||
* Exception on CommandPlayer
|
||||
*
|
||||
* @author Pavol Zibrita <pavol.zibrita@gmail.com>
|
||||
*/
|
||||
public class CommandPlayerException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 8413902962574061832L;
|
||||
private final String error;
|
||||
|
||||
public CommandPlayerException(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
}
|
31
OsmAnd/src/net/osmand/plus/voice/CommandPlayerFactory.java
Normal file
31
OsmAnd/src/net/osmand/plus/voice/CommandPlayerFactory.java
Normal file
|
@ -0,0 +1,31 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.activities.OsmandApplication;
|
||||
import android.content.Context;
|
||||
|
||||
public class CommandPlayerFactory {
|
||||
|
||||
public static CommandPlayer createCommandPlayer(String voiceProvider, OsmandApplication osmandApplication, Context ctx)
|
||||
throws CommandPlayerException
|
||||
{
|
||||
if (voiceProvider != null){
|
||||
File parent = OsmandSettings.getOsmandSettings(ctx).extendOsmandPath(ResourceManager.VOICE_PATH);
|
||||
File voiceDir = new File(parent, voiceProvider);
|
||||
if(!voiceDir.exists()){
|
||||
throw new CommandPlayerException(ctx.getString(R.string.voice_data_unavailable));
|
||||
}
|
||||
if (MediaCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return new MediaCommandPlayerImpl(osmandApplication, voiceProvider);
|
||||
} else if (TTSCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return new TTSCommandPlayerImpl(osmandApplication, voiceProvider);
|
||||
}
|
||||
throw new CommandPlayerException(ctx.getString(R.string.voice_data_not_supported));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
115
OsmAnd/src/net/osmand/plus/voice/MediaCommandPlayerImpl.java
Normal file
115
OsmAnd/src/net/osmand/plus/voice/MediaCommandPlayerImpl.java
Normal file
|
@ -0,0 +1,115 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
|
||||
/**
|
||||
* That class represents command player.
|
||||
* It gets commands from input, analyze what files should be played and play
|
||||
* them using media player
|
||||
*/
|
||||
public class MediaCommandPlayerImpl extends AbstractPrologCommandPlayer {
|
||||
|
||||
private static final String CONFIG_FILE = "_config.p";
|
||||
|
||||
private static final Log log = LogUtil.getLog(MediaCommandPlayerImpl.class);
|
||||
|
||||
// playing media
|
||||
private MediaPlayer mediaPlayer;
|
||||
// indicates that player is ready to play first file
|
||||
private boolean playNext = true;
|
||||
private List<String> filesToPlay = Collections.synchronizedList(new ArrayList<String>());
|
||||
|
||||
|
||||
public MediaCommandPlayerImpl(Context ctx, String voiceProvider)
|
||||
throws CommandPlayerException
|
||||
{
|
||||
super(ctx, voiceProvider, CONFIG_FILE);
|
||||
mediaPlayer = new MediaPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
mediaPlayer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playCommands(CommandBuilder builder){
|
||||
filesToPlay.addAll(builder.execute());
|
||||
playQueue();
|
||||
}
|
||||
|
||||
private synchronized void playQueue() {
|
||||
while (!filesToPlay.isEmpty() && playNext) {
|
||||
String f = filesToPlay.remove(0);
|
||||
if (f != null && voiceDir != null) {
|
||||
boolean exists = false;
|
||||
// if(voiceZipFile != null){
|
||||
// ZipEntry entry = voiceZipFile.getEntry(f);
|
||||
// exists = entry != null;
|
||||
// voiceZipFile.getInputStream(entry);
|
||||
//
|
||||
// } else {
|
||||
File file = new File(voiceDir, f);
|
||||
exists = file.exists();
|
||||
// }
|
||||
if (exists) {
|
||||
log.debug("Playing file : " + f); //$NON-NLS-1$
|
||||
playNext = false;
|
||||
try {
|
||||
// Can't play sound file from zip it seams to be impossible only unpack and play!!!
|
||||
mediaPlayer.setDataSource(file.getAbsolutePath());
|
||||
mediaPlayer.prepare();
|
||||
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mp.release();
|
||||
mediaPlayer = new MediaPlayer();
|
||||
int sleep = 60;
|
||||
boolean delay = true;
|
||||
while (!filesToPlay.isEmpty() && delay) {
|
||||
delay = filesToPlay.get(0).startsWith(DELAY_CONST);
|
||||
if (delay) {
|
||||
String s = filesToPlay.remove(0).substring(DELAY_CONST.length());
|
||||
try {
|
||||
sleep += Integer.parseInt(s);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(sleep);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
playNext = true;
|
||||
playQueue();
|
||||
}
|
||||
});
|
||||
|
||||
mediaPlayer.start();
|
||||
} catch (Exception e) {
|
||||
log.error("Error while playing voice command", e); //$NON-NLS-1$
|
||||
playNext = true;
|
||||
|
||||
}
|
||||
} else {
|
||||
log.info("Play file not found : " + f); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMyData(File voiceDir) {
|
||||
return new File(voiceDir, CONFIG_FILE).exists();
|
||||
}
|
||||
}
|
39
OsmAnd/src/net/osmand/plus/voice/TTSCommandPlayerImpl.java
Normal file
39
OsmAnd/src/net/osmand/plus/voice/TTSCommandPlayerImpl.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.plus.activities.InitTTSActivity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
|
||||
public class TTSCommandPlayerImpl extends AbstractPrologCommandPlayer {
|
||||
|
||||
private static final String CONFIG_FILE = "_ttsconfig.p";
|
||||
|
||||
protected TTSCommandPlayerImpl(Context ctx, String voiceProvider) throws CommandPlayerException {
|
||||
super(ctx, voiceProvider, CONFIG_FILE);
|
||||
final Intent intent = new Intent(ctx, InitTTSActivity.class);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
ctx.startActivity(intent);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playCommands(CommandBuilder builder) {
|
||||
if (TTSOsmand.mTts != null) {
|
||||
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(' ');
|
||||
}
|
||||
TTSOsmand.mTts.speak(bld.toString(), TextToSpeech.QUEUE_ADD, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMyData(File voiceDir) {
|
||||
return new File(voiceDir, CONFIG_FILE).exists();
|
||||
}
|
||||
|
||||
}
|
9
OsmAnd/src/net/osmand/plus/voice/TTSOsmand.java
Normal file
9
OsmAnd/src/net/osmand/plus/voice/TTSOsmand.java
Normal file
|
@ -0,0 +1,9 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import android.speech.tts.TextToSpeech;
|
||||
|
||||
public class TTSOsmand {
|
||||
|
||||
public static TextToSpeech mTts;
|
||||
|
||||
}
|
124
OsmAnd/voice/en-tts/_ttsconfig.p
Normal file
124
OsmAnd/voice/en-tts/_ttsconfig.p
Normal file
|
@ -0,0 +1,124 @@
|
|||
:- op('==', xfy, 500).
|
||||
version(0).
|
||||
|
||||
|
||||
% before each announcement (beep)
|
||||
preamble - [].
|
||||
|
||||
|
||||
%% TURNS
|
||||
turn('left', ['turn.ogg', 'left-e.ogg']).
|
||||
turn('left_sh', ['sharp_left-e.ogg']).
|
||||
turn('left_sl', ['turn.ogg', 'left-e.ogg']).
|
||||
turn('right', ['turn.ogg', 'right-e.ogg']).
|
||||
turn('right_sh', ['sharp_right-e.ogg']).
|
||||
turn('right_sl', ['turn.ogg', 'right-e.ogg']).
|
||||
|
||||
prepare_turn(Turn, Dist) == ['Prepare_to-a.ogg', 'after-m.ogg', delay_450, D, delay_450, M] :-
|
||||
distance(Dist) == D, turn(Turn, M).
|
||||
turn(Turn, Dist) == ['after-m.ogg', delay_250, D, delay_250, M] :-
|
||||
distance(Dist) == D, turn(Turn, M).
|
||||
turn(Turn) == M :- turn(Turn, M).
|
||||
|
||||
|
||||
prepare_make_ut(Dist) == ['Prepare_to-a.ogg', 'after-m.ogg', delay_300, D, delay_300,'turn_back-e.ogg'] :-
|
||||
distance(Dist) == D.
|
||||
|
||||
prepare_roundabout(Dist) == ['prepare_to-enter.ogg', 'after-m.ogg', delay_300, D] :-
|
||||
distance(Dist) == D.
|
||||
|
||||
make_ut(Dist) == ['after-m.ogg', delay_300, D, delay_300, 'turn_back-e.ogg'] :-
|
||||
distance(Dist) == D.
|
||||
make_ut == ['turn_back-e.ogg'].
|
||||
|
||||
roundabout(Dist, _Angle, Exit) == ['after-m.ogg', delay_300, D, delay_300, 'enter_the_roundabout-e.ogg', delay_250, 'and_take.ogg',
|
||||
delay_250, E, 'exit-e.ogg'] :- distance(Dist) == D, nth(Exit, E).
|
||||
roundabout(_Angle, Exit) == ['taking.ogg', delay_250, E, 'exit-e.ogg'] :- nth(Exit, E).
|
||||
|
||||
and_arrive_destination == ['arrive_at_your_destination-e.ogg']. % Miss and?
|
||||
then == ['then.ogg', delay_350].
|
||||
reached_destination == ['you_have_reached_your_destination.ogg'].
|
||||
bear_right == ['keep_right-e.ogg'].
|
||||
bear_left == ['keep_left-e.ogg'].
|
||||
route_recalc(_Dist) == []. % ['recalc.ogg']. %nothing to said possibly beep?
|
||||
route_new_calc(Dist) == ['the_trip_is_more_than.ogg', delay_150, D] :- distance(Dist) == D. % nothing to said possibly beep?
|
||||
|
||||
go_ahead(Dist) == ['drive_for-h.ogg', delay_250, D]:- distance(Dist) == D.
|
||||
go_ahead == ['continue_straight-e.ogg'].
|
||||
|
||||
%%
|
||||
nth(1, '1st.ogg').
|
||||
nth(2, '2nd.ogg').
|
||||
nth(3, '3rd.ogg').
|
||||
nth(4, '4th.ogg').
|
||||
nth(5, '5th.ogg').
|
||||
nth(6, '6th.ogg').
|
||||
nth(7, '7th.ogg').
|
||||
nth(8, '8th.ogg').
|
||||
nth(9, '9th.ogg').
|
||||
nth(10, '10th.ogg').
|
||||
nth(11, '11th.ogg').
|
||||
nth(12, '12th.ogg').
|
||||
nth(13, '13th.ogg').
|
||||
nth(14, '14th.ogg').
|
||||
nth(15, '15th.ogg').
|
||||
nth(16, '16th.ogg').
|
||||
nth(17, '17th.ogg').
|
||||
|
||||
|
||||
%%% distance measure
|
||||
distance(Dist) == T :- Dist < 1000, dist(Dist, F), append(F, 'meters-e.ogg',T).
|
||||
dist(D, ['10.ogg']) :- D < 20, !.
|
||||
dist(D, ['20.ogg']) :- D < 30, !.
|
||||
dist(D, ['30.ogg']) :- D < 40, !.
|
||||
dist(D, ['40.ogg']) :- D < 50, !.
|
||||
dist(D, ['50.ogg']) :- D < 60, !.
|
||||
dist(D, ['60.ogg']) :- D < 70, !.
|
||||
dist(D, ['70.ogg']) :- D < 80, !.
|
||||
dist(D, ['80.ogg']) :- D < 90, !.
|
||||
dist(D, ['90.ogg']) :- D < 100, !.
|
||||
dist(D, ['100.ogg']) :- D < 150, !.
|
||||
dist(D, ['100_and.ogg', '50.ogg']) :- D < 200, !.
|
||||
dist(D, ['200.ogg']) :- D < 250, !.
|
||||
dist(D, ['200_and.ogg', '50.ogg']) :- D < 300, !.
|
||||
dist(D, ['300.ogg']) :- D < 350, !.
|
||||
dist(D, ['300_and.ogg', '50.ogg']) :- D < 400, !.
|
||||
dist(D, ['400.ogg']) :- D < 450, !.
|
||||
dist(D, ['400_and.ogg', '50.ogg']) :- D < 500, !.
|
||||
dist(D, ['500.ogg']) :- D < 550, !.
|
||||
dist(D, ['500_and.ogg', '50.ogg']) :- D < 600, !.
|
||||
dist(D, ['600.ogg']) :- D < 650, !.
|
||||
dist(D, ['600_and.ogg', '50.ogg']) :- D < 700, !.
|
||||
dist(D, ['700.ogg']) :- D < 750, !.
|
||||
dist(D, ['700_and.ogg', '50.ogg']) :- D < 800, !.
|
||||
dist(D, ['800.ogg']) :- D < 850, !.
|
||||
dist(D, ['800_and.ogg', '50.ogg']) :- D < 900, !.
|
||||
dist(D, ['900.ogg']) :- D < 950, !.
|
||||
dist(D, ['900_and.ogg', '50.ogg']) :- !.
|
||||
|
||||
|
||||
distance(Dist) == ['more_than.ogg', '1.ogg', 'kilometer-e.ogg'] :- Dist < 1500.
|
||||
distance(Dist) == ['more_than.ogg', '2.ogg', 'kilometers-e.ogg'] :- Dist < 3000.
|
||||
distance(Dist) == ['more_than.ogg', '3.ogg', 'kilometers-e.ogg'] :- Dist < 4000.
|
||||
distance(Dist) == ['more_than.ogg', '4.ogg', 'kilometers-e.ogg'] :- Dist < 5000.
|
||||
distance(Dist) == ['more_than.ogg', '5.ogg', 'kilometers-e.ogg'] :- Dist < 6000.
|
||||
distance(Dist) == ['more_than.ogg', '6.ogg', 'kilometers-e.ogg'] :- Dist < 7000.
|
||||
distance(Dist) == ['more_than.ogg', '7.ogg', 'kilometers-e.ogg'] :- Dist < 8000.
|
||||
distance(Dist) == ['more_than.ogg', '8.ogg', 'kilometers-e.ogg'] :- Dist < 9000.
|
||||
distance(Dist) == ['more_than.ogg', '9.ogg', 'kilometers-e.ogg'] :- Dist < 10000.
|
||||
distance(Dist) == ['more_than.ogg', X, 'kilometers-e.ogg'] :- D is Dist/1000, dist(D, X).
|
||||
|
||||
|
||||
|
||||
%% resolve command main method
|
||||
%% if you are familar with Prolog you can input specific to the whole mechanism,
|
||||
%% by adding exception cases.
|
||||
flatten(X, Y) :- flatten(X, [], Y), !.
|
||||
flatten([], Acc, Acc).
|
||||
flatten([X|Y], Acc, Res):-
|
||||
flatten(Y, Acc, R), flatten(X, R, Res).
|
||||
flatten(X, Acc, [X|Acc]).
|
||||
|
||||
resolve(X, Y) :- resolve_impl(X,Z), flatten(Z, Y).
|
||||
resolve_impl([],[]).
|
||||
resolve_impl([X|Rest], List) :- resolve_impl(Rest, Tail), ((X == L) -> append(L, Tail, List); List = Tail).
|
Loading…
Reference in a new issue