add voice engine
git-svn-id: https://osmand.googlecode.com/svn/trunk@320 e29c36b1-1cfa-d876-8d93-3434fc2bb7b8
This commit is contained in:
parent
d5692b938e
commit
7ed1ce9e4b
16 changed files with 475 additions and 68 deletions
|
@ -20,9 +20,11 @@ public class ToDoConstants {
|
|||
// 68. Implement service to app work with screen offline
|
||||
// (introduce special settings how often update location to monitoring & audio guidance)
|
||||
// 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
|
||||
// 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.
|
||||
// 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).
|
||||
|
@ -31,7 +33,7 @@ public class ToDoConstants {
|
|||
// Unscheduled (complex)
|
||||
// 66. Transport routing (show next stop, total distance, show stop get out) (?).
|
||||
// 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) (?)
|
||||
// 63. Support simple offline routing(require new index file) (?)
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@ import com.osmand.impl.ConsoleProgressImplementation;
|
|||
public class IndexBatchCreator {
|
||||
// config params
|
||||
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 writeWayNodes = true;
|
||||
|
||||
|
@ -52,30 +52,27 @@ public class IndexBatchCreator {
|
|||
// "czech_republic", "netherlands", // 168, 375,
|
||||
// "great_britain", "italy", // 281, 246,
|
||||
// ADD TO TOTAL : 2449 MB
|
||||
// TODO transport, poi : "czech_republic", "netherlands", "great_britain", "italy"
|
||||
// address : "great_britain", "italy" - out of memory
|
||||
// TODO "great_britain", "italy" (address out of memory, poi, transport) + netherlands
|
||||
|
||||
};
|
||||
|
||||
// TODO all
|
||||
protected static final String[] franceProvinces = new String[] {
|
||||
"alsace","aquitaine", "auvergne", "basse-normandie", "bourgogne", "bretagne", "centre",
|
||||
"champagne-ardenne", "corse", "franche-comte", "haute-normandie", "ile-de-france",
|
||||
"languedoc-roussillon", "limousin", "lorraine", "midi-pyrenees", "nord-pas-de-calais",
|
||||
"pays-de-la-loire", "picardie","poitou-charentes", "provence-alpes-cote-d-azur", "rhone-alpes"
|
||||
// "alsace","aquitaine", "auvergne", "basse-normandie", "bourgogne", "bretagne", "centre",
|
||||
// "champagne-ardenne", "corse", "franche-comte", "haute-normandie", "ile-de-france",
|
||||
// "languedoc-roussillon", "limousin", "lorraine", "midi-pyrenees", "nord-pas-de-calais",
|
||||
// "pays-de-la-loire", "picardie","poitou-charentes", "provence-alpes-cote-d-azur", "rhone-alpes"
|
||||
};
|
||||
|
||||
// TODO all
|
||||
protected static final String[] germanyLands = new String[] {
|
||||
"baden-wuerttemberg","bayern", "berlin", "brandenburg", "bremen", "hamburg", "hessen",
|
||||
"mecklenburg-vorpommern", "niedersachsen", "nordrhein-westfalen", "rheinland-pfalz", "saarland",
|
||||
"sachsen-anhalt", "sachsen", "schleswig-holstein", "thueringen",
|
||||
// "baden-wuerttemberg","bayern", "berlin", "brandenburg", "bremen", "hamburg", "hessen",
|
||||
// "mecklenburg-vorpommern", "niedersachsen", "nordrhein-westfalen", "rheinland-pfalz", "saarland",
|
||||
// "sachsen-anhalt", "sachsen", "schleswig-holstein", "thueringen",
|
||||
};
|
||||
|
||||
|
||||
protected static final String SITE_TO_DOWNLOAD2 = "http://downloads.cloudmade.com/"; //$NON-NLS-1$
|
||||
// us states
|
||||
// TODO address
|
||||
// Address (out of memory) : California ? , Florida ?, Georgia ?
|
||||
protected static final String[] usStates = new String[] {
|
||||
// "Alabama", "Alaska", "Arizona", "Arkansas", "California", "Colorado", "Connecticut",
|
||||
// "Delaware", "District_of_Columbia", "Florida", "Georgia", "Guantanamo_Bay", "Hawaii",
|
||||
|
@ -255,7 +252,7 @@ public class IndexBatchCreator {
|
|||
uploadIndex(new File(indexDirFiles, fName), alreadyUploadedFiles);
|
||||
}
|
||||
} 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) {
|
||||
System.gc();
|
||||
|
@ -323,7 +320,7 @@ public class IndexBatchCreator {
|
|||
is.close();
|
||||
zout.close();
|
||||
} catch (IOException e) {
|
||||
log.error("Exception while zipping file");
|
||||
log.error("Exception while zipping file", e);
|
||||
}
|
||||
if(f.delete()){
|
||||
log.info("Source odb file was deleted");
|
||||
|
|
|
@ -5,5 +5,6 @@
|
|||
<classpathentry kind="src" path="gen"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="lib" path="lib/bzip2-20090327.jar"/>
|
||||
<classpathentry kind="lib" path="lib/tuprolog.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
BIN
OsmAnd/lib/tuprolog.jar
Normal file
BIN
OsmAnd/lib/tuprolog.jar
Normal file
Binary file not shown.
|
@ -1,6 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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_mounted_ro">Карточка SD доступна только для чтения. \nВы не сможете загружать карты из интернета.</string>
|
||||
<string name="unzipping_file">Файл распаковывается</string>
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<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_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>
|
||||
|
|
|
@ -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/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/voice_provider" android:key="voice_provider" android:summary="@string/voice_provider_descr"></ListPreference>
|
||||
</PreferenceScreen>
|
||||
|
||||
<PreferenceScreen android:title="@string/monitor_preferences" android:summary="@string/monitor_preferences_descr">
|
||||
|
|
|
@ -495,4 +495,28 @@ public class OsmandSettings {
|
|||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.osmand.ProgressDialogImplementation;
|
|||
import com.osmand.R;
|
||||
import com.osmand.ResourceManager;
|
||||
import com.osmand.activities.search.SearchActivity;
|
||||
import com.osmand.voice.CommandPlayer;
|
||||
|
||||
public class MainMenuActivity extends Activity {
|
||||
|
||||
|
@ -57,7 +58,14 @@ public class MainMenuActivity extends Activity {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// initializing voice prolog subsystem
|
||||
|
||||
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);
|
||||
if (helper.hasDataToSave()) {
|
||||
impl.startTask(getString(R.string.saving_gpx_tracks), -1);
|
||||
|
@ -101,16 +109,12 @@ public class MainMenuActivity extends Activity {
|
|||
requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
setContentView(R.layout.menu);
|
||||
|
||||
|
||||
|
||||
|
||||
showMap = (Button) findViewById(R.id.MapButton);
|
||||
showMap.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final Intent mapIndent = new Intent(MainMenuActivity.this, MapActivity.class);
|
||||
startActivityForResult(mapIndent, 0);
|
||||
|
||||
}
|
||||
});
|
||||
settingsButton = (Button) findViewById(R.id.SettingsButton);
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package com.osmand.activities;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
|
@ -9,6 +12,7 @@ import android.content.SharedPreferences;
|
|||
import android.content.SharedPreferences.Editor;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Environment;
|
||||
import android.os.Bundle;
|
||||
import android.preference.CheckBoxPreference;
|
||||
import android.preference.EditTextPreference;
|
||||
|
@ -29,6 +33,7 @@ import com.osmand.OsmandSettings.ApplicationMode;
|
|||
import com.osmand.activities.RouteProvider.RouteService;
|
||||
import com.osmand.map.TileSourceManager;
|
||||
import com.osmand.map.TileSourceManager.TileSourceTemplate;
|
||||
import com.osmand.voice.CommandPlayer;
|
||||
|
||||
public class SettingsActivity extends PreferenceActivity implements OnPreferenceChangeListener, OnPreferenceClickListener {
|
||||
|
||||
|
@ -72,7 +77,7 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
private ListPreference routerPreference;
|
||||
private ListPreference maxLevelToDownload;
|
||||
private ListPreference mapScreenOrientation;
|
||||
|
||||
private ListPreference voicePreference;
|
||||
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
@ -127,6 +133,8 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
tileSourcePreference.setOnPreferenceChangeListener(this);
|
||||
routerPreference =(ListPreference) screen.findPreference(OsmandSettings.ROUTER_SERVICE);
|
||||
routerPreference.setOnPreferenceChangeListener(this);
|
||||
voicePreference =(ListPreference) screen.findPreference(OsmandSettings.VOICE_PROVIDER);
|
||||
voicePreference.setOnPreferenceChangeListener(this);
|
||||
|
||||
}
|
||||
|
||||
|
@ -195,6 +203,31 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
routerPreference.setEntryValues(entries);
|
||||
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 endZoom = 19;
|
||||
entries = new String[endZoom - startZoom + 1];
|
||||
|
@ -280,6 +313,15 @@ public class SettingsActivity extends PreferenceActivity implements OnPreference
|
|||
edit.putInt(OsmandSettings.ROUTER_SERVICE, s.ordinal());
|
||||
}
|
||||
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) {
|
||||
edit.putString(OsmandSettings.MAP_TILE_SOURCES, (String) newValue);
|
||||
edit.commit();
|
||||
|
|
|
@ -34,6 +34,7 @@ import com.osmand.activities.RoutingHelper.RouteDirectionInfo;
|
|||
import com.osmand.activities.RoutingHelper.TurnType;
|
||||
import com.osmand.osm.MapUtils;
|
||||
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);
|
||||
RoutingHelper inst = RoutingHelper.getInstance(this);
|
||||
Location loc = inst.getLocationFromRouteDirection(item);
|
||||
CommandPlayer player = CommandPlayer.getInstance(this);
|
||||
if(player != null){
|
||||
// TODO temp solution
|
||||
player.newCommandBuilder().prepareTurnLeft(300).play();
|
||||
}
|
||||
if(loc != null){
|
||||
OsmandSettings.setMapLocationToShow(this, loc.getLatitude(),loc.getLongitude());
|
||||
startActivity(new Intent(this, MapActivity.class));
|
||||
|
|
|
@ -190,15 +190,8 @@ public class OsmBugsLayer implements OsmandMapLayer {
|
|||
|
||||
@Override
|
||||
public boolean onLongPressEvent(PointF point) {
|
||||
if (objects != null && !objects.isEmpty()) {
|
||||
int ex = (int) point.x;
|
||||
int ey = (int) point.y;
|
||||
int radius = getRadiusBug(view.getZoom()) * 3 / 2;
|
||||
try {
|
||||
for (final 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) {
|
||||
final OpenStreetBug bug = getBugFromPoint(point);
|
||||
if(bug != null){
|
||||
Builder builder = new AlertDialog.Builder(view.getContext());
|
||||
Resources resources = view.getContext().getResources();
|
||||
builder.setItems(new String[]{
|
||||
|
@ -208,43 +201,49 @@ public class OsmBugsLayer implements OsmandMapLayer {
|
|||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if(which == 0){
|
||||
commentBug(view.getContext(), activity.getLayoutInflater(), n);
|
||||
commentBug(view.getContext(), activity.getLayoutInflater(), bug);
|
||||
} else if(which == 1){
|
||||
closeBug(view.getContext(), activity.getLayoutInflater(), n);
|
||||
closeBug(view.getContext(), activity.getLayoutInflater(), bug);
|
||||
}
|
||||
}
|
||||
});
|
||||
builder.create().show();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// that's really rare case, but is much efficient than introduce synchronized block
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(PointF point) {
|
||||
if (objects != null && !objects.isEmpty()) {
|
||||
public OpenStreetBug getBugFromPoint(PointF point){
|
||||
OpenStreetBug result = null;
|
||||
if (objects != null) {
|
||||
int ex = (int) point.x;
|
||||
int ey = (int) point.y;
|
||||
int radius = getRadiusBug(view.getZoom()) * 3 / 2;
|
||||
try {
|
||||
for (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 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;
|
||||
radius = Math.max(Math.abs(x - ex), Math.abs(y - ey));
|
||||
result = n;
|
||||
}
|
||||
}
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
// that's really rare case, but is much efficient than introduce synchronized block
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onTouchEvent(PointF point) {
|
||||
OpenStreetBug bug = getBugFromPoint(point);
|
||||
if(bug != null){
|
||||
String format = "Bug : " + bug.getName(); //$NON-NLS-1$
|
||||
Toast.makeText(view.getContext(), format, Toast.LENGTH_LONG).show();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -694,7 +694,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
|
|||
|
||||
@Override
|
||||
public boolean onDown(MotionEvent e) {
|
||||
animatedDraggingThread.stopAnimating();
|
||||
// enable double tap animation
|
||||
// animatedDraggingThread.stopAnimating();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -792,8 +793,8 @@ public class OsmandMapTileView extends SurfaceView implements IMapDownloaderCall
|
|||
@Override
|
||||
public boolean onDoubleTap(MotionEvent e) {
|
||||
LatLon l = getLatLonFromScreenPoint(e.getX(), e.getY());
|
||||
setLatLon(l.getLatitude(), l.getLongitude());
|
||||
setZoom(zoom + 1);
|
||||
getAnimatedDraggingThread().startMoving(getLatitude(), getLongitude(),
|
||||
l.getLatitude(), l.getLongitude(), getZoom(), getZoom() + 1, getSourceTileSize(), getRotate(), true);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -74,6 +74,7 @@ public class POIMapLayer implements OsmandMapLayer {
|
|||
}
|
||||
|
||||
public Amenity getAmenityFromPoint(PointF point){
|
||||
Amenity result = null;
|
||||
if (objects != null) {
|
||||
int ex = (int) point.x;
|
||||
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 y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
|
||||
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) {
|
||||
// that's really rare case, but is much efficient than introduce synchronized block
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ public class TransportStopsLayer implements OsmandMapLayer {
|
|||
}
|
||||
|
||||
public TransportStop getFromPoint(PointF point){
|
||||
TransportStop result = null;
|
||||
if (objects != null) {
|
||||
int ex = (int) point.x;
|
||||
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 y = view.getRotatedMapYForPoint(n.getLocation().getLatitude(), n.getLocation().getLongitude());
|
||||
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) {
|
||||
// that's really rare case, but is much efficient than introduce synchronized block
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
|
312
OsmAnd/src/com/osmand/voice/CommandPlayer.java
Normal file
312
OsmAnd/src/com/osmand/voice/CommandPlayer.java
Normal 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;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in a new issue