diff --git a/OsmAnd/build.gradle b/OsmAnd/build.gradle index ccfc56a840..267a49b5b4 100644 --- a/OsmAnd/build.gradle +++ b/OsmAnd/build.gradle @@ -363,6 +363,8 @@ dependencies { implementation 'com.vividsolutions:jts-core:1.14.0' implementation 'com.squareup.picasso:picasso:2.71828' + // JS core + //implementation 'com.github.LiquidPlayer:LiquidCore:0.4.6' // size restrictions // implementation 'com.ibm.icu:icu4j:50.1' // implementation 'net.sf.trove4j:trove4j:3.0.3' diff --git a/OsmAnd/src/net/osmand/plus/routing/JSVoiceRouter.java b/OsmAnd/src/net/osmand/plus/routing/JSVoiceRouter.java new file mode 100644 index 0000000000..26cb438580 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routing/JSVoiceRouter.java @@ -0,0 +1,324 @@ +package net.osmand.plus.routing; + +import net.osmand.Location; +import net.osmand.binary.RouteDataObject; +import net.osmand.plus.OsmandSettings; +import net.osmand.plus.voice.CommandBuilder; +import net.osmand.plus.voice.JSCommandBuilder; +import net.osmand.router.RouteSegmentResult; +import net.osmand.router.TurnType; + +import java.util.HashMap; +import java.util.Map; + + + +public class JSVoiceRouter extends VoiceRouter { + + public JSVoiceRouter(RoutingHelper router, OsmandSettings settings) { + super(router, settings); + } + + public Map getSpeakableJSStreetName(RouteSegmentResult currentSegment, RouteDirectionInfo i, boolean includeDest) { + Map result = new HashMap<>(); + if (i == null || !router.getSettings().SPEAK_STREET_NAMES.get()) { + return result; + } + if (player != null && player.supportsStructuredStreetNames()) { + + // Issue 2377: Play Dest here only if not already previously announced, to avoid repetition + if (includeDest == true) { + result.put("toRef", getSpeakablePointName(i.getRef())); + result.put("toStreetName", getSpeakablePointName(i.getStreetName())); + result.put("toDest", getSpeakablePointName(i.getDestinationName())); + } else { + result.put("toRef", getSpeakablePointName(i.getRef())); + result.put("toStreetName", getSpeakablePointName(i.getStreetName())); + result.put("toDest", ""); + } + if (currentSegment != null) { + // Issue 2377: Play Dest here only if not already previously announced, to avoid repetition + if (includeDest == true) { + RouteDataObject obj = currentSegment.getObject(); + result.put("fromRef", getSpeakablePointName(obj.getRef(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection()))); + result.put("fromStreetName", getSpeakablePointName(obj.getName(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get()))); + result.put("fromDest", getSpeakablePointName(obj.getDestinationName(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection()))); + } else { + RouteDataObject obj = currentSegment.getObject(); + result.put("fromRef", getSpeakablePointName(obj.getRef(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection()))); + result.put("fromStreetName", getSpeakablePointName(obj.getName(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get()))); + result.put("fromDest", ""); + } + } + + } else { + result.put("toRef", getSpeakablePointName(i.getRef())); + result.put("toStreetName", getSpeakablePointName(i.getStreetName())); + } + return result; + } + + /** + * Updates status of voice guidance + * @param currentLocation + */ + protected void updateStatus(Location currentLocation, boolean repeat) { + // Directly after turn: goAhead (dist), unless: + // < PREPARE_LONG_DISTANCE (e.g. 3500m): playPrepareTurn (-not played any more-) + // < PREPARE_DISTANCE (e.g. 1500m): playPrepareTurn ("Turn after ...") + // < TURN_IN_DISTANCE (e.g. 390m or 30sec): playMakeTurnIn ("Turn in ...") + // < TURN_DISTANCE (e.g. 50m or 7sec): playMakeTurn ("Turn ...") + float speed = DEFAULT_SPEED; + if (currentLocation != null && currentLocation.hasSpeed()) { + speed = Math.max(currentLocation.getSpeed(), speed); + } + + RouteCalculationResult.NextDirectionInfo nextInfo = router.getNextRouteDirectionInfo(new RouteCalculationResult.NextDirectionInfo(), true); + RouteSegmentResult currentSegment = router.getCurrentSegmentResult(); + if (nextInfo == null || nextInfo.directionInfo == null) { + return; + } + int dist = nextInfo.distanceTo; + RouteDirectionInfo next = nextInfo.directionInfo; + + // If routing is changed update status to unknown + if (next != nextRouteDirection) { + nextRouteDirection = next; + currentStatus = STATUS_UNKNOWN; + suppressDest = false; + playedAndArriveAtTarget = false; + announceBackOnRoute = false; + if (playGoAheadDist != -1) { + playGoAheadDist = 0; + } + } + + if (!repeat) { + if (dist <= 0) { + return; + } else if (needsInforming()) { + playGoAhead(dist, getSpeakableJSStreetName(currentSegment, next, false)); + return; + } else if (currentStatus == STATUS_TOLD) { + // nothing said possibly that's wrong case we should say before that + // however it should be checked manually ? + return; + } + } + + if (currentStatus == STATUS_UNKNOWN) { + // Play "Continue for ..." if (1) after route calculation no other prompt is due, or (2) after a turn if next turn is more than PREPARE_LONG_DISTANCE away + if ((playGoAheadDist == -1) || (dist > PREPARE_LONG_DISTANCE)) { + playGoAheadDist = dist - 3 * TURN_DISTANCE; + } + } + + RouteCalculationResult.NextDirectionInfo nextNextInfo = router.getNextRouteDirectionInfoAfter(nextInfo, new RouteCalculationResult.NextDirectionInfo(), true); //I think "true" is correct here, not "!repeat" + // Note: getNextRouteDirectionInfoAfter(nextInfo, x, y).distanceTo is distance from nextInfo, not from current position! + + // STATUS_TURN = "Turn (now)" + if ((repeat || statusNotPassed(STATUS_TURN)) && isDistanceLess(speed, dist, TURN_DISTANCE, TURN_DEFAULT_SPEED)) { + if (nextNextInfo.distanceTo < TURN_IN_DISTANCE_END && nextNextInfo != null) { + playMakeTurn(currentSegment, next, nextNextInfo); + } else { + playMakeTurn(currentSegment, next, null); + } + if (!next.getTurnType().goAhead() && isTargetPoint(nextNextInfo)) { // !goAhead() avoids isolated "and arrive.." prompt, as goAhead() is not pronounced + if (nextNextInfo.distanceTo < TURN_IN_DISTANCE_END) { + // Issue #2865: Ensure a distance associated with the destination arrival is always announced, either here, or in subsequent "Turn in" prompt + // Distance fon non-straights already announced in "Turn (now)"'s nextnext code above + if ((nextNextInfo != null) && (nextNextInfo.directionInfo != null) && nextNextInfo.directionInfo.getTurnType().goAhead()) { + playThen(); + playGoAhead(nextNextInfo.distanceTo, new HashMap()); + } + playAndArriveAtDestination(nextNextInfo); + } else if (nextNextInfo.distanceTo < 1.2f * TURN_IN_DISTANCE_END) { + // 1.2 is safety margin should the subsequent "Turn in" prompt not fit in amy more + playThen(); + playGoAhead(nextNextInfo.distanceTo, new HashMap()); + playAndArriveAtDestination(nextNextInfo); + } + } + nextStatusAfter(STATUS_TURN); + + // STATUS_TURN_IN = "Turn in ..." + } else if ((repeat || statusNotPassed(STATUS_TURN_IN)) && isDistanceLess(speed, dist, TURN_IN_DISTANCE, 0f)) { + if (repeat || dist >= TURN_IN_DISTANCE_END) { + if ((isDistanceLess(speed, nextNextInfo.distanceTo, TURN_DISTANCE, 0f) || nextNextInfo.distanceTo < TURN_IN_DISTANCE_END) && + nextNextInfo != null) { + playMakeTurnIn(currentSegment, next, dist - (int) btScoDelayDistance, nextNextInfo.directionInfo); + } else { + playMakeTurnIn(currentSegment, next, dist - (int) btScoDelayDistance, null); + } + playGoAndArriveAtDestination(repeat, nextInfo, currentSegment); + } + nextStatusAfter(STATUS_TURN_IN); + + // STATUS_PREPARE = "Turn after ..." + } else if ((repeat || statusNotPassed(STATUS_PREPARE)) && (dist <= PREPARE_DISTANCE)) { + if (repeat || dist >= PREPARE_DISTANCE_END) { + if (!repeat && (next.getTurnType().keepLeft() || next.getTurnType().keepRight())) { + // Do not play prepare for keep left/right + } else { + playPrepareTurn(currentSegment, next, dist); + playGoAndArriveAtDestination(repeat, nextInfo, currentSegment); + } + } + nextStatusAfter(STATUS_PREPARE); + + // STATUS_LONG_PREPARE = also "Turn after ...", we skip this now, users said this is obsolete + } else if ((repeat || statusNotPassed(STATUS_LONG_PREPARE)) && (dist <= PREPARE_LONG_DISTANCE)) { + if (repeat || dist >= PREPARE_LONG_DISTANCE_END) { + playPrepareTurn(currentSegment, next, dist); + playGoAndArriveAtDestination(repeat, nextInfo, currentSegment); + } + nextStatusAfter(STATUS_LONG_PREPARE); + + // STATUS_UNKNOWN = "Continue for ..." if (1) after route calculation no other prompt is due, or (2) after a turn if next turn is more than PREPARE_LONG_DISTANCE away + } else if (statusNotPassed(STATUS_UNKNOWN)) { + // Strange how we get here but + nextStatusAfter(STATUS_UNKNOWN); + } else if (repeat || (statusNotPassed(STATUS_PREPARE) && dist < playGoAheadDist)) { + playGoAheadDist = 0; + playGoAhead(dist, getSpeakableJSStreetName(currentSegment, next, false)); + } + } + + private void playPrepareTurn(RouteSegmentResult currentSegment, RouteDirectionInfo next, int dist) { + JSCommandBuilder play = (JSCommandBuilder) getNewCommandPlayerToPlay(); + if (play != null) { + String tParam = getTurnType(next.getTurnType()); + if (tParam != null) { + notifyOnVoiceMessage(); + play.prepareTurn(tParam, dist, getSpeakableJSStreetName(currentSegment, next, true)).play(); + } else if (next.getTurnType().isRoundAbout()) { + notifyOnVoiceMessage(); + play.prepareRoundAbout(dist, next.getTurnType().getExitOut(), getSpeakableJSStreetName(currentSegment, next, true)).play(); + } else if (next.getTurnType().getValue() == TurnType.TU || next.getTurnType().getValue() == TurnType.TRU) { + notifyOnVoiceMessage(); + play.prepareMakeUT(dist, getSpeakableJSStreetName(currentSegment, next, true)).play(); + } + } + } + + private void playMakeTurnIn(RouteSegmentResult currentSegment, RouteDirectionInfo next, int dist, RouteDirectionInfo pronounceNextNext) { + JSCommandBuilder play = (JSCommandBuilder) getNewCommandPlayerToPlay(); + if (play != null) { + String tParam = getTurnType(next.getTurnType()); + boolean isPlay = true; + if (tParam != null) { + play.turn(tParam, dist, getSpeakableJSStreetName(currentSegment, next, true)); + suppressDest = true; + } else if (next.getTurnType().isRoundAbout()) { + play.roundAbout(dist, next.getTurnType().getTurnAngle(), next.getTurnType().getExitOut(), getSpeakableJSStreetName(currentSegment, next, true)); + // Other than in prepareTurn, in prepareRoundabout we do not announce destination, so we can repeat it one more time + suppressDest = false; + } else if (next.getTurnType().getValue() == TurnType.TU || next.getTurnType().getValue() == TurnType.TRU) { + play.makeUT(dist, getSpeakableJSStreetName(currentSegment, next, true)); + suppressDest = true; + } else { + isPlay = false; + } + // 'then keep' preparation for next after next. (Also announces an interim straight segment, which is not pronounced above.) + if (pronounceNextNext != null) { + TurnType t = pronounceNextNext.getTurnType(); + isPlay = true; + if (t.getValue() != TurnType.C && next.getTurnType().getValue() == TurnType.C) { + play.goAhead(dist, getSpeakableJSStreetName(currentSegment, next, true)); + } + if (t.getValue() == TurnType.TL || t.getValue() == TurnType.TSHL || t.getValue() == TurnType.TSLL + || t.getValue() == TurnType.TU || t.getValue() == TurnType.KL ) { + play.then().bearLeft( getSpeakableJSStreetName(currentSegment, next, false)); + } else if (t.getValue() == TurnType.TR || t.getValue() == TurnType.TSHR || t.getValue() == TurnType.TSLR + || t.getValue() == TurnType.TRU || t.getValue() == TurnType.KR) { + play.then().bearRight( getSpeakableJSStreetName(currentSegment, next, false)); + } + } + if (isPlay) { + notifyOnVoiceMessage(); + play.play(); + } + } + } + + private void playGoAhead(int dist, Map streetName) { + CommandBuilder play = getNewCommandPlayerToPlay(); + JSCommandBuilder playJs = (JSCommandBuilder) play; + if (play != null) { + notifyOnVoiceMessage(); + playJs.goAhead(dist, streetName).play(); + } + } + + private void playMakeTurn(RouteSegmentResult currentSegment, RouteDirectionInfo next, RouteCalculationResult.NextDirectionInfo nextNextInfo) { + JSCommandBuilder play = (JSCommandBuilder) getNewCommandPlayerToPlay(); + if (play != null) { + String tParam = getTurnType(next.getTurnType()); + boolean isplay = true; + if (tParam != null) { + play.turn(tParam, getSpeakableJSStreetName(currentSegment, next, !suppressDest)); + } else if (next.getTurnType().isRoundAbout()) { + play.roundAbout(next.getTurnType().getTurnAngle(), next.getTurnType().getExitOut(), getSpeakableJSStreetName(currentSegment, next, !suppressDest)); + } else if (next.getTurnType().getValue() == TurnType.TU || next.getTurnType().getValue() == TurnType.TRU) { + play.makeUT(getSpeakableJSStreetName(currentSegment, next, !suppressDest)); + // Do not announce goAheads + //} else if (next.getTurnType().getValue() == TurnType.C)) { + // play.goAhead(); + } else { + isplay = false; + } + // Add turn after next + if ((nextNextInfo != null) && (nextNextInfo.directionInfo != null)) { + + // This case only needed should we want a prompt at the end of straight segments (equivalent of makeTurn) when nextNextInfo should be announced again there. + if (nextNextInfo.directionInfo.getTurnType().getValue() != TurnType.C && next.getTurnType().getValue() == TurnType.C) { + play.goAhead(); + isplay = true; + } + + String t2Param = getTurnType(nextNextInfo.directionInfo.getTurnType()); + if (t2Param != null) { + if (isplay) { + play.then(); + play.turn(t2Param, nextNextInfo.distanceTo, new HashMap()); + } + } else if (nextNextInfo.directionInfo.getTurnType().isRoundAbout()) { + if (isplay) { + play.then(); + play.roundAbout(nextNextInfo.distanceTo, nextNextInfo.directionInfo.getTurnType().getTurnAngle(), + nextNextInfo.directionInfo.getTurnType().getExitOut(), new HashMap()); + } + } else if (nextNextInfo.directionInfo.getTurnType().getValue() == TurnType.TU) { + if (isplay) { + play.then(); + play.makeUT(nextNextInfo.distanceTo, new HashMap()); + } + } + } + if (isplay) { + notifyOnVoiceMessage(); + play.play(); + } + } + } + + private void playGoAndArriveAtDestination(boolean repeat, RouteCalculationResult.NextDirectionInfo nextInfo, RouteSegmentResult currentSegment) { + RouteDirectionInfo next = nextInfo.directionInfo; + if (isTargetPoint(nextInfo) && (!playedAndArriveAtTarget || repeat)) { + if (next.getTurnType().goAhead()) { + playGoAhead(nextInfo.distanceTo, getSpeakableJSStreetName(currentSegment, next, false)); + playAndArriveAtDestination(nextInfo); + playedAndArriveAtTarget = true; + } else if (nextInfo.distanceTo <= 2 * TURN_IN_DISTANCE) { + playAndArriveAtDestination(nextInfo); + playedAndArriveAtTarget = true; + } + } + } + +} diff --git a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java index fa15b79b5d..c34f97f44b 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -97,7 +97,8 @@ public class RoutingHelper { public RoutingHelper(OsmandApplication context){ this.app = context; settings = context.getSettings(); - voiceRouter = new VoiceRouter(this, settings); + voiceRouter = settings.USE_JS_VOICE_GUIDANCE.get() ?new JSVoiceRouter(this, settings) + : new VoiceRouter(this, settings); provider = new RouteProvider(); setAppMode(settings.APPLICATION_MODE.get()); } diff --git a/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java b/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java index cab1e395ff..6ef3f69def 100644 --- a/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java +++ b/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java @@ -28,27 +28,27 @@ import android.media.SoundPool; public class VoiceRouter { private static final int STATUS_UTWP_TOLD = -1; - private static final int STATUS_UNKNOWN = 0; - private static final int STATUS_LONG_PREPARE = 1; - private static final int STATUS_PREPARE = 2; - private static final int STATUS_TURN_IN = 3; - private static final int STATUS_TURN = 4; - private static final int STATUS_TOLD = 5; + static final int STATUS_UNKNOWN = 0; + static final int STATUS_LONG_PREPARE = 1; + static final int STATUS_PREPARE = 2; + static final int STATUS_TURN_IN = 3; + static final int STATUS_TURN = 4; + static final int STATUS_TOLD = 5; - private final RoutingHelper router; - private static CommandPlayer player; - private final OsmandSettings settings; + protected final RoutingHelper router; + protected static CommandPlayer player; + protected final OsmandSettings settings; private static boolean mute = false; - private static int currentStatus = STATUS_UNKNOWN; - private static boolean playedAndArriveAtTarget = false; - private static float playGoAheadDist = 0; + static int currentStatus = STATUS_UNKNOWN; + static boolean playedAndArriveAtTarget = false; + static float playGoAheadDist = 0; private static long lastAnnouncedSpeedLimit = 0; private static long waitAnnouncedSpeedLimit = 0; private static long lastAnnouncedOffRoute = 0; private static long waitAnnouncedOffRoute = 0; - private static boolean suppressDest = false; - private static boolean announceBackOnRoute = false; + static boolean suppressDest = false; + static boolean announceBackOnRoute = false; // private static long lastTimeRouteRecalcAnnounced = 0; // Remember when last announcement was made private static long lastAnnouncement = 0; @@ -66,7 +66,7 @@ public class VoiceRouter { protected int TURN_DISTANCE = 0; protected static VoiceCommandPending pendingCommand = null; - private static RouteDirectionInfo nextRouteDirection; + static RouteDirectionInfo nextRouteDirection; private Term empty; private boolean useJS; @@ -167,7 +167,7 @@ public class VoiceRouter { } } - private double btScoDelayDistance = 0; + double btScoDelayDistance = 0; public boolean isDistanceLess(float currentSpeed, double dist, double etalon, float defSpeed) { if (defSpeed <= 0) { @@ -204,7 +204,7 @@ public class VoiceRouter { } } - private void nextStatusAfter(int previousStatus) { + void nextStatusAfter(int previousStatus) { //STATUS_UNKNOWN=0 -> STATUS_LONG_PREPARE=1 -> STATUS_PREPARE=2 -> STATUS_TURN_IN=3 -> STATUS_TURN=4 -> STATUS_TOLD=5 if (previousStatus != STATUS_TOLD) { this.currentStatus = previousStatus + 1; @@ -213,7 +213,7 @@ public class VoiceRouter { } } - private boolean statusNotPassed(int statusToCheck) { + boolean statusNotPassed(int statusToCheck) { return currentStatus <= statusToCheck; } @@ -398,14 +398,14 @@ public class VoiceRouter { } } - private boolean isTargetPoint(NextDirectionInfo info) { + boolean isTargetPoint(NextDirectionInfo info) { boolean in = info != null && info.intermediatePoint; boolean target = info == null || info.directionInfo == null || info.directionInfo.distance == 0; return in || target; } - private boolean needsInforming() { + boolean needsInforming() { final Integer repeat = settings.KEEP_INFORMING.get(); if (repeat == null || repeat == 0) return false; @@ -560,7 +560,7 @@ public class VoiceRouter { return false; } - private void playThen() { + void playThen() { CommandBuilder play = getNewCommandPlayerToPlay(); if (play != null) { notifyOnVoiceMessage(); @@ -718,7 +718,7 @@ public class VoiceRouter { } } - private void playAndArriveAtDestination(NextDirectionInfo info) { + void playAndArriveAtDestination(NextDirectionInfo info) { if (isTargetPoint(info)) { String pointName = info == null ? "" : info.pointName; CommandBuilder play = getNewCommandPlayerToPlay(); @@ -784,7 +784,7 @@ public class VoiceRouter { } } - private String getTurnType(TurnType t) { + String getTurnType(TurnType t) { if (TurnType.TL == t.getValue()) { return AbstractPrologCommandPlayer.A_LEFT; } else if (TurnType.TSHL == t.getValue()) { diff --git a/OsmAnd/src/net/osmand/plus/voice/AbstractJSCommandPlayer.java b/OsmAnd/src/net/osmand/plus/voice/AbstractJSCommandPlayer.java index 09db3cee5b..bb36ecfa0a 100644 --- a/OsmAnd/src/net/osmand/plus/voice/AbstractJSCommandPlayer.java +++ b/OsmAnd/src/net/osmand/plus/voice/AbstractJSCommandPlayer.java @@ -39,7 +39,7 @@ public class AbstractJSCommandPlayer implements CommandPlayer { @Override public String getLanguage() { - return null; + return "en"; } @Override diff --git a/OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java b/OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java index e8bffb4912..a3116afcfd 100644 --- a/OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java +++ b/OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java @@ -3,7 +3,12 @@ package net.osmand.plus.voice; import net.osmand.PlatformUtil; import org.apache.commons.logging.Log; +//import org.liquidplayer.javascript.JSContext; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -13,45 +18,25 @@ public class JSCommandBuilder extends CommandBuilder { private static final Log log = PlatformUtil.getLog(JSCommandBuilder.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_MAKE_UTWP = "make_ut_wp"; //$NON-NLS-1$ - protected static final String C_AND_ARRIVE_DESTINATION = "and_arrive_destination"; //$NON-NLS-1$ - protected static final String C_REACHED_DESTINATION = "reached_destination"; //$NON-NLS-1$ - protected static final String C_AND_ARRIVE_INTERMEDIATE = "and_arrive_intermediate"; //$NON-NLS-1$ - protected static final String C_REACHED_INTERMEDIATE = "reached_intermediate"; //$NON-NLS-1$ - protected static final String C_AND_ARRIVE_WAYPOINT = "and_arrive_waypoint"; //$NON-NLS-1$ - protected static final String C_AND_ARRIVE_FAVORITE = "and_arrive_favorite"; //$NON-NLS-1$ - protected static final String C_AND_ARRIVE_POI_WAYPOINT = "and_arrive_poi"; //$NON-NLS-1$ - protected static final String C_REACHED_WAYPOINT = "reached_waypoint"; //$NON-NLS-1$ - protected static final String C_REACHED_FAVORITE = "reached_favorite"; //$NON-NLS-1$ - protected static final String C_REACHED_POI = "reached_poi"; //$NON-NLS-1$ - protected static final String C_THEN = "then"; //$NON-NLS-1$ - protected static final String C_SPEAD_ALARM = "speed_alarm"; //$NON-NLS-1$ - protected static final String C_ATTENTION = "attention"; //$NON-NLS-1$ - protected static final String C_OFF_ROUTE = "off_route"; //$NON-NLS-1$ - protected static final String C_BACK_ON_ROUTE ="back_on_route"; //$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 C_LOCATION_LOST = "location_lost"; //$NON-NLS-1$ - protected static final String C_LOCATION_RECOVERED = "location_recovered"; //$NON-NLS-1$ - - +// private JSContext jsContext; private List listStruct = new ArrayList<>(); public JSCommandBuilder(CommandPlayer commandPlayer) { super(commandPlayer); +// jsContext = new JSContext(); } + public void setJSContext(String path) { +// String script = null; +// try { +// byte[] encoded = Files.readAllBytes(Paths.get(path)); +// script = new String(encoded, "UTF-8"); +// } catch (IOException e) { +// log.error(e.getMessage()); +// } +// if (script != null) +//// jsContext.evaluateScript(script); + } public void setParameters(String metricCons, boolean tts) { // TODO Set the parameters to js context diff --git a/OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java b/OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java index 4caefad1f7..f602c1df0d 100644 --- a/OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java +++ b/OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java @@ -46,6 +46,7 @@ public class JSTTSCommandPlayerImpl extends AbstractJSCommandPlayer { @Override public JSCommandBuilder newCommandBuilder() { JSCommandBuilder commandBuilder = new JSCommandBuilder(this); + commandBuilder.setJSContext(app.getSettings().VOICE_PROVIDER.get() + "en_tts.js"); commandBuilder.setParameters(app.getSettings().METRIC_SYSTEM.get().toHumanString(app), true); return commandBuilder; } @@ -91,7 +92,7 @@ public class JSTTSCommandPlayerImpl extends AbstractJSCommandPlayer { @Override public String getLanguage() { - return null; + return "en"; } @Override