/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- * * Copyright (C) 2010-2012 Richard Hughes * * Licensed under the GNU Lesser General Public License Version 2.1 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * SECTION:cd-sensor * @short_description: Client object for accessing information about colord sensors * * A helper GObject to use for accessing colord sensors, and to be notified * when it is changed. * * See also: #CdClient */ #include "config.h" #include #include #include #include #include "cd-sensor.h" static void cd_sensor_class_init (CdSensorClass *klass); static void cd_sensor_init (CdSensor *sensor); static void cd_sensor_finalize (GObject *object); #define CD_SENSOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CD_TYPE_SENSOR, CdSensorPrivate)) #define COLORD_DBUS_SERVICE "org.freedesktop.ColorManager" #define COLORD_DBUS_INTERFACE_SENSOR "org.freedesktop.ColorManager.Sensor" /** * CdSensorPrivate: * * Private #CdSensor data **/ struct _CdSensorPrivate { gchar *object_path; CdSensorKind kind; CdSensorState state; CdSensorCap mode; gchar *serial; gchar *model; gchar *vendor; gboolean native; gboolean locked; guint caps; GHashTable *options; GDBusProxy *proxy; }; enum { PROP_0, PROP_OBJECT_PATH, PROP_CONNECTED, PROP_KIND, PROP_STATE, PROP_MODE, PROP_SERIAL, PROP_MODEL, PROP_VENDOR, PROP_NATIVE, PROP_LOCKED, PROP_LAST }; enum { SIGNAL_BUTTON_PRESSED, SIGNAL_LAST }; static guint signals [SIGNAL_LAST] = { 0 }; G_DEFINE_TYPE (CdSensor, cd_sensor, G_TYPE_OBJECT) /** * cd_sensor_error_quark: * * Return value: An error quark. * * Since: 0.1.6 **/ GQuark cd_sensor_error_quark (void) { static GQuark quark = 0; if (!quark) quark = g_quark_from_static_string ("cd_sensor_error"); return quark; } /** * cd_sensor_set_object_path: * @sensor: a #CdSensor instance. * @object_path: The colord object path. * * Sets the object path of the sensor. * * Since: 0.1.8 **/ void cd_sensor_set_object_path (CdSensor *sensor, const gchar *object_path) { g_return_if_fail (CD_IS_SENSOR (sensor)); g_return_if_fail (sensor->priv->object_path == NULL); sensor->priv->object_path = g_strdup (object_path); } /** * cd_sensor_get_kind: * @sensor: a #CdSensor instance. * * Gets the sensor kind. * * Return value: A #CdSensorKind, e.g. %CD_SENSOR_KIND_HUEY * * Since: 0.1.6 **/ CdSensorKind cd_sensor_get_kind (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), CD_SENSOR_KIND_UNKNOWN); g_return_val_if_fail (sensor->priv->proxy != NULL, CD_SENSOR_KIND_UNKNOWN); return sensor->priv->kind; } /** * cd_sensor_get_state: * @sensor: a #CdSensor instance. * * Gets the sensor state. * * Return value: A #CdSensorState, e.g. %CD_SENSOR_STATE_IDLE * * Since: 0.1.6 **/ CdSensorState cd_sensor_get_state (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), CD_SENSOR_STATE_UNKNOWN); g_return_val_if_fail (sensor->priv->proxy != NULL, CD_SENSOR_STATE_UNKNOWN); return sensor->priv->state; } /** * cd_sensor_get_mode: * @sensor: a #CdSensor instance. * * Gets the sensor operating mode. * * Return value: A #CdSensorCap, e.g. %CD_SENSOR_CAP_AMBIENT * * Since: 0.1.6 **/ CdSensorCap cd_sensor_get_mode (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), CD_SENSOR_CAP_UNKNOWN); g_return_val_if_fail (sensor->priv->proxy != NULL, CD_SENSOR_CAP_UNKNOWN); return sensor->priv->mode; } /** * cd_sensor_get_serial: * @sensor: a #CdSensor instance. * * Gets the sensor serial number. * * Return value: A string, or %NULL for invalid * * Since: 0.1.6 **/ const gchar * cd_sensor_get_serial (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), NULL); g_return_val_if_fail (sensor->priv->proxy != NULL, NULL); return sensor->priv->serial; } /** * cd_sensor_get_model: * @sensor: a #CdSensor instance. * * Gets the sensor model. * * Return value: A string, or %NULL for invalid * * Since: 0.1.6 **/ const gchar * cd_sensor_get_model (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), NULL); g_return_val_if_fail (sensor->priv->proxy != NULL, NULL); return sensor->priv->model; } /** * cd_sensor_get_vendor: * @sensor: a #CdSensor instance. * * Gets the sensor vendor. * * Return value: A string, or %NULL for invalid * * Since: 0.1.6 **/ const gchar * cd_sensor_get_vendor (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), NULL); g_return_val_if_fail (sensor->priv->proxy != NULL, NULL); return sensor->priv->vendor; } /** * cd_sensor_get_native: * @sensor: a #CdSensor instance. * * Returns if the sensor has a native driver. * * Return value: %TRUE if VCGT is valid. * * Since: 0.1.6 **/ gboolean cd_sensor_get_native (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), FALSE); g_return_val_if_fail (sensor->priv->proxy != NULL, FALSE); return sensor->priv->native; } /** * cd_sensor_get_locked: * @sensor: a #CdSensor instance. * * Returns if the sensor is locked. * * Return value: %TRUE if VCGT is valid. * * Since: 0.1.6 **/ gboolean cd_sensor_get_locked (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), FALSE); g_return_val_if_fail (sensor->priv->proxy != NULL, FALSE); return sensor->priv->locked; } /** * cd_sensor_get_caps: * @sensor: a #CdSensor instance. * * Returns the sensor metadata. * * Return value: a #GHashTable, free with g_hash_table_unref(). * * Since: 0.1.6 **/ guint cd_sensor_get_caps (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), 0); g_return_val_if_fail (sensor->priv->proxy != NULL, 0); return sensor->priv->caps; } /** * cd_sensor_get_caps_item: * @sensor: a #CdSensor instance. * @cap: a specified capability, e.g. %CD_SENSOR_CAP_LCD * * Returns the sensor metadata for a specific key. * * Return value: %TRUE if the sensor has the specified capability * * Since: 0.1.6 **/ gboolean cd_sensor_has_cap (CdSensor *sensor, CdSensorCap cap) { g_return_val_if_fail (CD_IS_SENSOR (sensor), FALSE); g_return_val_if_fail (sensor->priv->proxy != NULL, FALSE); return (sensor->priv->caps & (1 << cap)) > 0; } /** * cd_sensor_set_caps_from_variant: **/ static void cd_sensor_set_caps_from_variant (CdSensor *sensor, GVariant *variant) { const gchar **caps_tmp; guint i; guint value; /* remove old entries */ sensor->priv->caps = 0; /* insert the new metadata */ caps_tmp = g_variant_get_strv (variant, NULL); for (i=0; caps_tmp[i] != NULL; i++) { value = 1 << cd_sensor_cap_from_string (caps_tmp[i]); sensor->priv->caps += value; } } /** * cd_sensor_set_options_from_variant: **/ static void cd_sensor_set_options_from_variant (CdSensor *sensor, GVariant *variant) { const gchar *prop_key; GVariantIter iter; GVariant *prop_value; /* remove old entries */ g_hash_table_remove_all (sensor->priv->options); /* insert the new options */ g_variant_iter_init (&iter, variant); while (g_variant_iter_loop (&iter, "{sv}", &prop_key, &prop_value)) { g_hash_table_insert (sensor->priv->options, g_strdup (prop_key), g_variant_ref (prop_value)); } } /** * cd_sensor_dbus_properties_changed_cb: **/ static void cd_sensor_dbus_properties_changed_cb (GDBusProxy *proxy, GVariant *changed_properties, const gchar * const *invalidated_properties, CdSensor *sensor) { guint i; guint len; GVariantIter iter; gchar *property_name; GVariant *property_value; g_return_if_fail (CD_IS_SENSOR (sensor)); len = g_variant_iter_init (&iter, changed_properties); for (i=0; i < len; i++) { g_variant_get_child (changed_properties, i, "{sv}", &property_name, &property_value); if (g_strcmp0 (property_name, "Kind") == 0) { sensor->priv->kind = cd_sensor_kind_from_string (g_variant_get_string (property_value, NULL)); g_object_notify (G_OBJECT (sensor), "kind"); } else if (g_strcmp0 (property_name, "State") == 0) { sensor->priv->state = cd_sensor_state_from_string (g_variant_get_string (property_value, NULL)); g_object_notify (G_OBJECT (sensor), "state"); } else if (g_strcmp0 (property_name, "Mode") == 0) { sensor->priv->mode = cd_sensor_cap_from_string (g_variant_get_string (property_value, NULL)); g_object_notify (G_OBJECT (sensor), "mode"); } else if (g_strcmp0 (property_name, "Serial") == 0) { g_free (sensor->priv->serial); sensor->priv->serial = g_variant_dup_string (property_value, NULL); g_object_notify (G_OBJECT (sensor), "serial"); } else if (g_strcmp0 (property_name, "Model") == 0) { g_free (sensor->priv->model); sensor->priv->model = g_variant_dup_string (property_value, NULL); g_object_notify (G_OBJECT (sensor), "model"); } else if (g_strcmp0 (property_name, "Vendor") == 0) { g_free (sensor->priv->vendor); sensor->priv->vendor = g_variant_dup_string (property_value, NULL); g_object_notify (G_OBJECT (sensor), "vendor"); } else if (g_strcmp0 (property_name, "Native") == 0) { sensor->priv->native = g_variant_get_boolean (property_value); g_object_notify (G_OBJECT (sensor), "native"); } else if (g_strcmp0 (property_name, "Locked") == 0) { sensor->priv->locked = g_variant_get_boolean (property_value); g_object_notify (G_OBJECT (sensor), "locked"); } else if (g_strcmp0 (property_name, "Capabilities") == 0) { cd_sensor_set_caps_from_variant (sensor, property_value); g_object_notify (G_OBJECT (sensor), "capabilities"); } else if (g_strcmp0 (property_name, "Options") == 0) { cd_sensor_set_options_from_variant (sensor, property_value); } else { g_warning ("%s property unhandled", property_name); } g_variant_unref (property_value); } } /** * cd_sensor_dbus_signal_cb: **/ static void cd_sensor_dbus_signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name, GVariant *parameters, CdSensor *sensor) { g_return_if_fail (CD_IS_SENSOR (sensor)); if (g_strcmp0 (signal_name, "ButtonPressed") == 0) { g_signal_emit (sensor, signals[SIGNAL_BUTTON_PRESSED], 0); } else { g_warning ("unhandled signal '%s'", signal_name); } } /**********************************************************************/ /** * cd_sensor_connect_cb: **/ static void cd_sensor_connect_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVariant *model = NULL; GVariant *serial = NULL; GVariant *vendor = NULL; GVariant *kind = NULL; GVariant *state = NULL; GVariant *mode = NULL; GVariant *native = NULL; GVariant *locked = NULL; GVariant *caps = NULL; GSimpleAsyncResult *res_source = G_SIMPLE_ASYNC_RESULT (user_data); CdSensor *sensor = CD_SENSOR (g_async_result_get_source_object (G_ASYNC_RESULT (user_data))); GError *error = NULL; /* get result */ sensor->priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error); if (sensor->priv->proxy == NULL) { g_simple_async_result_set_from_error (res_source, error); g_simple_async_result_complete (res_source); g_error_free (error); goto out; } /* get kind */ kind = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "Kind"); if (kind != NULL) sensor->priv->kind = cd_sensor_kind_from_string (g_variant_get_string (kind, NULL)); /* get state */ state = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "State"); if (state != NULL) sensor->priv->state = cd_colorspace_from_string (g_variant_get_string (state, NULL)); /* get mode */ mode = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "Mode"); if (mode != NULL) sensor->priv->mode = cd_sensor_cap_from_string (g_variant_get_string (state, NULL)); /* get sensor serial */ serial = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "Serial"); if (serial != NULL) sensor->priv->serial = g_variant_dup_string (serial, NULL); /* get vendor */ vendor = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "Vendor"); if (vendor != NULL) sensor->priv->vendor = g_variant_dup_string (vendor, NULL); /* get vendor */ model = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "Model"); if (model != NULL) sensor->priv->model = g_variant_dup_string (model, NULL); /* get native */ native = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "Native"); if (native != NULL) sensor->priv->native = g_variant_get_boolean (native); /* get locked */ locked = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "Locked"); if (locked != NULL) sensor->priv->locked = g_variant_get_boolean (locked); /* get if system wide */ caps = g_dbus_proxy_get_cached_property (sensor->priv->proxy, "Capabilities"); if (caps != NULL) cd_sensor_set_caps_from_variant (sensor, caps); /* get signals from DBus */ g_signal_connect (sensor->priv->proxy, "g-signal", G_CALLBACK (cd_sensor_dbus_signal_cb), sensor); /* watch if any remote properties change */ g_signal_connect (sensor->priv->proxy, "g-properties-changed", G_CALLBACK (cd_sensor_dbus_properties_changed_cb), sensor); /* we're done */ g_simple_async_result_complete (res_source); out: if (kind != NULL) g_variant_unref (kind); if (state != NULL) g_variant_unref (state); if (mode != NULL) g_variant_unref (mode); if (serial != NULL) g_variant_unref (serial); if (model != NULL) g_variant_unref (model); if (vendor != NULL) g_variant_unref (vendor); if (native != NULL) g_variant_unref (native); if (locked != NULL) g_variant_unref (locked); if (caps != NULL) g_variant_unref (caps); g_object_unref (res_source); } /** * cd_sensor_connect: * @sensor: a #CdSensor instance * @cancellable: a #GCancellable or %NULL * @callback: the function to run on completion * @user_data: the data to pass to @callback * * Connects to the sensor. * * Since: 0.1.8 **/ void cd_sensor_connect (CdSensor *sensor, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *res; g_return_if_fail (CD_IS_SENSOR (sensor)); g_return_if_fail (callback != NULL); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); res = g_simple_async_result_new (G_OBJECT (sensor), callback, user_data, cd_sensor_connect); /* already connected */ if (sensor->priv->proxy != NULL) { g_simple_async_result_set_op_res_gboolean (res, TRUE); g_simple_async_result_complete_in_idle (res); return; } /* connect async */ g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, NULL, COLORD_DBUS_SERVICE, sensor->priv->object_path, COLORD_DBUS_INTERFACE_SENSOR, cancellable, cd_sensor_connect_cb, res); } /** * cd_sensor_connect_finish: * @sensor: a #CdSensor instance * @res: the #GAsyncResult * @error: A #GError or %NULL * * Gets the result from the asynchronous function. * * Return value: %TRUE if we could connect to to the sensor * * Since: 0.1.8 **/ gboolean cd_sensor_connect_finish (CdSensor *sensor, GAsyncResult *res, GError **error) { gpointer source_tag; GSimpleAsyncResult *simple; g_return_val_if_fail (CD_IS_SENSOR (sensor), FALSE); g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); simple = G_SIMPLE_ASYNC_RESULT (res); source_tag = g_simple_async_result_get_source_tag (simple); g_return_val_if_fail (source_tag == cd_sensor_connect, FALSE); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; return TRUE; } /**********************************************************************/ /** * cd_sensor_lock_finish: * @sensor: a #CdSensor instance. * @res: the #GAsyncResult * @error: A #GError or %NULL * * Gets the result from the asynchronous function. * * Return value: success * * Since: 0.1.8 **/ gboolean cd_sensor_lock_finish (CdSensor *sensor, GAsyncResult *res, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail (CD_IS_SENSOR (sensor), FALSE); g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); simple = G_SIMPLE_ASYNC_RESULT (res); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; return g_simple_async_result_get_op_res_gboolean (simple); } static void cd_sensor_lock_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; GVariant *result; GSimpleAsyncResult *res_source = G_SIMPLE_ASYNC_RESULT (user_data); result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (result == NULL) { g_simple_async_result_set_error (res_source, CD_SENSOR_ERROR, CD_SENSOR_ERROR_FAILED, "Failed to Lock: %s", error->message); g_error_free (error); goto out; } /* success */ g_simple_async_result_set_op_res_gboolean (res_source, TRUE); g_variant_unref (result); out: g_simple_async_result_complete_in_idle (res_source); g_object_unref (res_source); } /** * cd_sensor_lock: * @sensor: a #CdSensor instance. * @cancellable: a #GCancellable, or %NULL * @callback: the function to run on completion * @user_data: the data to pass to @callback * * Locks the device so we can use it. * * Since: 0.1.8 **/ void cd_sensor_lock (CdSensor *sensor, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *res; g_return_if_fail (CD_IS_SENSOR (sensor)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (sensor->priv->proxy != NULL); res = g_simple_async_result_new (G_OBJECT (sensor), callback, user_data, cd_sensor_lock); g_dbus_proxy_call (sensor->priv->proxy, "Lock", NULL, G_DBUS_CALL_FLAGS_NONE, -1, cancellable, cd_sensor_lock_cb, res); } /**********************************************************************/ /** * cd_sensor_unlock_finish: * @sensor: a #CdSensor instance. * @res: the #GAsyncResult * @error: A #GError or %NULL * * Gets the result from the asynchronous function. * * Return value: success * * Since: 0.1.8 **/ gboolean cd_sensor_unlock_finish (CdSensor *sensor, GAsyncResult *res, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail (CD_IS_SENSOR (sensor), FALSE); g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); simple = G_SIMPLE_ASYNC_RESULT (res); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; return g_simple_async_result_get_op_res_gboolean (simple); } static void cd_sensor_unlock_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; GVariant *result; GSimpleAsyncResult *res_source = G_SIMPLE_ASYNC_RESULT (user_data); result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (result == NULL) { g_simple_async_result_set_error (res_source, CD_SENSOR_ERROR, CD_SENSOR_ERROR_FAILED, "Failed to Unlock: %s", error->message); g_error_free (error); goto out; } /* success */ g_simple_async_result_set_op_res_gboolean (res_source, TRUE); g_variant_unref (result); out: g_simple_async_result_complete_in_idle (res_source); g_object_unref (res_source); } /** * cd_sensor_unlock: * @sensor: a #CdSensor instance. * @cancellable: a #GCancellable, or %NULL * @callback: the function to run on completion * @user_data: the data to pass to @callback * * Unlocks the sensor for use by other programs. * * Since: 0.1.8 **/ void cd_sensor_unlock (CdSensor *sensor, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *res; g_return_if_fail (CD_IS_SENSOR (sensor)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (sensor->priv->proxy != NULL); res = g_simple_async_result_new (G_OBJECT (sensor), callback, user_data, cd_sensor_unlock); g_dbus_proxy_call (sensor->priv->proxy, "Unlock", NULL, G_DBUS_CALL_FLAGS_NONE, -1, cancellable, cd_sensor_unlock_cb, res); } /**********************************************************************/ /** * cd_sensor_set_options_finish: * @sensor: a #CdSensor instance. * @res: the #GAsyncResult * @error: A #GError or %NULL * * Gets the result from the asynchronous function. * * Return value: success * * Since: 0.1.20 **/ gboolean cd_sensor_set_options_finish (CdSensor *sensor, GAsyncResult *res, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail (CD_IS_SENSOR (sensor), FALSE); g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), FALSE); g_return_val_if_fail (error == NULL || *error == NULL, FALSE); simple = G_SIMPLE_ASYNC_RESULT (res); if (g_simple_async_result_propagate_error (simple, error)) return FALSE; return g_simple_async_result_get_op_res_gboolean (simple); } static void cd_sensor_set_options_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; GVariant *result; GSimpleAsyncResult *res_source = G_SIMPLE_ASYNC_RESULT (user_data); result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (result == NULL) { g_simple_async_result_set_error (res_source, CD_SENSOR_ERROR, CD_SENSOR_ERROR_FAILED, "Failed to set sensor options: %s", error->message); g_error_free (error); goto out; } /* success */ g_simple_async_result_set_op_res_gboolean (res_source, TRUE); g_variant_unref (result); out: g_simple_async_result_complete_in_idle (res_source); g_object_unref (res_source); } /** * cd_sensor_set_options: * @sensor: a #CdSensor instance. * @cancellable: a #GCancellable, or %NULL * @callback: the function to run on completion * @user_data: the data to pass to @callback * * Sets options on the sensor device. * * Since: 0.1.20 **/ void cd_sensor_set_options (CdSensor *sensor, GHashTable *values, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GList *list, *l; GSimpleAsyncResult *res; GVariantBuilder builder; g_return_if_fail (CD_IS_SENSOR (sensor)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (sensor->priv->proxy != NULL); res = g_simple_async_result_new (G_OBJECT (sensor), callback, user_data, cd_sensor_set_options); /* convert the hash table to an array of {sv} */ g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); list = g_hash_table_get_keys (values); for (l = list; l != NULL; l = l->next) { g_variant_builder_add (&builder, "{sv}", l->data, g_hash_table_lookup (values, l->data)); } g_list_free (list); g_dbus_proxy_call (sensor->priv->proxy, "SetOptions", g_variant_new ("(a{sv})", &builder), G_DBUS_CALL_FLAGS_NONE, -1, cancellable, cd_sensor_set_options_cb, res); } /**********************************************************************/ /** * cd_sensor_get_sample_finish: * @sensor: a #CdSensor instance. * @res: the #GAsyncResult * @error: A #GError or %NULL * * Gets the result from the asynchronous function. * * Return value: the XYZ reading, or %NULL * * Since: 0.1.8 **/ CdColorXYZ * cd_sensor_get_sample_finish (CdSensor *sensor, GAsyncResult *res, GError **error) { GSimpleAsyncResult *simple; g_return_val_if_fail (CD_IS_SENSOR (sensor), NULL); g_return_val_if_fail (G_IS_SIMPLE_ASYNC_RESULT (res), NULL); g_return_val_if_fail (error == NULL || *error == NULL, NULL); simple = G_SIMPLE_ASYNC_RESULT (res); if (g_simple_async_result_propagate_error (simple, error)) return NULL; return cd_color_xyz_dup (g_simple_async_result_get_op_res_gpointer (simple)); } static void cd_sensor_get_sample_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GError *error = NULL; GVariant *result; CdColorXYZ *xyz; GSimpleAsyncResult *res_source = G_SIMPLE_ASYNC_RESULT (user_data); result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error); if (result == NULL) { g_simple_async_result_set_error (res_source, CD_SENSOR_ERROR, CD_SENSOR_ERROR_FAILED, "Failed to GetSample: %s", error->message); g_error_free (error); goto out; } /* success */ xyz = cd_color_xyz_new (); g_variant_get (result, "(ddd)", &xyz->X, &xyz->Y, &xyz->Z); g_simple_async_result_set_op_res_gpointer (res_source, xyz, (GDestroyNotify) cd_color_xyz_free); g_variant_unref (result); out: g_simple_async_result_complete_in_idle (res_source); g_object_unref (res_source); } /** * cd_sensor_get_sample: * @sensor: a #CdSensor instance. * @cap: a #CdSensorCap * @cancellable: a #GCancellable, or %NULL * @callback: the function to run on completion * @user_data: the data to pass to @callback * * Gets a color sample from a sensor * * Since: 0.1.8 **/ void cd_sensor_get_sample (CdSensor *sensor, CdSensorCap cap, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { GSimpleAsyncResult *res; g_return_if_fail (CD_IS_SENSOR (sensor)); g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable)); g_return_if_fail (sensor->priv->proxy != NULL); res = g_simple_async_result_new (G_OBJECT (sensor), callback, user_data, cd_sensor_get_sample); g_dbus_proxy_call (sensor->priv->proxy, "GetSample", g_variant_new ("(s)", cd_sensor_cap_to_string (cap)), G_DBUS_CALL_FLAGS_NONE, -1, cancellable, cd_sensor_get_sample_cb, res); } /**********************************************************************/ /** * cd_sensor_get_object_path: * @sensor: a #CdSensor instance. * * Gets the object path for the sensor. * * Return value: the object path, or %NULL * * Since: 0.1.6 **/ const gchar * cd_sensor_get_object_path (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), NULL); return sensor->priv->object_path; } /** * cd_sensor_get_connected: * @sensor: a #CdSensor instance. * * Gets if the sensor has been connected. * * Return value: %TRUE if properties are valid * * Since: 0.1.9 **/ gboolean cd_sensor_get_connected (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), FALSE); return sensor->priv->proxy != NULL; } /** * cd_sensor_get_options: * @sensor: a #CdSensor instance. * * Gets any sensor options. * * Return value: (transfer full): A refcounted #GHashTable of (string, GVariant). * * Since: 0.1.20 **/ GHashTable * cd_sensor_get_options (CdSensor *sensor) { g_return_val_if_fail (CD_IS_SENSOR (sensor), NULL); return g_hash_table_ref (sensor->priv->options); } /** * cd_sensor_get_option: * @sensor: a #CdSensor instance. * @key: a key to search for. * * Gets a specific sensor option. * * Return value: A const string, or %NULL of not found. * * Since: 0.1.20 **/ const gchar * cd_sensor_get_option (CdSensor *sensor, const gchar *key) { g_return_val_if_fail (CD_IS_SENSOR (sensor), NULL); return g_hash_table_lookup (sensor->priv->options, key); } /** * cd_sensor_equal: * @sensor1: one #CdSensor instance. * @sensor2: another #CdSensor instance. * * Tests two sensors for equality. * * Return value: %TRUE if the sensors are the same device * * Since: 0.1.8 **/ gboolean cd_sensor_equal (CdSensor *sensor1, CdSensor *sensor2) { g_return_val_if_fail (CD_IS_SENSOR (sensor1), FALSE); g_return_val_if_fail (CD_IS_SENSOR (sensor2), FALSE); return g_strcmp0 (sensor1->priv->serial, sensor2->priv->serial) == 0; } /* * cd_sensor_set_property: */ static void cd_sensor_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) { CdSensor *sensor = CD_SENSOR (object); switch (prop_id) { case PROP_OBJECT_PATH: g_free (sensor->priv->object_path); sensor->priv->object_path = g_value_dup_string (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } /* * cd_sensor_get_property: */ static void cd_sensor_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) { CdSensor *sensor = CD_SENSOR (object); switch (prop_id) { case PROP_OBJECT_PATH: g_value_set_string (value, sensor->priv->object_path); break; case PROP_CONNECTED: g_value_set_boolean (value, sensor->priv->proxy != NULL); break; case PROP_KIND: g_value_set_uint (value, sensor->priv->kind); break; case PROP_STATE: g_value_set_uint (value, sensor->priv->state); break; case PROP_MODE: g_value_set_uint (value, sensor->priv->mode); break; case PROP_SERIAL: g_value_set_string (value, sensor->priv->serial); break; case PROP_MODEL: g_value_set_string (value, sensor->priv->model); break; case PROP_VENDOR: g_value_set_string (value, sensor->priv->vendor); break; case PROP_NATIVE: g_value_set_boolean (value, sensor->priv->native); break; case PROP_LOCKED: g_value_set_boolean (value, sensor->priv->locked); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } /* * cd_sensor_class_init: */ static void cd_sensor_class_init (CdSensorClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); object_class->finalize = cd_sensor_finalize; object_class->set_property = cd_sensor_set_property; object_class->get_property = cd_sensor_get_property; /** * CdSensor::button-pressed: * @sensor: the #CdSensor instance that emitted the signal * * The ::button-pressed signal is emitted when the button has been pressed. * * Since: 0.1.6 **/ signals [SIGNAL_BUTTON_PRESSED] = g_signal_new ("button-pressed", G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST, G_STRUCT_OFFSET (CdSensorClass, button_pressed), NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); /** * CdSensor:object-path: * * The object path of the remote object * * Since: 0.1.8 **/ g_object_class_install_property (object_class, PROP_OBJECT_PATH, g_param_spec_string ("object-path", NULL, NULL, NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /** * CdSensor:connected: * * The if the object path has been connected as is valid for use. * * Since: 0.1.9 **/ g_object_class_install_property (object_class, PROP_CONNECTED, g_param_spec_string ("connected", NULL, NULL, NULL, G_PARAM_READABLE)); /** * CdSensor:kind: * * The sensor kind. * * Since: 0.1.6 **/ g_object_class_install_property (object_class, PROP_KIND, g_param_spec_string ("kind", NULL, NULL, NULL, G_PARAM_READABLE)); /** * CdSensor:state: * * The sensor state. * * Since: 0.1.6 **/ g_object_class_install_property (object_class, PROP_STATE, g_param_spec_string ("state", NULL, NULL, NULL, G_PARAM_READABLE)); /** * CdSensor:mode: * * The sensor mode. * * Since: 0.1.6 **/ g_object_class_install_property (object_class, PROP_MODE, g_param_spec_string ("mode", NULL, NULL, NULL, G_PARAM_READABLE)); /** * CdSensor:serial: * * The sensor ID. * * Since: 0.1.6 **/ g_object_class_install_property (object_class, PROP_SERIAL, g_param_spec_string ("serial", NULL, NULL, NULL, G_PARAM_READABLE)); /** * CdSensor:model: * * The sensor model. * * Since: 0.1.6 **/ g_object_class_install_property (object_class, PROP_MODEL, g_param_spec_string ("model", NULL, NULL, NULL, G_PARAM_READABLE)); /** * CdSensor:vendor: * * The sensor vendor. * * Since: 0.1.6 **/ g_object_class_install_property (object_class, PROP_VENDOR, g_param_spec_string ("vendor", NULL, NULL, NULL, G_PARAM_READABLE)); /** * CdSensor:native: * * If the sensor has a native driver. * * Since: 0.1.6 **/ g_object_class_install_property (object_class, PROP_NATIVE, g_param_spec_string ("native", NULL, NULL, NULL, G_PARAM_READABLE)); /** * CdSensor:locked: * * If the sensor is locked. * * Since: 0.1.6 **/ g_object_class_install_property (object_class, PROP_LOCKED, g_param_spec_string ("locked", NULL, NULL, NULL, G_PARAM_READABLE)); g_type_class_add_private (klass, sizeof (CdSensorPrivate)); } /* * cd_sensor_init: */ static void cd_sensor_init (CdSensor *sensor) { sensor->priv = CD_SENSOR_GET_PRIVATE (sensor); sensor->priv->options = g_hash_table_new_full (g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_variant_unref); } /* * cd_sensor_finalize: */ static void cd_sensor_finalize (GObject *object) { CdSensor *sensor; guint ret; g_return_if_fail (CD_IS_SENSOR (object)); sensor = CD_SENSOR (object); g_free (sensor->priv->object_path); g_free (sensor->priv->serial); g_free (sensor->priv->model); g_free (sensor->priv->vendor); g_hash_table_unref (sensor->priv->options); if (sensor->priv->proxy != NULL) { ret = g_signal_handlers_disconnect_by_func (sensor->priv->proxy, G_CALLBACK (cd_sensor_dbus_signal_cb), sensor); g_assert (ret > 0); ret = g_signal_handlers_disconnect_by_func (sensor->priv->proxy, G_CALLBACK (cd_sensor_dbus_properties_changed_cb), sensor); g_assert (ret > 0); g_object_unref (sensor->priv->proxy); g_assert (!G_IS_DBUS_PROXY (sensor->priv->proxy)); } G_OBJECT_CLASS (cd_sensor_parent_class)->finalize (object); } /** * cd_sensor_new: * * Creates a new #CdSensor object. * * Return value: a new CdSensor object. * * Since: 0.1.6 **/ CdSensor * cd_sensor_new (void) { CdSensor *sensor; sensor = g_object_new (CD_TYPE_SENSOR, NULL); return CD_SENSOR (sensor); } /** * cd_sensor_new_with_object_path: * @object_path: The colord object path. * * Creates a new #CdSensor object with a known object path. * * Return value: a new sensor object. * * Since: 0.1.8 **/ CdSensor * cd_sensor_new_with_object_path (const gchar *object_path) { CdSensor *sensor; sensor = g_object_new (CD_TYPE_SENSOR, "object-path", object_path, NULL); return CD_SENSOR (sensor); }