From cf5b44cbf15f0439561678d57f69b545b75b0891 Mon Sep 17 00:00:00 2001 From: PaulStets Date: Tue, 21 Aug 2018 15:07:30 +0300 Subject: [PATCH] Refactoring of the js voice guidance --- .../plus/development/TestVoiceActivity.java | 171 +++------ .../osmand/plus/routing/JSVoiceRouter.java | 330 ------------------ .../osmand/plus/routing/RoutingHelper.java | 4 +- .../net/osmand/plus/routing/VoiceRouter.java | 157 ++++----- .../osmand/plus/routing/data/StreetName.java | 56 +++ .../net/osmand/plus/voice/CommandBuilder.java | 95 ++--- .../osmand/plus/voice/JSCommandBuilder.java | 34 +- 7 files changed, 254 insertions(+), 593 deletions(-) delete mode 100644 OsmAnd/src/net/osmand/plus/routing/JSVoiceRouter.java create mode 100644 OsmAnd/src/net/osmand/plus/routing/data/StreetName.java diff --git a/OsmAnd/src/net/osmand/plus/development/TestVoiceActivity.java b/OsmAnd/src/net/osmand/plus/development/TestVoiceActivity.java index 45e2bc42ef..b1b4b32dcf 100644 --- a/OsmAnd/src/net/osmand/plus/development/TestVoiceActivity.java +++ b/OsmAnd/src/net/osmand/plus/development/TestVoiceActivity.java @@ -21,6 +21,7 @@ import net.osmand.IndexConstants; import net.osmand.plus.OsmandApplication; import net.osmand.plus.R; import net.osmand.plus.activities.OsmandActionBarActivity; +import net.osmand.plus.routing.data.StreetName; import net.osmand.plus.voice.AbstractPrologCommandPlayer; import net.osmand.plus.voice.JSCommandBuilder; import net.osmand.plus.voice.JSMediaCommandPlayerImpl; @@ -134,148 +135,84 @@ public class TestVoiceActivity extends OsmandActionBarActivity { private String getVoiceSystemInfo() { String v =""; - v += " \u25CF App profile: " + ((OsmandApplication) getApplication()).getSettings().APPLICATION_MODE.get().getStringKey(); + v += " \u25CF App profile: " + ((OsmandApplication) getApplication()).getSettings().APPLICATION_MODE.get().getStringKey(); if (((OsmandApplication) getApplication()).getSettings().AUDIO_STREAM_GUIDANCE.get() == 3) { - v += "\n \u25CF Voice guidance output: Media/music audio"; + v += "\n \u25CF Voice guidance output: Media/music audio"; } else if (((OsmandApplication) getApplication()).getSettings().AUDIO_STREAM_GUIDANCE.get() == 5) { - v += "\n \u25CF Voice guidance output: Notification audio"; + v += "\n \u25CF Voice guidance output: Notification audio"; } else if (((OsmandApplication) getApplication()).getSettings().AUDIO_STREAM_GUIDANCE.get() == 0) { - v += "\n \u25CF Voice guidance output: Phone call audio"; + v += "\n \u25CF Voice guidance output: Phone call audio"; } else { - v += "\n \u25CF Voice guidance output: " + ((OsmandApplication) getApplication()).getSettings().AUDIO_STREAM_GUIDANCE.get(); + v += "\n \u25CF Voice guidance output: " + ((OsmandApplication) getApplication()).getSettings().AUDIO_STREAM_GUIDANCE.get(); } - v += "\n \u25CF OsmAnd voice: " + osmandVoice; - v += "\n \u25CF OsmAnd voice language: " + osmandVoiceLang; + v += "\n \u25CF OsmAnd voice: " + osmandVoice; + v += "\n \u25CF OsmAnd voice language: " + osmandVoiceLang; if (AbstractPrologCommandPlayer.getCurrentVersion() > 99) { - v += "\n \u25CF Voice language availability: " + TTSCommandPlayerImpl.getTtsVoiceStatus(); - v += "\n \u25CF Voice actually used: " + TTSCommandPlayerImpl.getTtsVoiceUsed(); + v += "\n \u25CF Voice language availability: " + TTSCommandPlayerImpl.getTtsVoiceStatus(); + v += "\n \u25CF Voice actually used: " + TTSCommandPlayerImpl.getTtsVoiceUsed(); } else { - v += "\n \u25CF Voice language availability: Recorded voice"; - v += "\n \u25CF Voice actually used: Recorded voice"; + v += "\n \u25CF Voice language availability: Recorded voice"; + v += "\n \u25CF Voice actually used: Recorded voice"; } if (((OsmandApplication) getApplication()).getSettings().AUDIO_STREAM_GUIDANCE.get() == 0) { - v += "\n \u25CF BT SCO: " + AbstractPrologCommandPlayer.btScoInit; + v += "\n \u25CF BT SCO: " + AbstractPrologCommandPlayer.btScoInit; } else { - v += "\n \u25CF BT SCO: The current app profile is not set to use 'Phone call audio'."; + v += "\n \u25CF BT SCO: The current app profile is not set to use 'Phone call audio'."; } - v += "\n \u25CF Phone call audio delay: " + ((OsmandApplication) getApplication()).getSettings().BT_SCO_DELAY.get() + "\u00A0ms"; + v += "\n \u25CF Phone call audio delay: " + ((OsmandApplication) getApplication()).getSettings().BT_SCO_DELAY.get() + "\u00A0ms"; return v; } - private Term street(CommandPlayer p, String name) { - return street(p, name, "", "", ""); - } - - private Term street(CommandPlayer p, String name, String ref) { - return street(p, name, ref, "", ""); - } - - private Term street(CommandPlayer p, String name, String ref, String dest) { - return street(p, name, ref, dest, ""); - } - - private Term getTermString(String s) { - if(!Algorithms.isEmpty(s)) { - return new Struct(s); - } - return new Struct(""); - } - - private Term street(CommandPlayer p, String name, String ref, String destName, String currentName) { - // Pass all test strings through our character replacement method - ref = VoiceRouter.getSpeakablePointName(ref); - name = VoiceRouter.getSpeakablePointName(name); - destName = VoiceRouter.getSpeakablePointName(destName); - currentName = VoiceRouter.getSpeakablePointName(currentName); - - if(p.supportsStructuredStreetNames()) { - Struct next = new Struct(new Term[] { getTermString(ref), - getTermString(name), - getTermString(destName) }); - Term current = new Struct(""); - if (currentName.length() > 0) { - current = new Struct(new Term[] { getTermString(""), - getTermString(currentName), - getTermString("") }); - } - Struct voice = new Struct("voice", next, current ); - return voice; - } - return new Struct(name); - } - private void addButtons(final LinearLayout ll, CommandPlayer p) { - boolean isJS = p instanceof JSTTSCommandPlayerImpl || p instanceof JSMediaCommandPlayerImpl; addButton(ll, "Route calculated and number tests:", builder(p)); - addButton(ll, "\u25BA (1.1) New route calculated, 150m, 230sec (00:03:50)", !isJS ? builder(p).newRouteCalculated(150, 230) : jsBuilder(p).newRouteCalculated(150, 230)); - addButton(ll, "\u25BA (1.2) New route calculated, 1350m, 3680sec (01:01:20)", !isJS ? builder(p).newRouteCalculated(1350, 3680) : jsBuilder(p).newRouteCalculated(1350, 3680)); - addButton(ll, "\u25BA (1.3) New route calculated 3700m, 7320sec (02:02)", !isJS ? builder(p).newRouteCalculated(3700, 7320) : jsBuilder(p).newRouteCalculated(3700, 7320)); - addButton(ll, "\u25BA (1.4) New route calculated 9100m, 10980sec (03:03)", !isJS ? builder(p).newRouteCalculated(9100, 10980) : jsBuilder(p).newRouteCalculated(9100, 10980)); - addButton(ll, "\u25BA (2.1) Route recalculated 11500m, 18600sec (05:10)", !isJS ? builder(p).routeRecalculated(11500, 18600) : jsBuilder(p).routeRecalculated(11500, 18600)); - addButton(ll, "\u25BA (2.2) Route recalculated 19633m, 26700sec (07:25)", !isJS ? builder(p).routeRecalculated(19633, 26700) : jsBuilder(p).routeRecalculated(19633, 26700)); - addButton(ll, "\u25BA (2.3) Route recalculated 89750m, 55800sec (15:30)", !isJS ? builder(p).routeRecalculated(89750, 55800) : jsBuilder(p).routeRecalculated(89750, 55800)); - addButton(ll, "\u25BA (2.4) Route recalculated 125900m, 92700sec (25:45)", !isJS ? builder(p).routeRecalculated(125900, 92700) : jsBuilder(p).routeRecalculated(125900, 92700)); + addButton(ll, "\u25BA (1.1) New route calculated, 150m, 230sec (00:03:50)", builder(p).newRouteCalculated(150, 230)); + addButton(ll, "\u25BA (1.2) New route calculated, 1350m, 3680sec (01:01:20)", builder(p).newRouteCalculated(1350, 3680)); + addButton(ll, "\u25BA (1.3) New route calculated 3700m, 7320sec (02:02)", builder(p).newRouteCalculated(3700, 7320)); + addButton(ll, "\u25BA (1.4) New route calculated 9100m, 10980sec (03:03)", builder(p).newRouteCalculated(9100, 10980)); + addButton(ll, "\u25BA (2.1) Route recalculated 11500m, 18600sec (05:10)", builder(p).routeRecalculated(11500, 18600)); + addButton(ll, "\u25BA (2.2) Route recalculated 19633m, 26700sec (07:25)", builder(p).routeRecalculated(19633, 26700) ); + addButton(ll, "\u25BA (2.3) Route recalculated 89750m, 55800sec (15:30)", builder(p).routeRecalculated(89750, 55800) ); + addButton(ll, "\u25BA (2.4) Route recalculated 125900m, 92700sec (25:45)", builder(p).routeRecalculated(125900, 92700) ); addButton(ll, "All turn types: prepareTurn, makeTurnIn, turn:", builder(p)); - addButton(ll, "\u25BA (3.1) After 1520m turn slightly left", !isJS ? builder(p).prepareTurn(AbstractPrologCommandPlayer.A_LEFT_SL, 1520, street(p, "")) : - jsBuilder(p).prepareTurn(AbstractPrologCommandPlayer.A_LEFT_SL, 1520, jsStreet(p, ""))); - addButton(ll, "\u25BA (3.2) In 450m turn sharply left onto 'Hauptstra"+"\u00df"+"e', then bear right", !isJS ? builder(p).turn(AbstractPrologCommandPlayer.A_LEFT_SH, 450, street(p, "Hauptstraße")).then().bearRight(street(p, "")) : - jsBuilder(p).turn(AbstractPrologCommandPlayer.A_LEFT_SH, 450, jsStreet(p, "Hauptstraße")).then().bearRight(jsStreet(p, ""))); - addButton(ll, "\u25BA (3.3) Turn left, then in 100m turn slightly right", !isJS ? builder(p).turn(AbstractPrologCommandPlayer.A_LEFT, street(p, "")).then().turn(AbstractPrologCommandPlayer.A_RIGHT_SL, 100, street(p, "")) : - jsBuilder(p).turn(AbstractPrologCommandPlayer.A_LEFT, jsStreet(p, "")).then().turn(AbstractPrologCommandPlayer.A_RIGHT_SL, 100, jsStreet(p, ""))); - addButton(ll, "\u25BA (3.4) After 3100m turn right onto 'SR 80' toward 'Rome'", !isJS ? builder(p).prepareTurn(AbstractPrologCommandPlayer.A_RIGHT, 3100, street(p, "", "SR 80", "Rome")) : - jsBuilder(p).prepareTurn(AbstractPrologCommandPlayer.A_RIGHT, 3100, jsStreet(p, "", "SR 80", "Rome"))); - addButton(ll, "\u25BA (3.5) In 370m turn slightly right onto 'Route 23' 'Main Street', then bear left", !isJS ? builder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_SL, 370, street(p, "Main Street", "Route 23")).then().bearLeft(street(p, "")) : - jsBuilder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_SL, 370, jsStreet(p, "Main jsStreet", "Route 23")).then().bearLeft(jsStreet(p, ""))); - addButton(ll, "\u25BA (3.6) Turn sharply right onto 'Dr.-Quinn-Stra"+"\u00df"+"e'", !isJS ? builder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_SH, street(p, "Dr.-Quinn-Straße")) : - jsBuilder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_SH, jsStreet(p, "Dr.-Quinn-Straße"))); + addButton(ll, "\u25BA (3.1) After 1520m turn slightly left", builder(p).prepareTurn(AbstractPrologCommandPlayer.A_LEFT_SL, 1520, street(p, ""))); + addButton(ll, "\u25BA (3.2) In 450m turn sharply left onto 'Hauptstra"+"\u00df"+"e', then bear right", builder(p).turn(AbstractPrologCommandPlayer.A_LEFT_SH, 450, street(p, "Hauptstraße")).then().bearRight(street(p, ""))); + addButton(ll, "\u25BA (3.3) Turn left, then in 100m turn slightly right", builder(p).turn(AbstractPrologCommandPlayer.A_LEFT, street(p, "")).then().turn(AbstractPrologCommandPlayer.A_RIGHT_SL, 100, street(p, ""))); + addButton(ll, "\u25BA (3.4) After 3100m turn right onto 'SR 80' toward 'Rome'", builder(p).prepareTurn(AbstractPrologCommandPlayer.A_RIGHT, 3100, street(p, "", "SR 80", "Rome"))); + addButton(ll, "\u25BA (3.5) In 370m turn slightly right onto 'Route 23' 'Main Street', then bear left", builder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_SL, 370, street(p, "Main Street", "Route 23")).then().bearLeft(street(p, ""))); + addButton(ll, "\u25BA (3.6) Turn sharply right onto 'Dr.-Quinn-Stra"+"\u00df"+"e'", builder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_SH, street(p, "Dr.-Quinn-Straße"))); addButton(ll, "Keep left/right: prepareTurn, makeTurnIn, turn:", builder(p)); - addButton(ll, "\u25BA (4.1) After 1810m keep left ' '", !isJS ? builder(p).prepareTurn(AbstractPrologCommandPlayer.A_LEFT_KEEP, 1810, street(p, "")) : - jsBuilder(p).prepareTurn(AbstractPrologCommandPlayer.A_LEFT_KEEP, 1810, jsStreet(p, ""))); - addButton(ll, "\u25BA (4.2) In 400m keep left ' ' then in 80m keep right onto 'A1'", !isJS ? builder(p).turn(AbstractPrologCommandPlayer.A_LEFT_KEEP, 400, street(p, "")).then().turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, 80, street(p,"", "A1")) : - jsBuilder(p).turn(AbstractPrologCommandPlayer.A_LEFT_KEEP, 400, jsStreet(p, "")).then().turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, 80, jsStreet(p,"", "A1"))); - addButton(ll, "\u25BA (4.3) Keep right on 'Highway 60'", !isJS ? builder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, street(p, "Highway 60", "", "", "Highway 60")) : - jsBuilder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, jsStreet(p, "Highway 60", "", "", "Highway 60"))); - addButton(ll, "\u25BA (4.4) Turn left onto 'Broadway', then in 100m keep right and arrive at your destination 'Town Hall'", !isJS ? + addButton(ll, "\u25BA (4.1) After 1810m keep left ' '", builder(p).prepareTurn(AbstractPrologCommandPlayer.A_LEFT_KEEP, 1810, street(p, ""))); + addButton(ll, "\u25BA (4.2) In 400m keep left ' ' then in 80m keep right onto 'A1'", builder(p).turn(AbstractPrologCommandPlayer.A_LEFT_KEEP, 400, street(p, "")).then().turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, 80, street(p,"", "A1"))); + addButton(ll, "\u25BA (4.3) Keep right on 'Highway 60'", builder(p).turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, street(p, "Highway 60", "", "", "Highway 60"))); + addButton(ll, "\u25BA (4.4) Turn left onto 'Broadway', then in 100m keep right and arrive at your destination 'Town Hall'", builder(p).turn(AbstractPrologCommandPlayer.A_LEFT, street(p, "Broadway")) - .then().turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, 100, street(p, "")).andArriveAtDestination("Town Hall") : - jsBuilder(p).turn(AbstractPrologCommandPlayer.A_LEFT, jsStreet(p, "Broadway")) - .then().turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, 100, jsStreet(p, "")).andArriveAtDestination("Town Hall")); - + .then().turn(AbstractPrologCommandPlayer.A_RIGHT_KEEP, 100, street(p, "")).andArriveAtDestination("Town Hall")); addButton(ll, "Roundabouts: prepareTurn, makeTurnIn, turn:", builder(p)); - addButton(ll, "\u25BA (5.1) After 1250m enter a roundabout", !isJS ? builder(p).prepareRoundAbout(1250, 3, street(p,"", "I 15", "Los Angeles")) : - jsBuilder(p).prepareRoundAbout(1250, 3, jsStreet(p,"", "I 15", "Los Angeles"))); - addButton(ll, "\u25BA (5.2) In 450m enter the roundabout and take the 1st exit onto 'I 15' toward 'Los Angeles'", !isJS ? builder(p).roundAbout(450, 0, 1, street(p,"", "I 15", "Los Angeles")) : - jsBuilder(p).roundAbout(450, 0, 1, jsStreet(p,"", "I 15", "Los Angeles"))); - addButton(ll, "\u25BA (5.3) Roundabout: Take the 2nd exit onto 'Highway 60'", !isJS ? builder(p).roundAbout(0, 2, street(p, "Highway 60")) : - jsBuilder(p).roundAbout(0, 2, jsStreet(p, "Highway 60"))); + addButton(ll, "\u25BA (5.1) After 1250m enter a roundabout", builder(p).prepareRoundAbout(1250, 3, street(p,"", "I 15", "Los Angeles"))); + addButton(ll, "\u25BA (5.2) In 450m enter the roundabout and take the 1st exit onto 'I 15' toward 'Los Angeles'", builder(p).roundAbout(450, 0, 1, street(p,"", "I 15", "Los Angeles"))); + addButton(ll, "\u25BA (5.3) Roundabout: Take the 2nd exit onto 'Highway 60'", builder(p).roundAbout(0, 2, street(p, "Highway 60"))); addButton(ll, "U-turns: prepareTurn, makeTurnIn, turn, when possible:", builder(p)); - addButton(ll, "\u25BA (6.1) After 640m make a U-turn", !isJS ? builder(p).prepareMakeUT(640, street(p, "")) : - jsBuilder(p).prepareMakeUT(640, jsStreet(p, ""))); - addButton(ll, "\u25BA (6.2) In 400m make a U-turn", !isJS ? builder(p).makeUT(400, street(p, "")) : - jsBuilder(p).makeUT(400, jsStreet(p, ""))); - addButton(ll, "\u25BA (6.3) Make a U-turn on 'Riviera'", !isJS ? builder(p).makeUT(street(p, "Riviera", "", "", "Riviera")) : - jsBuilder(p).makeUT(jsStreet(p, "Riviera", "", "", "Riviera"))); + addButton(ll, "\u25BA (6.1) After 640m make a U-turn", builder(p).prepareMakeUT(640, street(p, ""))); + addButton(ll, "\u25BA (6.2) In 400m make a U-turn", builder(p).makeUT(400, street(p, ""))); + addButton(ll, "\u25BA (6.3) Make a U-turn on 'Riviera'", builder(p).makeUT(street(p, "Riviera", "", "", "Riviera"))); addButton(ll, "\u25BA (6.4) When possible, make a U-turn", builder(p).makeUTwp()); addButton(ll, "Go straight, follow the road, approaching:", builder(p)); addButton(ll, "\u25BA (7.1) Straight ahead", builder(p).goAhead()); - addButton(ll, "\u25BA (7.2) Continue for 2350m to ' '", !isJS ? builder(p).goAhead(2350, street(p, "")) : - jsBuilder(p).goAhead(2350, jsStreet(p, ""))); - addButton(ll, "\u25BA (7.3) Continue for 360m to 'Broadway' and arrive at your intermediate destination ' '", !isJS ? builder(p).goAhead(360, street(p,"Broadway")).andArriveAtIntermediatePoint("") : - jsBuilder(p).goAhead(360, jsStreet(p,"Broadway")).andArriveAtIntermediatePoint("")); - addButton(ll, "\u25BA (7.4) Continue for 800m to 'Dr Martin Luther King Jr Boulevard' and arrive at your destination ' '", !isJS ? builder(p).goAhead(800, street(p,"", "Dr Martin Luther King Jr Boulevard")).andArriveAtDestination("") : - jsBuilder(p).goAhead(800, jsStreet(p,"", "Dr Martin Luther King Jr Boulevard")).andArriveAtDestination("")); - addButton(ll, "\u25BA (7.5) Continue for 200m and pass GPX waypoint 'Trailhead'", !isJS ? builder(p).goAhead(200, null).andArriveAtWayPoint("Trailhead") : jsBuilder(p).goAhead(200, new HashMap()).andArriveAtWayPoint("Trailhead")); - addButton(ll, "\u25BA (7.6) Continue for 400m and pass favorite 'Brewery'", !isJS ? builder(p).goAhead(400, null).andArriveAtFavorite("Brewery") : jsBuilder(p).goAhead(400, new HashMap()).andArriveAtFavorite("Brewery")); - addButton(ll, "\u25BA (7.7) Continue for 600m and pass POI 'Museum'", !isJS ? builder(p).goAhead(600, null).andArriveAtPoi("Museum") : jsBuilder(p).goAhead(600, new HashMap()).andArriveAtPoi("Museum")); + addButton(ll, "\u25BA (7.2) Continue for 2350m to ' '", builder(p).goAhead(2350, street(p))); + addButton(ll, "\u25BA (7.3) Continue for 360m to 'Broadway' and arrive at your intermediate destination ' '", builder(p).goAhead(360, street(p,"Broadway")).andArriveAtIntermediatePoint("")); + addButton(ll, "\u25BA (7.4) Continue for 800m to 'Dr Martin Luther King Jr Boulevard' and arrive at your destination ' '", builder(p).goAhead(800, street(p,"", "Dr Martin Luther King Jr Boulevard")).andArriveAtDestination("")); + addButton(ll, "\u25BA (7.5) Continue for 200m and pass GPX waypoint 'Trailhead'", builder(p).goAhead(200, new StreetName()).andArriveAtWayPoint("Trailhead") ); + addButton(ll, "\u25BA (7.6) Continue for 400m and pass favorite 'Brewery'", builder(p).goAhead(400, new StreetName()).andArriveAtFavorite("Brewery") ); + addButton(ll, "\u25BA (7.7) Continue for 600m and pass POI 'Museum'", builder(p).goAhead(600, new StreetName()).andArriveAtPoi("Museum") ); addButton(ll, "Arriving and passing points:", builder(p)); addButton(ll, "\u25BA (8.1) Arrive at your destination 'Home'", builder(p).arrivedAtDestination("Home")); @@ -307,10 +244,10 @@ public class TestVoiceActivity extends OsmandActionBarActivity { ll.forceLayout(); } - private Map jsStreet(CommandPlayer p, String... args) { + private StreetName street(CommandPlayer p, String... args) { Map res = new HashMap<>(); if (!p.supportsStructuredStreetNames()) { - return res; + return new StreetName(); } String[] streetNames = new String[]{"toRef", "toStreetName", "toDest", "fromRef", "fromStreetName", "fromDest"}; for (int i = 0; i < args.length; i++) { @@ -321,17 +258,13 @@ public class TestVoiceActivity extends OsmandActionBarActivity { res.put(streetName, ""); } } - return res; + return new StreetName(res); } private CommandBuilder builder(CommandPlayer p){ return p.newCommandBuilder(); } - private JSCommandBuilder jsBuilder(CommandPlayer p) { - return (JSCommandBuilder) p.newCommandBuilder(); - } - public void addButton(ViewGroup layout, final String description, final CommandBuilder builder){ final Button button = new Button(this); button.setGravity(Gravity.LEFT); @@ -385,9 +318,9 @@ public class TestVoiceActivity extends OsmandActionBarActivity { public boolean onOptionsItemSelected(MenuItem item) { int itemId = item.getItemId(); switch (itemId) { - case android.R.id.home: - finish(); - return true; + case android.R.id.home: + finish(); + return true; } return false; } diff --git a/OsmAnd/src/net/osmand/plus/routing/JSVoiceRouter.java b/OsmAnd/src/net/osmand/plus/routing/JSVoiceRouter.java deleted file mode 100644 index 393c39957a..0000000000 --- a/OsmAnd/src/net/osmand/plus/routing/JSVoiceRouter.java +++ /dev/null @@ -1,330 +0,0 @@ -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", getNonNullString(getSpeakablePointName(i.getRef()))); - result.put("toStreetName", getNonNullString(getSpeakablePointName(i.getStreetName()))); - result.put("toDest", getNonNullString(getSpeakablePointName(i.getDestinationName()))); - } else { - result.put("toRef", getNonNullString(getSpeakablePointName(i.getRef()))); - result.put("toStreetName", getNonNullString(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", getNonNullString(getSpeakablePointName(obj.getRef(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection())))); - result.put("fromStreetName", getNonNullString(getSpeakablePointName(obj.getName(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get())))); - result.put("fromDest", getNonNullString(getSpeakablePointName(obj.getDestinationName(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection())))); - } else { - RouteDataObject obj = currentSegment.getObject(); - result.put("fromRef", getNonNullString(getSpeakablePointName(obj.getRef(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection())))); - result.put("fromStreetName", getNonNullString(getSpeakablePointName(obj.getName(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get())))); - result.put("fromDest", ""); - } - } - - } else { - result.put("toRef", getNonNullString(getSpeakablePointName(i.getRef()))); - result.put("toStreetName", getNonNullString(getSpeakablePointName(i.getStreetName()))); - result.put("toDest", ""); - } - return result; - } - - private String getNonNullString(String speakablePointName) { - return speakablePointName == null ? "" : speakablePointName; - } - - /** - * Updates status of voice guidance - * @param currentLocation - */ - @Override - 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 f246cbac77..fa15b79b5d 100644 --- a/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java +++ b/OsmAnd/src/net/osmand/plus/routing/RoutingHelper.java @@ -97,9 +97,7 @@ public class RoutingHelper { public RoutingHelper(OsmandApplication context){ this.app = context; settings = context.getSettings(); - boolean useJS = settings.USE_JS_VOICE_GUIDANCE.get(); - voiceRouter = useJS ? new JSVoiceRouter(this, settings) - : new VoiceRouter(this, settings); + voiceRouter = 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 6ef3f69def..6a78be862e 100644 --- a/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java +++ b/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java @@ -2,7 +2,9 @@ package net.osmand.plus.routing; import java.io.IOException; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import net.osmand.Location; @@ -13,6 +15,7 @@ import net.osmand.plus.OsmandSettings; import net.osmand.plus.helpers.WaypointHelper.LocationPointWrapper; import net.osmand.plus.routing.AlarmInfo.AlarmInfoType; import net.osmand.plus.routing.RouteCalculationResult.NextDirectionInfo; +import net.osmand.plus.routing.data.StreetName; import net.osmand.plus.voice.AbstractPrologCommandPlayer; import net.osmand.plus.voice.CommandBuilder; import net.osmand.plus.voice.CommandPlayer; @@ -28,48 +31,51 @@ import android.media.SoundPool; public class VoiceRouter { private static final int STATUS_UTWP_TOLD = -1; - 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 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; + public static final String TO_REF = "toRef"; + public static final String TO_STREET_NAME = "toStreetName"; + public static final String TO_DEST = "toDest"; + public static final String FROM_REF = "fromRef"; + public static final String FROM_STREET_NAME = "fromStreetName"; + public static final String FROM_DEST = "fromDest"; + protected final RoutingHelper router; protected static CommandPlayer player; protected final OsmandSettings settings; private static boolean mute = false; - static int currentStatus = STATUS_UNKNOWN; - static boolean playedAndArriveAtTarget = false; - static float playGoAheadDist = 0; + private static int currentStatus = STATUS_UNKNOWN; + private static boolean playedAndArriveAtTarget = false; + private static float playGoAheadDist = 0; private static long lastAnnouncedSpeedLimit = 0; private static long waitAnnouncedSpeedLimit = 0; private static long lastAnnouncedOffRoute = 0; private static long waitAnnouncedOffRoute = 0; - static boolean suppressDest = false; - static boolean announceBackOnRoute = false; + private static boolean suppressDest = false; + private static boolean announceBackOnRoute = false; // private static long lastTimeRouteRecalcAnnounced = 0; // Remember when last announcement was made private static long lastAnnouncement = 0; // Default speed to have comfortable announcements (Speed in m/s) - protected float DEFAULT_SPEED = 12; - protected float TURN_DEFAULT_SPEED = 5; + private float DEFAULT_SPEED = 12; + private float TURN_DEFAULT_SPEED = 5; - protected int PREPARE_LONG_DISTANCE = 0; - protected int PREPARE_LONG_DISTANCE_END = 0; + private int PREPARE_LONG_DISTANCE = 0; + private int PREPARE_LONG_DISTANCE_END = 0; protected int PREPARE_DISTANCE = 0; - protected int PREPARE_DISTANCE_END = 0; - protected int TURN_IN_DISTANCE = 0; - protected int TURN_IN_DISTANCE_END = 0; - protected int TURN_DISTANCE = 0; + private int PREPARE_DISTANCE_END = 0; + private int TURN_IN_DISTANCE = 0; + private int TURN_IN_DISTANCE_END = 0; + private int TURN_DISTANCE = 0; - protected static VoiceCommandPending pendingCommand = null; - static RouteDirectionInfo nextRouteDirection; - private Term empty; - - private boolean useJS; + private static VoiceCommandPending pendingCommand = null; + private static RouteDirectionInfo nextRouteDirection; public interface VoiceMessageListener { void onVoiceMessage(); @@ -77,17 +83,15 @@ public class VoiceRouter { private ConcurrentHashMap voiceMessageListeners; - public VoiceRouter(RoutingHelper router, final OsmandSettings settings) { + VoiceRouter(RoutingHelper router, final OsmandSettings settings) { this.router = router; this.settings = settings; - useJS = settings.USE_JS_VOICE_GUIDANCE.get(); - this.mute = settings.VOICE_MUTE.get(); - empty = new Struct(""); + mute = settings.VOICE_MUTE.get(); voiceMessageListeners = new ConcurrentHashMap(); } public void setPlayer(CommandPlayer player) { - this.player = player; + VoiceRouter.player = player; if (pendingCommand != null && player != null) { CommandBuilder newCommand = getNewCommandPlayerToPlay(); if (newCommand != null) { @@ -109,7 +113,7 @@ public class VoiceRouter { return mute; } - protected CommandBuilder getNewCommandPlayerToPlay() { + private CommandBuilder getNewCommandPlayerToPlay() { if (player == null) { return null; } @@ -167,7 +171,7 @@ public class VoiceRouter { } } - double btScoDelayDistance = 0; + private double btScoDelayDistance = 0; public boolean isDistanceLess(float currentSpeed, double dist, double etalon, float defSpeed) { if (defSpeed <= 0) { @@ -204,7 +208,7 @@ public class VoiceRouter { } } - void nextStatusAfter(int previousStatus) { + private 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 +217,7 @@ public class VoiceRouter { } } - boolean statusNotPassed(int statusToCheck) { + private boolean statusNotPassed(int statusToCheck) { return currentStatus <= statusToCheck; } @@ -237,7 +241,7 @@ public class VoiceRouter { public void announceBackOnRoute() { CommandBuilder p = getNewCommandPlayerToPlay(); - if (announceBackOnRoute == true) { + if (announceBackOnRoute) { if (p != null) { notifyOnVoiceMessage(); p.backOnRoute().play(); @@ -398,14 +402,14 @@ public class VoiceRouter { } } - boolean isTargetPoint(NextDirectionInfo info) { + private boolean isTargetPoint(NextDirectionInfo info) { boolean in = info != null && info.intermediatePoint; boolean target = info == null || info.directionInfo == null || info.directionInfo.distance == 0; return in || target; } - boolean needsInforming() { + private boolean needsInforming() { final Integer repeat = settings.KEEP_INFORMING.get(); if (repeat == null || repeat == 0) return false; @@ -485,13 +489,13 @@ public class VoiceRouter { // 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, empty); + playGoAhead(nextNextInfo.distanceTo, new StreetName()); } 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, empty); + playGoAhead(nextNextInfo.distanceTo, new StreetName()); playAndArriveAtDestination(nextNextInfo); } } @@ -568,7 +572,7 @@ public class VoiceRouter { } } - private void playGoAhead(int dist, Term streetName) { + private void playGoAhead(int dist, StreetName streetName) { CommandBuilder play = getNewCommandPlayerToPlay(); if (play != null) { notifyOnVoiceMessage(); @@ -576,57 +580,54 @@ public class VoiceRouter { } } - public Term getSpeakableStreetName(RouteSegmentResult currentSegment, RouteDirectionInfo i, boolean includeDest) { + private StreetName getSpeakableStreetName(RouteSegmentResult currentSegment, RouteDirectionInfo i, boolean includeDest) { + Map result = new HashMap<>(); if (i == null || !router.getSettings().SPEAK_STREET_NAMES.get()) { - return empty; + return new StreetName(result); } if (player != null && player.supportsStructuredStreetNames()) { - Term next = empty; + // Issue 2377: Play Dest here only if not already previously announced, to avoid repetition if (includeDest == true) { - next = new Struct(new Term[] { getTermString(getSpeakablePointName(i.getRef())), - getTermString(getSpeakablePointName(i.getStreetName())), - getTermString(getSpeakablePointName(i.getDestinationName())) }); + result.put(TO_REF, getNonNullString(getSpeakablePointName(i.getRef()))); + result.put(TO_STREET_NAME, getNonNullString(getSpeakablePointName(i.getStreetName()))); + result.put(TO_DEST, getNonNullString(getSpeakablePointName(i.getDestinationName()))); } else { - next = new Struct(new Term[] { getTermString(getSpeakablePointName(i.getRef())), - getTermString(getSpeakablePointName(i.getStreetName())), - empty }); + result.put(TO_REF, getNonNullString(getSpeakablePointName(i.getRef()))); + result.put(TO_STREET_NAME, getNonNullString(getSpeakablePointName(i.getStreetName()))); + result.put(TO_DEST, ""); } - Term current = empty; if (currentSegment != null) { // Issue 2377: Play Dest here only if not already previously announced, to avoid repetition if (includeDest == true) { RouteDataObject obj = currentSegment.getObject(); - current = new Struct(new Term[] { getTermString(getSpeakablePointName(obj.getRef(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection()))), - getTermString(getSpeakablePointName(obj.getName(settings.MAP_PREFERRED_LOCALE.get(), settings.MAP_TRANSLITERATE_NAMES.get()))), - getTermString(getSpeakablePointName(obj.getDestinationName(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection()))) }); + result.put(FROM_REF, getNonNullString(getSpeakablePointName(obj.getRef(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection())))); + result.put(FROM_STREET_NAME, getNonNullString(getSpeakablePointName(obj.getName(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get())))); + result.put(FROM_DEST, getNonNullString(getSpeakablePointName(obj.getDestinationName(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection())))); } else { RouteDataObject obj = currentSegment.getObject(); - current = new Struct(new Term[] { getTermString(getSpeakablePointName(obj.getRef(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection()))), - getTermString(getSpeakablePointName(obj.getName(settings.MAP_PREFERRED_LOCALE.get(), - settings.MAP_TRANSLITERATE_NAMES.get()))), - empty }); + result.put(FROM_REF, getNonNullString(getSpeakablePointName(obj.getRef(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get(), currentSegment.isForwardDirection())))); + result.put(FROM_STREET_NAME, getNonNullString(getSpeakablePointName(obj.getName(settings.MAP_PREFERRED_LOCALE.get(), + settings.MAP_TRANSLITERATE_NAMES.get())))); + result.put(FROM_DEST, ""); } } - Struct voice = new Struct("voice", next, current ); - return voice; + } else { - Term rf = getTermString(getSpeakablePointName(i.getRef())); - if (rf == empty) { - rf = getTermString(getSpeakablePointName(i.getStreetName())); - } - return rf; + result.put("toRef", getNonNullString(getSpeakablePointName(i.getRef()))); + result.put(TO_STREET_NAME, getNonNullString(getSpeakablePointName(i.getStreetName()))); + result.put(TO_DEST, ""); } + return new StreetName(result); } - - private Term getTermString(String s) { - if (!Algorithms.isEmpty(s)) { - return new Struct(s); - } - return empty; + + + private String getNonNullString(String speakablePointName) { + return speakablePointName == null ? "" : speakablePointName; } public static String getSpeakablePointName(String pn) { @@ -718,7 +719,7 @@ public class VoiceRouter { } } - void playAndArriveAtDestination(NextDirectionInfo info) { + private void playAndArriveAtDestination(NextDirectionInfo info) { if (isTargetPoint(info)) { String pointName = info == null ? "" : info.pointName; CommandBuilder play = getNewCommandPlayerToPlay(); @@ -763,17 +764,17 @@ public class VoiceRouter { if (t2Param != null) { if (isplay) { play.then(); - play.turn(t2Param, nextNextInfo.distanceTo, empty); + play.turn(t2Param, nextNextInfo.distanceTo, new StreetName()); } } else if (nextNextInfo.directionInfo.getTurnType().isRoundAbout()) { if (isplay) { play.then(); - play.roundAbout(nextNextInfo.distanceTo, nextNextInfo.directionInfo.getTurnType().getTurnAngle(), nextNextInfo.directionInfo.getTurnType().getExitOut(), empty); + play.roundAbout(nextNextInfo.distanceTo, nextNextInfo.directionInfo.getTurnType().getTurnAngle(), nextNextInfo.directionInfo.getTurnType().getExitOut(), new StreetName()); } } else if (nextNextInfo.directionInfo.getTurnType().getValue() == TurnType.TU) { if (isplay) { play.then(); - play.makeUT(nextNextInfo.distanceTo, empty); + play.makeUT(nextNextInfo.distanceTo, new StreetName()); } } } @@ -784,7 +785,7 @@ public class VoiceRouter { } } - String getTurnType(TurnType t) { + private 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/routing/data/StreetName.java b/OsmAnd/src/net/osmand/plus/routing/data/StreetName.java new file mode 100644 index 0000000000..e4b90b7941 --- /dev/null +++ b/OsmAnd/src/net/osmand/plus/routing/data/StreetName.java @@ -0,0 +1,56 @@ +package net.osmand.plus.routing.data; + +import net.osmand.plus.routing.VoiceRouter; +import net.osmand.util.Algorithms; + +import java.util.HashMap; +import java.util.Map; + +import alice.tuprolog.Struct; +import alice.tuprolog.Term; + +public class StreetName { + + private Map names; + private static final Term empty = new Struct("");; + + public StreetName(Map data) { + this.names = data; + } + + public StreetName() { + names = new HashMap<>(); + } + + public Map toMap() { + return names; + } + + public Term toTerm() { + if (names == null || names.isEmpty()) { + return empty; + } + if (names.size() > 3) { + Term next = new Struct(new Term[]{getTermString(names.get(VoiceRouter.TO_REF)), + getTermString(names.get(VoiceRouter.TO_STREET_NAME)), + getTermString(names.get(VoiceRouter.TO_DEST))}); + Term current = new Struct(new Term[]{getTermString(names.get(VoiceRouter.FROM_REF)), + getTermString(names.get(VoiceRouter.FROM_STREET_NAME)), + getTermString(names.get(VoiceRouter.FROM_DEST))}); + return new Struct("voice", next, current); + } else { + Term rf = getTermString(names.get(VoiceRouter.TO_REF)); + if (rf == empty) { + rf = getTermString(names.get(VoiceRouter.TO_STREET_NAME)); + } + return rf; + } + } + + private Term getTermString(String s) { + if (!Algorithms.isEmpty(s)) { + return new Struct(s); + } + return empty; + } +} diff --git a/OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java b/OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java index 01640b1c34..779ec2ca62 100644 --- a/OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java +++ b/OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java @@ -6,6 +6,7 @@ import java.util.List; import net.osmand.PlatformUtil; import net.osmand.plus.R; +import net.osmand.plus.routing.data.StreetName; import org.apache.commons.logging.Log; @@ -41,32 +42,32 @@ public class CommandBuilder { 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$ - + /** - * + * */ protected final CommandPlayer commandPlayer; protected boolean alreadyExecuted = false; private List listStruct = new ArrayList(); - + public CommandBuilder(CommandPlayer commandPlayer){ this.commandPlayer = commandPlayer; } - + private void checkState() { if(alreadyExecuted){ throw new IllegalArgumentException(); } } - + private CommandBuilder addCommand(String name, Object... args){ Struct struct = prepareStruct(name, args); listStruct.add(struct); @@ -80,6 +81,8 @@ public class CommandBuilder { Object o = args[i]; if(o instanceof Term){ list[i] = (Term) o; + } else if (o instanceof StreetName){ + list[i] = ((StreetName)o).toTerm(); } else if(o instanceof java.lang.Number){ if(o instanceof java.lang.Double){ list[i] = new alice.tuprolog.Double((Double) o); @@ -103,7 +106,7 @@ public class CommandBuilder { } return struct; } - + private CommandBuilder alt(Struct... s1) { if (s1.length == 1) { listStruct.add(s1[0]); @@ -112,32 +115,31 @@ public class CommandBuilder { } return this; } - - + public CommandBuilder goAhead(){ return addCommand(C_GO_AHEAD); } - public CommandBuilder goAhead(double dist, Term streetName){ + public CommandBuilder goAhead(double dist, StreetName streetName){ return alt(prepareStruct(C_GO_AHEAD, dist, streetName), prepareStruct(C_GO_AHEAD, dist)); } - + public CommandBuilder makeUTwp(){ return addCommand(C_MAKE_UTWP); } - public CommandBuilder makeUT(Term streetName){ + public CommandBuilder makeUT(StreetName streetName){ return alt(prepareStruct(C_MAKE_UT, streetName), prepareStruct(C_MAKE_UT)); } - + public CommandBuilder speedAlarm(int maxSpeed, float speed){ return addCommand(C_SPEAD_ALARM, maxSpeed, speed); } - + public CommandBuilder attention(String type){ return addCommand(C_ATTENTION, type); } - + public CommandBuilder offRoute(double dist){ return addCommand(C_OFF_ROUTE, dist); } @@ -145,50 +147,49 @@ public class CommandBuilder { public CommandBuilder backOnRoute(){ return addCommand(C_BACK_ON_ROUTE); } - - public CommandBuilder makeUT(double dist, Term streetName){ + + public CommandBuilder makeUT(double dist, StreetName streetName){ return alt(prepareStruct(C_MAKE_UT, dist, streetName), prepareStruct(C_MAKE_UT, dist)); } - - public CommandBuilder prepareMakeUT(double dist, Term streetName){ + + public CommandBuilder prepareMakeUT(double dist, StreetName streetName){ return alt(prepareStruct(C_PREPARE_MAKE_UT, dist, streetName), prepareStruct(C_PREPARE_MAKE_UT, dist)); } - - - public CommandBuilder turn(String param, Term streetName) { + + public CommandBuilder turn(String param, StreetName streetName) { return alt(prepareStruct(C_TURN, param, streetName), prepareStruct(C_TURN, param)); } - - public CommandBuilder turn(String param, double dist, Term streetName){ + + public CommandBuilder turn(String param, double dist, StreetName streetName){ return alt(prepareStruct(C_TURN, param, dist, streetName), prepareStruct(C_TURN, param, dist)); } - + /** - * + * * @param param A_LEFT, A_RIGHT, ... * @param dist * @return */ - public CommandBuilder prepareTurn(String param, double dist, Term streetName){ + public CommandBuilder prepareTurn(String param, double dist, StreetName streetName){ return alt(prepareStruct(C_PREPARE_TURN, param, dist, streetName), prepareStruct(C_PREPARE_TURN, param, dist)); } - - public CommandBuilder prepareRoundAbout(double dist, int exit, Term streetName){ + + public CommandBuilder prepareRoundAbout(double dist, int exit, StreetName streetName){ return alt(prepareStruct(C_PREPARE_ROUNDABOUT, dist, exit, streetName), prepareStruct(C_PREPARE_ROUNDABOUT, dist)); } - - public CommandBuilder roundAbout(double dist, double angle, int exit, Term streetName){ + + public CommandBuilder roundAbout(double dist, double angle, int exit, StreetName streetName){ return alt(prepareStruct(C_ROUNDABOUT, dist, angle, exit, streetName), prepareStruct(C_ROUNDABOUT, dist, angle, exit)); } - - public CommandBuilder roundAbout(double angle, int exit, Term streetName) { + + public CommandBuilder roundAbout(double angle, int exit, StreetName streetName) { return alt(prepareStruct(C_ROUNDABOUT, angle, exit, streetName), prepareStruct(C_ROUNDABOUT, angle, exit)); } - + public CommandBuilder andArriveAtDestination(String name){ return alt(prepareStruct(C_AND_ARRIVE_DESTINATION, name), prepareStruct(C_AND_ARRIVE_DESTINATION)); } - + public CommandBuilder arrivedAtDestination(String name){ return alt(prepareStruct(C_REACHED_DESTINATION, name), prepareStruct(C_REACHED_DESTINATION)); } @@ -224,31 +225,31 @@ public class CommandBuilder { public CommandBuilder arrivedAtPoi(String name) { return addCommand(C_REACHED_POI, name); } - - public CommandBuilder bearLeft(Term streetName){ + + public CommandBuilder bearLeft(StreetName streetName){ return alt(prepareStruct(C_BEAR_LEFT, streetName), prepareStruct(C_BEAR_LEFT)); } - - public CommandBuilder bearRight(Term streetName){ + + public CommandBuilder bearRight(StreetName streetName){ return alt(prepareStruct(C_BEAR_RIGHT, streetName), prepareStruct(C_BEAR_RIGHT)); } - + public CommandBuilder then(){ return addCommand(C_THEN); } - + public CommandBuilder gpsLocationLost() { return addCommand(C_LOCATION_LOST); } - + public CommandBuilder gpsLocationRecover() { return addCommand(C_LOCATION_RECOVERED); } - + public CommandBuilder newRouteCalculated(double dist, int time){ return alt(prepareStruct(C_ROUTE_NEW_CALC, dist, time), prepareStruct(C_ROUTE_NEW_CALC, dist)); } - + public CommandBuilder routeRecalculated(double dist, int time){ return alt(prepareStruct(C_ROUTE_RECALC, dist, time), prepareStruct(C_ROUTE_RECALC, dist)); } @@ -256,8 +257,8 @@ public class CommandBuilder { public void play(){ this.commandPlayer.playCommands(this); } - - + + protected List execute(){ alreadyExecuted = true; return this.commandPlayer.execute(listStruct); diff --git a/OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java b/OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java index b49829a548..52a6d6ac6e 100644 --- a/OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java +++ b/OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java @@ -1,6 +1,7 @@ package net.osmand.plus.voice; import net.osmand.PlatformUtil; +import net.osmand.plus.routing.data.StreetName; import org.apache.commons.logging.Log; import org.json.JSONObject; @@ -40,8 +41,8 @@ public class JSCommandBuilder extends CommandBuilder { this.jsScope = jsScope; } - private Object convertStreetName(Map streetName) { - return NativeJSON.parse(jsContext, jsScope, new JSONObject(streetName).toString(), + private Object convertStreetName(StreetName streetName) { + return NativeJSON.parse(jsContext, jsScope, new JSONObject(streetName.toMap()).toString(), new NullCallable()); } @@ -70,18 +71,19 @@ public class JSCommandBuilder extends CommandBuilder { } public JSCommandBuilder goAhead(){ - return goAhead(-1, new HashMap()); + return goAhead(-1, new StreetName()); } - public JSCommandBuilder goAhead(double dist, Map streetName){ + public JSCommandBuilder goAhead(double dist, StreetName streetName){ return addCommand(C_GO_AHEAD, dist, convertStreetName(streetName)); } + @Override public JSCommandBuilder makeUTwp(){ - return makeUT(new HashMap()); + return makeUT(new StreetName()); } - public JSCommandBuilder makeUT(Map streetName){ + public JSCommandBuilder makeUT(StreetName streetName){ return makeUT(-1, streetName); } @Override @@ -101,20 +103,20 @@ public class JSCommandBuilder extends CommandBuilder { return addCommand(C_BACK_ON_ROUTE); } - public JSCommandBuilder makeUT(double dist, Map streetName){ + public JSCommandBuilder makeUT(double dist, StreetName streetName){ return addCommand(C_MAKE_UT, dist, convertStreetName(streetName)); } - public JSCommandBuilder prepareMakeUT(double dist, Map streetName){ + public JSCommandBuilder prepareMakeUT(double dist, StreetName streetName){ return addCommand(C_PREPARE_MAKE_UT, dist, convertStreetName(streetName)); } - public JSCommandBuilder turn(String param, Map streetName) { + public JSCommandBuilder turn(String param, StreetName streetName) { return turn(param, -1, streetName); } - public JSCommandBuilder turn(String param, double dist, Map streetName) { + public JSCommandBuilder turn(String param, double dist, StreetName streetName) { return addCommand(C_TURN, param, dist, convertStreetName(streetName)); } @@ -124,19 +126,19 @@ public class JSCommandBuilder extends CommandBuilder { * @param dist * @return */ - public JSCommandBuilder prepareTurn(String param, double dist, Map streetName){ + public JSCommandBuilder prepareTurn(String param, double dist, StreetName streetName){ return addCommand(C_PREPARE_TURN, param, dist, convertStreetName(streetName)); } - public JSCommandBuilder prepareRoundAbout(double dist, int exit, Map streetName){ + public JSCommandBuilder prepareRoundAbout(double dist, int exit, StreetName streetName){ return addCommand(C_PREPARE_ROUNDABOUT, dist, exit, convertStreetName(streetName)); } - public JSCommandBuilder roundAbout(double dist, double angle, int exit, Map streetName){ + public JSCommandBuilder roundAbout(double dist, double angle, int exit, StreetName streetName){ return addCommand(C_ROUNDABOUT, dist, angle, exit, convertStreetName(streetName)); } - public JSCommandBuilder roundAbout(double angle, int exit, Map streetName) { + public JSCommandBuilder roundAbout(double angle, int exit, StreetName streetName) { return roundAbout(-1, angle, exit, streetName); } @Override @@ -180,11 +182,11 @@ public class JSCommandBuilder extends CommandBuilder { return addCommand(C_REACHED_POI, name); } - public JSCommandBuilder bearLeft(Map streetName){ + public JSCommandBuilder bearLeft(StreetName streetName){ return addCommand(C_BEAR_LEFT, convertStreetName(streetName)); } - public JSCommandBuilder bearRight(Map streetName){ + public JSCommandBuilder bearRight(StreetName streetName){ return addCommand(C_BEAR_RIGHT, convertStreetName(streetName)); }