altos/test: Adjust CRC error rate after FEC fix
[fw/altos] / micropeak / MicroPeak.java
1 /*
2  * Copyright © 2012 Keith Packard <keithp@keithp.com>
3  *
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; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  */
18
19 package org.altusmetrum.micropeak;
20
21 import java.awt.*;
22 import java.awt.event.*;
23 import javax.swing.*;
24 import java.io.*;
25 import java.util.concurrent.*;
26 import java.util.*;
27 import org.altusmetrum.altoslib_14.*;
28 import org.altusmetrum.altosuilib_14.*;
29
30 public class MicroPeak extends MicroFrame implements ActionListener, ItemListener, AltosFilterListener {
31
32         File            filename;
33         AltosGraph      graph;
34         AltosUIEnable   enable;
35         AltosFlightStatsTable   statsTable;
36         MicroRaw        raw;
37         MicroData       data;
38         Container       container;
39         JTabbedPane     pane;
40         JMenuBar        menu_bar;
41         static int      number_of_windows;
42
43         /* File menu */
44         final static String     open_command = "open";
45         final static String     save_command = "save";
46         final static String     export_command = "export";
47         final static String     preferences_command = "preferences";
48         final static String     close_command = "close";
49         final static String     exit_command = "exit";
50
51         static final String[][] file_menu_entries = new String[][] {
52                 { "Open",               open_command },
53                 { "Save a Copy",        save_command },
54                 { "Export Data",        export_command },
55                 { "Preferences",        preferences_command },
56                 { "Close",              close_command },
57                 { "Exit",               exit_command },
58         };
59
60         /* Download menu */
61         final static String     download_command = "download";
62         final static String     download_label = "Download";
63
64         MicroPeak SetData(MicroData data) {
65                 MicroPeak       mp = this;
66                 if (this.data != null) {
67                         mp = new MicroPeak();
68                         return mp.SetData(data);
69                 }
70                 this.data = data;
71                 if (data.flight_series == null)
72                         System.out.printf("no data in flight\n");
73                 if (data.flight_stats == null)
74                         System.out.printf("no stats in flight\n");
75                 graph.set_data(data.flight_stats, data.flight_series);
76                 statsTable.set_stats(data.flight_stats);
77                 raw.setData(data);
78                 setTitle(data.name);
79                 return this;
80         }
81
82         void SetName(String name) {
83                 graph.setName(name);
84                 setTitle(name);
85         }
86
87         private static MicroData ReadFile(File filename) throws IOException, FileNotFoundException {
88                 MicroData       data = null;
89                 FileInputStream fis = new FileInputStream(filename);
90                 try {
91                         data = new MicroData((InputStream) fis, filename.getName());
92                         AltosUIPreferences.set_last_logdir(filename);
93                 } catch (MicroData.NonHexcharException nhe) {
94                         data = null;
95                 } catch (MicroData.FileEndedException nhe) {
96                         data = null;
97                 } catch (InterruptedException ie) {
98                         data = null;
99                 } finally {
100                         fis.close();
101                 }
102                 return data;
103         }
104
105         private void OpenFile(File filename) {
106                 try {
107                         SetData(ReadFile(filename));
108                 } catch (FileNotFoundException fne) {
109                         JOptionPane.showMessageDialog(this,
110                                                       fne.getMessage(),
111                                                       "Cannot open file",
112                                                       JOptionPane.ERROR_MESSAGE);
113                 } catch (IOException ioe) {
114                         JOptionPane.showMessageDialog(this,
115                                                       ioe.getMessage(),
116                                                       "File Read Error",
117                                                       JOptionPane.ERROR_MESSAGE);
118                 }
119         }
120
121         private void SelectFile() {
122                 MicroFileChooser        chooser = new MicroFileChooser(this);
123                 File                    file = chooser.runDialog();
124
125                 if (file != null)
126                         OpenFile(file);
127         }
128
129         private void Preferences() {
130                 new AltosUIConfigure(this);
131         }
132
133         private void DownloadData() {
134                 AltosDevice     device = MicroDeviceDialog.show(this);
135
136                 if (device != null)
137                         new MicroDownload(this, device);
138         }
139
140         private void no_data() {
141                         JOptionPane.showMessageDialog(this,
142                                                       "No data available",
143                                                       "No data",
144                                                       JOptionPane.INFORMATION_MESSAGE);
145         }
146
147         private void Save() {
148                 if (data == null) {
149                         no_data();
150                         return;
151                 }
152                 MicroSave       save = new MicroSave (this, data);
153                 if (save.runDialog())
154                         SetName(data.name);
155         }
156
157         private void Export() {
158                 if (data == null) {
159                         no_data();
160                         return;
161                 }
162                 MicroExport     export = new MicroExport (this, data);
163                 export.runDialog();
164         }
165
166         private static void CommandGraph(File file) {
167                 MicroPeak m = new MicroPeak();
168                 m.OpenFile(file);
169         }
170
171         private static void CommandExport(File file) {
172                 try {
173                         MicroData d = ReadFile(file);
174                         if (d != null) {
175                                 File    csv = new File(AltosLib.replace_extension(file.getPath(), ".csv"));
176                                 try {
177                                         System.out.printf ("Export \"%s\" to \"%s\"\n", file.getPath(), csv.getPath());
178                                         MicroExport.export(csv, d);
179                                 } catch (FileNotFoundException fe) {
180                                         System.err.printf("Cannot create file \"%s\" (%s)\n", csv.getName(), fe.getMessage());
181                                 } catch (IOException ie) {
182                                         System.err.printf("Cannot write file \"%s\" (%s)\n", csv.getName(), ie.getMessage());
183                                 }
184                         }
185                 } catch (IOException ie) {
186                         System.err.printf("Cannot read file \"%s\" (%s)\n", file.getName(), ie.getMessage());
187                 }
188         }
189
190         private void Close() {
191                 setVisible(false);
192                 dispose();
193                 --number_of_windows;
194                 if (number_of_windows == 0)
195                         System.exit(0);
196         }
197
198         public void actionPerformed(ActionEvent ev) {
199                 if (open_command.equals(ev.getActionCommand()))
200                         SelectFile();
201                 else if (save_command.equals(ev.getActionCommand()))
202                         Save();
203                 else if (export_command.equals(ev.getActionCommand()))
204                         Export();
205                 else if (preferences_command.equals(ev.getActionCommand()))
206                         Preferences();
207                 else if (close_command.equals(ev.getActionCommand()))
208                         Close();
209                 else if (exit_command.equals(ev.getActionCommand()))
210                         System.exit(0);
211                 else if (download_command.equals(ev.getActionCommand()))
212                         DownloadData();
213         }
214
215         public void itemStateChanged(ItemEvent e) {
216         }
217
218         /* OSXAdapter interfaces */
219         public void macosx_file_handler(String path) {
220                 CommandGraph(new File(path));
221         }
222
223         public void macosx_quit_handler() {
224                 System.exit(0);
225         }
226
227         public void macosx_preferences_handler() {
228                 Preferences();
229         }
230
231         public void filter_changed(double speed_filter, double accel_filter) {
232                 data.flight_series.set_filter(speed_filter, accel_filter);
233                 graph.filter_changed();
234                 data.flight_stats = new AltosFlightStats(data.flight_series);
235                 statsTable.filter_changed(data.flight_stats);
236         }
237
238         public double speed_filter() {
239                 if (data != null && data.flight_series != null)
240                         return data.flight_series.speed_filter_width;
241                 return 4.0;
242         }
243
244         public double accel_filter() {
245                 if (data != null && data.flight_series != null)
246                         return data.flight_series.accel_filter_width;
247                 return 1.0;
248         }
249
250         private void add_menu(JMenu menu, String label, String action) {
251                 JMenuItem       item = new JMenuItem(label);
252                 menu.add(item);
253                 item.addActionListener(this);
254                 item.setActionCommand(action);
255         }
256
257
258         private JMenu make_menu(String label, String[][] items) {
259                 JMenu   menu = new JMenu(label);
260                 for (int i = 0; i < items.length; i++) {
261                         if (MAC_OS_X) {
262                                 if (items[i][1].equals("exit"))
263                                         continue;
264                                 if (items[i][1].equals("preferences"))
265                                         continue;
266                         }
267                         add_menu(menu, items[i][0], items[i][1]);
268                 }
269                 menu_bar.add(menu);
270                 return menu;
271         }
272
273         public MicroPeak() {
274
275                 ++number_of_windows;
276
277                 register_for_macosx_events();
278
279                 AltosUIPreferences.set_component(this);
280
281                 container = getContentPane();
282                 pane = new JTabbedPane();
283
284                 setTitle("MicroPeak");
285
286                 menu_bar = new JMenuBar();
287                 setJMenuBar(menu_bar);
288
289                 JMenu file_menu = make_menu("File", file_menu_entries);
290
291                 JButton download_button = new JButton (download_label);
292                 download_button.setActionCommand(download_command);
293                 download_button.addActionListener(this);
294                 menu_bar.add(download_button);
295
296                 setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
297                 addWindowListener(new WindowAdapter() {
298                         @Override
299                         public void windowClosing(WindowEvent e) {
300                                 statsTable.tell_closing();
301                                 raw.tell_closing();
302                                 Close();
303                         }
304                 });
305
306                 enable = new AltosUIEnable(this);
307
308                 graph = new AltosGraph(enable);
309                 statsTable = new AltosFlightStatsTable();
310                 raw = new MicroRaw();
311                 pane.add(graph.panel, "Graph");
312                 pane.add(enable, "Configure Graph");
313                 pane.add(statsTable, "Statistics");
314                 JScrollPane scroll = new JScrollPane(raw);
315                 pane.add(scroll, "Raw Data");
316                 pane.doLayout();
317                 pane.validate();
318                 container.add(pane);
319                 container.doLayout();
320                 container.validate();
321                 doLayout();
322                 validate();
323                 pack();
324                 setVisible(true);
325         }
326
327         public static void help(int code) {
328                 System.out.printf("Usage: micropeak [OPTION] ... [FILE]...\n");
329                 System.out.printf("  Options:\n");
330                 System.out.printf("    --csv\tgenerate comma separated output for spreadsheets, etc\n");
331                 System.out.printf("    --graph\tgraph a flight\n");
332                 System.exit(code);
333         }
334
335         public static void main(final String[] args) {
336                 boolean opened = false;
337                 boolean graphing = true;
338
339                 try {
340                         UIManager.setLookAndFeel(AltosUIPreferences.look_and_feel());
341                 } catch (Exception e) {
342                 }
343
344                 for (int i = 0; i < args.length; i++) {
345                         if (args[i].equals("--help"))
346                                 help(0);
347                         else if (args[i].equals("--export"))
348                                 graphing = false;
349                         else if (args[i].equals("--graph"))
350                                 graphing = true;
351                         else if (args[i].startsWith("--"))
352                                 help(1);
353                         else {
354                                 File    file = new File(args[i]);
355                                 try {
356                                         if (graphing)
357                                                 CommandGraph(file);
358                                         else
359                                                 CommandExport(file);
360                                         opened = true;
361                                 } catch (Exception e) {
362                                         System.err.printf("Error processing \"%s\": %s %s\n",
363                                                           file.getName(), e.toString(), e.getMessage());
364                                         e.printStackTrace();
365                                 }
366                         }
367                 }
368                 if (!opened)
369                         new MicroPeak();
370         }
371 }