Started adding js voice guidance
This commit is contained in:
parent
78d78036d5
commit
638f487eda
9 changed files with 396 additions and 3 deletions
|
@ -2913,4 +2913,6 @@
|
|||
<string name="wiki_article_search_text">Searching for the corresponding wiki article</string>
|
||||
<string name="wiki_article_not_found">Article not found</string>
|
||||
<string name="how_to_open_wiki_title">How to open Wikipedia articles?</string>
|
||||
<string name="use_js_voice_guidance">Use JS voice guidance</string>
|
||||
<string name="use_js_voice_guidance_description">Use new voice guidance logic based on JavaScript</string>
|
||||
</resources>
|
||||
|
|
|
@ -46,6 +46,7 @@ import net.osmand.plus.search.QuickSearchHelper;
|
|||
import net.osmand.plus.views.corenative.NativeCoreContext;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.voice.CommandPlayerException;
|
||||
import net.osmand.plus.voice.JSTTSCommandPlayerImpl;
|
||||
import net.osmand.plus.voice.MediaCommandPlayerImpl;
|
||||
import net.osmand.plus.voice.TTSCommandPlayerImpl;
|
||||
import net.osmand.plus.wikivoyage.data.TravelDbHelper;
|
||||
|
@ -577,7 +578,9 @@ public class AppInitializer implements IProgress {
|
|||
if (!voiceDir.exists()) {
|
||||
throw new CommandPlayerException(ctx.getString(R.string.voice_data_unavailable));
|
||||
}
|
||||
|
||||
if (app.getSettings().USE_JS_VOICE_GUIDANCE.get()) {
|
||||
return new JSTTSCommandPlayerImpl(osmandApplication, applicationMode, osmandApplication.getRoutingHelper().getVoiceRouter(), voiceProvider);
|
||||
}
|
||||
if (MediaCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return new MediaCommandPlayerImpl(osmandApplication, applicationMode, osmandApplication.getRoutingHelper().getVoiceRouter(), voiceProvider);
|
||||
} else if (TTSCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
|
|
|
@ -1340,6 +1340,8 @@ public class OsmandSettings {
|
|||
|
||||
public final OsmandPreference<Boolean> ANIMATE_MY_LOCATION = new BooleanPreference("animate_my_location", true).makeGlobal().cache();
|
||||
|
||||
public final OsmandPreference<Boolean> USE_JS_VOICE_GUIDANCE = new BooleanPreference("use_js_voice_guidance", false);
|
||||
|
||||
public final OsmandPreference<Boolean> ROUTE_MAP_MARKERS_START_MY_LOC = new BooleanPreference("route_map_markers_start_my_loc", false).makeGlobal().cache();
|
||||
public final OsmandPreference<Boolean> ROUTE_MAP_MARKERS_ROUND_TRIP = new BooleanPreference("route_map_markers_round_trip", false).makeGlobal().cache();
|
||||
|
||||
|
|
|
@ -63,6 +63,9 @@ public class SettingsDevelopmentActivity extends SettingsBaseActivity {
|
|||
R.string.animate_my_location,
|
||||
R.string.animate_my_location_desc));
|
||||
|
||||
cat.addPreference(createCheckBoxPreference(settings.USE_JS_VOICE_GUIDANCE, getString(R.string.use_js_voice_guidance),
|
||||
getString(R.string.use_js_voice_guidance_description)));
|
||||
|
||||
final Preference firstRunPreference = new Preference(this);
|
||||
firstRunPreference.setTitle(R.string.simulate_initial_startup);
|
||||
firstRunPreference.setSummary(R.string.simulate_initial_startup_descr);
|
||||
|
|
|
@ -69,6 +69,8 @@ public class VoiceRouter {
|
|||
private static RouteDirectionInfo nextRouteDirection;
|
||||
private Term empty;
|
||||
|
||||
private boolean useJS;
|
||||
|
||||
public interface VoiceMessageListener {
|
||||
void onVoiceMessage();
|
||||
}
|
||||
|
@ -78,6 +80,7 @@ public class VoiceRouter {
|
|||
public 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("");
|
||||
voiceMessageListeners = new ConcurrentHashMap<VoiceRouter.VoiceMessageListener, Integer>();
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import alice.tuprolog.Struct;
|
||||
|
||||
public class AbstractJSCommandPlayer implements CommandPlayer {
|
||||
@Override
|
||||
public String getCurrentVoice() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandBuilder newCommandBuilder() {
|
||||
JSCommandBuilder commandBuilder = new JSCommandBuilder(this);
|
||||
commandBuilder.setParameters("km-m", true);
|
||||
return commandBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playCommands(CommandBuilder builder) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> execute(List<Struct> listStruct) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAudioStream(int streamType) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsStructuredStreetNames() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
}
|
|
@ -53,8 +53,8 @@ public class CommandBuilder {
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private final CommandPlayer commandPlayer;
|
||||
private boolean alreadyExecuted = false;
|
||||
protected final CommandPlayer commandPlayer;
|
||||
protected boolean alreadyExecuted = false;
|
||||
private List<Struct> listStruct = new ArrayList<Struct>();
|
||||
|
||||
public CommandBuilder(CommandPlayer commandPlayer){
|
||||
|
|
220
OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java
Normal file
220
OsmAnd/src/net/osmand/plus/voice/JSCommandBuilder.java
Normal file
|
@ -0,0 +1,220 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import net.osmand.PlatformUtil;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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 List<String> listStruct = new ArrayList<>();
|
||||
|
||||
public JSCommandBuilder(CommandPlayer commandPlayer) {
|
||||
super(commandPlayer);
|
||||
}
|
||||
|
||||
|
||||
public void setParameters(String metricCons, boolean tts) {
|
||||
// TODO Set the parameters to js context
|
||||
}
|
||||
|
||||
private JSCommandBuilder addCommand(String name, Object... args){
|
||||
// TODO add JSCore
|
||||
listStruct.add(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
public JSCommandBuilder goAhead(){
|
||||
return goAhead(-1, new HashMap<String, String>());
|
||||
}
|
||||
|
||||
public JSCommandBuilder goAhead(double dist, Map<String, String> streetName){
|
||||
return addCommand(C_GO_AHEAD, dist, streetName);
|
||||
}
|
||||
|
||||
public JSCommandBuilder makeUTwp(){
|
||||
return makeUT(new HashMap<String, String>());
|
||||
}
|
||||
|
||||
public JSCommandBuilder makeUT(Map<String, String> streetName){
|
||||
return addCommand(C_MAKE_UT, streetName);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder speedAlarm(int maxSpeed, float speed){
|
||||
return addCommand(C_SPEAD_ALARM, maxSpeed, speed);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder attention(String type){
|
||||
return addCommand(C_ATTENTION, type);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder offRoute(double dist){
|
||||
return addCommand(C_OFF_ROUTE, dist);
|
||||
}
|
||||
@Override
|
||||
public CommandBuilder backOnRoute(){
|
||||
return addCommand(C_BACK_ON_ROUTE);
|
||||
}
|
||||
|
||||
public JSCommandBuilder makeUT(double dist, Map<String,String> streetName){
|
||||
return addCommand(C_MAKE_UT, dist, streetName);
|
||||
}
|
||||
|
||||
public JSCommandBuilder prepareMakeUT(double dist, Map<String, String> streetName){
|
||||
return addCommand(C_PREPARE_MAKE_UT, dist, streetName);
|
||||
}
|
||||
|
||||
|
||||
public JSCommandBuilder turn(String param, Map<String, String> streetName) {
|
||||
return addCommand(C_TURN, param, streetName);
|
||||
}
|
||||
|
||||
public JSCommandBuilder turn(String param, double dist, Map<String, String> streetName){
|
||||
return addCommand(C_TURN, param, dist, streetName);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param param A_LEFT, A_RIGHT, ...
|
||||
* @param dist
|
||||
* @return
|
||||
*/
|
||||
public JSCommandBuilder prepareTurn(String param, double dist, Map<String, String> streetName){
|
||||
return addCommand(C_PREPARE_TURN, param, dist, streetName);
|
||||
}
|
||||
|
||||
public JSCommandBuilder prepareRoundAbout(double dist, int exit, Map<String, String> streetName){
|
||||
return addCommand(C_PREPARE_ROUNDABOUT, dist, exit, streetName);
|
||||
}
|
||||
|
||||
public JSCommandBuilder roundAbout(double dist, double angle, int exit, Map<String, String> streetName){
|
||||
return addCommand(C_ROUNDABOUT, dist, angle, exit, streetName);
|
||||
}
|
||||
|
||||
public JSCommandBuilder roundAbout(double angle, int exit, Map<String, String> streetName) {
|
||||
return roundAbout(-1, angle, exit, streetName);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder andArriveAtDestination(String name){
|
||||
return addCommand(C_AND_ARRIVE_DESTINATION, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder arrivedAtDestination(String name){
|
||||
return addCommand(C_REACHED_DESTINATION, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder andArriveAtIntermediatePoint(String name){
|
||||
return addCommand(C_AND_ARRIVE_INTERMEDIATE, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder arrivedAtIntermediatePoint(String name) {
|
||||
return addCommand(C_REACHED_INTERMEDIATE, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder andArriveAtWayPoint(String name){
|
||||
return addCommand(C_AND_ARRIVE_WAYPOINT, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder arrivedAtWayPoint(String name) {
|
||||
return addCommand(C_REACHED_WAYPOINT, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder andArriveAtFavorite(String name) {
|
||||
return addCommand(C_AND_ARRIVE_FAVORITE, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder arrivedAtFavorite(String name) {
|
||||
return addCommand(C_REACHED_FAVORITE, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder andArriveAtPoi(String name) {
|
||||
return addCommand(C_AND_ARRIVE_POI_WAYPOINT, name);
|
||||
}
|
||||
@Override
|
||||
public JSCommandBuilder arrivedAtPoi(String name) {
|
||||
return addCommand(C_REACHED_POI, name);
|
||||
}
|
||||
|
||||
public JSCommandBuilder bearLeft(Map<String,String> streetName){
|
||||
return addCommand(C_BEAR_LEFT, streetName);
|
||||
}
|
||||
|
||||
public JSCommandBuilder bearRight(Map<String, String> streetName){
|
||||
return addCommand(C_BEAR_RIGHT, streetName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSCommandBuilder then(){
|
||||
return addCommand(C_THEN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSCommandBuilder gpsLocationLost() {
|
||||
return addCommand(C_LOCATION_LOST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSCommandBuilder gpsLocationRecover() {
|
||||
return addCommand(C_LOCATION_RECOVERED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSCommandBuilder newRouteCalculated(double dist, int time){
|
||||
return addCommand(C_ROUTE_NEW_CALC, dist, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSCommandBuilder routeRecalculated(double dist, int time){
|
||||
return addCommand(C_ROUTE_RECALC, dist, time);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void play(){
|
||||
this.commandPlayer.playCommands(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> execute(){
|
||||
alreadyExecuted = true;
|
||||
return listStruct;
|
||||
}
|
||||
}
|
106
OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java
Normal file
106
OsmAnd/src/net/osmand/plus/voice/JSTTSCommandPlayerImpl.java
Normal file
|
@ -0,0 +1,106 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.support.v7.app.AlertDialog;
|
||||
import android.util.Log;
|
||||
|
||||
import net.osmand.plus.ApplicationMode;
|
||||
import net.osmand.plus.OsmandApplication;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.routing.VoiceRouter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public class JSTTSCommandPlayerImpl extends AbstractJSCommandPlayer {
|
||||
|
||||
private static final String TAG = JSTTSCommandPlayerImpl.class.getSimpleName();
|
||||
private static TextToSpeech mTts;
|
||||
|
||||
private OsmandApplication app;
|
||||
private ApplicationMode appMode;
|
||||
private VoiceRouter vrt;
|
||||
private String voiceProvider;
|
||||
|
||||
private HashMap<String, String> params = new HashMap<String, String>();
|
||||
|
||||
private static int ttsRequests = 0;
|
||||
|
||||
public JSTTSCommandPlayerImpl(OsmandApplication ctx, ApplicationMode applicationMode, VoiceRouter vrt, String voiceProvider) {
|
||||
this.app = ctx;
|
||||
this.appMode = applicationMode;
|
||||
this.vrt = vrt;
|
||||
this.voiceProvider = voiceProvider;
|
||||
mTts = new TextToSpeech(ctx, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentVoice() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSCommandBuilder newCommandBuilder() {
|
||||
JSCommandBuilder commandBuilder = new JSCommandBuilder(this);
|
||||
commandBuilder.setParameters(app.getSettings().METRIC_SYSTEM.get().toHumanString(app), true);
|
||||
return commandBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playCommands(CommandBuilder builder) {
|
||||
final List<String> execute = builder.execute(); //list of strings, the speech text, play it
|
||||
StringBuilder bld = new StringBuilder();
|
||||
for (String s : execute) {
|
||||
bld.append(s).append(' ');
|
||||
}
|
||||
if (mTts != null && !vrt.isMute()) {
|
||||
if (ttsRequests++ == 0) {
|
||||
// Delay first prompt of each batch to allow BT SCO connection being established
|
||||
if (app.getSettings().AUDIO_STREAM_GUIDANCE.getModeValue(appMode) == 0) {
|
||||
ttsRequests++;
|
||||
if (android.os.Build.VERSION.SDK_INT < 21) {
|
||||
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,""+System.currentTimeMillis());
|
||||
mTts.playSilence(app.getSettings().BT_SCO_DELAY.get(), TextToSpeech.QUEUE_ADD, params);
|
||||
} else {
|
||||
mTts.playSilentUtterance(app.getSettings().BT_SCO_DELAY.get(), TextToSpeech.QUEUE_ADD, ""+System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
Log.d(TAG, "ttsRequests= "+ttsRequests);
|
||||
params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,""+System.currentTimeMillis());
|
||||
mTts.speak(bld.toString(), TextToSpeech.QUEUE_ADD, params);
|
||||
// Audio focus will be released when onUtteranceCompleted() completed is called by the TTS engine.
|
||||
} else if (app != null && vrt.isMute()) {
|
||||
// sendAlertToAndroidWear(ctx, bld.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateAudioStream(int streamType) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsStructuredStreetNames() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue