add voice engine

git-svn-id: https://osmand.googlecode.com/svn/trunk@320 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
Victor Shcherb 2010-07-12 20:05:23 +00:00
parent d5692b938e
commit 7ed1ce9e4b
16 changed files with 475 additions and 68 deletions

View file

@ -20,9 +20,11 @@ public class ToDoConstants {
// 68. Implement service to app work with screen offline // 68. Implement service to app work with screen offline
// (introduce special settings how often update location to monitoring & audio guidance) // (introduce special settings how often update location to monitoring & audio guidance)
// Improvement : Show stops in the transport route on the map // Improvement : Show stops in the transport route on the map
// Improvement : redesign poi selecting (show on map )
// 69. Add phone information to POI
// Not clear if it is really needed // Not clear if it is really needed
// 43. Enable poi filter by name // 43. Enable poi filter by name (find lake by name or shop) - case sensitive search DB!
// 45. Get clear <Use internet> settings. Move that setting on top settings screen. // 45. Get clear <Use internet> settings. Move that setting on top settings screen.
// That setting should rule all activities that use internet. It should ask whenever internet is used // That setting should rule all activities that use internet. It should ask whenever internet is used
// (would you like to use internet for that operation - if using internet is not checked). // (would you like to use internet for that operation - if using internet is not checked).
@ -31,7 +33,7 @@ public class ToDoConstants {
// Unscheduled (complex) // Unscheduled (complex)
// 66. Transport routing (show next stop, total distance, show stop get out) (?). // 66. Transport routing (show next stop, total distance, show stop get out) (?).
// 64. Traffic information (?) // 64. Traffic information (?)
// 65. Intermediate points - for better control routing, to avoid traffic jam ...(?) // 65. Intermediate points - for better control routing, to avoid traffic jams ...(?)
// 40. Support simple vector road rendering (require new index file) (?) // 40. Support simple vector road rendering (require new index file) (?)
// 63. Support simple offline routing(require new index file) (?) // 63. Support simple offline routing(require new index file) (?)

View file

@ -26,7 +26,7 @@ import com.osmand.impl.ConsoleProgressImplementation;
public class IndexBatchCreator { public class IndexBatchCreator {
// config params // config params
private static final boolean indexPOI = true; private static final boolean indexPOI = true;
private static final boolean indexAddress = true; private static final boolean indexAddress = false;
private static final boolean indexTransport = true; private static final boolean indexTransport = true;
private static final boolean writeWayNodes = true; private static final boolean writeWayNodes = true;
@ -52,30 +52,27 @@ public class IndexBatchCreator {
// "czech_republic", "netherlands", // 168, 375, // "czech_republic", "netherlands", // 168, 375,
// "great_britain", "italy", // 281, 246, // "great_britain", "italy", // 281, 246,
// ADD TO TOTAL : 2449 MB // ADD TO TOTAL : 2449 MB
// TODO transport, poi : "czech_republic", "netherlands", "great_britain", "italy" // TODO "great_britain", "italy" (address out of memory, poi, transport) + netherlands
// address : "great_britain", "italy" - out of memory
}; };
// TODO all
protected static final String[] franceProvinces = new String[] { protected static final String[] franceProvinces = new String[] {
"alsace","aquitaine", "auvergne", "basse-normandie", "bourgogne", "bretagne", "centre", // "alsace","aquitaine", "auvergne", "basse-normandie", "bourgogne", "bretagne", "centre",
"champagne-ardenne", "corse", "franche-comte", "haute-normandie", "ile-de-france", // "champagne-ardenne", "corse", "franche-comte", "haute-normandie", "ile-de-france",
"languedoc-roussillon", "limousin", "lorraine", "midi-pyrenees", "nord-pas-de-calais", // "languedoc-roussillon", "limousin", "lorraine", "midi-pyrenees", "nord-pas-de-calais",
"pays-de-la-loire", "picardie","poitou-charentes", "provence-alpes-cote-d-azur", "rhone-alpes" // "pays-de-la-loire", "picardie","poitou-charentes", "provence-alpes-cote-d-azur", "rhone-alpes"
}; };
// TODO all
protected static final String[] germanyLands = new String[] { protected static final String[] germanyLands = new String[] {
"baden-wuerttemberg","bayern", "berlin", "brandenburg", "bremen", "hamburg", "hessen", // "baden-wuerttemberg","bayern", "berlin", "brandenburg", "bremen", "hamburg", "hessen",
"mecklenburg-vorpommern", "niedersachsen", "nordrhein-westfalen", "rheinland-pfalz", "saarland", // "mecklenburg-vorpommern", "niedersachsen", "nordrhein-westfalen", "rheinland-pfalz", "saarland",
"sachsen-anhalt", "sachsen", "schleswig-holstein", "thueringen", // "sachsen-anhalt", "sachsen", "schleswig-holstein", "thueringen",
}; };
protected static final String SITE_TO_DOWNLOAD2 = "http://downloads.cloudmade.com/"; //$NON-NLS-1$ protected static final String SITE_TO_DOWNLOAD2 = "http://downloads.cloudmade.com/"; //$NON-NLS-1$
// us states // us states
// TODO address // Address (out of memory) : California ? , Florida ?, Georgia ?
protected static final String[] usStates = new String[] { protected static final String[] usStates = new String[] {
// "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut", // "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut",
// "Delaware", "District_of_Columbia", "Florida", "Georgia", "Guantanamo_Bay", "Hawaii", // "Delaware", "District_of_Columbia", "Florida", "Georgia", "Guantanamo_Bay", "Hawaii",
@ -255,7 +252,7 @@ public class IndexBatchCreator {
uploadIndex(new File(indexDirFiles, fName), alreadyUploadedFiles); uploadIndex(new File(indexDirFiles, fName), alreadyUploadedFiles);
} }
} catch (Exception e) { } catch (Exception e) {
log.error("Exception generating indexes for " + f.getName()); //$NON-NLS-1$ log.error("Exception generating indexes for " + f.getName(), e); //$NON-NLS-1$
} }
} catch (OutOfMemoryError e) { } catch (OutOfMemoryError e) {
System.gc(); System.gc();
@ -323,7 +320,7 @@ public class IndexBatchCreator {
is.close(); is.close();
zout.close(); zout.close();
} catch (IOException e) { } catch (IOException e) {
log.error("Exception while zipping file"); log.error("Exception while zipping file", e);
} }
if(f.delete()){ if(f.delete()){
log.info("Source odb file was deleted"); log.info("Source odb file was deleted");

View file

@ -5,5 +5,6 @@
<classpathentry kind="src" path="gen"/> <classpathentry kind="src" path="gen"/>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/> <classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry kind="lib" path="lib/bzip2-20090327.jar"/> <classpathentry kind="lib" path="lib/bzip2-20090327.jar"/>
<classpathentry kind="lib" path="lib/tuprolog.jar"/>
<classpathentry kind="output" path="bin"/> <classpathentry kind="output" path="bin"/>
</classpath> </classpath>

BIN
OsmAnd/lib/tuprolog.jar Normal file

Binary file not shown.

View file

@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="stop_routing">Stop routing</string> <string name="voice_not_use">Не использовать</string>
<string name="voice_provider_descr">Выберите голос для маршрутизации</string>
<string name="voice_provider">Голосовые данные</string>
<string name="voice_data_initializing">Инициализируются голосовые данные...</string>
<string name="voice_data_not_supported">Голосовые данные не поддерживаются текущей версией приложения</string>
<string name="voice_data_corrupted">Выбранные голосовые данные не правильного формата</string>
<string name="voice_data_unavailable">Выбранные голосовые данные не доступны</string>
<string name="stop_routing">Отменить маршрут</string>
<string name="sd_unmounted">Карточка SD недоступна. \nВы не сможете работать с картой.</string> <string name="sd_unmounted">Карточка SD недоступна. \nВы не сможете работать с картой.</string>
<string name="sd_mounted_ro">Карточка SD доступна только для чтения. \nВы не сможете загружать карты из интернета.</string> <string name="sd_mounted_ro">Карточка SD доступна только для чтения. \nВы не сможете загружать карты из интернета.</string>
<string name="unzipping_file">Файл распаковывается</string> <string name="unzipping_file">Файл распаковывается</string>

View file

@ -1,6 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<string name="stop_routing">Отменить маршрут</string> <string name="voice_not_use">Not use</string>
<string name="voice_provider_descr">Choose voice data for routing</string>
<string name="voice_provider">Voice data</string>
<string name="voice_data_initializing">Initializing voice data...</string>
<string name="voice_data_not_supported">Voice data has different version that application supports</string>
<string name="voice_data_corrupted">Specified voice data is corrupted</string>
<string name="voice_data_unavailable">Current voice data is not available</string>
<string name="stop_routing">Stop routing</string>
<string name="sd_unmounted">SD card is not accessible. \nYou can\'t see map and find anything.</string> <string name="sd_unmounted">SD card is not accessible. \nYou can\'t see map and find anything.</string>
<string name="sd_mounted_ro">SD card is read-only accessible. \nYou can see only preloaded map and can\'t download from internet.</string> <string name="sd_mounted_ro">SD card is read-only accessible. \nYou can see only preloaded map and can\'t download from internet.</string>
<string name="unzipping_file">File is unzipping</string> <string name="unzipping_file">File is unzipping</string>

View file

@ -22,6 +22,7 @@
<Preference android:title="@string/reload_indexes" android:key="reload_indexes" android:summary="@string/reload_indexes_descr"></Preference> <Preference android:title="@string/reload_indexes" android:key="reload_indexes" android:summary="@string/reload_indexes_descr"></Preference>
<Preference android:title="@string/download_indexes" android:key="download_indexes" android:summary="@string/download_indexes_descr"></Preference> <Preference android:title="@string/download_indexes" android:key="download_indexes" android:summary="@string/download_indexes_descr"></Preference>
<ListPreference android:title="@string/router_service" android:key="router_service" android:summary="@string/router_service_descr"></ListPreference> <ListPreference android:title="@string/router_service" android:key="router_service" android:summary="@string/router_service_descr"></ListPreference>
<ListPreference android:title="@string/voice_provider" android:key="voice_provider" android:summary="@string/voice_provider_descr"></ListPreference>
</PreferenceScreen> </PreferenceScreen>
<PreferenceScreen android:title="@string/monitor_preferences" android:summary="@string/monitor_preferences_descr"> <PreferenceScreen android:title="@string/monitor_preferences" android:summary="@string/monitor_preferences_descr">

View file

@ -495,4 +495,28 @@ public class OsmandSettings {
} }
return new PoiFilter(null); return new PoiFilter(null);
} }
// this value string is synchronized with settings_pref.xml preference name
public static final String VOICE_PROVIDER = "voice_provider"; //$NON-NLS-1$
public static String getVoiceProvider(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.getString(VOICE_PROVIDER, null);
}
public static final String VOICE_MUTE = "voice_mute"; //$NON-NLS-1$
public static final boolean VOICE_MUTE_DEF = false;
public static boolean isVoiceMute(Context ctx){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.getBoolean(VOICE_MUTE, VOICE_MUTE_DEF);
}
public static boolean setVoiceMute(Context ctx, boolean mute){
SharedPreferences prefs = ctx.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
return prefs.edit().putBoolean(VOICE_MUTE, mute).commit();
}
} }

View file

@ -32,6 +32,7 @@ import com.osmand.ProgressDialogImplementation;
import com.osmand.R; import com.osmand.R;
import com.osmand.ResourceManager; import com.osmand.ResourceManager;
import com.osmand.activities.search.SearchActivity; import com.osmand.activities.search.SearchActivity;
import com.osmand.voice.CommandPlayer;
public class MainMenuActivity extends Activity { public class MainMenuActivity extends Activity {
@ -57,7 +58,14 @@ public class MainMenuActivity extends Activity {
@Override @Override
public void run() { public void run() {
try { try {
// initializing voice prolog subsystem
List<String> warnings = ResourceManager.getResourceManager().reloadIndexes(impl); List<String> warnings = ResourceManager.getResourceManager().reloadIndexes(impl);
impl.startTask(getString(R.string.voice_data_initializing), -1);
String w = CommandPlayer.init(MainMenuActivity.this);
if(w != null){
warnings.add(w);
}
SavingTrackHelper helper = new SavingTrackHelper(MainMenuActivity.this); SavingTrackHelper helper = new SavingTrackHelper(MainMenuActivity.this);
if (helper.hasDataToSave()) { if (helper.hasDataToSave()) {
impl.startTask(getString(R.string.saving_gpx_tracks), -1); impl.startTask(getString(R.string.saving_gpx_tracks), -1);
@ -100,9 +108,6 @@ public class MainMenuActivity extends Activity {
requestWindowFeature(Window.FEATURE_NO_TITLE); requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.menu); setContentView(R.layout.menu);
showMap = (Button) findViewById(R.id.MapButton); showMap = (Button) findViewById(R.id.MapButton);
showMap.setOnClickListener(new OnClickListener() { showMap.setOnClickListener(new OnClickListener() {
@ -110,7 +115,6 @@ public class MainMenuActivity extends Activity {
public void onClick(View v) { public void onClick(View v) {
final Intent mapIndent = new Intent(MainMenuActivity.this, MapActivity.class); final Intent mapIndent = new Intent(MainMenuActivity.this, MapActivity.class);
startActivityForResult(mapIndent, 0); startActivityForResult(mapIndent, 0);
} }
}); });
settingsButton = (Button) findViewById(R.id.SettingsButton); settingsButton = (Button) findViewById(R.id.SettingsButton);

View file

@ -1,6 +1,9 @@
package com.osmand.activities; package com.osmand.activities;
import java.io.File;
import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context; import android.content.Context;
@ -9,6 +12,7 @@ import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor; import android.content.SharedPreferences.Editor;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Environment;
import android.os.Bundle; import android.os.Bundle;
import android.preference.CheckBoxPreference; import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference; import android.preference.EditTextPreference;
@ -29,6 +33,7 @@ import com.osmand.OsmandSettings.ApplicationMode;
import com.osmand.activities.RouteProvider.RouteService; import com.osmand.activities.RouteProvider.RouteService;
import com.osmand.map.TileSourceManager; import com.osmand.map.TileSourceManager;
import com.osmand.map.TileSourceManager.TileSourceTemplate; import com.osmand.map.TileSourceManager.TileSourceTemplate;
import com.osmand.voice.CommandPlayer;
public class SettingsActivity extends PreferenceActivity implements OnPreferenceChangeListener, OnPreferenceClickListener { public class SettingsActivity extends PreferenceActivity implements OnPreferenceChangeListener, OnPreferenceClickListener {
@ -72,7 +77,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
private ListPreference routerPreference; private ListPreference routerPreference;
private ListPreference maxLevelToDownload; private ListPreference maxLevelToDownload;
private ListPreference mapScreenOrientation; private ListPreference mapScreenOrientation;
private ListPreference voicePreference;
private BooleanPreference[] booleanPreferences = new BooleanPreference[]{ private BooleanPreference[] booleanPreferences = new BooleanPreference[]{
@ -87,6 +92,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
new BooleanPreference(OsmandSettings.SAVE_TRACK_TO_GPX, OsmandSettings.SAVE_TRACK_TO_GPX_DEF), new BooleanPreference(OsmandSettings.SAVE_TRACK_TO_GPX, OsmandSettings.SAVE_TRACK_TO_GPX_DEF),
}; };
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
@ -127,6 +133,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
tileSourcePreference.setOnPreferenceChangeListener(this); tileSourcePreference.setOnPreferenceChangeListener(this);
routerPreference =(ListPreference) screen.findPreference(OsmandSettings.ROUTER_SERVICE); routerPreference =(ListPreference) screen.findPreference(OsmandSettings.ROUTER_SERVICE);
routerPreference.setOnPreferenceChangeListener(this); routerPreference.setOnPreferenceChangeListener(this);
voicePreference =(ListPreference) screen.findPreference(OsmandSettings.VOICE_PROVIDER);
voicePreference.setOnPreferenceChangeListener(this);
} }
@ -194,6 +202,31 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
routerPreference.setEntries(entries); routerPreference.setEntries(entries);
routerPreference.setEntryValues(entries); routerPreference.setEntryValues(entries);
routerPreference.setValue(entry); routerPreference.setValue(entry);
// read available voice data
File extStorage = new File(Environment.getExternalStorageDirectory(), CommandPlayer.VOICE_DIR);
Set<String> setFiles = new LinkedHashSet<String>();
if (extStorage.exists()) {
for (File f : extStorage.listFiles()) {
if (f.isDirectory()) {
setFiles.add(f.getName());
}
}
}
String provider = OsmandSettings.getVoiceProvider(this);
entries = new String[setFiles.size() + 1];
int k = 0;
entries[k++] = getString(R.string.voice_not_use);
for(String s : setFiles){
entries[k++] = s;
}
voicePreference.setEntries(entries);
voicePreference.setEntryValues(entries);
if(setFiles.contains(provider)){
voicePreference.setValue(provider);
} else {
voicePreference.setValueIndex(0);
}
int startZoom = 12; int startZoom = 12;
int endZoom = 19; int endZoom = 19;
@ -280,6 +313,15 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
edit.putInt(OsmandSettings.ROUTER_SERVICE, s.ordinal()); edit.putInt(OsmandSettings.ROUTER_SERVICE, s.ordinal());
} }
edit.commit(); edit.commit();
} else if (preference == voicePreference) {
int i = voicePreference.findIndexOfValue((String) newValue);
if(i==0){
edit.putString(OsmandSettings.VOICE_PROVIDER, null);
} else {
edit.putString(OsmandSettings.VOICE_PROVIDER, (String) newValue);
}
edit.commit();
CommandPlayer.init(this);
} else if (preference == tileSourcePreference) { } else if (preference == tileSourcePreference) {
edit.putString(OsmandSettings.MAP_TILE_SOURCES, (String) newValue); edit.putString(OsmandSettings.MAP_TILE_SOURCES, (String) newValue);
edit.commit(); edit.commit();

View file

@ -34,6 +34,7 @@ import com.osmand.activities.RoutingHelper.RouteDirectionInfo;
import com.osmand.activities.RoutingHelper.TurnType; import com.osmand.activities.RoutingHelper.TurnType;
import com.osmand.osm.MapUtils; import com.osmand.osm.MapUtils;
import com.osmand.views.MapInfoLayer; import com.osmand.views.MapInfoLayer;
import com.osmand.voice.CommandPlayer;
/** /**
* *
@ -62,6 +63,11 @@ public class ShowRouteInfoActivity extends ListActivity {
RouteDirectionInfo item = ((RouteInfoAdapter)getListAdapter()).getItem(position - 1); RouteDirectionInfo item = ((RouteInfoAdapter)getListAdapter()).getItem(position - 1);
RoutingHelper inst = RoutingHelper.getInstance(this); RoutingHelper inst = RoutingHelper.getInstance(this);
Location loc = inst.getLocationFromRouteDirection(item); Location loc = inst.getLocationFromRouteDirection(item);
CommandPlayer player = CommandPlayer.getInstance(this);
if(player != null){
// TODO temp solution
player.newCommandBuilder().prepareTurnLeft(300).play();
}
if(loc != null){ if(loc != null){
OsmandSettings.setMapLocationToShow(this, loc.getLatitude(),loc.getLongitude()); OsmandSettings.setMapLocationToShow(this, loc.getLatitude(),loc.getLongitude());
startActivity(new Intent(this, MapActivity.class)); startActivity(new Intent(this, MapActivity.class));

View file

@ -190,60 +190,59 @@ public class OsmBugsLayer implements OsmandMapLayer {
@Override @Override
public boolean onLongPressEvent(PointF point) { public boolean onLongPressEvent(PointF point) {
if (objects != null && !objects.isEmpty()) { final OpenStreetBug bug = getBugFromPoint(point);
if(bug != null){
Builder builder = new AlertDialog.Builder(view.getContext());
Resources resources = view.getContext().getResources();
builder.setItems(new String[]{
resources.getString(R.string.osb_comment_menu_item),
resources.getString(R.string.osb_close_menu_item)
}, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 0){
commentBug(view.getContext(), activity.getLayoutInflater(), bug);
} else if(which == 1){
closeBug(view.getContext(), activity.getLayoutInflater(), bug);
}
}
});
builder.create().show();
return true;
}
return false;
}
public OpenStreetBug getBugFromPoint(PointF point){
OpenStreetBug result = null;
if (objects != null) {
int ex = (int) point.x; int ex = (int) point.x;
int ey = (int) point.y; int ey = (int) point.y;
int radius = getRadiusBug(view.getZoom()) * 3 / 2; int radius = getRadiusBug(view.getZoom()) * 3 / 2;
try { try {
for (final OpenStreetBug n : objects) { for (int i = 0; i < objects.size(); i++) {
OpenStreetBug n = objects.get(i);
int x = view.getRotatedMapXForPoint(n.getLatitude(), n.getLongitude()); int x = view.getRotatedMapXForPoint(n.getLatitude(), n.getLongitude());
int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude()); int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude());
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) { if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
Builder builder = new AlertDialog.Builder(view.getContext()); radius = Math.max(Math.abs(x - ex), Math.abs(y - ey));
Resources resources = view.getContext().getResources(); result = n;
builder.setItems(new String[]{
resources.getString(R.string.osb_comment_menu_item),
resources.getString(R.string.osb_close_menu_item)
}, new DialogInterface.OnClickListener(){
@Override
public void onClick(DialogInterface dialog, int which) {
if(which == 0){
commentBug(view.getContext(), activity.getLayoutInflater(), n);
} else if(which == 1){
closeBug(view.getContext(), activity.getLayoutInflater(), n);
}
}
});
builder.create().show();
return true;
} }
} }
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
// that's really rare case, but is much efficient than introduce synchronized block // that's really rare case, but is much efficient than introduce synchronized block
} }
} }
return false; return result;
} }
@Override @Override
public boolean onTouchEvent(PointF point) { public boolean onTouchEvent(PointF point) {
if (objects != null && !objects.isEmpty()) { OpenStreetBug bug = getBugFromPoint(point);
int ex = (int) point.x; if(bug != null){
int ey = (int) point.y; String format = "Bug : " + bug.getName(); //$NON-NLS-1$
int radius = getRadiusBug(view.getZoom()) * 3 / 2; Toast.makeText(view.getContext(), format, Toast.LENGTH_LONG).show();
try { return true;
for (OpenStreetBug n : objects) {
int x = view.getRotatedMapXForPoint(n.getLatitude(), n.getLongitude());
int y = view.getRotatedMapYForPoint(n.getLatitude(), n.getLongitude());
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
String format = "Bug : " + n.getName(); //$NON-NLS-1$
Toast.makeText(view.getContext(), format, Toast.LENGTH_LONG).show();
return true;
}
}
} catch (IndexOutOfBoundsException e) {
// that's really rare case, but is much efficient than introduce synchronized block
}
} }
return false; return false;
} }

View file

@ -694,7 +694,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
@Override @Override
public boolean onDown(MotionEvent e) { public boolean onDown(MotionEvent e) {
animatedDraggingThread.stopAnimating(); // enable double tap animation
// animatedDraggingThread.stopAnimating();
return false; return false;
} }
@ -792,8 +793,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
@Override @Override
public boolean onDoubleTap(MotionEvent e) { public boolean onDoubleTap(MotionEvent e) {
LatLon l = getLatLonFromScreenPoint(e.getX(), e.getY()); LatLon l = getLatLonFromScreenPoint(e.getX(), e.getY());
setLatLon(l.getLatitude(), l.getLongitude()); getAnimatedDraggingThread().startMoving(getLatitude(), getLongitude(),
setZoom(zoom + 1); l.getLatitude(), l.getLongitude(), getZoom(), getZoom() + 1, getSourceTileSize(), getRotate(), true);
return true; return true;
} }

View file

@ -74,6 +74,7 @@ public class POIMapLayer implements OsmandMapLayer {
} }
public Amenity getAmenityFromPoint(PointF point){ public Amenity getAmenityFromPoint(PointF point){
Amenity result = null;
if (objects != null) { if (objects != null) {
int ex = (int) point.x; int ex = (int) point.x;
int ey = (int) point.y; int ey = (int) point.y;
@ -84,14 +85,15 @@ public class POIMapLayer implements OsmandMapLayer {
int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude()); int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude()); int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) { if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
return n; radius = Math.max(Math.abs(x - ex), Math.abs(y - ey));
result = n;
} }
} }
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
// that's really rare case, but is much efficient than introduce synchronized block // that's really rare case, but is much efficient than introduce synchronized block
} }
} }
return null; return result;
} }

View file

@ -44,6 +44,7 @@ public class TransportStopsLayer implements OsmandMapLayer {
} }
public TransportStop getFromPoint(PointF point){ public TransportStop getFromPoint(PointF point){
TransportStop result = null;
if (objects != null) { if (objects != null) {
int ex = (int) point.x; int ex = (int) point.x;
int ey = (int) point.y; int ey = (int) point.y;
@ -54,14 +55,15 @@ public class TransportStopsLayer implements OsmandMapLayer {
int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude()); int x = view.getRotatedMapXForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude()); int y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) { if (Math.abs(x - ex) <= radius && Math.abs(y - ey) <= radius) {
return n; radius = Math.max(Math.abs(x - ex), Math.abs(y - ey));
result = n;
} }
} }
} catch (IndexOutOfBoundsException e) { } catch (IndexOutOfBoundsException e) {
// that's really rare case, but is much efficient than introduce synchronized block // that's really rare case, but is much efficient than introduce synchronized block
} }
} }
return null; return result;
} }

View file

@ -0,0 +1,312 @@
package com.osmand.voice;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
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;
import android.media.MediaPlayer;
import android.os.Environment;
import com.osmand.Algoritms;
import com.osmand.LogUtil;
import com.osmand.OsmandSettings;
import com.osmand.R;
import com.osmand.ResourceManager;
public class CommandPlayer {
public static final String VOICE_DIR = ResourceManager.APP_DIR + "/voice"; //$NON-NLS-1$
public static final int VOICE_VERSION = 0;
private static final Log log = LogUtil.getLog(CommandPlayer.class);
private static CommandPlayer instance = null;
protected Context ctx;
private File voiceDir;
// resolving commands to play
private Prolog prologSystem;
// playing media
private MediaPlayer mediaPlayer;
private List<String> filesToPlay = new ArrayList<String>();
/**
* @param ctx
* @return null could be returned it means there is no available voice config
*/
public static CommandPlayer getInstance(Context ctx) {
init(ctx);
return instance;
}
public static String init(Context ctx){
if(OsmandSettings.getVoiceProvider(ctx) == null && instance == null){
return null;
}
if(instance == null){
long time = System.currentTimeMillis();
instance = new CommandPlayer(ctx);
if (log.isInfoEnabled()) {
log.info("Initializing prolog system : " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
}
}
instance.ctx = ctx;
if(!Algoritms.objectEquals(OsmandSettings.getVoiceProvider(ctx), instance.getCurrentVoice())){
return instance.init();
}
return null;
}
protected CommandPlayer(Context ctx){
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();
}
public String getCurrentVoice(){
if(voiceDir == null){
return null;
}
return voiceDir.getName();
}
protected String init(){
String voiceProvider = OsmandSettings.getVoiceProvider(ctx);
prologSystem.clearTheory();
voiceDir = null;
if(voiceProvider != null){
File parent = new File(Environment.getExternalStorageDirectory(), VOICE_DIR);
voiceDir = new File(parent, voiceProvider);
if(!voiceDir.exists()){
voiceDir = null;
return ctx.getString(R.string.voice_data_unavailable);
}
}
if(voiceDir != null) {
long time = System.currentTimeMillis();
File config = new File(voiceDir, "_config.p"); //$NON-NLS-1$
boolean wrong = !config.exists();
if (!wrong) {
try {
prologSystem.setTheory(new Theory(new FileInputStream(config)));
} catch (InvalidTheoryException e) {
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
} catch (IOException e) {
log.error("Loading voice config exception " + voiceProvider, e); //$NON-NLS-1$
}
}
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() == 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 static final String P_VERSION = "version"; //$NON-NLS-1$
protected static final String P_RESOLVE = "resolve"; //$NON-NLS-1$
protected static final String С_PREPARE_TURN_LEFT = "prepare_turn_left"; //$NON-NLS-1$
protected static final String С_PREPARE_TURN_RIGHT = "prepare_turn_right"; //$NON-NLS-1$
protected static final String С_PREAMBLE = "preamble"; //$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(С_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);
listStruct.add(struct);
return this;
}
public CommandBuilder prepareTurnLeft(double dist){
return addCommand(С_PREPARE_TURN_LEFT, dist);
}
public CommandBuilder prepareTurnRight(double dist){
return addCommand(С_PREPARE_TURN_LEFT, dist);
}
public void play(){
CommandPlayer.this.playCommands(this);
}
protected List<String> execute(){
alreadyExecuted = true;
return CommandPlayer.this.execute(listStruct);
}
}
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 void playQueue() {
boolean playNext = true;
while (!filesToPlay.isEmpty() && playNext) {
String f = filesToPlay.remove(0);
if (f != null && voiceDir != null) {
File file = new File(voiceDir, f);
if (file.exists()) {
try {
mediaPlayer.setDataSource(file.getAbsolutePath());
mediaPlayer.prepare();
mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer mp) {
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) {
}
playQueue();
}
});
playNext = false;
mediaPlayer.start();
} catch (Exception e) {
log.error("Error while playing voice command", e); //$NON-NLS-1$
playNext = true;
}
}
}
}
}
}