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