Merge tts branch into master
This commit is contained in:
commit
1dc78bb32a
13 changed files with 1005 additions and 516 deletions
|
@ -1,5 +1,10 @@
|
|||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<resources>
|
||||
<string name="tts_language_not_supported_title">Language unsupported</string>
|
||||
<string name="tts_language_not_supported">The selected language is not supported by the installed TTS engine. Do you want to go to market and search for other TTS engine? Else preset TTS language will be used.</string>
|
||||
<string name="tts_missing_language_data_title">Missing data</string>
|
||||
<string name="tts_missing_language_data">Data for selected language are not installed. Do you want to go market to install them?</string>
|
||||
|
||||
<string name="gpx_option_reverse_route">Reverse GPX route</string>
|
||||
<string name="gpx_option_destination_point">Use current destination point</string>
|
||||
<string name="gpx_option_from_start_point">Pass whole track</string>
|
||||
|
|
|
@ -6,9 +6,9 @@ import java.util.List;
|
|||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.CallbackWithObject;
|
||||
import net.osmand.GPXUtilities.GPXFileResult;
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.Version;
|
||||
import net.osmand.GPXUtilities.GPXFileResult;
|
||||
import net.osmand.data.MapTileDownloader;
|
||||
import net.osmand.data.MapTileDownloader.DownloadRequest;
|
||||
import net.osmand.data.MapTileDownloader.IMapDownloaderCallback;
|
||||
|
@ -27,17 +27,17 @@ import net.osmand.plus.views.OsmandMapTileView;
|
|||
import net.osmand.plus.views.PointLocationLayer;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Dialog;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.ComponentName;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.DialogInterface.OnMultiChoiceClickListener;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Color;
|
||||
|
@ -66,8 +66,8 @@ import android.view.MenuInflater;
|
|||
import android.view.MenuItem;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.Window;
|
||||
import android.view.animation.AccelerateInterpolator;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.Transformation;
|
||||
|
@ -150,7 +150,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
settings = ((OsmandApplication) getApplication()).getSettings();
|
||||
settings = getMyApplication().getSettings();
|
||||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
// Full screen is not used here
|
||||
// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
|
@ -183,7 +183,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
@Override
|
||||
public void tileDownloaded(DownloadRequest request) {
|
||||
if(request != null && !request.error && request.fileToSave != null){
|
||||
ResourceManager mgr = ((OsmandApplication)getApplication()).getResourceManager();
|
||||
ResourceManager mgr = getMyApplication().getResourceManager();
|
||||
mgr.tileDownloaded(request);
|
||||
}
|
||||
mapView.tileDownloaded(request);
|
||||
|
@ -193,7 +193,8 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
|
||||
|
||||
savingTrackHelper = new SavingTrackHelper(this);
|
||||
routingHelper = ((OsmandApplication) getApplication()).getRoutingHelper();
|
||||
routingHelper = getMyApplication().getRoutingHelper();
|
||||
routingHelper.getVoiceRouter().onActivityInit(this);
|
||||
|
||||
LatLon pointToNavigate = settings.getPointToNavigate();
|
||||
// This situtation could be when navigation suddenly crashed and after restarting
|
||||
|
@ -213,7 +214,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
routingHelper.setFollowingMode(true);
|
||||
((OsmandApplication)getApplication()).showDialogInitializingCommandPlayer(MapActivity.this);
|
||||
getMyApplication().showDialogInitializingCommandPlayer(MapActivity.this);
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.default_buttons_no, new DialogInterface.OnClickListener(){
|
||||
|
@ -269,6 +270,10 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
|
||||
}
|
||||
|
||||
private OsmandApplication getMyApplication() {
|
||||
return ((OsmandApplication) getApplication());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Dialog onCreateDialog(int id) {
|
||||
if(id == OsmandApplication.PROGRESS_DIALOG){
|
||||
|
@ -334,7 +339,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
public void onClick(View v) {
|
||||
dlg.dismiss();
|
||||
|
||||
((OsmandApplication) getApplication()).closeApplication();
|
||||
getMyApplication().closeApplication();
|
||||
// 1. Work for almost all cases when user open apps from main menu
|
||||
Intent newIntent = new Intent(MapActivity.this, MainMenuActivity.class);
|
||||
newIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
|
||||
|
@ -427,6 +432,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
mNotificationManager.cancel(APP_NOTIFICATION_ID);
|
||||
}
|
||||
MapTileDownloader.getInstance().removeDownloaderCallback(mapView);
|
||||
routingHelper.getVoiceRouter().onActivityStop(this);
|
||||
}
|
||||
|
||||
|
||||
|
@ -684,9 +690,6 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
@ -699,8 +702,9 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
sensorRegistered = false;
|
||||
currentLocationProvider = null;
|
||||
routingHelper.setUiActivity(null);
|
||||
routingHelper.getVoiceRouter().onActivityStop(this);
|
||||
|
||||
((OsmandApplication)getApplication()).getDaynightHelper().onMapPause();
|
||||
getMyApplication().getDaynightHelper().onMapPause();
|
||||
|
||||
settings.setLastKnownMapLocation((float) mapView.getLatitude(), (float) mapView.getLongitude());
|
||||
AnimateDraggingMapThread animatedThread = mapView.getAnimatedDraggingThread();
|
||||
|
@ -715,8 +719,8 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
wakeLock = null;
|
||||
}
|
||||
settings.MAP_ACTIVITY_ENABLED.set(false);
|
||||
((OsmandApplication)getApplication()).getResourceManager().interruptRendering();
|
||||
((OsmandApplication)getApplication()).getResourceManager().setBusyIndicator(null);
|
||||
getMyApplication().getResourceManager().interruptRendering();
|
||||
getMyApplication().getResourceManager().setBusyIndicator(null);
|
||||
}
|
||||
|
||||
private void updateApplicationModeSettings(){
|
||||
|
@ -781,7 +785,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
}
|
||||
|
||||
routingHelper.setUiActivity(this);
|
||||
|
||||
routingHelper.getVoiceRouter().onActivityInit(this);
|
||||
|
||||
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
|
||||
try {
|
||||
|
@ -831,10 +835,10 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
|
||||
View progress = findViewById(R.id.ProgressBar);
|
||||
if(progress != null){
|
||||
((OsmandApplication) getApplication()).getResourceManager().setBusyIndicator(new BusyIndicator(this, progress));
|
||||
getMyApplication().getResourceManager().setBusyIndicator(new BusyIndicator(this, progress));
|
||||
}
|
||||
|
||||
((OsmandApplication)getApplication()).getDaynightHelper().onMapResume();
|
||||
getMyApplication().getDaynightHelper().onMapResume();
|
||||
}
|
||||
|
||||
|
||||
|
@ -937,8 +941,8 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
boolean val = super.onPrepareOptionsMenu(menu);
|
||||
MenuItem navigateToPointMenu = menu.findItem(R.id.map_navigate_to_point);
|
||||
if (navigateToPointMenu != null) {
|
||||
navigateToPointMenu.setTitle(routingHelper.isRouteCalculated() ? R.string.stop_routing : R.string.stop_navigation);
|
||||
if (settings.getPointToNavigate() != null) {
|
||||
navigateToPointMenu.setTitle(routingHelper.isRouteCalculated() ? R.string.stop_routing : R.string.stop_navigation);
|
||||
navigateToPointMenu.setVisible(true);
|
||||
} else {
|
||||
navigateToPointMenu.setVisible(false);
|
||||
|
@ -946,64 +950,73 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
}
|
||||
MenuItem muteMenu = menu.findItem(R.id.map_mute);
|
||||
if(muteMenu != null){
|
||||
muteMenu.setTitle(routingHelper.getVoiceRouter().isMute() ? R.string.menu_mute_on : R.string.menu_mute_off);
|
||||
if (routingHelper.getFinalLocation() != null && routingHelper.isFollowingMode()) {
|
||||
muteMenu.setTitle(routingHelper.getVoiceRouter().isMute() ? R.string.menu_mute_on : R.string.menu_mute_off);
|
||||
muteMenu.setVisible(true);
|
||||
} else {
|
||||
muteMenu.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.map_show_settings) {
|
||||
final Intent settings = new Intent(MapActivity.this, SettingsActivity.class);
|
||||
startActivity(settings);
|
||||
switch (item.getItemId()) {
|
||||
case R.id.map_show_settings:
|
||||
final Intent intentSettings = new Intent(MapActivity.this,
|
||||
SettingsActivity.class);
|
||||
startActivity(intentSettings);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.map_where_am_i) {
|
||||
case R.id.map_where_am_i:
|
||||
backToLocationImpl();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.map_show_gps_status) {
|
||||
case R.id.map_show_gps_status:
|
||||
Intent intent = new Intent();
|
||||
intent.setComponent(new ComponentName(GPS_STATUS_COMPONENT, GPS_STATUS_ACTIVITY));
|
||||
ResolveInfo resolved = getPackageManager().resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
if(resolved != null){
|
||||
intent.setComponent(new ComponentName(GPS_STATUS_COMPONENT,
|
||||
GPS_STATUS_ACTIVITY));
|
||||
ResolveInfo resolved = getPackageManager().resolveActivity(intent,
|
||||
PackageManager.MATCH_DEFAULT_ONLY);
|
||||
if (resolved != null) {
|
||||
startActivity(intent);
|
||||
} else {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setMessage(getString(R.string.gps_status_app_not_found));
|
||||
builder.setPositiveButton(getString(R.string.default_buttons_yes),
|
||||
builder.setPositiveButton(
|
||||
getString(R.string.default_buttons_yes),
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("market://search?q=pname:" + GPS_STATUS_COMPONENT));
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW,
|
||||
Uri.parse("market://search?q=pname:"
|
||||
+ GPS_STATUS_COMPONENT));
|
||||
try {
|
||||
startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(getString(R.string.default_buttons_no), null);
|
||||
builder.setNegativeButton(
|
||||
getString(R.string.default_buttons_no), null);
|
||||
builder.show();
|
||||
}
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.map_get_directions) {
|
||||
case R.id.map_get_directions:
|
||||
getDirections(mapView.getLatitude(), mapView.getLongitude(), true);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.map_layers) {
|
||||
case R.id.map_layers:
|
||||
mapLayers.openLayerSelectionDialog(mapView);
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.map_specify_point) {
|
||||
case R.id.map_specify_point:
|
||||
NavigatePointActivity dlg = new NavigatePointActivity(this);
|
||||
dlg.showDialog();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.map_mute) {
|
||||
routingHelper.getVoiceRouter().setMute(!routingHelper.getVoiceRouter().isMute());
|
||||
case R.id.map_mute:
|
||||
routingHelper.getVoiceRouter().setMute(
|
||||
!routingHelper.getVoiceRouter().isMute());
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.map_navigate_to_point) {
|
||||
case R.id.map_navigate_to_point:
|
||||
if(mapLayers.getNavigationLayer().getPointToNavigate() != null){
|
||||
if(routingHelper.isRouteCalculated()){
|
||||
routingHelper.setFinalAndCurrentLocation(null, null);
|
||||
|
@ -1016,15 +1029,17 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
navigateToPoint(new LatLon(mapView.getLatitude(), mapView.getLongitude()));
|
||||
}
|
||||
mapView.refreshMap();
|
||||
} else if (item.getItemId() == R.id.map_gpx_routing) {
|
||||
return true;
|
||||
case R.id.map_gpx_routing:
|
||||
useGPXRouting();
|
||||
return true;
|
||||
} else if (item.getItemId() == R.id.map_show_point_options) {
|
||||
case R.id.map_show_point_options:
|
||||
contextMenuPoint(mapView.getLatitude(), mapView.getLongitude());
|
||||
return true;
|
||||
}
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
private ApplicationMode getAppMode(ToggleButton[] buttons){
|
||||
for(int i=0; i<buttons.length; i++){
|
||||
|
@ -1090,9 +1105,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
ApplicationMode mode = getAppMode(buttons);
|
||||
Location map = new Location("map"); //$NON-NLS-1$
|
||||
map.setLatitude(lat);
|
||||
map.setLongitude(lon);
|
||||
Location map = getLocationToStartFrom(lat, lon);
|
||||
routingHelper.setAppMode(mode);
|
||||
settings.FOLLOW_TO_THE_ROUTE.set(false);
|
||||
routingHelper.setFollowingMode(false);
|
||||
|
@ -1111,19 +1124,13 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
mapView.refreshMap();
|
||||
}
|
||||
|
||||
Location location = getLastKnownLocation();
|
||||
if(location == null){
|
||||
location = new Location("map"); //$NON-NLS-1$
|
||||
location.setLatitude(lat);
|
||||
location.setLongitude(lon);
|
||||
}
|
||||
Location location = getLocationToStartFrom(lat, lon);
|
||||
routingHelper.setAppMode(mode);
|
||||
settings.FOLLOW_TO_THE_ROUTE.set(true);
|
||||
routingHelper.setFollowingMode(true);
|
||||
routingHelper.setFinalAndCurrentLocation(getPointToNavigate(), location);
|
||||
|
||||
((OsmandApplication) getApplication()).showDialogInitializingCommandPlayer(MapActivity.this);
|
||||
|
||||
dialog.dismiss();
|
||||
getMyApplication().showDialogInitializingCommandPlayer(MapActivity.this);
|
||||
}
|
||||
};
|
||||
DialogInterface.OnClickListener showRoute = new DialogInterface.OnClickListener(){
|
||||
|
@ -1177,7 +1184,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
}
|
||||
|
||||
public FavouritesDbHelper getFavoritesHelper() {
|
||||
return ((OsmandApplication)getApplication()).getFavorites();
|
||||
return getMyApplication().getFavorites();
|
||||
}
|
||||
|
||||
private void useGPXRouting() {
|
||||
|
@ -1230,7 +1237,7 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
settings.FOLLOW_TO_THE_ROUTE.set(true);
|
||||
routingHelper.setFollowingMode(true);
|
||||
routingHelper.setFinalAndCurrentLocation(endPoint, startForRouting, l);
|
||||
((OsmandApplication)getApplication()).showDialogInitializingCommandPlayer(MapActivity.this);
|
||||
getMyApplication().showDialogInitializingCommandPlayer(MapActivity.this);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1321,4 +1328,14 @@ public class MapActivity extends Activity implements IMapLocationListener, Senso
|
|||
public void onAccuracyChanged(Sensor sensor, int accuracy) {
|
||||
}
|
||||
|
||||
private Location getLocationToStartFrom(final double lat, final double lon) {
|
||||
Location location = getLastKnownLocation();
|
||||
if(location == null){
|
||||
location = new Location("map"); //$NON-NLS-1$
|
||||
location.setLatitude(lat);
|
||||
location.setLongitude(lon);
|
||||
}
|
||||
return location;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,11 +24,13 @@ import net.osmand.plus.R;
|
|||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.render.RendererRegistry;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.voice.CommandPlayerException;
|
||||
import net.osmand.plus.voice.CommandPlayerFactory;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.Application;
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
|
@ -194,7 +196,7 @@ public class OsmandApplication extends Application {
|
|||
}
|
||||
|
||||
|
||||
public void showDialogInitializingCommandPlayer(final Context uiContext){
|
||||
public void showDialogInitializingCommandPlayer(final Activity uiContext){
|
||||
String voiceProvider = osmandSettings.VOICE_PROVIDER.get();
|
||||
if(voiceProvider == null){
|
||||
Builder builder = new AlertDialog.Builder(uiContext);
|
||||
|
@ -219,30 +221,35 @@ public class OsmandApplication extends Application {
|
|||
|
||||
}
|
||||
|
||||
private void initVoiceDataInDifferentThread(Context uiContext) {
|
||||
final ProgressDialog dlg = ProgressDialog.show(uiContext, getString(R.string.loading_data), getString(R.string.voice_data_initializing));
|
||||
private void initVoiceDataInDifferentThread(final Activity uiContext) {
|
||||
final ProgressDialog dlg = ProgressDialog.show(uiContext,
|
||||
getString(R.string.loading_data),
|
||||
getString(R.string.voice_data_initializing));
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
String w = null;
|
||||
try {
|
||||
w = initCommandPlayer();
|
||||
} finally {
|
||||
initCommandPlayer(uiContext);
|
||||
dlg.dismiss();
|
||||
}
|
||||
if(w != null){
|
||||
showWarning(dlg.getContext(), w);
|
||||
} catch (CommandPlayerException e) {
|
||||
dlg.dismiss();
|
||||
showWarning(uiContext, e.getError());
|
||||
}
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public String initCommandPlayer() {
|
||||
if (player == null) {
|
||||
player = new CommandPlayer(OsmandApplication.this);
|
||||
public void initCommandPlayer(Activity ctx)
|
||||
throws CommandPlayerException
|
||||
{
|
||||
final String voiceProvider = osmandSettings.VOICE_PROVIDER.get();
|
||||
if (player == null || !Algoritms.objectEquals(voiceProvider, player.getCurrentVoice())) {
|
||||
if (player != null) {
|
||||
player.clear();
|
||||
}
|
||||
player = CommandPlayerFactory.createCommandPlayer(voiceProvider,OsmandApplication.this, ctx);
|
||||
routingHelper.getVoiceRouter().setPlayer(player);
|
||||
}
|
||||
return player.init(osmandSettings.VOICE_PROVIDER.get());
|
||||
}
|
||||
|
||||
public NavigationService getNavigationService() {
|
||||
|
|
|
@ -7,33 +7,34 @@ import java.util.LinkedHashMap;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import net.osmand.map.TileSourceManager;
|
||||
import net.osmand.map.TileSourceManager.TileSourceTemplate;
|
||||
import net.osmand.plus.NavigationService;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.ProgressDialogImplementation;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.OsmandSettings.DayNightMode;
|
||||
import net.osmand.plus.OsmandSettings.MetricsConstants;
|
||||
import net.osmand.plus.OsmandSettings.OsmandPreference;
|
||||
import net.osmand.plus.ProgressDialogImplementation;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.activities.RouteProvider.RouteService;
|
||||
import net.osmand.plus.render.MapRenderRepositories;
|
||||
import net.osmand.plus.views.SeekBarPreference;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.location.LocationManager;
|
||||
import android.media.AudioManager;
|
||||
|
@ -42,10 +43,10 @@ import android.preference.CheckBoxPreference;
|
|||
import android.preference.EditTextPreference;
|
||||
import android.preference.ListPreference;
|
||||
import android.preference.Preference;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.preference.Preference.OnPreferenceClickListener;
|
||||
import android.preference.PreferenceActivity;
|
||||
import android.preference.PreferenceScreen;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class SettingsActivity extends PreferenceActivity implements OnPreferenceChangeListener, OnPreferenceClickListener {
|
||||
|
@ -315,8 +316,12 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
unregisterReceiver(broadcastReceiver);
|
||||
//we are initializing player in this activity, we must also stop it
|
||||
final CommandPlayer player = getMyApplication().getPlayer();
|
||||
if (player != null) {
|
||||
player.onActvitiyStop(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void updateAllSettings(){
|
||||
for(OsmandPreference<Boolean> b : booleanPreferences.values()){
|
||||
|
@ -397,6 +402,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
fill(tileSourcePreference, entries, values, value);
|
||||
}
|
||||
|
||||
|
||||
private void fill(ListPreference component, String[] list, String[] values, String selected) {
|
||||
component.setEntries(list);
|
||||
component.setEntryValues(values);
|
||||
|
@ -435,7 +441,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
// Specific actions after list preference changed
|
||||
if (changed) {
|
||||
if (listPref.getId().equals(osmandSettings.VOICE_PROVIDER.getId())) {
|
||||
getMyApplication().initCommandPlayer();
|
||||
getMyApplication().showDialogInitializingCommandPlayer(this);
|
||||
} else if (listPref.getId().equals(osmandSettings.APPLICATION_MODE.getId())) {
|
||||
updateAllSettings();
|
||||
} else if (listPref.getId().equals(osmandSettings.PREFERRED_LOCALE.getId())) {
|
||||
|
|
|
@ -2,8 +2,10 @@ package net.osmand.plus.activities;
|
|||
|
||||
import net.osmand.plus.activities.RoutingHelper.RouteDirectionInfo;
|
||||
import net.osmand.plus.activities.RoutingHelper.TurnType;
|
||||
import net.osmand.plus.voice.AbstractPrologCommandPlayer;
|
||||
import net.osmand.plus.voice.CommandBuilder;
|
||||
import net.osmand.plus.voice.CommandPlayer;
|
||||
import net.osmand.plus.voice.CommandPlayer.CommandBuilder;
|
||||
import android.app.Activity;
|
||||
|
||||
|
||||
public class VoiceRouter {
|
||||
|
@ -227,17 +229,17 @@ public class VoiceRouter {
|
|||
|
||||
private String getTurnType(TurnType t){
|
||||
if(TurnType.TL.equals(t.getValue())){
|
||||
return CommandPlayer.A_LEFT;
|
||||
return AbstractPrologCommandPlayer.A_LEFT;
|
||||
} else if(TurnType.TSHL.equals(t.getValue())){
|
||||
return CommandPlayer.A_LEFT_SH;
|
||||
return AbstractPrologCommandPlayer.A_LEFT_SH;
|
||||
} else if(TurnType.TSLL.equals(t.getValue())){
|
||||
return CommandPlayer.A_LEFT_SL;
|
||||
return AbstractPrologCommandPlayer.A_LEFT_SL;
|
||||
} else if(TurnType.TR.equals(t.getValue())){
|
||||
return CommandPlayer.A_RIGHT;
|
||||
return AbstractPrologCommandPlayer.A_RIGHT;
|
||||
} else if(TurnType.TSHR.equals(t.getValue())){
|
||||
return CommandPlayer.A_RIGHT_SH;
|
||||
return AbstractPrologCommandPlayer.A_RIGHT_SH;
|
||||
} else if(TurnType.TSLR.equals(t.getValue())){
|
||||
return CommandPlayer.A_RIGHT_SL;
|
||||
return AbstractPrologCommandPlayer.A_RIGHT_SL;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -262,4 +264,16 @@ public class VoiceRouter {
|
|||
}
|
||||
}
|
||||
|
||||
public void onActivityInit(Activity activity) {
|
||||
if (player != null) {
|
||||
player.onActivityInit(activity);
|
||||
}
|
||||
}
|
||||
|
||||
public void onActivityStop(Activity activity) {
|
||||
if (player != null) {
|
||||
player.onActvitiyStop(activity);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,179 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import alice.tuprolog.InvalidLibraryException;
|
||||
import alice.tuprolog.InvalidTheoryException;
|
||||
import alice.tuprolog.NoSolutionException;
|
||||
import alice.tuprolog.Number;
|
||||
import alice.tuprolog.Prolog;
|
||||
import alice.tuprolog.SolveInfo;
|
||||
import alice.tuprolog.Struct;
|
||||
import alice.tuprolog.Term;
|
||||
import alice.tuprolog.Theory;
|
||||
import alice.tuprolog.Var;
|
||||
import android.content.Context;
|
||||
|
||||
public abstract class AbstractPrologCommandPlayer implements CommandPlayer {
|
||||
|
||||
private static final Log log = LogUtil
|
||||
.getLog(AbstractPrologCommandPlayer.class);
|
||||
|
||||
protected Context ctx;
|
||||
protected File voiceDir;
|
||||
protected Prolog prologSystem;
|
||||
protected static final String P_VERSION = "version";
|
||||
protected static final String P_RESOLVE = "resolve";
|
||||
public static final String A_LEFT = "left";
|
||||
public static final String A_LEFT_SH = "left_sh";
|
||||
public static final String A_LEFT_SL = "left_sl";
|
||||
public static final String A_RIGHT = "right";
|
||||
public static final String A_RIGHT_SH = "right_sh";
|
||||
public static final String A_RIGHT_SL = "right_sl";
|
||||
protected static final String DELAY_CONST = "delay_";
|
||||
private final int voiceVersion;
|
||||
|
||||
protected AbstractPrologCommandPlayer(Context ctx, String voiceProvider, String configFile, int voiceVersion)
|
||||
throws CommandPlayerException
|
||||
{
|
||||
this.voiceVersion = voiceVersion;
|
||||
long time = System.currentTimeMillis();
|
||||
try {
|
||||
this.ctx = ctx;
|
||||
prologSystem = new Prolog(
|
||||
new String[] { "alice.tuprolog.lib.BasicLibrary" }); //$NON-NLS-1$
|
||||
} catch (InvalidLibraryException e) {
|
||||
log.error("Initializing error", e); //$NON-NLS-1$
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing prolog system : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
|
||||
}
|
||||
init(voiceProvider, configFile);
|
||||
}
|
||||
|
||||
private void init(String voiceProvider, String configFile) throws CommandPlayerException {
|
||||
prologSystem.clearTheory();
|
||||
voiceDir = null;
|
||||
if (voiceProvider != null) {
|
||||
File parent = OsmandSettings.getOsmandSettings(ctx).extendOsmandPath(ResourceManager.VOICE_PATH);
|
||||
voiceDir = new File(parent, voiceProvider);
|
||||
if (!voiceDir.exists()) {
|
||||
voiceDir = null;
|
||||
throw new CommandPlayerException(
|
||||
ctx.getString(R.string.voice_data_unavailable));
|
||||
}
|
||||
}
|
||||
|
||||
// see comments below why it is impossible to read from zip (don't know
|
||||
// how to play file from zip)
|
||||
// voiceZipFile = null;
|
||||
if (voiceDir != null) {
|
||||
long time = System.currentTimeMillis();
|
||||
boolean wrong = false;
|
||||
try {
|
||||
InputStream config;
|
||||
// if (voiceDir.getName().endsWith(".zip")) { //$NON-NLS-1$
|
||||
// voiceZipFile = new ZipFile(voiceDir);
|
||||
// config = voiceZipFile.getInputStream(voiceZipFile.getEntry("_config.p")); //$NON-NLS-1$
|
||||
// } else {
|
||||
config = new FileInputStream(new File(voiceDir, configFile)); //$NON-NLS-1$
|
||||
// }
|
||||
if (!wrong) {
|
||||
prologSystem.setTheory(new Theory(config));
|
||||
}
|
||||
} catch (InvalidTheoryException e) {
|
||||
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
|
||||
wrong = true;
|
||||
} catch (IOException e) {
|
||||
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
|
||||
wrong = true;
|
||||
}
|
||||
if (wrong) {
|
||||
throw new CommandPlayerException(ctx.getString(R.string.voice_data_corrupted));
|
||||
} else {
|
||||
Term val = solveSimplePredicate(P_VERSION);
|
||||
if (!(val instanceof Number) || ((Number)val).intValue() != voiceVersion) {
|
||||
throw new CommandPlayerException(ctx.getString(R.string.voice_data_not_supported));
|
||||
}
|
||||
}
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing voice subsystem " + voiceProvider + " : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
protected Term solveSimplePredicate(String predicate) {
|
||||
Term val = null;
|
||||
Var v = new Var("MyVariable"); //$NON-NLS-1$
|
||||
SolveInfo s = prologSystem.solve(new Struct(predicate, v));
|
||||
if (s.isSuccess()) {
|
||||
prologSystem.solveEnd();
|
||||
try {
|
||||
val = s.getVarValue(v.getName());
|
||||
} catch (NoSolutionException e) {
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> execute(List<Struct> listCmd){
|
||||
Struct list = new Struct(listCmd.toArray(new Term[listCmd.size()]));
|
||||
Var result = new Var("RESULT"); //$NON-NLS-1$
|
||||
List<String> files = new ArrayList<String>();
|
||||
SolveInfo res = prologSystem.solve(new Struct(P_RESOLVE, list, result));
|
||||
|
||||
if (res.isSuccess()) {
|
||||
try {
|
||||
prologSystem.solveEnd();
|
||||
Term solution = res.getVarValue(result.getName());
|
||||
|
||||
Iterator<?> listIterator = ((Struct) solution).listIterator();
|
||||
while(listIterator.hasNext()){
|
||||
Object term = listIterator.next();
|
||||
if(term instanceof Struct){
|
||||
files.add(((Struct) term).getName());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NoSolutionException e) {
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentVoice() {
|
||||
if (voiceDir == null) {
|
||||
return null;
|
||||
}
|
||||
return voiceDir.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandBuilder newCommandBuilder() {
|
||||
return new CommandBuilder(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
ctx = null;
|
||||
prologSystem = null;
|
||||
}
|
||||
|
||||
}
|
179
OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java
Normal file
179
OsmAnd/src/net/osmand/plus/voice/CommandBuilder.java
Normal file
|
@ -0,0 +1,179 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import alice.tuprolog.Struct;
|
||||
import alice.tuprolog.Term;
|
||||
|
||||
public class CommandBuilder {
|
||||
|
||||
private static final Log log = LogUtil.getLog(CommandBuilder.class);
|
||||
|
||||
protected static final String C_PREPARE_TURN = "prepare_turn"; //$NON-NLS-1$
|
||||
protected static final String C_PREPARE_ROUNDABOUT = "prepare_roundabout"; //$NON-NLS-1$
|
||||
protected static final String C_PREPARE_MAKE_UT = "prepare_make_ut"; //$NON-NLS-1$
|
||||
protected static final String C_ROUNDABOUT = "roundabout"; //$NON-NLS-1$
|
||||
protected static final String C_GO_AHEAD = "go_ahead"; //$NON-NLS-1$
|
||||
protected static final String C_TURN = "turn"; //$NON-NLS-1$
|
||||
protected static final String C_MAKE_UT = "make_ut"; //$NON-NLS-1$
|
||||
protected static final String C_PREAMBLE = "preamble"; //$NON-NLS-1$
|
||||
protected static final String C_AND_ARRIVE_DESTINATION = "and_arrive_destination"; //$NON-NLS-1$
|
||||
protected static final String C_THEN = "then"; //$NON-NLS-1$
|
||||
protected static final String C_REACHED_DESTINATION = "reached_destination"; //$NON-NLS-1$
|
||||
protected static final String C_BEAR_LEFT = "bear_left"; //$NON-NLS-1$
|
||||
protected static final String C_BEAR_RIGHT = "bear_right"; //$NON-NLS-1$
|
||||
protected static final String C_ROUTE_RECALC = "route_recalc"; //$NON-NLS-1$
|
||||
protected static final String C_ROUTE_NEW_CALC = "route_new_calc"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private final CommandPlayer commandPlayer;
|
||||
private boolean alreadyExecuted = false;
|
||||
private List<Struct> listStruct = new ArrayList<Struct>();
|
||||
|
||||
public CommandBuilder(CommandPlayer commandPlayer){
|
||||
this(commandPlayer, true);
|
||||
}
|
||||
|
||||
public CommandBuilder(CommandPlayer commandPlayer, boolean preamble) {
|
||||
this.commandPlayer = commandPlayer;
|
||||
if (preamble) {
|
||||
addCommand(C_PREAMBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkState(){
|
||||
if(alreadyExecuted){
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private CommandBuilder addCommand(String name, Object... args){
|
||||
checkState();
|
||||
Term[] list = new Term[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object o = args[i];
|
||||
if(o instanceof java.lang.Number){
|
||||
if(o instanceof java.lang.Double){
|
||||
list[i] = new alice.tuprolog.Double((Double) o);
|
||||
} else if(o instanceof java.lang.Float){
|
||||
list[i] = new alice.tuprolog.Float((Float) o);
|
||||
} else if(o instanceof java.lang.Long){
|
||||
list[i] = new alice.tuprolog.Long((Long) o);
|
||||
} else {
|
||||
list[i] = new alice.tuprolog.Int(((java.lang.Number)o).intValue());
|
||||
}
|
||||
} else if(o instanceof String){
|
||||
list[i] = new Struct((String) o);
|
||||
}
|
||||
if(list[i]== null){
|
||||
throw new NullPointerException(name +" " + o); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
Struct struct = new Struct(name, list);
|
||||
if(log.isDebugEnabled()){
|
||||
log.debug("Adding command : " + name + " " + Arrays.toString(args)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
listStruct.add(struct);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandBuilder goAhead(){
|
||||
return addCommand(C_GO_AHEAD);
|
||||
}
|
||||
|
||||
public CommandBuilder goAhead(double dist){
|
||||
return addCommand(C_GO_AHEAD, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder makeUT(){
|
||||
return addCommand(C_MAKE_UT);
|
||||
}
|
||||
|
||||
public CommandBuilder makeUT(double dist){
|
||||
return addCommand(C_MAKE_UT, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder prepareMakeUT(double dist){
|
||||
return addCommand(C_PREPARE_MAKE_UT, dist);
|
||||
}
|
||||
|
||||
|
||||
public CommandBuilder turn(String param){
|
||||
return addCommand(C_TURN, param);
|
||||
}
|
||||
|
||||
public CommandBuilder turn(String param, double dist){
|
||||
return addCommand(C_TURN, param, dist);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param param A_LEFT, A_RIGHT, ...
|
||||
* @param dist
|
||||
* @return
|
||||
*/
|
||||
public CommandBuilder prepareTurn(String param, double dist){
|
||||
return addCommand(C_PREPARE_TURN, param, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder prepareRoundAbout(double dist){
|
||||
return addCommand(C_PREPARE_ROUNDABOUT, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder roundAbout(double dist, double angle, int exit){
|
||||
return addCommand(C_ROUNDABOUT, dist, angle, exit);
|
||||
}
|
||||
|
||||
public CommandBuilder roundAbout(double angle, int exit){
|
||||
return addCommand(C_ROUNDABOUT, angle, exit);
|
||||
}
|
||||
|
||||
public CommandBuilder andArriveAtDestination(){
|
||||
return addCommand(C_AND_ARRIVE_DESTINATION);
|
||||
}
|
||||
|
||||
public CommandBuilder arrivedAtDestination(){
|
||||
return addCommand(C_REACHED_DESTINATION);
|
||||
}
|
||||
|
||||
public CommandBuilder bearLeft(){
|
||||
return addCommand(C_BEAR_LEFT);
|
||||
}
|
||||
|
||||
public CommandBuilder bearRight(){
|
||||
return addCommand(C_BEAR_RIGHT);
|
||||
}
|
||||
|
||||
public CommandBuilder then(){
|
||||
return addCommand(C_THEN);
|
||||
}
|
||||
|
||||
public CommandBuilder newRouteCalculated(double dist){
|
||||
return addCommand(C_ROUTE_NEW_CALC, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder routeRecalculated(double dist){
|
||||
return addCommand(C_ROUTE_RECALC, dist);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void play(){
|
||||
this.commandPlayer.playCommands(this);
|
||||
}
|
||||
|
||||
protected List<String> execute(){
|
||||
alreadyExecuted = true;
|
||||
return this.commandPlayer.execute(listStruct);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,420 +1,24 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
import net.osmand.data.IndexConstants;
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import alice.tuprolog.InvalidLibraryException;
|
||||
import alice.tuprolog.InvalidTheoryException;
|
||||
import alice.tuprolog.NoSolutionException;
|
||||
import alice.tuprolog.Number;
|
||||
import alice.tuprolog.Prolog;
|
||||
import alice.tuprolog.SolveInfo;
|
||||
import alice.tuprolog.Struct;
|
||||
import alice.tuprolog.Term;
|
||||
import alice.tuprolog.Theory;
|
||||
import alice.tuprolog.Var;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
|
||||
/**
|
||||
* That class represents command player.
|
||||
* It gets commands from input, analyze what files should be played and play
|
||||
* them using media player
|
||||
*/
|
||||
public class CommandPlayer {
|
||||
public interface CommandPlayer {
|
||||
|
||||
private static final Log log = LogUtil.getLog(CommandPlayer.class);
|
||||
public abstract String getCurrentVoice();
|
||||
|
||||
protected Context ctx;
|
||||
// or zip file
|
||||
private File voiceDir;
|
||||
// private ZipFile voiceZipFile;
|
||||
public abstract CommandBuilder newCommandBuilder();
|
||||
|
||||
// resolving commands to play
|
||||
private Prolog prologSystem;
|
||||
public abstract void playCommands(CommandBuilder builder);
|
||||
|
||||
// playing media
|
||||
private MediaPlayer mediaPlayer;
|
||||
// indicates that player is ready to play first file
|
||||
private boolean playNext = true;
|
||||
private List<String> filesToPlay = Collections.synchronizedList(new ArrayList<String>());
|
||||
public abstract void clear();
|
||||
|
||||
public abstract List<String> execute(List<Struct> listStruct);
|
||||
|
||||
public CommandPlayer(Context ctx){
|
||||
long time = System.currentTimeMillis();
|
||||
try {
|
||||
this.ctx = ctx;
|
||||
prologSystem = new Prolog(new String[]{"alice.tuprolog.lib.BasicLibrary"}); //$NON-NLS-1$
|
||||
} catch (InvalidLibraryException e) {
|
||||
log.error("Initializing error", e); //$NON-NLS-1$
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
mediaPlayer = new MediaPlayer();
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing prolog system : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public String getCurrentVoice(){
|
||||
if(voiceDir == null){
|
||||
return null;
|
||||
}
|
||||
return voiceDir.getName();
|
||||
}
|
||||
|
||||
public String init(String voiceProvider){
|
||||
prologSystem.clearTheory();
|
||||
voiceDir = null;
|
||||
if(voiceProvider != null){
|
||||
File parent = OsmandSettings.getOsmandSettings(ctx).extendOsmandPath(ResourceManager.VOICE_PATH);
|
||||
voiceDir = new File(parent, voiceProvider);
|
||||
if(!voiceDir.exists()){
|
||||
voiceDir = null;
|
||||
return ctx.getString(R.string.voice_data_unavailable);
|
||||
}
|
||||
}
|
||||
|
||||
// see comments below why it is impossible to read from zip (don't know how to play file from zip)
|
||||
// voiceZipFile = null;
|
||||
if(voiceDir != null) {
|
||||
long time = System.currentTimeMillis();
|
||||
boolean wrong = false;
|
||||
try {
|
||||
InputStream config;
|
||||
// if (voiceDir.getName().endsWith(".zip")) { //$NON-NLS-1$
|
||||
// voiceZipFile = new ZipFile(voiceDir);
|
||||
// config = voiceZipFile.getInputStream(voiceZipFile.getEntry("_config.p")); //$NON-NLS-1$
|
||||
// } else {
|
||||
config = new FileInputStream(new File(voiceDir, "_config.p")); //$NON-NLS-1$
|
||||
// }
|
||||
if (!wrong) {
|
||||
prologSystem.setTheory(new Theory(config));
|
||||
}
|
||||
} catch (InvalidTheoryException e) {
|
||||
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
|
||||
wrong = true;
|
||||
} catch (IOException e) {
|
||||
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
|
||||
wrong = true;
|
||||
}
|
||||
if(wrong){
|
||||
return ctx.getString(R.string.voice_data_corrupted);
|
||||
} else {
|
||||
boolean versionSupported = false;
|
||||
Var v = new Var("VERSION"); //$NON-NLS-1$
|
||||
SolveInfo s = prologSystem.solve(new Struct(P_VERSION, v));
|
||||
if(s.isSuccess()){
|
||||
prologSystem.solveEnd();
|
||||
try {
|
||||
Term val = s.getVarValue(v.getName());
|
||||
if(val instanceof Number){
|
||||
versionSupported = ((Number) val).intValue() == IndexConstants.VOICE_VERSION;
|
||||
}
|
||||
} catch (NoSolutionException e) {
|
||||
}
|
||||
}
|
||||
if(!versionSupported){
|
||||
return ctx.getString(R.string.voice_data_not_supported);
|
||||
}
|
||||
}
|
||||
|
||||
if (log.isInfoEnabled()) {
|
||||
log.info("Initializing voice subsystem " + voiceProvider + " : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public CommandBuilder newCommandBuilder(){
|
||||
return new CommandBuilder();
|
||||
}
|
||||
|
||||
|
||||
protected List<String> execute(List<Struct> listCmd){
|
||||
Struct list = new Struct(listCmd.toArray(new Term[listCmd.size()]));
|
||||
Var result = new Var("RESULT"); //$NON-NLS-1$
|
||||
List<String> files = new ArrayList<String>();
|
||||
SolveInfo res = prologSystem.solve(new Struct(P_RESOLVE, list, result));
|
||||
|
||||
if (res.isSuccess()) {
|
||||
try {
|
||||
prologSystem.solveEnd();
|
||||
Term solution = res.getVarValue(result.getName());
|
||||
|
||||
Iterator<?> listIterator = ((Struct) solution).listIterator();
|
||||
while(listIterator.hasNext()){
|
||||
Object term = listIterator.next();
|
||||
if(term instanceof Struct){
|
||||
files.add(((Struct) term).getName());
|
||||
}
|
||||
}
|
||||
|
||||
} catch (NoSolutionException e) {
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
|
||||
public void playCommands(CommandBuilder builder){
|
||||
filesToPlay.addAll(builder.execute());
|
||||
playQueue();
|
||||
}
|
||||
|
||||
private synchronized void playQueue() {
|
||||
while (!filesToPlay.isEmpty() && playNext) {
|
||||
String f = filesToPlay.remove(0);
|
||||
if (f != null && voiceDir != null) {
|
||||
boolean exists = false;
|
||||
// if(voiceZipFile != null){
|
||||
// ZipEntry entry = voiceZipFile.getEntry(f);
|
||||
// exists = entry != null;
|
||||
// voiceZipFile.getInputStream(entry);
|
||||
//
|
||||
// } else {
|
||||
File file = new File(voiceDir, f);
|
||||
exists = file.exists();
|
||||
// }
|
||||
if (exists) {
|
||||
log.debug("Playing file : " + f); //$NON-NLS-1$
|
||||
playNext = false;
|
||||
try {
|
||||
// Can't play sound file from zip it seams to be impossible only unpack and play!!!
|
||||
mediaPlayer.setDataSource(file.getAbsolutePath());
|
||||
mediaPlayer.prepare();
|
||||
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mp.release();
|
||||
mediaPlayer = new MediaPlayer();
|
||||
int sleep = 60;
|
||||
boolean delay = true;
|
||||
while (!filesToPlay.isEmpty() && delay) {
|
||||
delay = filesToPlay.get(0).startsWith(DELAY_CONST);
|
||||
if (delay) {
|
||||
String s = filesToPlay.remove(0).substring(DELAY_CONST.length());
|
||||
try {
|
||||
sleep += Integer.parseInt(s);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(sleep);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
playNext = true;
|
||||
playQueue();
|
||||
}
|
||||
});
|
||||
|
||||
mediaPlayer.start();
|
||||
} catch (Exception e) {
|
||||
log.error("Error while playing voice command", e); //$NON-NLS-1$
|
||||
playNext = true;
|
||||
|
||||
}
|
||||
} else {
|
||||
log.info("Play file not found : " + f); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected static final String P_VERSION = "version"; //$NON-NLS-1$
|
||||
protected static final String P_RESOLVE = "resolve"; //$NON-NLS-1$
|
||||
|
||||
public static final String A_LEFT = "left"; //$NON-NLS-1$
|
||||
public static final String A_LEFT_SH = "left_sh"; //$NON-NLS-1$
|
||||
public static final String A_LEFT_SL = "left_sl"; //$NON-NLS-1$
|
||||
public static final String A_RIGHT = "right"; //$NON-NLS-1$
|
||||
public static final String A_RIGHT_SH = "right_sh"; //$NON-NLS-1$
|
||||
public static final String A_RIGHT_SL = "right_sl"; //$NON-NLS-1$
|
||||
|
||||
protected static final String C_PREPARE_TURN = "prepare_turn"; //$NON-NLS-1$
|
||||
protected static final String C_PREPARE_ROUNDABOUT = "prepare_roundabout"; //$NON-NLS-1$
|
||||
protected static final String C_PREPARE_MAKE_UT = "prepare_make_ut"; //$NON-NLS-1$
|
||||
protected static final String C_ROUNDABOUT = "roundabout"; //$NON-NLS-1$
|
||||
protected static final String C_GO_AHEAD = "go_ahead"; //$NON-NLS-1$
|
||||
protected static final String C_TURN = "turn"; //$NON-NLS-1$
|
||||
protected static final String C_MAKE_UT = "make_ut"; //$NON-NLS-1$
|
||||
protected static final String C_PREAMBLE = "preamble"; //$NON-NLS-1$
|
||||
protected static final String C_AND_ARRIVE_DESTINATION = "and_arrive_destination"; //$NON-NLS-1$
|
||||
protected static final String C_THEN = "then"; //$NON-NLS-1$
|
||||
protected static final String C_REACHED_DESTINATION = "reached_destination"; //$NON-NLS-1$
|
||||
protected static final String C_BEAR_LEFT = "bear_left"; //$NON-NLS-1$
|
||||
protected static final String C_BEAR_RIGHT = "bear_right"; //$NON-NLS-1$
|
||||
protected static final String C_ROUTE_RECALC = "route_recalc"; //$NON-NLS-1$
|
||||
protected static final String C_ROUTE_NEW_CALC = "route_new_calc"; //$NON-NLS-1$
|
||||
|
||||
|
||||
protected static final String DELAY_CONST = "delay_"; //$NON-NLS-1$
|
||||
|
||||
public class CommandBuilder {
|
||||
|
||||
|
||||
private boolean alreadyExecuted = false;
|
||||
private List<Struct> listStruct = new ArrayList<Struct>();
|
||||
|
||||
public CommandBuilder(){
|
||||
this(true);
|
||||
}
|
||||
|
||||
public CommandBuilder(boolean preamble) {
|
||||
if (preamble) {
|
||||
addCommand(C_PREAMBLE);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkState(){
|
||||
if(alreadyExecuted){
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
private CommandBuilder addCommand(String name, Object... args){
|
||||
checkState();
|
||||
Term[] list = new Term[args.length];
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
Object o = args[i];
|
||||
if(o instanceof java.lang.Number){
|
||||
if(o instanceof java.lang.Double){
|
||||
list[i] = new alice.tuprolog.Double((Double) o);
|
||||
} else if(o instanceof java.lang.Float){
|
||||
list[i] = new alice.tuprolog.Float((Float) o);
|
||||
} else if(o instanceof java.lang.Long){
|
||||
list[i] = new alice.tuprolog.Long((Long) o);
|
||||
} else {
|
||||
list[i] = new alice.tuprolog.Int(((java.lang.Number)o).intValue());
|
||||
}
|
||||
} else if(o instanceof String){
|
||||
list[i] = new Struct((String) o);
|
||||
}
|
||||
if(list[i]== null){
|
||||
throw new NullPointerException(name +" " + o); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
Struct struct = new Struct(name, list);
|
||||
if(log.isDebugEnabled()){
|
||||
log.debug("Adding command : " + name + " " + Arrays.toString(args)); //$NON-NLS-1$ //$NON-NLS-2$
|
||||
}
|
||||
listStruct.add(struct);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public CommandBuilder goAhead(){
|
||||
return addCommand(C_GO_AHEAD);
|
||||
}
|
||||
|
||||
public CommandBuilder goAhead(double dist){
|
||||
return addCommand(C_GO_AHEAD, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder makeUT(){
|
||||
return addCommand(C_MAKE_UT);
|
||||
}
|
||||
|
||||
public CommandBuilder makeUT(double dist){
|
||||
return addCommand(C_MAKE_UT, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder prepareMakeUT(double dist){
|
||||
return addCommand(C_PREPARE_MAKE_UT, dist);
|
||||
}
|
||||
|
||||
|
||||
public CommandBuilder turn(String param){
|
||||
return addCommand(C_TURN, param);
|
||||
}
|
||||
|
||||
public CommandBuilder turn(String param, double dist){
|
||||
return addCommand(C_TURN, param, dist);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param param A_LEFT, A_RIGHT, ...
|
||||
* @param dist
|
||||
* @return
|
||||
*/
|
||||
public CommandBuilder prepareTurn(String param, double dist){
|
||||
return addCommand(C_PREPARE_TURN, param, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder prepareRoundAbout(double dist){
|
||||
return addCommand(C_PREPARE_ROUNDABOUT, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder roundAbout(double dist, double angle, int exit){
|
||||
return addCommand(C_ROUNDABOUT, dist, angle, exit);
|
||||
}
|
||||
|
||||
public CommandBuilder roundAbout(double angle, int exit){
|
||||
return addCommand(C_ROUNDABOUT, angle, exit);
|
||||
}
|
||||
|
||||
public CommandBuilder andArriveAtDestination(){
|
||||
return addCommand(C_AND_ARRIVE_DESTINATION);
|
||||
}
|
||||
|
||||
public CommandBuilder arrivedAtDestination(){
|
||||
return addCommand(C_REACHED_DESTINATION);
|
||||
}
|
||||
|
||||
public CommandBuilder bearLeft(){
|
||||
return addCommand(C_BEAR_LEFT);
|
||||
}
|
||||
|
||||
public CommandBuilder bearRight(){
|
||||
return addCommand(C_BEAR_RIGHT);
|
||||
}
|
||||
|
||||
public CommandBuilder then(){
|
||||
return addCommand(C_THEN);
|
||||
}
|
||||
|
||||
public CommandBuilder newRouteCalculated(double dist){
|
||||
return addCommand(C_ROUTE_NEW_CALC, dist);
|
||||
}
|
||||
|
||||
public CommandBuilder routeRecalculated(double dist){
|
||||
return addCommand(C_ROUTE_RECALC, dist);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void play(){
|
||||
CommandPlayer.this.playCommands(this);
|
||||
}
|
||||
|
||||
protected List<String> execute(){
|
||||
alreadyExecuted = true;
|
||||
return CommandPlayer.this.execute(listStruct);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void onActivityInit(Activity ctx);
|
||||
|
||||
public void onActvitiyStop(Context ctx);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
22
OsmAnd/src/net/osmand/plus/voice/CommandPlayerException.java
Normal file
22
OsmAnd/src/net/osmand/plus/voice/CommandPlayerException.java
Normal file
|
@ -0,0 +1,22 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
|
||||
/**
|
||||
* Exception on CommandPlayer
|
||||
*
|
||||
* @author Pavol Zibrita <pavol.zibrita@gmail.com>
|
||||
*/
|
||||
public class CommandPlayerException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 8413902962574061832L;
|
||||
private final String error;
|
||||
|
||||
public CommandPlayerException(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return error;
|
||||
}
|
||||
|
||||
}
|
34
OsmAnd/src/net/osmand/plus/voice/CommandPlayerFactory.java
Normal file
34
OsmAnd/src/net/osmand/plus/voice/CommandPlayerFactory.java
Normal file
|
@ -0,0 +1,34 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import net.osmand.plus.OsmandSettings;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.ResourceManager;
|
||||
import net.osmand.plus.activities.OsmandApplication;
|
||||
import android.app.Activity;
|
||||
import android.os.Build;
|
||||
|
||||
public class CommandPlayerFactory
|
||||
{
|
||||
public static CommandPlayer createCommandPlayer(String voiceProvider, OsmandApplication osmandApplication, Activity ctx)
|
||||
throws CommandPlayerException
|
||||
{
|
||||
if (voiceProvider != null){
|
||||
File parent = OsmandSettings.getOsmandSettings(ctx).extendOsmandPath(ResourceManager.VOICE_PATH);
|
||||
File voiceDir = new File(parent, voiceProvider);
|
||||
if(!voiceDir.exists()){
|
||||
throw new CommandPlayerException(ctx.getString(R.string.voice_data_unavailable));
|
||||
}
|
||||
if (MediaCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return new MediaCommandPlayerImpl(osmandApplication, voiceProvider);
|
||||
} else if (Integer.parseInt(Build.VERSION.SDK) >= 4) {
|
||||
if (TTSCommandPlayerImpl.isMyData(voiceDir)) {
|
||||
return new TTSCommandPlayerImpl(ctx, voiceProvider);
|
||||
}
|
||||
}
|
||||
throw new CommandPlayerException(ctx.getString(R.string.voice_data_not_supported));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
127
OsmAnd/src/net/osmand/plus/voice/MediaCommandPlayerImpl.java
Normal file
127
OsmAnd/src/net/osmand/plus/voice/MediaCommandPlayerImpl.java
Normal file
|
@ -0,0 +1,127 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.osmand.LogUtil;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.media.MediaPlayer;
|
||||
|
||||
/**
|
||||
* That class represents command player.
|
||||
* It gets commands from input, analyze what files should be played and play
|
||||
* them using media player
|
||||
*/
|
||||
public class MediaCommandPlayerImpl extends AbstractPrologCommandPlayer {
|
||||
|
||||
private static final String CONFIG_FILE = "_config.p";
|
||||
private static final int MEDIA_VOICE_VERSION = 0;
|
||||
|
||||
private static final Log log = LogUtil.getLog(MediaCommandPlayerImpl.class);
|
||||
|
||||
// playing media
|
||||
private MediaPlayer mediaPlayer;
|
||||
// indicates that player is ready to play first file
|
||||
private boolean playNext = true;
|
||||
private List<String> filesToPlay = Collections.synchronizedList(new ArrayList<String>());
|
||||
|
||||
|
||||
public MediaCommandPlayerImpl(Context ctx, String voiceProvider)
|
||||
throws CommandPlayerException
|
||||
{
|
||||
super(ctx, voiceProvider, CONFIG_FILE, MEDIA_VOICE_VERSION);
|
||||
mediaPlayer = new MediaPlayer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityInit(Activity ctx) {
|
||||
//do nothing here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActvitiyStop(Context ctx) {
|
||||
//do nothing here
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
mediaPlayer = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playCommands(CommandBuilder builder){
|
||||
filesToPlay.addAll(builder.execute());
|
||||
playQueue();
|
||||
}
|
||||
|
||||
private synchronized void playQueue() {
|
||||
while (!filesToPlay.isEmpty() && playNext) {
|
||||
String f = filesToPlay.remove(0);
|
||||
if (f != null && voiceDir != null) {
|
||||
boolean exists = false;
|
||||
// if(voiceZipFile != null){
|
||||
// ZipEntry entry = voiceZipFile.getEntry(f);
|
||||
// exists = entry != null;
|
||||
// voiceZipFile.getInputStream(entry);
|
||||
//
|
||||
// } else {
|
||||
File file = new File(voiceDir, f);
|
||||
exists = file.exists();
|
||||
// }
|
||||
if (exists) {
|
||||
log.debug("Playing file : " + f); //$NON-NLS-1$
|
||||
playNext = false;
|
||||
try {
|
||||
// Can't play sound file from zip it seams to be impossible only unpack and play!!!
|
||||
mediaPlayer.setDataSource(file.getAbsolutePath());
|
||||
mediaPlayer.prepare();
|
||||
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
|
||||
public void onCompletion(MediaPlayer mp) {
|
||||
mp.release();
|
||||
mediaPlayer = new MediaPlayer();
|
||||
int sleep = 60;
|
||||
boolean delay = true;
|
||||
while (!filesToPlay.isEmpty() && delay) {
|
||||
delay = filesToPlay.get(0).startsWith(DELAY_CONST);
|
||||
if (delay) {
|
||||
String s = filesToPlay.remove(0).substring(DELAY_CONST.length());
|
||||
try {
|
||||
sleep += Integer.parseInt(s);
|
||||
} catch (NumberFormatException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
Thread.sleep(sleep);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
playNext = true;
|
||||
playQueue();
|
||||
}
|
||||
});
|
||||
|
||||
mediaPlayer.start();
|
||||
} catch (Exception e) {
|
||||
log.error("Error while playing voice command", e); //$NON-NLS-1$
|
||||
playNext = true;
|
||||
|
||||
}
|
||||
} else {
|
||||
log.info("Play file not found : " + f); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isMyData(File voiceDir) {
|
||||
return new File(voiceDir, CONFIG_FILE).exists();
|
||||
}
|
||||
}
|
175
OsmAnd/src/net/osmand/plus/voice/TTSCommandPlayerImpl.java
Normal file
175
OsmAnd/src/net/osmand/plus/voice/TTSCommandPlayerImpl.java
Normal file
|
@ -0,0 +1,175 @@
|
|||
package net.osmand.plus.voice;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import net.osmand.Algoritms;
|
||||
import net.osmand.plus.R;
|
||||
import net.osmand.plus.activities.SettingsActivity;
|
||||
import alice.tuprolog.Struct;
|
||||
import alice.tuprolog.Term;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.net.Uri;
|
||||
import android.speech.tts.TextToSpeech;
|
||||
import android.speech.tts.TextToSpeech.OnInitListener;
|
||||
|
||||
public class TTSCommandPlayerImpl extends AbstractPrologCommandPlayer {
|
||||
|
||||
private final class IntentStarter implements
|
||||
DialogInterface.OnClickListener {
|
||||
private final Activity ctx;
|
||||
private final String intentAction;
|
||||
private final Uri intentData;
|
||||
|
||||
private IntentStarter(Activity ctx, String intentAction) {
|
||||
this(ctx,intentAction, null);
|
||||
}
|
||||
|
||||
private IntentStarter(Activity ctx, String intentAction, Uri intentData) {
|
||||
this.ctx = ctx;
|
||||
this.intentAction = intentAction;
|
||||
this.intentData = intentData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
Intent installIntent = new Intent();
|
||||
installIntent.setAction(intentAction);
|
||||
if (intentData != null) {
|
||||
installIntent.setData(intentData);
|
||||
}
|
||||
ctx.startActivity(installIntent);
|
||||
}
|
||||
}
|
||||
|
||||
private static final String CONFIG_FILE = "_ttsconfig.p";
|
||||
private static final int TTS_VOICE_VERSION = 100;
|
||||
private TextToSpeech mTts;
|
||||
private Context mTtsContext;
|
||||
private String language;
|
||||
|
||||
protected TTSCommandPlayerImpl(Activity ctx, String voiceProvider)
|
||||
throws CommandPlayerException {
|
||||
super(ctx, voiceProvider, CONFIG_FILE, TTS_VOICE_VERSION);
|
||||
final Term langVal = solveSimplePredicate("language");
|
||||
if (langVal instanceof Struct) {
|
||||
language = ((Struct) langVal).getName();
|
||||
}
|
||||
if (Algoritms.isEmpty(language)) {
|
||||
throw new CommandPlayerException(
|
||||
ctx.getString(R.string.voice_data_corrupted));
|
||||
}
|
||||
onActivityInit(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playCommands(CommandBuilder builder) {
|
||||
if (mTts != null) {
|
||||
final List<String> execute = builder.execute(); //list of strings, the speech text, play it
|
||||
StringBuilder bld = new StringBuilder();
|
||||
for (String s : execute) {
|
||||
bld.append(s).append(' ');
|
||||
}
|
||||
mTts.speak(bld.toString(), TextToSpeech.QUEUE_ADD, null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityInit(final Activity ctx) {
|
||||
if (mTts != null && mTtsContext != ctx) {
|
||||
//clear only, if the mTts was initialized in another context.
|
||||
//Unfortunately, for example from settings to map first the map is initialized than
|
||||
//the settingsactivity is destroyed...
|
||||
internalClear();
|
||||
}
|
||||
if (mTts == null) {
|
||||
mTtsContext = ctx;
|
||||
mTts = new TextToSpeech(ctx, new OnInitListener() {
|
||||
@Override
|
||||
public void onInit(int status) {
|
||||
if (status != TextToSpeech.SUCCESS) {
|
||||
internalClear();
|
||||
} else {
|
||||
switch (mTts.isLanguageAvailable(new Locale(language)))
|
||||
{
|
||||
case TextToSpeech.LANG_MISSING_DATA:
|
||||
internalClear();
|
||||
Builder builder = createAlertDialog(
|
||||
R.string.tts_missing_language_data_title,
|
||||
R.string.tts_missing_language_data,
|
||||
new IntentStarter(
|
||||
ctx,
|
||||
TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA),
|
||||
ctx);
|
||||
builder.show();
|
||||
break;
|
||||
case TextToSpeech.LANG_AVAILABLE:
|
||||
mTts.setLanguage(new Locale(language));
|
||||
break;
|
||||
case TextToSpeech.LANG_NOT_SUPPORTED:
|
||||
//maybe weird, but I didn't want to introduce parameter in around 5 methods just to do
|
||||
//this if condition
|
||||
if (ctx instanceof SettingsActivity) {
|
||||
builder = createAlertDialog(
|
||||
R.string.tts_language_not_supported_title,
|
||||
R.string.tts_language_not_supported,
|
||||
new IntentStarter(
|
||||
ctx,
|
||||
Intent.ACTION_VIEW, Uri.parse("market://search?q=text to speech engine"
|
||||
)),
|
||||
ctx);
|
||||
builder.show();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Builder createAlertDialog(int titleResID, int messageResID, IntentStarter intentStarter, final Activity ctx) {
|
||||
Builder builder = new AlertDialog.Builder(ctx);
|
||||
builder.setCancelable(true);
|
||||
builder.setNegativeButton(R.string.default_buttons_no, null);
|
||||
builder.setPositiveButton(R.string.default_buttons_yes, intentStarter);
|
||||
builder.setTitle(titleResID);
|
||||
builder.setMessage(messageResID);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActvitiyStop(Context ctx) {
|
||||
//stop only when the context is the same
|
||||
if (mTtsContext == ctx) {
|
||||
internalClear();
|
||||
}
|
||||
}
|
||||
|
||||
private void internalClear() {
|
||||
if (mTts != null) {
|
||||
mTts.shutdown();
|
||||
mTtsContext = null;
|
||||
mTts = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
super.clear();
|
||||
internalClear();
|
||||
}
|
||||
|
||||
public static boolean isMyData(File voiceDir) throws CommandPlayerException {
|
||||
return new File(voiceDir, CONFIG_FILE).exists();
|
||||
}
|
||||
|
||||
}
|
120
OsmAnd/voice/en-tts/_ttsconfig.p
Normal file
120
OsmAnd/voice/en-tts/_ttsconfig.p
Normal file
|
@ -0,0 +1,120 @@
|
|||
:- op('==', xfy, 500).
|
||||
version(100).
|
||||
language(en).
|
||||
|
||||
% before each announcement (beep)
|
||||
preamble - [].
|
||||
|
||||
|
||||
%% TURNS
|
||||
turn('left', ['turn left ']).
|
||||
turn('left_sh', ['sharp left ']).
|
||||
turn('left_sl', ['turn slightly left ']).
|
||||
turn('right', ['turn right ']).
|
||||
turn('right_sh', ['sharp right ']).
|
||||
turn('right_sl', ['turn slightly right ']).
|
||||
|
||||
prepare_turn(Turn, Dist) == ['Prepare to ', M, ' after ', D] :-
|
||||
distance(Dist) == D, turn(Turn, M).
|
||||
turn(Turn, Dist) == ['After ', D, M] :-
|
||||
distance(Dist) == D, turn(Turn, M).
|
||||
turn(Turn) == M :- turn(Turn, M).
|
||||
|
||||
|
||||
prepare_make_ut(Dist) == ['Prepare to turn after ', D, ' turn back'] :-
|
||||
distance(Dist) == D.
|
||||
|
||||
prepare_roundabout(Dist) == ['Prepare to enter roundabout after ', D] :-
|
||||
distance(Dist) == D.
|
||||
|
||||
make_ut(Dist) == ['After ', D, ' turn back '] :-
|
||||
distance(Dist) == D.
|
||||
make_ut == ['Turn back '].
|
||||
|
||||
roundabout(Dist, _Angle, Exit) == ['After ', D, ' enter the roundabout, and take the ', E, 'exit'] :- distance(Dist) == D, nth(Exit, E).
|
||||
roundabout(_Angle, Exit) == ['taking the ', E, 'exit'] :- nth(Exit, E).
|
||||
|
||||
and_arrive_destination == ['and arrive at your destination ']. % Miss and?
|
||||
then == ['then '].
|
||||
reached_destination == ['you have reached your destination '].
|
||||
bear_right == ['keep right '].
|
||||
bear_left == ['keep left '].
|
||||
route_recalc(_Dist) == []. % ['recalculating route ']. %nothing to said possibly beep?
|
||||
route_new_calc(Dist) == ['The trip is ', D] :- distance(Dist) == D. % nothing to said possibly beep?
|
||||
|
||||
go_ahead(Dist) == ['Drive for ', D]:- distance(Dist) == D.
|
||||
go_ahead == ['Continue straight ahead '].
|
||||
|
||||
%%
|
||||
nth(1, '1st ').
|
||||
nth(2, '2nd ').
|
||||
nth(3, '3rd ').
|
||||
nth(4, '4th ').
|
||||
nth(5, '5th ').
|
||||
nth(6, '6th ').
|
||||
nth(7, '7th ').
|
||||
nth(8, '8th ').
|
||||
nth(9, '9th ').
|
||||
nth(10, '10th ').
|
||||
nth(11, '11th ').
|
||||
nth(12, '12th ').
|
||||
nth(13, '13th ').
|
||||
nth(14, '14th ').
|
||||
nth(15, '15th ').
|
||||
nth(16, '16th ').
|
||||
nth(17, '17th ').
|
||||
|
||||
|
||||
%%% distance measure
|
||||
distance(Dist) == T :- Dist < 1000, dist(Dist, F), append(F, ' meters',T).
|
||||
dist(D, ['10 ']) :- D < 20, !.
|
||||
dist(D, ['20 ']) :- D < 30, !.
|
||||
dist(D, ['30 ']) :- D < 40, !.
|
||||
dist(D, ['40 ']) :- D < 50, !.
|
||||
dist(D, ['50 ']) :- D < 60, !.
|
||||
dist(D, ['60 ']) :- D < 70, !.
|
||||
dist(D, ['70 ']) :- D < 80, !.
|
||||
dist(D, ['80 ']) :- D < 90, !.
|
||||
dist(D, ['90 ']) :- D < 100, !.
|
||||
dist(D, ['100 ']) :- D < 150, !.
|
||||
dist(D, ['150 ']) :- D < 200, !.
|
||||
dist(D, ['200 ']) :- D < 250, !.
|
||||
dist(D, ['250 ']) :- D < 300, !.
|
||||
dist(D, ['300 ']) :- D < 350, !.
|
||||
dist(D, ['350 ']) :- D < 400, !.
|
||||
dist(D, ['400 ']) :- D < 450, !.
|
||||
dist(D, ['450 ']) :- D < 500, !.
|
||||
dist(D, ['500 ']) :- D < 550, !.
|
||||
dist(D, ['550 ']) :- D < 600, !.
|
||||
dist(D, ['600 ']) :- D < 650, !.
|
||||
dist(D, ['650 ']) :- D < 700, !.
|
||||
dist(D, ['700 ']) :- D < 750, !.
|
||||
dist(D, ['750 ']) :- D < 800, !.
|
||||
dist(D, ['800 ']) :- D < 850, !.
|
||||
dist(D, ['850 ']) :- D < 900, !.
|
||||
dist(D, ['900 ']) :- D < 950, !.
|
||||
dist(D, ['950 ']) :- !.
|
||||
|
||||
distance(Dist) == ['more than 1 kilometer '] :- Dist < 1500.
|
||||
distance(Dist) == ['more than 2 kilometers '] :- Dist < 3000.
|
||||
distance(Dist) == ['more than 3 kilometers '] :- Dist < 4000.
|
||||
distance(Dist) == ['more than 4 kilometers '] :- Dist < 5000.
|
||||
distance(Dist) == ['more than 5 kilometers '] :- Dist < 6000.
|
||||
distance(Dist) == ['more than 6 kilometers '] :- Dist < 7000.
|
||||
distance(Dist) == ['more than 7 kilometers '] :- Dist < 8000.
|
||||
distance(Dist) == ['more than 8 kilometers '] :- Dist < 9000.
|
||||
distance(Dist) == ['more than 9 kilometers '] :- Dist < 10000.
|
||||
distance(Dist) == ['more than ', X, ' kilometers '] :- D is Dist/1000, dist(D, X).
|
||||
|
||||
%% resolve command main method
|
||||
%% if you are familar with Prolog you can input specific to the whole mechanism,
|
||||
%% by adding exception cases.
|
||||
flatten(X, Y) :- flatten(X, [], Y), !.
|
||||
flatten([], Acc, Acc).
|
||||
flatten([X|Y], Acc, Res):-
|
||||
flatten(Y, Acc, R), flatten(X, R, Res).
|
||||
flatten(X, Acc, [X|Acc]).
|
||||
|
||||
resolve(X, Y) :- resolve_impl(X,Z), flatten(Z, Y).
|
||||
resolve_impl([],[]).
|
||||
resolve_impl([X|Rest], List) :- resolve_impl(Rest, Tail), ((X == L) -> append(L, Tail, List); List = Tail).
|
Loading…
Reference in a new issue