dconf-client: include dconf-paths header
[dconf.git] / client / dconf-client.c
blobfb265272a766fcb80ac9e4b8e3678c926e985230
1 /*
2 * Copyright © 2010 Codethink Limited
3 * Copyright © 2012 Canonical Limited
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the licence, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18 * Author: Ryan Lortie <desrt@desrt.ca>
21 #include "config.h"
23 #include "dconf-client.h"
25 #include "../engine/dconf-engine.h"
26 #include "../common/dconf-paths.h"
27 #include <glib-object.h>
29 /**
30 * SECTION:client
31 * @title: DConfClient
32 * @short_description: Direct read and write access to dconf, based on GDBus
34 * This is the primary client interface to dconf.
36 * It allows applications to directly read from and write to the dconf
37 * database. Applications can subscribe to change notifications.
39 * Most applications probably don't want to access dconf directly and
40 * would be better off using something like #GSettings.
42 * Please note that the API of libdconf is not stable in any way. It
43 * has changed in incompatible ways in the past and there will be
44 * further changes in the future.
45 **/
47 /**
48 * DConfClient:
50 * The main object for interacting with dconf. This is a #GObject, so
51 * you should manage it with g_object_ref() and g_object_unref().
52 **/
53 struct _DConfClient
55 GObject parent_instance;
57 DConfEngine *engine;
58 GMainContext *context;
61 G_DEFINE_TYPE (DConfClient, dconf_client, G_TYPE_OBJECT)
63 enum
65 SIGNAL_CHANGED,
66 N_SIGNALS
68 static guint dconf_client_signals[N_SIGNALS];
70 static void
71 dconf_client_finalize (GObject *object)
73 DConfClient *client = DCONF_CLIENT (object);
75 dconf_engine_unref (client->engine);
76 g_main_context_unref (client->context);
78 G_OBJECT_CLASS (dconf_client_parent_class)
79 ->finalize (object);
82 static void
83 dconf_client_init (DConfClient *client)
87 static void
88 dconf_client_class_init (DConfClientClass *class)
90 class->finalize = dconf_client_finalize;
92 /**
93 * DConfClient::changed:
94 * @client: the #DConfClient reporting the change
95 * @prefix: the prefix under which the changes happened
96 * @changes: the list of paths that were changed, relative to @prefix
97 * @tag: the tag for the change, if it originated from the service
99 * This signal is emitted when the #DConfClient has a possible change
100 * to report. The signal is an indication that a change may have
101 * occurred; it's possible that the keys will still have the same value
102 * as before.
104 * To ensure that you receive notification about changes to paths that
105 * you are interested in you must call dconf_client_watch_fast() or
106 * dconf_client_watch_sync(). You may still receive notifications for
107 * paths that you did not explicitly watch.
109 * @prefix will be an absolute dconf path; see dconf_is_path().
110 * @changes is a %NULL-terminated array of dconf rel paths; see
111 * dconf_is_rel_path().
113 * @tag is an opaque tag string, or %NULL. The only thing you should
114 * do with @tag is to compare it to tag values returned by
115 * dconf_client_write_sync() or dconf_client_change_sync().
117 * The number of changes being reported is equal to the length of
118 * @changes. Appending each item in @changes to @prefix will give the
119 * absolute path of each changed item.
121 * If a single key has changed then @prefix will be equal to the key
122 * and @changes will contain a single item: the empty string.
124 * If a single dir has changed (indicating that any key under the dir
125 * may have changed) then @prefix will be equal to the dir and
126 * @changes will contain a single empty string.
128 * If more than one change is being reported then @changes will have
129 * more than one item.
131 dconf_client_signals[SIGNAL_CHANGED] = g_signal_new ("changed", DCONF_TYPE_CLIENT, G_SIGNAL_RUN_LAST,
132 0, NULL, NULL, NULL, G_TYPE_NONE, 3,
133 G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
134 G_TYPE_STRV | G_SIGNAL_TYPE_STATIC_SCOPE,
135 G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE);
138 typedef struct
140 DConfClient *client;
141 gchar *prefix;
142 gchar **changes;
143 gchar *tag;
144 } DConfClientChange;
146 static gboolean
147 dconf_client_dispatch_change_signal (gpointer user_data)
149 DConfClientChange *change = user_data;
151 g_signal_emit (change->client, dconf_client_signals[SIGNAL_CHANGED], 0,
152 change->prefix, change->changes, change->tag);
154 g_object_unref (change->client);
155 g_free (change->prefix);
156 g_strfreev (change->changes);
157 g_free (change->tag);
158 g_slice_free (DConfClientChange, change);
160 return G_SOURCE_REMOVE;
163 void
164 dconf_engine_change_notify (DConfEngine *engine,
165 const gchar *prefix,
166 const gchar * const *changes,
167 const gchar * tag,
168 gboolean is_writability,
169 gpointer origin_tag,
170 gpointer user_data)
172 GWeakRef *weak_ref = user_data;
173 DConfClientChange *change;
174 DConfClient *client;
176 client = g_weak_ref_get (weak_ref);
178 if (client == NULL)
179 return;
181 g_return_if_fail (DCONF_IS_CLIENT (client));
183 change = g_slice_new (DConfClientChange);
184 change->client = client;
185 change->prefix = g_strdup (prefix);
186 change->changes = g_strdupv ((gchar **) changes);
187 change->tag = g_strdup (tag);
189 g_main_context_invoke (client->context, dconf_client_dispatch_change_signal, change);
192 static void
193 dconf_client_free_weak_ref (gpointer data)
195 GWeakRef *weak_ref = data;
197 g_weak_ref_clear (weak_ref);
198 g_slice_free (GWeakRef, weak_ref);
202 * dconf_client_new:
204 * Creates a new #DConfClient.
206 * Returns: a new #DConfClient
208 DConfClient *
209 dconf_client_new (void)
211 DConfClient *client;
212 GWeakRef *weak_ref;
214 client = g_object_new (DCONF_TYPE_CLIENT, NULL);
215 weak_ref = g_slice_new (GWeakRef);
216 g_weak_ref_init (weak_ref, client);
217 client->engine = dconf_engine_new (NULL, weak_ref, dconf_client_free_weak_ref);
218 client->context = g_main_context_ref_thread_default ();
220 return client;
224 * dconf_client_read:
225 * @client: a #DConfClient
226 * @key: the key to read the value of
228 * Reads the current value of @key.
230 * If @key exists, its value is returned. Otherwise, %NULL is returned.
232 * If there are outstanding "fast" changes in progress they may affect
233 * the result of this call.
235 * Returns: a #GVariant, or %NULL
237 GVariant *
238 dconf_client_read (DConfClient *client,
239 const gchar *key)
241 g_return_val_if_fail (DCONF_IS_CLIENT (client), NULL);
243 return dconf_engine_read (client->engine, NULL, key);
246 /* This provides a "read through" queue that resets all of the keys.
247 * This is a good way to get the default value for a key.
249 * We cache the value of this queue in a static instead of generating
250 * and freeing it each time.
252 static GQueue *
253 dconf_client_get_reset_queue (void)
255 static GQueue *reset_queue;
257 if (g_once_init_enter (&reset_queue))
259 DConfChangeset *reset_all;
260 GQueue *tmp;
262 reset_all = dconf_changeset_new ();
263 dconf_changeset_set (reset_all, "/", NULL);
264 dconf_changeset_seal (reset_all);
266 tmp = g_queue_new ();
267 g_queue_push_tail (tmp, reset_all);
268 g_once_init_leave (&reset_queue, tmp);
271 return reset_queue;
275 * dconf_client_read_default:
276 * @client: a #DConfClient
277 * @key: the key to read the default value of
279 * Reads the current default value of @key.
281 * The default value of the key is the value that the key would have if
282 * were to be reset. This is usually %NULL, but it may be something
283 * else in the case that the system administrator has defined a default
284 * value for a key.
286 * If there are outstanding "fast" changes in progress they may affect
287 * the result of this call.
289 * Returns: a #GVariant, or %NULL
291 GVariant *
292 dconf_client_read_default (DConfClient *client,
293 const gchar *key)
295 g_return_val_if_fail (DCONF_IS_CLIENT (client), NULL);
297 return dconf_engine_read (client->engine, dconf_client_get_reset_queue (), key);
301 * dconf_client_list:
302 * @client: a #DConfClient
303 * @dir: the dir to list the contents of
304 * @length: the length of the returned list
306 * Gets the list of all dirs and keys immediately under @dir.
308 * If @length is non-%NULL then it will be set to the length of the
309 * returned array. In any case, the array is %NULL-terminated.
311 * IF there are outstanding "fast" changes in progress then this call
312 * may return inaccurate results with respect to those outstanding
313 * changes.
315 * Returns: an array of strings, never %NULL.
317 gchar **
318 dconf_client_list (DConfClient *client,
319 const gchar *dir,
320 gint *length)
322 g_return_val_if_fail (DCONF_IS_CLIENT (client), NULL);
324 return dconf_engine_list (client->engine, dir, length);
328 * dconf_client_list_locks:
329 * @client: a #DConfClient
330 * @dir: the dir to limit results to
331 * @length: the length of the returned list.
333 * Lists all locks under @dir in effect for @client.
335 * If no locks are in effect, an empty list is returned. If no keys are
336 * writable at all then a list containing @dir is returned.
338 * The returned list will be %NULL-terminated.
340 * Returns: an array of strings, never %NULL.
342 gchar **
343 dconf_client_list_locks (DConfClient *client,
344 const gchar *path,
345 gint *length)
347 g_return_val_if_fail (DCONF_IS_CLIENT (client), NULL);
348 g_return_val_if_fail (dconf_is_path (path, NULL), NULL);
350 return dconf_engine_list_locks (client->engine, path, length);
354 * dconf_client_is_writable:
355 * @client: a #DConfClient
356 * @key: the key to check for writability
358 * Checks if @key is writable (ie: the key has no locks).
360 * This call does not verify that writing to the key will actually be
361 * successful. It only checks that the database is writable and that
362 * there are no locks affecting @key. Other issues (such as a full disk
363 * or an inability to connect to the bus and start the service) may
364 * cause the write to fail.
366 * Returns: %TRUE is @key is writable
368 gboolean
369 dconf_client_is_writable (DConfClient *client,
370 const gchar *key)
372 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
374 return dconf_engine_is_writable (client->engine, key);
378 * dconf_client_write_fast:
379 * @client: a #DConfClient
380 * @key: the key to write to
381 * @value: a #GVariant, the value to write
382 * @error: a pointer to a %NULL #GError, or %NULL
384 * Writes @value to the given @key, or reset @key to its default value.
386 * If @value is %NULL then @key is reset to its default value (which may
387 * be completely unset), otherwise @value becomes the new value.
389 * This call merely queues up the write and returns immediately, without
390 * blocking. The only errors that can be detected or reported at this
391 * point are attempts to write to read-only keys. If the application
392 * exits immediately after this function returns then the queued call
393 * may never be sent; see dconf_client_sync().
395 * A local copy of the written value is kept so that calls to
396 * dconf_client_read() that occur before the service actually makes the
397 * change will return the new value.
399 * If the write is queued then a change signal will be directly emitted.
400 * If this function is being called from the main context of @client
401 * then the signal is emitted before this function returns; otherwise it
402 * is scheduled on the main context.
404 * Returns: %TRUE if the write was queued
406 gboolean
407 dconf_client_write_fast (DConfClient *client,
408 const gchar *key,
409 GVariant *value,
410 GError **error)
412 DConfChangeset *changeset;
413 gboolean success;
415 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
417 changeset = dconf_changeset_new_write (key, value);
418 success = dconf_engine_change_fast (client->engine, changeset, NULL, error);
419 dconf_changeset_unref (changeset);
421 return success;
425 * dconf_client_write_sync:
426 * @client: a #DConfClient
427 * @key: the key to write to
428 * @value: a #GVariant, the value to write
429 * @tag: (out) (allow-none): the tag from this write
430 * @cancellable: a #GCancellable, or %NULL
431 * @error: a pointer to a %NULL #GError, or %NULL
433 * Write @value to the given @key, or reset @key to its default value.
435 * If @value is %NULL then @key is reset to its default value (which may
436 * be completely unset), otherwise @value becomes the new value.
438 * This call blocks until the write is complete. This call will
439 * therefore detect and report all cases of failure. If the modified
440 * key is currently being watched then a signal will be emitted from the
441 * main context of @client (once the signal arrives from the service).
443 * If @tag is non-%NULL then it is set to the unique tag associated with
444 * this write. This is the same tag that will appear in the following
445 * change signal.
447 * Returns: %TRUE on success, else %FALSE with @error set
449 gboolean
450 dconf_client_write_sync (DConfClient *client,
451 const gchar *key,
452 GVariant *value,
453 gchar **tag,
454 GCancellable *cancellable,
455 GError **error)
457 DConfChangeset *changeset;
458 gboolean success;
460 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
462 changeset = dconf_changeset_new_write (key, value);
463 success = dconf_engine_change_sync (client->engine, changeset, tag, error);
464 dconf_changeset_unref (changeset);
466 return success;
470 * dconf_client_change_fast:
471 * @client: a #DConfClient
472 * @changeset: the changeset describing the requested change
473 * @error: a pointer to a %NULL #GError, or %NULL
475 * Performs the change operation described by @changeset.
477 * Once @changeset is passed to this call it can no longer be modified.
479 * This call merely queues up the write and returns immediately, without
480 * blocking. The only errors that can be detected or reported at this
481 * point are attempts to write to read-only keys. If the application
482 * exits immediately after this function returns then the queued call
483 * may never be sent; see dconf_client_sync().
485 * A local copy of the written value is kept so that calls to
486 * dconf_client_read() that occur before the service actually makes the
487 * change will return the new value.
489 * If the write is queued then a change signal will be directly emitted.
490 * If this function is being called from the main context of @client
491 * then the signal is emitted before this function returns; otherwise it
492 * is scheduled on the main context.
494 * Returns: %TRUE if the requested changed was queued
496 gboolean
497 dconf_client_change_fast (DConfClient *client,
498 DConfChangeset *changeset,
499 GError **error)
501 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
503 return dconf_engine_change_fast (client->engine, changeset, NULL, error);
507 * dconf_client_change_sync:
508 * @client: a #DConfClient
509 * @changeset: the changeset describing the requested change
510 * @tag: (out) (allow-none): the tag from this write
511 * @cancellable: a #GCancellable, or %NULL
512 * @error: a pointer to a %NULL #GError, or %NULL
514 * Performs the change operation described by @changeset.
516 * Once @changeset is passed to this call it can no longer be modified.
518 * This call blocks until the change is complete. This call will
519 * therefore detect and report all cases of failure. If any of the
520 * modified keys are currently being watched then a signal will be
521 * emitted from the main context of @client (once the signal arrives
522 * from the service).
524 * If @tag is non-%NULL then it is set to the unique tag associated with
525 * this change. This is the same tag that will appear in the following
526 * change signal. If @changeset makes no changes then @tag may be
527 * non-unique (eg: the empty string may be used for empty changesets).
529 * Returns: %TRUE on success, else %FALSE with @error set
531 gboolean
532 dconf_client_change_sync (DConfClient *client,
533 DConfChangeset *changeset,
534 gchar **tag,
535 GCancellable *cancellable,
536 GError **error)
538 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
540 return dconf_engine_change_sync (client->engine, changeset, tag, error);
544 * dconf_client_watch_fast:
545 * @client: a #DConfClient
546 * @path: a path to watch
548 * Requests change notifications for @path.
550 * If @path is a key then the single key is monitored. If @path is a
551 * dir then all keys under the dir are monitored.
553 * This function queues the watch request with D-Bus and returns
554 * immediately. There is a very slim chance that the dconf database
555 * could change before the watch is actually established. If that is
556 * the case then a synthetic change signal will be emitted.
558 * Errors are silently ignored.
560 void
561 dconf_client_watch_fast (DConfClient *client,
562 const gchar *path)
564 g_return_if_fail (DCONF_IS_CLIENT (client));
566 dconf_engine_watch_fast (client->engine, path);
570 * dconf_client_watch_sync:
571 * @client: a #DConfClient
572 * @path: a path to watch
574 * Requests change notifications for @path.
576 * If @path is a key then the single key is monitored. If @path is a
577 * dir then all keys under the dir are monitored.
579 * This function submits each of the various watch requests that are
580 * required to monitor a key and waits until each of them returns. By
581 * the time this function returns, the watch has been established.
583 * Errors are silently ignored.
585 void
586 dconf_client_watch_sync (DConfClient *client,
587 const gchar *path)
589 g_return_if_fail (DCONF_IS_CLIENT (client));
591 dconf_engine_watch_sync (client->engine, path);
595 * dconf_client_unwatch_fast:
596 * @client: a #DConfClient
597 * @path: a path previously watched
599 * Cancels the effect of a previous call to dconf_client_watch_fast().
601 * This call returns immediately.
603 * It is still possible that change signals are received after this call
604 * had returned (watching guarantees notification of changes, but
605 * unwatching does not guarantee no notifications).
607 void
608 dconf_client_unwatch_fast (DConfClient *client,
609 const gchar *path)
611 g_return_if_fail (DCONF_IS_CLIENT (client));
613 dconf_engine_unwatch_fast (client->engine, path);
617 * dconf_client_unwatch_sync:
618 * @client: a #DConfClient
619 * @path: a path previously watched
621 * Cancels the effect of a previous call to dconf_client_watch_sync().
623 * This function submits each of the various unwatch requests and waits
624 * until each of them returns. It is still possible that change signals
625 * are received after this call has returned (watching guarantees
626 * notification of changes, but unwatching does not guarantee no
627 * notifications).
629 void
630 dconf_client_unwatch_sync (DConfClient *client,
631 const gchar *path)
633 g_return_if_fail (DCONF_IS_CLIENT (client));
635 dconf_engine_unwatch_sync (client->engine, path);
639 * dconf_client_sync:
640 * @client: a #DConfClient
642 * Blocks until all outstanding "fast" change or write operations have
643 * been submitted to the service.
645 * Applications should generally call this before exiting on any
646 * #DConfClient that they wrote to.
648 void
649 dconf_client_sync (DConfClient *client)
651 g_return_if_fail (DCONF_IS_CLIENT (client));
653 dconf_engine_sync (client->engine);