[notification-daemon] nd-daemon: rewrite



commit 61ff779d3d4d6f44686d66fd96edd16bae8de49c
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Wed Sep 16 18:30:13 2015 +0300

    nd-daemon: rewrite

 po/POTFILES.in        |    1 +
 src/Makefile.am       |    1 +
 src/nd-daemon.c       |  598 ++++++++++++++++++++++++-------------------------
 src/nd-daemon.h       |   69 ++-----
 src/nd-main.c         |   98 ++++++++
 src/nd-notification.c |   20 +-
 src/nd-notification.h |   16 +-
 7 files changed, 424 insertions(+), 379 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 886cbc9..8fa2135 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -4,5 +4,6 @@ data/notification-daemon.desktop.in.in
 data/notification-daemon-autostart.desktop.in.in
 src/nd-bubble.c
 src/nd-daemon.c
+src/nd-main.c
 src/nd-notification-box.c
 src/nd-queue.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 5cbc2e8..5adfd6a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -9,6 +9,7 @@ notification_daemon_SOURCES = \
        nd-bubble.h \
        nd-daemon.c \
        nd-daemon.h \
+       nd-main.c \
        nd-notification.c \
        nd-notification.h \
        nd-notification-box.c \
diff --git a/src/nd-daemon.c b/src/nd-daemon.c
index 2f5f89d..041fce4 100644
--- a/src/nd-daemon.c
+++ b/src/nd-daemon.c
@@ -1,404 +1,384 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
+/*
  * Copyright (C) 2006 Christian Hammond <chipx86 chipx86 com>
  * Copyright (C) 2005 John (J5) Palmieri <johnp redhat com>
  * Copyright (C) 2010 Red Hat, Inc.
+ * Copyright (C) 2015 Alberts Muktupāvels
  *
- * This program is free software; you can redistribute it and/or modify
+ * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
+ * 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
+ * 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.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
 
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <stdio.h>
-
 #include <glib/gi18n.h>
-#include <glib.h>
-#include <gio/gio.h>
-#include <glib-object.h>
 #include <gtk/gtk.h>
 
-#include <X11/Xproto.h>
-
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xatom.h>
-#include <gdk/gdkx.h>
-
 #include "nd-daemon.h"
+#include "nd-fd-notifications.h"
 #include "nd-notification.h"
 #include "nd-queue.h"
 
+#define NOTIFICATIONS_DBUS_NAME "org.freedesktop.Notifications"
+#define NOTIFICATIONS_DBUS_PATH "/org/freedesktop/Notifications"
+
+#define INFO_NAME "Notification Daemon"
+#define INFO_VENDOR "GNOME"
+#define INFO_VERSION PACKAGE_VERSION
+#define INFO_SPEC_VERSION "1.2"
+
 #define MAX_NOTIFICATIONS 20
 
-#define IDLE_SECONDS 30
-#define NOTIFICATION_BUS_NAME      "org.freedesktop.Notifications"
-#define NOTIFICATION_BUS_PATH      "/org/freedesktop/Notifications"
+struct _NdDaemon
+{
+  GObject            parent;
+
+  gboolean           replace;
 
-#define NOTIFICATION_SPEC_VERSION  "1.2"
+  NdFdNotifications *notifications;
+  guint              bus_name_id;
 
-#define NW_GET_DAEMON(nw) \
-        (g_object_get_data(G_OBJECT(nw), "_notify_daemon"))
+  NdQueue           *queue;
+};
 
-struct _NotifyDaemonPrivate
+enum
 {
-        GDBusConnection *connection;
-        NdQueue         *queue;
+  PROP_0,
+
+  PROP_REPLACE,
+
+  LAST_PROP
 };
 
-static void notify_daemon_finalize (GObject *object);
+static GParamSpec *properties[LAST_PROP] = { NULL };
 
-G_DEFINE_TYPE (NotifyDaemon, notify_daemon, G_TYPE_OBJECT);
+G_DEFINE_TYPE (NdDaemon, nd_daemon, G_TYPE_OBJECT)
 
 static void
-notify_daemon_class_init (NotifyDaemonClass *daemon_class)
+closed_cb (NdNotification *notification,
+           gint            reason,
+           gpointer        user_data)
 {
-        GObjectClass   *object_class = G_OBJECT_CLASS (daemon_class);
+  NdDaemon *daemon;
+  gint id;
 
-        object_class->finalize = notify_daemon_finalize;
+  daemon = ND_DAEMON (user_data);
+  id = nd_notification_get_id (notification);
 
-        g_type_class_add_private (daemon_class, sizeof (NotifyDaemonPrivate));
+  nd_fd_notifications_emit_notification_closed (daemon->notifications,
+                                                id, reason);
 }
 
 static void
-notify_daemon_init (NotifyDaemon *daemon)
+action_invoked_cb (NdNotification *notification,
+                   const gchar    *action,
+                   gpointer        user_data)
 {
-        daemon->priv = G_TYPE_INSTANCE_GET_PRIVATE (daemon,
-                                                    NOTIFY_TYPE_DAEMON,
-                                                    NotifyDaemonPrivate);
+  NdDaemon *daemon;
+  gint id;
+
+  daemon = ND_DAEMON (user_data);
+  id = nd_notification_get_id (notification);
 
-        daemon->priv->queue = nd_queue_new ();
+  nd_fd_notifications_emit_action_invoked (daemon->notifications,
+                                           id, action);
+
+  /* Resident notifications does not close when actions are invoked. */
+  if (!nd_notification_get_is_resident (notification))
+    nd_notification_close (notification, ND_NOTIFICATION_CLOSED_USER);
 }
 
-static void
-notify_daemon_finalize (GObject *object)
+static gboolean
+handle_close_notification_cb (NdFdNotifications     *object,
+                              GDBusMethodInvocation *invocation,
+                              guint                  id,
+                              gpointer               user_data)
 {
-        NotifyDaemon *daemon;
+  NdDaemon *daemon;
+  const gchar *error_name;
+  const gchar *error_message;
+  NdNotification *notification;
 
-        daemon = NOTIFY_DAEMON (object);
+  daemon = ND_DAEMON (user_data);
+  error_name = "org.freedesktop.Notifications.InvalidId";
+  error_message = _("Invalid notification identifier");
 
-        g_object_unref (daemon->priv->queue);
+  if (id == 0)
+    {
+      g_dbus_method_invocation_return_dbus_error (invocation, error_name,
+                                                  error_message);
 
-        g_free (daemon->priv);
+      return TRUE;
+    }
 
-        G_OBJECT_CLASS (notify_daemon_parent_class)->finalize (object);
-}
+  notification = nd_queue_lookup (daemon->queue, id);
 
-static void
-on_notification_close (NdNotification *notification,
-                       int             reason,
-                       NotifyDaemon   *daemon)
-{
-        g_dbus_connection_emit_signal (daemon->priv->connection,
-                                       nd_notification_get_sender (notification),
-                                       "/org/freedesktop/Notifications",
-                                       "org.freedesktop.Notifications",
-                                       "NotificationClosed",
-                                       g_variant_new ("(uu)", nd_notification_get_id (notification), reason),
-                                       NULL);
+  if (notification == NULL)
+    {
+      g_dbus_method_invocation_return_dbus_error (invocation, error_name,
+                                                  error_message);
+
+      return TRUE;
+    }
+
+  nd_notification_close (notification, ND_NOTIFICATION_CLOSED_API);
+  nd_fd_notifications_complete_close_notification (object, invocation);
+
+  return TRUE;
 }
 
-static void
-on_notification_action_invoked (NdNotification *notification,
-                                const char     *action,
-                                NotifyDaemon   *daemon)
+static gboolean
+handle_get_capabilities_cb (NdFdNotifications     *object,
+                            GDBusMethodInvocation *invocation,
+                            gpointer               user_data)
 {
-        g_dbus_connection_emit_signal (daemon->priv->connection,
-                                       nd_notification_get_sender (notification),
-                                       "/org/freedesktop/Notifications",
-                                       "org.freedesktop.Notifications",
-                                       "ActionInvoked",
-                                       g_variant_new ("(us)", nd_notification_get_id (notification), action),
-                                       NULL);
-
-        /* resident notifications don't close when actions are invoked */
-        if (! nd_notification_get_is_resident (notification)) {
-                nd_notification_close (notification, ND_NOTIFICATION_CLOSED_USER);
-        }
-}
+  const gchar *const capabilities[] =
+  {
+    "actions", "body", "body-hyperlinks", "body-markup", "icon-static",
+    "sound", "persistence", "action-icons", NULL
+  };
 
-/* ---------------------------------------------------------------------------------------------- */
-
-static GDBusNodeInfo *introspection_data = NULL;
-
-/* Introspection data for the service we are exporting */
-static const char introspection_xml[] =
-        "<node>"
-        "  <interface name='org.freedesktop.Notifications'>"
-        "    <method name='Notify'>"
-        "      <arg type='s' name='app_name' direction='in' />"
-        "      <arg type='u' name='id' direction='in' />"
-        "      <arg type='s' name='icon' direction='in' />"
-        "      <arg type='s' name='summary' direction='in' />"
-        "      <arg type='s' name='body' direction='in' />"
-        "      <arg type='as' name='actions' direction='in' />"
-        "      <arg type='a{sv}' name='hints' direction='in' />"
-        "      <arg type='i' name='timeout' direction='in' />"
-        "      <arg type='u' name='return_id' direction='out' />"
-        "    </method>"
-        "    <method name='CloseNotification'>"
-        "      <arg type='u' name='id' direction='in' />"
-        "    </method>"
-        "    <method name='GetCapabilities'>"
-        "      <arg type='as' name='return_caps' direction='out'/>"
-        "    </method>"
-        "    <method name='GetServerInformation'>"
-        "      <arg type='s' name='return_name' direction='out'/>"
-        "      <arg type='s' name='return_vendor' direction='out'/>"
-        "      <arg type='s' name='return_version' direction='out'/>"
-        "      <arg type='s' name='return_spec_version' direction='out'/>"
-        "    </method>"
-        "  </interface>"
-        "</node>";
+  nd_fd_notifications_complete_get_capabilities (object, invocation,
+                                                 capabilities);
 
-static void
-handle_notify (NotifyDaemon          *daemon,
-               const char            *sender,
-               GVariant              *parameters,
-               GDBusMethodInvocation *invocation)
+  return TRUE;
+}
+
+static gboolean
+handle_get_server_information_cb (NdFdNotifications     *object,
+                                  GDBusMethodInvocation *invocation,
+                                  gpointer               user_data)
 {
-        NdNotification *notification;
-        const char     *app_name;
-        guint           id;
-        const char     *icon_name;
-        const char     *summary;
-        const char     *body;
-        const char    **actions;
-        GVariantIter   *hints_iter;
-        int             timeout;
-
-        if (nd_queue_length (daemon->priv->queue) > MAX_NOTIFICATIONS) {
-                g_dbus_method_invocation_return_dbus_error (invocation,
-                                                            
"org.freedesktop.Notifications.MaxNotificationsExceeded",
-                                                            _("Exceeded maximum number of notifications"));
-                return;
-        }
-
-        g_variant_get (parameters,
-                       "(&su&s&s&s^a&sa{sv}i)",
-                       &app_name,
-                       &id,
-                       &icon_name,
-                       &summary,
-                       &body,
-                       &actions,
-                       &hints_iter,
-                       &timeout);
-
-        if (id > 0) {
-                notification = nd_queue_lookup (daemon->priv->queue, id);
-                if (notification == NULL) {
-                        id = 0;
-                } else {
-                        g_object_ref (notification);
-                }
-        }
-
-        if (id == 0) {
-                notification = nd_notification_new (sender);
-                g_signal_connect (notification, "closed", G_CALLBACK (on_notification_close), daemon);
-                g_signal_connect (notification, "action-invoked", G_CALLBACK 
(on_notification_action_invoked), daemon);
-        }
-
-        nd_notification_update (notification,
-                                app_name,
-                                icon_name,
-                                summary,
-                                body,
-                                actions,
-                                hints_iter,
-                                timeout);
-
-        if (id == 0 || !nd_notification_get_is_queued (notification)) {
-                nd_queue_add (daemon->priv->queue, notification);
-                nd_notification_set_is_queued (notification, TRUE);
-        }
-
-        g_dbus_method_invocation_return_value (invocation,
-                                               g_variant_new ("(u)", nd_notification_get_id (notification)));
-
-        g_object_unref (notification);
+  nd_fd_notifications_complete_get_server_information (object, invocation,
+                                                       INFO_NAME, INFO_VENDOR,
+                                                       INFO_VERSION,
+                                                       INFO_SPEC_VERSION);
+
+  return TRUE;
 }
 
-static void
-handle_close_notification (NotifyDaemon          *daemon,
-                           const char            *sender,
-                           GVariant              *parameters,
-                           GDBusMethodInvocation *invocation)
+static gboolean
+handle_notify_cb (NdFdNotifications     *object,
+                  GDBusMethodInvocation *invocation,
+                  const gchar           *app_name,
+                  guint                  replaces_id,
+                  const gchar           *app_icon,
+                  const gchar           *summary,
+                  const gchar           *body,
+                  const gchar *const    *actions,
+                  GVariant              *hints,
+                  gint                   expire_timeout,
+                  gpointer               user_data)
 {
-        NdNotification *notification;
-        guint           id;
+  NdDaemon *daemon;
+  const gchar *error_name;
+  const gchar *error_message;
+  NdNotification *notification;
+  gint new_id;
+
+  daemon = ND_DAEMON (user_data);
+
+  if (nd_queue_length (daemon->queue) > MAX_NOTIFICATIONS)
+    {
+      error_name = "org.freedesktop.Notifications.InvalidId";
+      error_message = _("Invalid notification identifier");
+
+      g_dbus_method_invocation_return_dbus_error (invocation, error_name,
+                                                  error_message);
+
+      return TRUE;
+    }
+
+  if (replaces_id > 0)
+    {
+      notification = nd_queue_lookup (daemon->queue, replaces_id);
 
-        g_variant_get (parameters, "(u)", &id);
+      if (notification == NULL)
+        replaces_id = 0;
+      else
+        g_object_ref (notification);
+    }
 
-        if (id == 0) {
-                g_dbus_method_invocation_return_dbus_error (invocation,
-                                                            "org.freedesktop.Notifications.InvalidId",
-                                                            _("Invalid notification identifier"));
-                return;
-        }
+  if (replaces_id == 0)
+    {
+      const gchar *sender;
 
-        notification = nd_queue_lookup (daemon->priv->queue, id);
-        if (notification != NULL) {
-                nd_notification_close (notification, ND_NOTIFICATION_CLOSED_API);
-        }
+      sender = g_dbus_method_invocation_get_sender (invocation);
+      notification = nd_notification_new (sender);
 
-        g_dbus_method_invocation_return_value (invocation, NULL);
+      g_signal_connect (notification, "closed",
+                        G_CALLBACK (closed_cb), daemon);
+      g_signal_connect (notification, "action-invoked",
+                        G_CALLBACK (action_invoked_cb), daemon);
+    }
+
+  nd_notification_update (notification, app_name, app_icon, summary, body,
+                          actions, hints, expire_timeout);
+
+  if (replaces_id == 0 || !nd_notification_get_is_queued (notification))
+    {
+      nd_queue_add (daemon->queue, notification);
+      nd_notification_set_is_queued (notification, TRUE);
+    }
+
+  new_id = nd_notification_get_id (notification);
+  nd_fd_notifications_complete_notify (object, invocation, new_id);
+
+  g_object_unref (notification);
+
+  return TRUE;
 }
 
 static void
-handle_get_capabilities (NotifyDaemon          *daemon,
-                         const char            *sender,
-                         GVariant              *parameters,
-                         GDBusMethodInvocation *invocation)
+bus_acquired_handler_cb (GDBusConnection *connection,
+                         const gchar     *name,
+                         gpointer         user_data)
 {
-        GVariantBuilder *builder;
-
-        builder = g_variant_builder_new (G_VARIANT_TYPE ("as"));
-        g_variant_builder_add (builder, "s", "actions");
-        g_variant_builder_add (builder, "s", "body");
-        g_variant_builder_add (builder, "s", "body-hyperlinks");
-        g_variant_builder_add (builder, "s", "body-markup");
-        g_variant_builder_add (builder, "s", "icon-static");
-        g_variant_builder_add (builder, "s", "sound");
-        g_variant_builder_add (builder, "s", "persistence");
-        g_variant_builder_add (builder, "s", "action-icons");
-
-        g_dbus_method_invocation_return_value (invocation,
-                                               g_variant_new ("(as)", builder));
-        g_variant_builder_unref (builder);
+  NdDaemon *daemon;
+  GDBusInterfaceSkeleton *skeleton;
+  GError *error;
+  gboolean exported;
+
+  daemon = ND_DAEMON (user_data);
+  skeleton = G_DBUS_INTERFACE_SKELETON (daemon->notifications);
+
+  g_signal_connect (daemon->notifications, "handle-close-notification",
+                    G_CALLBACK (handle_close_notification_cb), daemon);
+  g_signal_connect (daemon->notifications, "handle-get-capabilities",
+                    G_CALLBACK (handle_get_capabilities_cb), daemon);
+  g_signal_connect (daemon->notifications, "handle-get-server-information",
+                    G_CALLBACK (handle_get_server_information_cb), daemon);
+  g_signal_connect (daemon->notifications, "handle-notify",
+                    G_CALLBACK (handle_notify_cb), daemon);
+
+  error = NULL;
+  exported = g_dbus_interface_skeleton_export (skeleton, connection,
+                                               NOTIFICATIONS_DBUS_PATH, &error);
+
+  if (!exported)
+    {
+      g_warning ("Failed to export interface: %s", error->message);
+      g_error_free (error);
+
+      gtk_main_quit ();
+    }
 }
 
 static void
-handle_get_server_information (NotifyDaemon          *daemon,
-                               const char            *sender,
-                               GVariant              *parameters,
-                               GDBusMethodInvocation *invocation)
+name_lost_handler_cb (GDBusConnection *connection,
+                      const gchar     *name,
+                      gpointer         user_data)
 {
-        g_dbus_method_invocation_return_value (invocation,
-                                               g_variant_new ("(ssss)",
-                                                              "Notification Daemon",
-                                                              "GNOME",
-                                                              PACKAGE_VERSION,
-                                                              NOTIFICATION_SPEC_VERSION));
+  gtk_main_quit ();
 }
 
 static void
-handle_method_call (GDBusConnection       *connection,
-                    const char            *sender,
-                    const char            *object_path,
-                    const char            *interface_name,
-                    const char            *method_name,
-                    GVariant              *parameters,
-                    GDBusMethodInvocation *invocation,
-                    gpointer               user_data)
+nd_daemon_constructed (GObject *object)
 {
-        NotifyDaemon *daemon = user_data;
-
-        if (g_strcmp0 (method_name, "Notify") == 0) {
-                handle_notify (daemon, sender, parameters, invocation);
-        } else if (g_strcmp0 (method_name, "CloseNotification") == 0) {
-                handle_close_notification (daemon, sender, parameters, invocation);
-        } else if (g_strcmp0 (method_name, "GetCapabilities") == 0) {
-                handle_get_capabilities (daemon, sender, parameters, invocation);
-        } else if (g_strcmp0 (method_name, "GetServerInformation") == 0) {
-                handle_get_server_information (daemon, sender, parameters, invocation);
-        }
-}
+  NdDaemon *daemon;
+  GBusNameOwnerFlags flags;
 
-/* for now */
-static const GDBusInterfaceVTable interface_vtable =
-{
-        handle_method_call,
-        NULL, /* get property */
-        NULL  /* set property */
-};
+  daemon = ND_DAEMON (object);
 
-static void
-on_bus_acquired (GDBusConnection *connection,
-                 const char      *name,
-                 gpointer         user_data)
-{
-        NotifyDaemon *daemon = user_data;
-        guint         registration_id;
-
-        registration_id = g_dbus_connection_register_object (connection,
-                                                             "/org/freedesktop/Notifications",
-                                                             introspection_data->interfaces[0],
-                                                             &interface_vtable,
-                                                             daemon,
-                                                             NULL,  /* user_data_free_func */
-                                                             NULL); /* GError** */
-        g_assert (registration_id > 0);
-}
+  G_OBJECT_CLASS (nd_daemon_parent_class)->constructed (object);
 
-static void
-on_name_acquired (GDBusConnection *connection,
-                  const char      *name,
-                  gpointer         user_data)
-{
-        NotifyDaemon *daemon = user_data;
-        daemon->priv->connection = connection;
+  flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
+  if (daemon->replace)
+    flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;
+
+  daemon->bus_name_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+                                        NOTIFICATIONS_DBUS_NAME, flags,
+                                        bus_acquired_handler_cb, NULL,
+                                        name_lost_handler_cb, daemon, NULL);
 }
 
 static void
-on_name_lost (GDBusConnection *connection,
-              const char      *name,
-              gpointer         user_data)
+nd_daemon_dispose (GObject *object)
 {
-        exit (1);
-}
+  NdDaemon *daemon;
+
+  daemon = ND_DAEMON (object);
 
+  if (daemon->notifications != NULL)
+    {
+      GDBusInterfaceSkeleton *skeleton;
 
-int
-main (int argc, char **argv)
+      skeleton = G_DBUS_INTERFACE_SKELETON (daemon->notifications);
+      g_dbus_interface_skeleton_unexport (skeleton);
+
+      g_clear_object (&daemon->notifications);
+    }
+
+  if (daemon->bus_name_id > 0)
+    {
+      g_bus_unown_name (daemon->bus_name_id);
+      daemon->bus_name_id = 0;
+    }
+
+  g_clear_object (&daemon->queue);
+
+  G_OBJECT_CLASS (nd_daemon_parent_class)->dispose (object);
+}
+
+static void
+nd_daemon_set_property (GObject      *object,
+                        guint         property_id,
+                        const GValue *value,
+                        GParamSpec   *pspec)
 {
-        NotifyDaemon *daemon;
-        guint         owner_id;
+  NdDaemon *daemon;
 
-        bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
-        bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
-        textdomain (GETTEXT_PACKAGE);
+  daemon = ND_DAEMON (object);
 
-        g_log_set_always_fatal (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL);
+  switch (property_id)
+    {
+      case PROP_REPLACE:
+        daemon->replace = g_value_get_boolean (value);
+        break;
 
-        gtk_init (&argc, &argv);
+      default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+        break;
+    }
+}
 
-        introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
-        g_assert (introspection_data != NULL);
+static void
+nd_daemon_class_init (NdDaemonClass *daemon_class)
+{
+  GObjectClass *object_class;
 
-        daemon = g_object_new (NOTIFY_TYPE_DAEMON, NULL);
+  object_class = G_OBJECT_CLASS (daemon_class);
 
-        owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
-                                   "org.freedesktop.Notifications",
-                                   G_BUS_NAME_OWNER_FLAGS_NONE,
-                                   on_bus_acquired,
-                                   on_name_acquired,
-                                   on_name_lost,
-                                   daemon,
-                                   NULL);
+  object_class->constructed = nd_daemon_constructed;
+  object_class->dispose = nd_daemon_dispose;
+  object_class->set_property = nd_daemon_set_property;
 
-        gtk_main ();
+  properties[PROP_REPLACE] =
+    g_param_spec_boolean ("replace", "replace", "replace", FALSE,
+                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE |
+                          G_PARAM_STATIC_STRINGS);
 
-        g_bus_unown_name (owner_id);
-        g_dbus_node_info_unref (introspection_data);
+  g_object_class_install_properties (object_class, LAST_PROP, properties);
+}
 
-        g_object_unref (daemon);
+static void
+nd_daemon_init (NdDaemon *daemon)
+{
+  daemon->notifications = nd_fd_notifications_skeleton_new ();
+  daemon->queue = nd_queue_new ();
+}
 
-        return 0;
+NdDaemon *
+nd_daemon_new (gboolean replace)
+{
+  return g_object_new (ND_TYPE_DAEMON, "replace", replace, NULL);
 }
diff --git a/src/nd-daemon.h b/src/nd-daemon.h
index e9e7412..762dbb8 100644
--- a/src/nd-daemon.h
+++ b/src/nd-daemon.h
@@ -1,69 +1,32 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+/*
+ * Copyright (C) 2015 Alberts Muktupāvels
  *
- * Copyright (C) 2006 Christian Hammond <chipx86 chipx86 com>
- * Copyright (C) 2005 John (J5) Palmieri <johnp redhat com>
- * Copyright (C) 2010 Red Hat, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
+ * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2, or (at your option)
- * any later version.
+ * 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
+ * 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.
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
-#ifndef NOTIFY_DAEMON_H
-#define NOTIFY_DAEMON_H
-
-#include <glib.h>
-#include <glib-object.h>
-
-#define NOTIFY_TYPE_DAEMON (notify_daemon_get_type())
-#define NOTIFY_DAEMON(obj) \
-        (G_TYPE_CHECK_INSTANCE_CAST ((obj), NOTIFY_TYPE_DAEMON, NotifyDaemon))
-#define NOTIFY_DAEMON_CLASS(klass) \
-        (G_TYPE_CHECK_CLASS_CAST ((klass), NOTIFY_TYPE_DAEMON, NotifyDaemonClass))
-#define NOTIFY_IS_DAEMON(obj) \
-        (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NOTIFY_TYPE_DAEMON))
-#define NOTIFY_IS_DAEMON_CLASS(klass) \
-        (G_TYPE_CHECK_CLASS_TYPE ((klass), NOTIFY_TYPE_DAEMON))
-#define NOTIFY_DAEMON_GET_CLASS(obj) \
-        (G_TYPE_INSTANCE_GET_CLASS((obj), NOTIFY_TYPE_DAEMON, NotifyDaemonClass))
 
-#define NOTIFY_DAEMON_DEFAULT_TIMEOUT 7000
+#ifndef ND_DAEMON_H
+#define ND_DAEMON_H
 
-enum
-{
-        URGENCY_LOW,
-        URGENCY_NORMAL,
-        URGENCY_CRITICAL
-};
-
-typedef struct _NotifyDaemon NotifyDaemon;
-typedef struct _NotifyDaemonClass NotifyDaemonClass;
-typedef struct _NotifyDaemonPrivate NotifyDaemonPrivate;
-
-struct _NotifyDaemon
-{
-        GObject         parent;
+#include <glib-object.h>
 
-        /*< private > */
-        NotifyDaemonPrivate *priv;
-};
+G_BEGIN_DECLS
 
-struct _NotifyDaemonClass
-{
-        GObjectClass    parent_class;
-};
+#define ND_TYPE_DAEMON nd_daemon_get_type ()
+G_DECLARE_FINAL_TYPE (NdDaemon, nd_daemon, ND, DAEMON, GObject)
 
-G_BEGIN_DECLS GType notify_daemon_get_type (void);
+NdDaemon *nd_daemon_new (gboolean replace);
 
 G_END_DECLS
-#endif /* NOTIFY_DAEMON_H */
+
+#endif
diff --git a/src/nd-main.c b/src/nd-main.c
new file mode 100644
index 0000000..e49339f
--- /dev/null
+++ b/src/nd-main.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2015 Alberts Muktupāvels
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <stdlib.h>
+
+#include "nd-daemon.h"
+
+static gboolean debug = FALSE;
+static gboolean replace = FALSE;
+
+static GOptionEntry entries[] =
+{
+  {
+    "debug", 0, G_OPTION_FLAG_NONE,
+    G_OPTION_ARG_NONE, &debug,
+    N_("Enable debugging code"),
+    NULL
+  },
+  {
+    "replace", 'r', G_OPTION_FLAG_NONE,
+    G_OPTION_ARG_NONE, &replace,
+    N_("Replace a currently running application"),
+    NULL
+  },
+  {
+    NULL
+  }
+};
+
+static gboolean
+parse_arguments (int    *argc,
+                 char ***argv)
+{
+  GOptionContext *context;
+  GOptionGroup *gtk_group;
+  GError *error;
+
+  context = g_option_context_new (NULL);
+  gtk_group = gtk_get_option_group (FALSE);
+
+  g_option_context_add_main_entries (context, entries, NULL);
+  g_option_context_add_group (context, gtk_group);
+
+  error = NULL;
+  if (g_option_context_parse (context, argc, argv, &error) == FALSE)
+    {
+      g_warning ("Failed to parse command line arguments: %s", error->message);
+      g_error_free (error);
+
+      return FALSE;
+    }
+
+  if (debug)
+    g_setenv ("G_MESSAGES_DEBUG", "all", FALSE);
+
+  return TRUE;
+}
+
+int
+main (int argc, char *argv[])
+{
+  NdDaemon *daemon;
+
+  bindtextdomain (GETTEXT_PACKAGE, LOCALE_DIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  textdomain (GETTEXT_PACKAGE);
+
+  gtk_init (&argc, &argv);
+
+  if (!parse_arguments (&argc, &argv))
+    return EXIT_FAILURE;
+
+  daemon = nd_daemon_new (replace);
+
+  gtk_main ();
+
+  g_object_unref (daemon);
+
+  return EXIT_SUCCESS;
+}
diff --git a/src/nd-notification.c b/src/nd-notification.c
index f784b90..cc20309 100644
--- a/src/nd-notification.c
+++ b/src/nd-notification.c
@@ -151,16 +151,17 @@ nd_notification_finalize (GObject *object)
 }
 
 gboolean
-nd_notification_update (NdNotification *notification,
-                        const char     *app_name,
-                        const char     *icon,
-                        const char     *summary,
-                        const char     *body,
-                        const char    **actions,
-                        GVariantIter   *hints_iter,
-                        int             timeout)
+nd_notification_update (NdNotification     *notification,
+                        const gchar        *app_name,
+                        const gchar        *icon,
+                        const gchar        *summary,
+                        const gchar        *body,
+                        const gchar *const *actions,
+                        GVariant           *hints,
+                        gint                timeout)
 {
         GVariant *item;
+        GVariantIter iter;
 
         g_return_val_if_fail (ND_IS_NOTIFICATION (notification), FALSE);
 
@@ -181,7 +182,8 @@ nd_notification_update (NdNotification *notification,
 
         g_hash_table_remove_all (notification->hints);
 
-        while ((item = g_variant_iter_next_value (hints_iter))) {
+        g_variant_iter_init (&iter, hints);
+        while ((item = g_variant_iter_next_value (&iter))) {
                 const char *key;
                 GVariant   *value;
 
diff --git a/src/nd-notification.h b/src/nd-notification.h
index c67edaa..ac96f27 100644
--- a/src/nd-notification.h
+++ b/src/nd-notification.h
@@ -47,14 +47,14 @@ typedef enum
 GType                 nd_notification_get_type            (void) G_GNUC_CONST;
 
 NdNotification *      nd_notification_new                 (const char     *sender);
-gboolean              nd_notification_update              (NdNotification *notification,
-                                                           const char     *app_name,
-                                                           const char     *icon,
-                                                           const char     *summary,
-                                                           const char     *body,
-                                                           const char    **actions,
-                                                           GVariantIter   *hints_iter,
-                                                           int             timeout);
+gboolean              nd_notification_update              (NdNotification     *notification,
+                                                           const gchar        *app_name,
+                                                           const gchar        *icon,
+                                                           const gchar        *summary,
+                                                           const gchar        *body,
+                                                           const gchar *const *actions,
+                                                           GVariant           *hints,
+                                                           gint                timeout);
 
 void                  nd_notification_set_is_queued       (NdNotification *notification,
                                                            gboolean        is_queued);


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