From 21d176f161b90f18f236ef887cef9676d712eee3 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 21 Apr 2016 21:12:40 -0400 Subject: Update java library version numbers Prepare for 1.6.3 release. Signed-off-by: Keith Packard --- altoslib/AltosMapLoader.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'altoslib/AltosMapLoader.java') diff --git a/altoslib/AltosMapLoader.java b/altoslib/AltosMapLoader.java index 9ed93a42..9d4059e6 100644 --- a/altoslib/AltosMapLoader.java +++ b/altoslib/AltosMapLoader.java @@ -15,7 +15,7 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ -package org.altusmetrum.altoslib_9; +package org.altusmetrum.altoslib_10; import java.io.*; import java.util.*; -- cgit v1.2.3 From ec20e2f72460010c4f59e6d59775671260e01026 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 28 Apr 2016 12:29:16 -0700 Subject: altoslib: Make AltosPreferencesBackend abstract. Add set/put Serializable This lets us add functionality to this directly, such as the new serializable APIs. Signed-off-by: Keith Packard --- altosdroid/res/values/strings.xml | 2 +- .../org/altusmetrum/AltosDroid/AltosDroidLink.java | 6 +- .../AltosDroid/AltosDroidPreferencesBackend.java | 2 +- .../altusmetrum/AltosDroid/IgniterActivity.java | 106 ++++++++++++++------- .../AltosDroid/ManageFrequenciesActivity.java | 9 ++ altoslib/AltosFrequency.java | 6 +- altoslib/AltosLink.java | 4 +- altoslib/AltosMapLoader.java | 2 - altoslib/AltosPreferences.java | 98 +++++-------------- altoslib/AltosPreferencesBackend.java | 76 +++++++++++---- altosuilib/AltosUIPreferencesBackend.java | 2 +- 11 files changed, 176 insertions(+), 137 deletions(-) (limited to 'altoslib/AltosMapLoader.java') diff --git a/altosdroid/res/values/strings.xml b/altosdroid/res/values/strings.xml index 58057cac..4380d62d 100644 --- a/altosdroid/res/values/strings.xml +++ b/altosdroid/res/values/strings.xml @@ -116,7 +116,7 @@ Idle Mode Callsign - Connect + Monitor Disconnect Reboot Fire Igniters diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java index 2b10b11f..0fd9af75 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidLink.java @@ -170,8 +170,8 @@ public abstract class AltosDroidLink extends AltosLink { } buffer_off = 0; } - if (AltosDebug.D) - debug_input(in_buffer[buffer_off]); +// if (AltosDebug.D) +// debug_input(in_buffer[buffer_off]); return in_buffer[buffer_off++]; } @@ -207,7 +207,7 @@ public abstract class AltosDroidLink extends AltosLink { public void print(String data) { byte[] bytes = data.getBytes(); - AltosDebug.debug(data.replace('\n', '\\')); +// AltosDebug.debug(data.replace('\n', '\\')); for (byte b : bytes) putchar(b); } diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java index c2db3774..5c7ec513 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosDroidPreferencesBackend.java @@ -26,7 +26,7 @@ import android.util.*; import org.altusmetrum.altoslib_10.*; -public class AltosDroidPreferencesBackend implements AltosPreferencesBackend { +public class AltosDroidPreferencesBackend extends AltosPreferencesBackend { public final static String NAME = "org.altusmetrum.AltosDroid"; private Context context = null; private SharedPreferences prefs = null; diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java index 9e3dac67..931c3cfd 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/IgniterActivity.java @@ -43,7 +43,6 @@ class IgniterItem { public TextView status_view = null; private void update() { - AltosDebug.debug("update item %s %s", pretty, status); if (pretty_view != null) pretty_view.setText(pretty); if (status_view != null) @@ -77,7 +76,6 @@ class IgniterItem { } public IgniterItem() { - AltosDebug.debug("New igniter item"); } } @@ -102,9 +100,7 @@ class IgniterAdapter extends ArrayAdapter { item.realize(igniter_view, (TextView) igniter_view.findViewById(R.id.igniter_name), (TextView) igniter_view.findViewById(R.id.igniter_status)); - AltosDebug.debug("Realize new igniter view"); - } else - AltosDebug.debug("Reuse existing igniter view"); + } if (position == selected_item) item.igniter_view.setBackgroundColor(Color.RED); else @@ -123,11 +119,11 @@ public class IgniterActivity extends Activity { private IgniterAdapter igniters_adapter; private boolean is_bound; - private boolean timer_running; private Messenger service = null; private final Messenger messenger = new Messenger(new IncomingHandler(this)); - private Timer timer; + private Timer query_timer; + private boolean query_timer_running; private Timer arm_timer; private int arm_remaining; @@ -156,6 +152,7 @@ public class IgniterActivity extends Activity { private ServiceConnection connection = new ServiceConnection() { public void onServiceConnected(ComponentName className, IBinder binder) { service = new Messenger(binder); + query_timer_tick(); } public void onServiceDisconnected(ComponentName className) { @@ -205,12 +202,16 @@ public class IgniterActivity extends Activity { IgniterItem item = igniters_adapter.getItem(igniters_adapter.selected_item); FireThread ft = new FireThread(item.name); ft.run(); + arm.setChecked(false); } } private void arm_igniter(boolean is_checked) { if (is_checked) { + arm_timer_stop(); arm_timer = new Timer(); + arm_remaining = 10; + arm_set_text(); fire.setEnabled(true); arm_timer.scheduleAtFixedRate(new TimerTask() { public void run() { @@ -218,22 +219,37 @@ public class IgniterActivity extends Activity { }}, 1000L, 1000L); } else { - arm_timer.cancel(); + arm_timer_stop(); fire.setEnabled(false); } } - private synchronized void timer_tick() { - if (timer_running) + private synchronized void query_timer_tick() { + if (query_timer_running) return; - timer_running = true; - try { - Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY); - msg.replyTo = messenger; - service.send(msg); - } catch (RemoteException re) { - timer_running = false; - } + if (service == null) + return; + query_timer_running = true; + Thread thread = new Thread(new Runnable() { + public void run() { + try { + Message msg = Message.obtain(null, TelemetryService.MSG_IGNITER_QUERY); + msg.replyTo = messenger; + if (service == null) { + synchronized(IgniterActivity.this) { + query_timer_running = false; + } + } else + service.send(msg); + } catch (RemoteException re) { + AltosDebug.debug("igniter query thread failed"); + synchronized(IgniterActivity.this) { + query_timer_running = false; + } + } + } + }); + thread.start(); } private boolean set_igniter(HashMap status, String name, String pretty) { @@ -253,7 +269,7 @@ public class IgniterActivity extends Activity { } private synchronized void igniter_status(HashMap status) { - timer_running = false; + query_timer_running = false; if (status == null) { AltosDebug.debug("no igniter status"); return; @@ -266,24 +282,41 @@ public class IgniterActivity extends Activity { if (!set_igniter(status, name, pretty)) break; } -// if (igniters_adapter.selected_item >= 0) -// igniters_view.setSelection(selected_item); + } + + private synchronized void arm_timer_stop() { + if (arm_timer != null) { + arm_timer.cancel(); + arm_timer = null; + } + arm_remaining = 0; } private void arm_set_text() { String text = String.format("Armed %d", arm_remaining); + if (arm.isChecked()) + arm.setText(text); arm.setTextOn(text); } private void arm_timer_tick() { --arm_remaining; if (arm_remaining <= 0) { - timer.cancel(); - arm.setChecked(false); - fire.setEnabled(false); - } else - arm_set_text(); + arm_timer_stop(); + runOnUiThread(new Runnable() { + public void run() { + arm.setChecked(false); + fire.setEnabled(false); + } + }); + } else { + runOnUiThread(new Runnable() { + public void run() { + arm_set_text(); + } + }); + } } private void select_item(int position) { @@ -293,8 +326,6 @@ public class IgniterActivity extends Activity { if (position >= 0) { igniters_view.setItemChecked(position, true); arm.setEnabled(true); - arm_remaining = 10; - arm_set_text(); } else arm.setEnabled(false); igniters_adapter.selected_item = position; @@ -304,6 +335,7 @@ public class IgniterActivity extends Activity { private class IgniterItemClickListener implements ListView.OnItemClickListener { @Override public void onItemClick(AdapterView av, View v, int position, long id) { + AltosDebug.debug("select %d\n", position); select_item(position); } } @@ -325,6 +357,7 @@ public class IgniterActivity extends Activity { igniters_view.setOnItemClickListener(new IgniterItemClickListener()); fire = (Button) findViewById(R.id.igniter_fire); + fire.setEnabled(false); fire.setOnClickListener(new OnClickListener() { public void onClick(View v) { fire_igniter(); @@ -352,19 +385,24 @@ public class IgniterActivity extends Activity { @Override protected void onResume() { super.onResume(); - timer = new Timer(true); - timer.scheduleAtFixedRate(new TimerTask() { + query_timer = new Timer(true); + query_timer.scheduleAtFixedRate(new TimerTask() { public void run() { - timer_tick(); + query_timer_tick(); }}, - 1000L, 1000L); + 0L, 5000L); } @Override protected void onPause() { super.onPause(); - timer.cancel(); - timer = null; + if (query_timer != null) { + query_timer.cancel(); + query_timer = null; + } + arm_timer_stop(); + arm.setChecked(false); + fire.setEnabled(false); } @Override diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java index 172c44fe..401cdc9d 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/ManageFrequenciesActivity.java @@ -28,6 +28,7 @@ import android.graphics.*; import android.os.*; import android.view.*; import android.view.View.*; +import android.view.inputmethod.*; import android.widget.*; import android.widget.AdapterView.*; @@ -186,6 +187,13 @@ public class ManageFrequenciesActivity extends Activity { } } + private void hide_keyboard() { + InputMethodManager imm = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE); + View view = getCurrentFocus(); + if (view != null) + imm.hideSoftInputFromWindow(view.getWindowToken(), 0); + } + private void set() { String frequency_text = set_frequency.getEditableText().toString(); String description_text = set_description.getEditableText().toString(); @@ -199,6 +207,7 @@ public class ManageFrequenciesActivity extends Activity { changed = true; } catch (ParseException pe) { } + hide_keyboard(); } private void remove() { diff --git a/altoslib/AltosFrequency.java b/altoslib/AltosFrequency.java index 80e0d724..9542fe33 100644 --- a/altoslib/AltosFrequency.java +++ b/altoslib/AltosFrequency.java @@ -17,7 +17,11 @@ package org.altusmetrum.altoslib_10; -public class AltosFrequency { +import java.io.*; +import java.util.*; +import java.text.*; + +public class AltosFrequency implements Serializable { public double frequency; public String description; diff --git a/altoslib/AltosLink.java b/altoslib/AltosLink.java index 73bab3ef..cd8609c0 100644 --- a/altoslib/AltosLink.java +++ b/altoslib/AltosLink.java @@ -170,8 +170,8 @@ public abstract class AltosLink implements Runnable { boolean can_cancel = can_cancel_reply(); String reply = null; - if (!can_cancel && remote) - System.out.printf("Uh-oh, reading remote serial device from swing thread\n"); +// if (!can_cancel && remote) +// System.out.printf("Uh-oh, reading remote serial device from swing thread\n"); if (remote && can_cancel) { timeout = 500; diff --git a/altoslib/AltosMapLoader.java b/altoslib/AltosMapLoader.java index 9d4059e6..15fd756e 100644 --- a/altoslib/AltosMapLoader.java +++ b/altoslib/AltosMapLoader.java @@ -88,7 +88,6 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen for (int y = (int) upper_left.y; y <= lower_right.y; y += AltosMap.px_size) { for (int x = (int) upper_left.x; x <= lower_right.x; x += AltosMap.px_size) { - listener.debug("Make tile at %d, %d\n", x, y); AltosPointInt point = new AltosPointInt(x, y); AltosLatLon ul = transform.lat_lon(point); AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2)); @@ -174,7 +173,6 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen ++tiles_loaded_total; ++tiles_loaded_layer; - listener.debug("total %d layer %d\n", tiles_loaded_total, tiles_loaded_layer); if (tiles_loaded_layer == tiles_this_layer) { ++layers_loaded; diff --git a/altoslib/AltosPreferences.java b/altoslib/AltosPreferences.java index 4bf48f6d..cc340d03 100644 --- a/altoslib/AltosPreferences.java +++ b/altoslib/AltosPreferences.java @@ -116,6 +116,7 @@ public class AltosPreferences { public final static String frequency_count = "COUNT"; public final static String frequency_format = "FREQUENCY-%d"; public final static String description_format = "DESCRIPTION-%d"; + public final static String frequenciesPreference = "FREQUENCIES"; /* Units preference */ @@ -132,24 +133,29 @@ public class AltosPreferences { static int map_type; public static AltosFrequency[] load_common_frequencies() { + AltosFrequency[] frequencies = null; - boolean existing = false; - existing = backend.nodeExists(common_frequencies_node_name); - if (existing) { - AltosPreferencesBackend node = backend.node(common_frequencies_node_name); - int count = node.getInt(frequency_count, 0); + frequencies = (AltosFrequency[]) backend.getSerializable(frequenciesPreference, null); + + if (frequencies == null) { + if (backend.nodeExists(common_frequencies_node_name)) { + AltosPreferencesBackend node = backend.node(common_frequencies_node_name); + int count = node.getInt(frequency_count, 0); - frequencies = new AltosFrequency[count]; - for (int i = 0; i < count; i++) { - double frequency; - String description; + frequencies = new AltosFrequency[count]; + for (int i = 0; i < count; i++) { + double frequency; + String description; - frequency = node.getDouble(String.format(frequency_format, i), 0.0); - description = node.getString(String.format(description_format, i), null); - frequencies[i] = new AltosFrequency(frequency, description); + frequency = node.getDouble(String.format(frequency_format, i), 0.0); + description = node.getString(String.format(description_format, i), null); + frequencies[i] = new AltosFrequency(frequency, description); + } } - } else { + } + + if (frequencies == null) { frequencies = new AltosFrequency[10]; for (int i = 0; i < 10; i++) { frequencies[i] = new AltosFrequency(434.550 + i * .1, @@ -159,15 +165,6 @@ public class AltosPreferences { return frequencies; } - public static void save_common_frequencies(AltosFrequency[] frequencies) { - AltosPreferencesBackend node = backend.node(common_frequencies_node_name); - - node.putInt(frequency_count, frequencies.length); - for (int i = 0; i < frequencies.length; i++) { - node.putDouble(String.format(frequency_format, i), frequencies[i].frequency); - node.putString(String.format(description_format, i), frequencies[i].description); - } - } public static int launcher_serial; public static int launcher_channel; @@ -355,28 +352,10 @@ public class AltosPreferences { public static void set_state(int serial, AltosState state, AltosListenerState listener_state) { - backend.debug("set_state for %d pos %g,%g\n", - serial, - state.gps != null ? state.gps.lat : 0.0, - state.gps != null ? state.gps.lon : 0.0); - - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - - try { - ObjectOutputStream oos = new ObjectOutputStream(baos); - - AltosSavedState saved_state = new AltosSavedState(state, listener_state); - oos.writeObject(saved_state); - - byte[] bytes = baos.toByteArray(); - - synchronized(backend) { - backend.putBytes(String.format(statePreferenceFormat, serial), bytes); - backend.putInt(statePreferenceLatest, serial); - flush_preferences(); - } - } catch (IOException ie) { - backend.debug("set_state failed %s\n", ie.toString()); + synchronized(backend) { + backend.putSerializable(String.format(statePreferenceFormat, serial), + new AltosSavedState(state, listener_state)); + backend.putInt(statePreferenceLatest, serial); } } @@ -386,7 +365,6 @@ public class AltosPreferences { for (String key : keys) { if (key.startsWith(statePreferenceHead)) { - backend.debug("list_states %s\n", key); try { int serial = AltosParse.parse_int(key.substring(statePreferenceHead.length())); states.add(serial); @@ -412,35 +390,9 @@ public class AltosPreferences { } public static AltosSavedState state(int serial) { - byte[] bytes = null; - - backend.debug("get state %d\n", serial); - synchronized(backend) { - bytes = backend.getBytes(String.format(statePreferenceFormat, serial), null); - } - - if (bytes == null) { - backend.debug("no state for %d\n", serial); - return null; - } - - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - - try { - ObjectInputStream ois = new ObjectInputStream(bais); - AltosSavedState saved_state = (AltosSavedState) ois.readObject(); - backend.debug("got saved state for %d: %g,%g\n", - serial, - saved_state.state.gps != null ? saved_state.state.gps.lat : 0.0, - saved_state.state.gps != null ? saved_state.state.gps.lon : 0.0); - return saved_state; - } catch (IOException ie) { - backend.debug("IO exception %s\n", ie.toString()); - } catch (ClassNotFoundException ce) { - backend.debug("ClassNotFoundException %s\n", ce.toString()); + return (AltosSavedState) backend.getSerializable(String.format(statePreferenceFormat, serial), null); } - return null; } public static void set_scanning_telemetry(int new_scanning_telemetry) { @@ -556,7 +508,7 @@ public class AltosPreferences { public static void set_common_frequencies(AltosFrequency[] frequencies) { synchronized(backend) { common_frequencies = frequencies; - save_common_frequencies(frequencies); + backend.putSerializable(frequenciesPreference, frequencies); flush_preferences(); } } diff --git a/altoslib/AltosPreferencesBackend.java b/altoslib/AltosPreferencesBackend.java index 9f2e8f7c..6e1124e2 100644 --- a/altoslib/AltosPreferencesBackend.java +++ b/altoslib/AltosPreferencesBackend.java @@ -17,34 +17,72 @@ package org.altusmetrum.altoslib_10; -import java.io.File; +import java.io.*; +import java.util.*; +import java.text.*; -public interface AltosPreferencesBackend { +public abstract class AltosPreferencesBackend { - public String getString(String key, String def); - public void putString(String key, String value); + public abstract String getString(String key, String def); + public abstract void putString(String key, String value); - public int getInt(String key, int def); - public void putInt(String key, int value); + public abstract int getInt(String key, int def); + public abstract void putInt(String key, int value); - public double getDouble(String key, double def); - public void putDouble(String key, double value); + public abstract double getDouble(String key, double def); + public abstract void putDouble(String key, double value); - public boolean getBoolean(String key, boolean def); - public void putBoolean(String key, boolean value); + public abstract boolean getBoolean(String key, boolean def); + public abstract void putBoolean(String key, boolean value); - public byte[] getBytes(String key, byte[] def); - public void putBytes(String key, byte[] value); + public abstract byte[] getBytes(String key, byte[] def); + public abstract void putBytes(String key, byte[] value); - public boolean nodeExists(String key); - public AltosPreferencesBackend node(String key); + public Serializable getSerializable(String key, Serializable def) { + byte[] bytes = null; - public String[] keys(); - public void remove(String key); + bytes = getBytes(key, null); + if (bytes == null) + return def; - public void flush(); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - public File homeDirectory(); + try { + ObjectInputStream ois = new ObjectInputStream(bais); + Serializable object = (Serializable) ois.readObject(); + return object; + } catch (IOException ie) { + debug("IO exception %s\n", ie.toString()); + } catch (ClassNotFoundException ce) { + debug("ClassNotFoundException %s\n", ce.toString()); + } + return def; + } - public void debug(String format, Object ... arguments); + public void putSerializable(String key, Serializable object) { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + + try { + ObjectOutputStream oos = new ObjectOutputStream(baos); + + oos.writeObject(object); + byte[] bytes = baos.toByteArray(); + + putBytes(key, bytes); + } catch (IOException ie) { + debug("set_state failed %s\n", ie.toString()); + } + } + + public abstract boolean nodeExists(String key); + public abstract AltosPreferencesBackend node(String key); + + public abstract String[] keys(); + public abstract void remove(String key); + + public abstract void flush(); + + public abstract File homeDirectory(); + + public abstract void debug(String format, Object ... arguments); } diff --git a/altosuilib/AltosUIPreferencesBackend.java b/altosuilib/AltosUIPreferencesBackend.java index 9d3f15a2..d232edf7 100644 --- a/altosuilib/AltosUIPreferencesBackend.java +++ b/altosuilib/AltosUIPreferencesBackend.java @@ -22,7 +22,7 @@ import java.util.prefs.*; import org.altusmetrum.altoslib_10.*; import javax.swing.filechooser.FileSystemView; -public class AltosUIPreferencesBackend implements AltosPreferencesBackend { +public class AltosUIPreferencesBackend extends AltosPreferencesBackend { private Preferences _preferences = null; -- cgit v1.2.3 From e0081f7ba6fc9f1e4484d3e291fd30065ad5b620 Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 5 May 2016 02:25:52 -0700 Subject: altoslib: Fix map preloading callbacks, run in separate thread The map storage and tile callbacks were muddled together. Create clearly separate states for map data and have status updates be delivered when registering for new status events so that registration is sufficient to track the state without an explicit call to get the current state. Run the map tile creation in a separate thread so that even checking status of files on disk runs out of the UI thread. These fixes serve to make the pacifier update more smoothly, and also not over/under count tile loading so that the loading actually completes when all of the tiles are loaded. Signed-off-by: Keith Packard --- .../altusmetrum/AltosDroid/AltosMapOffline.java | 14 ++-- .../altusmetrum/AltosDroid/PreloadMapActivity.java | 13 ++-- altoslib/AltosMap.java | 8 +-- altoslib/AltosMapCache.java | 78 ++++++---------------- altoslib/AltosMapInterface.java | 2 +- altoslib/AltosMapLoader.java | 72 ++++++++++---------- altoslib/AltosMapStore.java | 47 ++++++------- altoslib/AltosMapTile.java | 64 +++++++++++------- altoslib/AltosMapTileListener.java | 2 - altosuilib/AltosUIMapNew.java | 18 +++-- altosuilib/AltosUIMapPreloadNew.java | 9 ++- 11 files changed, 146 insertions(+), 181 deletions(-) (limited to 'altoslib/AltosMapLoader.java') diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java index bde80cfc..ab142b17 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/AltosMapOffline.java @@ -133,7 +133,7 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal if (canvas.quickReject(pt.x, pt.y, pt.x + px_size, pt.y + px_size, Canvas.EdgeType.AA)) return; - AltosImage altos_image = cache.get(this, store, px_size, px_size); + AltosImage altos_image = this.get_image(); MapImage map_image = (MapImage) altos_image; @@ -150,8 +150,8 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal if (t.has_location()) { String message = null; switch (status) { - case AltosMapTile.loading: - message = "Loading..."; + case AltosMapTile.fetching: + message = "Fetching..."; break; case AltosMapTile.bad_request: message = "Internal error"; @@ -181,14 +181,14 @@ public class AltosMapOffline extends View implements ScaleGestureDetector.OnScal } } - public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { - super(listener, upper_left, center, zoom, maptype, px_size, 2); + public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { + super(cache, upper_left, center, zoom, maptype, px_size, 2); } } - public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { - return new MapTile(listener, upper_left, center, zoom, maptype, px_size); + public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { + return new MapTile(cache, upper_left, center, zoom, maptype, px_size); } public AltosMapPath new_path() { diff --git a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java index 87f03a92..13a44e1f 100644 --- a/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java +++ b/altosdroid/src/org/altusmetrum/AltosDroid/PreloadMapActivity.java @@ -107,7 +107,6 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe } AltosMap map; - AltosMapLoader loader; class PreloadMapImage implements AltosImage { public void flush() { @@ -137,14 +136,14 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe public void paint(AltosMapTransform t) { } - public PreloadMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { - super(listener, upper_left, center, zoom, maptype, px_size, 2); + public PreloadMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { + super(cache, upper_left, center, zoom, maptype, px_size, 2); } } - public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { - return new PreloadMapTile(listener, upper_left, center, zoom, maptype, px_size); + public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { + return new PreloadMapTile(cache, upper_left, center, zoom, maptype, px_size); } public int width() { @@ -265,7 +264,7 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe AltosDebug.debug("PreloadMap load %f %f %d %d %f %d\n", lat, lon, min, max, r, t); - loader.load(lat, lon, min, max, r, t); + new AltosMapLoader(map, this, lat, lon, min, max, r, t); } catch (ParseException e) { AltosDebug.debug("PreloadMap load raised exception %s", e.toString()); } @@ -398,8 +397,6 @@ public class PreloadMapActivity extends Activity implements AltosLaunchSiteListe map = new AltosMap(this); - loader = new AltosMapLoader(map, this); - // Listen for GPS and Network position updates LocationManager locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE); diff --git a/altoslib/AltosMap.java b/altoslib/AltosMap.java index 26851e96..1841277f 100644 --- a/altoslib/AltosMap.java +++ b/altoslib/AltosMap.java @@ -328,7 +328,8 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { if (!tiles.containsKey(point)) { AltosLatLon ul = transform.lat_lon(point); AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2)); - AltosMapTile tile = map_interface.new_tile(this, ul, center, zoom, maptype, px_size); + AltosMapTile tile = map_interface.new_tile(cache, ul, center, zoom, maptype, px_size); + tile.add_listener(this); tiles.put(point, tile); } } @@ -345,11 +346,6 @@ public class AltosMap implements AltosMapTileListener, AltosMapStoreListener { centre(lat, lon); tiles.clear(); make_tiles(); - for (AltosMapTile tile : tiles.values()) { - tile.add_store_listener(this); - if (tile.store_status() != AltosMapTile.loading) - listener.notify_tile(tile, tile.store_status()); - } repaint(); } diff --git a/altoslib/AltosMapCache.java b/altoslib/AltosMapCache.java index 17a36ff3..38e0f769 100644 --- a/altoslib/AltosMapCache.java +++ b/altoslib/AltosMapCache.java @@ -23,25 +23,20 @@ import java.net.*; public class AltosMapCache implements AltosMapCacheListener { /* An entry in the MapCache */ - class MapCacheElement implements AltosMapStoreListener { + class MapCacheElement implements AltosMapTileListener { AltosMapTile tile; /* Notify when image has been loaded */ AltosImage image; - AltosMapStore store; long used; class loader implements Runnable { public void run() { - if (image != null) - tile.notify_image(image); - try { - image = map_interface.load_image(store.file); - } catch (Exception ex) { + if (image == null) { + try { + image = map_interface.load_image(tile.store.file); + } catch (Exception ex) { + } } - if (image == null) - tile.set_status(AltosMapTile.failed); - else - tile.set_status(AltosMapTile.success); tile.notify_image(image); } } @@ -60,41 +55,21 @@ public class AltosMapCache implements AltosMapCacheListener { } public boolean has_map() { - return store.status() == AltosMapTile.success; + return tile.status == AltosMapTile.loaded; } - public synchronized void notify_store(AltosMapStore store, int status) { - switch (status) { - case AltosMapTile.loading: - break; - case AltosMapTile.success: + public synchronized void notify_tile(AltosMapTile tile, int status) { + if (status == AltosMapTile.fetched) { + System.out.printf("tile fetched, loading image\n"); load(); - break; - default: - tile.set_status(status); - tile.notify_image(null); } } - public MapCacheElement(AltosMapTile tile, AltosMapStore store) throws IOException { + public MapCacheElement(AltosMapTile tile) { this.tile = tile; this.image = null; - this.store = store; this.used = 0; - - int status = store.status(); - switch (status) { - case AltosMapTile.loading: - store.add_listener(this); - break; - case AltosMapTile.success: - load(); - break; - default: - tile.set_status(status); - tile.notify_image(null); - break; - } + tile.add_listener(this); } } @@ -135,7 +110,7 @@ public class AltosMapCache implements AltosMapCacheListener { } } - public AltosImage get(AltosMapTile tile, AltosMapStore store, int width, int height) { + public AltosImage get(AltosMapTile tile) { int oldest = -1; long age = used; @@ -148,7 +123,7 @@ public class AltosMapCache implements AltosMapCacheListener { oldest = i; break; } - if (store.equals(element.store)) { + if (tile.store.equals(element.tile.store)) { element.used = used++; return element.image; } @@ -158,24 +133,15 @@ public class AltosMapCache implements AltosMapCacheListener { } } - try { - element = new MapCacheElement(tile, store); - element.used = used++; - if (elements[oldest] != null) - elements[oldest].flush(); + element = new MapCacheElement(tile); + element.used = used++; + if (elements[oldest] != null) + elements[oldest].flush(); - elements[oldest] = element; - - if (element.image == null) - tile.set_status(AltosMapTile.loading); - else - tile.set_status(AltosMapTile.success); - - return element.image; - } catch (IOException e) { - tile.set_status(AltosMapTile.failed); - return null; - } + elements[oldest] = element; + System.out.printf("AltosMapCache.get image ? %s\n", + element.image == null ? "false" : "true"); + return element.image; } } diff --git a/altoslib/AltosMapInterface.java b/altoslib/AltosMapInterface.java index 71936ad2..756a78f2 100644 --- a/altoslib/AltosMapInterface.java +++ b/altoslib/AltosMapInterface.java @@ -29,7 +29,7 @@ public interface AltosMapInterface { public abstract AltosMapMark new_mark(double lat, double lon, int state); - public abstract AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size); + public abstract AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size); public abstract int width(); diff --git a/altoslib/AltosMapLoader.java b/altoslib/AltosMapLoader.java index 15fd756e..7112a1c4 100644 --- a/altoslib/AltosMapLoader.java +++ b/altoslib/AltosMapLoader.java @@ -24,7 +24,7 @@ import java.lang.Math; import java.net.URL; import java.net.URLConnection; -public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListener { +public class AltosMapLoader extends Thread implements AltosMapTileListener { AltosMapLoaderListener listener; double latitude, longitude; @@ -91,10 +91,8 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen AltosPointInt point = new AltosPointInt(x, y); AltosLatLon ul = transform.lat_lon(point); AltosLatLon center = transform.lat_lon(new AltosPointDouble(x + AltosMap.px_size/2, y + AltosMap.px_size/2)); - AltosMapTile tile = map.map_interface.new_tile(this, ul, center, zoom, maptype, AltosMap.px_size); - tile.add_store_listener(this); - if (tile.store_status() != AltosMapTile.loading) - notify_tile(tile, tile.store_status()); + AltosMapTile tile = map.map_interface.new_tile(null, ul, center, zoom, maptype, AltosMap.px_size); + tile.add_listener(this); } } } @@ -123,7 +121,7 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen do_load(); } - private void start_load() { + public void run() { cur_z = min_z; int ntype = 0; @@ -138,66 +136,64 @@ public class AltosMapLoader implements AltosMapTileListener, AltosMapStoreListen cur_type = next_type(0); + tiles_total = 0; for (int z = min_z; z <= max_z; z++) - tiles_total += tiles_per_layer(z); + tiles_total += tiles_per_layer(z) * ntype; layers_total = (max_z - min_z + 1) * ntype; layers_loaded = 0; tiles_loaded_total = 0; - listener.debug("total tiles %d\n", tiles_total); + listener.debug("total tiles %d layers %d\n", tiles_total, layers_total); listener.loader_start(tiles_total); do_load(); } - public void load(double latitude, double longitude, int min_z, int max_z, double radius, int all_types) { - listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n", - latitude, longitude, min_z, max_z, radius, all_types); - this.latitude = latitude; - this.longitude = longitude; - this.min_z = min_z; - this.max_z = max_z; - this.radius = radius; - this.all_types = all_types; - start_load(); - } - - public synchronized void notify_store(AltosMapStore store, int status) { + public synchronized void notify_tile(AltosMapTile tile, int status) { boolean do_next = false; - if (status == AltosMapTile.loading) + if (status == AltosMapTile.fetching) return; + tile.remove_listener(this); + if (layers_loaded >= layers_total) return; ++tiles_loaded_total; ++tiles_loaded_layer; + listener.debug("AltosMapLoader.notify_tile status %d total %d of %d layer %d of %d\n", + status, tiles_loaded_total, tiles_total, tiles_loaded_layer, tiles_this_layer); + if (tiles_loaded_layer == tiles_this_layer) { ++layers_loaded; listener.debug("%d layers loaded\n", layers_loaded); - if (layers_loaded == layers_total) { - listener.loader_done(tiles_total); - return; - } else { - do_next = true; - } + do_next = true; } - listener.loader_notify(tiles_loaded_total, - tiles_total, store.file.toString()); - if (do_next) - next_load(); - } - public synchronized void notify_tile(AltosMapTile tile, int status) { - notify_store(tile.store, status); + if (tiles_loaded_total == tiles_total) + listener.loader_done(tiles_total); + else { + listener.loader_notify(tiles_loaded_total, + tiles_total, tile.store.file.toString()); + if (do_next) + next_load(); + } } - public AltosMapCache cache() { return map.cache(); } - - public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener) { + public AltosMapLoader(AltosMap map, AltosMapLoaderListener listener, + double latitude, double longitude, int min_z, int max_z, double radius, int all_types) { + listener.debug("lat %f lon %f min_z %d max_z %d radius %f all_types %d\n", + latitude, longitude, min_z, max_z, radius, all_types); this.map = map; this.listener = listener; + this.latitude = latitude; + this.longitude = longitude; + this.min_z = min_z; + this.max_z = max_z; + this.radius = radius; + this.all_types = all_types; + start(); } } diff --git a/altoslib/AltosMapStore.java b/altoslib/AltosMapStore.java index eebef310..aed365ca 100644 --- a/altoslib/AltosMapStore.java +++ b/altoslib/AltosMapStore.java @@ -35,6 +35,7 @@ public class AltosMapStore { public synchronized void add_listener(AltosMapStoreListener listener) { if (!listeners.contains(listener)) listeners.add(listener); + listener.notify_store(this, status); } public synchronized void remove_listener(AltosMapStoreListener listener) { @@ -110,7 +111,7 @@ public class AltosMapStore { file.delete(); return AltosMapTile.bad_request; } - return AltosMapTile.success; + return AltosMapTile.fetched; } static Object fetch_lock = new Object(); @@ -118,42 +119,42 @@ public class AltosMapStore { static final long forbidden_interval = 60l * 1000l * 1000l * 1000l; static final long google_maps_ratelimit_ms = 1200; - static Object loader_lock = new Object(); + static Object fetcher_lock = new Object(); static LinkedList waiting = new LinkedList(); static LinkedList running = new LinkedList(); - static final int concurrent_loaders = 128; + static final int concurrent_fetchers = 128; - static void start_loaders() { - while (!waiting.isEmpty() && running.size() < concurrent_loaders) { + static void start_fetchers() { + while (!waiting.isEmpty() && running.size() < concurrent_fetchers) { AltosMapStore s = waiting.remove(); running.add(s); - Thread lt = s.make_loader_thread(); + Thread lt = s.make_fetcher_thread(); lt.start(); } } - void finish_loader() { - synchronized(loader_lock) { + void finish_fetcher() { + synchronized(fetcher_lock) { running.remove(this); - start_loaders(); + start_fetchers(); } } - void add_loader() { - synchronized(loader_lock) { + void add_fetcher() { + synchronized(fetcher_lock) { waiting.add(this); - start_loaders(); + start_fetchers(); } } - class loader implements Runnable { + class fetcher implements Runnable { public void run() { try { if (file.exists()) { - notify_listeners(AltosMapTile.success); + notify_listeners(AltosMapTile.fetched); return; } @@ -170,7 +171,7 @@ public class AltosMapStore { synchronized (fetch_lock) { long startTime = System.nanoTime(); new_status = fetch_url(); - if (new_status == AltosMapTile.success) { + if (new_status == AltosMapTile.fetched) { long duration_ms = (System.nanoTime() - startTime) / 1000000; if (duration_ms < google_maps_ratelimit_ms) { try { @@ -186,17 +187,17 @@ public class AltosMapStore { } notify_listeners(new_status); } finally { - finish_loader(); + finish_fetcher(); } } } - private Thread make_loader_thread() { - return new Thread(new loader()); + private Thread make_fetcher_thread() { + return new Thread(new fetcher()); } - private void load() { - add_loader(); + private void fetch() { + add_fetcher(); } private AltosMapStore (String url, File file) { @@ -204,10 +205,10 @@ public class AltosMapStore { this.file = file; if (file.exists()) - status = AltosMapTile.success; + status = AltosMapTile.fetched; else { - status = AltosMapTile.loading; - load(); + status = AltosMapTile.fetching; + fetch(); } } diff --git a/altoslib/AltosMapTile.java b/altoslib/AltosMapTile.java index 076c5937..fdc8ff65 100644 --- a/altoslib/AltosMapTile.java +++ b/altoslib/AltosMapTile.java @@ -20,22 +20,23 @@ package org.altusmetrum.altoslib_10; import java.io.*; import java.util.*; -public abstract class AltosMapTile implements AltosFontListener { - AltosMapTileListener listener; +public abstract class AltosMapTile implements AltosFontListener, AltosMapStoreListener { + LinkedList listeners = new LinkedList(); public AltosLatLon upper_left, center; public int px_size; int zoom; int maptype; int scale; + private AltosMapCache cache; public AltosMapStore store; - public AltosMapCache cache; public int status; - static public final int success = 0; - static public final int loading = 1; - static public final int failed = 2; - static public final int bad_request = 3; - static public final int forbidden = 4; + static public final int loaded = 0; /* loaded from file */ + static public final int fetched = 1; /* downloaded to file */ + static public final int fetching = 2; /* downloading from net */ + static public final int failed = 3; /* loading from file failed */ + static public final int bad_request = 4;/* downloading failed */ + static public final int forbidden = 5; /* downloading failed */ private File map_file() { double lat = center.lat; @@ -79,33 +80,46 @@ public abstract class AltosMapTile implements AltosFontListener { public void font_size_changed(int font_size) { } - public void set_status(int status) { + private synchronized void notify_listeners(int status) { this.status = status; - listener.notify_tile(this, status); + for (AltosMapTileListener listener : listeners) + listener.notify_tile(this, status); } - public void notify_image(AltosImage image) { - listener.notify_tile(this, status); + public void notify_store(AltosMapStore store, int status) { +// System.out.printf("AltosMapTile.notify_store %d\n", status); + notify_listeners(status); } - public int store_status() { - return store.status(); + public void notify_image(AltosImage image) { + if (image == null) + status = failed; + else + status = loaded; + notify_listeners(status); } - public void add_store_listener(AltosMapStoreListener listener) { - store.add_listener(listener); + public abstract void paint(AltosMapTransform t); + + public AltosImage get_image() { + if (cache == null) + return null; + return cache.get(this); } - public void remove_store_listener(AltosMapStoreListener listener) { - store.remove_listener(listener); + public synchronized void add_listener(AltosMapTileListener listener) { + if (!listeners.contains(listener)) + listeners.add(listener); + listener.notify_tile(this, status); } - public abstract void paint(AltosMapTransform t); + public synchronized void remove_listener(AltosMapTileListener listener) { + listeners.remove(listener); + } - public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) { - this.listener = listener; + public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size, int scale) { + this.cache = cache; this.upper_left = upper_left; - this.cache = listener.cache(); while (center.lon < -180.0) center.lon += 360.0; @@ -118,11 +132,11 @@ public abstract class AltosMapTile implements AltosFontListener { this.px_size = px_size; this.scale = scale; - status = AltosMapTile.loading; store = AltosMapStore.get(map_url(), map_file()); + store.add_listener(this); } - public AltosMapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { - this(listener, upper_left, center, zoom, maptype, px_size, 1); + public AltosMapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { + this(cache, upper_left, center, zoom, maptype, px_size, 1); } } diff --git a/altoslib/AltosMapTileListener.java b/altoslib/AltosMapTileListener.java index 6ab03638..6d78b205 100644 --- a/altoslib/AltosMapTileListener.java +++ b/altoslib/AltosMapTileListener.java @@ -19,6 +19,4 @@ package org.altusmetrum.altoslib_10; public interface AltosMapTileListener { abstract public void notify_tile(AltosMapTile tile, int status); - - abstract public AltosMapCache cache(); } diff --git a/altosuilib/AltosUIMapNew.java b/altosuilib/AltosUIMapNew.java index c867bf2e..a90e8c91 100644 --- a/altosuilib/AltosUIMapNew.java +++ b/altosuilib/AltosUIMapNew.java @@ -241,8 +241,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt } class MapTile extends AltosMapTile { - public MapTile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { - super(listener, upper_left, center, zoom, maptype, px_size); + public MapTile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { + super(cache, upper_left, center, zoom, maptype, px_size); } public void paint(AltosMapTransform t) { @@ -254,11 +254,9 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt if (!g.hitClip(point.x, point.y, px_size, px_size)) return; - AltosImage altos_image = cache.get(this, store, px_size, px_size); - + AltosImage altos_image = get_image(); AltosUIImage ui_image = (AltosUIImage) altos_image; - - Image image = null; + Image image = null; if (ui_image != null) image = ui_image.image; @@ -272,8 +270,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt if (t.has_location()) { String message = null; switch (status) { - case AltosMapTile.loading: - message = "Loading..."; + case AltosMapTile.fetching: + message = "Fetching..."; break; case AltosMapTile.bad_request: message = "Internal error"; @@ -334,8 +332,8 @@ public class AltosUIMapNew extends JComponent implements AltosFlightDisplay, Alt return new MapMark(lat, lon, state); } - public AltosMapTile new_tile(AltosMapTileListener listener, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { - return new MapTile(listener, upper_left, center, zoom, maptype, px_size); + public AltosMapTile new_tile(AltosMapCache cache, AltosLatLon upper_left, AltosLatLon center, int zoom, int maptype, int px_size) { + return new MapTile(cache, upper_left, center, zoom, maptype, px_size); } public int width() { diff --git a/altosuilib/AltosUIMapPreloadNew.java b/altosuilib/AltosUIMapPreloadNew.java index b5f4dbf8..3269bbdd 100644 --- a/altosuilib/AltosUIMapPreloadNew.java +++ b/altosuilib/AltosUIMapPreloadNew.java @@ -127,8 +127,6 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener JProgressBar pbar; - AltosMapLoader loader; - JLabel site_list_label; JComboBox site_list; @@ -238,7 +236,10 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener r = r * 1000; loading = true; - loader.load(latitude, longitude, min_z, max_z, r, all_types()); + new AltosMapLoader(map.map, this, + latitude, longitude, + min_z, max_z, r, all_types()); + } catch (ParseException pe) { load_button.setSelected(false); } @@ -271,8 +272,6 @@ public class AltosUIMapPreloadNew extends AltosUIFrame implements ActionListener map = new AltosUIMapNew(); - loader = new AltosMapLoader(map.map, this); - c.fill = GridBagConstraints.BOTH; c.anchor = GridBagConstraints.CENTER; c.insets = i; -- cgit v1.2.3