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 /plugins/media-keys/libhal-glib/hal-device.c | |
parent | 4049b530416b99407eaf210fded7aa2550f60ea7 (diff) | |
download | gnome-settings-daemon-73597b1c95df1c6faa0007f142aca24845b27d3d.tar.gz |
Add libhal-glib
Diffstat (limited to 'plugins/media-keys/libhal-glib/hal-device.c')
-rw-r--r-- | plugins/media-keys/libhal-glib/hal-device.c | 636 |
1 files changed, 636 insertions, 0 deletions
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); +} |