summaryrefslogtreecommitdiff
path: root/command/command.c
diff options
context:
space:
mode:
authorWu Xiaotian <[email protected]>2018-11-21 19:15:34 +0800
committerraveit65 <[email protected]>2019-07-08 14:31:05 +0200
commit18cf1e9710b8a308b8f8f9c6c0019b3a9c2b3cda (patch)
tree168cfb954322b4e4b2265532c717dbf34588119b /command/command.c
parentdff2e89cad44df3b77be3923ea8914c3eb549b62 (diff)
downloadmate-applets-18cf1e9710b8a308b8f8f9c6c0019b3a9c2b3cda.tar.bz2
mate-applets-18cf1e9710b8a308b8f8f9c6c0019b3a9c2b3cda.tar.xz
Make command applet run commands asynchronously
Diffstat (limited to 'command/command.c')
-rw-r--r--command/command.c132
1 files changed, 124 insertions, 8 deletions
diff --git a/command/command.c b/command/command.c
index 67bc5de6..a0523b17 100644
--- a/command/command.c
+++ b/command/command.c
@@ -54,6 +54,8 @@ typedef struct
MatePanelApplet *applet;
GSettings *settings;
+ GPid child_pid;
+ gchar *buffer;
GtkLabel *label;
GtkImage *image;
@@ -95,6 +97,18 @@ command_applet_destroy (MatePanelApplet *applet_widget, CommandApplet *command_a
command_applet->command = NULL;
}
+ if (command_applet->child_pid != (GPid) 0)
+ {
+ g_spawn_close_pid (command_applet->child_pid);
+ command_applet->child_pid = 0;
+ }
+
+ if (command_applet->buffer != NULL)
+ {
+ g_free (command_applet->buffer);
+ command_applet->buffer = NULL;
+ }
+
g_object_unref (command_applet->settings);
}
@@ -205,7 +219,8 @@ settings_width_changed (GSettings *settings, gchar *key, CommandApplet *command_
width = g_settings_get_int (command_applet->settings, WIDTH_KEY);
- command_applet->width = width;
+ if (command_applet->width != width)
+ command_applet->width = width;
/* execute command to start new timer */
command_execute (command_applet);
@@ -288,26 +303,125 @@ process_command_output (CommandApplet *command_applet, gchar *output)
}
static gboolean
+stdout_io_func (GIOChannel *ioc, GIOCondition cond, gpointer data)
+{
+ CommandApplet *command_applet;
+
+ command_applet = data;
+ if (cond & (G_IO_IN | G_IO_PRI))
+ {
+ if (strlen (command_applet->buffer) == 0)
+ {
+ GError *error = NULL;
+ GIOStatus ret;
+ gsize len = 0;
+
+ ret = g_io_channel_read_chars (ioc, command_applet->buffer, command_applet->width, &len, &error);
+ if (len <= 0 || ret != G_IO_STATUS_NORMAL)
+ {
+ g_clear_error (&error);
+ return FALSE;
+ }
+ process_command_output (command_applet, command_applet->buffer);
+ }
+ return FALSE;
+ }
+
+ if (cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL))
+ return FALSE;
+
+ return TRUE;
+}
+
+static void
+on_child_exit (GPid child_pid, gint status, gpointer data)
+{
+ CommandApplet *command_applet;
+
+ command_applet = data;
+ g_spawn_close_pid (child_pid);
+ command_applet->child_pid = 0;
+}
+
+static GIOChannel *
+set_up_io_channel (gint fd, GIOCondition cond, GIOFunc func, gpointer data)
+{
+ GIOChannel *ioc;
+
+ ioc = g_io_channel_unix_new (fd);
+
+ g_io_channel_set_encoding (ioc, NULL, NULL);
+ g_io_channel_set_buffered (ioc, FALSE);
+
+ g_io_channel_set_close_on_unref (ioc, TRUE);
+
+ g_io_add_watch (ioc, cond, func, data);
+ g_io_channel_unref (ioc);
+
+ return ioc;
+}
+
+static gboolean
command_execute (CommandApplet *command_applet)
{
GError *error = NULL;
- gchar *output = NULL;
- gint ret = 0;
+ gint argc;
+ gchar **argv;
+ gint stdout_fd;
- if (g_spawn_command_line_sync (command_applet->command, &output, NULL, &ret, &error))
+ /* command is empty, wait for next timer execution */
+ if (strlen (command_applet->command) == 0)
{
- process_command_output (command_applet, output);
+ return TRUE;
}
- else
+
+ if (!g_shell_parse_argv (command_applet->command, &argc, &argv, &error))
+ {
gtk_label_set_text (command_applet->label, ERROR_OUTPUT);
+ g_clear_error (&error);
+ return FALSE;
+ }
+
+ /* command running, wait for next timer execution */
+ if (command_applet->child_pid != (GPid) 0)
+ {
+ g_strfreev (argv);
+ return TRUE;
+ }
+
+ if (!g_spawn_async_with_pipes (NULL,
+ argv,
+ NULL,
+ (GSpawnFlags) G_SPAWN_SEARCH_PATH | G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL,
+ NULL,
+ &command_applet->child_pid,
+ NULL,
+ &stdout_fd,
+ NULL,
+ &error))
+ {
+ g_clear_error (&error);
+ g_strfreev (argv);
+ return TRUE;
+ }
+
+ if (command_applet->buffer != NULL) {
+ g_free(command_applet->buffer);
+ }
+ command_applet->buffer = g_new0(gchar, command_applet->width+1);
+
+ set_up_io_channel (stdout_fd, G_IO_IN|G_IO_PRI|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
+ stdout_io_func, command_applet);
- g_free (output);
+ if (command_applet->child_pid != (GPid) 0)
+ g_child_watch_add (command_applet->child_pid, on_child_exit, command_applet);
/* start timer for next execution */
command_applet->timeout_id = g_timeout_add_seconds (command_applet->interval,
(GSourceFunc) command_execute,
command_applet);
-
+ g_strfreev (argv);
return FALSE;
}
@@ -334,6 +448,8 @@ command_applet_fill (MatePanelApplet* applet)
command_applet->image = GTK_IMAGE (gtk_image_new_from_icon_name (APPLET_ICON, 24));
command_applet->label = GTK_LABEL (gtk_label_new (ERROR_OUTPUT));
command_applet->timeout_id = 0;
+ command_applet->child_pid = 0;
+ command_applet->buffer = NULL;
/* we add the Gtk label into the applet */
gtk_box_pack_start (command_applet->box,