[gnome-disk-utility] Add gnome-settings-daemon plug-in to warn user on SMART failures
- From: David Zeuthen <davidz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-disk-utility] Add gnome-settings-daemon plug-in to warn user on SMART failures
- Date: Mon, 12 Nov 2012 17:54:49 +0000 (UTC)
commit 314b9d0f29cdf8a8f88dc22b6ab8c520f2a83eb0
Author: David Zeuthen <zeuthen gmail com>
Date: Mon Nov 12 12:48:44 2012 -0500
Add gnome-settings-daemon plug-in to warn user on SMART failures
This feature was cut in the rewrite that happened for 3.4 - just
adding it back.
Signed-off-by: David Zeuthen <zeuthen gmail com>
configure.ac | 9 +
data/Makefile.am | 5 +-
...ettings-daemon.plugins.gdu-sd.gschema.xml.in.in | 15 +
src/Makefile.am | 2 +-
src/notify/Makefile.am | 95 +++++
src/notify/gdu-sd-plugin.gnome-settings-plugin.in | 8 +
src/notify/gdusdmonitor.c | 368 ++++++++++++++++++++
src/notify/gdusdmonitor.h | 31 ++
src/notify/gdusdplugin.c | 124 +++++++
src/notify/gdusdplugin.h | 33 ++
src/notify/testplugin.c | 74 ++++
11 files changed, 762 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index a2ccf68..4deac78 100644
--- a/configure.ac
+++ b/configure.ac
@@ -88,6 +88,8 @@ LIBSECRET1_REQUIRED=0.7
PWQUALITY_REQUIRED=1.0.0
CANBERRA_REQUIRED=0.1
LIBDVDREAD_REQUIRED=4.2.0
+GSD_PLUGIN_REQUIRED=3.6
+LIBNOTIFY_REQUIRED=0.7
PKG_CHECK_MODULES(GLIB2, [gmodule-2.0 gio-unix-2.0 >= $GLIB2_REQUIRED])
PKG_CHECK_MODULES(UDISKS2, [udisks2 >= $UDISKS2_REQUIRED])
@@ -96,6 +98,11 @@ PKG_CHECK_MODULES(LIBSECRET1, [libsecret-1 >= $LIBSECRET1_REQUIRED])
PKG_CHECK_MODULES(PWQUALITY, [pwquality >= $PWQUALITY_REQUIRED])
PKG_CHECK_MODULES(CANBERRA, [libcanberra-gtk3 >= $CANBERRA_REQUIRED])
PKG_CHECK_MODULES(LIBDVDREAD, [dvdread >= $LIBDVDREAD_REQUIRED])
+PKG_CHECK_MODULES(GSD_PLUGIN, [gnome-settings-daemon >= GSD_PLUGIN_REQUIRED])
+PKG_CHECK_MODULES(LIBNOTIFY, [libnotify >= LIBNOTIFY_REQUIRED])
+
+gsd_plugindir='${libdir}/gnome-settings-daemon-3.0'
+AC_SUBST([gsd_plugindir])
GLIB_GSETTINGS
@@ -147,6 +154,7 @@ src/Makefile
src/libgdu/Makefile
src/disks/Makefile
src/disk-image-mounter/Makefile
+src/notify/Makefile
po/Makefile.in
data/Makefile
data/icons/Makefile
@@ -158,6 +166,7 @@ data/icons/48x48/Makefile
data/icons/256x256/Makefile
data/icons/scalable/Makefile
data/org.gnome.Disks.gschema.xml.in
+data/org.gnome.settings-daemon.plugins.gdu-sd.gschema.xml.in
data/ui/Makefile
doc/Makefile
doc/man/Makefile
diff --git a/data/Makefile.am b/data/Makefile.am
index 5924742..33ac654 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -7,7 +7,10 @@ desktop_in_files = gnome-disks.desktop.in gnome-disk-image-mounter.desktop.in
desktop_DATA = $(desktop_in_files:.desktop.in=.desktop)
# GSettings schemas
-gsettings_SCHEMAS = org.gnome.Disks.gschema.xml
+gsettings_SCHEMAS = \
+ org.gnome.Disks.gschema.xml \
+ org.gnome.settings-daemon.plugins.gdu-sd.gschema.xml \
+ $(NULL)
@INTLTOOL_DESKTOP_RULE@
@INTLTOOL_XML_NOMERGE_RULE@
diff --git a/data/org.gnome.settings-daemon.plugins.gdu-sd.gschema.xml.in.in b/data/org.gnome.settings-daemon.plugins.gdu-sd.gschema.xml.in.in
new file mode 100644
index 0000000..d16aa7f
--- /dev/null
+++ b/data/org.gnome.settings-daemon.plugins.gdu-sd.gschema.xml.in.in
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist>
+ <schema gettext-domain="@GETTEXT_PACKAGE@" id="org.gnome.settings-daemon.plugins.gdu-sd" path="/org/gnome/settings-daemon/plugins/gdu-sd/">
+ <key name="active" type="b">
+ <default>true</default>
+ <_summary>Activation of this plugin</_summary>
+ <_description>Whether this plugin would be activated by gnome-settings-daemon or not</_description>
+ </key>
+ <key name="priority" type="i">
+ <default>1</default>
+ <_summary>Priority to use for this plugin</_summary>
+ <_description>Priority to use for this plugin in gnome-settings-daemon startup queue</_description>
+ </key>
+ </schema>
+</schemalist>
diff --git a/src/Makefile.am b/src/Makefile.am
index 4aceda0..b1d8e95 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = libgdu disks disk-image-mounter
+SUBDIRS = libgdu disks disk-image-mounter notify
clean-local :
rm -f *~
diff --git a/src/notify/Makefile.am b/src/notify/Makefile.am
new file mode 100644
index 0000000..e20323b
--- /dev/null
+++ b/src/notify/Makefile.am
@@ -0,0 +1,95 @@
+
+NULL =
+
+gdu_sd_plugin_name = gdu-sd
+
+gdu_sd_plugindir=$(gsd_plugindir)
+
+gdu_sd_plugin_LTLIBRARIES = \
+ libgdu-sd.la \
+ $(NULL)
+
+libgdu_sd_la_SOURCES = \
+ gdusdplugin.h gdusdplugin.c \
+ gdusdmonitor.h gdusdmonitor.c \
+ $(NULL)
+
+libgdu_sd_la_CPPFLAGS = \
+ -DGNOME_SETTINGS_LOCALEDIR=\""$(datadir)/locale"\" \
+ $(AM_CPPFLAGS)
+
+libgdu_sd_la_CFLAGS = \
+ $(GSD_PLUGIN_CFLAGS) \
+ $(GLIB2_CFLAGS) \
+ $(GTK3_CFLAGS) \
+ $(UDISKS2_CFLAGS) \
+ $(LIBNOTIFY_CFLAGS) \
+ $(NULL)
+
+libgdu_sd_la_LDFLAGS = \
+ -export-dynamic \
+ -export-symbols-regex '^register_gnome_settings_plugin' \
+ -module \
+ -avoid-version \
+ -no-undefined \
+ $(NULL)
+
+libgdu_sd_la_LIBADD = \
+ $(GSD_PLUGIN_LIBS) \
+ $(GLIB2_LIBS) \
+ $(GTK3_LIBS) \
+ $(UDISKS2_LIBS) \
+ $(LIBNOTIFY_LIBS) \
+ $(NULL)
+
+# ----------------------------------------------------------------------
+
+noinst_PROGRAMS = test-plugin
+
+test_plugin_SOURCES = \
+ testplugin.c \
+ gdusdmonitor.h gdusdmonitor.c \
+ $(NULL)
+
+test_plugin_CPPFLAGS = \
+ $(NULL)
+
+test_plugin_CFLAGS = \
+ $(GLIB2_CFLAGS) \
+ $(GTK3_CFLAGS) \
+ $(UDISKS2_CFLAGS) \
+ $(LIBNOTIFY_CFLAGS) \
+ $(NULL)
+
+test_plugin_LDADD = \
+ $(GLIB2_LIBS) \
+ $(GTK3_LIBS) \
+ $(UDISKS2_LIBS) \
+ $(LIBNOTIFY_LIBS) \
+ $(NULL)
+
+# ----------------------------------------------------------------------
+
+gdu_sd_plugin_in_files = \
+ gdu-sd-plugin.gnome-settings-plugin.in \
+ $(NULL)
+
+gdu_sd_plugin_DATA = $(gdu_sd_plugin_in_files:.gnome-settings-plugin.in=.gnome-settings-plugin)
+
+%.gnome-settings-plugin: %.gnome-settings-plugin.in
+ LC_ALL=C $(INTLTOOL_MERGE) -d -u -c $(top_builddir)/po/.intltool-merge-cache $(top_srcdir)/po $< $@
+
+EXTRA_DIST = \
+ $(gdu_sd_plugin_in_files) \
+ $(NULL)
+
+CLEANFILES = \
+ $(gdu_sd_plugin_DATA) \
+ $(NULL)
+
+DISTCLEANFILES = \
+ $(gdu_sd_plugin_DATA) \
+ $(NULL)
+
+clean-local :
+ rm -f *~
diff --git a/src/notify/gdu-sd-plugin.gnome-settings-plugin.in b/src/notify/gdu-sd-plugin.gnome-settings-plugin.in
new file mode 100644
index 0000000..6c9aac6
--- /dev/null
+++ b/src/notify/gdu-sd-plugin.gnome-settings-plugin.in
@@ -0,0 +1,8 @@
+[GNOME Settings Plugin]
+Module=gdu-sd
+IAge=0
+_Name=Disks Problem Monitor
+_Description=Warns about problems with disks and storage devices
+Authors=David Zeuthen
+Copyright=Copyright © 2012 David Zeuthen
+Website=
diff --git a/src/notify/gdusdmonitor.c b/src/notify/gdusdmonitor.c
new file mode 100644
index 0000000..7267663
--- /dev/null
+++ b/src/notify/gdusdmonitor.c
@@ -0,0 +1,368 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under GPL version 2 or later.
+ *
+ * Author: David Zeuthen <zeuthen gmail com>
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+#include <libnotify/notify.h>
+
+#include <udisks/udisks.h>
+
+#include "gdusdmonitor.h"
+
+struct GduSdMonitorClass;
+typedef struct GduSdMonitorClass GduSdMonitorClass;
+
+struct GduSdMonitorClass {
+ GObjectClass parent_class;
+};
+
+struct GduSdMonitor {
+ GObject parent_instance;
+
+ UDisksClient *client;
+
+ /* ATA SMART problems */
+ GList *ata_smart_problems;
+ NotifyNotification *ata_smart_notification;
+};
+
+G_DEFINE_TYPE (GduSdMonitor, gdu_sd_monitor, G_TYPE_OBJECT);
+
+static void on_client_changed (UDisksClient *client,
+ gpointer user_data);
+
+static void update (GduSdMonitor *monitor);
+
+static void
+udisks_client_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GduSdMonitor *monitor = GDU_SD_MONITOR (user_data);
+ GError *error = NULL;
+
+ monitor->client = udisks_client_new_finish (res, &error);
+ if (monitor->client == NULL)
+ {
+ g_warning ("Error initializing udisks client: %s (%s, %d)",
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_clear_error (&error);
+ }
+ else
+ {
+ g_signal_connect (monitor->client,
+ "changed",
+ G_CALLBACK (on_client_changed),
+ monitor);
+ update (monitor);
+ }
+ g_object_unref (monitor);
+}
+
+static void
+gdu_sd_monitor_init (GduSdMonitor *monitor)
+{
+ udisks_client_new (NULL, /* GCancellable* */
+ udisks_client_cb,
+ g_object_ref (monitor));
+}
+
+static void
+gdu_sd_monitor_finalize (GObject *object)
+{
+ GduSdMonitor *monitor = GDU_SD_MONITOR (object);
+
+ if (monitor->client != NULL)
+ {
+ g_signal_handlers_disconnect_by_func (monitor->client, on_client_changed, monitor);
+ g_clear_object (&monitor->client);
+ }
+
+ g_list_free_full (monitor->ata_smart_problems, g_object_unref);
+ g_clear_object (&monitor->ata_smart_notification);
+
+ G_OBJECT_CLASS (gdu_sd_monitor_parent_class)->finalize (object);
+}
+
+static void
+gdu_sd_monitor_class_init (GduSdMonitorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = gdu_sd_monitor_finalize;
+}
+
+GduSdMonitor *
+gdu_sd_monitor_new (void)
+{
+ return GDU_SD_MONITOR (g_object_new (GDU_TYPE_SD_MONITOR, NULL));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+diff_sorted_lists (GList *list1,
+ GList *list2,
+ GCompareFunc compare,
+ GList **added,
+ GList **removed)
+{
+ int order;
+
+ *added = *removed = NULL;
+
+ while (list1 != NULL &&
+ list2 != NULL)
+ {
+ order = (*compare) (list1->data, list2->data);
+ if (order < 0)
+ {
+ *removed = g_list_prepend (*removed, list1->data);
+ list1 = list1->next;
+ }
+ else if (order > 0)
+ {
+ *added = g_list_prepend (*added, list2->data);
+ list2 = list2->next;
+ }
+ else
+ { /* same item */
+ list1 = list1->next;
+ list2 = list2->next;
+ }
+ }
+
+ while (list1 != NULL)
+ {
+ *removed = g_list_prepend (*removed, list1->data);
+ list1 = list1->next;
+ }
+ while (list2 != NULL)
+ {
+ *added = g_list_prepend (*added, list2->data);
+ list2 = list2->next;
+ }
+}
+
+static gint
+ptr_compare (gconstpointer a, gconstpointer b)
+{
+ if (a > b)
+ return 1;
+ else if (a < b)
+ return -1;
+ else
+ return 0;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef gboolean (*CheckProblemFunc) (GduSdMonitor *monitor,
+ UDisksObject *object);
+
+static void
+update_problems (GduSdMonitor *monitor,
+ GList **problem_list,
+ CheckProblemFunc check_func)
+{
+ GList *want = NULL;
+ GList *added = NULL;
+ GList *removed = NULL;
+ GList *objects;
+ GList *l;
+
+ objects = g_dbus_object_manager_get_objects (udisks_client_get_object_manager (monitor->client));
+ for (l = objects; l != NULL; l = l->next)
+ {
+ UDisksObject *object = UDISKS_OBJECT (l->data);
+ if (check_func (monitor, object))
+ want = g_list_prepend (want, object);
+ }
+
+ want = g_list_sort (want, ptr_compare);
+ *problem_list = g_list_sort (*problem_list, ptr_compare);
+ diff_sorted_lists (*problem_list,
+ want,
+ ptr_compare,
+ &added,
+ &removed);
+
+ for (l = removed; l != NULL; l = l->next)
+ {
+ UDisksObject *object = UDISKS_OBJECT (l->data);
+ *problem_list = g_list_remove (*problem_list, object);
+ g_object_unref (object);
+ }
+
+ for (l = added; l != NULL; l = l->next)
+ {
+ UDisksObject *object = UDISKS_OBJECT (l->data);
+ *problem_list = g_list_prepend (*problem_list, g_object_ref (object));
+ }
+
+ g_list_free (removed);
+ g_list_free (added);
+ g_list_free (want);
+ g_list_free_full (objects, g_object_unref);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_examine_action_clicked (NotifyNotification *notification,
+ const gchar *action,
+ gpointer user_data)
+{
+ GduSdMonitor *monitor = GDU_SD_MONITOR (user_data);
+ const gchar *device_file = NULL;
+ gchar *command_line = NULL;
+ GAppInfo *app_info = NULL;
+ GError *error = NULL;
+
+ if (g_strcmp0 (action, "examine-smart") == 0)
+ {
+ if (monitor->ata_smart_problems != NULL)
+ {
+ UDisksObject *object = UDISKS_OBJECT (monitor->ata_smart_problems->data);
+ if (object != NULL)
+ {
+ UDisksDrive *drive = udisks_object_peek_drive (object);
+ if (drive != NULL)
+ {
+ UDisksBlock *block = udisks_client_get_block_for_drive (monitor->client,
+ drive,
+ TRUE); /* get_physical */
+ if (block != NULL)
+ {
+ device_file = udisks_block_get_device (block);
+ g_object_ref (block);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ if (device_file != NULL)
+ command_line = g_strdup_printf ("gnome-disks --block-device %s", device_file);
+ else
+ command_line = g_strdup_printf ("gnome-disks");
+
+
+ app_info = g_app_info_create_from_commandline (command_line,
+ NULL, /* application name */
+ G_APP_INFO_CREATE_SUPPORTS_STARTUP_NOTIFICATION,
+ NULL);
+ if (!g_app_info_launch (app_info, NULL, NULL, &error))
+ {
+ g_warning ("Error launching gnome-disks: %s (%s, %d)",
+ error->message, g_quark_to_string (error->domain), error->code);
+ g_clear_error (&error);
+ }
+ g_clear_object (&app_info);
+ g_free (command_line);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+update_notification (GduSdMonitor *monitor,
+ GList *problems,
+ NotifyNotification **notification,
+ const gchar *title,
+ const gchar *text,
+ const gchar *icon_name,
+ const gchar *action,
+ const gchar *action_label)
+{
+ if (g_list_length (problems) > 0)
+ {
+ g_warn_if_fail (*notification == NULL);
+ *notification = notify_notification_new (title, text, icon_name);
+ notify_notification_set_urgency (*notification, NOTIFY_URGENCY_CRITICAL);
+ notify_notification_set_timeout (*notification, NOTIFY_EXPIRES_NEVER);
+ notify_notification_set_hint_string (*notification, "desktop-entry", "gnome-disks");
+ notify_notification_add_action (*notification,
+ action,
+ action_label,
+ (NotifyActionCallback) on_examine_action_clicked,
+ monitor,
+ NULL);
+ notify_notification_show (*notification, NULL);
+ }
+ else
+ {
+ if (*notification != NULL)
+ {
+ notify_notification_close (*notification, NULL);
+ g_clear_object (notification);
+ }
+ }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+
+static gboolean
+check_for_ata_smart_problem (GduSdMonitor *monitor,
+ UDisksObject *object)
+{
+ gboolean ret = FALSE;
+ UDisksDriveAta *ata = NULL;
+
+ ata = udisks_object_peek_drive_ata (object);
+ if (ata == NULL)
+ goto out;
+
+ /* For now we only check if the SMART status is set to FAIL
+ *
+ * - could add other heuristics (attributes failing, many bad sectors, temperature, etc.)
+ * - could check if user wants to ignore the failure
+ */
+ if (!udisks_drive_ata_get_smart_failing (ata))
+ goto out;
+
+ ret = TRUE;
+
+ out:
+ return ret;
+}
+
+static void
+update (GduSdMonitor *monitor)
+{
+ update_problems (monitor, &monitor->ata_smart_problems, check_for_ata_smart_problem);
+ update_notification (monitor,
+ monitor->ata_smart_problems,
+ &monitor->ata_smart_notification,
+ /* Translators: This is used as the title of the SMART failure notification */
+ C_("notify-smart", "Hard Disk Problems Detected"),
+ /* Translators: This is used as the text of the SMART failure notification */
+ C_("notify-smart", "One or more hard disks are likely to fail soon."),
+ "gnome-disks",
+ "examine-smart",
+ /* Translators: Text for button in SMART failure notification */
+ C_("notify-smart", "Examine"));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_client_changed (UDisksClient *client,
+ gpointer user_data)
+{
+ GduSdMonitor *monitor = GDU_SD_MONITOR (user_data);
+ update (monitor);
+}
diff --git a/src/notify/gdusdmonitor.h b/src/notify/gdusdmonitor.h
new file mode 100644
index 0000000..5f34974
--- /dev/null
+++ b/src/notify/gdusdmonitor.h
@@ -0,0 +1,31 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under GPL version 2 or later.
+ *
+ * Author: David Zeuthen <zeuthen gmail com>
+ */
+
+#ifndef __GDU_SD_MONITOR_H__
+#define __GDU_SD_MONITOR_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_SD_MONITOR (gdu_sd_monitor_get_type ())
+#define GDU_SD_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_SD_MONITOR, GduSdMonitor))
+#define GDU_IS_SD_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_SD_MONITOR))
+
+struct GduSdMonitor;
+typedef struct GduSdMonitor GduSdMonitor;
+
+GType gdu_sd_monitor_get_type (void) G_GNUC_CONST;
+GduSdMonitor *gdu_sd_monitor_new (void);
+
+G_END_DECLS
+
+#endif /* __GDU_SD_MONITOR_H__ */
diff --git a/src/notify/gdusdplugin.c b/src/notify/gdusdplugin.c
new file mode 100644
index 0000000..19ef845
--- /dev/null
+++ b/src/notify/gdusdplugin.c
@@ -0,0 +1,124 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under GPL version 2 or later.
+ *
+ * Author: David Zeuthen <zeuthen gmail com>
+ */
+
+#include "config.h"
+
+#include <glib/gi18n-lib.h>
+#include <gmodule.h>
+#include <gio/gio.h>
+
+#include "gdusdplugin.h"
+#include "gdusdmonitor.h"
+
+#include <gnome-settings-daemon/gnome-settings-plugin.h>
+
+struct GduSdPluginClass;
+typedef struct GduSdPluginClass GduSdPluginClass;
+
+struct GduSdPlugin
+{
+ GnomeSettingsPlugin parent_instance;
+ GduSdMonitor *monitor;
+ guint name_owner_id;
+};
+
+struct GduSdPluginClass
+{
+ GnomeSettingsPluginClass parent_class;
+};
+
+GNOME_SETTINGS_PLUGIN_REGISTER (GduSdPlugin, gdu_sd_plugin)
+
+static void
+name_acquired_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GduSdPlugin *plugin = GDU_SD_PLUGIN (user_data);
+ g_warn_if_fail (plugin->monitor == NULL);
+ g_clear_object (&plugin->monitor);
+ plugin->monitor = gdu_sd_monitor_new ();
+}
+
+static void
+name_lost_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GduSdPlugin *plugin = GDU_SD_PLUGIN (user_data);
+ g_clear_object (&plugin->monitor);
+}
+
+static void
+gdu_sd_plugin_init (GduSdPlugin *plugin)
+{
+}
+
+static void
+gdu_sd_plugin_finalize (GObject *object)
+{
+ GduSdPlugin *plugin = GDU_SD_PLUGIN (object);
+
+ if (plugin->name_owner_id == 0)
+ {
+ g_bus_unown_name (plugin->name_owner_id);
+ plugin->name_owner_id = 0;
+ g_clear_object (&plugin->monitor);
+ }
+ g_clear_object (&plugin->monitor);
+
+ G_OBJECT_CLASS (gdu_sd_plugin_parent_class)->finalize (object);
+}
+
+static void
+impl_activate (GnomeSettingsPlugin *_plugin)
+{
+ GduSdPlugin *plugin = GDU_SD_PLUGIN (_plugin);
+ /* The reason for claiming a unique name is so it's easier to test
+ * code changes - it helps ensure that only one instance of
+ * GduSdMonitor is running at any one time. See also testplugin.c.
+ */
+ if (plugin->name_owner_id == 0)
+ {
+ plugin->name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ "org.gnome.Disks.NotificationMonitor",
+ G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
+ G_BUS_NAME_OWNER_FLAGS_REPLACE,
+ NULL, /* bus_acquired_handler */
+ name_acquired_handler,
+ name_lost_handler,
+ plugin,
+ NULL); /* GDestroyNotify */
+ }
+
+}
+
+static void
+impl_deactivate (GnomeSettingsPlugin *_plugin)
+{
+ GduSdPlugin *plugin = GDU_SD_PLUGIN (_plugin);
+ if (plugin->name_owner_id == 0)
+ {
+ g_bus_unown_name (plugin->name_owner_id);
+ plugin->name_owner_id = 0;
+ g_clear_object (&plugin->monitor);
+ }
+ g_clear_object (&plugin->monitor);
+}
+
+static void
+gdu_sd_plugin_class_init (GduSdPluginClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GnomeSettingsPluginClass *plugin_class = GNOME_SETTINGS_PLUGIN_CLASS (klass);
+
+ object_class->finalize = gdu_sd_plugin_finalize;
+ plugin_class->activate = impl_activate;
+ plugin_class->deactivate = impl_deactivate;
+}
diff --git a/src/notify/gdusdplugin.h b/src/notify/gdusdplugin.h
new file mode 100644
index 0000000..5cadba1
--- /dev/null
+++ b/src/notify/gdusdplugin.h
@@ -0,0 +1,33 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under GPL version 2 or later.
+ *
+ * Author: David Zeuthen <zeuthen gmail com>
+ */
+
+#ifndef __GDU_SD_PLUGIN_H__
+#define __GDU_SD_PLUGIN_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gmodule.h>
+
+G_BEGIN_DECLS
+
+#define GDU_TYPE_SD_PLUGIN_PLUGIN (gdu_sd_plugin_get_type ())
+#define GDU_SD_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDU_TYPE_SD_PLUGIN_PLUGIN, GduSdPlugin))
+#define GDU_IS_SD_PLUGIN_PLUGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDU_TYPE_SD_PLUGIN_PLUGIN))
+
+struct GduSdPlugin;
+typedef struct GduSdPlugin GduSdPlugin;
+
+GType gdu_sd_plugin_get_type (void) G_GNUC_CONST;
+
+/* All the plugins must implement this function */
+G_MODULE_EXPORT GType register_gnome_settings_plugin (GTypeModule *module);
+
+G_END_DECLS
+
+#endif /* __GDU_SD_PLUGIN_H__ */
diff --git a/src/notify/testplugin.c b/src/notify/testplugin.c
new file mode 100644
index 0000000..756a337
--- /dev/null
+++ b/src/notify/testplugin.c
@@ -0,0 +1,74 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Licensed under GPL version 2 or later.
+ *
+ * Author: David Zeuthen <zeuthen gmail com>
+ */
+
+#include "config.h"
+
+#include <gio/gio.h>
+#include <libnotify/notify.h>
+
+#include "gdusdmonitor.h"
+
+static void
+name_acquired_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GduSdMonitor **monitor = user_data;
+
+ g_warn_if_fail (*monitor == NULL);
+ g_clear_object (monitor);
+ *monitor = gdu_sd_monitor_new ();
+}
+
+static void
+name_lost_handler (GDBusConnection *connection,
+ const gchar *name,
+ gpointer user_data)
+{
+ GduSdMonitor **monitor = user_data;
+
+ g_clear_object (monitor);
+}
+
+int
+main (int argc, char *argv[])
+{
+ GMainLoop *loop = NULL;
+ guint name_owner_id = 0;
+ GduSdMonitor *monitor = NULL;
+
+ g_type_init ();
+
+ notify_init ("test-gdusdplugin");
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ /* The reason for claiming a unique name is so it's easier to test
+ * code changes - it helps ensure that only one instance of
+ * GduSdMonitor is running at any one time. See also
+ * gdusdplugin.c:impl_activate().
+ */
+ name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ "org.gnome.Disks.NotificationMonitor",
+ G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT |
+ G_BUS_NAME_OWNER_FLAGS_REPLACE,
+ NULL, /* bus_acquired_handler */
+ name_acquired_handler,
+ name_lost_handler,
+ &monitor,
+ NULL); /* GDestroyNotify */
+
+ g_main_loop_run (loop);
+
+ g_bus_unown_name (name_owner_id);
+ g_main_loop_unref (loop);
+ g_object_unref (monitor);
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]