[evince/wip/app: 6/19] daemon: Port to GApplication



commit ffe6aae294025103ccdf8ce6fe5553a6c510f742
Author: Christian Persch <chpe gnome org>
Date:   Tue Jun 12 13:41:35 2012 +0200

    daemon: Port to GApplication

 shell/ev-daemon.c |  283 +++++++++++++++++++++++++++++++----------------------
 1 files changed, 165 insertions(+), 118 deletions(-)
---
diff --git a/shell/ev-daemon.c b/shell/ev-daemon.c
index c4ba6d6..cabac93 100644
--- a/shell/ev-daemon.c
+++ b/shell/ev-daemon.c
@@ -2,7 +2,7 @@
  *  this file is part of evince, a gnome document viewer
  *
  * Copyright (C) 2009 Carlos Garcia Campos  <carlosgc gnome org>
- * Copyright  2010 Christian Persch
+ * Copyright  2010, 2012 Christian Persch
  *
  * Evince is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by
@@ -42,9 +42,32 @@
 
 #define LOG g_printerr
 
-static GList *ev_daemon_docs = NULL;
-static guint kill_timer_id;
-static GHashTable *pending_invocations = NULL;
+
+#define EV_TYPE_DAEMON_APPLICATION              (ev_daemon_application_get_type ())
+#define EV_DAEMON_APPLICATION(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplication))
+#define EV_DAEMON_APPLICATION_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplicationClass))
+#define EV_IS_DAEMON_APPLICATION(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), EV_TYPE_DAEMON_APPLICATION))
+#define EV_IS_DAEMON_APPLICATION_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_DAEMON_APPLICATION))
+#define EV_DAEMON_APPLICATION_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_DAEMON_APPLICATION, EvDaemonApplicationClass))
+
+typedef struct _EvDaemonApplication        EvDaemonApplication;
+typedef struct _EvDaemonApplicationClass   EvDaemonApplicationClass;
+
+struct _EvDaemonApplicationClass {
+        GApplicationClass parent_class;
+};
+
+struct _EvDaemonApplication
+{
+        GApplication parent_instance;
+
+        EvDaemon   *daemon;
+        GHashTable *pending_invocations;
+        GList      *docs;
+};
+
+static GType ev_daemon_application_get_type (void);
+G_DEFINE_TYPE (EvDaemonApplication, ev_daemon_application, G_TYPE_APPLICATION)
 
 typedef struct {
 	gchar *dbus_name;
@@ -68,11 +91,12 @@ ev_doc_free (EvDoc *doc)
 }
 
 static EvDoc *
-ev_daemon_find_doc (const gchar *uri)
+ev_daemon_application_find_doc (EvDaemonApplication *application,
+                                const gchar *uri)
 {
 	GList *l;
 
-	for (l = ev_daemon_docs; l != NULL; l = l->next) {
+	for (l = application->docs; l != NULL; l = l->next) {
 		EvDoc *doc = (EvDoc *)l->data;
 
 		if (strcmp (doc->uri, uri) == 0)
@@ -82,39 +106,6 @@ ev_daemon_find_doc (const gchar *uri)
 	return NULL;
 }
 
-static void
-ev_daemon_stop_killtimer (void)
-{
-	if (kill_timer_id != 0)
-		g_source_remove (kill_timer_id);
-	kill_timer_id = 0;
-}
-
-static gboolean
-ev_daemon_shutdown (gpointer user_data)
-{
-        GMainLoop *loop = (GMainLoop *) user_data;
-
-        LOG ("Timeout; exiting daemon.\n");
-
-        if (g_main_loop_is_running (loop))
-                g_main_loop_quit (loop);
-
-        return FALSE;
-}
-
-static void
-ev_daemon_maybe_start_killtimer (gpointer data)
-{
-	ev_daemon_stop_killtimer ();
-        if (ev_daemon_docs != NULL)
-                return;
-
-	kill_timer_id = g_timeout_add_seconds (DAEMON_TIMEOUT,
-                                               (GSourceFunc) ev_daemon_shutdown,
-                                               data);
-}
-
 static gboolean
 spawn_evince (const gchar *uri)
 {
@@ -152,11 +143,12 @@ name_vanished_cb (GDBusConnection *connection,
                   const gchar     *name,
                   gpointer         user_data)
 {
+        EvDaemonApplication *application = user_data;
 	GList *l;
 
         LOG ("Watch name'%s' disappeared\n", name);
 
-        for (l = ev_daemon_docs; l != NULL; l = l->next) {
+        for (l = application->docs; l != NULL; l = l->next) {
                 EvDoc *doc = (EvDoc *) l->data;
 
                 if (strcmp (doc->dbus_name, name) != 0)
@@ -164,23 +156,24 @@ name_vanished_cb (GDBusConnection *connection,
 
                 LOG ("Watch found URI '%s' for name; removing\n", doc->uri);
 
-                ev_daemon_docs = g_list_delete_link (ev_daemon_docs, l);
+                application->docs = g_list_delete_link (application->docs, l);
                 ev_doc_free (doc);
-                
-                ev_daemon_maybe_start_killtimer (user_data);
+
+                g_application_release (G_APPLICATION (application));
                 return;
         }
 }
 
 static void
-process_pending_invocations (const gchar *uri,
+process_pending_invocations (EvDaemonApplication *application,
+                             const gchar *uri,
 			     const gchar *dbus_name)
 {
 	GList *l;
 	GList *uri_invocations;
 
 	LOG ("RegisterDocument process pending invocations for URI %s\n", uri);
-	uri_invocations = g_hash_table_lookup (pending_invocations, uri);
+	uri_invocations = g_hash_table_lookup (application->pending_invocations, uri);
 
 	for (l = uri_invocations; l != NULL; l = l->next) {
 		GDBusMethodInvocation *invocation;
@@ -191,7 +184,7 @@ process_pending_invocations (const gchar *uri,
 	}
 
 	g_list_free (uri_invocations);
-	g_hash_table_remove (pending_invocations, uri);
+	g_hash_table_remove (application->pending_invocations, uri);
 }
 
 static void
@@ -201,14 +194,21 @@ document_loaded_cb (GDBusConnection *connection,
 		    const gchar     *interface_name,
 		    const gchar     *signal_name,
 		    GVariant        *parameters,
-		    EvDoc           *doc)
+		    gpointer         user_data)
 {
-	const gchar *uri;
+        EvDaemonApplication *application = user_data;
+        const gchar *uri;
+        EvDoc *doc;
 
 	g_variant_get (parameters, "(&s)", &uri);
-	if (strcmp (uri, doc->uri) == 0)
-		process_pending_invocations (uri, sender_name);
+        doc = ev_daemon_application_find_doc (application, uri);
+        if (doc != NULL &&
+	    strcmp (uri, doc->uri) == 0) {
+		process_pending_invocations (application, uri, sender_name);
+        }
+
 	g_dbus_connection_signal_unsubscribe (connection, doc->loaded_id);
+        doc->loaded_id = 0;
 }
 
 static gboolean
@@ -217,26 +217,29 @@ handle_register_document_cb (EvDaemon *object,
                              const gchar *uri,
                              gpointer user_data)
 {
+        EvDaemonApplication *application = user_data;
         GDBusConnection *connection;
         const char *sender;
         EvDoc       *doc;
 
-        doc = ev_daemon_find_doc (uri);
+        doc = ev_daemon_application_find_doc (application, uri);
         if (doc != NULL) {
                 LOG ("RegisterDocument found owner '%s' for URI '%s'\n", doc->dbus_name, uri);
                 ev_daemon_complete_register_document (object, invocation, doc->dbus_name);
                 return TRUE;
         }
 
-        ev_daemon_stop_killtimer ();
-
         sender = g_dbus_method_invocation_get_sender (invocation);
         connection = g_dbus_method_invocation_get_connection (invocation);
 
+        LOG ("RegisterDocument registered owner '%s' for URI '%s'\n", sender, uri);
+
         doc = g_new (EvDoc, 1);
         doc->dbus_name = g_strdup (sender);
         doc->uri = g_strdup (uri);
 
+        application->docs = g_list_prepend (application->docs, doc);
+
         doc->loaded_id = g_dbus_connection_signal_subscribe (connection,
                                                              doc->dbus_name,
                                                              EV_DBUS_WINDOW_INTERFACE_NAME,
@@ -244,20 +247,19 @@ handle_register_document_cb (EvDaemon *object,
                                                              NULL,
                                                              NULL,
                                                              0,
-                                                             (GDBusSignalCallback) document_loaded_cb,
-                                                             doc,
-                                                             NULL);
+                                                             document_loaded_cb,
+                                                             application, NULL);
         doc->watch_id = g_bus_watch_name_on_connection (connection,
                                                         sender,
                                                         G_BUS_NAME_WATCHER_FLAGS_NONE,
                                                         name_appeared_cb,
                                                         name_vanished_cb,
-                                                        user_data, NULL);
-
-        LOG ("RegisterDocument registered owner '%s' for URI '%s'\n", doc->dbus_name, uri);
-        ev_daemon_docs = g_list_prepend (ev_daemon_docs, doc);
+                                                        application, NULL);
 
         ev_daemon_complete_register_document (object, invocation, "");
+
+        g_application_hold (G_APPLICATION (application));
+
         return TRUE;
 }
 
@@ -267,12 +269,13 @@ handle_unregister_document_cb (EvDaemon *object,
                                const gchar *uri,
                                gpointer user_data)
 {
+        EvDaemonApplication *application = user_data;
         EvDoc *doc;
         const char *sender;
 
         LOG ("UnregisterDocument URI '%s'\n", uri);
 
-        doc = ev_daemon_find_doc (uri);
+        doc = ev_daemon_application_find_doc (application, uri);
         if (doc == NULL) {
                 LOG ("UnregisterDocument URI was not registered!\n");
                 g_dbus_method_invocation_return_error_literal (invocation,
@@ -294,11 +297,20 @@ handle_unregister_document_cb (EvDaemon *object,
                 return TRUE;
         }
 
-        ev_daemon_docs = g_list_remove (ev_daemon_docs, doc);
+        application->docs = g_list_remove (application->docs, doc);
+
+        if (doc->loaded_id != 0) {
+                g_dbus_connection_signal_unsubscribe (g_dbus_method_invocation_get_connection (invocation),
+                                                      doc->loaded_id);
+                doc->loaded_id = 0;
+        }
+
         ev_doc_free (doc);
-        ev_daemon_maybe_start_killtimer (user_data);
 
         ev_daemon_complete_unregister_document (object, invocation);
+
+        g_application_release (G_APPLICATION (application));
+
         return TRUE;
 }
 
@@ -309,11 +321,12 @@ handle_find_document_cb (EvDaemon *object,
                          gboolean spawn,
                          gpointer user_data)
 {
+        EvDaemonApplication *application = user_data;
         EvDoc *doc;
 
         LOG ("FindDocument URI '%s' \n", uri);
 
-        doc = ev_daemon_find_doc (uri);
+        doc = ev_daemon_application_find_doc (application, uri);
         if (doc != NULL) {
                 ev_daemon_complete_find_document (object, invocation, doc->dbus_name);
                 return TRUE;
@@ -323,7 +336,7 @@ handle_find_document_cb (EvDaemon *object,
                 GList *uri_invocations;
                 gboolean ret_val = TRUE;
 
-                uri_invocations = g_hash_table_lookup (pending_invocations, uri);
+                uri_invocations = g_hash_table_lookup (application->pending_invocations, uri);
 
                 if (uri_invocations == NULL) {
                         /* Only spawn once. */
@@ -333,7 +346,7 @@ handle_find_document_cb (EvDaemon *object,
                 if (ret_val) {
                         /* Only defer DBUS answer if evince was succesfully spawned */
                         uri_invocations = g_list_prepend (uri_invocations, invocation);
-                        g_hash_table_insert (pending_invocations,
+                        g_hash_table_insert (application->pending_invocations,
                                              g_strdup (uri),
                                              uri_invocations);
                         return TRUE;
@@ -346,89 +359,123 @@ handle_find_document_cb (EvDaemon *object,
         return TRUE;
 }
 
-static void
-bus_acquired_cb (GDBusConnection *connection,
-		 const gchar     *name,
-		 gpointer         user_data)
+/* ------------------------------------------------------------------------- */
+
+static gboolean
+ev_daemon_application_dbus_register (GApplication    *gapplication,
+                                     GDBusConnection *connection,
+                                     const gchar     *object_path,
+                                     GError         **error)
 {
-	GMainLoop *loop = (GMainLoop *) user_data;
+        EvDaemonApplication *application = EV_DAEMON_APPLICATION (gapplication);
         EvDaemon *skeleton;
-	GError    *error = NULL;
+
+        if (!G_APPLICATION_CLASS (ev_daemon_application_parent_class)->dbus_register (gapplication,
+                                                                                      connection,
+                                                                                      object_path,
+                                                                                      error))
+                return FALSE;
 
         skeleton = ev_daemon_skeleton_new ();
         if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
                                                connection,
                                                EV_DBUS_DAEMON_OBJECT_PATH,
-                                               &error)) {
-                g_printerr ("Failed to export object: %s\n", error->message);
-		g_error_free (error);
-
-		if (g_main_loop_is_running (loop))
-			g_main_loop_quit (loop);
-	}
+                                               error)) {
+                g_object_unref (skeleton);
+                return FALSE;
+        }
 
+        application->daemon = skeleton;
         g_signal_connect (skeleton, "handle-register-document",
-                          G_CALLBACK (handle_register_document_cb), loop);
+                          G_CALLBACK (handle_register_document_cb), application);
         g_signal_connect (skeleton, "handle-unregister-document",
-                          G_CALLBACK (handle_unregister_document_cb), loop);
+                          G_CALLBACK (handle_unregister_document_cb), application);
         g_signal_connect (skeleton, "handle-find-document",
-                          G_CALLBACK (handle_find_document_cb), loop);
+                          G_CALLBACK (handle_find_document_cb), application);
+        return TRUE;
 }
 
 static void
-name_acquired_cb (GDBusConnection *connection,
-                  const gchar     *name,
-                  gpointer         user_data)
+ev_daemon_application_dbus_unregister (GApplication    *gapplication,
+                                       GDBusConnection *connection,
+                                       const gchar     *object_path)
 {
-	ev_daemon_maybe_start_killtimer (user_data);
+        EvDaemonApplication *application = EV_DAEMON_APPLICATION (gapplication);
+
+        if (application->daemon) {
+                g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (application->daemon));
+                g_object_unref (application->daemon);
+                application->daemon = NULL;
+        }
+
+        G_APPLICATION_CLASS (ev_daemon_application_parent_class)->dbus_unregister (gapplication,
+                                                                                   connection,
+                                                                                   object_path);
 }
 
 static void
-name_lost_cb (GDBusConnection *connection,
-              const gchar     *name,
-              gpointer         user_data)
+ev_daemon_application_init (EvDaemonApplication *application)
 {
-          GMainLoop *loop = (GMainLoop *) user_data;
+        application->pending_invocations = g_hash_table_new_full (g_str_hash,
+                                                                  g_str_equal,
+                                                                  (GDestroyNotify) g_free,
+                                                                  NULL);
+}
+
+static void
+ev_daemon_application_finalize (GObject *object)
+{
+        EvDaemonApplication *application = EV_DAEMON_APPLICATION (object);
+
+        g_warn_if_fail (g_hash_table_size (application->pending_invocations) == 0);
+        g_hash_table_destroy (application->pending_invocations);
 
-          /* Failed to acquire the name; exit daemon */
-          if (g_main_loop_is_running (loop))
-                  g_main_loop_quit (loop);
+        g_list_free_full (application->docs, (GDestroyNotify) ev_doc_free);
+
+        G_OBJECT_CLASS (ev_daemon_application_parent_class)->finalize (object);
 }
 
+static void
+ev_daemon_application_class_init (EvDaemonApplicationClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        GApplicationClass *g_application_class = G_APPLICATION_CLASS (klass);
+
+        object_class->finalize = ev_daemon_application_finalize;
+
+        g_application_class->dbus_register = ev_daemon_application_dbus_register;
+        g_application_class->dbus_unregister = ev_daemon_application_dbus_unregister;
+}
+
+/* ------------------------------------------------------------------------- */
+
 gint
 main (gint argc, gchar **argv)
 {
-	GMainLoop *loop;
-        guint owner_id;
+        GApplication *application;
+        const GApplicationFlags flags = G_APPLICATION_IS_SERVICE;
+        GError *error = NULL;
+        int status = 1;
 
         g_set_prgname ("evince-daemon");
 
 	g_type_init ();
 
-	loop = g_main_loop_new (NULL, FALSE);
+        application = g_object_new (EV_TYPE_DAEMON_APPLICATION,
+                                    "application-id", EV_DBUS_DAEMON_NAME,
+                                    "flags", flags,
+                                    NULL);
+        g_application_set_inactivity_timeout (application, DAEMON_TIMEOUT);
 
-	pending_invocations = g_hash_table_new_full (g_str_hash,
-						     g_str_equal,
-						     (GDestroyNotify)g_free,
-						     NULL);
-
-        owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
-				   EV_DBUS_DAEMON_NAME,
-				   G_BUS_NAME_OWNER_FLAGS_NONE,
-				   bus_acquired_cb,
-				   name_acquired_cb,
-				   name_lost_cb,
-				   g_main_loop_ref (loop),
-				   (GDestroyNotify) g_main_loop_unref);
-
-        g_main_loop_run (loop);
-
-        g_bus_unown_name (owner_id);
+        if (!g_application_register (application, NULL, &error)) {
+                g_printerr ("Failed to register: %s\n", error->message);
+                g_error_free (error);
+                goto done;
+        }
 
-        g_main_loop_unref (loop);
-        g_list_foreach (ev_daemon_docs, (GFunc)ev_doc_free, NULL);
-        g_list_free (ev_daemon_docs);
-        g_hash_table_destroy (pending_invocations);
+        status = g_application_run (application, 0, NULL);
 
-	return 0;
+    done:
+        g_object_unref (application);
+	return status;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]