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