1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2010-2013 Richard Hughes <richard@hughsie.com>
4 *
5 * Licensed under the GNU Lesser General Public License Version 2.1
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * SECTION:cd-client
24 * @short_description: Main client object for accessing the colord daemon
25 *
26 * A helper GObject to use for accessing colord information, and to be notified
27 * when it is changed.
28 *
29 * See also: #CdDevice
30 */
31
32 #include "config.h"
33
34 #include <fcntl.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <sys/stat.h>
38 #include <sys/types.h>
39
40 #include <gio/gio.h>
41 #ifdef __unix__
42 #include <gio/gunixfdlist.h>
43 #endif
44 #include <glib/gstdio.h>
45 #include <glib.h>
46
47 #include "cd-enum.h"
48 #include "cd-client.h"
49 #include "cd-client-sync.h"
50 #include "cd-device.h"
51 #include "cd-device-sync.h"
52 #include "cd-sensor.h"
53 #include "cd-profile-sync.h"
54
55 static void cd_client_class_init (CdClientClass *klass);
56 static void cd_client_init (CdClient *client);
57 static void cd_client_finalize (GObject *object);
58
59 #define GET_PRIVATE(o) (cd_client_get_instance_private (o))
60
61 #define CD_CLIENT_MESSAGE_TIMEOUT 15000 /* ms */
62 #define CD_CLIENT_IMPORT_DAEMON_TIMEOUT 5000 /* ms */
63 #define COLORD_DBUS_SERVICE "org.freedesktop.ColorManager"
64 #define COLORD_DBUS_PATH "/org/freedesktop/ColorManager"
65 #define COLORD_DBUS_INTERFACE "org.freedesktop.ColorManager"
66
67 /**
68 * CdClientPrivate:
69 *
70 * Private #CdClient data
71 **/
72 typedef struct
73 {
74 GDBusProxy *proxy;
75 gchar *daemon_version;
76 gchar *system_vendor;
77 gchar *system_model;
78 } CdClientPrivate;
79
80 enum {
81 SIGNAL_CHANGED,
82 SIGNAL_DEVICE_ADDED,
83 SIGNAL_DEVICE_REMOVED,
84 SIGNAL_DEVICE_CHANGED,
85 SIGNAL_PROFILE_ADDED,
86 SIGNAL_PROFILE_REMOVED,
87 SIGNAL_PROFILE_CHANGED,
88 SIGNAL_SENSOR_ADDED,
89 SIGNAL_SENSOR_REMOVED,
90 SIGNAL_SENSOR_CHANGED,
91 SIGNAL_LAST
92 };
93
94 enum {
95 PROP_0,
96 PROP_DAEMON_VERSION,
97 PROP_CONNECTED,
98 PROP_SYSTEM_VENDOR,
99 PROP_SYSTEM_MODEL,
100 PROP_LAST
101 };
102
103 static guint signals [SIGNAL_LAST] = { 0 };
104 static gpointer cd_client_object = NULL;
105
G_DEFINE_TYPE_WITH_PRIVATE(CdClient,cd_client,G_TYPE_OBJECT)106 G_DEFINE_TYPE_WITH_PRIVATE (CdClient, cd_client, G_TYPE_OBJECT)
107
108 /**
109 * cd_client_error_quark:
110 *
111 * Return value: An error quark.
112 *
113 * Since: 0.1.0
114 **/
115 GQuark
116 cd_client_error_quark (void)
117 {
118 static GQuark quark = 0;
119 if (!quark) {
120 quark = g_quark_from_static_string ("cd_client_error");
121 g_dbus_error_register_error (quark,
122 CD_CLIENT_ERROR_INTERNAL,
123 COLORD_DBUS_SERVICE ".Failed");
124 g_dbus_error_register_error (quark,
125 CD_CLIENT_ERROR_ALREADY_EXISTS,
126 COLORD_DBUS_SERVICE ".AlreadyExists");
127 }
128 return quark;
129 }
130
131 /**
132 * cd_client_get_daemon_version:
133 * @client: a #CdClient instance.
134 *
135 * Get colord daemon version.
136 *
137 * Return value: string containing the daemon version, e.g. "0.1.0"
138 *
139 * Since: 0.1.0
140 **/
141 const gchar *
cd_client_get_daemon_version(CdClient * client)142 cd_client_get_daemon_version (CdClient *client)
143 {
144 CdClientPrivate *priv = GET_PRIVATE (client);
145 g_return_val_if_fail (CD_IS_CLIENT (client), NULL);
146 g_return_val_if_fail (priv->proxy != NULL, NULL);
147 return priv->daemon_version;
148 }
149
150 /**
151 * cd_client_get_system_vendor:
152 * @client: a #CdClient instance.
153 *
154 * Get system vendor.
155 *
156 * Return value: string containing the system vendor, e.g. "Lenovo"
157 *
158 * Since: 1.0.2
159 **/
160 const gchar *
cd_client_get_system_vendor(CdClient * client)161 cd_client_get_system_vendor (CdClient *client)
162 {
163 CdClientPrivate *priv = GET_PRIVATE (client);
164 g_return_val_if_fail (CD_IS_CLIENT (client), NULL);
165 g_return_val_if_fail (priv->proxy != NULL, NULL);
166 return priv->system_vendor;
167 }
168
169 /**
170 * cd_client_get_system_model:
171 * @client: a #CdClient instance.
172 *
173 * Get system model.
174 *
175 * Return value: string containing the system model, e.g. "T61"
176 *
177 * Since: 1.0.2
178 **/
179 const gchar *
cd_client_get_system_model(CdClient * client)180 cd_client_get_system_model (CdClient *client)
181 {
182 CdClientPrivate *priv = GET_PRIVATE (client);
183 g_return_val_if_fail (CD_IS_CLIENT (client), NULL);
184 g_return_val_if_fail (priv->proxy != NULL, NULL);
185 return priv->system_model;
186 }
187
188 /**
189 * cd_client_get_connected:
190 * @client: a #CdClient instance.
191 *
192 * Gets if the client has been connected.
193 *
194 * Return value: %TRUE if properties are valid
195 *
196 * Since: 0.1.9
197 **/
198 gboolean
cd_client_get_connected(CdClient * client)199 cd_client_get_connected (CdClient *client)
200 {
201 CdClientPrivate *priv = GET_PRIVATE (client);
202 g_return_val_if_fail (CD_IS_CLIENT (client), FALSE);
203 return priv->proxy != NULL;
204 }
205
206 /**
207 * cd_client_get_has_server:
208 * @client: a #CdClient instance.
209 *
210 * Gets if the colord server is currently running.
211 * WARNING: This function may block for up to 5 seconds waiting for the daemon
212 * to start if it is not already running.
213 *
214 * Return value: %TRUE if the colord process is running
215 *
216 * Since: 0.1.12
217 **/
218 gboolean
cd_client_get_has_server(CdClient * client)219 cd_client_get_has_server (CdClient *client)
220 {
221 g_autofree gchar *name_owner = NULL;
222 g_autoptr(GDBusProxy) proxy = NULL;
223
224 g_return_val_if_fail (CD_IS_CLIENT (client), FALSE);
225
226 /* get name owner */
227 proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
228 G_DBUS_PROXY_FLAGS_NONE,
229 NULL,
230 COLORD_DBUS_SERVICE,
231 COLORD_DBUS_PATH,
232 COLORD_DBUS_INTERFACE,
233 NULL,
234 NULL);
235 if (proxy == NULL)
236 return FALSE;
237 name_owner = g_dbus_proxy_get_name_owner (proxy);
238 if (name_owner == NULL)
239 return FALSE;
240
241 /* just assume it's ready for use */
242 return TRUE;
243 }
244
245 /**********************************************************************/
246
247 /**
248 * cd_client_dbus_signal_cb:
249 **/
250 static void
cd_client_dbus_signal_cb(GDBusProxy * proxy,gchar * sender_name,gchar * signal_name,GVariant * parameters,CdClient * client)251 cd_client_dbus_signal_cb (GDBusProxy *proxy,
252 gchar *sender_name,
253 gchar *signal_name,
254 GVariant *parameters,
255 CdClient *client)
256 {
257 g_autofree gchar *object_path_tmp = NULL;
258 g_autoptr(CdDevice) device = NULL;
259 g_autoptr(CdProfile) profile = NULL;
260 g_autoptr(CdSensor) sensor = NULL;
261
262 if (g_strcmp0 (signal_name, "Changed") == 0) {
263 g_warning ("changed");
264 } else if (g_strcmp0 (signal_name, "DeviceAdded") == 0) {
265 g_variant_get (parameters, "(o)", &object_path_tmp);
266 device = cd_device_new_with_object_path (object_path_tmp);
267 g_signal_emit (client, signals[SIGNAL_DEVICE_ADDED], 0,
268 device);
269 } else if (g_strcmp0 (signal_name, "DeviceRemoved") == 0) {
270 g_variant_get (parameters, "(o)", &object_path_tmp);
271 device = cd_device_new_with_object_path (object_path_tmp);
272 g_signal_emit (client, signals[SIGNAL_DEVICE_REMOVED], 0,
273 device);
274 } else if (g_strcmp0 (signal_name, "DeviceChanged") == 0) {
275 g_variant_get (parameters, "(o)", &object_path_tmp);
276 device = cd_device_new_with_object_path (object_path_tmp);
277 g_signal_emit (client, signals[SIGNAL_DEVICE_CHANGED], 0,
278 device);
279 } else if (g_strcmp0 (signal_name, "ProfileAdded") == 0) {
280 g_variant_get (parameters, "(o)", &object_path_tmp);
281 profile = cd_profile_new_with_object_path (object_path_tmp);
282 g_signal_emit (client, signals[SIGNAL_PROFILE_ADDED], 0,
283 profile);
284 } else if (g_strcmp0 (signal_name, "ProfileRemoved") == 0) {
285 g_variant_get (parameters, "(o)", &object_path_tmp);
286 profile = cd_profile_new_with_object_path (object_path_tmp);
287 g_signal_emit (client, signals[SIGNAL_PROFILE_REMOVED], 0,
288 profile);
289 } else if (g_strcmp0 (signal_name, "ProfileChanged") == 0) {
290 g_variant_get (parameters, "(o)", &object_path_tmp);
291 profile = cd_profile_new_with_object_path (object_path_tmp);
292 g_signal_emit (client, signals[SIGNAL_PROFILE_CHANGED], 0,
293 profile);
294 } else if (g_strcmp0 (signal_name, "SensorAdded") == 0) {
295 g_variant_get (parameters, "(o)", &object_path_tmp);
296 sensor = cd_sensor_new_with_object_path (object_path_tmp);
297 g_signal_emit (client, signals[SIGNAL_SENSOR_ADDED], 0,
298 sensor);
299 } else if (g_strcmp0 (signal_name, "SensorRemoved") == 0) {
300 g_variant_get (parameters, "(o)", &object_path_tmp);
301 sensor = cd_sensor_new_with_object_path (object_path_tmp);
302 g_signal_emit (client, signals[SIGNAL_SENSOR_REMOVED], 0,
303 sensor);
304 } else if (g_strcmp0 (signal_name, "SensorChanged") == 0) {
305 g_variant_get (parameters, "(o)", &object_path_tmp);
306 sensor = cd_sensor_new_with_object_path (object_path_tmp);
307 g_signal_emit (client, signals[SIGNAL_SENSOR_CHANGED], 0,
308 sensor);
309 } else {
310 g_warning ("unhandled signal '%s'", signal_name);
311 }
312 }
313
314 /**
315 * cd_client_owner_notify_cb:
316 **/
317 static void
cd_client_owner_notify_cb(GObject * object,GParamSpec * pspec,CdClient * client)318 cd_client_owner_notify_cb (GObject *object,
319 GParamSpec *pspec,
320 CdClient *client)
321 {
322 /* daemon has quit, clearing caches */
323 }
324
325 /**********************************************************************/
326
327 /**
328 * cd_client_connect_finish:
329 * @client: a #CdClient instance.
330 * @res: the #GAsyncResult
331 * @error: A #GError or %NULL
332 *
333 * Gets the result from the asynchronous function.
334 *
335 * Return value: success
336 *
337 * Since: 0.1.6
338 **/
339 gboolean
cd_client_connect_finish(CdClient * client,GAsyncResult * res,GError ** error)340 cd_client_connect_finish (CdClient *client,
341 GAsyncResult *res,
342 GError **error)
343 {
344 g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
345 return g_task_propagate_boolean (G_TASK (res), error);
346 }
347
348 static void
cd_client_connect_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)349 cd_client_connect_cb (GObject *source_object,
350 GAsyncResult *res,
351 gpointer user_data)
352 {
353 g_autoptr(GError) error = NULL;
354 g_autoptr(GTask) task = G_TASK (user_data);
355 g_autoptr(GVariant) daemon_version = NULL;
356 g_autoptr(GVariant) system_model = NULL;
357 g_autoptr(GVariant) system_vendor = NULL;
358 CdClient *client = CD_CLIENT (g_task_get_source_object (task));
359 CdClientPrivate *priv = GET_PRIVATE (client);
360
361 /* get result */
362 priv->proxy = g_dbus_proxy_new_for_bus_finish (res, &error);
363 if (priv->proxy == NULL) {
364 g_task_return_new_error (task,
365 CD_CLIENT_ERROR,
366 CD_CLIENT_ERROR_INTERNAL,
367 "%s",
368 error->message);
369 return;
370 }
371
372 /* get daemon version */
373 daemon_version = g_dbus_proxy_get_cached_property (priv->proxy,
374 CD_CLIENT_PROPERTY_DAEMON_VERSION);
375 if (daemon_version != NULL) {
376 g_free (priv->daemon_version);
377 priv->daemon_version = g_variant_dup_string (daemon_version, NULL);
378 }
379
380 /* get system info */
381 system_vendor = g_dbus_proxy_get_cached_property (priv->proxy,
382 CD_CLIENT_PROPERTY_SYSTEM_VENDOR);
383 if (system_vendor != NULL) {
384 g_free (priv->system_vendor);
385 priv->system_vendor = g_variant_dup_string (system_vendor, NULL);
386 }
387
388 /* get system model */
389 system_model = g_dbus_proxy_get_cached_property (priv->proxy,
390 CD_CLIENT_PROPERTY_SYSTEM_MODEL);
391 if (system_model != NULL) {
392 g_free (priv->system_model);
393 priv->system_model = g_variant_dup_string (system_model, NULL);
394 }
395
396 /* get signals from DBus */
397 g_signal_connect_object (priv->proxy,
398 "g-signal",
399 G_CALLBACK (cd_client_dbus_signal_cb),
400 client, 0);
401
402 /* watch to see if it's fallen off the bus */
403 g_signal_connect_object (priv->proxy,
404 "notify::g-name-owner",
405 G_CALLBACK (cd_client_owner_notify_cb),
406 client, 0);
407
408 /* success */
409 g_task_return_boolean (task, TRUE);
410 }
411
412 /**
413 * cd_client_connect:
414 * @client: a #CdClient instance
415 * @cancellable: a #GCancellable or %NULL
416 * @callback: the function to run on completion
417 * @user_data: the data to pass to @callback
418 *
419 * Connects to the colord daemon.
420 *
421 * Since: 0.1.6
422 **/
423 void
cd_client_connect(CdClient * client,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)424 cd_client_connect (CdClient *client,
425 GCancellable *cancellable,
426 GAsyncReadyCallback callback,
427 gpointer user_data)
428 {
429 CdClientPrivate *priv = GET_PRIVATE (client);
430 GTask *task = NULL;
431
432 g_return_if_fail (CD_IS_CLIENT (client));
433 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
434
435 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
436
437 /* already connected */
438 if (priv->proxy != NULL) {
439 g_task_return_boolean (task, TRUE);
440 g_object_unref (task);
441 return;
442 }
443
444 /* connect async */
445 g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
446 G_DBUS_PROXY_FLAGS_NONE,
447 NULL,
448 COLORD_DBUS_SERVICE,
449 COLORD_DBUS_PATH,
450 COLORD_DBUS_INTERFACE,
451 cancellable,
452 cd_client_connect_cb,
453 task);
454 }
455
456 /**********************************************************************/
457
458 /**
459 * cd_client_create_device_finish:
460 * @client: a #CdClient instance.
461 * @res: the #GAsyncResult
462 * @error: A #GError or %NULL
463 *
464 * Gets the result from the asynchronous function.
465 *
466 * Return value: (transfer full): a #CdDevice or %NULL
467 *
468 * Since: 0.1.8
469 **/
470 CdDevice *
cd_client_create_device_finish(CdClient * client,GAsyncResult * res,GError ** error)471 cd_client_create_device_finish (CdClient *client,
472 GAsyncResult *res,
473 GError **error)
474 {
475 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
476 return g_task_propagate_pointer (G_TASK (res), error);
477 }
478
479 /**
480 * cd_client_fixup_dbus_error:
481 **/
482 static void
cd_client_fixup_dbus_error(GError * error)483 cd_client_fixup_dbus_error (GError *error)
484 {
485 g_autofree gchar *name = NULL;
486
487 g_return_if_fail (error != NULL);
488
489 /* is a remote error? */
490 if (!g_dbus_error_is_remote_error (error))
491 return;
492
493 /* parse the remote error */
494 name = g_dbus_error_get_remote_error (error);
495 error->domain = CD_CLIENT_ERROR;
496 error->code = cd_client_error_from_string (name);
497 g_dbus_error_strip_remote_error (error);
498 }
499
500 static void
cd_client_create_device_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)501 cd_client_create_device_cb (GObject *source_object,
502 GAsyncResult *res,
503 gpointer user_data)
504 {
505 CdDevice *device;
506 g_autoptr(GError) error = NULL;
507 g_autofree gchar *object_path = NULL;
508 g_autoptr(GTask) task = G_TASK (user_data);
509 g_autoptr(GVariant) result = NULL;
510
511 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
512 res,
513 &error);
514 if (result == NULL) {
515 cd_client_fixup_dbus_error (error);
516 g_task_return_error (task, error);
517 error = NULL;
518 return;
519 }
520
521 /* create CdDevice object */
522 g_variant_get (result, "(o)", &object_path);
523 device = cd_device_new ();
524 cd_device_set_object_path (device, object_path);
525
526 /* success */
527 g_task_return_pointer (task, device, (GDestroyNotify) g_object_unref);
528 }
529
530 /**
531 * cd_client_create_device:
532 * @client: a #CdClient instance.
533 * @id: identifier for the device
534 * @scope: the scope of the device
535 * @properties: (element-type utf8 utf8) (allow-none): properties to
536 * set on the device, or %NULL
537 * @cancellable: a #GCancellable, or %NULL
538 * @callback: the function to run on completion
539 * @user_data: the data to pass to @callback
540 *
541 * Creates a color device.
542 *
543 * Since: 0.1.8
544 **/
545 void
cd_client_create_device(CdClient * client,const gchar * id,CdObjectScope scope,GHashTable * properties,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)546 cd_client_create_device (CdClient *client,
547 const gchar *id,
548 CdObjectScope scope,
549 GHashTable *properties,
550 GCancellable *cancellable,
551 GAsyncReadyCallback callback,
552 gpointer user_data)
553 {
554 CdClientPrivate *priv = GET_PRIVATE (client);
555 const gchar *value;
556 GTask *task = NULL;
557 GVariantBuilder builder;
558 GList *list, *l;
559
560 g_return_if_fail (CD_IS_CLIENT (client));
561 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
562 g_return_if_fail (priv->proxy != NULL);
563
564 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
565
566 /* add properties */
567 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
568 if (properties != NULL) {
569 list = g_hash_table_get_keys (properties);
570 for (l = list; l != NULL; l = l->next) {
571 value = g_hash_table_lookup (properties, l->data);
572 g_variant_builder_add (&builder,
573 "{ss}",
574 l->data,
575 value != NULL ? value : "");
576 }
577 g_list_free (list);
578 } else {
579 /* just fake something here */
580 g_variant_builder_add (&builder,
581 "{ss}",
582 CD_DEVICE_PROPERTY_KIND,
583 "unknown");
584 }
585
586 g_dbus_proxy_call (priv->proxy,
587 "CreateDevice",
588 g_variant_new ("(ssa{ss})",
589 id,
590 cd_object_scope_to_string (scope),
591 &builder),
592 G_DBUS_CALL_FLAGS_NONE,
593 -1,
594 cancellable,
595 cd_client_create_device_cb,
596 task);
597 }
598
599 /**********************************************************************/
600
601 /**
602 * cd_client_create_profile_finish:
603 * @client: a #CdClient instance.
604 * @res: the #GAsyncResult
605 * @error: A #GError or %NULL
606 *
607 * Gets the result from the asynchronous function.
608 *
609 * Return value: (transfer full): a #CdProfile or %NULL
610 *
611 * Since: 0.1.8
612 **/
613 CdProfile *
cd_client_create_profile_finish(CdClient * client,GAsyncResult * res,GError ** error)614 cd_client_create_profile_finish (CdClient *client,
615 GAsyncResult *res,
616 GError **error)
617 {
618 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
619 return g_task_propagate_pointer (G_TASK (res), error);
620 }
621
622 static void
cd_client_create_profile_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)623 cd_client_create_profile_cb (GObject *source_object,
624 GAsyncResult *res,
625 gpointer user_data)
626 {
627 CdProfile *profile;
628 g_autoptr(GError) error = NULL;
629 g_autofree gchar *object_path = NULL;
630 g_autoptr(GDBusMessage) reply = NULL;
631 g_autoptr(GTask) task = G_TASK (user_data);
632
633 reply = g_dbus_connection_send_message_with_reply_finish (G_DBUS_CONNECTION (source_object),
634 res,
635 &error);
636 if (reply == NULL) {
637 cd_client_fixup_dbus_error (error);
638 g_task_return_error (task, error);
639 error = NULL;
640 return;
641 }
642
643 /* this is an error message */
644 if (g_dbus_message_get_message_type (reply) == G_DBUS_MESSAGE_TYPE_ERROR) {
645 g_dbus_message_to_gerror (reply, &error);
646 cd_client_fixup_dbus_error (error);
647 g_task_return_error (task, error);
648 error = NULL;
649 return;
650 }
651
652 /* create thick CdDevice object */
653 g_variant_get (g_dbus_message_get_body (reply), "(o)",
654 &object_path);
655 profile = cd_profile_new ();
656 cd_profile_set_object_path (profile, object_path);
657
658 /* success */
659 g_task_return_pointer (task, profile, (GDestroyNotify) g_object_unref);
660 }
661
662 /**
663 * cd_client_create_profile:
664 * @client: a #CdClient instance.
665 * @id: identifier for the profile
666 * @scope: the scope of the profile
667 * @properties: (element-type utf8 utf8) (allow-none): properties to
668 * set on the profile, or %NULL
669 * @cancellable: a #GCancellable, or %NULL
670 * @callback: the function to run on completion
671 * @user_data: the data to pass to @callback
672 *
673 * Creates a color profile.
674 *
675 * Since: 0.1.8
676 **/
677 void
cd_client_create_profile(CdClient * client,const gchar * id,CdObjectScope scope,GHashTable * properties,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)678 cd_client_create_profile (CdClient *client,
679 const gchar *id,
680 CdObjectScope scope,
681 GHashTable *properties,
682 GCancellable *cancellable,
683 GAsyncReadyCallback callback,
684 gpointer user_data)
685 {
686 CdClientPrivate *priv = GET_PRIVATE (client);
687 GDBusConnection *connection;
688 gint fd = -1;
689 GList *list, *l;
690 GVariant *body;
691 GVariantBuilder builder;
692 GTask *task = NULL;
693 g_autoptr(GDBusMessage) request = NULL;
694 g_autoptr(GUnixFDList) fd_list = NULL;
695
696 g_return_if_fail (CD_IS_CLIENT (client));
697 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
698 g_return_if_fail (priv->proxy != NULL);
699 g_return_if_fail (id != NULL);
700
701 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
702
703 /* add properties */
704 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
705 if (properties != NULL &&
706 g_hash_table_size (properties) > 0) {
707 list = g_hash_table_get_keys (properties);
708 for (l = list; l != NULL; l = l->next) {
709 g_variant_builder_add (&builder,
710 "{ss}",
711 l->data,
712 g_hash_table_lookup (properties,
713 l->data));
714 }
715 g_list_free (list);
716 } else {
717 /* just fake something here */
718 g_variant_builder_add (&builder,
719 "{ss}",
720 CD_PROFILE_PROPERTY_QUALIFIER,
721 "");
722 }
723
724 /* do low level call */
725 request = g_dbus_message_new_method_call (COLORD_DBUS_SERVICE,
726 COLORD_DBUS_PATH,
727 COLORD_DBUS_INTERFACE,
728 "CreateProfileWithFd");
729
730 /* get fd if possible top avoid open() in daemon */
731 #ifdef __unix__
732 if (properties != NULL) {
733 const gchar *filename;
734 filename = g_hash_table_lookup (properties,
735 CD_PROFILE_PROPERTY_FILENAME);
736 if (filename != NULL) {
737 gint retval;
738 fd = open (filename, O_RDONLY);
739 if (fd < 0) {
740 g_task_return_new_error (task,
741 CD_CLIENT_ERROR,
742 CD_CLIENT_ERROR_INTERNAL,
743 "Failed to open %s",
744 filename);
745 return;
746 }
747
748 /* set out of band file descriptor */
749 fd_list = g_unix_fd_list_new ();
750 retval = g_unix_fd_list_append (fd_list, fd, NULL);
751 g_assert (retval != -1);
752 g_dbus_message_set_unix_fd_list (request, fd_list);
753
754 /* g_unix_fd_list_append did a dup() already */
755 close (fd);
756 }
757 }
758 #endif
759
760 /* set parameters */
761 body = g_variant_new ("(ssha{ss})",
762 id,
763 cd_object_scope_to_string (scope),
764 fd > -1 ? 0 : -1,
765 &builder);
766 g_dbus_message_set_body (request, body);
767
768 /* send sync message to the bus */
769 connection = g_dbus_proxy_get_connection (priv->proxy);
770 g_dbus_connection_send_message_with_reply (connection,
771 request,
772 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
773 CD_CLIENT_MESSAGE_TIMEOUT,
774 NULL,
775 cancellable,
776 cd_client_create_profile_cb,
777 task);
778 }
779
780 /**********************************************************************/
781 /**
782 * cd_client_create_profile_for_icc:
783 * @client: a #CdClient instance.
784 * @icc: #CdIcc object
785 * @scope: the scope of the profile
786 * @cancellable: a #GCancellable, or %NULL
787 * @callback: the function to run on completion
788 * @user_data: the data to pass to @callback
789 *
790 * Creates a color profile for an #CdIcc Object.
791 *
792 * Since: 1.1.1
793 **/
794 void
cd_client_create_profile_for_icc(CdClient * client,CdIcc * icc,CdObjectScope scope,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)795 cd_client_create_profile_for_icc (CdClient *client,
796 CdIcc *icc,
797 CdObjectScope scope,
798 GCancellable *cancellable,
799 GAsyncReadyCallback callback,
800 gpointer user_data)
801 {
802 const gchar *checksum;
803 const gchar *filename;
804 g_autofree gchar *profile_id = NULL;
805 g_autoptr(GHashTable) profile_props = NULL;
806
807 g_return_if_fail (CD_IS_CLIENT (client));
808 g_return_if_fail (CD_IS_ICC (icc));
809 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
810
811 /* generate ID */
812 checksum = cd_icc_get_checksum (icc);
813 filename = cd_icc_get_filename (icc);
814 profile_id = g_strdup_printf ("icc-%s", checksum);
815 profile_props = g_hash_table_new_full (g_str_hash, g_str_equal,
816 NULL, NULL);
817 g_hash_table_insert (profile_props,
818 (gpointer) CD_PROFILE_PROPERTY_FILENAME,
819 (gpointer) filename);
820 g_hash_table_insert (profile_props,
821 (gpointer) CD_PROFILE_METADATA_FILE_CHECKSUM,
822 (gpointer) checksum);
823 cd_client_create_profile (client,
824 profile_id,
825 scope,
826 profile_props,
827 NULL,
828 callback,
829 user_data);
830 }
831
832
833 /**
834 * cd_client_create_profile_for_icc_finish:
835 * @client: a #CdClient instance.
836 * @res: the #GAsyncResult
837 * @error: A #GError or %NULL
838 *
839 * Gets the result from the asynchronous function.
840 *
841 * Return value: (transfer full): a #CdProfile or %NULL
842 *
843 * Since: 1.1.1
844 **/
845 CdProfile *
cd_client_create_profile_for_icc_finish(CdClient * client,GAsyncResult * res,GError ** error)846 cd_client_create_profile_for_icc_finish (CdClient *client,
847 GAsyncResult *res,
848 GError **error)
849 {
850 return cd_client_create_profile_finish (client, res, error);
851 }
852
853 /**********************************************************************/
854
855 /**
856 * cd_client_import_get_profile_destination:
857 **/
858 static GFile *
cd_client_import_get_profile_destination(GFile * file)859 cd_client_import_get_profile_destination (GFile *file)
860 {
861 g_autofree gchar *basename = NULL;
862 g_autofree gchar *destination = NULL;
863
864 g_return_val_if_fail (file != NULL, NULL);
865
866 /* get destination filename for this source file */
867 basename = g_file_get_basename (file);
868 destination = g_build_filename (g_get_user_data_dir (), "icc", basename, NULL);
869 return g_file_new_for_path (destination);
870 }
871
872 /**
873 * cd_client_import_mkdir_and_copy:
874 **/
875 static gboolean
cd_client_import_mkdir_and_copy(GFile * source,GFile * destination,GCancellable * cancellable,GError ** error)876 cd_client_import_mkdir_and_copy (GFile *source,
877 GFile *destination,
878 GCancellable *cancellable,
879 GError **error)
880 {
881 g_autoptr(GFile) parent = NULL;
882
883 g_return_val_if_fail (source != NULL, FALSE);
884 g_return_val_if_fail (destination != NULL, FALSE);
885
886 /* get parent */
887 parent = g_file_get_parent (destination);
888
889 /* create directory */
890 if (!g_file_query_exists (parent, cancellable)) {
891 if (!g_file_make_directory_with_parents (parent, cancellable, error))
892 return FALSE;
893 }
894
895 /* do the copy */
896 return g_file_copy (source, destination,
897 G_FILE_COPY_OVERWRITE,
898 cancellable, NULL, NULL, error);
899 }
900
901 typedef struct {
902 GFile *dest;
903 GFile *file;
904 guint hangcheck_id;
905 guint profile_added_id;
906 } CdClientImportTaskData;
907
908 /**
909 * cd_client_import_profile_finish:
910 * @client: a #CdClient instance.
911 * @res: the #GAsyncResult
912 * @error: A #GError or %NULL
913 *
914 * Gets the result from the asynchronous function.
915 *
916 * Return value: (transfer full): a #CdProfile or %NULL
917 *
918 * Since: 0.1.12
919 **/
920 CdProfile *
cd_client_import_profile_finish(CdClient * client,GAsyncResult * res,GError ** error)921 cd_client_import_profile_finish (CdClient *client,
922 GAsyncResult *res,
923 GError **error)
924 {
925 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
926 return g_task_propagate_pointer (G_TASK (res), error);
927 }
928
929 static void
cd_client_import_task_data_free(CdClientImportTaskData * tdata)930 cd_client_import_task_data_free (CdClientImportTaskData *tdata)
931 {
932 g_object_unref (tdata->file);
933 g_object_unref (tdata->dest);
934 // if (tdata->profile_added_id > 0)
935 // g_signal_handler_disconnect (tdata->client, tdata->profile_added_id);
936 if (tdata->hangcheck_id > 0)
937 g_source_remove (tdata->hangcheck_id);
938 g_free (tdata);
939 }
940
941 static void
cd_client_import_profile_added_cb(CdClient * client,CdProfile * profile,gpointer user_data)942 cd_client_import_profile_added_cb (CdClient *client,
943 CdProfile *profile,
944 gpointer user_data)
945 {
946 GTask *task = G_TASK (user_data);
947 g_task_return_pointer (task, g_object_ref (profile), (GDestroyNotify) g_object_unref);
948 g_object_unref (task);
949 }
950
951 static gboolean
cd_client_import_hangcheck_cb(gpointer user_data)952 cd_client_import_hangcheck_cb (gpointer user_data)
953 {
954 GTask *task = G_TASK (user_data);
955 CdClientImportTaskData *tdata = g_task_get_task_data (task);
956 g_task_return_new_error (task,
957 CD_CLIENT_ERROR,
958 CD_CLIENT_ERROR_INTERNAL,
959 "The profile was not added in time");
960 tdata->hangcheck_id = 0;
961 g_object_unref (task);
962 return G_SOURCE_REMOVE;
963 }
964
965 static void
cd_client_import_profile_find_filename_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)966 cd_client_import_profile_find_filename_cb (GObject *source_object,
967 GAsyncResult *res,
968 gpointer user_data)
969 {
970 GTask *task = G_TASK (user_data);
971 CdClient *client = CD_CLIENT (source_object);
972 CdClientImportTaskData *tdata = g_task_get_task_data (task);
973 gboolean ret;
974 g_autoptr(GError) error = NULL;
975 g_autoptr(CdProfile) profile = NULL;
976
977 /* does the profile already exist */
978 profile = cd_client_find_profile_by_filename_finish (client, res, &error);
979 if (profile != NULL) {
980 g_autofree gchar *filename = NULL;
981 filename = g_file_get_path (tdata->dest);
982 g_task_return_new_error (task,
983 CD_CLIENT_ERROR,
984 CD_CLIENT_ERROR_ALREADY_EXISTS,
985 "The profile %s already exists",
986 filename);
987 g_object_unref (task);
988 return;
989 }
990 if (!g_error_matches (error,
991 CD_CLIENT_ERROR,
992 CD_CLIENT_ERROR_NOT_FOUND)) {
993 cd_client_fixup_dbus_error (error);
994 g_task_return_error (task, error);
995 g_object_unref (task);
996 return;
997 }
998
999 /* reset the error */
1000 g_clear_error (&error);
1001
1002 /* watch for a new profile to be detected and added,
1003 * but time out after a couple of seconds */
1004 tdata->hangcheck_id = g_timeout_add (CD_CLIENT_IMPORT_DAEMON_TIMEOUT,
1005 cd_client_import_hangcheck_cb,
1006 task);
1007 tdata->profile_added_id = g_signal_connect (client, "profile-added",
1008 G_CALLBACK (cd_client_import_profile_added_cb),
1009 task);
1010
1011 /* copy profile to the correct place */
1012 ret = cd_client_import_mkdir_and_copy (tdata->file,
1013 tdata->dest,
1014 g_task_get_cancellable (task),
1015 &error);
1016 if (!ret) {
1017 g_task_return_new_error (task,
1018 CD_CLIENT_ERROR,
1019 CD_CLIENT_ERROR_INTERNAL,
1020 "Failed to copy: %s",
1021 error->message);
1022 g_object_unref (task);
1023 }
1024 }
1025
1026 static void
cd_client_import_profile_query_info_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1027 cd_client_import_profile_query_info_cb (GObject *source_object,
1028 GAsyncResult *res,
1029 gpointer user_data)
1030 {
1031 GTask *task = G_TASK (user_data);
1032 CdClient *client = CD_CLIENT (g_task_get_source_object (task));
1033 CdClientImportTaskData *tdata = g_task_get_task_data (task);
1034 const gchar *type;
1035 g_autoptr(GError) error = NULL;
1036 g_autofree gchar *filename = NULL;
1037 g_autoptr(GFileInfo) info = NULL;
1038
1039 /* get the file info */
1040 filename = g_file_get_path (tdata->dest);
1041 info = g_file_query_info_finish (G_FILE (source_object),
1042 res,
1043 &error);
1044 if (info == NULL) {
1045 g_task_return_new_error (task,
1046 CD_CLIENT_ERROR,
1047 CD_CLIENT_ERROR_INTERNAL,
1048 "Cannot get content type for %s: %s",
1049 filename,
1050 error->message);
1051 g_object_unref (task);
1052 return;
1053 }
1054
1055 /* check the content type */
1056 type = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE);
1057 if (g_strcmp0 (type, "application/vnd.iccprofile") != 0) {
1058 g_task_return_new_error (task,
1059 CD_CLIENT_ERROR,
1060 CD_CLIENT_ERROR_FILE_INVALID,
1061 "Incorrect content type for %s, got %s",
1062 filename, type);
1063 g_object_unref (task);
1064 return;
1065 }
1066
1067 /* does this profile already exist? */
1068 cd_client_find_profile_by_filename (client,
1069 filename,
1070 g_task_get_cancellable (task),
1071 cd_client_import_profile_find_filename_cb,
1072 task);
1073 }
1074
1075 /**
1076 * cd_client_import_profile:
1077 * @client: a #CdClient instance.
1078 * @file: a #GFile
1079 * @cancellable: a #GCancellable, or %NULL
1080 * @callback: the function to run on completion
1081 * @user_data: the data to pass to @callback
1082 *
1083 * Imports a color profile into the users home directory.
1084 *
1085 * If the profile should be accessable for all users, then call
1086 * cd_profile_install_system_wide() on the result.
1087 *
1088 * Since: 0.1.12
1089 **/
1090 void
cd_client_import_profile(CdClient * client,GFile * file,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1091 cd_client_import_profile (CdClient *client,
1092 GFile *file,
1093 GCancellable *cancellable,
1094 GAsyncReadyCallback callback,
1095 gpointer user_data)
1096 {
1097 CdClientImportTaskData *tdata;
1098 GTask *task;
1099
1100 g_return_if_fail (CD_IS_CLIENT (client));
1101 g_return_if_fail (G_IS_FILE (file));
1102 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1103
1104 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1105 tdata = g_new0 (CdClientImportTaskData, 1);
1106 tdata->file = g_object_ref (file);
1107 tdata->dest = cd_client_import_get_profile_destination (file);
1108 g_task_set_task_data (task, tdata, (GDestroyNotify) cd_client_import_task_data_free);
1109
1110 /* check the file really is an ICC file */
1111 g_file_query_info_async (tdata->file,
1112 G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
1113 G_FILE_QUERY_INFO_NONE,
1114 G_PRIORITY_DEFAULT,
1115 cancellable,
1116 cd_client_import_profile_query_info_cb,
1117 task);
1118 }
1119
1120 /**********************************************************************/
1121
1122 /**
1123 * cd_client_delete_device_finish:
1124 * @client: a #CdClient instance.
1125 * @res: the #GAsyncResult
1126 * @error: A #GError or %NULL
1127 *
1128 * Gets the result from the asynchronous function.
1129 *
1130 * Return value: success
1131 *
1132 * Since: 0.1.8
1133 **/
1134 gboolean
cd_client_delete_device_finish(CdClient * client,GAsyncResult * res,GError ** error)1135 cd_client_delete_device_finish (CdClient *client,
1136 GAsyncResult *res,
1137 GError **error)
1138 {
1139 g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
1140 return g_task_propagate_boolean (G_TASK (res), error);
1141 }
1142
1143 static void
cd_client_delete_device_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1144 cd_client_delete_device_cb (GObject *source_object,
1145 GAsyncResult *res,
1146 gpointer user_data)
1147 {
1148 g_autoptr(GError) error = NULL;
1149 g_autoptr(GTask) task = G_TASK (user_data);
1150 g_autoptr(GVariant) result = NULL;
1151
1152 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1153 res,
1154 &error);
1155 if (result == NULL) {
1156 cd_client_fixup_dbus_error (error);
1157 g_task_return_error (task, error);
1158 error = NULL;
1159 return;
1160 }
1161
1162 /* success */
1163 g_task_return_boolean (task, TRUE);
1164 }
1165
1166 /**
1167 * cd_client_delete_device:
1168 * @client: a #CdClient instance.
1169 * @device: a #CdDevice
1170 * @cancellable: a #GCancellable, or %NULL
1171 * @callback: the function to run on completion
1172 * @user_data: the data to pass to @callback
1173 *
1174 * Deletes a device.
1175 *
1176 * Since: 0.1.8
1177 **/
1178 void
cd_client_delete_device(CdClient * client,CdDevice * device,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1179 cd_client_delete_device (CdClient *client,
1180 CdDevice *device,
1181 GCancellable *cancellable,
1182 GAsyncReadyCallback callback,
1183 gpointer user_data)
1184 {
1185 CdClientPrivate *priv = GET_PRIVATE (client);
1186 GTask *task = NULL;
1187
1188 g_return_if_fail (CD_IS_CLIENT (client));
1189 g_return_if_fail (CD_IS_DEVICE (device));
1190 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1191 g_return_if_fail (priv->proxy != NULL);
1192
1193 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1194 g_dbus_proxy_call (priv->proxy,
1195 "DeleteDevice",
1196 g_variant_new ("(o)",
1197 cd_device_get_object_path (device)),
1198 G_DBUS_CALL_FLAGS_NONE,
1199 -1,
1200 cancellable,
1201 cd_client_delete_device_cb,
1202 task);
1203 }
1204
1205 /**********************************************************************/
1206
1207 /**
1208 * cd_client_delete_profile_finish:
1209 * @client: a #CdClient instance.
1210 * @res: the #GAsyncResult
1211 * @error: A #GError or %NULL
1212 *
1213 * Gets the result from the asynchronous function.
1214 *
1215 * Return value: success
1216 *
1217 * Since: 0.1.8
1218 **/
1219 gboolean
cd_client_delete_profile_finish(CdClient * client,GAsyncResult * res,GError ** error)1220 cd_client_delete_profile_finish (CdClient *client,
1221 GAsyncResult *res,
1222 GError **error)
1223 {
1224 g_return_val_if_fail (g_task_is_valid (res, client), FALSE);
1225 return g_task_propagate_boolean (G_TASK (res), error);
1226 }
1227
1228 static void
cd_client_delete_profile_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1229 cd_client_delete_profile_cb (GObject *source_object,
1230 GAsyncResult *res,
1231 gpointer user_data)
1232 {
1233 g_autoptr(GError) error = NULL;
1234 g_autoptr(GTask) task = G_TASK (user_data);
1235 g_autoptr(GVariant) result = NULL;
1236
1237 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1238 res,
1239 &error);
1240 if (result == NULL) {
1241 cd_client_fixup_dbus_error (error);
1242 g_task_return_error (task, error);
1243 error = NULL;
1244 return;
1245 }
1246
1247 /* success */
1248 g_task_return_boolean (task, TRUE);
1249 }
1250
1251 /**
1252 * cd_client_delete_profile:
1253 * @client: a #CdClient instance.
1254 * @profile: a #CdProfile
1255 * @cancellable: a #GCancellable, or %NULL
1256 * @callback: the function to run on completion
1257 * @user_data: the data to pass to @callback
1258 *
1259 * Deletes a profile.
1260 *
1261 * Since: 0.1.8
1262 **/
1263 void
cd_client_delete_profile(CdClient * client,CdProfile * profile,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1264 cd_client_delete_profile (CdClient *client,
1265 CdProfile *profile,
1266 GCancellable *cancellable,
1267 GAsyncReadyCallback callback,
1268 gpointer user_data)
1269 {
1270 CdClientPrivate *priv = GET_PRIVATE (client);
1271 GTask *task = NULL;
1272
1273 g_return_if_fail (CD_IS_CLIENT (client));
1274 g_return_if_fail (CD_IS_PROFILE (profile));
1275 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1276 g_return_if_fail (priv->proxy != NULL);
1277
1278 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1279 g_dbus_proxy_call (priv->proxy,
1280 "DeleteProfile",
1281 g_variant_new ("(o)",
1282 cd_profile_get_object_path (profile)),
1283 G_DBUS_CALL_FLAGS_NONE,
1284 -1,
1285 cancellable,
1286 cd_client_delete_profile_cb,
1287 task);
1288 }
1289
1290 /**********************************************************************/
1291
1292 /**
1293 * cd_client_find_device_finish:
1294 * @client: a #CdClient instance.
1295 * @res: the #GAsyncResult
1296 * @error: A #GError or %NULL
1297 *
1298 * Gets the result from the asynchronous function.
1299 *
1300 * Return value: (transfer full): a #CdDevice or %NULL
1301 *
1302 * Since: 0.1.8
1303 **/
1304 CdDevice *
cd_client_find_device_finish(CdClient * client,GAsyncResult * res,GError ** error)1305 cd_client_find_device_finish (CdClient *client,
1306 GAsyncResult *res,
1307 GError **error)
1308 {
1309 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
1310 return g_task_propagate_pointer (G_TASK (res), error);
1311 }
1312
1313 static void
cd_client_find_device_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1314 cd_client_find_device_cb (GObject *source_object,
1315 GAsyncResult *res,
1316 gpointer user_data)
1317 {
1318 CdDevice *device;
1319 g_autoptr(GError) error = NULL;
1320 g_autofree gchar *object_path = NULL;
1321 g_autoptr(GTask) task = G_TASK (user_data);
1322 g_autoptr(GVariant) result = NULL;
1323
1324 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1325 res,
1326 &error);
1327 if (result == NULL) {
1328 cd_client_fixup_dbus_error (error);
1329 g_task_return_error (task, error);
1330 error = NULL;
1331 return;
1332 }
1333
1334 /* create a device object */
1335 g_variant_get (result, "(o)", &object_path);
1336 device = cd_device_new ();
1337 cd_device_set_object_path (device, object_path);
1338
1339 /* success */
1340 g_task_return_pointer (task, device, (GDestroyNotify) g_object_unref);
1341 }
1342
1343 /**
1344 * cd_client_find_device:
1345 * @client: a #CdClient instance.
1346 * @id: a device id
1347 * @cancellable: a #GCancellable, or %NULL
1348 * @callback: the function to run on completion
1349 * @user_data: the data to pass to @callback
1350 *
1351 * Finds a device by an ID.
1352 *
1353 * Since: 0.1.8
1354 **/
1355 void
cd_client_find_device(CdClient * client,const gchar * id,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1356 cd_client_find_device (CdClient *client,
1357 const gchar *id,
1358 GCancellable *cancellable,
1359 GAsyncReadyCallback callback,
1360 gpointer user_data)
1361 {
1362 CdClientPrivate *priv = GET_PRIVATE (client);
1363 GTask *task = NULL;
1364
1365 g_return_if_fail (CD_IS_CLIENT (client));
1366 g_return_if_fail (id != NULL);
1367 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1368 g_return_if_fail (priv->proxy != NULL);
1369
1370 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1371 g_dbus_proxy_call (priv->proxy,
1372 "FindDeviceById",
1373 g_variant_new ("(s)", id),
1374 G_DBUS_CALL_FLAGS_NONE,
1375 -1,
1376 cancellable,
1377 cd_client_find_device_cb,
1378 task);
1379 }
1380
1381 /**********************************************************************/
1382
1383 /**
1384 * cd_client_find_device_by_property_finish:
1385 * @client: a #CdClient instance.
1386 * @res: the #GAsyncResult
1387 * @error: A #GError or %NULL
1388 *
1389 * Gets the result from the asynchronous function.
1390 *
1391 * Return value: (transfer full): a #CdDevice or %NULL
1392 *
1393 * Since: 0.1.8
1394 **/
1395 CdDevice *
cd_client_find_device_by_property_finish(CdClient * client,GAsyncResult * res,GError ** error)1396 cd_client_find_device_by_property_finish (CdClient *client,
1397 GAsyncResult *res,
1398 GError **error)
1399 {
1400 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
1401 return g_task_propagate_pointer (G_TASK (res), error);
1402 }
1403
1404 static void
cd_client_find_device_by_property_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1405 cd_client_find_device_by_property_cb (GObject *source_object,
1406 GAsyncResult *res,
1407 gpointer user_data)
1408 {
1409 CdDevice *device;
1410 g_autoptr(GError) error = NULL;
1411 g_autofree gchar *object_path = NULL;
1412 g_autoptr(GTask) task = G_TASK (user_data);
1413 g_autoptr(GVariant) result = NULL;
1414
1415 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1416 res,
1417 &error);
1418 if (result == NULL) {
1419 cd_client_fixup_dbus_error (error);
1420 g_task_return_error (task, error);
1421 error = NULL;
1422 return;
1423 }
1424
1425 /* create a device object */
1426 g_variant_get (result, "(o)", &object_path);
1427 device = cd_device_new ();
1428 cd_device_set_object_path (device, object_path);
1429
1430 /* success */
1431 g_task_return_pointer (task, device, (GDestroyNotify) g_object_unref);
1432 }
1433
1434 /**
1435 * cd_client_find_device_by_property:
1436 * @client: a #CdClient instance.
1437 * @key: the device property key
1438 * @value: the device property value
1439 * @cancellable: a #GCancellable, or %NULL
1440 * @callback: the function to run on completion
1441 * @user_data: the data to pass to @callback
1442 *
1443 * Finds a color device that has a property value.
1444 *
1445 * Since: 0.1.8
1446 **/
1447 void
cd_client_find_device_by_property(CdClient * client,const gchar * key,const gchar * value,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1448 cd_client_find_device_by_property (CdClient *client,
1449 const gchar *key,
1450 const gchar *value,
1451 GCancellable *cancellable,
1452 GAsyncReadyCallback callback,
1453 gpointer user_data)
1454 {
1455 CdClientPrivate *priv = GET_PRIVATE (client);
1456 GTask *task = NULL;
1457
1458 g_return_if_fail (CD_IS_CLIENT (client));
1459 g_return_if_fail (key != NULL);
1460 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1461 g_return_if_fail (priv->proxy != NULL);
1462
1463 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1464 g_dbus_proxy_call (priv->proxy,
1465 "FindDeviceByProperty",
1466 g_variant_new ("(ss)", key, value),
1467 G_DBUS_CALL_FLAGS_NONE,
1468 -1,
1469 cancellable,
1470 cd_client_find_device_by_property_cb,
1471 task);
1472 }
1473
1474 /**********************************************************************/
1475
1476 /**
1477 * cd_client_find_profile_finish:
1478 * @client: a #CdClient instance.
1479 * @res: the #GAsyncResult
1480 * @error: A #GError or %NULL
1481 *
1482 * Gets the result from the asynchronous function.
1483 *
1484 * Return value: (transfer full): a #CdProfile or %NULL
1485 *
1486 * Since: 0.1.8
1487 **/
1488 CdProfile *
cd_client_find_profile_finish(CdClient * client,GAsyncResult * res,GError ** error)1489 cd_client_find_profile_finish (CdClient *client,
1490 GAsyncResult *res,
1491 GError **error)
1492 {
1493 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
1494 return g_task_propagate_pointer (G_TASK (res), error);
1495 }
1496
1497 static void
cd_client_find_profile_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1498 cd_client_find_profile_cb (GObject *source_object,
1499 GAsyncResult *res,
1500 gpointer user_data)
1501 {
1502 CdProfile *profile;
1503 g_autoptr(GError) error = NULL;
1504 g_autofree gchar *object_path = NULL;
1505 g_autoptr(GTask) task = G_TASK (user_data);
1506 g_autoptr(GVariant) result = NULL;
1507
1508 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1509 res,
1510 &error);
1511 if (result == NULL) {
1512 cd_client_fixup_dbus_error (error);
1513 g_task_return_error (task, error);
1514 error = NULL;
1515 return;
1516 }
1517
1518 /* create a profile object */
1519 g_variant_get (result, "(o)", &object_path);
1520 profile = cd_profile_new ();
1521 cd_profile_set_object_path (profile, object_path);
1522
1523 /* success */
1524 g_task_return_pointer (task, profile, (GDestroyNotify) g_object_unref);
1525 }
1526
1527 /**
1528 * cd_client_find_profile:
1529 * @client: a #CdClient instance.
1530 * @id: a profile id
1531 * @cancellable: a #GCancellable, or %NULL
1532 * @callback: the function to run on completion
1533 * @user_data: the data to pass to @callback
1534 *
1535 * Finds a profile by an ID.
1536 *
1537 * Since: 0.1.8
1538 **/
1539 void
cd_client_find_profile(CdClient * client,const gchar * id,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1540 cd_client_find_profile (CdClient *client,
1541 const gchar *id,
1542 GCancellable *cancellable,
1543 GAsyncReadyCallback callback,
1544 gpointer user_data)
1545 {
1546 CdClientPrivate *priv = GET_PRIVATE (client);
1547 GTask *task = NULL;
1548
1549 g_return_if_fail (CD_IS_CLIENT (client));
1550 g_return_if_fail (id != NULL);
1551 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1552 g_return_if_fail (priv->proxy != NULL);
1553
1554 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1555 g_dbus_proxy_call (priv->proxy,
1556 "FindProfileById",
1557 g_variant_new ("(s)", id),
1558 G_DBUS_CALL_FLAGS_NONE,
1559 -1,
1560 cancellable,
1561 cd_client_find_profile_cb,
1562 task);
1563 }
1564
1565 /**********************************************************************/
1566
1567 /**
1568 * cd_client_find_profile_by_filename_finish:
1569 * @client: a #CdClient instance.
1570 * @res: the #GAsyncResult
1571 * @error: A #GError or %NULL
1572 *
1573 * Gets the result from the asynchronous function.
1574 *
1575 * Return value: (transfer full): a #CdProfile or %NULL
1576 *
1577 * Since: 0.1.8
1578 **/
1579 CdProfile *
cd_client_find_profile_by_filename_finish(CdClient * client,GAsyncResult * res,GError ** error)1580 cd_client_find_profile_by_filename_finish (CdClient *client,
1581 GAsyncResult *res,
1582 GError **error)
1583 {
1584 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
1585 return g_task_propagate_pointer (G_TASK (res), error);
1586 }
1587
1588 static void
cd_client_find_profile_by_filename_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1589 cd_client_find_profile_by_filename_cb (GObject *source_object,
1590 GAsyncResult *res,
1591 gpointer user_data)
1592 {
1593 CdProfile *profile;
1594 g_autoptr(GError) error = NULL;
1595 g_autofree gchar *object_path = NULL;
1596 g_autoptr(GTask) task = G_TASK (user_data);
1597 g_autoptr(GVariant) result = NULL;
1598
1599 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1600 res,
1601 &error);
1602 if (result == NULL) {
1603 cd_client_fixup_dbus_error (error);
1604 g_task_return_error (task, error);
1605 error = NULL;
1606 return;
1607 }
1608
1609 /* create a profile object */
1610 g_variant_get (result, "(o)", &object_path);
1611 profile = cd_profile_new ();
1612 cd_profile_set_object_path (profile, object_path);
1613
1614 /* success */
1615 g_task_return_pointer (task, profile, (GDestroyNotify) g_object_unref);
1616 }
1617
1618 /**
1619 * cd_client_find_profile_by_filename:
1620 * @client: a #CdClient instance.
1621 * @filename: a profile filename
1622 * @cancellable: a #GCancellable, or %NULL
1623 * @callback: the function to run on completion
1624 * @user_data: the data to pass to @callback
1625 *
1626 * Finds a profile by a filename.
1627 *
1628 * Since: 0.1.8
1629 **/
1630 void
cd_client_find_profile_by_filename(CdClient * client,const gchar * filename,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1631 cd_client_find_profile_by_filename (CdClient *client,
1632 const gchar *filename,
1633 GCancellable *cancellable,
1634 GAsyncReadyCallback callback,
1635 gpointer user_data)
1636 {
1637 CdClientPrivate *priv = GET_PRIVATE (client);
1638 GTask *task = NULL;
1639
1640 g_return_if_fail (CD_IS_CLIENT (client));
1641 g_return_if_fail (filename != NULL);
1642 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1643 g_return_if_fail (priv->proxy != NULL);
1644
1645 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1646 g_dbus_proxy_call (priv->proxy,
1647 "FindProfileByFilename",
1648 g_variant_new ("(s)", filename),
1649 G_DBUS_CALL_FLAGS_NONE,
1650 -1,
1651 cancellable,
1652 cd_client_find_profile_by_filename_cb,
1653 task);
1654 }
1655
1656 /**********************************************************************/
1657
1658 /**
1659 * cd_client_get_standard_space_finish:
1660 * @client: a #CdClient instance.
1661 * @res: the #GAsyncResult
1662 * @error: A #GError or %NULL
1663 *
1664 * Gets the result from the asynchronous function.
1665 *
1666 * Return value: (transfer full): a #CdProfile or %NULL
1667 *
1668 * Since: 0.1.8
1669 **/
1670 CdProfile *
cd_client_get_standard_space_finish(CdClient * client,GAsyncResult * res,GError ** error)1671 cd_client_get_standard_space_finish (CdClient *client,
1672 GAsyncResult *res,
1673 GError **error)
1674 {
1675 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
1676 return g_task_propagate_pointer (G_TASK (res), error);
1677 }
1678
1679 static void
cd_client_get_standard_space_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1680 cd_client_get_standard_space_cb (GObject *source_object,
1681 GAsyncResult *res,
1682 gpointer user_data)
1683 {
1684 CdProfile *profile;
1685 g_autoptr(GError) error = NULL;
1686 g_autofree gchar *object_path = NULL;
1687 g_autoptr(GTask) task = G_TASK (user_data);
1688 g_autoptr(GVariant) result = NULL;
1689
1690 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1691 res,
1692 &error);
1693 if (result == NULL) {
1694 cd_client_fixup_dbus_error (error);
1695 g_task_return_error (task, error);
1696 error = NULL;
1697 return;
1698 }
1699
1700 /* create a profile object */
1701 g_variant_get (result, "(o)", &object_path);
1702 profile = cd_profile_new ();
1703 cd_profile_set_object_path (profile, object_path);
1704
1705 /* success */
1706 g_task_return_pointer (task, profile, (GDestroyNotify) g_object_unref);
1707 }
1708
1709 /**
1710 * cd_client_get_standard_space:
1711 * @client: a #CdStandardSpace instance.
1712 * @standard_space: a profile id
1713 * @cancellable: a #GCancellable, or %NULL
1714 * @callback: the function to run on completion
1715 * @user_data: the data to pass to @callback
1716 *
1717 * Finds a standard profile space.
1718 *
1719 * Since: 0.1.8
1720 **/
1721 void
cd_client_get_standard_space(CdClient * client,CdStandardSpace standard_space,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1722 cd_client_get_standard_space (CdClient *client,
1723 CdStandardSpace standard_space,
1724 GCancellable *cancellable,
1725 GAsyncReadyCallback callback,
1726 gpointer user_data)
1727 {
1728 CdClientPrivate *priv = GET_PRIVATE (client);
1729 GTask *task = NULL;
1730
1731 g_return_if_fail (CD_IS_CLIENT (client));
1732 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1733 g_return_if_fail (priv->proxy != NULL);
1734
1735 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1736 g_dbus_proxy_call (priv->proxy,
1737 "GetStandardSpace",
1738 g_variant_new ("(s)",
1739 cd_standard_space_to_string (standard_space)),
1740 G_DBUS_CALL_FLAGS_NONE,
1741 -1,
1742 cancellable,
1743 cd_client_get_standard_space_cb,
1744 task);
1745 }
1746
1747 /**********************************************************************/
1748
1749 /**
1750 * cd_client_get_device_array_from_variant:
1751 **/
1752 static GPtrArray *
cd_client_get_device_array_from_variant(CdClient * client,GVariant * result)1753 cd_client_get_device_array_from_variant (CdClient *client,
1754 GVariant *result)
1755 {
1756 CdDevice *device;
1757 GPtrArray *array = NULL;
1758 GVariantIter iter;
1759 guint i;
1760 guint len;
1761 g_autoptr(GVariant) child = NULL;
1762
1763 /* add each device */
1764 array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
1765 child = g_variant_get_child_value (result, 0);
1766 len = g_variant_iter_init (&iter, child);
1767 for (i = 0; i < len; i++) {
1768 g_autofree gchar *object_path_tmp = NULL;
1769 g_variant_get_child (child, i,
1770 "o", &object_path_tmp);
1771 device = cd_device_new_with_object_path (object_path_tmp);
1772 g_ptr_array_add (array, device);
1773 }
1774 return array;
1775 }
1776
1777 /**
1778 * cd_client_get_devices_finish:
1779 * @client: a #CdClient instance.
1780 * @res: the #GAsyncResult
1781 * @error: A #GError or %NULL
1782 *
1783 * Gets the result from the asynchronous function.
1784 *
1785 * Return value: (element-type CdDevice) (transfer full): the devices
1786 *
1787 * Since: 0.1.8
1788 **/
1789 GPtrArray *
cd_client_get_devices_finish(CdClient * client,GAsyncResult * res,GError ** error)1790 cd_client_get_devices_finish (CdClient *client,
1791 GAsyncResult *res,
1792 GError **error)
1793 {
1794 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
1795 return g_task_propagate_pointer (G_TASK (res), error);
1796 }
1797
1798 static void
cd_client_get_devices_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1799 cd_client_get_devices_cb (GObject *source_object,
1800 GAsyncResult *res,
1801 gpointer user_data)
1802 {
1803 CdClient *client;
1804 GPtrArray *array;
1805 g_autoptr(GError) error = NULL;
1806 g_autofree gchar *object_path = NULL;
1807 g_autoptr(GTask) task = G_TASK (user_data);
1808 g_autoptr(GVariant) result = NULL;
1809
1810 client = CD_CLIENT (g_task_get_source_object (task));
1811 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1812 res,
1813 &error);
1814 if (result == NULL) {
1815 cd_client_fixup_dbus_error (error);
1816 g_task_return_error (task, error);
1817 error = NULL;
1818 return;
1819 }
1820
1821 /* create a profile object */
1822 array = cd_client_get_device_array_from_variant (client, result);
1823
1824 /* success */
1825 g_task_return_pointer (task, array, (GDestroyNotify) g_ptr_array_unref);
1826 }
1827
1828 /**
1829 * cd_client_get_devices:
1830 * @client: a #CdClient instance.
1831 * @cancellable: a #GCancellable, or %NULL
1832 * @callback: the function to run on completion
1833 * @user_data: the data to pass to @callback
1834 *
1835 * Gets an array of color devices.
1836 *
1837 * Since: 0.1.8
1838 **/
1839 void
cd_client_get_devices(CdClient * client,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1840 cd_client_get_devices (CdClient *client,
1841 GCancellable *cancellable,
1842 GAsyncReadyCallback callback,
1843 gpointer user_data)
1844 {
1845 CdClientPrivate *priv = GET_PRIVATE (client);
1846 GTask *task = NULL;
1847
1848 g_return_if_fail (CD_IS_CLIENT (client));
1849 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1850 g_return_if_fail (priv->proxy != NULL);
1851
1852 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1853 g_dbus_proxy_call (priv->proxy,
1854 "GetDevices",
1855 NULL,
1856 G_DBUS_CALL_FLAGS_NONE,
1857 -1,
1858 cancellable,
1859 cd_client_get_devices_cb,
1860 task);
1861 }
1862
1863 /**********************************************************************/
1864
1865 /**
1866 * cd_client_get_devices_by_kind_finish:
1867 * @client: a #CdClient instance.
1868 * @res: the #GAsyncResult
1869 * @error: A #GError or %NULL
1870 *
1871 * Gets the result from the asynchronous function.
1872 *
1873 * Return value: (element-type CdDevice) (transfer full): the devices
1874 *
1875 * Since: 0.1.8
1876 **/
1877 GPtrArray *
cd_client_get_devices_by_kind_finish(CdClient * client,GAsyncResult * res,GError ** error)1878 cd_client_get_devices_by_kind_finish (CdClient *client,
1879 GAsyncResult *res,
1880 GError **error)
1881 {
1882 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
1883 return g_task_propagate_pointer (G_TASK (res), error);
1884 }
1885
1886 static void
cd_client_get_devices_by_kind_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)1887 cd_client_get_devices_by_kind_cb (GObject *source_object,
1888 GAsyncResult *res,
1889 gpointer user_data)
1890 {
1891 CdClient *client;
1892 GPtrArray *array;
1893 g_autoptr(GError) error = NULL;
1894 g_autofree gchar *object_path = NULL;
1895 g_autoptr(GTask) task = G_TASK (user_data);
1896 g_autoptr(GVariant) result = NULL;
1897
1898 client = CD_CLIENT (g_task_get_source_object (task));
1899 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
1900 res,
1901 &error);
1902 if (result == NULL) {
1903 cd_client_fixup_dbus_error (error);
1904 g_task_return_error (task, error);
1905 error = NULL;
1906 return;
1907 }
1908
1909 /* create a profile object */
1910 array = cd_client_get_device_array_from_variant (client, result);
1911
1912 /* success */
1913 g_task_return_pointer (task, array, (GDestroyNotify) g_ptr_array_unref);
1914 }
1915
1916 /**
1917 * cd_client_get_devices_by_kind:
1918 * @client: a #CdClient instance.
1919 * @kind: the type of device.
1920 * @cancellable: a #GCancellable, or %NULL
1921 * @callback: the function to run on completion
1922 * @user_data: the data to pass to @callback
1923 *
1924 * Gets an array of color devices.
1925 *
1926 * Since: 0.1.8
1927 **/
1928 void
cd_client_get_devices_by_kind(CdClient * client,CdDeviceKind kind,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)1929 cd_client_get_devices_by_kind (CdClient *client,
1930 CdDeviceKind kind,
1931 GCancellable *cancellable,
1932 GAsyncReadyCallback callback,
1933 gpointer user_data)
1934 {
1935 CdClientPrivate *priv = GET_PRIVATE (client);
1936 GTask *task = NULL;
1937
1938 g_return_if_fail (CD_IS_CLIENT (client));
1939 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
1940 g_return_if_fail (priv->proxy != NULL);
1941
1942 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
1943 g_dbus_proxy_call (priv->proxy,
1944 "GetDevicesByKind",
1945 g_variant_new ("(s)",
1946 cd_device_kind_to_string (kind)),
1947 G_DBUS_CALL_FLAGS_NONE,
1948 -1,
1949 cancellable,
1950 cd_client_get_devices_by_kind_cb,
1951 task);
1952 }
1953
1954 /**********************************************************************/
1955
1956 /**
1957 * cd_client_get_profile_array_from_variant:
1958 **/
1959 static GPtrArray *
cd_client_get_profile_array_from_variant(CdClient * client,GVariant * result)1960 cd_client_get_profile_array_from_variant (CdClient *client,
1961 GVariant *result)
1962 {
1963 CdProfile *profile;
1964 GPtrArray *array = NULL;
1965 GVariantIter iter;
1966 guint i;
1967 guint len;
1968 g_autoptr(GVariant) child = NULL;
1969
1970 /* add each profile */
1971 array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
1972 child = g_variant_get_child_value (result, 0);
1973 len = g_variant_iter_init (&iter, child);
1974 for (i = 0; i < len; i++) {
1975 g_autofree gchar *object_path_tmp = NULL;
1976 g_variant_get_child (child, i,
1977 "o", &object_path_tmp);
1978 profile = cd_profile_new_with_object_path (object_path_tmp);
1979 g_ptr_array_add (array, profile);
1980 }
1981 return array;
1982 }
1983
1984 /**
1985 * cd_client_get_profiles_finish:
1986 * @client: a #CdClient instance.
1987 * @res: the #GAsyncResult
1988 * @error: A #GError or %NULL
1989 *
1990 * Gets the result from the asynchronous function.
1991 *
1992 * Return value: (element-type CdProfile) (transfer full): the profiles
1993 *
1994 * Since: 0.1.8
1995 **/
1996 GPtrArray *
cd_client_get_profiles_finish(CdClient * client,GAsyncResult * res,GError ** error)1997 cd_client_get_profiles_finish (CdClient *client,
1998 GAsyncResult *res,
1999 GError **error)
2000 {
2001 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
2002 return g_task_propagate_pointer (G_TASK (res), error);
2003 }
2004
2005 static void
cd_client_get_profiles_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)2006 cd_client_get_profiles_cb (GObject *source_object,
2007 GAsyncResult *res,
2008 gpointer user_data)
2009 {
2010 CdClient *client;
2011 GPtrArray *array;
2012 g_autoptr(GError) error = NULL;
2013 g_autofree gchar *object_path = NULL;
2014 g_autoptr(GTask) task = G_TASK (user_data);
2015 g_autoptr(GVariant) result = NULL;
2016
2017 client = CD_CLIENT (g_task_get_source_object (task));
2018 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
2019 res,
2020 &error);
2021 if (result == NULL) {
2022 cd_client_fixup_dbus_error (error);
2023 g_task_return_error (task, error);
2024 error = NULL;
2025 return;
2026 }
2027
2028 /* create a profile object */
2029 array = cd_client_get_profile_array_from_variant (client, result);
2030
2031 /* success */
2032 g_task_return_pointer (task, array, (GDestroyNotify) g_ptr_array_unref);
2033 }
2034
2035 /**
2036 * cd_client_get_profiles:
2037 * @client: a #CdClient instance.
2038 * @cancellable: a #GCancellable, or %NULL
2039 * @callback: the function to run on completion
2040 * @user_data: the data to pass to @callback
2041 *
2042 * Gets an array of color profiles.
2043 *
2044 * Since: 0.1.8
2045 **/
2046 void
cd_client_get_profiles(CdClient * client,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2047 cd_client_get_profiles (CdClient *client,
2048 GCancellable *cancellable,
2049 GAsyncReadyCallback callback,
2050 gpointer user_data)
2051 {
2052 CdClientPrivate *priv = GET_PRIVATE (client);
2053 GTask *task = NULL;
2054
2055 g_return_if_fail (CD_IS_CLIENT (client));
2056 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2057 g_return_if_fail (priv->proxy != NULL);
2058
2059 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
2060 g_dbus_proxy_call (priv->proxy,
2061 "GetProfiles",
2062 NULL,
2063 G_DBUS_CALL_FLAGS_NONE,
2064 -1,
2065 cancellable,
2066 cd_client_get_profiles_cb,
2067 task);
2068 }
2069
2070 /**********************************************************************/
2071
2072 /**
2073 * cd_client_get_sensor_array_from_variant:
2074 **/
2075 static GPtrArray *
cd_client_get_sensor_array_from_variant(CdClient * client,GVariant * result)2076 cd_client_get_sensor_array_from_variant (CdClient *client,
2077 GVariant *result)
2078 {
2079 CdSensor *sensor;
2080 GPtrArray *array = NULL;
2081 GVariantIter iter;
2082 guint i;
2083 guint len;
2084 g_autoptr(GVariant) child = NULL;
2085
2086 /* add each sensor */
2087 array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_object_unref);
2088 child = g_variant_get_child_value (result, 0);
2089 len = g_variant_iter_init (&iter, child);
2090 for (i = 0; i < len; i++) {
2091 g_autofree gchar *object_path_tmp = NULL;
2092 g_variant_get_child (child, i,
2093 "o", &object_path_tmp);
2094 sensor = cd_sensor_new_with_object_path (object_path_tmp);
2095 g_ptr_array_add (array, sensor);
2096 }
2097 return array;
2098 }
2099
2100 /**
2101 * cd_client_get_sensors_finish:
2102 * @client: a #CdClient instance.
2103 * @res: the #GAsyncResult
2104 * @error: A #GError or %NULL
2105 *
2106 * Gets the result from the asynchronous function.
2107 *
2108 * Return value: (element-type CdSensor) (transfer full): the sensors
2109 *
2110 * Since: 0.1.8
2111 **/
2112 GPtrArray *
cd_client_get_sensors_finish(CdClient * client,GAsyncResult * res,GError ** error)2113 cd_client_get_sensors_finish (CdClient *client,
2114 GAsyncResult *res,
2115 GError **error)
2116 {
2117 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
2118 return g_task_propagate_pointer (G_TASK (res), error);
2119 }
2120
2121 static void
cd_client_get_sensors_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)2122 cd_client_get_sensors_cb (GObject *source_object,
2123 GAsyncResult *res,
2124 gpointer user_data)
2125 {
2126 GPtrArray *array;
2127 g_autoptr(GError) error = NULL;
2128 g_autofree gchar *object_path = NULL;
2129 g_autoptr(GTask) task = G_TASK (user_data);
2130 g_autoptr(GVariant) result = NULL;
2131 CdClient *client = CD_CLIENT (g_task_get_source_object (task));
2132
2133 client = CD_CLIENT (g_task_get_source_object (task));
2134 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
2135 res,
2136 &error);
2137 if (result == NULL) {
2138 cd_client_fixup_dbus_error (error);
2139 g_task_return_error (task, error);
2140 error = NULL;
2141 return;
2142 }
2143
2144 /* create a sensor object */
2145 array = cd_client_get_sensor_array_from_variant (client, result);
2146
2147 /* success */
2148 g_task_return_pointer (task, array, (GDestroyNotify) g_ptr_array_unref);
2149 }
2150
2151 /**
2152 * cd_client_get_sensors:
2153 * @client: a #CdClient instance.
2154 * @cancellable: a #GCancellable, or %NULL
2155 * @callback: the function to run on completion
2156 * @user_data: the data to pass to @callback
2157 *
2158 * Gets an array of color sensors.
2159 *
2160 * Since: 0.1.8
2161 **/
2162 void
cd_client_get_sensors(CdClient * client,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2163 cd_client_get_sensors (CdClient *client,
2164 GCancellable *cancellable,
2165 GAsyncReadyCallback callback,
2166 gpointer user_data)
2167 {
2168 CdClientPrivate *priv = GET_PRIVATE (client);
2169 GTask *task = NULL;
2170
2171 g_return_if_fail (CD_IS_CLIENT (client));
2172 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2173 g_return_if_fail (priv->proxy != NULL);
2174
2175 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
2176 g_dbus_proxy_call (priv->proxy,
2177 "GetSensors",
2178 NULL,
2179 G_DBUS_CALL_FLAGS_NONE,
2180 -1,
2181 cancellable,
2182 cd_client_get_sensors_cb,
2183 task);
2184 }
2185
2186 /**********************************************************************/
2187
2188 /**
2189 * cd_client_find_profile_by_property_finish:
2190 * @client: a #CdClient instance.
2191 * @res: the #GAsyncResult
2192 * @error: A #GError or %NULL
2193 *
2194 * Gets the result from the asynchronous function.
2195 *
2196 * Return value: (transfer full): a #CdProfile or %NULL
2197 *
2198 * Since: 0.1.24
2199 **/
2200 CdProfile *
cd_client_find_profile_by_property_finish(CdClient * client,GAsyncResult * res,GError ** error)2201 cd_client_find_profile_by_property_finish (CdClient *client,
2202 GAsyncResult *res,
2203 GError **error)
2204 {
2205 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
2206 return g_task_propagate_pointer (G_TASK (res), error);
2207 }
2208
2209 static void
cd_client_find_profile_by_property_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)2210 cd_client_find_profile_by_property_cb (GObject *source_object,
2211 GAsyncResult *res,
2212 gpointer user_data)
2213 {
2214 CdProfile *profile;
2215 g_autoptr(GError) error = NULL;
2216 g_autofree gchar *object_path = NULL;
2217 g_autoptr(GTask) task = G_TASK (user_data);
2218 g_autoptr(GVariant) result = NULL;
2219
2220 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
2221 res,
2222 &error);
2223 if (result == NULL) {
2224 cd_client_fixup_dbus_error (error);
2225 g_task_return_error (task, error);
2226 error = NULL;
2227 return;
2228 }
2229
2230 /* create a profile object */
2231 g_variant_get (result, "(o)", &object_path);
2232 profile = cd_profile_new ();
2233 cd_profile_set_object_path (profile, object_path);
2234
2235 /* success */
2236 g_task_return_pointer (task, profile, (GDestroyNotify) g_object_unref);
2237 }
2238
2239 /**
2240 * cd_client_find_profile_by_property:
2241 * @client: a #CdClient instance.
2242 * @key: the profile property key
2243 * @value: the profile property value
2244 * @cancellable: a #GCancellable, or %NULL
2245 * @callback: the function to run on completion
2246 * @user_data: the data to pass to @callback
2247 *
2248 * Finds a color profile that has a property value.
2249 *
2250 * Since: 0.1.24
2251 **/
2252 void
cd_client_find_profile_by_property(CdClient * client,const gchar * key,const gchar * value,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2253 cd_client_find_profile_by_property (CdClient *client,
2254 const gchar *key,
2255 const gchar *value,
2256 GCancellable *cancellable,
2257 GAsyncReadyCallback callback,
2258 gpointer user_data)
2259 {
2260 CdClientPrivate *priv = GET_PRIVATE (client);
2261 GTask *task = NULL;
2262
2263 g_return_if_fail (CD_IS_CLIENT (client));
2264 g_return_if_fail (key != NULL);
2265 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2266 g_return_if_fail (priv->proxy != NULL);
2267
2268 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
2269 g_dbus_proxy_call (priv->proxy,
2270 "FindProfileByProperty",
2271 g_variant_new ("(ss)", key, value),
2272 G_DBUS_CALL_FLAGS_NONE,
2273 -1,
2274 cancellable,
2275 cd_client_find_profile_by_property_cb,
2276 task);
2277 }
2278
2279 /**********************************************************************/
2280
2281 /**
2282 * cd_client_find_sensor_finish:
2283 * @client: a #CdClient instance.
2284 * @res: the #GAsyncResult
2285 * @error: A #GError or %NULL
2286 *
2287 * Gets the result from the asynchronous function.
2288 *
2289 * Return value: (transfer full): a #CdSensor or %NULL
2290 *
2291 * Since: 0.1.26
2292 **/
2293 CdSensor *
cd_client_find_sensor_finish(CdClient * client,GAsyncResult * res,GError ** error)2294 cd_client_find_sensor_finish (CdClient *client,
2295 GAsyncResult *res,
2296 GError **error)
2297 {
2298 g_return_val_if_fail (g_task_is_valid (res, client), NULL);
2299 return g_task_propagate_pointer (G_TASK (res), error);
2300 }
2301
2302 static void
cd_client_find_sensor_cb(GObject * source_object,GAsyncResult * res,gpointer user_data)2303 cd_client_find_sensor_cb (GObject *source_object,
2304 GAsyncResult *res,
2305 gpointer user_data)
2306 {
2307 CdSensor *sensor;
2308 g_autoptr(GError) error = NULL;
2309 g_autofree gchar *object_path = NULL;
2310 g_autoptr(GTask) task = G_TASK (user_data);
2311 g_autoptr(GVariant) result = NULL;
2312
2313 result = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
2314 res,
2315 &error);
2316 if (result == NULL) {
2317 cd_client_fixup_dbus_error (error);
2318 g_task_return_error (task, error);
2319 error = NULL;
2320 return;
2321 }
2322
2323 /* create a sensor object */
2324 g_variant_get (result, "(o)", &object_path);
2325 sensor = cd_sensor_new ();
2326 cd_sensor_set_object_path (sensor, object_path);
2327
2328 /* success */
2329 g_task_return_pointer (task, sensor, (GDestroyNotify) g_object_unref);
2330 }
2331
2332 /**
2333 * cd_client_find_sensor:
2334 * @client: a #CdClient instance.
2335 * @id: a sensor id
2336 * @cancellable: a #GCancellable, or %NULL
2337 * @callback: the function to run on completion
2338 * @user_data: the data to pass to @callback
2339 *
2340 * Finds a sensor by an ID.
2341 *
2342 * Since: 0.1.26
2343 **/
2344 void
cd_client_find_sensor(CdClient * client,const gchar * id,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)2345 cd_client_find_sensor (CdClient *client,
2346 const gchar *id,
2347 GCancellable *cancellable,
2348 GAsyncReadyCallback callback,
2349 gpointer user_data)
2350 {
2351 CdClientPrivate *priv = GET_PRIVATE (client);
2352 GTask *task = NULL;
2353
2354 g_return_if_fail (CD_IS_CLIENT (client));
2355 g_return_if_fail (id != NULL);
2356 g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2357 g_return_if_fail (priv->proxy != NULL);
2358
2359 task = g_task_new (G_OBJECT (client), cancellable, callback, user_data);
2360 g_dbus_proxy_call (priv->proxy,
2361 "FindSensorById",
2362 g_variant_new ("(s)", id),
2363 G_DBUS_CALL_FLAGS_NONE,
2364 -1,
2365 cancellable,
2366 cd_client_find_sensor_cb,
2367 task);
2368 }
2369
2370 /**********************************************************************/
2371
2372 /*
2373 * cd_client_get_property:
2374 */
2375 static void
cd_client_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2376 cd_client_get_property (GObject *object,
2377 guint prop_id,
2378 GValue *value,
2379 GParamSpec *pspec)
2380 {
2381 CdClient *client = CD_CLIENT (object);
2382 CdClientPrivate *priv = GET_PRIVATE (client);
2383
2384 switch (prop_id) {
2385 case PROP_DAEMON_VERSION:
2386 g_value_set_string (value, priv->daemon_version);
2387 break;
2388 case PROP_SYSTEM_VENDOR:
2389 g_value_set_string (value, priv->system_vendor);
2390 break;
2391 case PROP_SYSTEM_MODEL:
2392 g_value_set_string (value, priv->system_model);
2393 break;
2394 case PROP_CONNECTED:
2395 g_value_set_boolean (value, priv->proxy != NULL);
2396 break;
2397 default:
2398 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2399 break;
2400 }
2401 }
2402
2403 /*
2404 * cd_client_class_init:
2405 */
2406 static void
cd_client_class_init(CdClientClass * klass)2407 cd_client_class_init (CdClientClass *klass)
2408 {
2409 GObjectClass *object_class = G_OBJECT_CLASS (klass);
2410
2411 object_class->get_property = cd_client_get_property;
2412 object_class->finalize = cd_client_finalize;
2413
2414 /**
2415 * CdClient:daemon-version:
2416 *
2417 * The daemon version.
2418 *
2419 * Since: 0.1.0
2420 */
2421 g_object_class_install_property (object_class,
2422 PROP_DAEMON_VERSION,
2423 g_param_spec_string ("daemon-version",
2424 "Daemon version",
2425 NULL,
2426 NULL,
2427 G_PARAM_READABLE));
2428 /**
2429 * CdClient:system-vendor:
2430 *
2431 * The system vendor.
2432 *
2433 * Since: 1.0.2
2434 */
2435 g_object_class_install_property (object_class,
2436 PROP_SYSTEM_VENDOR,
2437 g_param_spec_string ("system-vendor",
2438 "System Vendor",
2439 NULL,
2440 NULL,
2441 G_PARAM_READABLE));
2442 /**
2443 * CdClient:system-model:
2444 *
2445 * The system model.
2446 *
2447 * Since: 1.0.2
2448 */
2449 g_object_class_install_property (object_class,
2450 PROP_SYSTEM_MODEL,
2451 g_param_spec_string ("system-model",
2452 "System model",
2453 NULL,
2454 NULL,
2455 G_PARAM_READABLE));
2456 /**
2457 * CdClient:connected:
2458 *
2459 * The if the object path has been connected as is valid for use.
2460 *
2461 * Since: 0.1.9
2462 **/
2463 g_object_class_install_property (object_class,
2464 PROP_CONNECTED,
2465 g_param_spec_string ("connected",
2466 NULL, NULL,
2467 NULL,
2468 G_PARAM_READABLE));
2469
2470 /**
2471 * CdClient::device-added:
2472 * @client: the #CdClient instance that emitted the signal
2473 * @device: the #CdDevice that was added.
2474 *
2475 * The ::device-added signal is emitted when a device is added.
2476 *
2477 * Since: 0.1.0
2478 **/
2479 signals [SIGNAL_DEVICE_ADDED] =
2480 g_signal_new ("device-added",
2481 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2482 G_STRUCT_OFFSET (CdClientClass, device_added),
2483 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2484 G_TYPE_NONE, 1, CD_TYPE_DEVICE);
2485
2486 /**
2487 * CdClient::device-removed:
2488 * @client: the #CdClient instance that emitted the signal
2489 * @device: the #CdDevice that was removed.
2490 *
2491 * The ::device-added signal is emitted when a device is removed.
2492 *
2493 * Since: 0.1.0
2494 **/
2495 signals [SIGNAL_DEVICE_REMOVED] =
2496 g_signal_new ("device-removed",
2497 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2498 G_STRUCT_OFFSET (CdClientClass, device_removed),
2499 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2500 G_TYPE_NONE, 1, CD_TYPE_DEVICE);
2501 /**
2502 * CdClient::device-changed:
2503 * @client: the #CdClient instance that emitted the signal
2504 * @device: the #CdDevice that was changed.
2505 *
2506 * The ::device-changed signal is emitted when a device is changed.
2507 *
2508 * Since: 0.1.2
2509 **/
2510 signals [SIGNAL_DEVICE_CHANGED] =
2511 g_signal_new ("device-changed",
2512 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2513 G_STRUCT_OFFSET (CdClientClass, device_changed),
2514 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2515 G_TYPE_NONE, 1, CD_TYPE_DEVICE);
2516 /**
2517 * CdClient::profile-added:
2518 * @client: the #CdClient instance that emitted the signal
2519 * @profile: the #CdProfile that was added.
2520 *
2521 * The ::profile-added signal is emitted when a profile is added.
2522 *
2523 * Since: 0.1.2
2524 **/
2525 signals [SIGNAL_PROFILE_ADDED] =
2526 g_signal_new ("profile-added",
2527 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2528 G_STRUCT_OFFSET (CdClientClass, profile_added),
2529 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2530 G_TYPE_NONE, 1, CD_TYPE_PROFILE);
2531
2532 /**
2533 * CdClient::profile-removed:
2534 * @client: the #CdClient instance that emitted the signal
2535 * @profile: the #CdProfile that was removed.
2536 *
2537 * The ::profile-added signal is emitted when a profile is removed.
2538 *
2539 * Since: 0.1.2
2540 **/
2541 signals [SIGNAL_PROFILE_REMOVED] =
2542 g_signal_new ("profile-removed",
2543 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2544 G_STRUCT_OFFSET (CdClientClass, profile_removed),
2545 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2546 G_TYPE_NONE, 1, CD_TYPE_PROFILE);
2547 /**
2548 * CdClient::profile-changed:
2549 * @client: the #CdClient instance that emitted the signal
2550 * @profile: the #CdProfile that was removed.
2551 *
2552 * The ::profile-changed signal is emitted when a profile is changed.
2553 *
2554 * Since: 0.1.2
2555 **/
2556 signals [SIGNAL_PROFILE_CHANGED] =
2557 g_signal_new ("profile-changed",
2558 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2559 G_STRUCT_OFFSET (CdClientClass, profile_changed),
2560 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2561 G_TYPE_NONE, 1, CD_TYPE_PROFILE);
2562
2563 /**
2564 * CdClient::sensor-added:
2565 * @client: the #CdClient instance that emitted the signal
2566 * @sensor: the #CdSensor that was added.
2567 *
2568 * The ::sensor-added signal is emitted when a sensor is added.
2569 *
2570 * Since: 0.1.6
2571 **/
2572 signals [SIGNAL_SENSOR_ADDED] =
2573 g_signal_new ("sensor-added",
2574 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2575 G_STRUCT_OFFSET (CdClientClass, sensor_added),
2576 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2577 G_TYPE_NONE, 1, CD_TYPE_SENSOR);
2578
2579 /**
2580 * CdClient::sensor-removed:
2581 * @client: the #CdClient instance that emitted the signal
2582 * @sensor: the #CdSensor that was removed.
2583 *
2584 * The ::sensor-added signal is emitted when a sensor is removed.
2585 *
2586 * Since: 0.1.6
2587 **/
2588 signals [SIGNAL_SENSOR_REMOVED] =
2589 g_signal_new ("sensor-removed",
2590 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2591 G_STRUCT_OFFSET (CdClientClass, sensor_removed),
2592 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2593 G_TYPE_NONE, 1, CD_TYPE_SENSOR);
2594 /**
2595 * CdClient::sensor-changed:
2596 * @client: the #CdClient instance that emitted the signal
2597 * @sensor: the #CdSensor that was removed.
2598 *
2599 * The ::sensor-changed signal is emitted when a sensor is changed.
2600 *
2601 * Since: 0.1.6
2602 **/
2603 signals [SIGNAL_SENSOR_CHANGED] =
2604 g_signal_new ("sensor-changed",
2605 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2606 G_STRUCT_OFFSET (CdClientClass, sensor_changed),
2607 NULL, NULL, g_cclosure_marshal_VOID__OBJECT,
2608 G_TYPE_NONE, 1, CD_TYPE_SENSOR);
2609
2610 /**
2611 * CdClient::changed:
2612 * @client: the #CdDevice instance that emitted the signal
2613 *
2614 * The ::changed signal is emitted when properties may have changed.
2615 *
2616 * Since: 0.1.0
2617 **/
2618 signals [SIGNAL_CHANGED] =
2619 g_signal_new ("changed",
2620 G_TYPE_FROM_CLASS (object_class), G_SIGNAL_RUN_LAST,
2621 G_STRUCT_OFFSET (CdClientClass, changed),
2622 NULL, NULL, g_cclosure_marshal_VOID__VOID,
2623 G_TYPE_NONE, 0);
2624 }
2625
2626 /*
2627 * cd_client_init:
2628 */
2629 static void
cd_client_init(CdClient * client)2630 cd_client_init (CdClient *client)
2631 {
2632 /* ensure the remote errors are registered */
2633 cd_client_error_quark ();
2634 }
2635
2636 /*
2637 * cd_client_finalize:
2638 */
2639 static void
cd_client_finalize(GObject * object)2640 cd_client_finalize (GObject *object)
2641 {
2642 CdClient *client = CD_CLIENT (object);
2643 CdClientPrivate *priv = GET_PRIVATE (client);
2644
2645 g_return_if_fail (CD_IS_CLIENT (object));
2646
2647 g_free (priv->daemon_version);
2648 g_free (priv->system_vendor);
2649 g_free (priv->system_model);
2650 if (priv->proxy != NULL)
2651 g_object_unref (priv->proxy);
2652
2653 G_OBJECT_CLASS (cd_client_parent_class)->finalize (object);
2654 }
2655
2656 /**
2657 * cd_client_new:
2658 *
2659 * Creates a new #CdClient object.
2660 *
2661 * Return value: a new CdClient object.
2662 *
2663 * Since: 0.1.0
2664 **/
2665 CdClient *
cd_client_new(void)2666 cd_client_new (void)
2667 {
2668 if (cd_client_object != NULL) {
2669 g_object_ref (cd_client_object);
2670 } else {
2671 cd_client_object = g_object_new (CD_TYPE_CLIENT, NULL);
2672 g_object_add_weak_pointer (cd_client_object, &cd_client_object);
2673 }
2674 return CD_CLIENT (cd_client_object);
2675 }
2676
2677