summaryrefslogtreecommitdiff
path: root/dispatcher
diff options
context:
space:
mode:
authorCarlos Garnacho <carlosg@gnome.org>2007-11-23 01:23:19 +0100
committerCarlos Garnacho <carlosg@gnome.org>2007-12-12 01:22:01 +0100
commite07b5dcee02d5c40faf3f3c954d7b4407035aabb (patch)
treea177d250442615245f11ca333a183586c1a1c51d /dispatcher
parent2cb1a1001f45fc83a7777cf9b582843be4822fd0 (diff)
Add StbFileMonitor object, use it in the dispatcher to emit "changed" when any configuration file has changed.
Now, configuration modules have to implement the getFiles method, so the dispatcher can query it and monitor the relevant files. * dispatcher/file-monitor.[ch]: new object * dispatcher/dispatcher.c: query files and at them to the monitor * configure.in: look optionally for Gio. This feature will not be compiled if Gio is not found. * dispatcher/Makefile.am: make necessary changes.
Diffstat (limited to 'dispatcher')
-rw-r--r--dispatcher/Makefile.am10
-rw-r--r--dispatcher/dispatcher.c130
-rw-r--r--dispatcher/file-monitor.c179
-rw-r--r--dispatcher/file-monitor.h65
4 files changed, 381 insertions, 3 deletions
diff --git a/dispatcher/Makefile.am b/dispatcher/Makefile.am
index 40f0144..6af7afc 100644
--- a/dispatcher/Makefile.am
+++ b/dispatcher/Makefile.am
@@ -1,11 +1,17 @@
INCLUDES = \
-Wall \
$(DISPATCHER_CFLAGS) \
- $(POLKIT_CFLAGS)
+ $(POLKIT_CFLAGS) \
+ $(GIO_CFLAGS)
bin_PROGRAMS = system-tools-backends
-system_tools_backends_LDADD = $(DISPATCHER_LIBS) $(POLKIT_LIBS)
+if HAVE_GIO
+file_monitor_sources = file-monitor.c file-monitor.h
+endif
+
+system_tools_backends_LDADD = $(DISPATCHER_LIBS) $(POLKIT_LIBS) $(GIO_LIBS)
system_tools_backends_SOURCES = \
+ $(file_monitor_sources) \
dispatcher.c dispatcher.h \
main.c
diff --git a/dispatcher/dispatcher.c b/dispatcher/dispatcher.c
index 5439c25..462ce7c 100644
--- a/dispatcher/dispatcher.c
+++ b/dispatcher/dispatcher.c
@@ -35,6 +35,9 @@
#include <polkit-dbus/polkit-dbus.h>
#endif
+#ifdef HAVE_GIO
+#include "file-monitor.h"
+#endif
#define DBUS_ADDRESS_ENVVAR "DBUS_SESSION_BUS_ADDRESS"
#define DBUS_INTERFACE_STB "org.freedesktop.SystemToolsBackends"
@@ -71,6 +74,10 @@ struct StbDispatcherPrivate
PolKitContext *polkit_context;
#endif
+#ifdef HAVE_GIO
+ StbFileMonitor *file_monitor;
+#endif
+
guint debug : 1;
};
@@ -98,6 +105,8 @@ static void stb_dispatcher_get_property (GObject *object,
GValue *value,
GParamSpec *pspec);
+static gchar* get_destination (DBusMessage *message);
+
G_DEFINE_TYPE (StbDispatcher, stb_dispatcher, G_TYPE_OBJECT);
@@ -203,6 +212,104 @@ retrieve_platform (DBusMessage *message)
return NULL;
}
+#ifdef HAVE_GIO
+static void
+dispatch_file_list (DBusPendingCall *pending_call,
+ gpointer data)
+{
+ StbDispatcher *dispatcher;
+ StbDispatcherPrivate *priv;
+ DBusMessage *reply;
+ DBusError error;
+ gchar **files;
+ gint n_files;
+
+ dispatcher = STB_DISPATCHER (data);
+ priv = STB_DISPATCHER_GET_PRIVATE (dispatcher);
+ reply = dbus_pending_call_steal_reply (pending_call);
+ dbus_error_init (&error);
+
+ if (dbus_set_error_from_message (&error, reply))
+ {
+ g_critical (error.message);
+ dbus_error_free (&error);
+ dbus_message_unref (reply);
+ return;
+ }
+
+ if (dbus_message_get_args (reply, &error,
+ DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &files, &n_files,
+ DBUS_TYPE_INVALID))
+ {
+ stb_file_monitor_add_files (priv->file_monitor,
+ dbus_message_get_path (reply),
+ (const gchar **) files);
+ dbus_free_string_array (files);
+ }
+ else
+ {
+ g_critical (error.message);
+ }
+
+ dbus_message_unref (reply);
+}
+
+static void
+query_file_list (StbDispatcher *dispatcher,
+ DBusMessage *message)
+{
+ StbDispatcherPrivate *priv;
+ DBusPendingCall *pending_call;
+ DBusMessage *file_message;
+ gchar *destination;
+
+ priv = STB_DISPATCHER_GET_PRIVATE (dispatcher);
+ destination = get_destination (message);
+
+ if (G_UNLIKELY (!destination))
+ return;
+
+ if (stb_file_monitor_is_object_handled (priv->file_monitor, destination))
+ {
+ g_free (destination);
+ return;
+ }
+
+ file_message = dbus_message_new_method_call (destination,
+ dbus_message_get_path (message),
+ DBUS_INTERFACE_STB,
+ "getFiles");
+
+ dbus_connection_send_with_reply (priv->session_connection, file_message, &pending_call, -1);
+
+ if (pending_call)
+ {
+ dbus_pending_call_set_notify (pending_call,
+ dispatch_file_list,
+ g_object_ref (dispatcher),
+ (DBusFreeFunction) g_object_unref);
+ dbus_pending_call_unref (pending_call);
+ }
+
+ dbus_message_unref (file_message);
+ g_free (destination);
+}
+
+static void
+object_changed_cb (StbDispatcher *dispatcher,
+ const gchar *object_path)
+{
+ StbDispatcherPrivate *priv;
+ DBusMessage *signal;
+
+ priv = STB_DISPATCHER_GET_PRIVATE (dispatcher);
+ signal = dbus_message_new_signal (object_path, DBUS_INTERFACE_STB, "changed");
+
+ dbus_connection_send (priv->connection, signal, NULL);
+ dbus_message_unref (signal);
+}
+#endif /* HAVE_GIO */
+
static void
dispatch_reply (DBusPendingCall *pending_call,
gpointer data)
@@ -220,7 +327,17 @@ dispatch_reply (DBusPendingCall *pending_call,
/* get the platform if necessary */
if (dbus_message_has_interface (reply, DBUS_INTERFACE_STB_PLATFORM) &&
dbus_message_has_member (reply, "getPlatform") && !priv->platform)
- priv->platform = retrieve_platform (reply);
+ {
+ /* get the platform if necessary */
+ priv->platform = retrieve_platform (reply);
+ }
+#ifdef HAVE_GIO
+ else if (dbus_message_has_interface (reply, DBUS_INTERFACE_STB))
+ {
+ /* monitor configuration files */
+ query_file_list (async_data->dispatcher, reply);
+ }
+#endif /* HAVE_GIO */
/* send the reply back */
dbus_message_set_destination (reply, async_data->destination);
@@ -564,6 +681,13 @@ stb_dispatcher_init (StbDispatcher *dispatcher)
priv->polkit_context = polkit_context_new ();
polkit_context_init (priv->polkit_context, NULL);
#endif
+
+#ifdef HAVE_GIO
+ priv->file_monitor = stb_file_monitor_new ();
+
+ g_signal_connect_swapped (priv->file_monitor, "object_changed",
+ G_CALLBACK (object_changed_cb), dispatcher);
+#endif
}
static void
@@ -614,6 +738,10 @@ stb_dispatcher_finalize (GObject *object)
polkit_context_unref (priv->polkit_context);
#endif
+#ifdef HAVE_GIO
+ g_object_unref (priv->file_monitor);
+#endif
+
/* terminate the private bus */
if (priv->bus_pid)
{
diff --git a/dispatcher/file-monitor.c b/dispatcher/file-monitor.c
new file mode 100644
index 0000000..39ec9cd
--- /dev/null
+++ b/dispatcher/file-monitor.c
@@ -0,0 +1,179 @@
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
+/* Copyright (C) 2007 Carlos Garnacho
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Carlos Garnacho Parro <carlosg@gnome.org>
+ */
+
+#include <glib.h>
+#include <gio/gvfs.h>
+#include <gio/gfilemonitor.h>
+#include "file-monitor.h"
+
+#define STB_FILE_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), STB_TYPE_FILE_MONITOR, StbFileMonitorPrivate))
+
+enum {
+ OBJECT_CHANGED,
+ LAST_SIGNAL
+};
+
+typedef struct StbFileMonitorPrivate StbFileMonitorPrivate;
+
+struct StbFileMonitorPrivate
+{
+ GHashTable *monitors;
+};
+
+static GQuark file_monitor_qdata;
+static guint signals [LAST_SIGNAL];
+
+static void stb_file_monitor_finalize (GObject *object);
+
+G_DEFINE_TYPE (StbFileMonitor, stb_file_monitor, G_TYPE_OBJECT);
+
+static void
+stb_file_monitor_class_init (StbFileMonitorClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+
+ object_class->finalize = stb_file_monitor_finalize;
+
+ file_monitor_qdata = g_quark_from_static_string ("stb-file-monitor-data");
+
+ signals [OBJECT_CHANGED] =
+ g_signal_new ("object-changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (StbFileMonitorClass, object_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1, G_TYPE_STRING);
+
+ g_type_class_add_private (object_class,
+ sizeof (StbFileMonitorPrivate));
+}
+
+static void
+destroy_monitor_list (gpointer data)
+{
+ GList *list = (GList *) data;
+
+ g_list_foreach (list, (GFunc) g_object_unref, NULL);
+ g_list_free (list);
+}
+
+static void
+stb_file_monitor_init (StbFileMonitor *file_monitor)
+{
+ StbFileMonitorPrivate *priv;
+
+ priv = STB_FILE_MONITOR_GET_PRIVATE (file_monitor);
+
+ priv->monitors = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) destroy_monitor_list);
+}
+
+static void
+stb_file_monitor_finalize (GObject *object)
+{
+ StbFileMonitorPrivate *priv;
+
+ priv = STB_FILE_MONITOR_GET_PRIVATE (object);
+
+ g_hash_table_unref (priv->monitors);
+
+ G_OBJECT_CLASS (stb_file_monitor_parent_class)->finalize (object);
+}
+
+StbFileMonitor *
+stb_file_monitor_new (void)
+{
+ return g_object_new (STB_TYPE_FILE_MONITOR, NULL);
+}
+
+static void
+monitor_changed (GFileMonitor *monitor,
+ GFile *file,
+ GFile *other_file,
+ GFileMonitorEvent event,
+ gpointer user_data)
+{
+ StbFileMonitor *file_monitor;
+ const gchar *object;
+
+ if (event == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
+ {
+ file_monitor = STB_FILE_MONITOR (user_data);
+ object = g_object_get_qdata (G_OBJECT (monitor), file_monitor_qdata);
+
+ g_signal_emit (file_monitor, signals [OBJECT_CHANGED], 0, object);
+ }
+}
+
+void
+stb_file_monitor_add_files (StbFileMonitor *file_monitor,
+ const gchar *object,
+ const gchar **files)
+{
+ StbFileMonitorPrivate *priv;
+ GList *object_monitors;
+ gchar *key;
+ gint f;
+
+ g_return_if_fail (STB_IS_FILE_MONITOR (file_monitor));
+
+ priv = STB_FILE_MONITOR_GET_PRIVATE (file_monitor);
+
+ if (stb_file_monitor_is_object_handled (file_monitor, object))
+ return;
+
+ key = g_strdup (object);
+ object_monitors = NULL;
+
+ for (f = 0; files[f]; f++)
+ {
+ GFileMonitor *monitor;
+ GFile *file;
+
+ file = g_file_new_for_path (files[f]);
+ monitor = g_file_monitor_file (file, G_FILE_MONITOR_FLAGS_NONE, NULL);
+ g_object_set_qdata (G_OBJECT (monitor), file_monitor_qdata, key);
+
+ g_signal_connect (monitor, "changed",
+ G_CALLBACK (monitor_changed), file_monitor);
+
+ g_print ("jijijiji\n");
+
+ object_monitors = g_list_prepend (object_monitors, monitor);
+ }
+
+ g_hash_table_insert (priv->monitors, key, object_monitors);
+}
+
+gboolean
+stb_file_monitor_is_object_handled (StbFileMonitor *file_monitor,
+ const gchar *object)
+{
+ StbFileMonitorPrivate *priv;
+
+ g_return_val_if_fail (STB_IS_FILE_MONITOR (file_monitor), FALSE);
+
+ priv = STB_FILE_MONITOR_GET_PRIVATE (file_monitor);
+
+ return (g_hash_table_lookup (priv->monitors, object) != NULL);
+}
diff --git a/dispatcher/file-monitor.h b/dispatcher/file-monitor.h
new file mode 100644
index 0000000..b92f114
--- /dev/null
+++ b/dispatcher/file-monitor.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C; c-file-style: "gnu"; tab-width: 8 -*- */
+/* Copyright (C) 2007 Carlos Garnacho
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors: Carlos Garnacho Parro <carlosg@gnome.org>
+ */
+
+#ifndef __STB_FILE_MONITOR_H
+#define __STB_FILE_MONITOR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define STB_TYPE_FILE_MONITOR (stb_file_monitor_get_type ())
+#define STB_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), STB_TYPE_FILE_MONITOR, StbFileMonitor))
+#define STB_FILE_MONITOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), STB_TYPE_FILE_MONITOR, StbFileMonitorClass))
+#define STB_IS_FILE_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), STB_TYPE_FILE_MONITOR))
+#define STB_IS_FILE_MONITOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((o), STB_TYPE_FILE_MONITOR))
+#define STB_FILE_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), STB_TYPE_FILE_MONITOR, StbFileMonitorClass))
+
+typedef struct StbFileMonitor StbFileMonitor;
+typedef struct StbFileMonitorClass StbFileMonitorClass;
+
+struct StbFileMonitor
+{
+ GObject parent;
+
+ /*<private>*/
+ gpointer _priv;
+};
+
+struct StbFileMonitorClass
+{
+ GObjectClass parent_class;
+
+ void (* object_changed) (StbFileMonitor *file_monitor,
+ const gchar *object);
+};
+
+GType stb_file_monitor_get_type (void);
+StbFileMonitor *stb_file_monitor_new (void);
+
+void stb_file_monitor_add_files (StbFileMonitor *file_monitor,
+ const gchar *object,
+ const gchar **files);
+gboolean stb_file_monitor_is_object_handled (StbFileMonitor *file_monitor,
+ const gchar *object);
+
+G_END_DECLS
+
+#endif /* __STB_FILE_MONITOR_H */