altosui/telegps/micropeak: Handle both MULTI_LIB and non-MULTI_LIB builds
[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_11.*;
26 import org.altusmetrum.altosuilib_11.*;
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                                         serial_line.close();
165                                 } catch (InterruptedException ie) {
166                                 }
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                 try {
233                         /* bounds check stuff */
234                         if (config_ui.flight_log_max() > data.log_space() / 1024) {
235                                 JOptionPane.showMessageDialog(owner,
236                                                               String.format("Requested flight log, %dk, is larger than the available space, %dk.\n",
237                                                                             config_ui.flight_log_max(),
238                                                                             data.log_space() / 1024),
239                                                               "Maximum Flight Log Too Large",
240                                                               JOptionPane.ERROR_MESSAGE);
241                                 return;
242                         }
243
244                         /* Pull data out of the UI and stuff back into our local data record */
245
246                         data.get_values(config_ui);
247                         run_serial_thread(serial_mode_save);
248                 } catch (AltosConfigDataException ae) {
249                         JOptionPane.showMessageDialog(owner,
250                                                       ae.getMessage(),
251                                                       "Configuration Data Error",
252                                                       JOptionPane.ERROR_MESSAGE);
253                 }
254         }
255
256         public void actionPerformed(ActionEvent e) {
257                 String  cmd = e.getActionCommand();
258                 try {
259                         if (cmd.equals("Save")) {
260                                 save_data();
261                         } else if (cmd.equals("Reset")) {
262                                 set_ui();
263                         } else if (cmd.equals("Reboot")) {
264                                 if (serial_line != null)
265                                         run_serial_thread(serial_mode_reboot);
266                         } else if (cmd.equals("Close")) {
267                                 if (serial_line != null)
268                                         serial_line.close();
269                         }
270                 } catch (InterruptedException ie) {
271                         abort();
272                 } catch (TimeoutException te) {
273                         abort();
274                 }
275         }
276
277         public AltosConfig(JFrame given_owner) {
278                 owner = given_owner;
279
280                 device = AltosDeviceUIDialog.show(owner, Altos.product_any);
281                 if (device != null) {
282                         try {
283                                 serial_line = new AltosSerial(device);
284                                 try {
285                                         if (device.matchProduct(Altos.product_basestation))
286                                                 remote = true;
287                                         init_ui();
288                                 } catch (InterruptedException ie) {
289                                         abort();
290                                 } catch (TimeoutException te) {
291                                         abort();
292                                 }
293                         } catch (FileNotFoundException ee) {
294                                 JOptionPane.showMessageDialog(owner,
295                                                               ee.getMessage(),
296                                                               "Cannot open target device",
297                                                               JOptionPane.ERROR_MESSAGE);
298                         } catch (AltosSerialInUseException si) {
299                                 JOptionPane.showMessageDialog(owner,
300                                                               String.format("Device \"%s\" already in use",
301                                                                             device.toShortString()),
302                                                               "Device in use",
303                                                               JOptionPane.ERROR_MESSAGE);
304                         }
305                 }
306         }
307 }