summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Mena Quintero <federico@novell.com>2010-01-12 14:04:16 -0600
committerFederico Mena Quintero <federico@novell.com>2010-01-27 18:34:52 -0600
commit73597b1c95df1c6faa0007f142aca24845b27d3d (patch)
tree2b3a89d78c63341c439ea83e9ae3be21d8155824
parent4049b530416b99407eaf210fded7aa2550f60ea7 (diff)
downloadgnome-settings-daemon-73597b1c95df1c6faa0007f142aca24845b27d3d.tar.gz
Add libhal-glib
-rw-r--r--plugins/media-keys/libhal-glib/Makefile.am57
-rw-r--r--plugins/media-keys/libhal-glib/egg-dbus-monitor.c250
-rw-r--r--plugins/media-keys/libhal-glib/egg-dbus-monitor.h65
-rw-r--r--plugins/media-keys/libhal-glib/egg-dbus-proxy.c293
-rw-r--r--plugins/media-keys/libhal-glib/egg-dbus-proxy.h66
-rw-r--r--plugins/media-keys/libhal-glib/egg-debug.c308
-rw-r--r--plugins/media-keys/libhal-glib/egg-debug.h83
-rw-r--r--plugins/media-keys/libhal-glib/hal-device-power.c541
-rw-r--r--plugins/media-keys/libhal-glib/hal-device-power.h77
-rw-r--r--plugins/media-keys/libhal-glib/hal-device-store.c309
-rw-r--r--plugins/media-keys/libhal-glib/hal-device-store.h67
-rw-r--r--plugins/media-keys/libhal-glib/hal-device.c636
-rw-r--r--plugins/media-keys/libhal-glib/hal-device.h96
-rw-r--r--plugins/media-keys/libhal-glib/hal-manager.c602
-rw-r--r--plugins/media-keys/libhal-glib/hal-manager.h106
-rw-r--r--plugins/media-keys/libhal-glib/hal-marshal.list9
16 files changed, 3565 insertions, 0 deletions
diff --git a/plugins/media-keys/libhal-glib/Makefile.am b/plugins/media-keys/libhal-glib/Makefile.am
new file mode 100644
index 00000000..9dc87305
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/Makefile.am
@@ -0,0 +1,57 @@
+noinst_LTLIBRARIES = \
+ libhal-glib.la
+
+libhal_glib_la_SOURCES = \
+ egg-dbus-proxy.h \
+ egg-dbus-proxy.c \
+ egg-dbus-monitor.h \
+ egg-dbus-monitor.c \
+ egg-debug.h \
+ egg-debug.c \
+ hal-marshal.h \
+ hal-marshal.c \
+ hal-device.c \
+ hal-device.h \
+ hal-manager.c \
+ hal-manager.h \
+ hal-device-store.c \
+ hal-device-store.h \
+ hal-device-power.c \
+ hal-device-power.h
+
+libhal_glib_la_CFLAGS = \
+ $(SETTINGS_PLUGIN_CFLAGS) \
+ $(GST_CFLAGS) \
+ $(AM_CFLAGS) \
+ -DEGG_LOG_FILE=\""~/dalston.log\"" \
+ -DEGG_VERBOSE="\"DALSTON_VERBOSE\"" \
+ -DEGG_LOGGING="\"DALSTON_LOGGING\"" \
+ -DEGG_CONSOLE="\"DALSTON_CONSOLE\"" \
+ -DPACKAGE_DATA_DIR=\""$(datadir)"\" \
+ -DPACKAGE_LOCALE_DIR=\""$(prefix)/$(DATADIRNAME)/locale"\"
+
+
+libhal_glib_la_LIBADD = \
+ $(GLIB_LIBS) \
+ $(DBUS_GLIB_LIBS)
+
+EXTRA_DIST = \
+ hal-marshal.list
+
+BUILT_SOURCES = \
+ hal-marshal.c \
+ hal-marshal.h
+
+hal-marshal.c: hal-marshal.list
+ echo "#include \"hal-marshal.h\"" > $@ && \
+ glib-genmarshal $< --prefix=hal_marshal --body >> $@
+
+hal-marshal.h: hal-marshal.list
+ glib-genmarshal $< --prefix=hal_marshal --header > $@
+
+clean-local:
+ rm -f *~
+ rm -f hal-marshal.c hal-marshal.h
+
+CLEANFILES = $(BUILT_SOURCES)
+
diff --git a/plugins/media-keys/libhal-glib/egg-dbus-monitor.c b/plugins/media-keys/libhal-glib/egg-dbus-monitor.c
new file mode 100644
index 00000000..3375b5d3
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/egg-dbus-monitor.c
@@ -0,0 +1,250 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2008 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <glib.h>
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <dbus/dbus.h>
+
+#include "egg-debug.h"
+#include "egg-dbus-monitor.h"
+
+static void egg_dbus_monitor_finalize (GObject *object);
+
+#define EGG_DBUS_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_DBUS_MONITOR, EggDbusMonitorPrivate))
+
+struct EggDbusMonitorPrivate
+{
+ gchar *service;
+ DBusGProxy *proxy;
+ DBusGConnection *connection;
+ const gchar *unique_name;
+};
+
+enum {
+ EGG_DBUS_MONITOR_CONNECTION_CHANGED,
+ EGG_DBUS_MONITOR_CONNECTION_REPLACED,
+ EGG_DBUS_MONITOR_LAST_SIGNAL
+};
+
+static guint signals [EGG_DBUS_MONITOR_LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (EggDbusMonitor, egg_dbus_monitor, G_TYPE_OBJECT)
+
+/**
+ * egg_dbus_monitor_name_owner_changed_cb:
+ **/
+static void
+egg_dbus_monitor_name_owner_changed_cb (DBusGProxy *proxy, const gchar *name,
+ const gchar *prev, const gchar *new,
+ EggDbusMonitor *monitor)
+{
+ guint new_len;
+ guint prev_len;
+
+ g_return_if_fail (EGG_IS_DBUS_MONITOR (monitor));
+ if (monitor->priv->proxy == NULL)
+ return;
+
+ /* not us */
+ if (strcmp (name, monitor->priv->service) != 0)
+ return;
+
+ /* ITS4: ignore, not used for allocation */
+ new_len = strlen (new);
+ /* ITS4: ignore, not used for allocation */
+ prev_len = strlen (prev);
+
+ /* something --> nothing */
+ if (prev_len != 0 && new_len == 0) {
+ g_signal_emit (monitor, signals [EGG_DBUS_MONITOR_CONNECTION_CHANGED], 0, FALSE);
+ return;
+ }
+
+ /* nothing --> something */
+ if (prev_len == 0 && new_len != 0) {
+ g_signal_emit (monitor, signals [EGG_DBUS_MONITOR_CONNECTION_CHANGED], 0, TRUE);
+ return;
+ }
+
+ /* something --> something (we've replaced the old process) */
+ if (prev_len != 0 && new_len != 0) {
+ /* only send this to the prev client */
+ if (strcmp (monitor->priv->unique_name, prev) == 0)
+ g_signal_emit (monitor, signals [EGG_DBUS_MONITOR_CONNECTION_REPLACED], 0);
+ return;
+ }
+}
+
+/**
+ * egg_dbus_monitor_assign:
+ * @monitor: This class instance
+ * @connection: The bus connection
+ * @service: The EGG_DBUS_MONITOR service name
+ * Return value: success
+ *
+ * Emits connection-changed(TRUE) if connection is alive - this means you
+ * have to connect up the callback before this function is called.
+ **/
+gboolean
+egg_dbus_monitor_assign (EggDbusMonitor *monitor, DBusGConnection *connection, const gchar *service)
+{
+ GError *error = NULL;
+ gboolean connected;
+ DBusConnection *conn;
+
+ g_return_val_if_fail (EGG_IS_DBUS_MONITOR (monitor), FALSE);
+ g_return_val_if_fail (service != NULL, FALSE);
+ g_return_val_if_fail (connection != NULL, FALSE);
+
+ if (monitor->priv->proxy != NULL) {
+ egg_warning ("already assigned!");
+ return FALSE;
+ }
+
+ monitor->priv->service = g_strdup (service);
+ monitor->priv->connection = connection;
+ monitor->priv->proxy = dbus_g_proxy_new_for_name (monitor->priv->connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ if (error != NULL) {
+ egg_warning ("Cannot connect to DBUS: %s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+ dbus_g_proxy_add_signal (monitor->priv->proxy, "NameOwnerChanged",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (monitor->priv->proxy, "NameOwnerChanged",
+ G_CALLBACK (egg_dbus_monitor_name_owner_changed_cb),
+ monitor, NULL);
+
+ /* coldplug */
+ connected = egg_dbus_monitor_is_connected (monitor);
+ if (connected)
+ g_signal_emit (monitor, signals [EGG_DBUS_MONITOR_CONNECTION_CHANGED], 0, TRUE);
+
+ /* save this for the replaced check */
+ conn = dbus_g_connection_get_connection (monitor->priv->connection);
+ monitor->priv->unique_name = dbus_bus_get_unique_name (conn);
+ return TRUE;
+}
+
+/**
+ * egg_dbus_monitor_is_connected:
+ * @monitor: This class instance
+ * Return value: if we are connected to a valid watch
+ **/
+gboolean
+egg_dbus_monitor_is_connected (EggDbusMonitor *monitor)
+{
+ DBusError error;
+ DBusConnection *conn;
+ gboolean ret;
+ g_return_val_if_fail (EGG_IS_DBUS_MONITOR (monitor), FALSE);
+
+ /* get raw connection */
+ conn = dbus_g_connection_get_connection (monitor->priv->connection);
+ dbus_error_init (&error);
+ ret = dbus_bus_name_has_owner (conn, monitor->priv->service, &error);
+ if (dbus_error_is_set (&error)) {
+ egg_debug ("error: %s", error.message);
+ dbus_error_free (&error);
+ }
+
+ return ret;
+}
+
+/**
+ * egg_dbus_monitor_class_init:
+ * @klass: The EggDbusMonitorClass
+ **/
+static void
+egg_dbus_monitor_class_init (EggDbusMonitorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = egg_dbus_monitor_finalize;
+ g_type_class_add_private (klass, sizeof (EggDbusMonitorPrivate));
+ signals [EGG_DBUS_MONITOR_CONNECTION_CHANGED] =
+ g_signal_new ("connection-changed",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggDbusMonitorClass, connection_changed),
+ NULL, NULL, g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+ signals [EGG_DBUS_MONITOR_CONNECTION_REPLACED] =
+ g_signal_new ("connection-replaced",
+ G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggDbusMonitorClass, connection_replaced),
+ NULL, NULL, g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+}
+
+/**
+ * egg_dbus_monitor_init:
+ * @monitor: This class instance
+ **/
+static void
+egg_dbus_monitor_init (EggDbusMonitor *monitor)
+{
+ monitor->priv = EGG_DBUS_MONITOR_GET_PRIVATE (monitor);
+ monitor->priv->service = NULL;
+ monitor->priv->connection = NULL;
+ monitor->priv->proxy = NULL;
+}
+
+/**
+ * egg_dbus_monitor_finalize:
+ * @object: The object to finalize
+ **/
+static void
+egg_dbus_monitor_finalize (GObject *object)
+{
+ EggDbusMonitor *monitor;
+
+ g_return_if_fail (EGG_IS_DBUS_MONITOR (object));
+
+ monitor = EGG_DBUS_MONITOR (object);
+
+ g_return_if_fail (monitor->priv != NULL);
+ if (monitor->priv->proxy != NULL)
+ g_object_unref (monitor->priv->proxy);
+
+ G_OBJECT_CLASS (egg_dbus_monitor_parent_class)->finalize (object);
+}
+
+/**
+ * egg_dbus_monitor_new:
+ *
+ * Return value: a new EggDbusMonitor object.
+ **/
+EggDbusMonitor *
+egg_dbus_monitor_new (void)
+{
+ EggDbusMonitor *monitor;
+ monitor = g_object_new (EGG_TYPE_DBUS_MONITOR, NULL);
+ return EGG_DBUS_MONITOR (monitor);
+}
+
diff --git a/plugins/media-keys/libhal-glib/egg-dbus-monitor.h b/plugins/media-keys/libhal-glib/egg-dbus-monitor.h
new file mode 100644
index 00000000..6aea31d4
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/egg-dbus-monitor.h
@@ -0,0 +1,65 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2008 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_DBUS_MONITOR_H
+#define __EGG_DBUS_MONITOR_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_DBUS_MONITOR (egg_dbus_monitor_get_type ())
+#define EGG_DBUS_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EGG_TYPE_DBUS_MONITOR, EggDbusMonitor))
+#define EGG_DBUS_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EGG_TYPE_DBUS_MONITOR, EggDbusMonitorClass))
+#define EGG_IS_DBUS_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EGG_TYPE_DBUS_MONITOR))
+#define EGG_IS_DBUS_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EGG_TYPE_DBUS_MONITOR))
+#define EGG_DBUS_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EGG_TYPE_DBUS_MONITOR, EggDbusMonitorClass))
+#define EGG_DBUS_MONITOR_ERROR (egg_dbus_monitor_error_quark ())
+#define EGG_DBUS_MONITOR_TYPE_ERROR (egg_dbus_monitor_error_get_type ())
+
+typedef struct EggDbusMonitorPrivate EggDbusMonitorPrivate;
+
+typedef struct
+{
+ GObject parent;
+ EggDbusMonitorPrivate *priv;
+} EggDbusMonitor;
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (* connection_changed) (EggDbusMonitor *watch,
+ gboolean connected);
+ void (* connection_replaced) (EggDbusMonitor *watch);
+} EggDbusMonitorClass;
+
+GType egg_dbus_monitor_get_type (void);
+EggDbusMonitor *egg_dbus_monitor_new (void);
+gboolean egg_dbus_monitor_assign (EggDbusMonitor *monitor,
+ DBusGConnection *connection,
+ const gchar *service);
+gboolean egg_dbus_monitor_is_connected (EggDbusMonitor *monitor);
+
+G_END_DECLS
+
+#endif /* __EGG_DBUS_MONITOR_H */
+
diff --git a/plugins/media-keys/libhal-glib/egg-dbus-proxy.c b/plugins/media-keys/libhal-glib/egg-dbus-proxy.c
new file mode 100644
index 00000000..a76f7b67
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/egg-dbus-proxy.c
@@ -0,0 +1,293 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2008 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+
+#include "egg-debug.h"
+#include "egg-dbus-monitor.h"
+#include "egg-dbus-proxy.h"
+
+static void egg_dbus_proxy_finalize (GObject *object);
+
+#define EGG_DBUS_PROXY_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), EGG_TYPE_DBUS_PROXY, EggDbusProxyPrivate))
+
+/* this is a managed proxy, i.e. a proxy that handles messagebus and DBUS service restarts. */
+struct EggDbusProxyPrivate
+{
+ gchar *service;
+ gchar *interface;
+ gchar *path;
+ DBusGProxy *proxy;
+ EggDbusMonitor *monitor;
+ gboolean assigned;
+ DBusGConnection *connection;
+ gulong monitor_callback_id;
+};
+
+enum {
+ PROXY_STATUS,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (EggDbusProxy, egg_dbus_proxy, G_TYPE_OBJECT)
+
+/**
+ * egg_dbus_proxy_connect:
+ * @proxy: This class instance
+ * Return value: success
+ **/
+static gboolean
+egg_dbus_proxy_connect (EggDbusProxy *proxy)
+{
+ g_return_val_if_fail (EGG_IS_DBUS_PROXY (proxy), FALSE);
+
+ /* are already connected? */
+ if (proxy->priv->proxy != NULL) {
+ egg_debug ("already connected to %s", proxy->priv->service);
+ return FALSE;
+ }
+
+ proxy->priv->proxy = dbus_g_proxy_new_for_name (proxy->priv->connection,
+ proxy->priv->service,
+ proxy->priv->path,
+ proxy->priv->interface);
+
+ /* shouldn't be, but make sure proxy valid */
+ if (proxy->priv->proxy == NULL) {
+ egg_debug ("proxy is NULL, maybe the daemon responsible "
+ "for %s is not running?", proxy->priv->service);
+ return FALSE;
+ }
+
+ if (egg_dbus_proxy_is_connected (proxy))
+ g_signal_emit (proxy, signals [PROXY_STATUS], 0, TRUE);
+
+ return TRUE;
+}
+
+/**
+ * egg_dbus_proxy_disconnect:
+ * @proxy: This class instance
+ * Return value: success
+ **/
+static gboolean
+egg_dbus_proxy_disconnect (EggDbusProxy *proxy)
+{
+ g_return_val_if_fail (EGG_IS_DBUS_PROXY (proxy), FALSE);
+
+ /* are already disconnected? */
+ if (proxy->priv->proxy == NULL) {
+ if (proxy->priv->service)
+ egg_debug ("already disconnected from %s", proxy->priv->service);
+ else
+ egg_debug ("already disconnected.");
+ return FALSE;
+ }
+
+ g_signal_emit (proxy, signals [PROXY_STATUS], 0, FALSE);
+
+ g_object_unref (proxy->priv->proxy);
+ proxy->priv->proxy = NULL;
+
+ return TRUE;
+}
+
+/**
+ * dbus_monitor_connection_cb:
+ * @proxy: The dbus raw proxy
+ * @status: The status of the service, where TRUE is connected
+ * @screensaver: This class instance
+ **/
+static void
+dbus_monitor_connection_cb (EggDbusMonitor *monitor, gboolean status, EggDbusProxy *proxy)
+{
+ g_return_if_fail (EGG_IS_DBUS_PROXY (proxy));
+ if (proxy->priv->assigned == FALSE)
+ return;
+ if (status)
+ g_signal_emit (proxy, signals [PROXY_STATUS], 0, TRUE);
+ else
+ g_signal_emit (proxy, signals [PROXY_STATUS], 0, FALSE);
+}
+
+/**
+ * egg_dbus_proxy_assign:
+ * @proxy: This class instance
+ * @connections: The bus connection
+ * @service: The DBUS service name
+ * @interface: The DBUS interface
+ * @path: The DBUS path
+ * Return value: The DBUS proxy, or NULL if we haven't connected yet.
+ **/
+DBusGProxy *
+egg_dbus_proxy_assign (EggDbusProxy *proxy, DBusGConnection *connection,
+ const gchar *service, const gchar *path, const gchar *interface)
+{
+ g_return_val_if_fail (EGG_IS_DBUS_PROXY (proxy), NULL);
+ g_return_val_if_fail (connection != NULL, NULL);
+ g_return_val_if_fail (service != NULL, NULL);
+ g_return_val_if_fail (interface != NULL, NULL);
+ g_return_val_if_fail (path != NULL, NULL);
+
+ if (proxy->priv->assigned) {
+ egg_warning ("already assigned proxy!");
+ return NULL;
+ }
+
+ proxy->priv->service = g_strdup (service);
+ proxy->priv->interface = g_strdup (interface);
+ proxy->priv->path = g_strdup (path);
+ proxy->priv->connection = connection;
+ proxy->priv->assigned = TRUE;
+
+ /* We have to save the connection and remove the signal id later as
+ instances of this object are likely to be registering with a
+ singleton object many times */
+ egg_dbus_monitor_assign (proxy->priv->monitor, connection, service);
+
+ /* try to connect and return proxy (or NULL if invalid) */
+ egg_dbus_proxy_connect (proxy);
+
+ return proxy->priv->proxy;
+}
+
+/**
+ * egg_dbus_proxy_get_proxy:
+ * @proxy: This class instance
+ * Return value: The DBUS proxy, or NULL if we are not connected
+ **/
+DBusGProxy *
+egg_dbus_proxy_get_proxy (EggDbusProxy *proxy)
+{
+ g_return_val_if_fail (EGG_IS_DBUS_PROXY (proxy), NULL);
+ if (proxy->priv->assigned == FALSE)
+ return NULL;
+ return proxy->priv->proxy;
+}
+
+/**
+ * egg_dbus_proxy_is_connected:
+ * @proxy: This class instance
+ * Return value: if we are connected to a valid proxy
+ **/
+gboolean
+egg_dbus_proxy_is_connected (EggDbusProxy *proxy)
+{
+ g_return_val_if_fail (EGG_IS_DBUS_PROXY (proxy), FALSE);
+ if (proxy->priv->assigned == FALSE)
+ return FALSE;
+ if (proxy->priv->proxy == NULL)
+ return FALSE;
+ return TRUE;
+}
+
+/**
+ * egg_dbus_proxy_class_init:
+ * @proxy: This class instance
+ **/
+static void
+egg_dbus_proxy_class_init (EggDbusProxyClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = egg_dbus_proxy_finalize;
+ g_type_class_add_private (klass, sizeof (EggDbusProxyPrivate));
+
+ signals [PROXY_STATUS] =
+ g_signal_new ("proxy-status",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (EggDbusProxyClass, proxy_status),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
+}
+
+/**
+ * egg_dbus_proxy_init:
+ * @egg_dbus_proxy: This class instance
+ **/
+static void
+egg_dbus_proxy_init (EggDbusProxy *proxy)
+{
+ proxy->priv = EGG_DBUS_PROXY_GET_PRIVATE (proxy);
+
+ proxy->priv->connection = NULL;
+ proxy->priv->proxy = NULL;
+ proxy->priv->service = NULL;
+ proxy->priv->interface = NULL;
+ proxy->priv->path = NULL;
+ proxy->priv->assigned = FALSE;
+ proxy->priv->monitor = egg_dbus_monitor_new ();
+ proxy->priv->monitor_callback_id =
+ g_signal_connect (proxy->priv->monitor, "connection-changed",
+ G_CALLBACK (dbus_monitor_connection_cb), proxy);
+ proxy->priv->monitor_callback_id = 0;
+}
+
+/**
+ * egg_dbus_proxy_finalize:
+ * @object: This class instance
+ **/
+static void
+egg_dbus_proxy_finalize (GObject *object)
+{
+ EggDbusProxy *proxy;
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (EGG_IS_DBUS_PROXY (object));
+
+ proxy = EGG_DBUS_PROXY (object);
+ proxy->priv = EGG_DBUS_PROXY_GET_PRIVATE (proxy);
+
+ if (proxy->priv->monitor_callback_id != 0)
+ g_signal_handler_disconnect (proxy->priv->monitor,
+ proxy->priv->monitor_callback_id);
+
+ egg_dbus_proxy_disconnect (proxy);
+
+ if (proxy->priv->proxy != NULL)
+ g_object_unref (proxy->priv->proxy);
+ g_object_unref (proxy->priv->monitor);
+ g_free (proxy->priv->service);
+ g_free (proxy->priv->interface);
+ g_free (proxy->priv->path);
+
+ G_OBJECT_CLASS (egg_dbus_proxy_parent_class)->finalize (object);
+}
+
+/**
+ * egg_dbus_proxy_new:
+ * Return value: new class instance.
+ **/
+EggDbusProxy *
+egg_dbus_proxy_new (void)
+{
+ EggDbusProxy *proxy;
+ proxy = g_object_new (EGG_TYPE_DBUS_PROXY, NULL);
+ return EGG_DBUS_PROXY (proxy);
+}
+
diff --git a/plugins/media-keys/libhal-glib/egg-dbus-proxy.h b/plugins/media-keys/libhal-glib/egg-dbus-proxy.h
new file mode 100644
index 00000000..2d904d5b
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/egg-dbus-proxy.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006-2008 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __DBUSPROXY_H
+#define __DBUSPROXY_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define EGG_TYPE_DBUS_PROXY (egg_dbus_proxy_get_type ())
+#define EGG_DBUS_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), EGG_TYPE_DBUS_PROXY, EggDbusProxy))
+#define EGG_DBUS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), EGG_TYPE_DBUS_PROXY, EggDbusProxyClass))
+#define EGG_IS_DBUS_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), EGG_TYPE_DBUS_PROXY))
+#define EGG_IS_DBUS_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), EGG_TYPE_DBUS_PROXY))
+#define EGG_DBUS_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), EGG_TYPE_DBUS_PROXY, EggDbusProxyClass))
+
+typedef struct EggDbusProxyPrivate EggDbusProxyPrivate;
+
+typedef struct
+{
+ GObject parent;
+ EggDbusProxyPrivate *priv;
+} EggDbusProxy;
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (* proxy_status) (EggDbusProxy *proxy,
+ gboolean status);
+} EggDbusProxyClass;
+
+GType egg_dbus_proxy_get_type (void);
+EggDbusProxy *egg_dbus_proxy_new (void);
+
+DBusGProxy *egg_dbus_proxy_assign (EggDbusProxy *dbus_proxy,
+ DBusGConnection *connection,
+ const gchar *service,
+ const gchar *path,
+ const gchar *interface);
+DBusGProxy *egg_dbus_proxy_get_proxy (EggDbusProxy *egg_dbus_proxy);
+gboolean egg_dbus_proxy_is_connected (EggDbusProxy *egg_dbus_proxy);
+
+G_END_DECLS
+
+#endif /* __DBUSPROXY_H */
+
diff --git a/plugins/media-keys/libhal-glib/egg-debug.c b/plugins/media-keys/libhal-glib/egg-debug.c
new file mode 100644
index 00000000..f18a5d1f
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/egg-debug.c
@@ -0,0 +1,308 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:egg-debug
+ * @short_description: Debugging functions
+ *
+ * This file contains functions that can be used for debugging.
+ */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gprintf.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <execinfo.h>
+
+#include "egg-debug.h"
+
+#define CONSOLE_RESET 0
+#define CONSOLE_BLACK 30
+#define CONSOLE_RED 31
+#define CONSOLE_GREEN 32
+#define CONSOLE_YELLOW 33
+#define CONSOLE_BLUE 34
+#define CONSOLE_MAGENTA 35
+#define CONSOLE_CYAN 36
+#define CONSOLE_WHITE 37
+
+static gint fd = -1;
+
+/**
+ * pk_set_console_mode:
+ **/
+static void
+pk_set_console_mode (guint console_code)
+{
+ gchar command[13];
+
+ /* don't put extra commands into logs */
+ if (!egg_debug_is_console ())
+ return;
+
+ /* Command is the control command to the terminal */
+ g_snprintf (command, 13, "%c[%dm", 0x1B, console_code);
+ printf ("%s", command);
+}
+
+/**
+ * egg_debug_backtrace:
+ **/
+void
+egg_debug_backtrace (void)
+{
+ void *call_stack[512];
+ int call_stack_size;
+ char **symbols;
+ int i = 1;
+
+ call_stack_size = backtrace (call_stack, G_N_ELEMENTS (call_stack));
+ symbols = backtrace_symbols (call_stack, call_stack_size);
+ if (symbols != NULL) {
+ pk_set_console_mode (CONSOLE_RED);
+ g_print ("Traceback:\n");
+ while (i < call_stack_size) {
+ g_print ("\t%s\n", symbols[i]);
+ i++;
+ }
+ pk_set_console_mode (CONSOLE_RESET);
+ free (symbols);
+ }
+}
+
+/**
+ * pk_log_line:
+ **/
+static void
+pk_log_line (const gchar *buffer)
+{
+ ssize_t count;
+ /* open a file */
+ if (fd == -1) {
+ /* ITS4: ignore, /var/log/foo is owned by root, and this is just debug text */
+ fd = open (EGG_LOG_FILE, O_WRONLY|O_APPEND|O_CREAT, 0777);
+ if (fd == -1)
+ g_error ("could not open log: '%s'", EGG_LOG_FILE);
+ }
+
+ /* ITS4: ignore, debug text always NULL terminated */
+ count = write (fd, buffer, strlen (buffer));
+ if (count == -1)
+ g_warning ("could not write %s", buffer);
+ /* newline */
+ count = write (fd, "\n", 1);
+ if (count == -1)
+ g_warning ("could not write newline");
+}
+
+/**
+ * pk_print_line:
+ **/
+static void
+pk_print_line (const gchar *func, const gchar *file, const int line, const gchar *buffer, guint color)
+{
+ gchar *str_time;
+ gchar *header;
+ time_t the_time;
+ GThread *thread;
+
+ time (&the_time);
+ str_time = g_new0 (gchar, 255);
+ strftime (str_time, 254, "%H:%M:%S", localtime (&the_time));
+ thread = g_thread_self ();
+
+ /* generate header text */
+ header = g_strdup_printf ("TI:%s\tTH:%p\tFI:%s\tFN:%s,%d", str_time, thread, file, func, line);
+ g_free (str_time);
+
+ /* always in light green */
+ pk_set_console_mode (CONSOLE_GREEN);
+ printf ("%s\n", header);
+
+ /* different colors according to the severity */
+ pk_set_console_mode (color);
+ printf (" - %s\n", buffer);
+ pk_set_console_mode (CONSOLE_RESET);
+
+ /* log to a file */
+ if (egg_debug_is_logging ()) {
+ pk_log_line (header);
+ pk_log_line (buffer);
+ }
+
+ /* flush this output, as we need to debug */
+ fflush (stdout);
+
+ g_free (header);
+}
+
+/**
+ * egg_debug_real:
+ **/
+void
+egg_debug_real (const gchar *func, const gchar *file, const int line, const gchar *format, ...)
+{
+ va_list args;
+ gchar *buffer = NULL;
+
+ if (!egg_debug_enabled ())
+ return;
+
+ va_start (args, format);
+ g_vasprintf (&buffer, format, args);
+ va_end (args);
+
+ pk_print_line (func, file, line, buffer, CONSOLE_BLUE);
+
+ g_free(buffer);
+}
+
+/**
+ * egg_warning_real:
+ **/
+void
+egg_warning_real (const gchar *func, const gchar *file, const int line, const gchar *format, ...)
+{
+ va_list args;
+ gchar *buffer = NULL;
+
+ if (!egg_debug_enabled ())
+ return;
+
+ va_start (args, format);
+ g_vasprintf (&buffer, format, args);
+ va_end (args);
+
+ /* do extra stuff for a warning */
+ if (!egg_debug_is_console ())
+ printf ("*** WARNING ***\n");
+ pk_print_line (func, file, line, buffer, CONSOLE_RED);
+
+ g_free(buffer);
+}
+
+/**
+ * egg_error_real:
+ **/
+void
+egg_error_real (const gchar *func, const gchar *file, const int line, const gchar *format, ...)
+{
+ va_list args;
+ gchar *buffer = NULL;
+
+ va_start (args, format);
+ g_vasprintf (&buffer, format, args);
+ va_end (args);
+
+ /* do extra stuff for a warning */
+ if (!egg_debug_is_console ())
+ printf ("*** ERROR ***\n");
+ pk_print_line (func, file, line, buffer, CONSOLE_RED);
+ g_free(buffer);
+
+ /* we want to fix this! */
+ egg_debug_backtrace ();
+
+ exit (1);
+}
+
+/**
+ * egg_debug_enabled:
+ *
+ * Returns: TRUE if we have debugging enabled
+ **/
+gboolean
+egg_debug_enabled (void)
+{
+ const gchar *env;
+ env = g_getenv (EGG_VERBOSE);
+ return (g_strcmp0 (env, "1") == 0);
+}
+
+/**
+ * egg_debug_is_logging:
+ *
+ * Returns: TRUE if we have logging enabled
+ **/
+gboolean
+egg_debug_is_logging (void)
+{
+ const gchar *env;
+ env = g_getenv (EGG_LOGGING);
+ return (g_strcmp0 (env, "1") == 0);
+}
+
+/**
+ * egg_debug_is_console:
+ *
+ * Returns: TRUE if we have debugging enabled
+ **/
+gboolean
+egg_debug_is_console (void)
+{
+ const gchar *env;
+ env = g_getenv (EGG_CONSOLE);
+ return (g_strcmp0 (env, "1") == 0);
+}
+
+/**
+ * egg_debug_set_logging:
+ **/
+void
+egg_debug_set_logging (gboolean enabled)
+{
+ if (enabled)
+ g_setenv (EGG_LOGGING, "1", TRUE);
+ else
+ g_setenv (EGG_LOGGING, "0", TRUE);
+
+ if (egg_debug_is_logging ())
+ egg_debug ("logging to %s", EGG_LOG_FILE);
+}
+
+/**
+ * egg_debug_init:
+ * @debug: If we should print out verbose logging
+ **/
+void
+egg_debug_init (gboolean debug)
+{
+ /* check if we are on console */
+ if (isatty (fileno (stdout)) == 1)
+ g_setenv (EGG_CONSOLE, "1", FALSE);
+ else
+ g_setenv (EGG_CONSOLE, "0", FALSE);
+ if (debug)
+ g_setenv (EGG_VERBOSE, "1", FALSE);
+ else
+ g_setenv (EGG_VERBOSE, "0", FALSE);
+ egg_debug ("Verbose debugging %i (on console %i)%s", egg_debug_enabled (), egg_debug_is_console (), EGG_VERBOSE);
+}
+
diff --git a/plugins/media-keys/libhal-glib/egg-debug.h b/plugins/media-keys/libhal-glib/egg-debug.h
new file mode 100644
index 00000000..c935dcb1
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/egg-debug.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007-2008 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EGG_DEBUG_H
+#define __EGG_DEBUG_H
+
+#include <stdarg.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+/**
+ * egg_debug:
+ *
+ * Non critical debugging
+ */
+#define egg_debug(...) egg_debug_real (__func__, __FILE__, __LINE__, __VA_ARGS__)
+
+/**
+ * egg_warning:
+ *
+ * Important debugging
+ */
+#define egg_warning(...) egg_warning_real (__func__, __FILE__, __LINE__, __VA_ARGS__)
+
+/**
+ * egg_error:
+ *
+ * Critical debugging, with exit
+ */
+#define egg_error(...) egg_error_real (__func__, __FILE__, __LINE__, __VA_ARGS__)
+
+#elif defined(__GNUC__) && __GNUC__ >= 3
+#define egg_debug(...) egg_debug_real (__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
+#define egg_warning(...) egg_warning_real (__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
+#define egg_error(...) egg_error_real (__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define egg_debug(...)
+#define egg_warning(...)
+#define egg_error(...)
+#endif
+
+void egg_debug_init (gboolean debug);
+void egg_debug_set_logging (gboolean enabled);
+gboolean egg_debug_enabled (void);
+gboolean egg_debug_is_logging (void);
+gboolean egg_debug_is_console (void);
+void egg_debug_backtrace (void);
+void egg_debug_real (const gchar *func,
+ const gchar *file,
+ int line,
+ const gchar *format, ...) __attribute__((format (printf,4,5)));
+void egg_warning_real (const gchar *func,
+ const gchar *file,
+ int line,
+ const gchar *format, ...) __attribute__((format (printf,4,5)));
+void egg_error_real (const gchar *func,
+ const gchar *file,
+ int line,
+ const gchar *format, ...) G_GNUC_NORETURN __attribute__((format (printf,4,5)));
+
+G_END_DECLS
+
+#endif /* __EGG_DEBUG_H */
diff --git a/plugins/media-keys/libhal-glib/hal-device-power.c b/plugins/media-keys/libhal-glib/hal-device-power.c
new file mode 100644
index 00000000..69c80612
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-device-power.c
@@ -0,0 +1,541 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005-2007 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+#include <time.h>
+
+#include "egg-debug.h"
+#include "egg-dbus-proxy.h"
+
+#include "hal-marshal.h"
+#include "hal-device-power.h"
+#include "hal-device.h"
+#include "hal-manager.h"
+
+static void hal_device_power_class_init (HalDevicePowerClass *klass);
+static void hal_device_power_init (HalDevicePower *power);
+static void hal_device_power_finalize (GObject *object);
+
+#define HAL_DEVICE_POWER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), HAL_TYPE_DEVICE_POWER, HalDevicePowerPrivate))
+
+struct HalDevicePowerPrivate
+{
+ HalDevice *computer;
+ EggDbusProxy *gproxy;
+};
+
+static gpointer hal_device_power_object = NULL;
+G_DEFINE_TYPE (HalDevicePower, hal_device_power, G_TYPE_OBJECT)
+
+/**
+ * hal_device_power_class_init:
+ * @klass: This class instance
+ **/
+static void
+hal_device_power_class_init (HalDevicePowerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = hal_device_power_finalize;
+ g_type_class_add_private (klass, sizeof (HalDevicePowerPrivate));
+}
+
+/**
+ * hal_device_power_init:
+ *
+ * @power: This class instance
+ **/
+static void
+hal_device_power_init (HalDevicePower *power)
+{
+ DBusGConnection *connection;
+ power->priv = HAL_DEVICE_POWER_GET_PRIVATE (power);
+
+ /* get the power connection */
+ power->priv->gproxy = egg_dbus_proxy_new ();
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+ egg_dbus_proxy_assign (power->priv->gproxy, connection, HAL_DBUS_SERVICE,
+ HAL_ROOT_COMPUTER, HAL_DBUS_INTERFACE_POWER);
+ if (power->priv->gproxy == NULL)
+ egg_warning ("HAL does not support power management!");
+
+ power->priv->computer = hal_device_new ();
+ hal_device_set_udi (power->priv->computer, HAL_ROOT_COMPUTER);
+}
+
+/**
+ * hal_device_power_is_laptop:
+ *
+ * @power: This class instance
+ * Return value: TRUE is computer is identified as a laptop
+ *
+ * Returns true if system.formfactor is "laptop"
+ **/
+gboolean
+hal_device_power_is_laptop (HalDevicePower *power)
+{
+ gboolean ret = TRUE;
+ gchar *formfactor = NULL;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+
+ /* always present */
+ hal_device_get_string (power->priv->computer, "system.formfactor", &formfactor, NULL);
+ if (formfactor == NULL) {
+ /* no need to free */
+ return FALSE;
+ }
+ if (strcmp (formfactor, "laptop") != 0) {
+ egg_debug ("This machine is not identified as a laptop."
+ "system.formfactor is %s.", formfactor);
+ ret = FALSE;
+ }
+ g_free (formfactor);
+ return ret;
+}
+
+/**
+ * hal_device_power_has_support:
+ *
+ * @power: This class instance
+ * Return value: TRUE if haldaemon has power management capability
+ *
+ * Finds out if power management functions are running (only ACPI, PMU, APM)
+ **/
+gboolean
+hal_device_power_has_support (HalDevicePower *power)
+{
+ gchar *type = NULL;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+
+ hal_device_get_string (power->priv->computer, "power_management.type", &type, NULL);
+ /* this key only has to exist to be pm okay */
+ if (type != NULL) {
+ g_free (type);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * hal_device_power_can_suspend:
+ *
+ * @power: This class instance
+ * Return value: TRUE if kernel suspend support is compiled in
+ *
+ * Finds out if HAL indicates that we can suspend
+ **/
+gboolean
+hal_device_power_can_suspend (HalDevicePower *power)
+{
+ gboolean exists;
+ gboolean can_suspend;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+
+ /* TODO: Change to can_suspend when rely on newer HAL */
+ exists = hal_device_get_bool (power->priv->computer,
+ "power_management.can_suspend",
+ &can_suspend, NULL);
+ if (exists == FALSE) {
+ egg_warning ("Key can_suspend missing");
+ return FALSE;
+ }
+ return can_suspend;
+}
+
+/**
+ * hal_device_power_can_hibernate:
+ *
+ * @power: This class instance
+ * Return value: TRUE if kernel hibernation support is compiled in
+ *
+ * Finds out if HAL indicates that we can hibernate
+ **/
+gboolean
+hal_device_power_can_hibernate (HalDevicePower *power)
+{
+ gboolean exists;
+ gboolean can_hibernate;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+
+ /* TODO: Change to can_hibernate when rely on newer HAL */
+ exists = hal_device_get_bool (power->priv->computer,
+ "power_management.can_hibernate",
+ &can_hibernate, NULL);
+ if (exists == FALSE) {
+ egg_warning ("Key can_hibernate missing");
+ return FALSE;
+ }
+ return can_hibernate;
+}
+
+/**
+ * hal_device_power_filter_error:
+ *
+ * We have to ignore dbus timeouts sometimes
+ **/
+static gboolean
+hal_device_power_filter_error (GError **error)
+{
+ /* short cut for speed, no error */
+ if (error == NULL || *error == NULL)
+ return FALSE;
+
+ /* DBUS might time out, which is okay. We can remove this code
+ when the dbus glib bindings are fixed. See #332888 */
+ if (g_error_matches (*error, DBUS_GERROR, DBUS_GERROR_NO_REPLY)) {
+ egg_warning ("DBUS timed out, but recovering");
+ g_error_free (*error);
+ *error = NULL;
+ return TRUE;
+ }
+ egg_warning ("Method failed\n(%s)", (*error)->message);
+ return FALSE;
+}
+
+/**
+ * hal_device_power_suspend:
+ *
+ * @power: This class instance
+ * @wakeup: Seconds to wakeup, currently unsupported
+ * Return value: Success, true if we suspended OK
+ *
+ * Uses org.freedesktop.Hal.Device.SystemPowerManagement.Suspend ()
+ **/
+gboolean
+hal_device_power_suspend (HalDevicePower *power, guint wakeup, GError **error)
+{
+ time_t start;
+ time_t end;
+ gint retval = 0;
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (power->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+
+ time (&start);
+ ret = dbus_g_proxy_call (proxy, "Suspend", error,
+ G_TYPE_INT, wakeup,
+ G_TYPE_INVALID,
+ G_TYPE_INT, &retval,
+ G_TYPE_INVALID);
+ /* we might have to ignore the error */
+ if (error != NULL && hal_device_power_filter_error (error))
+ return TRUE;
+ if (retval != 0)
+ egg_warning ("Suspend failed without error message");
+
+ /* compare the amount of time that has passed - if it's more than 6 hours
+ * then the dbus call timed out (dbus-pending-call.c) */
+ if (ret != 0) {
+ time (&end);
+ if (difftime (start, end) >= 6*60*60*1000)
+ return TRUE;
+ }
+
+ return ret;
+}
+
+/**
+ * hal_device_power_pm_method_void:
+ *
+ * @power: This class instance
+ * @method: The method name, e.g. "Hibernate"
+ * Return value: Success, true if we did OK
+ *
+ * Do a method on org.freedesktop.Hal.Device.SystemPowerManagement.*
+ * with no arguments.
+ **/
+static gboolean
+hal_device_power_pm_method_void (HalDevicePower *power, const gchar *method, GError **error)
+{
+ time_t start;
+ time_t end;
+ guint retval = 0;
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+ g_return_val_if_fail (method != NULL, FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (power->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("not connected");
+ return FALSE;
+ }
+
+ time (&start);
+ ret = dbus_g_proxy_call (proxy, method, error,
+ G_TYPE_INVALID,
+ G_TYPE_INT, &retval,
+ G_TYPE_INVALID);
+ /* we might have to ignore the error */
+ if (error != NULL && hal_device_power_filter_error (error))
+ return TRUE;
+ if (retval != 0)
+ egg_warning ("%s failed in a horrible way!", method);
+
+ /* compare the amount of time that has passed - if it's more than 6 hours
+ * then the dbus call timed out (dbus-pending-call.c) */
+ if (ret != 0) {
+ time (&end);
+ if (difftime (start,end) >= 6*60*60*1000)
+ return TRUE;
+ }
+
+ return ret;
+}
+
+/**
+ * hal_device_power_hibernate:
+ *
+ * @power: This class instance
+ * Return value: Success, true if we hibernated OK
+ *
+ * Uses org.freedesktop.Hal.Device.SystemPowerManagement.Hibernate ()
+ **/
+gboolean
+hal_device_power_hibernate (HalDevicePower *power, GError **error)
+{
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+ return hal_device_power_pm_method_void (power, "Hibernate", error);
+}
+
+/**
+ * hal_device_power_shutdown:
+ *
+ * Return value: Success, true if we shutdown OK
+ *
+ * Uses org.freedesktop.Hal.Device.SystemPowerManagement.Shutdown ()
+ **/
+gboolean
+hal_device_power_shutdown (HalDevicePower *power, GError **error)
+{
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+ return hal_device_power_pm_method_void (power, "Shutdown", error);
+}
+
+/**
+ * hal_device_power_reboot:
+ *
+ * @power: This class instance
+ * Return value: Success, true if we shutdown OK
+ *
+ * Uses org.freedesktop.Hal.Device.SystemPowerManagement.Reboot ()
+ **/
+gboolean
+hal_device_power_reboot (HalDevicePower *power, GError **error)
+{
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+ return hal_device_power_pm_method_void (power, "Reboot", error);
+}
+
+/**
+ * hal_device_power_enable_power_save:
+ *
+ * @power: This class instance
+ * @enable: True to enable low power mode
+ * Return value: Success, true if we set the mode
+ *
+ * Uses org.freedesktop.Hal.Device.SystemPowerManagement.SetPowerSave ()
+ **/
+gboolean
+hal_device_power_enable_power_save (HalDevicePower *power, gboolean enable)
+{
+ gint retval = 0;
+ GError *error = NULL;
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (power != NULL, FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (power->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+
+ /* abort if we are not a "qualified" laptop */
+ if (hal_device_power_is_laptop (power) == FALSE) {
+ egg_debug ("We are not a laptop, so not even trying");
+ return FALSE;
+ }
+
+ ret = dbus_g_proxy_call (proxy, "SetPowerSave", &error,
+ G_TYPE_BOOLEAN, enable,
+ G_TYPE_INVALID,
+ G_TYPE_INT, &retval,
+ G_TYPE_INVALID);
+ if (retval != 0)
+ egg_warning ("SetPowerSave failed in a horrible way!");
+ return ret;
+}
+
+/**
+ * hal_device_power_has_suspend_error:
+ *
+ * @power: This class instance
+ * @enable: Return true if there was a suspend error
+ * Return value: Success
+ *
+ * TODO: should call a method on HAL and also return the ouput of the file
+ **/
+gboolean
+hal_device_power_has_suspend_error (HalDevicePower *power, gboolean *state)
+{
+ g_return_val_if_fail (power != NULL, FALSE);
+ g_return_val_if_fail (state != NULL, FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+ *state = g_file_test ("/var/lib/hal/system-power-suspend-output", G_FILE_TEST_EXISTS);
+ return TRUE;
+}
+
+/**
+ * hal_device_power_has_hibernate_error:
+ *
+ * @power: This class instance
+ * @enable: Return true if there was a hibernate error
+ * Return value: Success
+ *
+ * TODO: should call a method on HAL and also return the ouput of the file
+ **/
+gboolean
+hal_device_power_has_hibernate_error (HalDevicePower *power, gboolean *state)
+{
+ g_return_val_if_fail (power != NULL, FALSE);
+ g_return_val_if_fail (state != NULL, FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+ *state = g_file_test ("/var/lib/hal/system-power-hibernate-output", G_FILE_TEST_EXISTS);
+ return TRUE;
+}
+
+/**
+ * hal_device_power_clear_suspend_error:
+ *
+ * @power: This class instance
+ * Return value: Success
+ *
+ * Tells HAL to try and clear the suspend error as we appear to be okay
+ **/
+gboolean
+hal_device_power_clear_suspend_error (HalDevicePower *power, GError **error)
+{
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (power != NULL, FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (power->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+
+ ret = dbus_g_proxy_call (proxy, "SuspendClearError", error,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+ return ret;
+}
+
+/**
+ * hal_device_power_clear_hibernate_error:
+ *
+ * @power: This class instance
+ * Return value: Success
+ *
+ * Tells HAL to try and clear the hibernate error as we appear to be okay
+ **/
+gboolean
+hal_device_power_clear_hibernate_error (HalDevicePower *power, GError **error)
+{
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (power != NULL, FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE_POWER (power), FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (power->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+
+ ret = dbus_g_proxy_call (proxy, "HibernateClearError", error,
+ G_TYPE_INVALID, G_TYPE_INVALID);
+ return ret;
+}
+
+/**
+ * hal_device_power_finalize:
+ * @object: This class instance
+ **/
+static void
+hal_device_power_finalize (GObject *object)
+{
+ HalDevicePower *power;
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (HAL_IS_DEVICE_POWER (object));
+
+ power = HAL_DEVICE_POWER (object);
+ power->priv = HAL_DEVICE_POWER_GET_PRIVATE (power);
+
+ g_object_unref (power->priv->gproxy);
+ g_object_unref (power->priv->computer);
+
+ G_OBJECT_CLASS (hal_device_power_parent_class)->finalize (object);
+}
+
+/**
+ * hal_device_power_new:
+ * Return value: new HalDevicePower instance.
+ **/
+HalDevicePower *
+hal_device_power_new (void)
+{
+ if (hal_device_power_object != NULL) {
+ g_object_ref (hal_device_power_object);
+ } else {
+ hal_device_power_object = g_object_new (HAL_TYPE_DEVICE_POWER, NULL);
+ g_object_add_weak_pointer (hal_device_power_object, &hal_device_power_object);
+ }
+ return HAL_DEVICE_POWER (hal_device_power_object);
+}
+
diff --git a/plugins/media-keys/libhal-glib/hal-device-power.h b/plugins/media-keys/libhal-glib/hal-device-power.h
new file mode 100644
index 00000000..702c9a10
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-device-power.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005-2007 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __HALDEVICEPOWER_H
+#define __HALDEVICEPOWER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define HAL_TYPE_DEVICE_POWER (hal_device_power_get_type ())
+#define HAL_DEVICE_POWER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), HAL_TYPE_DEVICE_POWER, HalDevicePower))
+#define HAL_DEVICE_POWER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), HAL_TYPE_DEVICE_POWER, HalDevicePowerClass))
+#define HAL_IS_DEVICE_POWER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), HAL_TYPE_DEVICE_POWER))
+#define HAL_IS_DEVICE_POWER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), HAL_TYPE_DEVICE_POWER))
+#define HAL_DEVICE_POWER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), HAL_TYPE_DEVICE_POWER, HalDevicePowerClass))
+
+typedef struct HalDevicePowerPrivate HalDevicePowerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ HalDevicePowerPrivate *priv;
+} HalDevicePower;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} HalDevicePowerClass;
+
+GType hal_device_power_get_type (void);
+HalDevicePower *hal_device_power_new (void);
+
+gboolean hal_device_power_has_support (HalDevicePower *power);
+gboolean hal_device_power_can_suspend (HalDevicePower *power);
+gboolean hal_device_power_can_hibernate (HalDevicePower *power);
+gboolean hal_device_power_suspend (HalDevicePower *power,
+ guint wakeup,
+ GError **error);
+gboolean hal_device_power_hibernate (HalDevicePower *power,
+ GError **error);
+gboolean hal_device_power_shutdown (HalDevicePower *power,
+ GError **error);
+gboolean hal_device_power_reboot (HalDevicePower *power,
+ GError **error);
+gboolean hal_device_power_has_suspend_error (HalDevicePower *power,
+ gboolean *state);
+gboolean hal_device_power_has_hibernate_error (HalDevicePower *power,
+ gboolean *state);
+gboolean hal_device_power_clear_suspend_error (HalDevicePower *power,
+ GError **error);
+gboolean hal_device_power_clear_hibernate_error (HalDevicePower *power,
+ GError **error);
+gboolean hal_device_power_enable_power_save (HalDevicePower *power,
+ gboolean enable);
+
+G_END_DECLS
+
+#endif /* __HALDEVICEPOWER_H */
diff --git a/plugins/media-keys/libhal-glib/hal-device-store.c b/plugins/media-keys/libhal-glib/hal-device-store.c
new file mode 100644
index 00000000..ea178098
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-device-store.c
@@ -0,0 +1,309 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "egg-debug.h"
+
+#include "hal-marshal.h"
+#include "hal-device.h"
+#include "hal-device-store.h"
+
+static void hal_device_store_class_init (HalDeviceStoreClass *klass);
+static void hal_device_store_init (HalDeviceStore *device_store);
+static void hal_device_store_finalize (GObject *object);
+
+#define HAL_DEVICE_STORE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), HAL_TYPE_DEVICE_STORE, HalDeviceStorePrivate))
+
+struct HalDeviceStorePrivate
+{
+ GPtrArray *array; /* the device array */
+};
+
+enum {
+ DEVICE_REMOVED, /* is not expected to work yet */
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (HalDeviceStore, hal_device_store, G_TYPE_OBJECT)
+
+/**
+ * hal_device_store_index_udi:
+ *
+ * Returns -1 if not found
+ *
+ * @device_store: This store instance
+ * @device: The device
+ */
+static gint
+hal_device_store_index_udi (HalDeviceStore *device_store, const gchar *udi)
+{
+ gint i;
+ guint length;
+ HalDevice *d;
+
+ length = device_store->priv->array->len;
+ for (i=0;i<length;i++) {
+ d = (HalDevice *) g_ptr_array_index (device_store->priv->array, i);
+ if (strcmp (hal_device_get_udi (d), udi) == 0) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+/**
+ * hal_device_store_index:
+ *
+ * Returns -1 if not found
+ *
+ * @device_store: This store instance
+ * @device: The device
+ */
+static gint
+hal_device_store_index (HalDeviceStore *device_store, HalDevice *device)
+{
+ HalDevice *d;
+ gint i;
+ guint length;
+ const gchar *udi;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_STORE (device_store), FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+
+ length = device_store->priv->array->len;
+ udi = hal_device_get_udi (device);
+
+ /* trivial check, is instance the same (FAST) */
+ for (i=0;i<length;i++) {
+ d = (HalDevice *) g_ptr_array_index (device_store->priv->array, i);
+ if (d == device) {
+ return i;
+ }
+ }
+
+ /* non trivial check, is udi the same (SLOW) */
+ return hal_device_store_index_udi (device_store, udi);
+}
+
+/**
+ * hal_device_store_find_udi:
+ *
+ * NULL return value is not found
+ *
+ * @device_store: This store instance
+ * @device: The device
+ */
+HalDevice *
+hal_device_store_find_udi (HalDeviceStore *device_store, const gchar *udi)
+{
+ gint index;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_STORE (device_store), NULL);
+ g_return_val_if_fail (udi != NULL, NULL);
+
+ index = hal_device_store_index_udi (device_store, udi);
+ if (index == -1) {
+ return NULL;
+ }
+
+ /* return the device */
+ return (HalDevice *) g_ptr_array_index (device_store->priv->array, index);
+}
+
+/**
+ * hal_device_store_present:
+ *
+ * @device_store: This store instance
+ * @device: The device
+ */
+gboolean
+hal_device_store_present (HalDeviceStore *device_store, HalDevice *device)
+{
+ g_return_val_if_fail (HAL_IS_DEVICE_STORE (device_store), FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+
+ /* if we have an index, we have the device */
+ if (hal_device_store_index (device_store, device) != -1) {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+/**
+ * hal_device_store_insert:
+ *
+ * @device_store: This store instance
+ * @device: The device
+ */
+gboolean
+hal_device_store_insert (HalDeviceStore *device_store, HalDevice *device)
+{
+ g_return_val_if_fail (HAL_IS_DEVICE_STORE (device_store), FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+
+ if (hal_device_store_present (device_store, device)) {
+ return FALSE;
+ }
+
+ g_ptr_array_add (device_store->priv->array, (gpointer) device);
+ return TRUE;
+}
+
+/**
+ * hal_device_store_remove:
+ *
+ * @device_store: This store instance
+ * @device: The device
+ */
+gboolean
+hal_device_store_remove (HalDeviceStore *device_store, HalDevice *device)
+{
+ gint index;
+ HalDevice *d;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_STORE (device_store), FALSE);
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+
+ index = hal_device_store_index (device_store, device);
+ if (index == -1) {
+ return FALSE;
+ }
+
+ /* we unref because this may be the only pointer to this instance */
+ d = (HalDevice *) g_ptr_array_index (device_store->priv->array, index);
+ g_object_unref (d);
+
+ /* remove from the device_store */
+ g_ptr_array_remove_index (device_store->priv->array, index);
+
+ return TRUE;
+}
+
+/**
+ * hal_device_store_print:
+ *
+ * @device_store: This store instance
+ */
+gboolean
+hal_device_store_print (HalDeviceStore *device_store)
+{
+ HalDevice *d;
+ guint i;
+ guint length;
+
+ g_return_val_if_fail (HAL_IS_DEVICE_STORE (device_store), FALSE);
+
+ length = device_store->priv->array->len;
+ g_print ("Printing device list in %p\n", device_store);
+ for (i=0;i<length;i++) {
+ d = (HalDevice *) g_ptr_array_index (device_store->priv->array, i);
+ g_print ("%i: %s\n", i, hal_device_get_udi (d));
+ }
+
+ return TRUE;
+}
+
+/**
+ * hal_device_store_class_init:
+ * @klass: This class instance
+ **/
+static void
+hal_device_store_class_init (HalDeviceStoreClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = hal_device_store_finalize;
+ g_type_class_add_private (klass, sizeof (HalDeviceStorePrivate));
+
+ signals [DEVICE_REMOVED] =
+ g_signal_new ("device-removed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalDeviceStoreClass, device_removed),
+ NULL,
+ NULL,
+ hal_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_STRING);
+}
+
+/**
+ * hal_device_store_init:
+ *
+ * @hal_device_store: This class instance
+ **/
+static void
+hal_device_store_init (HalDeviceStore *device_store)
+{
+ device_store->priv = HAL_DEVICE_STORE_GET_PRIVATE (device_store);
+
+ device_store->priv->array = g_ptr_array_new ();
+}
+
+/**
+ * hal_device_store_finalize:
+ * @object: This class instance
+ **/
+static void
+hal_device_store_finalize (GObject *object)
+{
+ HalDeviceStore *device_store;
+ HalDevice *d;
+ gint i;
+ guint length;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (HAL_IS_DEVICE_STORE (object));
+
+ device_store = HAL_DEVICE_STORE (object);
+ device_store->priv = HAL_DEVICE_STORE_GET_PRIVATE (device_store);
+
+ length = device_store->priv->array->len;
+
+ /* unref all */
+ for (i=0;i<length;i++) {
+ d = (HalDevice *) g_ptr_array_index (device_store->priv->array, i);
+ g_object_unref (d);
+ }
+ g_ptr_array_free (device_store->priv->array, TRUE);
+
+ G_OBJECT_CLASS (hal_device_store_parent_class)->finalize (object);
+}
+
+/**
+ * hal_device_store_new:
+ * Return value: new HalDeviceStore instance.
+ **/
+HalDeviceStore *
+hal_device_store_new (void)
+{
+ HalDeviceStore *device_store = g_object_new (HAL_TYPE_DEVICE_STORE, NULL);
+ return HAL_DEVICE_STORE (device_store);
+}
+
diff --git a/plugins/media-keys/libhal-glib/hal-device-store.h b/plugins/media-keys/libhal-glib/hal-device-store.h
new file mode 100644
index 00000000..f45c8595
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-device-store.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __HAL_DEVICE_STORE_H
+#define __HAL_DEVICE_STORE_H
+
+#include <glib-object.h>
+#include "hal-device.h"
+
+G_BEGIN_DECLS
+
+#define HAL_TYPE_DEVICE_STORE (hal_device_store_get_type ())
+#define HAL_DEVICE_STORE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), HAL_TYPE_DEVICE_STORE, HalDeviceStore))
+#define HAL_DEVICE_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), HAL_TYPE_DEVICE_STORE, HalDeviceStoreClass))
+#define HAL_IS_DEVICE_STORE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), HAL_TYPE_DEVICE_STORE))
+#define HAL_IS_DEVICE_STORE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), HAL_TYPE_DEVICE_STORE))
+#define HAL_DEVICE_STORE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), HAL_TYPE_DEVICE_STORE, HalDeviceStoreClass))
+
+typedef struct HalDeviceStorePrivate HalDeviceStorePrivate;
+
+typedef struct
+{
+ GObject parent;
+ HalDeviceStorePrivate *priv;
+} HalDeviceStore;
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (* device_removed) (HalDeviceStore *device_store,
+ HalDevice *device);
+} HalDeviceStoreClass;
+
+GType hal_device_store_get_type (void);
+HalDeviceStore *hal_device_store_new (void);
+
+HalDevice *hal_device_store_find_udi (HalDeviceStore *device_store,
+ const gchar *udi);
+gboolean hal_device_store_insert (HalDeviceStore *device_store,
+ HalDevice *device);
+gboolean hal_device_store_present (HalDeviceStore *device_store,
+ HalDevice *device);
+gboolean hal_device_store_remove (HalDeviceStore *device_store,
+ HalDevice *device);
+gboolean hal_device_store_print (HalDeviceStore *device_store);
+
+G_END_DECLS
+
+#endif /* __HAL_DEVICE_STORE_H */
diff --git a/plugins/media-keys/libhal-glib/hal-device.c b/plugins/media-keys/libhal-glib/hal-device.c
new file mode 100644
index 00000000..b4d73a66
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-device.c
@@ -0,0 +1,636 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005-2007 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+
+#include "egg-debug.h"
+#include "egg-dbus-proxy.h"
+
+#include "hal-marshal.h"
+#include "hal-device-power.h"
+#include "hal-device.h"
+#include "hal-manager.h"
+
+static void hal_device_class_init (HalDeviceClass *klass);
+static void hal_device_init (HalDevice *device);
+static void hal_device_finalize (GObject *object);
+
+#define HAL_DEVICE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), HAL_TYPE_DEVICE, HalDevicePrivate))
+
+struct HalDevicePrivate
+{
+ DBusGConnection *connection;
+ gboolean use_property_modified;
+ gboolean use_condition;
+ EggDbusProxy *gproxy;
+ gchar *udi;
+};
+
+/* Signals emitted from HalDevice are:
+ *
+ * device-added
+ * device-removed
+ * device-property-modified
+ * device-condition
+ * new-capability
+ * lost-capability
+ * daemon-start
+ * daemon-stop
+ */
+enum {
+ DEVICE_PROPERTY_MODIFIED,
+ DEVICE_CONDITION,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+
+G_DEFINE_TYPE (HalDevice, hal_device, G_TYPE_OBJECT)
+
+/**
+ * hal_device_set_udi:
+ *
+ * Return value: TRUE for success, FALSE for failure
+ **/
+gboolean
+hal_device_set_udi (HalDevice *device, const gchar *udi)
+{
+ DBusGProxy *proxy;
+ DBusGConnection *connection;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (udi != NULL, FALSE);
+
+ if (device->priv->udi != NULL) {
+ /* aready set UDI */
+ return FALSE;
+ }
+
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+ proxy = egg_dbus_proxy_assign (device->priv->gproxy, connection,
+ HAL_DBUS_SERVICE, udi, HAL_DBUS_INTERFACE_DEVICE);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy failed");
+ return FALSE;
+ }
+ device->priv->udi = g_strdup (udi);
+
+ return TRUE;
+}
+
+/**
+ * hal_device_get_udi:
+ *
+ * Return value: UDI
+ **/
+const gchar *
+hal_device_get_udi (HalDevice *device)
+{
+ g_return_val_if_fail (HAL_IS_DEVICE (device), NULL);
+
+ return device->priv->udi;
+}
+
+/**
+ * hal_device_get_bool:
+ *
+ * @hal_device: This class instance
+ * @key: The key to query
+ * @value: return value, passed by ref
+ * Return value: TRUE for success, FALSE for failure
+ **/
+gboolean
+hal_device_get_bool (HalDevice *device,
+ const gchar *key,
+ gboolean *value,
+ GError **error)
+{
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (device->priv->udi != NULL, FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (device->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ ret = dbus_g_proxy_call (proxy, "GetPropertyBoolean", error,
+ G_TYPE_STRING, key,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, value,
+ G_TYPE_INVALID);
+ if (!ret) {
+ *value = FALSE;
+ }
+ return ret;
+}
+
+/**
+ * hal_device_get_string:
+ *
+ * @hal_device: This class instance
+ * @key: The key to query
+ * @value: return value, passed by ref
+ * Return value: TRUE for success, FALSE for failure
+ *
+ * You must g_free () the return value.
+ **/
+gboolean
+hal_device_get_string (HalDevice *device,
+ const gchar *key,
+ gchar **value,
+ GError **error)
+{
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (device->priv->udi != NULL, FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (device->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ ret = dbus_g_proxy_call (proxy, "GetPropertyString", error,
+ G_TYPE_STRING, key,
+ G_TYPE_INVALID,
+ G_TYPE_STRING, value,
+ G_TYPE_INVALID);
+ if (!ret) {
+ *value = NULL;
+ }
+ return ret;
+}
+
+/**
+ * hal_device_get_int:
+ *
+ * @hal_device: This class instance
+ * @key: The key to query
+ * @value: return value, passed by ref
+ * Return value: TRUE for success, FALSE for failure
+ **/
+gboolean
+hal_device_get_int (HalDevice *device,
+ const gchar *key,
+ gint *value,
+ GError **error)
+{
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (device->priv->udi != NULL, FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (device->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ ret = dbus_g_proxy_call (proxy, "GetPropertyInteger", error,
+ G_TYPE_STRING, key,
+ G_TYPE_INVALID,
+ G_TYPE_INT, value,
+ G_TYPE_INVALID);
+ if (!ret) {
+ *value = 0;
+ }
+ return ret;
+}
+
+/**
+ * hal_device_get_uint:
+ *
+ * HAL has no concept of a UINT, only INT
+ **/
+gboolean
+hal_device_get_uint (HalDevice *device,
+ const gchar *key,
+ guint *value,
+ GError **error)
+{
+ gint tvalue;
+ gboolean ret;
+
+ /* bodge */
+ ret = hal_device_get_int (device, key, &tvalue, error);
+ *value = (guint) tvalue;
+ return ret;
+}
+
+/**
+ * hal_device_query_capability:
+ *
+ * @hal_device: This class instance
+ * @capability: The capability, e.g. "battery"
+ * @value: return value, passed by ref
+ * Return value: TRUE for success, FALSE for failure
+ **/
+gboolean
+hal_device_query_capability (HalDevice *device,
+ const gchar *capability,
+ gboolean *has_capability,
+ GError **error)
+{
+ gboolean ret;
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (capability != NULL, FALSE);
+ g_return_val_if_fail (has_capability != NULL, FALSE);
+ g_return_val_if_fail (device->priv->udi != NULL, FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (device->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ ret = dbus_g_proxy_call (proxy, "QueryCapability", error,
+ G_TYPE_STRING, capability,
+ G_TYPE_INVALID,
+ G_TYPE_BOOLEAN, has_capability,
+ G_TYPE_INVALID);
+ if (!ret) {
+ *has_capability = FALSE;
+ }
+ return ret;
+}
+
+/**
+ * watch_device_property_modified:
+ *
+ * @key: Property key
+ * @is_added: If the key was added
+ * @is_removed: If the key was removed
+ *
+ * Invoked when a property of a device in the Global Device List is
+ * changed, and we have we have subscribed to changes for that device.
+ */
+static void
+watch_device_property_modified (DBusGProxy *proxy,
+ const gchar *key,
+ gboolean is_added,
+ gboolean is_removed,
+ gboolean finally,
+ HalDevice *device)
+{
+ g_signal_emit (device, signals [DEVICE_PROPERTY_MODIFIED], 0,
+ key, is_added, is_removed, finally);
+}
+
+/**
+ * watch_device_properties_modified_cb:
+ *
+ * @proxy: The org.freedesktop.Hal.Manager proxy
+ * @device: This class instance
+ *
+ * Demultiplex the composite PropertyModified events here.
+ */
+static void
+watch_device_properties_modified_cb (DBusGProxy *proxy,
+ gint type,
+ GPtrArray *properties,
+ HalDevice *device)
+{
+ GValueArray *array;
+ const gchar *udi;
+ const gchar *key;
+ gboolean added;
+ gboolean removed;
+ gboolean finally = FALSE;
+ guint i;
+
+ udi = dbus_g_proxy_get_path (proxy);
+
+ array = NULL;
+
+ for (i = 0; i < properties->len; i++) {
+ array = g_ptr_array_index (properties, i);
+ if (array->n_values != 3) {
+ egg_warning ("array->n_values invalid (!3)");
+ return;
+ }
+
+ key = g_value_get_string (g_value_array_get_nth (array, 0));
+ removed = g_value_get_boolean (g_value_array_get_nth (array, 1));
+ added = g_value_get_boolean (g_value_array_get_nth (array, 2));
+
+ /* Work out if this PropertyModified is the last to be sent as
+ * sometimes we only want to refresh caches when we have all
+ * the info from a UDI */
+ if (i == properties->len - 1) {
+ finally = TRUE;
+ }
+
+ watch_device_property_modified (proxy, key, added, removed, finally, device);
+ }
+}
+
+/**
+ * hal_device_watch_property_modified:
+ *
+ * Watch the specified device, so it emits device-property-modified and
+ * adds to the gpm cache so we don't get asked to add it again.
+ */
+gboolean
+hal_device_watch_property_modified (HalDevice *device)
+{
+ DBusGProxy *proxy;
+ GType struct_array_type, struct_type;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (device->priv->udi != NULL, FALSE);
+
+ if (device->priv->use_property_modified) {
+ /* already watched */
+ return FALSE;
+ }
+
+ device->priv->use_property_modified = TRUE;
+
+ struct_type = dbus_g_type_get_struct ("GValueArray",
+ G_TYPE_STRING,
+ G_TYPE_BOOLEAN,
+ G_TYPE_BOOLEAN,
+ G_TYPE_INVALID);
+
+ struct_array_type = dbus_g_type_get_collection ("GPtrArray", struct_type);
+
+ dbus_g_object_register_marshaller (hal_marshal_VOID__INT_BOXED,
+ G_TYPE_NONE, G_TYPE_INT,
+ struct_array_type, G_TYPE_INVALID);
+
+ proxy = egg_dbus_proxy_get_proxy (device->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ dbus_g_proxy_add_signal (proxy, "PropertyModified",
+ G_TYPE_INT, struct_array_type, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (proxy, "PropertyModified",
+ G_CALLBACK (watch_device_properties_modified_cb), device, NULL);
+ return TRUE;
+}
+
+/**
+ * watch_device_condition_cb:
+ *
+ * @udi: Univerisal Device Id
+ * @name: Name of condition
+ * @details: D-BUS message with parameters
+ *
+ * Invoked when a property of a device in the Global Device List is
+ * changed, and we have we have subscribed to changes for that device.
+ */
+static void
+watch_device_condition_cb (DBusGProxy *proxy,
+ const gchar *condition,
+ const gchar *details,
+ HalDevice *device)
+{
+ g_signal_emit (device, signals [DEVICE_CONDITION], 0, condition, details);
+}
+
+/**
+ * hal_device_watch_condition:
+ *
+ * Watch the specified device, so it emits a device-condition
+ */
+gboolean
+hal_device_watch_condition (HalDevice *device)
+{
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+ g_return_val_if_fail (device->priv->udi != NULL, FALSE);
+
+ if (device->priv->use_condition) {
+ /* already watched */
+ return FALSE;
+ }
+
+ device->priv->use_condition = TRUE;
+
+ dbus_g_object_register_marshaller (hal_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_INVALID);
+
+ proxy = egg_dbus_proxy_get_proxy (device->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ dbus_g_proxy_add_signal (proxy, "Condition",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (proxy, "Condition",
+ G_CALLBACK (watch_device_condition_cb), device, NULL);
+ return TRUE;
+}
+
+/**
+ * hal_device_remove_condition:
+ *
+ * Remove the specified device, so it does not emit device-condition signals.
+ */
+gboolean
+hal_device_remove_condition (HalDevice *device)
+{
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+
+ if (device->priv->use_condition == FALSE) {
+ /* already connected */
+ return FALSE;
+ }
+
+ device->priv->use_condition = FALSE;
+
+ proxy = egg_dbus_proxy_get_proxy (device->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ dbus_g_proxy_disconnect_signal (proxy, "Condition",
+ G_CALLBACK (watch_device_condition_cb), device);
+ return TRUE;
+}
+
+/**
+ * hal_device_remove_property_modified:
+ *
+ * Remove the specified device, so it does not emit device-propery-modified.
+ */
+gboolean
+hal_device_remove_property_modified (HalDevice *device)
+{
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_DEVICE (device), FALSE);
+
+ if (device->priv->use_property_modified == FALSE) {
+ /* already disconnected */
+ return FALSE;
+ }
+
+ device->priv->use_property_modified = FALSE;
+
+ proxy = egg_dbus_proxy_get_proxy (device->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+ dbus_g_proxy_disconnect_signal (proxy, "PropertyModified",
+ G_CALLBACK (watch_device_properties_modified_cb), device);
+ return TRUE;
+}
+
+/**
+ * proxy_status_cb:
+ * @proxy: The dbus raw proxy
+ * @status: The status of the service, where TRUE is connected
+ * @hal_manager: This class instance
+ **/
+static void
+proxy_status_cb (DBusGProxy *proxy,
+ gboolean status,
+ HalDevice *device)
+{
+ g_return_if_fail (HAL_IS_DEVICE (device));
+ if (status) {
+ /* should join */
+ } else {
+ /* should unjoin */
+ }
+}
+
+/**
+ * hal_device_class_init:
+ * @klass: This class instance
+ **/
+static void
+hal_device_class_init (HalDeviceClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = hal_device_finalize;
+ g_type_class_add_private (klass, sizeof (HalDevicePrivate));
+
+ signals [DEVICE_PROPERTY_MODIFIED] =
+ g_signal_new ("property-modified",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalDeviceClass, device_property_modified),
+ NULL,
+ NULL,
+ hal_marshal_VOID__STRING_BOOLEAN_BOOLEAN_BOOLEAN,
+ G_TYPE_NONE, 4, G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN);
+ signals [DEVICE_CONDITION] =
+ g_signal_new ("device-condition",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalDeviceClass, device_condition),
+ NULL,
+ NULL,
+ hal_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_STRING);
+}
+
+/**
+ * hal_device_init:
+ *
+ * @hal_device: This class instance
+ **/
+static void
+hal_device_init (HalDevice *device)
+{
+ GError *error = NULL;
+
+ device->priv = HAL_DEVICE_GET_PRIVATE (device);
+
+ device->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (error != NULL) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ device->priv->use_property_modified = FALSE;
+ device->priv->use_condition = FALSE;
+
+ /* get the manager connection */
+ device->priv->gproxy = egg_dbus_proxy_new ();
+ g_signal_connect (device->priv->gproxy, "proxy-status",
+ G_CALLBACK (proxy_status_cb), device);
+}
+
+/**
+ * hal_device_finalize:
+ * @object: This class instance
+ **/
+static void
+hal_device_finalize (GObject *object)
+{
+ HalDevice *device;
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (HAL_IS_DEVICE (object));
+
+ device = HAL_DEVICE (object);
+ device->priv = HAL_DEVICE_GET_PRIVATE (device);
+
+ if (device->priv->use_property_modified) {
+ hal_device_remove_property_modified (device);
+ }
+ if (device->priv->use_condition) {
+ hal_device_remove_condition (device);
+ }
+
+ g_object_unref (device->priv->gproxy);
+ g_free (device->priv->udi);
+
+ G_OBJECT_CLASS (hal_device_parent_class)->finalize (object);
+}
+
+/**
+ * hal_device_new:
+ * Return value: new HalDevice instance.
+ **/
+HalDevice *
+hal_device_new (void)
+{
+ HalDevice *device = g_object_new (HAL_TYPE_DEVICE, NULL);
+ return HAL_DEVICE (device);
+}
diff --git a/plugins/media-keys/libhal-glib/hal-device.h b/plugins/media-keys/libhal-glib/hal-device.h
new file mode 100644
index 00000000..ffd7e192
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-device.h
@@ -0,0 +1,96 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005-2007 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __HAL_DEVICE_H
+#define __HAL_DEVICE_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define HAL_TYPE_DEVICE (hal_device_get_type ())
+#define HAL_DEVICE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), HAL_TYPE_DEVICE, HalDevice))
+#define HAL_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), HAL_TYPE_DEVICE, HalDeviceClass))
+#define HAL_IS_DEVICE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), HAL_TYPE_DEVICE))
+#define HAL_IS_DEVICE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), HAL_TYPE_DEVICE))
+#define HAL_DEVICE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), HAL_TYPE_DEVICE, HalDeviceClass))
+
+typedef struct HalDevicePrivate HalDevicePrivate;
+
+typedef struct
+{
+ GObject parent;
+ HalDevicePrivate *priv;
+} HalDevice;
+
+/* Signals emitted from HalDevice are:
+ *
+ * device-property-modified
+ * device-condition
+ */
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (* device_property_modified) (HalDevice *device,
+ const gchar *key,
+ gboolean is_added,
+ gboolean is_removed,
+ gboolean finally);
+ void (* device_condition) (HalDevice *device,
+ const gchar *condition,
+ const gchar *details);
+} HalDeviceClass;
+
+GType hal_device_get_type (void);
+HalDevice *hal_device_new (void);
+
+gboolean hal_device_set_udi (HalDevice *device,
+ const gchar *udi);
+const gchar *hal_device_get_udi (HalDevice *device);
+gboolean hal_device_get_bool (HalDevice *device,
+ const gchar *key,
+ gboolean *value,
+ GError **error);
+gboolean hal_device_get_string (HalDevice *device,
+ const gchar *key,
+ gchar **value,
+ GError **error);
+gboolean hal_device_get_int (HalDevice *device,
+ const gchar *key,
+ gint *value,
+ GError **error);
+gboolean hal_device_get_uint (HalDevice *device,
+ const gchar *key,
+ guint *value,
+ GError **error);
+gboolean hal_device_query_capability (HalDevice *device,
+ const gchar *capability,
+ gboolean *has_capability,
+ GError **error);
+gboolean hal_device_watch_condition (HalDevice *device);
+gboolean hal_device_watch_property_modified (HalDevice *device);
+gboolean hal_device_remove_condition (HalDevice *device);
+gboolean hal_device_remove_property_modified (HalDevice *device);
+
+G_END_DECLS
+
+#endif /* __HAL_DEVICE_H */
diff --git a/plugins/media-keys/libhal-glib/hal-manager.c b/plugins/media-keys/libhal-glib/hal-manager.c
new file mode 100644
index 00000000..d7806040
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-manager.c
@@ -0,0 +1,602 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005-2007 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <dbus/dbus-glib.h>
+
+#include "egg-debug.h"
+#include "egg-dbus-proxy.h"
+
+#include "hal-marshal.h"
+#include "hal-device-power.h"
+#include "hal-device.h"
+#include "hal-manager.h"
+
+static void hal_manager_class_init (HalManagerClass *klass);
+static void hal_manager_init (HalManager *hal_manager);
+static void hal_manager_finalize (GObject *object);
+
+#define HAL_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), HAL_TYPE_MANAGER, HalManagerPrivate))
+
+struct HalManagerPrivate
+{
+ DBusGConnection *connection;
+ HalDevice *computer;
+ EggDbusProxy *gproxy;
+};
+
+/* Signals emitted from HalManager are:
+ *
+ * device-added
+ * device-removed
+ * new-capability
+ * lost-capability
+ * daemon-start
+ * daemon-stop
+ */
+enum {
+ DEVICE_ADDED,
+ DEVICE_REMOVED,
+ NEW_CAPABILITY,
+ LOST_CAPABILITY,
+ DAEMON_START,
+ DAEMON_STOP,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0 };
+static gpointer hal_manager_object = NULL;
+
+G_DEFINE_TYPE (HalManager, hal_manager, G_TYPE_OBJECT)
+
+/**
+ * hal_manager_is_running:
+ *
+ * @hal_manager: This class instance
+ * Return value: TRUE if hal_managerdaemon is running
+ *
+ * Finds out if hal_manager is running
+ **/
+gboolean
+hal_manager_is_running (HalManager *manager)
+{
+ gchar *udi = NULL;
+ gboolean running;
+
+ g_return_val_if_fail (HAL_IS_MANAGER (manager), FALSE);
+
+ running = hal_device_get_string (manager->priv->computer, "info.udi", &udi, NULL);
+ g_free (udi);
+ return running;
+}
+
+/**
+ * hal_manager_find_capability:
+ *
+ * @hal_manager: This class instance
+ * @capability: The capability, e.g. "battery"
+ * @value: return value, passed by ref
+ * Return value: TRUE for success, FALSE for failure
+ **/
+gboolean
+hal_manager_find_capability (HalManager *manager,
+ const gchar *capability,
+ gchar ***value,
+ GError **error)
+{
+ DBusGProxy *proxy = NULL;
+ gboolean ret;
+
+ g_return_val_if_fail (HAL_IS_MANAGER (manager), FALSE);
+ g_return_val_if_fail (capability != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+
+ proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
+ HAL_DBUS_SERVICE,
+ HAL_DBUS_PATH_MANAGER,
+ HAL_DBUS_INTERFACE_MANAGER);
+ ret = dbus_g_proxy_call (proxy, "FindDeviceByCapability", error,
+ G_TYPE_STRING, capability,
+ G_TYPE_INVALID,
+ G_TYPE_STRV, value,
+ G_TYPE_INVALID);
+ if (!ret) {
+ *value = NULL;
+ }
+ return ret;
+}
+
+/**
+ * hal_manager_find_device_string_match:
+ *
+ * @hal_manager: This class instance
+ * @key: The key, e.g. "battery.type"
+ * @value: The value, e.g. "primary"
+ * @devices: return value, passed by ref
+ * Return value: TRUE for success, FALSE for failure
+ **/
+gboolean
+hal_manager_find_device_string_match (HalManager *manager,
+ const gchar *key,
+ const gchar *value,
+ gchar ***devices,
+ GError **error)
+{
+ DBusGProxy *proxy = NULL;
+ gboolean ret;
+
+ g_return_val_if_fail (HAL_IS_MANAGER (manager), FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+ g_return_val_if_fail (value != NULL, FALSE);
+ g_return_val_if_fail (devices != NULL, FALSE);
+
+ proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
+ HAL_DBUS_SERVICE,
+ HAL_DBUS_PATH_MANAGER,
+ HAL_DBUS_INTERFACE_MANAGER);
+ ret = dbus_g_proxy_call (proxy, "FindDeviceStringMatch", error,
+ G_TYPE_STRING, key,
+ G_TYPE_STRING, value,
+ G_TYPE_INVALID,
+ G_TYPE_STRV, devices,
+ G_TYPE_INVALID);
+ if (!ret) {
+ *devices = NULL;
+ }
+ return ret;
+}
+
+/**
+ * hal_manager_free_capability:
+ *
+ * @value: The list of strings to free
+ *
+ * Frees value result of hal_manager_find_capability. Safe to call with NULL.
+ **/
+void
+hal_manager_free_capability (gchar **value)
+{
+ gint i;
+
+ if (value == NULL) {
+ return;
+ }
+ for (i=0; value[i]; i++) {
+ g_free (value[i]);
+ }
+ g_free (value);
+}
+
+/**
+ * hal_manager_num_devices_of_capability:
+ *
+ * @manager: This class instance
+ * @capability: The capability, e.g. "battery"
+ * Return value: Number of devices of that capability
+ *
+ * Get the number of devices on system with a specific capability
+ **/
+gint
+hal_manager_num_devices_of_capability (HalManager *manager,
+ const gchar *capability)
+{
+ gint i;
+ gchar **names;
+ gboolean ret;
+
+ g_return_val_if_fail (HAL_IS_MANAGER (manager), 0);
+ g_return_val_if_fail (capability != NULL, 0);
+
+ ret = hal_manager_find_capability (manager, capability, &names, NULL);
+ if (!ret) {
+ return 0;
+ }
+ /* iterate to find number of items */
+ for (i = 0; names[i]; i++) {};
+ hal_manager_free_capability (names);
+ return i;
+}
+
+/**
+ * hal_manager_num_devices_of_capability_with_value:
+ *
+ * @manager: This class instance
+ * @capability: The capability, e.g. "battery"
+ * @key: The key to match, e.g. "button.type"
+ * @value: The key match, e.g. "power"
+ * Return value: Number of devices of that capability
+ *
+ * Get the number of devices on system with a specific capability and key value
+ **/
+gint
+hal_manager_num_devices_of_capability_with_value (HalManager *manager,
+ const gchar *capability,
+ const gchar *key,
+ const gchar *value)
+{
+ gint i;
+ gint valid = 0;
+ gchar **names;
+ gboolean ret;
+ HalDevice *hal_device;
+
+ g_return_val_if_fail (HAL_IS_MANAGER (manager), 0);
+ g_return_val_if_fail (capability != NULL, 0);
+ g_return_val_if_fail (key != NULL, 0);
+ g_return_val_if_fail (value != NULL, 0);
+
+ ret = hal_manager_find_capability (manager, capability, &names, NULL);
+ if (!ret) {
+ return 0;
+ }
+ for (i = 0; names[i]; i++) {
+ gchar *type = NULL;
+ hal_device = hal_device_new ();
+ hal_device_set_udi (hal_device, names[i]);
+ hal_device_get_string (hal_device, key, &type, NULL);
+ g_object_unref (hal_device);
+ if (type != NULL) {
+ if (strcmp (type, value) == 0)
+ valid++;
+ g_free (type);
+ }
+ }
+ hal_manager_free_capability (names);
+ return valid;
+}
+
+/**
+ * hal_manager_class_init:
+ * @klass: This class instance
+ **/
+static void
+hal_manager_class_init (HalManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ object_class->finalize = hal_manager_finalize;
+ g_type_class_add_private (klass, sizeof (HalManagerPrivate));
+
+ signals [DEVICE_ADDED] =
+ g_signal_new ("device-added",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalManagerClass, device_added),
+ NULL,
+ NULL,
+ hal_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ signals [DEVICE_REMOVED] =
+ g_signal_new ("device-removed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalManagerClass, device_removed),
+ NULL,
+ NULL,
+ hal_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ signals [NEW_CAPABILITY] =
+ g_signal_new ("new-capability",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalManagerClass, new_capability),
+ NULL,
+ NULL,
+ hal_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_STRING);
+
+ signals [LOST_CAPABILITY] =
+ g_signal_new ("lost-capability",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalManagerClass, lost_capability),
+ NULL,
+ NULL,
+ hal_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_STRING);
+
+ signals [DAEMON_START] =
+ g_signal_new ("daemon-start",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalManagerClass, daemon_start),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+
+ signals [DAEMON_STOP] =
+ g_signal_new ("daemon-stop",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (HalManagerClass, daemon_stop),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0);
+}
+
+/**
+ * hal_manager_device_added_cb:
+ *
+ * @proxy: The org.freedesktop.Hal.Manager proxy
+ * @udi: Univerisal Device Id
+ * @manager: This class instance
+ *
+ * Invoked when a device is added.
+ */
+static void
+hal_manager_device_added_cb (DBusGProxy *proxy,
+ const gchar *udi,
+ HalManager *manager)
+{
+ g_signal_emit (manager, signals [DEVICE_ADDED], 0, udi);
+}
+
+/**
+ * hal_manager_device_removed_cb:
+ *
+ * @proxy: The org.freedesktop.Hal.Manager proxy
+ * @udi: Univerisal Device Id
+ * @manager: This class instance
+ *
+ * Invoked when a device is removed.
+ */
+static void
+hal_manager_device_removed_cb (DBusGProxy *proxy,
+ const gchar *udi,
+ HalManager *manager)
+{
+ g_signal_emit (manager, signals [DEVICE_REMOVED], 0, udi);
+}
+
+/**
+ * hal_manager_new_capability_cb:
+ *
+ * @proxy: The org.freedesktop.Hal.Manager proxy
+ * @udi: Univerisal Device Id
+ * @capability: The new capability, e.g. "battery"
+ * @manager: This class instance
+ *
+ * Invoked when a device gets a new condition.
+ */
+static void
+hal_manager_new_capability_cb (DBusGProxy *proxy,
+ const gchar *udi,
+ const gchar *capability,
+ HalManager *manager)
+{
+ g_signal_emit (manager, signals [NEW_CAPABILITY], 0, udi, capability);
+}
+
+/**
+ * hal_manager_proxy_connect_more:
+ *
+ * @manager: This class instance
+ * Return value: Success
+ *
+ * Connect the manager proxy to HAL and register some basic callbacks
+ */
+static gboolean
+hal_manager_proxy_connect_more (HalManager *manager)
+{
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_MANAGER (manager), FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (manager->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+
+ /* connect the org.freedesktop.Hal.Manager signals */
+ dbus_g_proxy_add_signal (proxy, "DeviceAdded",
+ G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (proxy, "DeviceAdded",
+ G_CALLBACK (hal_manager_device_added_cb), manager, NULL);
+
+ dbus_g_proxy_add_signal (proxy, "DeviceRemoved",
+ G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (proxy, "DeviceRemoved",
+ G_CALLBACK (hal_manager_device_removed_cb), manager, NULL);
+
+ dbus_g_object_register_marshaller (hal_marshal_VOID__STRING_STRING,
+ G_TYPE_NONE, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_add_signal (proxy, "NewCapability",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (proxy, "NewCapability",
+ G_CALLBACK (hal_manager_new_capability_cb), manager, NULL);
+
+ return TRUE;
+}
+
+/**
+ * hal_manager_proxy_disconnect_more:
+ *
+ * @manager: This class instance
+ * Return value: Success
+ *
+ * Disconnect the manager proxy to HAL_MANAGER and disconnect some basic callbacks
+ */
+static gboolean
+hal_manager_proxy_disconnect_more (HalManager *manager)
+{
+ DBusGProxy *proxy;
+
+ g_return_val_if_fail (HAL_IS_MANAGER (manager), FALSE);
+
+ proxy = egg_dbus_proxy_get_proxy (manager->priv->gproxy);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("proxy NULL!!");
+ return FALSE;
+ }
+
+ dbus_g_proxy_disconnect_signal (proxy, "DeviceRemoved",
+ G_CALLBACK (hal_manager_device_removed_cb), manager);
+ dbus_g_proxy_disconnect_signal (proxy, "NewCapability",
+ G_CALLBACK (hal_manager_new_capability_cb), manager);
+
+ return TRUE;
+}
+
+/**
+ * proxy_status_cb:
+ * @proxy: The dbus raw proxy
+ * @status: The status of the service, where TRUE is connected
+ * @manager: This class instance
+ **/
+static void
+proxy_status_cb (DBusGProxy *proxy,
+ gboolean status,
+ HalManager *manager)
+{
+ g_return_if_fail (HAL_IS_MANAGER (manager));
+ if (status) {
+ g_signal_emit (manager, signals [DAEMON_START], 0);
+ } else {
+ g_signal_emit (manager, signals [DAEMON_STOP], 0);
+ }
+}
+
+/**
+ * hal_manager_init:
+ *
+ * @manager: This class instance
+ **/
+static void
+hal_manager_init (HalManager *manager)
+{
+ GError *error = NULL;
+ DBusGProxy *proxy;
+ DBusGConnection *connection;
+ gboolean ret;
+
+ manager->priv = HAL_MANAGER_GET_PRIVATE (manager);
+
+ manager->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (error) {
+ egg_warning ("%s", error->message);
+ g_error_free (error);
+ }
+
+ /* get the manager connection */
+ manager->priv->gproxy = egg_dbus_proxy_new ();
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL);
+ proxy = egg_dbus_proxy_assign (manager->priv->gproxy, connection,
+ HAL_DBUS_SERVICE, HAL_DBUS_PATH_MANAGER,
+ HAL_DBUS_INTERFACE_MANAGER);
+ if (DBUS_IS_G_PROXY (proxy) == FALSE) {
+ egg_warning ("Either HAL or DBUS are not working!");
+ exit (0);
+ }
+
+ g_signal_connect (manager->priv->gproxy, "proxy-status",
+ G_CALLBACK (proxy_status_cb), manager);
+
+ /* use the computer object */
+ manager->priv->computer = hal_device_new();
+ ret = hal_device_set_udi (manager->priv->computer, HAL_ROOT_COMPUTER);
+ if (!ret) {
+ egg_warning ("failed to get Computer root object");
+ }
+
+ /* blindly try to connect, assuming HAL is alive */
+ hal_manager_proxy_connect_more (manager);
+}
+
+/**
+ * hal_manager_is_laptop:
+ *
+ * @manager: This class instance
+ * Return value: TRUE is computer is identified as a laptop
+ *
+ * Returns true if system.formfactor is "laptop"
+ **/
+gboolean
+hal_manager_is_laptop (HalManager *manager)
+{
+ gboolean ret = TRUE;
+ gchar *formfactor = NULL;
+
+ g_return_val_if_fail (HAL_IS_MANAGER (manager), FALSE);
+
+ /* always present */
+ hal_device_get_string (manager->priv->computer, "system.formfactor", &formfactor, NULL);
+ if (formfactor == NULL) {
+ /* no need to free */
+ return FALSE;
+ }
+ if (strcmp (formfactor, "laptop") != 0) {
+ egg_warning ("This machine is not identified as a laptop."
+ "system.formfactor is %s.", formfactor);
+ ret = FALSE;
+ }
+ g_free (formfactor);
+ return ret;
+}
+
+/**
+ * hal_manager_finalize:
+ * @object: This class instance
+ **/
+static void
+hal_manager_finalize (GObject *object)
+{
+ HalManager *manager;
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (HAL_IS_MANAGER (object));
+
+ manager = HAL_MANAGER (object);
+ manager->priv = HAL_MANAGER_GET_PRIVATE (manager);
+
+ g_object_unref (manager->priv->gproxy);
+ g_object_unref (manager->priv->computer);
+
+ G_OBJECT_CLASS (hal_manager_parent_class)->finalize (object);
+}
+
+/**
+ * hal_manager_new:
+ * Return value: new HalManager instance.
+ **/
+HalManager *
+hal_manager_new (void)
+{
+ if (hal_manager_object != NULL) {
+ g_object_ref (hal_manager_object);
+ } else {
+ hal_manager_object = g_object_new (HAL_TYPE_MANAGER, NULL);
+ g_object_add_weak_pointer (hal_manager_object, &hal_manager_object);
+ }
+ return HAL_MANAGER (hal_manager_object);
+}
+
diff --git a/plugins/media-keys/libhal-glib/hal-manager.h b/plugins/media-keys/libhal-glib/hal-manager.h
new file mode 100644
index 00000000..dd60dc25
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-manager.h
@@ -0,0 +1,106 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005-2006 Richard Hughes <richard@hughsie.com>
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __HAL_MANAGER_H
+#define __HAL_MANAGER_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define HAL_DBUS_SERVICE "org.freedesktop.Hal"
+#define HAL_DBUS_PATH_MANAGER "/org/freedesktop/Hal/Manager"
+#define HAL_DBUS_INTERFACE_MANAGER "org.freedesktop.Hal.Manager"
+#define HAL_DBUS_INTERFACE_DEVICE "org.freedesktop.Hal.Device"
+#define HAL_DBUS_INTERFACE_LAPTOP_PANEL "org.freedesktop.Hal.Device.LaptopPanel"
+#define HAL_DBUS_INTERFACE_POWER "org.freedesktop.Hal.Device.SystemPowerManagement"
+#define HAL_DBUS_INTERFACE_CPUFREQ "org.freedesktop.Hal.Device.CPUFreq"
+#define HAL_DBUS_INTERFACE_KBD_BACKLIGHT "org.freedesktop.Hal.Device.KeyboardBacklight"
+#define HAL_DBUS_INTERFACE_LIGHT_SENSOR "org.freedesktop.Hal.Device.LightSensor"
+#define HAL_ROOT_COMPUTER "/org/freedesktop/Hal/devices/computer"
+
+#define HAL_TYPE_MANAGER (hal_manager_get_type ())
+#define HAL_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), HAL_TYPE_MANAGER, HalManager))
+#define HAL_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), HAL_TYPE_MANAGER, HalManagerClass))
+#define HAL_IS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), HAL_TYPE_MANAGER))
+#define HAL_IS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), HAL_TYPE_MANAGER))
+#define HAL_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), HAL_TYPE_MANAGER, HalManagerClass))
+
+typedef struct HalManagerPrivate HalManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ HalManagerPrivate *priv;
+} HalManager;
+
+/* Signals emitted from HalManager are:
+ *
+ * device-added
+ * device-removed
+ * new-capability
+ * lost-capability
+ * daemon-start
+ * daemon-stop
+ */
+
+typedef struct
+{
+ GObjectClass parent_class;
+ void (* device_added) (HalManager *manager,
+ const gchar *udi);
+ void (* device_removed) (HalManager *manager,
+ const gchar *udi);
+ void (* new_capability) (HalManager *manager,
+ const gchar *udi,
+ const gchar *capability);
+ void (* lost_capability) (HalManager *manager,
+ const gchar *udi,
+ const gchar *capability);
+ void (* daemon_start) (HalManager *manager);
+ void (* daemon_stop) (HalManager *manager);
+} HalManagerClass;
+
+GType hal_manager_get_type (void);
+HalManager *hal_manager_new (void);
+
+gboolean hal_manager_is_running (HalManager *manager);
+gint hal_manager_num_devices_of_capability (HalManager *manager,
+ const gchar *capability);
+gint hal_manager_num_devices_of_capability_with_value (HalManager *manager,
+ const gchar *capability,
+ const gchar *key,
+ const gchar *value);
+gboolean hal_manager_find_capability (HalManager *manager,
+ const gchar *capability,
+ gchar ***value,
+ GError **error);
+gboolean hal_manager_find_device_string_match (HalManager *manager,
+ const gchar *key,
+ const gchar *value,
+ gchar ***devices,
+ GError **error);
+void hal_manager_free_capability (gchar **value);
+gboolean hal_manager_is_laptop (HalManager *manager);
+
+G_END_DECLS
+
+#endif /* __HAL_MANAGER_H */
diff --git a/plugins/media-keys/libhal-glib/hal-marshal.list b/plugins/media-keys/libhal-glib/hal-marshal.list
new file mode 100644
index 00000000..e5eb3da1
--- /dev/null
+++ b/plugins/media-keys/libhal-glib/hal-marshal.list
@@ -0,0 +1,9 @@
+NONE:INT,BOXED
+NONE:STRING,STRING
+NONE:STRING,STRING,STRING
+NONE:STRING,BOOLEAN
+NONE:STRING,STRING,BOOLEAN
+NONE:STRING,BOOLEAN,BOOLEAN,BOOLEAN
+NONE:INT
+NONE:STRING
+NONE:INT,LONG,BOOLEAN,BOOLEAN