altosuilib: Provide dialog while waiting for flash target to re-appear
authorKeith Packard <keithp@keithp.com>
Thu, 23 Aug 2018 00:44:02 +0000 (17:44 -0700)
committerKeith Packard <keithp@keithp.com>
Thu, 23 Aug 2018 00:44:02 +0000 (17:44 -0700)
On windows, switching to the boot loader can take a long time. Instead
of timing out after a second, show a dialog and let the user cancel
the operation if they get bored of waiting.

Signed-off-by: Keith Packard <keithp@keithp.com>
altosuilib/AltosFlashUI.java

index 4d9c662cc65bad5342c52668967552895ff34f77..6c9cae520a52143c049aa69947c79ed719d3ded1 100644 (file)
@@ -346,7 +346,7 @@ public class AltosFlashUI
                                                                    device.toShortString()),
                                                      "Device in use",
                                                      JOptionPane.ERROR_MESSAGE);
                                                                    device.toShortString()),
                                                      "Device in use",
                                                      JOptionPane.ERROR_MESSAGE);
-               } else if (e instanceof IOException) {
+               } else {
                        JOptionPane.showMessageDialog(frame,
                                                      e.getMessage(),
                                                      file.toString(),
                        JOptionPane.showMessageDialog(frame,
                                                      e.getMessage(),
                                                      file.toString(),
@@ -429,45 +429,235 @@ public class AltosFlashUI
 
        flash_task      flasher;
 
 
        flash_task      flasher;
 
-       private boolean open_device() throws InterruptedException {
-               try {
-                       link = new AltosSerial(device);
-                       if (is_pair_programmed())
-                               return true;
 
 
-                       if (link == null)
-                               throw new IOException(String.format("%s: open failed", device.toShortString()));
+       class open_task implements Runnable {
+               AltosDevice     device;
+               Thread          t;
+               open_dialog     dialog;
 
 
-                       while (!link.is_loader()) {
-                               link.to_loader();
+               public void do_exception(final Exception e) {
+                       SwingUtilities.invokeLater(
+                               new Runnable() {
+                                       public void run() {
+                                               try { dialog.open_exception(e); } catch (Exception ex) { }
+                                       }
+                               });
+               }
 
 
-                               java.util.List<AltosDevice> devices = null;
+               public void do_success(final AltosLink link) {
+                       SwingUtilities.invokeLater(
+                               new Runnable() {
+                                       public void run() {
+                                               try { dialog.open_success(link); } catch (Exception ex) { }
+                                       }
+                               });
+               }
 
 
-                               for (int tries = 0; tries < 10; tries++) {
-                                       Thread.sleep(100);
-                                       devices = AltosUSBDevice.list(AltosLib.product_altusmetrum);
-                                       if (devices.size() != 0)
-                                               break;
-                               }
+               public void do_failure() {
+                       SwingUtilities.invokeLater(
+                               new Runnable() {
+                                       public void run() {
+                                               try { dialog.open_failure(); } catch (Exception ex) { }
+                                       }
+                               });
+               }
+
+               public void do_cancel() {
+                       SwingUtilities.invokeLater(
+                               new Runnable() {
+                                       public void run() {
+                                               try { dialog.open_cancel(); } catch (Exception ex) { }
+                                       }
+                               });
+               }
+
+               public void run () {
+                       try {
+                               AltosLink link = null;
+
+                               for (;;) {
+                                       System.out.printf("Attempting to open %s\n", device.toShortString());
+
+                                       link = new AltosSerial(device);
+
+                                       if (link == null)
+                                               throw new IOException(String.format("%s: open failed",
+                                                                                   device.toShortString()));
 
 
-                               if (devices.size() == 1)
-                                       device = devices.get(0);
-                               else {
-                                       device = AltosDeviceUIDialog.show(frame, AltosLib.product_altusmetrum);
-                                       if (device == null)
-                                               return false;
+                                       /* See if the link is usable already */
+                                       if (is_pair_programmed() || link.is_loader()) {
+                                               System.out.printf("Device ready for use\n");
+                                               do_success(link);
+                                               return;
+                                       }
+
+                                       java.util.List<AltosDevice> prev_devices =
+                                               AltosUSBDevice.list(AltosLib.product_altusmetrum);
+
+                                       /* Nope, switch to loader and
+                                        * wait for it to re-appear
+                                        */
+
+                                       System.out.printf("Switch to loader\n");
+
+                                       link.to_loader();
+
+                                       /* This is a bit fragile, but
+                                        * I'm not sure what else to
+                                        * do other than ask the user.
+                                        *
+                                        * Search for a device which
+                                        * wasn't there before we
+                                        * asked the target to switch
+                                        * to loader mode
+                                        */
+
+                                       device = null;
+                                       for (;;) {
+                                               Thread.sleep(100);
+                                               java.util.List<AltosDevice> devices =
+                                                       AltosUSBDevice.list(AltosLib.product_altusmetrum);
+
+                                               for (AltosDevice d : devices) {
+                                                       boolean matched = false;
+                                                       System.out.printf("\tfound device %s\n", d.toShortString());
+                                                       for (AltosDevice p : prev_devices)
+                                                               if (d.equals(p)) {
+                                                                       matched = true;
+                                                                       break;
+                                                               }
+                                                       if (!matched) {
+                                                               System.out.printf("Identified new device %s\n", d.toShortString());
+                                                               device = d;
+                                                               break;
+                                                       }
+                                               }
+                                               if (device != null)
+                                                       break;
+                                       }
                                }
                                }
-                               link = new AltosSerial(device);
+                       } catch (AltosSerialInUseException ee) {
+                               do_exception(ee);
+                       } catch (FileNotFoundException fe) {
+                               do_exception(fe);
+                       } catch (IOException ie) {
+                               do_exception (ie);
+                       } catch (InterruptedException ie) {
                        }
                        }
-                       return true;
-               } catch (AltosSerialInUseException ee) {
-                       exception(ee);
-               } catch (FileNotFoundException fe) {
-                       exception(fe);
-               } catch (IOException ie) {
-                       exception (ie);
                }
                }
-               return false;
+
+               public void cancel() {
+                       t.interrupt();
+               }
+
+               public open_task(AltosDevice device, open_dialog dialog) {
+                       this.device = device;
+                       this.dialog = dialog;
+                       t = new Thread(this);
+                       t.start();
+               }
+       }
+
+       class open_dialog
+               extends AltosUIDialog
+               implements ActionListener
+       {
+               AltosUIFrame owner;
+
+               private JLabel  opening_label;
+               private JButton cancel_button;
+
+               boolean done = false;
+
+               AltosLink link = null;
+
+               open_task open = null;
+
+               public void open_exception(Exception e) {
+                       System.out.printf("open_exception\n");
+                       setVisible(false);
+                       exception(e);
+                       done = true;
+               }
+
+               public void open_success(AltosLink link) {
+                       System.out.printf("open_success\n");
+                       setVisible(false);
+                       this.link = link;
+                       done = true;
+               }
+
+               public void open_failure() {
+                       System.out.printf("open_failure\n");
+                       setVisible(false);
+                       done = true;
+               }
+
+               public void open_cancel() {
+                       System.out.printf("open_cancel\n");
+                       setVisible(false);
+                       done = true;
+               }
+
+               public AltosLink do_open(open_task open) throws InterruptedException {
+                       this.open = open;
+                       setVisible(true);
+                       return link;
+               }
+
+               public void actionPerformed(ActionEvent e) {
+                       String cmd = e.getActionCommand();
+
+                       if (cmd.equals("cancel"))
+                               if (open != null)
+                                       open.cancel();
+                       done = true;
+                       setVisible(false);
+               }
+
+               public open_dialog(AltosUIFrame in_owner) {
+                       super(in_owner, "Open Flash Target Device", true);
+                       owner = in_owner;
+
+                       Container               pane = getContentPane();
+                       GridBagConstraints      c = new GridBagConstraints();
+                       Insets                  i = new Insets(4,4,4,4);
+
+
+                       pane.setLayout(new GridBagLayout());
+
+                       opening_label = new JLabel("Opening Device");
+                       c.fill = GridBagConstraints.HORIZONTAL;
+                       c.anchor = GridBagConstraints.LINE_START;
+                       c.insets = i;
+                       c.weightx = 0;
+                       c.weighty = 0;
+
+                       c.gridx = 0;
+                       c.gridy = 0;
+
+                       pane.add(opening_label, c);
+
+                       cancel_button = new JButton("Cancel");
+                       cancel_button.addActionListener(this);
+                       cancel_button.setActionCommand("cancel");
+
+                       c.gridy = 1;
+                       pane.add(cancel_button, c);
+                       pack();
+                       setLocationRelativeTo(owner);
+               }
+       }
+
+       private boolean open_device() throws InterruptedException {
+
+               open_dialog     dialog = new open_dialog(frame);
+
+               open_task       open = new open_task(device, dialog);
+
+               link = dialog.do_open(open);
+
+               return link != null;
        }
 
        /*
        }
 
        /*