From: Keith Packard Date: Wed, 28 May 2014 23:06:14 +0000 (-0700) Subject: altosui/altosuilib: Shuffle lots more code from altosui into X-Git-Tag: 1.3.2.2~54 X-Git-Url: https://git.gag.com/?p=fw%2Faltos;a=commitdiff_plain;h=9b3516419981967a1c6ab956269139977ac368ca;hp=02e657e45e217dc483a81f28020cfe65a826e9be altosui/altosuilib: Shuffle lots more code from altosui into altosuilib All of the bluetooth management stuff, and AltosSerial. Signed-off-by: Keith Packard --- diff --git a/altosui/AltosBTDevice.java b/altosui/AltosBTDevice.java deleted file mode 100644 index e920803a..00000000 --- a/altosui/AltosBTDevice.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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 libaltosJNI.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosBTDevice extends altos_bt_device implements AltosDevice { - - public String getProductName() { - String name = getName(); - if (name == null) - return "Altus Metrum"; - int dash = name.lastIndexOf("-"); - if (dash < 0) - return name; - return name.substring(0,dash); - } - - public int getProduct() { - if (Altos.bt_product_telebt.equals(getProductName())) - return Altos.product_telebt; - return 0; - } - - public String getPath() { - return getAddr(); - } - - public String getErrorString() { - altos_error error = new altos_error(); - - libaltos.altos_get_last_error(error); - return String.format("%s (%d)", error.getString(), error.getCode()); - } - - public int getSerial() { - String name = getName(); - if (name == null) - return 0; - int dash = name.lastIndexOf("-"); - if (dash < 0 || dash >= name.length()) - return 0; - String sn = name.substring(dash + 1, name.length()); - try { - return Integer.parseInt(sn); - } catch (NumberFormatException ne) { - return 0; - } - } - - public String toString() { - return String.format("%-20.20s %4d %s", - getProductName(), getSerial(), getAddr()); - } - - public String toShortString() { - return String.format("%s %d %s", - getProductName(), getSerial(), getAddr()); - - } - - public SWIGTYPE_p_altos_file open() { - return libaltos.altos_bt_open(this); - } - - /* - private boolean isAltusMetrum() { - if (getName().startsWith(Altos.bt_product_telebt)) - return true; - return false; - } - */ - - public boolean matchProduct(int want_product) { - -// if (!isAltusMetrum()) -// return false; - - if (want_product == Altos.product_any) - return true; - - if (want_product == Altos.product_basestation) - return matchProduct(Altos.product_telebt); - - if (want_product == getProduct()) - return true; - - return false; - } - - public boolean equals(Object o) { - if (!(o instanceof AltosBTDevice)) - return false; - AltosBTDevice other = (AltosBTDevice) o; - return getName().equals(other.getName()) && getAddr().equals(other.getAddr()); - } - - public int hashCode() { - return getName().hashCode() ^ getAddr().hashCode(); - } - - public AltosBTDevice(String name, String addr) { - Altos.load_library(); - libaltos.altos_bt_fill_in(name, addr,this); - } - - public AltosBTDevice() { - } -} \ No newline at end of file diff --git a/altosui/AltosBTDeviceIterator.java b/altosui/AltosBTDeviceIterator.java deleted file mode 100644 index 4be5edf5..00000000 --- a/altosui/AltosBTDeviceIterator.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.util.*; -import libaltosJNI.*; - -public class AltosBTDeviceIterator implements Iterator { - AltosBTDevice current; - boolean done; - SWIGTYPE_p_altos_bt_list list; - - public boolean hasNext() { - if (list == null) - return false; - if (current != null) - return true; - if (done) - return false; - current = new AltosBTDevice(); - while (libaltos.altos_bt_list_next(list, current) != 0) { -// if (current.matchProduct(product)) - return true; - } - current = null; - done = true; - return false; - } - - public AltosBTDevice next() { - if (hasNext()) { - AltosBTDevice next = current; - current = null; - return next; - } - return null; - } - - public void remove() { - throw new UnsupportedOperationException(); - } - - public AltosBTDeviceIterator(int inquiry_time) { - done = false; - current = null; - list = libaltos.altos_bt_list_start(inquiry_time); - } -} diff --git a/altosui/AltosBTKnown.java b/altosui/AltosBTKnown.java deleted file mode 100644 index 3abbbe08..00000000 --- a/altosui/AltosBTKnown.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.util.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosBTKnown implements Iterable { - LinkedList devices = new LinkedList(); - AltosPreferencesBackend bt_pref = AltosUIPreferences.bt_devices(); - - private String get_address(String name) { - return bt_pref.getString(name, ""); - } - - private void set_address(String name, String addr) { - bt_pref.putString(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); - devices.add(new AltosBTDevice(name, addr)); - } - } catch (IllegalStateException ie) { - } - } - - public Iterator iterator() { - return devices.iterator(); - } - - private void flush() { - AltosUIPreferences.flush_preferences(); - } - - public void set(Iterable 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(); - for (AltosBTDevice new_device : new_devices) { - devices.add(new_device); - set_address(new_device.getName(), new_device.getAddr()); - } - flush(); - } - - public List list(int product) { - LinkedList list = new LinkedList(); - for (AltosBTDevice device : devices) { - if (device.matchProduct(product)) - list.add(device); - } - return list; - } - - public AltosBTKnown() { - devices = new LinkedList(); - bt_pref = AltosUIPreferences.bt_devices(); - load(); - } - - static AltosBTKnown known; - - static public AltosBTKnown bt_known() { - if (known == null) - known = new AltosBTKnown(); - return known; - } -} diff --git a/altosui/AltosBTManage.java b/altosui/AltosBTManage.java deleted file mode 100644 index e6e7efd4..00000000 --- a/altosui/AltosBTManage.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright © 2011 Keith Packard - * - * 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.awt.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.plaf.basic.*; -import java.util.*; -import java.util.concurrent.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable { - LinkedBlockingQueue found_devices; - Frame frame; - LinkedList listeners; - AltosBTKnown bt_known; - - class DeviceList extends JList implements Iterable { - LinkedList devices; - DefaultListModel list_model; - - public void add (AltosBTDevice 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 - //scroll pane to not let the user easily scroll up to the beginning - //of the list. An alternative would be to set the unitIncrement - //of the JScrollBar to a fixed value. You wouldn't get the nice - //aligned scrolling, but it should work. - public int getScrollableUnitIncrement(Rectangle visibleRect, - int orientation, - int direction) { - int row; - if (orientation == SwingConstants.VERTICAL && - direction < 0 && (row = getFirstVisibleIndex()) != -1) { - Rectangle r = getCellBounds(row, row); - if ((r.y == visibleRect.y) && (row != 0)) { - Point loc = r.getLocation(); - loc.y--; - int prevIndex = locationToIndex(loc); - Rectangle prevR = getCellBounds(prevIndex, prevIndex); - - if (prevR == null || prevR.y >= r.y) { - return 0; - } - return prevR.height; - } - } - return super.getScrollableUnitIncrement( - visibleRect, orientation, direction); - } - - public Iterator iterator() { - return devices.iterator(); - } - - public java.util.List selected_list() throws InterruptedException { - return getSelectedValuesList(); - } - - public DeviceList() { - devices = new LinkedList(); - list_model = new DefaultListModel(); - setModel(list_model); - setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); - setLayoutOrientation(JList.HORIZONTAL_WRAP); - setVisibleRowCount(-1); - } - } - - DeviceList visible_devices; - - DeviceList known_devices; - Thread bt_thread; - - public Iterator iterator() { - return known_devices.iterator(); - } - - public void commit() { - bt_known.set(this); - } - - public void add_known() { - try { - for (AltosBTDevice device : visible_devices.selected_list()) { - known_devices.add(device); - visible_devices.remove(device); - } - } catch (InterruptedException ie) { - } - } - - public void remove_known() { - try { - for (AltosBTDevice device : known_devices.selected_list()) { - known_devices.remove(device); - visible_devices.add(device); - } - } catch (InterruptedException ie) { - } - } - - 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(); - 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(); - if (!known_devices.contains(device)) - visible_devices.add(device); - } - } - - class BTGetVisibleDevices implements Runnable { - public void run () { - 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()); - } - } - } - } - - public static void show(Component frameComp, AltosBTKnown known) { - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosBTManage dialog; - - dialog = new AltosBTManage(frame, known); - dialog.setVisible(true); - } - - 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(); - - listeners = new LinkedList(); - - found_devices = new LinkedBlockingQueue(); - - 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; - c.weightx = 0; - c.weighty = 0; - 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; - c.weightx = 1; - c.weighty = 1; - 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; - c.weightx = 0; - c.weighty = 0; - - 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; - c.weightx = 1; - c.weighty = 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; - c.weightx = 0; - c.weighty = 0; - 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; - c.weightx = 0; - c.weighty = 0; - 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; - c.weightx = 0; - c.weighty = 0; - 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; - c.weightx = 0; - c.weighty = 0; - pane.add(ok_button, c); - - getRootPane().setDefaultButton(ok_button); - - pack(); - setLocationRelativeTo(frame); - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent e) { - bt_thread.interrupt(); - setVisible(false); - } - }); - } -} diff --git a/altosui/AltosDeviceUIDialog.java b/altosui/AltosDeviceUIDialog.java deleted file mode 100644 index 307c77f8..00000000 --- a/altosui/AltosDeviceUIDialog.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 javax.swing.*; -import java.awt.*; -import java.awt.event.*; -import org.altusmetrum.altosuilib_2.*; - -public class AltosDeviceUIDialog extends AltosDeviceDialog { - - public AltosDevice[] devices() { - java.util.List usb_devices = AltosUSBDevice.list(product); - int num_devices = usb_devices.size(); - java.util.List bt_devices = AltosBTKnown.bt_known().list(product); - num_devices += bt_devices.size(); - AltosDevice[] devices = new AltosDevice[num_devices]; - - 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; - } - - public void add_bluetooth() { - JButton manage_bluetooth_button = new JButton("Manage Bluetooth"); - manage_bluetooth_button.setActionCommand("manage"); - manage_bluetooth_button.addActionListener(this); - buttonPane.add(manage_bluetooth_button); - buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); - } - - public void actionPerformed(ActionEvent e) { - super.actionPerformed(e); - if ("manage".equals(e.getActionCommand())) { - AltosBTManage.show(frame, AltosBTKnown.bt_known()); - update_devices(); - } - } - - public AltosDeviceUIDialog (Frame in_frame, Component location, int in_product) { - super(in_frame, location, in_product); - } - - public static AltosDevice show (Component frameComp, int product) { - Frame frame = JOptionPane.getFrameForComponent(frameComp); - AltosDeviceUIDialog dialog; - - dialog = new AltosDeviceUIDialog(frame, frameComp, product); - dialog.setVisible(true); - return dialog.getValue(); - } -} diff --git a/altosui/AltosEepromDelete.java b/altosui/AltosEepromDelete.java index b6ac7edb..df2ade78 100644 --- a/altosui/AltosEepromDelete.java +++ b/altosui/AltosEepromDelete.java @@ -21,6 +21,7 @@ import java.awt.event.*; import javax.swing.*; import java.io.*; import java.util.concurrent.*; +import org.altusmetrum.altosuilib_2.*; import org.altusmetrum.altoslib_4.*; public class AltosEepromDelete implements Runnable { @@ -140,4 +141,4 @@ public class AltosEepromDelete implements Runnable { flights = given_flights; success = false; } -} \ No newline at end of file +} diff --git a/altosui/AltosSerial.java b/altosui/AltosSerial.java deleted file mode 100644 index 9b2180ba..00000000 --- a/altosui/AltosSerial.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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. - */ - -/* - * Deal with TeleDongle on a serial port - */ - -package altosui; - -import java.io.*; -import java.util.*; -import java.awt.*; -import javax.swing.*; -import org.altusmetrum.altoslib_4.*; -import org.altusmetrum.altosuilib_2.*; - -import libaltosJNI.*; - -/* - * This class reads from the serial port and places each received - * line in a queue. Dealing with that queue is left up to other - * threads. - */ - -public class AltosSerial extends AltosLink { - - static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); - - AltosDevice device; - SWIGTYPE_p_altos_file altos; - Thread input_thread; - String line; - byte[] line_bytes; - int line_count; - Frame frame; - - public int getchar() { - if (altos == null) - return ERROR; - return libaltos.altos_getchar(altos, 0); - } - - public void flush_output() { - super.flush_output(); - if (altos != null) { - if (libaltos.altos_flush(altos) != 0) - close_serial(); - } - } - - JDialog timeout_dialog; - - private void start_timeout_dialog_internal() { - - Object[] options = { "Cancel" }; - - JOptionPane pane = new JOptionPane(); - pane.setMessage(String.format("Connecting to %s, %7.3f MHz as %s", device.toShortString(), frequency, callsign)); - pane.setOptions(options); - pane.setInitialValue(null); - - timeout_dialog = pane.createDialog(frame, "Connecting..."); - - timeout_dialog.setVisible(true); - - Object o = pane.getValue(); - if (o == null) - return; - if (options[0].equals(o)) - reply_abort = true; - timeout_dialog.dispose(); - timeout_dialog = null; - } - - /* - * These are required by the AltosLink implementation - */ - - public boolean can_cancel_reply() { - /* - * Can cancel any replies not called from the dispatch thread - */ - return !SwingUtilities.isEventDispatchThread(); - } - - public boolean show_reply_timeout() { - if (!SwingUtilities.isEventDispatchThread() && frame != null) { - Runnable r = new Runnable() { - public void run() { - start_timeout_dialog_internal(); - } - }; - SwingUtilities.invokeLater(r); - return true; - } - return false; - } - - public void hide_reply_timeout() { - Runnable r = new Runnable() { - public void run() { - timeout_dialog.setVisible(false); - } - }; - SwingUtilities.invokeLater(r); - } - - private void close_serial() { - synchronized (devices_opened) { - devices_opened.remove(device.getPath()); - } - if (altos != null) { - libaltos.altos_free(altos); - altos = null; - } - abort_reply(); - } - - public void close() { - if (remote) { - try { - stop_remote(); - } catch (InterruptedException ie) { - } - } - if (in_reply != 0) - System.out.printf("Uh-oh. Closing active serial device\n"); - - close_serial(); - - if (input_thread != null) { - try { - input_thread.interrupt(); - input_thread.join(); - } catch (InterruptedException ie) { - } - input_thread = null; - } - if (debug) - System.out.printf("Closing %s\n", device.getPath()); - } - - private void putc(char c) { - if (altos != null) - if (libaltos.altos_putchar(altos, c) != 0) - close_serial(); - } - - public void putchar(byte c) { - if (altos != null) { - if (debug) - System.out.printf(" %02x", (int) c & 0xff); - if (libaltos.altos_putchar(altos, (char) c) != 0) - close_serial(); - } - } - - public void print(String data) { - for (int i = 0; i < data.length(); i++) - putc(data.charAt(i)); - } - - private void open() throws FileNotFoundException, AltosSerialInUseException { - synchronized (devices_opened) { - if (devices_opened.contains(device.getPath())) - throw new AltosSerialInUseException(device); - devices_opened.add(device.getPath()); - } - altos = device.open(); - if (altos == null) { - final String message = device.getErrorString(); - close(); - throw new FileNotFoundException(String.format("%s (%s)", - device.toShortString(), message)); - } - if (debug) - System.out.printf("Open %s\n", device.getPath()); - input_thread = new Thread(this); - input_thread.start(); - print("~\nE 0\n"); - set_monitor(false); - flush_output(); - } - - public void set_frame(Frame in_frame) { - frame = in_frame; - } - - public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { - device = in_device; - frame = null; - serial = device.getSerial(); - name = device.toShortString(); - open(); - } -} diff --git a/altosui/AltosSerialInUseException.java b/altosui/AltosSerialInUseException.java deleted file mode 100644 index 318155c8..00000000 --- a/altosui/AltosSerialInUseException.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright © 2010 Keith Packard - * - * 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 org.altusmetrum.altosuilib_2.*; - -public class AltosSerialInUseException extends Exception { - public AltosDevice device; - - public AltosSerialInUseException (AltosDevice in_device) { - device = in_device; - } -} diff --git a/altosui/Makefile.am b/altosui/Makefile.am index df9fe5d1..6f491d7d 100644 --- a/altosui/Makefile.am +++ b/altosui/Makefile.am @@ -10,12 +10,6 @@ CLASSPATH_ENV=mkdir -p $(JAVAROOT); CLASSPATH="$(JAVAROOT):../altoslib/*:../alto bin_SCRIPTS=altosui -altosui_BT = \ - AltosBTDevice.java \ - AltosBTDeviceIterator.java \ - AltosBTManage.java \ - AltosBTKnown.java - altosui_JAVA = \ AltosAscent.java \ AltosChannelMenu.java \ @@ -29,7 +23,6 @@ altosui_JAVA = \ AltosConfigTDUI.java \ AltosCSVUI.java \ AltosDescent.java \ - AltosDeviceUIDialog.java \ AltosEepromDelete.java \ AltosEepromManage.java \ AltosEepromMonitorUI.java \ @@ -54,15 +47,12 @@ altosui_JAVA = \ AltosUIPreferencesBackend.java \ AltosRomconfigUI.java \ AltosScanUI.java \ - AltosSerial.java \ - AltosSerialInUseException.java \ AltosUI.java \ AltosGraph.java \ AltosGraphDataPoint.java \ AltosGraphDataSet.java \ AltosGraphUI.java \ - AltosDataChooser.java \ - $(altosui_BT) + AltosDataChooser.java JFREECHART_CLASS= \ jfreechart.jar diff --git a/altosuilib/AltosBTDevice.java b/altosuilib/AltosBTDevice.java new file mode 100644 index 00000000..beefa532 --- /dev/null +++ b/altosuilib/AltosBTDevice.java @@ -0,0 +1,125 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 org.altusmetrum.altosuilib_2; + +import libaltosJNI.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosBTDevice extends altos_bt_device implements AltosDevice { + + public String getProductName() { + String name = getName(); + if (name == null) + return "Altus Metrum"; + int dash = name.lastIndexOf("-"); + if (dash < 0) + return name; + return name.substring(0,dash); + } + + public int getProduct() { + if (AltosLib.bt_product_telebt.equals(getProductName())) + return AltosLib.product_telebt; + return 0; + } + + public String getPath() { + return getAddr(); + } + + public String getErrorString() { + altos_error error = new altos_error(); + + libaltos.altos_get_last_error(error); + return String.format("%s (%d)", error.getString(), error.getCode()); + } + + public int getSerial() { + String name = getName(); + if (name == null) + return 0; + int dash = name.lastIndexOf("-"); + if (dash < 0 || dash >= name.length()) + return 0; + String sn = name.substring(dash + 1, name.length()); + try { + return Integer.parseInt(sn); + } catch (NumberFormatException ne) { + return 0; + } + } + + public String toString() { + return String.format("%-20.20s %4d %s", + getProductName(), getSerial(), getAddr()); + } + + public String toShortString() { + return String.format("%s %d %s", + getProductName(), getSerial(), getAddr()); + + } + + public SWIGTYPE_p_altos_file open() { + return libaltos.altos_bt_open(this); + } + + /* + private boolean isAltusMetrum() { + if (getName().startsWith(Altos.bt_product_telebt)) + return true; + return false; + } + */ + + public boolean matchProduct(int want_product) { + +// if (!isAltusMetrum()) +// return false; + + if (want_product == AltosLib.product_any) + return true; + + if (want_product == AltosLib.product_basestation) + return matchProduct(AltosLib.product_telebt); + + if (want_product == getProduct()) + return true; + + return false; + } + + public boolean equals(Object o) { + if (!(o instanceof AltosBTDevice)) + return false; + AltosBTDevice other = (AltosBTDevice) o; + return getName().equals(other.getName()) && getAddr().equals(other.getAddr()); + } + + public int hashCode() { + return getName().hashCode() ^ getAddr().hashCode(); + } + + public AltosBTDevice(String name, String addr) { + AltosUILib.load_library(); + libaltos.altos_bt_fill_in(name, addr,this); + } + + public AltosBTDevice() { + } +} diff --git a/altosuilib/AltosBTDeviceIterator.java b/altosuilib/AltosBTDeviceIterator.java new file mode 100644 index 00000000..cad60ffb --- /dev/null +++ b/altosuilib/AltosBTDeviceIterator.java @@ -0,0 +1,64 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 org.altusmetrum.altosuilib_2; + +import java.util.*; +import libaltosJNI.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosBTDeviceIterator implements Iterator { + AltosBTDevice current; + boolean done; + SWIGTYPE_p_altos_bt_list list; + + public boolean hasNext() { + if (list == null) + return false; + if (current != null) + return true; + if (done) + return false; + current = new AltosBTDevice(); + while (libaltos.altos_bt_list_next(list, current) != 0) { +// if (current.matchProduct(product)) + return true; + } + current = null; + done = true; + return false; + } + + public AltosBTDevice next() { + if (hasNext()) { + AltosBTDevice next = current; + current = null; + return next; + } + return null; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public AltosBTDeviceIterator(int inquiry_time) { + done = false; + current = null; + list = libaltos.altos_bt_list_start(inquiry_time); + } +} diff --git a/altosuilib/AltosBTKnown.java b/altosuilib/AltosBTKnown.java new file mode 100644 index 00000000..02883c75 --- /dev/null +++ b/altosuilib/AltosBTKnown.java @@ -0,0 +1,101 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 org.altusmetrum.altosuilib_2; + +import java.util.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosBTKnown implements Iterable { + LinkedList devices = new LinkedList(); + AltosPreferencesBackend bt_pref = AltosUIPreferences.bt_devices(); + + private String get_address(String name) { + return bt_pref.getString(name, ""); + } + + private void set_address(String name, String addr) { + bt_pref.putString(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); + devices.add(new AltosBTDevice(name, addr)); + } + } catch (IllegalStateException ie) { + } + } + + public Iterator iterator() { + return devices.iterator(); + } + + private void flush() { + AltosUIPreferences.flush_preferences(); + } + + public void set(Iterable 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(); + for (AltosBTDevice new_device : new_devices) { + devices.add(new_device); + set_address(new_device.getName(), new_device.getAddr()); + } + flush(); + } + + public List list(int product) { + LinkedList list = new LinkedList(); + for (AltosBTDevice device : devices) { + if (device.matchProduct(product)) + list.add(device); + } + return list; + } + + public AltosBTKnown() { + devices = new LinkedList(); + bt_pref = AltosUIPreferences.bt_devices(); + load(); + } + + static AltosBTKnown known; + + static public AltosBTKnown bt_known() { + if (known == null) + known = new AltosBTKnown(); + return known; + } +} diff --git a/altosuilib/AltosBTManage.java b/altosuilib/AltosBTManage.java new file mode 100644 index 00000000..6da0a3eb --- /dev/null +++ b/altosuilib/AltosBTManage.java @@ -0,0 +1,353 @@ +/* + * Copyright © 2011 Keith Packard + * + * 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 org.altusmetrum.altosuilib_2; + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.plaf.basic.*; +import java.util.*; +import java.util.concurrent.*; +import org.altusmetrum.altoslib_4.*; + +public class AltosBTManage extends AltosUIDialog implements ActionListener, Iterable { + LinkedBlockingQueue found_devices; + Frame frame; + LinkedList listeners; + AltosBTKnown bt_known; + + class DeviceList extends JList implements Iterable { + LinkedList devices; + DefaultListModel list_model; + + public void add (AltosBTDevice 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 + //scroll pane to not let the user easily scroll up to the beginning + //of the list. An alternative would be to set the unitIncrement + //of the JScrollBar to a fixed value. You wouldn't get the nice + //aligned scrolling, but it should work. + public int getScrollableUnitIncrement(Rectangle visibleRect, + int orientation, + int direction) { + int row; + if (orientation == SwingConstants.VERTICAL && + direction < 0 && (row = getFirstVisibleIndex()) != -1) { + Rectangle r = getCellBounds(row, row); + if ((r.y == visibleRect.y) && (row != 0)) { + Point loc = r.getLocation(); + loc.y--; + int prevIndex = locationToIndex(loc); + Rectangle prevR = getCellBounds(prevIndex, prevIndex); + + if (prevR == null || prevR.y >= r.y) { + return 0; + } + return prevR.height; + } + } + return super.getScrollableUnitIncrement( + visibleRect, orientation, direction); + } + + public Iterator iterator() { + return devices.iterator(); + } + + public java.util.List selected_list() throws InterruptedException { + return getSelectedValuesList(); + } + + public DeviceList() { + devices = new LinkedList(); + list_model = new DefaultListModel(); + setModel(list_model); + setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); + setLayoutOrientation(JList.HORIZONTAL_WRAP); + setVisibleRowCount(-1); + } + } + + DeviceList visible_devices; + + DeviceList known_devices; + Thread bt_thread; + + public Iterator iterator() { + return known_devices.iterator(); + } + + public void commit() { + bt_known.set(this); + } + + public void add_known() { + try { + for (AltosBTDevice device : visible_devices.selected_list()) { + known_devices.add(device); + visible_devices.remove(device); + } + } catch (InterruptedException ie) { + } + } + + public void remove_known() { + try { + for (AltosBTDevice device : known_devices.selected_list()) { + known_devices.remove(device); + visible_devices.add(device); + } + } catch (InterruptedException ie) { + } + } + + 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(); + 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(); + if (!known_devices.contains(device)) + visible_devices.add(device); + } + } + + class BTGetVisibleDevices implements Runnable { + public void run () { + 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()); + } + } + } + } + + public static void show(Component frameComp, AltosBTKnown known) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosBTManage dialog; + + dialog = new AltosBTManage(frame, known); + dialog.setVisible(true); + } + + 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(); + + listeners = new LinkedList(); + + found_devices = new LinkedBlockingQueue(); + + 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; + c.weightx = 0; + c.weighty = 0; + 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; + c.weightx = 1; + c.weighty = 1; + 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; + c.weightx = 0; + c.weighty = 0; + + 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; + c.weightx = 1; + c.weighty = 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; + c.weightx = 0; + c.weighty = 0; + 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; + c.weightx = 0; + c.weighty = 0; + 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; + c.weightx = 0; + c.weighty = 0; + 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; + c.weightx = 0; + c.weighty = 0; + pane.add(ok_button, c); + + getRootPane().setDefaultButton(ok_button); + + pack(); + setLocationRelativeTo(frame); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent e) { + bt_thread.interrupt(); + setVisible(false); + } + }); + } +} diff --git a/altosuilib/AltosDeviceUIDialog.java b/altosuilib/AltosDeviceUIDialog.java new file mode 100644 index 00000000..3013612a --- /dev/null +++ b/altosuilib/AltosDeviceUIDialog.java @@ -0,0 +1,69 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 org.altusmetrum.altosuilib_2; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.*; + +public class AltosDeviceUIDialog extends AltosDeviceDialog { + + public AltosDevice[] devices() { + java.util.List usb_devices = AltosUSBDevice.list(product); + int num_devices = usb_devices.size(); + java.util.List bt_devices = AltosBTKnown.bt_known().list(product); + num_devices += bt_devices.size(); + AltosDevice[] devices = new AltosDevice[num_devices]; + + 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; + } + + public void add_bluetooth() { + JButton manage_bluetooth_button = new JButton("Manage Bluetooth"); + manage_bluetooth_button.setActionCommand("manage"); + manage_bluetooth_button.addActionListener(this); + buttonPane.add(manage_bluetooth_button); + buttonPane.add(Box.createRigidArea(new Dimension(10, 0))); + } + + public void actionPerformed(ActionEvent e) { + super.actionPerformed(e); + if ("manage".equals(e.getActionCommand())) { + AltosBTManage.show(frame, AltosBTKnown.bt_known()); + update_devices(); + } + } + + public AltosDeviceUIDialog (Frame in_frame, Component location, int in_product) { + super(in_frame, location, in_product); + } + + public static AltosDevice show (Component frameComp, int product) { + Frame frame = JOptionPane.getFrameForComponent(frameComp); + AltosDeviceUIDialog dialog; + + dialog = new AltosDeviceUIDialog(frame, frameComp, product); + dialog.setVisible(true); + return dialog.getValue(); + } +} diff --git a/altosuilib/AltosSerial.java b/altosuilib/AltosSerial.java new file mode 100644 index 00000000..0632ca70 --- /dev/null +++ b/altosuilib/AltosSerial.java @@ -0,0 +1,208 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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. + */ + +/* + * Deal with TeleDongle on a serial port + */ + +package org.altusmetrum.altosuilib_2; + +import java.io.*; +import java.util.*; +import java.awt.*; +import javax.swing.*; +import org.altusmetrum.altoslib_4.*; +import libaltosJNI.*; + +/* + * This class reads from the serial port and places each received + * line in a queue. Dealing with that queue is left up to other + * threads. + */ + +public class AltosSerial extends AltosLink { + + static java.util.List devices_opened = Collections.synchronizedList(new LinkedList()); + + public AltosDevice device; + SWIGTYPE_p_altos_file altos; + Thread input_thread; + String line; + byte[] line_bytes; + int line_count; + Frame frame; + + public int getchar() { + if (altos == null) + return ERROR; + return libaltos.altos_getchar(altos, 0); + } + + public void flush_output() { + super.flush_output(); + if (altos != null) { + if (libaltos.altos_flush(altos) != 0) + close_serial(); + } + } + + JDialog timeout_dialog; + + private void start_timeout_dialog_internal() { + + Object[] options = { "Cancel" }; + + JOptionPane pane = new JOptionPane(); + pane.setMessage(String.format("Connecting to %s, %7.3f MHz as %s", device.toShortString(), frequency, callsign)); + pane.setOptions(options); + pane.setInitialValue(null); + + timeout_dialog = pane.createDialog(frame, "Connecting..."); + + timeout_dialog.setVisible(true); + + Object o = pane.getValue(); + if (o == null) + return; + if (options[0].equals(o)) + reply_abort = true; + timeout_dialog.dispose(); + timeout_dialog = null; + } + + /* + * These are required by the AltosLink implementation + */ + + public boolean can_cancel_reply() { + /* + * Can cancel any replies not called from the dispatch thread + */ + return !SwingUtilities.isEventDispatchThread(); + } + + public boolean show_reply_timeout() { + if (!SwingUtilities.isEventDispatchThread() && frame != null) { + Runnable r = new Runnable() { + public void run() { + start_timeout_dialog_internal(); + } + }; + SwingUtilities.invokeLater(r); + return true; + } + return false; + } + + public void hide_reply_timeout() { + Runnable r = new Runnable() { + public void run() { + timeout_dialog.setVisible(false); + } + }; + SwingUtilities.invokeLater(r); + } + + private void close_serial() { + synchronized (devices_opened) { + devices_opened.remove(device.getPath()); + } + if (altos != null) { + libaltos.altos_free(altos); + altos = null; + } + abort_reply(); + } + + public void close() { + if (remote) { + try { + stop_remote(); + } catch (InterruptedException ie) { + } + } + if (in_reply != 0) + System.out.printf("Uh-oh. Closing active serial device\n"); + + close_serial(); + + if (input_thread != null) { + try { + input_thread.interrupt(); + input_thread.join(); + } catch (InterruptedException ie) { + } + input_thread = null; + } + if (debug) + System.out.printf("Closing %s\n", device.getPath()); + } + + private void putc(char c) { + if (altos != null) + if (libaltos.altos_putchar(altos, c) != 0) + close_serial(); + } + + public void putchar(byte c) { + if (altos != null) { + if (debug) + System.out.printf(" %02x", (int) c & 0xff); + if (libaltos.altos_putchar(altos, (char) c) != 0) + close_serial(); + } + } + + public void print(String data) { + for (int i = 0; i < data.length(); i++) + putc(data.charAt(i)); + } + + private void open() throws FileNotFoundException, AltosSerialInUseException { + synchronized (devices_opened) { + if (devices_opened.contains(device.getPath())) + throw new AltosSerialInUseException(device); + devices_opened.add(device.getPath()); + } + altos = device.open(); + if (altos == null) { + final String message = device.getErrorString(); + close(); + throw new FileNotFoundException(String.format("%s (%s)", + device.toShortString(), message)); + } + if (debug) + System.out.printf("Open %s\n", device.getPath()); + input_thread = new Thread(this); + input_thread.start(); + print("~\nE 0\n"); + set_monitor(false); + flush_output(); + } + + public void set_frame(Frame in_frame) { + frame = in_frame; + } + + public AltosSerial(AltosDevice in_device) throws FileNotFoundException, AltosSerialInUseException { + device = in_device; + frame = null; + serial = device.getSerial(); + name = device.toShortString(); + open(); + } +} diff --git a/altosuilib/AltosSerialInUseException.java b/altosuilib/AltosSerialInUseException.java new file mode 100644 index 00000000..1e8207d1 --- /dev/null +++ b/altosuilib/AltosSerialInUseException.java @@ -0,0 +1,26 @@ +/* + * Copyright © 2010 Keith Packard + * + * 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 org.altusmetrum.altosuilib_2; + +public class AltosSerialInUseException extends Exception { + public AltosDevice device; + + public AltosSerialInUseException (AltosDevice in_device) { + device = in_device; + } +} diff --git a/altosuilib/Makefile.am b/altosuilib/Makefile.am index 10b756b8..fe0c3ec7 100644 --- a/altosuilib/Makefile.am +++ b/altosuilib/Makefile.am @@ -40,7 +40,15 @@ altosuilib_JAVA = \ AltosSiteMapImage.java \ AltosVoice.java \ AltosDisplayThread.java \ - AltosFreqList.java + AltosDeviceUIDialog.java \ + AltosFreqList.java \ + AltosSerial.java \ + AltosSerialInUseException.java \ + AltosBTDevice.java \ + AltosBTDeviceIterator.java \ + AltosBTManage.java \ + AltosBTKnown.java + JAR=altosuilib_$(ALTOSUILIB_VERSION).jar