2 * Copyright © 2010 Keith Packard <keithp@keithp.com>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 2 of the License.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public License along
14 * with this program; if not, write to the Free Software Foundation, Inc.,
15 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 import java.awt.event.*;
23 import javax.swing.filechooser.FileNameExtensionFilter;
24 import javax.swing.table.*;
28 import java.util.prefs.*;
29 import java.util.concurrent.LinkedBlockingQueue;
32 import altosui.AltosSerial;
33 import altosui.AltosSerialMonitor;
34 import altosui.AltosRecord;
35 import altosui.AltosTelemetry;
36 import altosui.AltosState;
37 import altosui.AltosDeviceDialog;
38 import altosui.AltosPreferences;
39 import altosui.AltosLog;
40 import altosui.AltosVoice;
41 import altosui.AltosFlightInfoTableModel;
42 import altosui.AltosFlashUI;
43 import altosui.AltosLogfileChooser;
44 import altosui.AltosCSVUI;
45 import altosui.AltosLine;
46 import altosui.AltosStatusTable;
47 import altosui.AltosInfoTable;
48 import altosui.AltosDisplayThread;
52 public class AltosUI extends JFrame {
53 public AltosVoice voice = new AltosVoice();
55 public static boolean load_library(Frame frame) {
56 if (!AltosDevice.load_library()) {
57 JOptionPane.showMessageDialog(frame,
58 String.format("No AltOS library in \"%s\"",
59 System.getProperty("java.library.path","<undefined>")),
60 "Cannot load device access library",
61 JOptionPane.ERROR_MESSAGE);
67 void telemetry_window(AltosDevice device) {
69 AltosFlightReader reader = new AltosTelemetryReader(device);
71 new AltosFlightUI(voice, reader, device.getSerial());
72 } catch (FileNotFoundException ee) {
73 JOptionPane.showMessageDialog(AltosUI.this,
74 String.format("Cannot open device \"%s\"",
76 "Cannot open target device",
77 JOptionPane.ERROR_MESSAGE);
78 } catch (IOException ee) {
79 JOptionPane.showMessageDialog(AltosUI.this,
82 JOptionPane.ERROR_MESSAGE);
90 java.net.URL imgURL = AltosUI.class.getResource("/altus-metrum-16x16.jpg");
92 setIconImage(new ImageIcon(imgURL).getImage());
94 AltosPreferences.init(this);
100 int dpi = Toolkit.getDefaultToolkit().getScreenResolution();
101 this.setSize(new Dimension (300, 100));
103 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
104 addWindowListener(new WindowAdapter() {
106 public void windowClosing(WindowEvent e) {
112 private void ConnectToDevice() {
113 AltosDevice device = AltosDeviceDialog.show(AltosUI.this,
114 AltosDevice.product_basestation);
117 telemetry_window(device);
120 void ConfigureCallsign() {
122 result = JOptionPane.showInputDialog(AltosUI.this,
123 "Configure Callsign",
124 AltosPreferences.callsign());
126 AltosPreferences.set_callsign(result);
129 void ConfigureTeleMetrum() {
130 new AltosConfig(AltosUI.this);
134 new AltosFlashUI(AltosUI.this);
138 * Replay a flight from telemetry data
140 private void Replay() {
141 AltosLogfileChooser chooser = new AltosLogfileChooser(
143 AltosRecordIterable iterable = chooser.runDialog();
144 if (iterable != null) {
145 AltosFlightReader reader = new AltosReplayReader(iterable.iterator(),
147 new AltosFlightUI(voice, reader);
151 /* Connect to TeleMetrum, either directly or through
152 * a TeleDongle over the packet link
154 private void SaveFlightData() {
155 new AltosEepromDownload(AltosUI.this);
158 /* Load a flight log file and write out a CSV file containing
159 * all of the data in standard units
162 private void ExportData() {
163 new AltosCSVUI(AltosUI.this);
166 /* Load a flight log CSV file and display a pretty graph.
169 private void GraphData() {
170 new AltosGraphUI(AltosUI.this);
173 /* Create the AltosUI menus
175 private void createMenu() {
176 JMenuBar menubar = new JMenuBar();
179 JRadioButtonMenuItem radioitem;
183 menu = new JMenu("File");
184 menu.setMnemonic(KeyEvent.VK_F);
187 item = new JMenuItem("Replay File",KeyEvent.VK_R);
188 item.addActionListener(new ActionListener() {
189 public void actionPerformed(ActionEvent e) {
195 item = new JMenuItem("Save Flight Data",KeyEvent.VK_S);
196 item.addActionListener(new ActionListener() {
197 public void actionPerformed(ActionEvent e) {
203 item = new JMenuItem("Flash Image",KeyEvent.VK_I);
204 item.addActionListener(new ActionListener() {
205 public void actionPerformed(ActionEvent e) {
211 item = new JMenuItem("Export Data",KeyEvent.VK_E);
212 item.addActionListener(new ActionListener() {
213 public void actionPerformed(ActionEvent e) {
219 item = new JMenuItem("Graph Data",KeyEvent.VK_G);
220 item.addActionListener(new ActionListener() {
221 public void actionPerformed(ActionEvent e) {
227 item = new JMenuItem("Quit",KeyEvent.VK_Q);
228 item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q,
229 ActionEvent.CTRL_MASK));
230 item.addActionListener(new ActionListener() {
231 public void actionPerformed(ActionEvent e) {
232 System.out.printf("exiting\n");
241 menu = new JMenu("Device");
242 menu.setMnemonic(KeyEvent.VK_D);
245 item = new JMenuItem("Connect to Device",KeyEvent.VK_C);
246 item.addActionListener(new ActionListener() {
247 public void actionPerformed(ActionEvent e) {
255 item = new JMenuItem("Set Callsign",KeyEvent.VK_S);
256 item.addActionListener(new ActionListener() {
257 public void actionPerformed(ActionEvent e) {
264 item = new JMenuItem("Configure TeleMetrum device",KeyEvent.VK_T);
265 item.addActionListener(new ActionListener() {
266 public void actionPerformed(ActionEvent e) {
267 ConfigureTeleMetrum();
275 menu = new JMenu("Log");
276 menu.setMnemonic(KeyEvent.VK_L);
279 item = new JMenuItem("New Log",KeyEvent.VK_N);
280 item.addActionListener(new ActionListener() {
281 public void actionPerformed(ActionEvent e) {
286 item = new JMenuItem("Configure Log",KeyEvent.VK_C);
287 item.addActionListener(new ActionListener() {
288 public void actionPerformed(ActionEvent e) {
289 AltosPreferences.ConfigureLog();
296 menu = new JMenu("Voice", true);
297 menu.setMnemonic(KeyEvent.VK_V);
300 radioitem = new JRadioButtonMenuItem("Enable Voice", AltosPreferences.voice());
301 radioitem.addActionListener(new ActionListener() {
302 public void actionPerformed(ActionEvent e) {
303 JRadioButtonMenuItem item = (JRadioButtonMenuItem) e.getSource();
304 boolean enabled = item.isSelected();
305 AltosPreferences.set_voice(enabled);
307 voice.speak_always("Enable voice.");
309 voice.speak_always("Disable voice.");
313 item = new JMenuItem("Test Voice",KeyEvent.VK_T);
314 item.addActionListener(new ActionListener() {
315 public void actionPerformed(ActionEvent e) {
316 voice.speak("That's one small step for man; one giant leap for mankind.");
321 this.setJMenuBar(menubar);
324 static AltosRecordIterable open_logfile(String filename) {
325 File file = new File (filename);
329 in = new FileInputStream(file);
330 if (filename.endsWith("eeprom"))
331 return new AltosEepromIterable(in);
333 return new AltosTelemetryIterable(in);
334 } catch (FileNotFoundException fe) {
335 System.out.printf("Cannot open '%s'\n", filename);
340 static AltosWriter open_csv(String filename) {
341 File file = new File (filename);
343 return new AltosCSV(file);
344 } catch (FileNotFoundException fe) {
345 System.out.printf("Cannot open '%s'\n", filename);
350 static AltosWriter open_kml(String filename) {
351 File file = new File (filename);
353 return new AltosKML(file);
354 } catch (FileNotFoundException fe) {
355 System.out.printf("Cannot open '%s'\n", filename);
360 static final int process_csv = 1;
361 static final int process_kml = 2;
363 static void process_file(String input, int process) {
364 AltosRecordIterable iterable = open_logfile(input);
365 if (iterable == null)
368 process = process_csv;
369 if ((process & process_csv) != 0) {
370 String output = Altos.replace_extension(input,".csv");
371 System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
372 if (input.equals(output)) {
373 System.out.printf("Not processing '%s'\n", input);
375 AltosWriter writer = open_csv(output);
376 if (writer != null) {
377 writer.write(iterable);
382 if ((process & process_kml) != 0) {
383 String output = Altos.replace_extension(input,".kml");
384 System.out.printf("Processing \"%s\" to \"%s\"\n", input, output);
385 if (input.equals(output)) {
386 System.out.printf("Not processing '%s'\n", input);
388 AltosWriter writer = open_kml(output);
391 writer.write(iterable);
397 public static void main(final String[] args) {
399 /* Handle batch-mode */
400 if (args.length > 0) {
401 for (int i = 0; i < args.length; i++) {
402 if (args[i].equals("--kml"))
403 process |= process_kml;
404 else if (args[i].equals("--csv"))
405 process |= process_csv;
407 process_file(args[i], process);
410 AltosUI altosui = new AltosUI();
411 altosui.setVisible(true);
413 AltosDevice[] devices = AltosDevice.list(AltosDevice.product_basestation);
414 for (int i = 0; i < devices.length; i++)
415 altosui.telemetry_window(devices[i]);