Handle disappearing serial devices
authorKeith Packard <keithp@keithp.com>
Mon, 18 May 2009 05:29:06 +0000 (22:29 -0700)
committerKeith Packard <keithp@keithp.com>
Mon, 18 May 2009 05:29:06 +0000 (22:29 -0700)
Put up a dialog when the serial open fails, and shut down monitoring when
the serial device disappears while running.

Signed-off-by: Keith Packard <keithp@keithp.com>
aoview/aoview.glade
aoview/aoview.h
aoview/aoview_dev_dialog.c
aoview/aoview_log.c
aoview/aoview_monitor.c
aoview/aoview_serial.c

index bf74da7b7bd62d35798f9f6ce71db14a20766cfb..925804727e35ba06e94adae3bed7683aef32bb62 100644 (file)
   </widget>
   <widget class="GtkMessageDialog" id="log_fail_dialog">
     <property name="border_width">5</property>
   </widget>
   <widget class="GtkMessageDialog" id="log_fail_dialog">
     <property name="border_width">5</property>
-    <property name="type">popup</property>
+    <property name="title" translatable="yes">Failed to create log</property>
     <property name="type_hint">normal</property>
     <property name="skip_taskbar_hint">True</property>
     <property name="type_hint">normal</property>
     <property name="skip_taskbar_hint">True</property>
+    <property name="transient_for">aoview</property>
     <property name="message_type">error</property>
     <property name="buttons">close</property>
     <property name="text">Cannot create log file</property>
     <property name="message_type">error</property>
     <property name="buttons">close</property>
     <property name="text">Cannot create log file</property>
       </widget>
     </child>
   </widget>
       </widget>
     </child>
   </widget>
+  <widget class="GtkMessageDialog" id="dev_open_fail_dialog">
+    <property name="border_width">5</property>
+    <property name="title" translatable="yes">Failed to open device</property>
+    <property name="type_hint">normal</property>
+    <property name="skip_taskbar_hint">True</property>
+    <property name="transient_for">aoview</property>
+    <property name="message_type">error</property>
+    <property name="buttons">close</property>
+    <property name="text">Cannot open device</property>
+    <child internal-child="vbox">
+      <widget class="GtkVBox" id="dialog-vbox6">
+        <property name="visible">True</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <widget class="GtkHButtonBox" id="dialog-action_area6">
+            <property name="visible">True</property>
+            <property name="layout_style">end</property>
+          </widget>
+          <packing>
+            <property name="expand">False</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+      </widget>
+    </child>
+  </widget>
 </glade-interface>
 </glade-interface>
index f584045f3a517a06ecac28112fbf77ff41a6c72b..7824491228a4eb10dfb834961ae2311df1404525 100644 (file)
@@ -73,7 +73,7 @@ struct aostate {
 void
 aoview_monitor_disconnect(void);
 
 void
 aoview_monitor_disconnect(void);
 
-void
+gboolean
 aoview_monitor_connect(char *tty);
 
 struct aoview_serial *
 aoview_monitor_connect(char *tty);
 
 struct aoview_serial *
@@ -82,9 +82,11 @@ aoview_serial_open(const char *tty);
 void
 aoview_serial_close(struct aoview_serial *serial);
 
 void
 aoview_serial_close(struct aoview_serial *serial);
 
+typedef void (*aoview_serial_callback)(gpointer user_data, struct aoview_serial *serial, gint revents);
+
 void
 aoview_serial_set_callback(struct aoview_serial *serial,
 void
 aoview_serial_set_callback(struct aoview_serial *serial,
-                          GSourceFunc func,
+                          aoview_serial_callback func,
                           gpointer data,
                           GDestroyNotify notify);
 
                           gpointer data,
                           GDestroyNotify notify);
 
index 00947404e7100dbf076cd00905f7af2a06a8f743..530187c11369329912f12e4923520a199b4811eb 100644 (file)
@@ -45,6 +45,23 @@ aoview_dev_dialog_map(GtkWidget *widget, gpointer data)
        gtk_tree_view_columns_autosize(dev_list);
 }
 
        gtk_tree_view_columns_autosize(dev_list);
 }
 
+static GtkMessageDialog *dev_open_fail_dialog;
+
+static void
+aoview_dev_open_failed(char *name)
+{
+       char    *utf8_file;
+       utf8_file = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
+       if (!utf8_file)
+               utf8_file = name;
+       gtk_message_dialog_format_secondary_text(dev_open_fail_dialog,
+                                                "\"%s\"", utf8_file);
+       if (utf8_file != name)
+               g_free(utf8_file);
+       gtk_dialog_run(GTK_DIALOG(dev_open_fail_dialog));
+       gtk_widget_hide(GTK_WIDGET(dev_open_fail_dialog));
+}
+
 static void
 aoview_dev_selected(GtkTreeModel *model,
                    GtkTreePath *path,
 static void
 aoview_dev_selected(GtkTreeModel *model,
                    GtkTreePath *path,
@@ -55,7 +72,8 @@ aoview_dev_selected(GtkTreeModel *model,
        gtk_tree_model_get(model, iter,
                           2, &string,
                           -1);
        gtk_tree_model_get(model, iter,
                           2, &string,
                           -1);
-       aoview_monitor_connect(string);
+       if (!aoview_monitor_connect(string))
+               aoview_dev_open_failed(string);
 }
 
 static GtkWidget       *dialog;
 }
 
 static GtkWidget       *dialog;
@@ -123,4 +141,7 @@ aoview_dev_dialog_init(GladeXML *xml)
        g_signal_connect(G_OBJECT(ao_disconnect), "activate",
                         G_CALLBACK(aoview_dev_disconnect),
                         ao_disconnect);
        g_signal_connect(G_OBJECT(ao_disconnect), "activate",
                         G_CALLBACK(aoview_dev_disconnect),
                         ao_disconnect);
+
+       dev_open_fail_dialog = GTK_MESSAGE_DIALOG(glade_xml_get_widget(xml, "dev_open_fail_dialog"));
+       assert(dev_open_fail_dialog);
 }
 }
index a9300f61e7c3d22b95ee70653a041a3f511c34c8..0afdb64e680168cc20fbdce0eec943d1288febd6 100644 (file)
@@ -92,7 +92,8 @@ aoview_log_open_failed(char *name)
                                                 "\"%s\"", utf8_file);
        if (utf8_file != name)
                g_free(utf8_file);
                                                 "\"%s\"", utf8_file);
        if (utf8_file != name)
                g_free(utf8_file);
-       gtk_widget_show(GTK_WIDGET(log_fail_dialog));
+       gtk_dialog_run(GTK_DIALOG(log_fail_dialog));
+       gtk_widget_hide(GTK_WIDGET(log_fail_dialog));
        aoview_log_failed = 1;
 }
 
        aoview_log_failed = 1;
 }
 
index 5c2daaa59d3b06561c05aec058494317b870da12..3b3245e268866a77c1941bd26e242eecf75b68ed 100644 (file)
@@ -116,38 +116,45 @@ aoview_monitor_parse(char *line)
        aoview_state_notify(&state);
 }
 
        aoview_state_notify(&state);
 }
 
-static gboolean
-aoview_monitor_callback(void *user_data)
+static void
+aoview_monitor_callback(gpointer user_data,
+                       struct aoview_serial *serial,
+                       gint revents)
 {
        int     c;
 
 {
        int     c;
 
-       if (!monitor_serial)
-               return FALSE;
-
-       for (;;) {
-               c = aoview_serial_getc(monitor_serial);
-               if (c == -1)
-                       break;
-               if (c == '\r')
-                       continue;
-               if (c == '\n') {
-                       monitor_line[monitor_pos] = '\0';
-                       if (monitor_pos)
-                       aoview_monitor_parse(monitor_line);
-                       monitor_pos = 0;
-               } else if (monitor_pos < MONITOR_LEN)
-                       monitor_line[monitor_pos++] = c;
+       if (revents & (G_IO_HUP|G_IO_ERR)) {
+               aoview_monitor_disconnect();
+               return;
+       }
+       if (revents & G_IO_IN) {
+               for (;;) {
+                       c = aoview_serial_getc(serial);
+                       if (c == -1)
+                               break;
+                       if (c == '\r')
+                               continue;
+                       if (c == '\n') {
+                               monitor_line[monitor_pos] = '\0';
+                               if (monitor_pos)
+                               aoview_monitor_parse(monitor_line);
+                               monitor_pos = 0;
+                       } else if (monitor_pos < MONITOR_LEN)
+                               monitor_line[monitor_pos++] = c;
+               }
        }
        }
-       return TRUE;
 }
 
 }
 
-void
+gboolean
 aoview_monitor_connect(char *tty)
 {
        aoview_monitor_disconnect();
        monitor_serial = aoview_serial_open(tty);
 aoview_monitor_connect(char *tty)
 {
        aoview_monitor_disconnect();
        monitor_serial = aoview_serial_open(tty);
+       if (!monitor_serial)
+               return FALSE;
        aoview_serial_set_callback(monitor_serial,
                                   aoview_monitor_callback,
                                   monitor_serial,
                                   NULL);
        aoview_serial_set_callback(monitor_serial,
                                   aoview_monitor_callback,
                                   monitor_serial,
                                   NULL);
+       return TRUE;
 }
 }
index 5cb286f88a924c30fb656c32f379f75bf5b1870c..1721a28671d8a01ab7cd2d66cbd98be719cdf85b 100644 (file)
@@ -191,6 +191,7 @@ serial_dispatch(GSource *source,
                gpointer user_data)
 {
        struct aoview_serial *serial = (struct aoview_serial *) source;
                gpointer user_data)
 {
        struct aoview_serial *serial = (struct aoview_serial *) source;
+       aoview_serial_callback func = (aoview_serial_callback) callback;
        gint revents = serial->poll_fd.revents;
 
        if (revents & G_IO_IN)
        gint revents = serial->poll_fd.revents;
 
        if (revents & G_IO_IN)
@@ -199,8 +200,8 @@ serial_dispatch(GSource *source,
        if (revents & G_IO_OUT)
                aoview_buf_flush(&serial->out_buf, serial->fd);
 
        if (revents & G_IO_OUT)
                aoview_buf_flush(&serial->out_buf, serial->fd);
 
-       if (callback && (revents & G_IO_IN))
-               (*callback)(user_data);
+       if (func)
+               (*func)(user_data, serial, revents);
        return TRUE;
 }
 
        return TRUE;
 }
 
@@ -262,9 +263,9 @@ aoview_serial_close(struct aoview_serial *serial)
 
 void
 aoview_serial_set_callback(struct aoview_serial *serial,
 
 void
 aoview_serial_set_callback(struct aoview_serial *serial,
-                          GSourceFunc func,
+                          aoview_serial_callback func,
                           gpointer data,
                           GDestroyNotify notify)
 {
                           gpointer data,
                           GDestroyNotify notify)
 {
-       g_source_set_callback(&serial->source, func, data, notify);
+       g_source_set_callback(&serial->source, (GSourceFunc) func, data, notify);
 }
 }