[gnome-settings-daemon/opensuse-moblin: 12/24] Add libhal-glib



commit 73597b1c95df1c6faa0007f142aca24845b27d3d
Author: Federico Mena Quintero <federico novell com>
Date:   Tue Jan 12 14:04:16 2010 -0600

    Add libhal-glib

 plugins/media-keys/libhal-glib/Makefile.am        |   57 ++
 plugins/media-keys/libhal-glib/egg-dbus-monitor.c |  250 ++++++++
 plugins/media-keys/libhal-glib/egg-dbus-monitor.h |   65 +++
 plugins/media-keys/libhal-glib/egg-dbus-proxy.c   |  293 ++++++++++
 plugins/media-keys/libhal-glib/egg-dbus-proxy.h   |   66 +++
 plugins/media-keys/libhal-glib/egg-debug.c        |  308 ++++++++++
 plugins/media-keys/libhal-glib/egg-debug.h        |   83 +++
 plugins/media-keys/libhal-glib/hal-device-power.c |  541 ++++++++++++++++++
 plugins/media-keys/libhal-glib/hal-device-power.h |   77 +++
 plugins/media-keys/libhal-glib/hal-device-store.c |  309 ++++++++++
 plugins/media-keys/libhal-glib/hal-device-store.h |   67 +++
 plugins/media-keys/libhal-glib/hal-device.c       |  636 +++++++++++++++++++++
 plugins/media-keys/libhal-glib/hal-device.h       |   96 +++
 plugins/media-keys/libhal-glib/hal-manager.c      |  602 +++++++++++++++++++
 plugins/media-keys/libhal-glib/hal-manager.h      |  106 ++++
 plugins/media-keys/libhal-glib/hal-marshal.list   |    9 +
 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 0000000..9dc8730
--- /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 0000000..3375b5d
--- /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 0000000..6aea31d
--- /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 0000000..a76f7b6
--- /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 0000000..2d904d5
--- /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 0000000..f18a5d1
--- /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 0000000..c935dcb
--- /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 0000000..69c8061
--- /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 0000000..702c9a1
--- /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 0000000..ea17809
--- /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 0000000..f45c859
--- /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 0000000..b4d73a6
--- /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 0000000..ffd7e19
--- /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 0000000..d780604
--- /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 0000000..dd60dc2
--- /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 0000000..e5eb3da
--- /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



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