altosui: Call config UI from AltosConfigData directly
[fw/altos] / altosui / AltosConfig.java
1 /*
2  * Copyright © 2010 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; version 2 of the License.
7  *
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.
12  *
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.
16  */
17
18 package altosui;
19
20 import java.awt.event.*;
21 import javax.swing.*;
22 import java.io.*;
23 import java.util.concurrent.*;
24 import org.altusmetrum.AltosLib.*;
25 import java.text.*;
26
27 public class AltosConfig implements ActionListener {
28
29         class int_ref {
30                 int     value;
31
32                 public int get() {
33                         return value;
34                 }
35                 public void set(int i) {
36                         value = i;
37                 }
38                 public int_ref(int i) {
39                         value = i;
40                 }
41         }
42
43         class string_ref {
44                 String  value;
45
46                 public String get() {
47                         return value;
48                 }
49                 public void set(String i) {
50                         value = i;
51                 }
52                 public string_ref(String i) {
53                         value = i;
54                 }
55         }
56
57         JFrame          owner;
58         AltosDevice     device;
59         AltosSerial     serial_line;
60         boolean         remote;
61
62         AltosConfigData data;
63         AltosConfigUI   config_ui;
64         boolean         serial_started;
65         boolean         made_visible;
66
67         void start_serial() throws InterruptedException, TimeoutException {
68                 serial_started = true;
69                 if (remote)
70                         serial_line.start_remote();
71         }
72
73         void stop_serial() throws InterruptedException {
74                 if (!serial_started)
75                         return;
76                 serial_started = false;
77                 if (remote)
78                         serial_line.stop_remote();
79         }
80
81         void update_ui() {
82                 data.set_values(config_ui);
83                 config_ui.set_clean();
84                 if (!made_visible) {
85                         made_visible = true;
86                         config_ui.make_visible();
87                 }
88         }
89
90         int     pyro;
91
92         final static int        serial_mode_read = 0;
93         final static int        serial_mode_save = 1;
94         final static int        serial_mode_reboot = 2;
95
96         class SerialData implements Runnable {
97                 AltosConfig     config;
98                 int             serial_mode;
99
100                 void callback(String in_cmd) {
101                         final String cmd = in_cmd;
102                         Runnable r = new Runnable() {
103                                         public void run() {
104                                                 if (cmd.equals("abort")) {
105                                                         abort();
106                                                 } else if (cmd.equals("all finished")) {
107                                                         if (serial_line != null)
108                                                                 update_ui();
109                                                 }
110                                         }
111                                 };
112                         SwingUtilities.invokeLater(r);
113                 }
114
115                 void get_data() {
116                         data = null;
117                         try {
118                                 start_serial();
119                                 data = new AltosConfigData(config.serial_line);
120                         } catch (InterruptedException ie) {
121                         } catch (TimeoutException te) {
122                                 try {
123                                         stop_serial();
124                                         callback("abort");
125                                 } catch (InterruptedException ie) {
126                                 }
127                         } finally {
128                                 try {
129                                         stop_serial();
130                                 } catch (InterruptedException ie) {
131                                 }
132                         }
133                         callback("all finished");
134                 }
135
136                 void save_data() {
137                         try {
138                                 start_serial();
139                                 data.save(serial_line, remote);
140                                 if (remote)
141                                         AltosUIPreferences.set_frequency(device.getSerial(),
142                                                                          data.frequency());
143                         } catch (InterruptedException ie) {
144                         } catch (TimeoutException te) {
145                         } finally {
146                                 try {
147                                         stop_serial();
148                                 } catch (InterruptedException ie) {
149                                 }
150                         }
151                 }
152
153                 void reboot() {
154                         try {
155                                 start_serial();
156                                 serial_line.printf("r eboot\n");
157                                 serial_line.flush_output();
158                         } catch (InterruptedException ie) {
159                         } catch (TimeoutException te) {
160                         } finally {
161                                 try {
162                                         stop_serial();
163                                 } catch (InterruptedException ie) {
164                                 }
165                                 serial_line.close();
166                         }
167                 }
168
169                 public void run () {
170                         switch (serial_mode) {
171                         case serial_mode_save:
172                                 save_data();
173                                 /* fall through ... */
174                         case serial_mode_read:
175                                 get_data();
176                                 break;
177                         case serial_mode_reboot:
178                                 reboot();
179                                 break;
180                         }
181                 }
182
183                 public SerialData(AltosConfig in_config, int in_serial_mode) {
184                         config = in_config;
185                         serial_mode = in_serial_mode;
186                 }
187         }
188
189         void run_serial_thread(int serial_mode) {
190                 SerialData      sd = new SerialData(this, serial_mode);
191                 Thread          st = new Thread(sd);
192                 st.start();
193         }
194
195         void init_ui () throws InterruptedException, TimeoutException {
196                 config_ui = new AltosConfigUI(owner, remote);
197                 config_ui.addActionListener(this);
198                 serial_line.set_frame(owner);
199                 set_ui();
200         }
201
202         void abort() {
203                 if (serial_line != null) {
204                         serial_line.close();
205                         serial_line = null;
206                 }
207                 JOptionPane.showMessageDialog(owner,
208                                               String.format("Connection to \"%s\" failed",
209                                                             device.toShortString()),
210                                               "Connection Failed",
211                                               JOptionPane.ERROR_MESSAGE);
212                 config_ui.setVisible(false);
213         }
214
215         void set_ui() throws InterruptedException, TimeoutException {
216                 if (serial_line != null)
217                         run_serial_thread(serial_mode_read);
218                 else
219                         update_ui();
220         }
221
222         double frequency() {
223                 return AltosConvert.radio_to_frequency(data.radio_frequency,
224                                                        data.radio_setting,
225                                                        data.radio_calibration,
226                                                        data.radio_channel);
227         }
228
229         void save_data() {
230
231                 /* bounds check stuff */
232                 if (config_ui.flight_log_max() > data.log_limit()) {
233                         JOptionPane.showMessageDialog(owner,
234                                                       String.format("Requested flight log, %dk, is larger than the available space, %dk.\n",
235                                                                     config_ui.flight_log_max(),
236                                                                     data.log_limit()),
237                                                       "Maximum Flight Log Too Large",
238                                                       JOptionPane.ERROR_MESSAGE);
239                         return;
240                 }
241
242                 /* Pull data out of the UI and stuff back into our local data record */
243
244                 data.get_values(config_ui);
245
246                 run_serial_thread(serial_mode_save);
247         }
248
249         public void actionPerformed(ActionEvent e) {
250                 String  cmd = e.getActionCommand();
251                 try {
252                         if (cmd.equals("Save")) {
253                                 save_data();
254                         } else if (cmd.equals("Reset")) {
255                                 set_ui();
256                         } else if (cmd.equals("Reboot")) {
257                                 if (serial_line != null)
258                                         run_serial_thread(serial_mode_reboot);
259                         } else if (cmd.equals("Close")) {
260                                 if (serial_line != null)
261                                         serial_line.close();
262                         }
263                 } catch (InterruptedException ie) {
264                         abort();
265                 } catch (TimeoutException te) {
266                         abort();
267                 }
268         }
269
270         public AltosConfig(JFrame given_owner) {
271                 owner = given_owner;
272
273                 device = AltosDeviceDialog.show(owner, Altos.product_any);
274                 if (device != null) {
275                         try {
276                                 serial_line = new AltosSerial(device);
277                                 try {
278                                         if (device.matchProduct(Altos.product_basestation))
279                                                 remote = true;
280                                         init_ui();
281                                 } catch (InterruptedException ie) {
282                                         abort();
283                                 } catch (TimeoutException te) {
284                                         abort();
285                                 }
286                         } catch (FileNotFoundException ee) {
287                                 JOptionPane.showMessageDialog(owner,
288                                                               ee.getMessage(),
289                                                               "Cannot open target device",
290                                                               JOptionPane.ERROR_MESSAGE);
291                         } catch (AltosSerialInUseException si) {
292                                 JOptionPane.showMessageDialog(owner,
293                                                               String.format("Device \"%s\" already in use",
294                                                                             device.toShortString()),
295                                                               "Device in use",
296                                                               JOptionPane.ERROR_MESSAGE);
297                         }
298                 }
299         }
300 }