package net.osmand.plus.activities; import net.osmand.plus.OsmandSettings.ApplicationMode; import net.osmand.plus.activities.RoutingHelper.RouteDirectionInfo; import net.osmand.plus.activities.RoutingHelper.TurnType; import net.osmand.plus.voice.CommandPlayer; import net.osmand.plus.voice.CommandPlayer.CommandBuilder; public class VoiceRouter { // 0 - unknown, 1 - notify prepare, 2 - notify to turn after , 3 - notify to turn private final int STATUS_UNKNOWN = 0; private final int STATUS_3000_PREPARE = 1; private final int STATUS_800_PREPARE = 2; private final int STATUS_200_TURN = 3; private final int STATUS_TURN = 4; private final int STATUS_TOLD = 5; private final RoutingHelper router; private boolean mute = false; private CommandPlayer player; private int currentDirection = 0; private int currentStatus = STATUS_UNKNOWN; public VoiceRouter(RoutingHelper router, CommandPlayer player) { this.router = router; this.player = player; updateAppMode(); } public void setPlayer(CommandPlayer player) { this.player = player; } public void setMute(boolean mute) { this.mute = mute; } public boolean isMute() { return mute; } protected CommandBuilder getNewCommandPlayerToPlay(){ if(player == null || mute){ return null; } return player.newCommandBuilder(); } protected int PREPARE_LONG_DISTANCE_ST = 2500; protected int PREPARE_LONG_DISTANCE_END = 3000; protected int PREPARE_DISTANCE = 0; protected int TURN_IN_DISTANCE = 0; protected int TURN_DISTANCE = 0; public void updateAppMode(){ if(router.getAppMode() == ApplicationMode.PEDESTRIAN){ PREPARE_DISTANCE = 400; TURN_IN_DISTANCE = 150; TURN_DISTANCE = 30; } else if(router.getAppMode() == ApplicationMode.BICYCLE){ PREPARE_DISTANCE = 550; TURN_IN_DISTANCE = 200; TURN_DISTANCE = 55; } else { PREPARE_DISTANCE = 800; TURN_IN_DISTANCE = 300; TURN_DISTANCE = 70; } } protected void updateStatus(){ // directly after turn (go - ahead dist) // < 800m prepare // < 200m turn in // < 50m turn if(currentDirection != router.currentDirectionInfo){ currentDirection = router.currentDirectionInfo; currentStatus = STATUS_UNKNOWN; } RouteDirectionInfo next = router.getNextRouteDirectionInfo(); int dist = router.getDistanceToNextRouteDirection(); if(next == null || next.distance == 0) { if(currentStatus == STATUS_UNKNOWN && currentDirection > 0){ CommandBuilder play = getNewCommandPlayerToPlay(); if(play != null){ play.goAhead(router.getLeftDistance()).andArriveAtDestination().play(); } currentStatus = STATUS_TOLD; } return; } if(dist == 0){ // nothing said possibly that's wrong case we should say before that // however it should be checked manually !? return; } RouteDirectionInfo nextNext = router.getNextNextRouteDirectionInfo(); if(currentStatus == STATUS_UNKNOWN){ if(dist > PREPARE_DISTANCE){ CommandBuilder play = getNewCommandPlayerToPlay(); if(play != null){ play.goAhead(dist).play(); } currentStatus = STATUS_3000_PREPARE; } else if (dist < TURN_IN_DISTANCE){ // should already told it currentStatus = STATUS_TURN; } } if(currentStatus <= STATUS_TURN && dist <= TURN_DISTANCE){ CommandBuilder play = getNewCommandPlayerToPlay(); if(play != null){ String tParam = getTurnType(next.turnType); boolean isplay = true; if(tParam != null){ play.turn(tParam); } else if(next.turnType.isRoundAbout()){ play.roundAbout(next.turnType.getTurnAngle(), next.turnType.getExitOut()); } else if(next.turnType.getValue().equals(TurnType.TU)){ play.makeUT(); // do not say it // } else if(next.turnType.getValue().equals(TurnType.C)){ // play.goAhead(); } else { isplay = false; } if (nextNext != null && next.distance <= TURN_IN_DISTANCE) { String t2Param = getTurnType(nextNext.turnType); if (t2Param != null) { if(isplay) { play.then(); } play.turn(t2Param, next.distance); } else if (nextNext.turnType.isRoundAbout()) { if(isplay) { play.then(); } play.roundAbout(next.distance, nextNext.turnType.getTurnAngle(), nextNext.turnType.getExitOut()); } else if (nextNext.turnType.getValue().equals(TurnType.TU)) { if(isplay) { play.then(); } play.makeUT(next.distance); } isplay = true; } if(isplay){ play.play(); } } currentStatus = STATUS_TOLD; } else if(currentStatus <= STATUS_200_TURN && dist <= TURN_IN_DISTANCE){ CommandBuilder play = getNewCommandPlayerToPlay(); if (play != null) { String tParam = getTurnType(next.turnType); boolean isPlay = true; if (tParam != null) { play.turn(tParam, dist); } else if (next.turnType.isRoundAbout()) { play.roundAbout(dist, next.turnType.getTurnAngle(), next.turnType.getExitOut()); } else if (next.turnType.getValue().equals(TurnType.TU)) { play.makeUT(dist); } else { isPlay = false; } if (nextNext != null && next.distance <= TURN_DISTANCE) { TurnType t = nextNext.turnType; isPlay = true; if (next.turnType.getValue().equals(TurnType.C) && !TurnType.C.equals(t.getValue())) { play.goAhead(dist); } if (TurnType.TL.equals(t.getValue()) || TurnType.TSHL.equals(t.getValue()) || TurnType.TSLL.equals(t.getValue()) || TurnType.TU.equals(t.getValue())) { play.then().bearLeft(); } else if (TurnType.TR.equals(t.getValue()) || TurnType.TSHR.equals(t.getValue()) || TurnType.TSLR.equals(t.getValue())) { play.then().bearRight(); } } if(isPlay){ play.play(); } } currentStatus = STATUS_TURN; } else if(currentStatus <= STATUS_800_PREPARE && dist <= PREPARE_DISTANCE){ CommandBuilder play = getNewCommandPlayerToPlay(); if(play != null){ String tParam = getTurnType(next.turnType); if(tParam != null){ play.prepareTurn(tParam, dist).play(); } else if(next.turnType.isRoundAbout()){ play.prepareRoundAbout(dist).play(); } else if(next.turnType.getValue().equals(TurnType.TU)){ play.prepareMakeUT(dist).play(); } } currentStatus = STATUS_200_TURN; } else if((currentStatus <= STATUS_800_PREPARE && dist <= PREPARE_DISTANCE) || (currentStatus <= STATUS_3000_PREPARE && dist <= PREPARE_LONG_DISTANCE_END && dist >= PREPARE_LONG_DISTANCE_ST)){ CommandBuilder play = getNewCommandPlayerToPlay(); if(play != null){ String tParam = getTurnType(next.turnType); if(tParam != null){ play.prepareTurn(tParam, dist).play(); } else if(next.turnType.isRoundAbout()){ play.prepareRoundAbout(dist).play(); } else if(next.turnType.getValue().equals(TurnType.TU)){ play.prepareMakeUT(dist).play(); } } currentStatus = currentStatus <= STATUS_3000_PREPARE ? STATUS_800_PREPARE : STATUS_200_TURN; } } private String getTurnType(TurnType t){ if(TurnType.TL.equals(t.getValue())){ return CommandPlayer.A_LEFT; } else if(TurnType.TSHL.equals(t.getValue())){ return CommandPlayer.A_LEFT_SH; } else if(TurnType.TSLL.equals(t.getValue())){ return CommandPlayer.A_LEFT_SL; } else if(TurnType.TR.equals(t.getValue())){ return CommandPlayer.A_RIGHT; } else if(TurnType.TSHR.equals(t.getValue())){ return CommandPlayer.A_RIGHT_SH; } else if(TurnType.TSLR.equals(t.getValue())){ return CommandPlayer.A_RIGHT_SL; } return null; } public void newRouteIsCalculated(boolean updateRoute) { CommandBuilder play = getNewCommandPlayerToPlay(); if (play != null) { if (updateRoute) { play.routeRecalculated(router.getLeftDistance()).play(); } else { play.newRouteCalculated(router.getLeftDistance()).play(); } } currentDirection = router.currentDirectionInfo; currentStatus = 0; } public void arrivedDestinationPoint() { CommandBuilder play = getNewCommandPlayerToPlay(); if(play != null){ play.arrivedAtDestination().play(); } } }