altosui: Split out flight monitoring to separate window
authorKeith Packard <keithp@keithp.com>
Sat, 6 Nov 2010 06:44:47 +0000 (23:44 -0700)
committerKeith Packard <keithp@keithp.com>
Tue, 9 Nov 2010 06:08:02 +0000 (22:08 -0800)
This creates a per-TD (or replay) window to contain the flight
monitoring information, allowing multiple monitors.

This also adds per-TD preferences for monitoring channel.

Signed-off-by: Keith Packard <keithp@keithp.com>
12 files changed:
ao-tools/altosui/AltosDisplayThread.java
ao-tools/altosui/AltosFlightReader.java [new file with mode: 0644]
ao-tools/altosui/AltosFlightUI.java [new file with mode: 0644]
ao-tools/altosui/AltosLog.java
ao-tools/altosui/AltosPreferences.java
ao-tools/altosui/AltosReplayReader.java [new file with mode: 0644]
ao-tools/altosui/AltosReplayThread.java [deleted file]
ao-tools/altosui/AltosSerial.java
ao-tools/altosui/AltosStatusTable.java
ao-tools/altosui/AltosTelemetryReader.java [new file with mode: 0644]
ao-tools/altosui/AltosUI.java
ao-tools/altosui/Makefile.am

index 9cc3d5ce9eb273ae49bab05d2fee22b2642d4d62..b15472edf7393a5764b6066cc7ae8a124609249d 100644 (file)
@@ -30,13 +30,14 @@ import java.util.concurrent.LinkedBlockingQueue;
 
 public class AltosDisplayThread extends Thread {
 
 
 public class AltosDisplayThread extends Thread {
 
-       Frame           parent;
-       IdleThread      idle_thread;
-       AltosVoice      voice;
-       String          name;
-       int             crc_errors;
-       AltosStatusTable flightStatus;
-       AltosInfoTable flightInfo;
+       Frame                   parent;
+       IdleThread              idle_thread;
+       AltosVoice              voice;
+       String                  name;
+       AltosFlightReader       reader;
+       int                     crc_errors;
+       AltosStatusTable        flightStatus;
+       AltosInfoTable          flightInfo;
 
        class IdleThread extends Thread {
 
 
        class IdleThread extends Thread {
 
@@ -150,14 +151,6 @@ public class AltosDisplayThread extends Thread {
                }
        }
 
                }
        }
 
-       void init() { }
-
-       AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
-
-       void close(boolean interrupted) { }
-
-       void update(AltosState state) throws InterruptedException { }
-
        boolean tell(AltosState state, AltosState old_state) {
                boolean ret = false;
                if (old_state == null || old_state.state != state.state) {
        boolean tell(AltosState state, AltosState old_state) {
                boolean ret = false;
                if (old_state == null || old_state.state != state.state) {
@@ -208,12 +201,12 @@ public class AltosDisplayThread extends Thread {
                try {
                        for (;;) {
                                try {
                try {
                        for (;;) {
                                try {
-                                       AltosRecord record = read();
+                                       AltosRecord record = reader.read();
                                        if (record == null)
                                                break;
                                        old_state = state;
                                        state = new AltosState(record, state);
                                        if (record == null)
                                                break;
                                        old_state = state;
                                        state = new AltosState(record, state);
-                                       update(state);
+                                       reader.update(state);
                                        show(state, crc_errors);
                                        told = tell(state, old_state);
                                        idle_thread.notice(state, told);
                                        show(state, crc_errors);
                                        told = tell(state, old_state);
                                        idle_thread.notice(state, told);
@@ -232,7 +225,9 @@ public class AltosDisplayThread extends Thread {
                                                      "Telemetry Read Error",
                                                      JOptionPane.ERROR_MESSAGE);
                } finally {
                                                      "Telemetry Read Error",
                                                      JOptionPane.ERROR_MESSAGE);
                } finally {
-                       close(interrupted);
+                       if (!interrupted)
+                               idle_thread.report(true);
+                       reader.close(interrupted);
                        idle_thread.interrupt();
                        try {
                                idle_thread.join();
                        idle_thread.interrupt();
                        try {
                                idle_thread.join();
@@ -240,16 +235,11 @@ public class AltosDisplayThread extends Thread {
                }
        }
 
                }
        }
 
-       public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosStatusTable in_status, AltosInfoTable in_info) {
+       public AltosDisplayThread(Frame in_parent, AltosVoice in_voice, AltosStatusTable in_status, AltosInfoTable in_info, AltosFlightReader in_reader) {
                parent = in_parent;
                voice = in_voice;
                flightStatus = in_status;
                flightInfo = in_info;
                parent = in_parent;
                voice = in_voice;
                flightStatus = in_status;
                flightInfo = in_info;
+               reader = in_reader;
        }
        }
-
-       public void report() {
-               if (idle_thread != null)
-                       idle_thread.report(true);
-       }
-
 }
 }
diff --git a/ao-tools/altosui/AltosFlightReader.java b/ao-tools/altosui/AltosFlightReader.java
new file mode 100644 (file)
index 0000000..3d59de9
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2010 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.text.*;
+import java.io.*;
+
+public class AltosFlightReader {
+       String name;
+
+       int serial;
+
+       void init() { }
+
+       AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException { return null; }
+
+       void close(boolean interrupted) { }
+
+       void set_channel(int channel) { }
+
+       void update(AltosState state) throws InterruptedException { }
+}
diff --git a/ao-tools/altosui/AltosFlightUI.java b/ao-tools/altosui/AltosFlightUI.java
new file mode 100644 (file)
index 0000000..84ba9dc
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright © 2010 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.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+public class AltosFlightUI extends JFrame {
+       String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
+       Object[][] statusData = { { "0", "pad", "-50", "0" } };
+
+       AltosVoice              voice;
+       AltosFlightReader       reader;
+       AltosDisplayThread      thread;
+
+       private Box vbox;
+       private AltosStatusTable flightStatus;
+       private AltosInfoTable flightInfo;
+
+       public int width() {
+               return flightInfo.width();
+       }
+
+       public int height() {
+               return flightStatus.height() + flightInfo.height();
+       }
+
+       void stop_display() {
+               if (thread != null && thread.isAlive()) {
+                       thread.interrupt();
+                       try {
+                               thread.join();
+                       } catch (InterruptedException ie) {}
+               }
+               thread = null;
+       }
+
+       void disconnect() {
+               stop_display();
+       }
+
+       public AltosFlightUI(AltosVoice in_voice, AltosFlightReader in_reader, final int serial) {
+               voice = in_voice;
+               reader = in_reader;
+
+               java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
+               if (imgURL != null)
+                       setIconImage(new ImageIcon(imgURL).getImage());
+
+               setTitle(String.format("AltOS %s", reader.name));
+
+               flightStatus = new AltosStatusTable();
+
+               vbox = new Box (BoxLayout.Y_AXIS);
+               vbox.add(flightStatus);
+
+               flightInfo = new AltosInfoTable();
+               vbox.add(flightInfo.box());
+
+               this.add(vbox);
+
+               if (serial >= 0) {
+                       JMenuBar menubar = new JMenuBar();
+
+                       // Channel menu
+                       {
+                               JMenu menu = new AltosChannelMenu(AltosPreferences.channel(serial));
+                               menu.addActionListener(new ActionListener() {
+                                               public void actionPerformed(ActionEvent e) {
+                                                       int channel = Integer.parseInt(e.getActionCommand());
+                                                       reader.set_channel(channel);
+                                                       AltosPreferences.set_channel(serial, channel);
+                                               }
+                                       });
+                               menu.setMnemonic(KeyEvent.VK_C);
+                               menubar.add(menu);
+                       }
+
+                       this.setJMenuBar(menubar);
+               }
+
+               this.setSize(new Dimension (width(), height()));
+               this.validate();
+
+               setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
+               addWindowListener(new WindowAdapter() {
+                       @Override
+                       public void windowClosing(WindowEvent e) {
+                               disconnect();
+                               setVisible(false);
+                               dispose();
+                       }
+               });
+
+               this.setVisible(true);
+
+               thread = new AltosDisplayThread(this, voice, flightStatus, flightInfo, reader);
+
+               thread.start();
+       }
+
+       public AltosFlightUI (AltosVoice in_voice, AltosFlightReader in_reader) {
+               this(in_voice, in_reader, -1);
+       }
+}
index f876bebae9166c1b205f36ce55f926f3a956d714..fed96c28b0c238b20b7c7db72ef5e586383bd8e1 100644 (file)
@@ -39,9 +39,15 @@ class AltosLog implements Runnable {
        FileWriter                      log_file;
        Thread                          log_thread;
 
        FileWriter                      log_file;
        Thread                          log_thread;
 
-       void close() throws IOException {
-               if (log_file != null)
-                       log_file.close();
+       void close() {
+               if (log_file != null) {
+                       try {
+                               log_file.close();
+                       } catch (IOException io) {
+                       }
+               }
+               if (log_thread != null)
+                       log_thread.interrupt();
        }
 
        boolean open (AltosTelemetry telem) throws IOException {
        }
 
        boolean open (AltosTelemetry telem) throws IOException {
@@ -89,10 +95,7 @@ class AltosLog implements Runnable {
                } catch (InterruptedException ie) {
                } catch (IOException ie) {
                }
                } catch (InterruptedException ie) {
                } catch (IOException ie) {
                }
-               try {
-                       close();
-               } catch (IOException ie) {
-               }
+               close();
        }
 
        public AltosLog (AltosSerial s) {
        }
 
        public AltosLog (AltosSerial s) {
index 526275635ff07b90960aa3bd74aeaa8e402a5f13..e2a3df3b7717bb5b92f9cf150706bdc49a7ecbb3 100644 (file)
@@ -32,7 +32,7 @@ class AltosPreferences {
        final static String logdirPreference = "LOGDIR";
 
        /* channel preference name */
        final static String logdirPreference = "LOGDIR";
 
        /* channel preference name */
-       final static String channelPreference = "CHANNEL";
+       final static String channelPreferenceFormat = "CHANNEL-%d";
 
        /* voice preference name */
        final static String voicePreference = "VOICE";
 
        /* voice preference name */
        final static String voicePreference = "VOICE";
@@ -52,8 +52,8 @@ class AltosPreferences {
        /* Log directory */
        static File logdir;
 
        /* Log directory */
        static File logdir;
 
-       /* Telemetry channel */
-       static int channel;
+       /* Channel (map serial to channel) */
+       static Hashtable<Integer, Integer> channels;
 
        /* Voice preference */
        static boolean voice;
 
        /* Voice preference */
        static boolean voice;
@@ -80,7 +80,7 @@ class AltosPreferences {
                                logdir.mkdirs();
                }
 
                                logdir.mkdirs();
                }
 
-               channel = preferences.getInt(channelPreference, 0);
+               channels = new Hashtable<Integer,Integer>();
 
                voice = preferences.getBoolean(voicePreference, true);
 
 
                voice = preferences.getBoolean(voicePreference, true);
 
@@ -151,15 +151,19 @@ class AltosPreferences {
                return logdir;
        }
 
                return logdir;
        }
 
-       public static void set_channel(int new_channel) {
-               channel = new_channel;
+       public static void set_channel(int serial, int new_channel) {
+               channels.put(serial, new_channel);
                synchronized (preferences) {
                synchronized (preferences) {
-                       preferences.putInt(channelPreference, channel);
+                       preferences.putInt(String.format(channelPreferenceFormat, serial), new_channel);
                        flush_preferences();
                }
        }
 
                        flush_preferences();
                }
        }
 
-       public static int channel() {
+       public static int channel(int serial) {
+               if (channels.containsKey(serial))
+                       return channels.get(serial);
+               int channel = preferences.getInt(String.format(channelPreferenceFormat, serial), 0);
+               channels.put(serial, channel);
                return channel;
        }
 
                return channel;
        }
 
diff --git a/ao-tools/altosui/AltosReplayReader.java b/ao-tools/altosui/AltosReplayReader.java
new file mode 100644 (file)
index 0000000..4e5e1d9
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2010 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.awt.*;
+import java.awt.event.*;
+import javax.swing.*;
+import javax.swing.filechooser.FileNameExtensionFilter;
+import javax.swing.table.*;
+import java.io.*;
+import java.util.*;
+import java.text.*;
+import java.util.prefs.*;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/*
+ * Open an existing telemetry file and replay it in realtime
+ */
+
+public class AltosReplayReader extends AltosFlightReader {
+       Iterator<AltosRecord>   iterator;
+
+       public AltosRecord read() {
+               if (iterator.hasNext())
+                       return iterator.next();
+               return null;
+       }
+
+       public void close (boolean interrupted) {
+       }
+
+       void update(AltosState state) throws InterruptedException {
+               /* Make it run in realtime after the rocket leaves the pad */
+               if (state.state > Altos.ao_flight_pad)
+                       Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
+       }
+
+       public AltosReplayReader(Iterator<AltosRecord> in_iterator, String in_name) {
+               iterator = in_iterator;
+               name = in_name;
+       }
+}
diff --git a/ao-tools/altosui/AltosReplayThread.java b/ao-tools/altosui/AltosReplayThread.java
deleted file mode 100644 (file)
index b418160..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright © 2010 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.awt.*;
-import java.awt.event.*;
-import javax.swing.*;
-import javax.swing.filechooser.FileNameExtensionFilter;
-import javax.swing.table.*;
-import java.io.*;
-import java.util.*;
-import java.text.*;
-import java.util.prefs.*;
-import java.util.concurrent.LinkedBlockingQueue;
-
-import altosui.Altos;
-import altosui.AltosSerial;
-import altosui.AltosSerialMonitor;
-import altosui.AltosRecord;
-import altosui.AltosTelemetry;
-import altosui.AltosState;
-import altosui.AltosDeviceDialog;
-import altosui.AltosPreferences;
-import altosui.AltosLog;
-import altosui.AltosVoice;
-import altosui.AltosFlightInfoTableModel;
-import altosui.AltosChannelMenu;
-import altosui.AltosFlashUI;
-import altosui.AltosLogfileChooser;
-import altosui.AltosCSVUI;
-import altosui.AltosLine;
-import altosui.AltosStatusTable;
-import altosui.AltosInfoTable;
-import altosui.AltosDisplayThread;
-
-/*
- * Open an existing telemetry file and replay it in realtime
- */
-
-public class AltosReplayThread extends AltosDisplayThread {
-       Iterator<AltosRecord>   iterator;
-       String                  name;
-
-       public AltosRecord read() {
-               if (iterator.hasNext())
-                       return iterator.next();
-               return null;
-       }
-
-       public void close (boolean interrupted) {
-               if (!interrupted)
-                       report();
-       }
-
-       void update(AltosState state) throws InterruptedException {
-               /* Make it run in realtime after the rocket leaves the pad */
-               if (state.state > Altos.ao_flight_pad)
-                       Thread.sleep((int) (Math.min(state.time_change,10) * 1000));
-       }
-
-       public AltosReplayThread(Frame parent, Iterator<AltosRecord> in_iterator,
-                                String in_name, AltosVoice voice,
-                                AltosStatusTable status, AltosInfoTable info) {
-               super(parent, voice, status, info);
-               iterator = in_iterator;
-               name = in_name;
-       }
-}
index a1fc4371c8a805b2175f6175c8111d4dcd567a3f..f65e44d6eb1dac84653b5f325d04f66d2e4cae98 100644 (file)
@@ -193,6 +193,8 @@ public class AltosSerial implements Runnable {
                print("~\nE 0\n");
                flush_output();
                set_monitor(monitor_mode);
                print("~\nE 0\n");
                flush_output();
                set_monitor(monitor_mode);
+               set_channel(AltosPreferences.channel());
+               set_callsign(AltosPreferences.callsign());
        }
 
        public void set_channel(int channel) {
        }
 
        public void set_channel(int channel) {
index 3965a57d0e6c26930ade10b71063ea5559e9d53b..0d3a5d147519601fe44dba38354da97afeeb659e 100644 (file)
@@ -34,14 +34,11 @@ import altosui.AltosFlightInfoTableModel;
 public class AltosStatusTable extends JTable {
        private AltosFlightStatusTableModel flightStatusModel;
 
 public class AltosStatusTable extends JTable {
        private AltosFlightStatusTableModel flightStatusModel;
 
-       JFrame  frame;
-
        private Font statusFont = new Font("SansSerif", Font.BOLD, 24);
 
        private Font statusFont = new Font("SansSerif", Font.BOLD, 24);
 
-       public AltosStatusTable(JFrame in_frame) {
+       public AltosStatusTable() {
                super((TableModel) new AltosFlightStatusTableModel());
                flightStatusModel = (AltosFlightStatusTableModel) getModel();
                super((TableModel) new AltosFlightStatusTableModel());
                flightStatusModel = (AltosFlightStatusTableModel) getModel();
-               frame = in_frame;
 
                setFont(statusFont);
 
 
                setFont(statusFont);
 
diff --git a/ao-tools/altosui/AltosTelemetryReader.java b/ao-tools/altosui/AltosTelemetryReader.java
new file mode 100644 (file)
index 0000000..0b5509e
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2010 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.text.*;
+import java.io.*;
+import java.util.concurrent.*;
+
+class AltosTelemetryReader extends AltosFlightReader {
+       AltosDevice     device;
+       AltosSerial     serial;
+       AltosLog        log;
+
+       LinkedBlockingQueue<AltosLine> telem;
+
+       AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException {
+               AltosLine l = telem.take();
+               if (l.line == null)
+                       throw new IOException("IO error");
+               return new AltosTelemetry(l.line);
+       }
+
+       void close(boolean interrupted) {
+               serial.remove_monitor(telem);
+               log.close();
+               serial.close();
+       }
+
+       void set_channel(int channel) {
+               serial.set_channel(channel);
+       }
+
+       void set_callsign(String callsign) {
+               serial.set_callsign(callsign);
+       }
+
+       public AltosTelemetryReader (AltosDevice in_device) throws FileNotFoundException, IOException {
+               device = in_device;
+               serial = new AltosSerial();
+               log = new AltosLog(serial);
+               name = device.getPath();
+
+               telem = new LinkedBlockingQueue<AltosLine>();
+               serial.add_monitor(telem);
+       }
+}
index 28ed42fbe4f89848db63fcaa2d11c46cb82ef59e..e1bbee307835521797f212d1731db6e30961968c 100644 (file)
@@ -39,7 +39,6 @@ import altosui.AltosPreferences;
 import altosui.AltosLog;
 import altosui.AltosVoice;
 import altosui.AltosFlightInfoTableModel;
 import altosui.AltosLog;
 import altosui.AltosVoice;
 import altosui.AltosFlightInfoTableModel;
-import altosui.AltosChannelMenu;
 import altosui.AltosFlashUI;
 import altosui.AltosLogfileChooser;
 import altosui.AltosCSVUI;
 import altosui.AltosFlashUI;
 import altosui.AltosLogfileChooser;
 import altosui.AltosCSVUI;
@@ -51,14 +50,6 @@ import altosui.AltosDisplayThread;
 import libaltosJNI.*;
 
 public class AltosUI extends JFrame {
 import libaltosJNI.*;
 
 public class AltosUI extends JFrame {
-       private int channel = -1;
-
-       private AltosStatusTable flightStatus;
-       private AltosInfoTable flightInfo;
-       private AltosSerial serial_line;
-       private AltosLog altos_log;
-       private Box vbox;
-
        public AltosVoice voice = new AltosVoice();
 
        public static boolean load_library(Frame frame) {
        public AltosVoice voice = new AltosVoice();
 
        public static boolean load_library(Frame frame) {
@@ -73,38 +64,41 @@ public class AltosUI extends JFrame {
                return true;
        }
 
                return true;
        }
 
+       void telemetry_window(AltosDevice device) {
+               try {
+                       AltosFlightReader reader = new AltosTelemetryReader(device);
+                       if (reader != null)
+                               new AltosFlightUI(voice, reader, device.getSerial());
+               } catch (FileNotFoundException ee) {
+                       JOptionPane.showMessageDialog(AltosUI.this,
+                                                     String.format("Cannot open device \"%s\"",
+                                                                   device.getPath()),
+                                                     "Cannot open target device",
+                                                     JOptionPane.ERROR_MESSAGE);
+               } catch (IOException ee) {
+                       JOptionPane.showMessageDialog(AltosUI.this,
+                                                     device.getPath(),
+                                                     "Unkonwn I/O error",
+                                                     JOptionPane.ERROR_MESSAGE);
+               }
+       }
+
        public AltosUI() {
 
                load_library(null);
 
        public AltosUI() {
 
                load_library(null);
 
-               String[] statusNames = { "Height (m)", "State", "RSSI (dBm)", "Speed (m/s)" };
-               Object[][] statusData = { { "0", "pad", "-50", "0" } };
-
                java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
                if (imgURL != null)
                        setIconImage(new ImageIcon(imgURL).getImage());
 
                AltosPreferences.init(this);
 
                java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
                if (imgURL != null)
                        setIconImage(new ImageIcon(imgURL).getImage());
 
                AltosPreferences.init(this);
 
-               vbox = Box.createVerticalBox();
-               this.add(vbox);
-
-               flightStatus = new AltosStatusTable(this);
-
-               vbox.add(flightStatus);
-
-               flightInfo = new AltosInfoTable();
-               vbox.add(flightInfo.box());
-
                setTitle("AltOS");
 
                createMenu();
 
                setTitle("AltOS");
 
                createMenu();
 
-               serial_line = new AltosSerial();
-               altos_log = new AltosLog(serial_line);
                int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
                int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
-               this.setSize(new Dimension (flightInfo.width(),
-                                           flightStatus.height() + flightInfo.height()));
+               this.setSize(new Dimension (300, 100));
                this.validate();
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                addWindowListener(new WindowAdapter() {
                this.validate();
                setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                addWindowListener(new WindowAdapter() {
@@ -113,63 +107,14 @@ public class AltosUI extends JFrame {
                                System.exit(0);
                        }
                });
                                System.exit(0);
                        }
                });
-               voice.speak("Rocket flight monitor ready.");
-       }
-
-       class DeviceThread extends AltosDisplayThread {
-               AltosSerial     serial;
-               LinkedBlockingQueue<AltosLine> telem;
-
-               AltosRecord read() throws InterruptedException, ParseException, AltosCRCException, IOException {
-                       AltosLine l = telem.take();
-                       if (l.line == null)
-                               throw new IOException("IO error");
-                       return new AltosTelemetry(l.line);
-               }
-
-               void close(boolean interrupted) {
-                       serial.close();
-                       serial.remove_monitor(telem);
-               }
-
-               public DeviceThread(AltosSerial s, String in_name, AltosVoice voice, AltosStatusTable status, AltosInfoTable info) {
-                       super(AltosUI.this, voice, status, info);
-                       serial = s;
-                       telem = new LinkedBlockingQueue<AltosLine>();
-                       serial.add_monitor(telem);
-                       name = in_name;
-               }
        }
 
        private void ConnectToDevice() {
                AltosDevice     device = AltosDeviceDialog.show(AltosUI.this,
                                                                AltosDevice.product_basestation);
 
        }
 
        private void ConnectToDevice() {
                AltosDevice     device = AltosDeviceDialog.show(AltosUI.this,
                                                                AltosDevice.product_basestation);
 
-               if (device != null) {
-                       try {
-                               stop_display();
-                               serial_line.open(device);
-                               DeviceThread thread = new DeviceThread(serial_line, device.getPath(), voice, flightStatus, flightInfo);
-                               serial_line.set_channel(AltosPreferences.channel());
-                               serial_line.set_callsign(AltosPreferences.callsign());
-                               run_display(thread);
-                       } catch (FileNotFoundException ee) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             String.format("Cannot open device \"%s\"",
-                                                                           device.getPath()),
-                                                             "Cannot open target device",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       } catch (IOException ee) {
-                               JOptionPane.showMessageDialog(AltosUI.this,
-                                                             device.getPath(),
-                                                             "Unkonwn I/O error",
-                                                             JOptionPane.ERROR_MESSAGE);
-                       }
-               }
-       }
-
-       void DisconnectFromDevice () {
-               stop_display();
+               if (device != null)
+                       telemetry_window(device);
        }
 
        void ConfigureCallsign() {
        }
 
        void ConfigureCallsign() {
@@ -177,11 +122,8 @@ public class AltosUI extends JFrame {
                result = JOptionPane.showInputDialog(AltosUI.this,
                                                     "Configure Callsign",
                                                     AltosPreferences.callsign());
                result = JOptionPane.showInputDialog(AltosUI.this,
                                                     "Configure Callsign",
                                                     AltosPreferences.callsign());
-               if (result != null) {
+               if (result != null)
                        AltosPreferences.set_callsign(result);
                        AltosPreferences.set_callsign(result);
-                       if (serial_line != null)
-                               serial_line.set_callsign(result);
-               }
        }
 
        void ConfigureTeleMetrum() {
        }
 
        void ConfigureTeleMetrum() {
@@ -192,25 +134,6 @@ public class AltosUI extends JFrame {
                new AltosFlashUI(AltosUI.this);
        }
 
                new AltosFlashUI(AltosUI.this);
        }
 
-
-       Thread          display_thread;
-
-       private void stop_display() {
-               if (display_thread != null && display_thread.isAlive()) {
-                       display_thread.interrupt();
-                       try {
-                               display_thread.join();
-                       } catch (InterruptedException ie) {}
-               }
-               display_thread = null;
-       }
-
-       private void run_display(Thread thread) {
-               stop_display();
-               display_thread = thread;
-               display_thread.start();
-       }
-
        /*
         * Replay a flight from telemetry data
         */
        /*
         * Replay a flight from telemetry data
         */
@@ -218,12 +141,11 @@ public class AltosUI extends JFrame {
                AltosLogfileChooser chooser = new AltosLogfileChooser(
                        AltosUI.this);
                AltosRecordIterable iterable = chooser.runDialog();
                AltosLogfileChooser chooser = new AltosLogfileChooser(
                        AltosUI.this);
                AltosRecordIterable iterable = chooser.runDialog();
-               if (iterable != null)
-                       run_display(new AltosReplayThread(this, iterable.iterator(),
-                                                         chooser.filename(),
-                                                         voice,
-                                                         flightStatus,
-                                                         flightInfo));
+               if (iterable != null) {
+                       AltosFlightReader reader = new AltosReplayReader(iterable.iterator(),
+                                                                        chooser.filename());
+                       new AltosFlightUI(voice, reader);
+               }
        }
 
        /* Connect to TeleMetrum, either directly or through
        }
 
        /* Connect to TeleMetrum, either directly or through
@@ -278,7 +200,7 @@ public class AltosUI extends JFrame {
                                });
                        menu.add(item);
 
                                });
                        menu.add(item);
 
-                       item = new JMenuItem("Flash Image",KeyEvent.VK_F);
+                       item = new JMenuItem("Flash Image",KeyEvent.VK_I);
                        item.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                FlashImage();
                        item.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                FlashImage();
@@ -286,7 +208,7 @@ public class AltosUI extends JFrame {
                                });
                        menu.add(item);
 
                                });
                        menu.add(item);
 
-                       item = new JMenuItem("Export Data",KeyEvent.VK_F);
+                       item = new JMenuItem("Export Data",KeyEvent.VK_E);
                        item.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                ExportData();
                        item.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                ExportData();
@@ -294,7 +216,7 @@ public class AltosUI extends JFrame {
                                });
                        menu.add(item);
 
                                });
                        menu.add(item);
 
-                       item = new JMenuItem("Graph Data",KeyEvent.VK_F);
+                       item = new JMenuItem("Graph Data",KeyEvent.VK_G);
                        item.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                GraphData();
                        item.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                GraphData();
@@ -307,6 +229,7 @@ public class AltosUI extends JFrame {
                                                                   ActionEvent.CTRL_MASK));
                        item.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
                                                                   ActionEvent.CTRL_MASK));
                        item.addActionListener(new ActionListener() {
                                        public void actionPerformed(ActionEvent e) {
+                                               System.out.printf("exiting\n");
                                                System.exit(0);
                                        }
                                });
                                                System.exit(0);
                                        }
                                });
@@ -314,7 +237,7 @@ public class AltosUI extends JFrame {
                }
 
                // Device menu
                }
 
                // Device menu
-               {
+               if (false) {
                        menu = new JMenu("Device");
                        menu.setMnemonic(KeyEvent.VK_D);
                        menubar.add(menu);
                        menu = new JMenu("Device");
                        menu.setMnemonic(KeyEvent.VK_D);
                        menubar.add(menu);
@@ -327,14 +250,6 @@ public class AltosUI extends JFrame {
                                });
                        menu.add(item);
 
                                });
                        menu.add(item);
 
-                       item = new JMenuItem("Disconnect from Device",KeyEvent.VK_D);
-                       item.addActionListener(new ActionListener() {
-                                       public void actionPerformed(ActionEvent e) {
-                                               DisconnectFromDevice();
-                                       }
-                               });
-                       menu.add(item);
-
                        menu.addSeparator();
 
                        item = new JMenuItem("Set Callsign",KeyEvent.VK_S);
                        menu.addSeparator();
 
                        item = new JMenuItem("Set Callsign",KeyEvent.VK_S);
@@ -403,23 +318,7 @@ public class AltosUI extends JFrame {
                                });
                        menu.add(item);
                }
                                });
                        menu.add(item);
                }
-
-               // Channel menu
-               {
-                       menu = new AltosChannelMenu(AltosPreferences.channel());
-                       menu.addActionListener(new ActionListener() {
-                                               public void actionPerformed(ActionEvent e) {
-                                                       int new_channel = Integer.parseInt(e.getActionCommand());
-                                                       AltosPreferences.set_channel(new_channel);
-                                                       serial_line.set_channel(new_channel);
-                                               }
-                               });
-                       menu.setMnemonic(KeyEvent.VK_C);
-                       menubar.add(menu);
-               }
-
                this.setJMenuBar(menubar);
                this.setJMenuBar(menubar);
-
        }
 
        static AltosRecordIterable open_logfile(String filename) {
        }
 
        static AltosRecordIterable open_logfile(String filename) {
@@ -510,6 +409,10 @@ public class AltosUI extends JFrame {
                } else {
                        AltosUI altosui = new AltosUI();
                        altosui.setVisible(true);
                } else {
                        AltosUI altosui = new AltosUI();
                        altosui.setVisible(true);
+
+                       AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation);
+                       for (int i = 0; i < devices.length; i++)
+                               altosui.telemetry_window(devices[i]);
                }
        }
 }
                }
        }
 }
index 2f4ed6d83e4c45e82b226f5f0fe01f9a13acc475..2322b93f109335fbbdc0b5210e7297e214632363 100644 (file)
@@ -29,7 +29,9 @@ altosui_JAVA = \
        AltosFlash.java \
        AltosFlashUI.java \
        AltosFlightInfoTableModel.java \
        AltosFlash.java \
        AltosFlashUI.java \
        AltosFlightInfoTableModel.java \
+       AltosFlightReader.java \
        AltosFlightStatusTableModel.java \
        AltosFlightStatusTableModel.java \
+       AltosFlightUI.java \
        AltosGPS.java \
        AltosGreatCircle.java \
        AltosHexfile.java \
        AltosGPS.java \
        AltosGreatCircle.java \
        AltosHexfile.java \
@@ -44,7 +46,8 @@ altosui_JAVA = \
        AltosReader.java \
        AltosRecord.java \
        AltosRecordIterable.java \
        AltosReader.java \
        AltosRecord.java \
        AltosRecordIterable.java \
-       AltosReplayThread.java \
+       AltosTelemetryReader.java \
+       AltosReplayReader.java \
        AltosRomconfig.java \
        AltosRomconfigUI.java \
        AltosSerial.java \
        AltosRomconfig.java \
        AltosRomconfigUI.java \
        AltosSerial.java \