altosui: Use persistent list of bluetooth devices for device dialogs
authorKeith Packard <keithp@keithp.com>
Tue, 19 Apr 2011 15:43:40 +0000 (08:43 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 19 Apr 2011 15:43:40 +0000 (08:43 -0700)
Store a list of known bluetooth devices as preferences. Always include
those in device dialogs with an option to go browse for more devices
in both the device dialog and the Configure AltosUI dialog.

Signed-off-by: Keith Packard <keithp@keithp.com>
16 files changed:
altosui/Altos.java
altosui/AltosBTDevice.java
altosui/AltosBTDeviceIterator.java
altosui/AltosBTKnown.java [new file with mode: 0644]
altosui/AltosBTManage.java
altosui/AltosConfigureUI.java
altosui/AltosDeviceDialog.java
altosui/AltosFlightUI.java
altosui/AltosPreferences.java
altosui/AltosSiteMap.java
altosui/AltosUI.java
altosui/AltosUSBDevice.java
altosui/Makefile.am
altosui/libaltos/cjnitest.c
altosui/libaltos/libaltos.c
altosui/libaltos/libaltos.h

index d221077..a087f73 100644 (file)
@@ -309,4 +309,6 @@ public class Altos {
        }
 
        public final static String bt_product_telebt = bt_product_telebt();
+
+       public static AltosBTKnown bt_known = new AltosBTKnown();
 }
index ff2be49..c2721b2 100644 (file)
@@ -86,8 +86,9 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice {
 
        public boolean matchProduct(int want_product) {
 
-               if (!isAltusMetrum())
-                       return false;
+               System.out.printf("matchProduct %s %d\n", toString(), want_product);
+//             if (!isAltusMetrum())
+//                     return false;
 
                if (want_product == Altos.product_any)
                        return true;
@@ -100,4 +101,23 @@ public class AltosBTDevice extends altos_bt_device implements AltosDevice {
 
                return false;
        }
+
+       public boolean equals(Object o) {
+               if (!(o instanceof AltosBTDevice))
+                       return false;
+               AltosBTDevice other = (AltosBTDevice) o;
+               System.out.printf("AltosBTDevice equals %s == %s\n", toString(), other.toString());
+               return getName().equals(other.getName()) && getAddr().equals(other.getAddr());
+       }
+
+       public int hashCode() {
+               return getName().hashCode() ^ getAddr().hashCode();
+       }
+
+       public AltosBTDevice(String name, String addr) {
+               libaltos.altos_bt_fill_in(name, addr,this);
+       }
+
+       public AltosBTDevice() {
+       }
 }
\ No newline at end of file
index 63ce367..7c36070 100644 (file)
@@ -21,7 +21,6 @@ import java.util.*;
 import libaltosJNI.*;
 
 public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
-       int             product;
        AltosBTDevice   current;
        boolean         done;
        SWIGTYPE_p_altos_bt_list list;
@@ -58,11 +57,9 @@ public class AltosBTDeviceIterator implements Iterator<AltosBTDevice> {
                throw new UnsupportedOperationException();
        }
 
-       public AltosBTDeviceIterator(int in_product) {
-               product = in_product;
+       public AltosBTDeviceIterator(int inquiry_time) {
                done = false;
                current = null;
-               list = libaltos.altos_bt_list_start();
-               System.out.printf("Iteration of BT list started\n");
+               list = libaltos.altos_bt_list_start(inquiry_time);
        }
 }
diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java
new file mode 100644 (file)
index 0000000..9583063
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright © 2011 Keith Packard <keithp@keithp.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+package altosui;
+import java.lang.*;
+import java.util.*;
+import libaltosJNI.*;
+import java.util.prefs.*;
+
+public class AltosBTKnown implements Iterable<AltosBTDevice> {
+       LinkedList<AltosBTDevice>       devices = new LinkedList<AltosBTDevice>();
+       Preferences                     bt_pref = AltosPreferences.bt_devices();
+
+       private String get_address(String name) {
+               return bt_pref.get(name, "");
+       }
+
+       private void set_address(String name, String addr) {
+               bt_pref.put(name, addr);
+               System.out.printf("saving known %s %s\n", name, addr);
+       }
+
+       private void remove(String name) {
+               bt_pref.remove(name);
+       }
+
+       private void load() {
+               try {
+                       String[] names = bt_pref.keys();
+                       for (int i = 0; i < names.length; i++) {
+                               String  name = names[i];
+                               String  addr = get_address(name);
+                               System.out.printf("Known device %s %s\n", name, addr);
+                               devices.add(new AltosBTDevice(name, addr));
+                       }
+               } catch (BackingStoreException be) {
+               } catch (IllegalStateException ie) {
+               }
+       }
+
+       public Iterator<AltosBTDevice> iterator() {
+               return devices.iterator();
+       }
+
+       private void flush() {
+               AltosPreferences.flush_preferences();
+       }
+
+       public void set(Iterable<AltosBTDevice> new_devices) {
+               for (AltosBTDevice old : devices) {
+                       boolean found = false;
+                       for (AltosBTDevice new_device : new_devices) {
+                               if (new_device.equals(old)) {
+                                       found = true;
+                                       break;
+                               }
+                       }
+                       if (!found)
+                               remove(old.getName());
+               }
+               devices = new LinkedList<AltosBTDevice>();
+               for (AltosBTDevice new_device : new_devices) {
+                       devices.add(new_device);
+                       set_address(new_device.getName(), new_device.getAddr());
+               }
+               flush();
+       }
+
+       public List<AltosDevice> list(int product) {
+               LinkedList<AltosDevice> list = new LinkedList<AltosDevice>();
+               for (AltosBTDevice device : devices) {
+                       if (device.matchProduct(product))
+                               list.add(device);
+               }
+               return list;
+       }
+
+       public AltosBTKnown() {
+               devices = new LinkedList<AltosBTDevice>();
+               bt_pref = AltosPreferences.bt_devices();
+               load();
+       }
+}
\ No newline at end of file
index 66e1210..98a8b75 100644 (file)
@@ -22,6 +22,8 @@ import java.awt.event.*;
 import javax.swing.*;
 import javax.swing.filechooser.FileNameExtensionFilter;
 import javax.swing.table.*;
+import javax.swing.event.*;
+import javax.swing.plaf.basic.*;
 import java.io.*;
 import java.util.*;
 import java.text.*;
@@ -30,17 +32,32 @@ import java.util.concurrent.*;
 
 import libaltosJNI.*;
 
-public class AltosBTManage extends JDialog implements ActionListener {
+public class AltosBTManage extends JDialog implements ActionListener, Iterable<AltosBTDevice> {
        LinkedBlockingQueue<AltosBTDevice> found_devices;
        Frame frame;
+       LinkedList<ActionListener> listeners;
+       AltosBTKnown    bt_known;
 
        class DeviceList extends JList implements Iterable<AltosBTDevice> {
                LinkedList<AltosBTDevice> devices;
                DefaultListModel        list_model;
 
                public void add (AltosBTDevice device) {
-                       devices.add(device);
-                       list_model.addElement(device);
+                       if (!devices.contains(device)) {
+                               devices.add(device);
+                               list_model.addElement(device);
+                       }
+               }
+
+               public void remove (AltosBTDevice device) {
+                       if (devices.contains(device)) {
+                               devices.remove(device);
+                               list_model.removeElement(device);
+                       }
+               }
+
+               public boolean contains(AltosBTDevice device) {
+                       return devices.contains(device);
                }
 
                //Subclass JList to workaround bug 4832765, which can cause the
@@ -75,6 +92,14 @@ public class AltosBTManage extends JDialog implements ActionListener {
                        return devices.iterator();
                }
 
+               public java.util.List<AltosBTDevice> selected_list() {
+                       java.util.LinkedList<AltosBTDevice> l = new java.util.LinkedList<AltosBTDevice>();
+                       Object[] a = getSelectedValues();
+                       for (int i = 0; i < a.length; i++)
+                               l.add((AltosBTDevice)a[i]);
+                       return l;
+               }
+
                public DeviceList() {
                        devices = new LinkedList<AltosBTDevice>();
                        list_model = new DefaultListModel();
@@ -87,111 +112,233 @@ public class AltosBTManage extends JDialog implements ActionListener {
 
        DeviceList      visible_devices;
 
-       DeviceList      selected_devices;
+       DeviceList      known_devices;
+       Thread          bt_thread;
+
+       public Iterator<AltosBTDevice> iterator() {
+               return known_devices.iterator();
+       }
+
+       public void commit() {
+               bt_known.set(this);
+       }
+
+       public void add_known() {
+               for (AltosBTDevice device : visible_devices.selected_list()) {
+                       System.out.printf("Add known %s\n", device.toString());
+                       known_devices.add(device);
+                       visible_devices.remove(device);
+               }
+       }
+
+       public void remove_known() {
+               for (AltosBTDevice device : known_devices.selected_list()) {
+                       System.out.printf("Remove known %s\n", device.toString());
+                       known_devices.remove(device);
+                       visible_devices.add(device);
+               }
+       }
+
+       public void addActionListener(ActionListener l) {
+               listeners.add(l);
+       }
+
+       private void forwardAction(ActionEvent e) {
+               for (ActionListener l : listeners)
+                       l.actionPerformed(e);
+       }
 
        public void actionPerformed(ActionEvent e) {
+               String  command = e.getActionCommand();
+               System.out.printf("manage command %s\n", command);
+               if ("ok".equals(command)) {
+                       bt_thread.interrupt();
+                       commit();
+                       setVisible(false);
+                       forwardAction(e);
+               } else if ("cancel".equals(command)) {
+                       bt_thread.interrupt();
+                       setVisible(false);
+                       forwardAction(e);
+               } else if ("select".equals(command)) {
+                       add_known();
+               } else if ("deselect".equals(command)) {
+                       remove_known();
+               }
        }
 
        public void got_visible_device() {
                while (!found_devices.isEmpty()) {
                        AltosBTDevice   device = found_devices.remove();
-                       visible_devices.add(device);
+                       if (!known_devices.contains(device))
+                               visible_devices.add(device);
                }
        }
 
        class BTGetVisibleDevices implements Runnable {
                public void run () {
-
-                       try {
-                               AltosBTDeviceIterator   i = new AltosBTDeviceIterator(Altos.product_any);
-                               AltosBTDevice           device;
-
-                               while ((device = i.next()) != null) {
-                                       Runnable r;
-
-                                       found_devices.add(device);
-                                       r = new Runnable() {
-                                                       public void run() {
-                                                               got_visible_device();
-                                                       }
-                                               };
-                                       SwingUtilities.invokeLater(r);
+                       for (;;)
+                               for (int time = 1; time <= 8; time <<= 1) {
+                                       AltosBTDeviceIterator   i = new AltosBTDeviceIterator(time);
+                                       AltosBTDevice           device;
+
+                                       if (Thread.interrupted())
+                                               return;
+                                       try {
+                                               while ((device = i.next()) != null) {
+                                                       Runnable r;
+
+                                                       if (Thread.interrupted())
+                                                               return;
+                                                       found_devices.add(device);
+                                                       r = new Runnable() {
+                                                                       public void run() {
+                                                                               got_visible_device();
+                                                                       }
+                                                               };
+                                                       SwingUtilities.invokeLater(r);
+                                               }
+                                       } catch (Exception e) {
+                                               System.out.printf("uh-oh, exception %s\n", e.toString());
+                                       }
                                }
-                       } catch (Exception e) {
-                               System.out.printf("uh-oh, exception %s\n", e.toString());
-                       }
                }
        }
 
-       public static void show(Component frameComp) {
+       public static void show(Component frameComp, AltosBTKnown known) {
                Frame   frame = JOptionPane.getFrameForComponent(frameComp);
                AltosBTManage   dialog;
 
-               dialog = new AltosBTManage(frame);
+               dialog = new AltosBTManage(frame, known);
                dialog.setVisible(true);
        }
 
-       public AltosBTManage(Frame in_frame) {
+       public AltosBTManage(Frame in_frame, AltosBTKnown in_known) {
                super(in_frame, "Manage Bluetooth Devices", true);
 
                frame = in_frame;
-
+               bt_known = in_known;
                BTGetVisibleDevices     get_visible_devices = new BTGetVisibleDevices();
+               bt_thread = new Thread(get_visible_devices);
+               bt_thread.start();
 
-               Thread t = new Thread(get_visible_devices);
-               t.start();
+               listeners = new LinkedList<ActionListener>();
 
                found_devices = new LinkedBlockingQueue<AltosBTDevice>();
 
-               JButton cancelButton = new JButton("Cancel");
-               cancelButton.addActionListener(this);
-
-               final JButton selectButton = new JButton("Select");
-               selectButton.setActionCommand("select");
-               selectButton.addActionListener(this);
-               getRootPane().setDefaultButton(selectButton);
-
-               selected_devices = new DeviceList();
-               JScrollPane selected_list_scroller = new JScrollPane(selected_devices);
-               selected_list_scroller.setPreferredSize(new Dimension(400, 80));
-               selected_list_scroller.setAlignmentX(LEFT_ALIGNMENT);
+               Container pane = getContentPane();
+               pane.setLayout(new GridBagLayout());
+
+               GridBagConstraints c = new GridBagConstraints();
+               c.insets = new Insets(4,4,4,4);
+
+               /*
+                * Known devices label and list
+                */
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = 0;
+               c.gridy = 0;
+               c.gridwidth = 1;
+               c.gridheight = 1;
+               pane.add(new JLabel("Known Devices"), c);
+
+               known_devices = new DeviceList();
+               for (AltosBTDevice device : bt_known)
+                       known_devices.add(device);
+
+               JScrollPane known_list_scroller = new JScrollPane(known_devices);
+               known_list_scroller.setPreferredSize(new Dimension(400, 80));
+               known_list_scroller.setAlignmentX(LEFT_ALIGNMENT);
+               c.fill = GridBagConstraints.BOTH;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = 0;
+               c.gridy = 1;
+               c.gridwidth = 1;
+               c.gridheight = 2;
+               pane.add(known_list_scroller, c);
+
+               /*
+                * Visible devices label and list
+                */
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = 2;
+               c.gridy = 0;
+               c.gridwidth = 1;
+               c.gridheight = 1;
+               pane.add(new JLabel("Visible Devices"), c);
 
                visible_devices = new DeviceList();
                JScrollPane visible_list_scroller = new JScrollPane(visible_devices);
                visible_list_scroller.setPreferredSize(new Dimension(400, 80));
                visible_list_scroller.setAlignmentX(LEFT_ALIGNMENT);
+               c.fill = GridBagConstraints.BOTH;
+               c.anchor = GridBagConstraints.WEST;
+               c.gridx = 2;
+               c.gridy = 1;
+               c.gridheight = 2;
+               c.gridwidth = 1;
+               pane.add(visible_list_scroller, c);
+
+               /*
+                * Arrows between the two lists
+                */
+               BasicArrowButton select_arrow = new BasicArrowButton(SwingConstants.WEST);
+               select_arrow.setActionCommand("select");
+               select_arrow.addActionListener(this);
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.SOUTH;
+               c.gridx = 1;
+               c.gridy = 1;
+               c.gridheight = 1;
+               c.gridwidth = 1;
+               pane.add(select_arrow, c);
+
+               BasicArrowButton deselect_arrow = new BasicArrowButton(SwingConstants.EAST);
+               deselect_arrow.setActionCommand("deselect");
+               deselect_arrow.addActionListener(this);
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.NORTH;
+               c.gridx = 1;
+               c.gridy = 2;
+               c.gridheight = 1;
+               c.gridwidth = 1;
+               pane.add(deselect_arrow, c);
+
+               JButton cancel_button = new JButton("Cancel");
+               cancel_button.setActionCommand("cancel");
+               cancel_button.addActionListener(this);
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.gridx = 0;
+               c.gridy = 3;
+               c.gridheight = 1;
+               c.gridwidth = 1;
+               pane.add(cancel_button, c);
+
+               JButton ok_button = new JButton("OK");
+               ok_button.setActionCommand("ok");
+               ok_button.addActionListener(this);
+               c.fill = GridBagConstraints.NONE;
+               c.anchor = GridBagConstraints.CENTER;
+               c.gridx = 2;
+               c.gridy = 3;
+               c.gridheight = 1;
+               c.gridwidth = 1;
+               pane.add(ok_button, c);
+
+               getRootPane().setDefaultButton(ok_button);
 
-               //Create a container so that we can add a title around
-               //the scroll pane.  Can't add a title directly to the
-               //scroll pane because its background would be white.
-               //Lay out the label and scroll pane from top to bottom.
-               JPanel listPane = new JPanel();
-               listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
-
-               JLabel label = new JLabel("Select Device");
-               label.setLabelFor(selected_devices);
-               listPane.add(label);
-               listPane.add(Box.createRigidArea(new Dimension(0,5)));
-               listPane.add(selected_list_scroller);
-               listPane.add(visible_list_scroller);
-               listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));
-
-               //Lay out the buttons from left to right.
-               JPanel buttonPane = new JPanel();
-               buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
-               buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
-               buttonPane.add(Box.createHorizontalGlue());
-               buttonPane.add(cancelButton);
-               buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
-               buttonPane.add(selectButton);
-
-               //Put everything together, using the content pane's BorderLayout.
-               Container contentPane = getContentPane();
-               contentPane.add(listPane, BorderLayout.CENTER);
-               contentPane.add(buttonPane, BorderLayout.PAGE_END);
-
-               //Initialize values.
-//             list.setSelectedValue(initial, true);
                pack();
+               setLocationRelativeTo(frame);
+               setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+               addWindowListener(new WindowAdapter() {
+                       @Override
+                       public void windowClosing(WindowEvent e) {
+                               bt_thread.interrupt();
+                               setVisible(false);
+                       }
+               });
        }
 }
index a2755a0..0f5e4a3 100644 (file)
@@ -204,7 +204,7 @@ public class AltosConfigureUI
                manage_bluetooth = new JButton("Manage Bluetooth");
                manage_bluetooth.addActionListener(new ActionListener() {
                                public void actionPerformed(ActionEvent e) {
-                                       new AltosBTManage(AltosBTDevice.bt_product_any, owner);
+                                       AltosBTManage.show(owner, Altos.bt_known);
                                }
                        });
                c.gridx = 1;
index fa20f86..e17504e 100644 (file)
@@ -26,37 +26,46 @@ import libaltosJNI.*;
 
 public class AltosDeviceDialog extends JDialog implements ActionListener {
 
-       public static AltosDevice show (Component frameComp, int product) {
-
-               Frame frame = JOptionPane.getFrameForComponent(frameComp);
-               AltosDevice[]   devices;
-               devices = AltosUSBDevice.list(product);
-               AltosDeviceDialog       dialog;
-
-               dialog = new AltosDeviceDialog(frame, frameComp,
-                                              devices);
-               dialog.setVisible(true);
-               return dialog.getValue();
-       }
-
        private AltosDevice     value;
        private JList           list;
        private JButton         cancel_button;
        private JButton         select_button;
        private JButton         manage_bluetooth_button;
        private Frame           frame;
+       private int             product;
 
        private AltosDevice getValue() {
                return value;
        }
 
-       private AltosDeviceDialog (Frame in_frame, Component location,
-                                  AltosDevice[] devices) {
+       private AltosDevice[] devices() {
+               java.util.List<AltosDevice>     usb_devices = AltosUSBDevice.list(product);
+               java.util.List<AltosDevice>     bt_devices = Altos.bt_known.list(product);
+               AltosDevice[]                   devices = new AltosDevice[usb_devices.size() + bt_devices.size()];
+
+               for (int i = 0; i < usb_devices.size(); i++)
+                       devices[i] = usb_devices.get(i);
+               int off = usb_devices.size();
+               for (int j = 0; j < bt_devices.size(); j++)
+                       devices[off + j] = bt_devices.get(j);
+               return devices;
+       }
+
+       private void update_devices() {
+               AltosDevice[] devices = devices();
+               list.setListData(devices);
+               select_button.setEnabled(devices.length > 0);
+       }
+
+       private AltosDeviceDialog (Frame in_frame, Component location, int in_product) {
                super(in_frame, "Device Selection", true);
 
+               product = in_product;
                frame = in_frame;
                value = null;
 
+               AltosDevice[]   devices = devices();
+
                cancel_button = new JButton("Cancel");
                cancel_button.setActionCommand("cancel");
                cancel_button.addActionListener(this);
@@ -147,7 +156,7 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {
                contentPane.add(buttonPane, BorderLayout.PAGE_END);
 
                //Initialize values.
-               if (devices != null && devices.length > 0)
+               if (devices != null && devices.length != 0)
                        list.setSelectedValue(devices[0], true);
                pack();
                setLocationRelativeTo(location);
@@ -158,10 +167,20 @@ public class AltosDeviceDialog extends JDialog implements ActionListener {
                if ("select".equals(e.getActionCommand()))
                        value = (AltosDevice)(list.getSelectedValue());
                if ("manage".equals(e.getActionCommand())) {
-                       AltosBTManage.show(frame);
+                       AltosBTManage.show(frame, Altos.bt_known);
+                       update_devices();
                        return;
                }
                setVisible(false);
        }
 
+       public static AltosDevice show (Component frameComp, int product) {
+
+               Frame                           frame = JOptionPane.getFrameForComponent(frameComp);
+               AltosDeviceDialog       dialog;
+
+               dialog = new AltosDeviceDialog(frame, frameComp, product);
+               dialog.setVisible(true);
+               return dialog.getValue();
+       }
 }
index 66dcdad..eb6c6d9 100644 (file)
@@ -122,7 +122,7 @@ public class AltosFlightUI extends JFrame implements AltosFlightDisplay {
        JComboBox       telemetries;
 
        public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
-               AltosPreferences.init(this);
+               AltosPreferences.set_component(this);
 
                voice = in_voice;
                reader = in_reader;
index 5f82765..b1192be 100644 (file)
@@ -79,11 +79,9 @@ class AltosPreferences {
        /* Serial debug */
        static boolean serial_debug;
 
-       public static void init(Component ui) {
+       public static void init() {
                preferences = Preferences.userRoot().node("/org/altusmetrum/altosui");
 
-               component = ui;
-
                /* Initialize logdir from preferences */
                String logdir_string = preferences.get(logdirPreference, null);
                if (logdir_string != null)
@@ -116,14 +114,23 @@ class AltosPreferences {
                AltosSerial.set_debug(serial_debug);
        }
 
+       static { init(); }
+
+       static void set_component(Component in_component) {
+               component = in_component;
+       }
+
        static void flush_preferences() {
                try {
                        preferences.flush();
                } catch (BackingStoreException ee) {
-                       JOptionPane.showMessageDialog(component,
-                                                     preferences.absolutePath(),
-                                                     "Cannot save prefernces",
-                                                     JOptionPane.ERROR_MESSAGE);
+                       if (component != null)
+                               JOptionPane.showMessageDialog(component,
+                                                             preferences.absolutePath(),
+                                                             "Cannot save prefernces",
+                                                             JOptionPane.ERROR_MESSAGE);
+                       else
+                               System.err.printf("Cannot save preferences\n");
                }
        }
 
@@ -262,4 +269,8 @@ class AltosPreferences {
        public static boolean serial_debug() {
                return serial_debug;
        }
+
+       public static Preferences bt_devices() {
+               return preferences.node("bt_devices");
+       }
 }
index f4b6b7e..7575c10 100644 (file)
@@ -164,8 +164,6 @@ public class AltosSiteMap extends JScrollPane implements AltosFlightDisplay {
        }
 
        public static void prefetchMaps(double lat, double lng, int w, int h) {
-               AltosPreferences.init(null);
-
                AltosSiteMap asm = new AltosSiteMap(true);
                asm.centre = asm.getBaseLocation(lat, lng);
 
index 4b808c4..7955c1c 100644 (file)
@@ -99,7 +99,7 @@ public class AltosUI extends JFrame {
                if (imgURL != null)
                        setIconImage(new ImageIcon(imgURL).getImage());
 
-               AltosPreferences.init(this);
+               AltosPreferences.set_component(this);
 
                pane = getContentPane();
                gridbag = new GridBagLayout();
@@ -397,9 +397,9 @@ public class AltosUI extends JFrame {
                        AltosUI altosui = new AltosUI();
                        altosui.setVisible(true);
 
-                       AltosDevice[] devices = AltosUSBDevice.list(Altos.product_basestation);
-                       for (int i = 0; i < devices.length; i++)
-                               altosui.telemetry_window(devices[i]);
+                       java.util.List<AltosDevice> devices = AltosUSBDevice.list(Altos.product_basestation);
+                       for (AltosDevice device : devices)
+                               altosui.telemetry_window(device);
                }
        }
 }
index deed005..dc746a6 100644 (file)
@@ -77,13 +77,13 @@ public class AltosUSBDevice  extends altos_device implements AltosDevice {
                return false;
        }
 
-       static AltosUSBDevice[] list(int product) {
+       static java.util.List<AltosDevice> list(int product) {
                if (!Altos.load_library())
                        return null;
 
                SWIGTYPE_p_altos_list list = libaltos.altos_list_start();
 
-               ArrayList<AltosUSBDevice> device_list = new ArrayList<AltosUSBDevice>();
+               ArrayList<AltosDevice> device_list = new ArrayList<AltosDevice>();
                if (list != null) {
                        for (;;) {
                                AltosUSBDevice device = new AltosUSBDevice();
@@ -95,9 +95,6 @@ public class AltosUSBDevice  extends altos_device implements AltosDevice {
                        libaltos.altos_list_finish(list);
                }
 
-               AltosUSBDevice[] devices = new AltosUSBDevice[device_list.size()];
-               for (int i = 0; i < device_list.size(); i++)
-                       devices[i] = device_list.get(i);
-               return devices;
+               return device_list;
        }
 }
\ No newline at end of file
index f2de4a3..f4d84ad 100644 (file)
@@ -30,6 +30,7 @@ altosui_JAVA = \
        AltosBTDevice.java \
        AltosBTDeviceIterator.java \
        AltosBTManage.java \
+       AltosBTKnown.java \
        AltosDisplayThread.java \
        AltosEepromChunk.java \
        AltosEepromDelete.java \
index 7956164..88e40d7 100644 (file)
@@ -41,7 +41,7 @@ main ()
                altos_close(file);
        }
        altos_list_finish(list);
-       bt_list = altos_bt_list_start();
+       bt_list = altos_bt_list_start(8);
        while (altos_bt_list_next(bt_list, &bt_device)) {
                printf ("%s %s\n", bt_device.name, bt_device.addr);
                if (strncmp(bt_device.name, "TeleBT", 6) == 0) {
index 13635a0..2c47f3e 100644 (file)
@@ -591,10 +591,9 @@ struct altos_bt_list {
 };
 
 #define INQUIRY_MAX_RSP        255
-#define INQUIRY_LEN    8
 
 struct altos_bt_list *
-altos_bt_list_start(void)
+altos_bt_list_start(int inquiry_time)
 {
        struct altos_bt_list    *bt_list;
 
@@ -614,7 +613,7 @@ altos_bt_list_start(void)
                goto no_sock;
 
        bt_list->num_rsp = hci_inquiry(bt_list->dev_id,
-                                      INQUIRY_LEN,
+                                      inquiry_time,
                                       INQUIRY_MAX_RSP,
                                       NULL,
                                       &bt_list->ii,
@@ -665,6 +664,15 @@ altos_bt_list_finish(struct altos_bt_list *bt_list)
        free(bt_list);
 }
 
+void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device)
+{
+       strncpy(device->name, name, sizeof (device->name));
+       device->name[sizeof(device->name)-1] = '\0';
+       strncpy(device->addr, addr, sizeof (device->addr));
+       device->addr[sizeof(device->addr)-1] = '\0';
+}
+
 struct altos_file *
 altos_bt_open(struct altos_bt_device *device)
 {
@@ -768,7 +776,7 @@ get_number(io_object_t object, CFStringRef entry, int *result)
 }
 
 struct altos_list *
-altos_list_start(void)
+altos_list_start(int time)
 {
        struct altos_list *list = calloc (sizeof (struct altos_list), 1);
        CFMutableDictionaryRef matching_dictionary = IOServiceMatching("IOUSBDevice");
index 9c3f965..f710919 100644 (file)
@@ -110,7 +110,7 @@ PUBLIC int
 altos_getchar(struct altos_file *file, int timeout);
 
 PUBLIC struct altos_bt_list *
-altos_bt_list_start(void);
+altos_bt_list_start(int inquiry_time);
 
 PUBLIC int
 altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device);
@@ -118,6 +118,9 @@ altos_bt_list_next(struct altos_bt_list *list, struct altos_bt_device *device);
 PUBLIC void
 altos_bt_list_finish(struct altos_bt_list *list);
 
+PUBLIC void
+altos_bt_fill_in(char *name, char *addr, struct altos_bt_device *device);
+
 PUBLIC struct altos_file *
 altos_bt_open(struct altos_bt_device *device);