Declare libdconf_service as a dependency
[dconf.git] / client / dconf-client.c
blobc315693efe5696b10d503677bef79c8facfe3dca
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 SIGNAL_WRITABILITY_CHANGED,
67 N_SIGNALS
69 static guint dconf_client_signals[N_SIGNALS];
71 static void
72 dconf_client_finalize (GObject *object)
74 DConfClient *client = DCONF_CLIENT (object);
76 dconf_engine_unref (client->engine);
77 g_main_context_unref (client->context);
79 G_OBJECT_CLASS (dconf_client_parent_class)
80 ->finalize (object);
83 static void
84 dconf_client_init (DConfClient *client)
88 static void
89 dconf_client_class_init (DConfClientClass *class)
91 GObjectClass *object_class = G_OBJECT_CLASS (class);
93 object_class->finalize = dconf_client_finalize;
95 /**
96 * DConfClient::changed:
97 * @client: the #DConfClient reporting the change
98 * @prefix: the prefix under which the changes happened
99 * @changes: the list of paths that were changed, relative to @prefix
100 * @tag: the tag for the change, if it originated from the service
102 * This signal is emitted when the #DConfClient has a possible change
103 * to report. The signal is an indication that a change may have
104 * occurred; it's possible that the keys will still have the same value
105 * as before.
107 * To ensure that you receive notification about changes to paths that
108 * you are interested in you must call dconf_client_watch_fast() or
109 * dconf_client_watch_sync(). You may still receive notifications for
110 * paths that you did not explicitly watch.
112 * @prefix will be an absolute dconf path; see dconf_is_path().
113 * @changes is a %NULL-terminated array of dconf rel paths; see
114 * dconf_is_rel_path().
116 * @tag is an opaque tag string, or %NULL. The only thing you should
117 * do with @tag is to compare it to tag values returned by
118 * dconf_client_write_sync() or dconf_client_change_sync().
120 * The number of changes being reported is equal to the length of
121 * @changes. Appending each item in @changes to @prefix will give the
122 * absolute path of each changed item.
124 * If a single key has changed then @prefix will be equal to the key
125 * and @changes will contain a single item: the empty string.
127 * If a single dir has changed (indicating that any key under the dir
128 * may have changed) then @prefix will be equal to the dir and
129 * @changes will contain a single empty string.
131 * If more than one change is being reported then @changes will have
132 * more than one item.
134 dconf_client_signals[SIGNAL_CHANGED] = g_signal_new ("changed", DCONF_TYPE_CLIENT, G_SIGNAL_RUN_LAST,
135 0, NULL, NULL, NULL, G_TYPE_NONE, 3,
136 G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
137 G_TYPE_STRV | G_SIGNAL_TYPE_STATIC_SCOPE,
138 G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE);
141 * DConfClient::writability-changed:
142 * @client: the #DConfClient reporting the change
143 * @path: the dir or key that changed
145 * Signal emitted when writability for a key (or all keys in a dir) changes.
146 * It will be immediately followed by #DConfClient::changed signal for
147 * the path.
149 dconf_client_signals[SIGNAL_WRITABILITY_CHANGED] = g_signal_new ("writability-changed", DCONF_TYPE_CLIENT,
150 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
151 G_TYPE_NONE, 1,
152 G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE);
155 typedef struct
157 DConfClient *client;
158 gchar *prefix;
159 gchar **changes;
160 gchar *tag;
161 gboolean is_writability;
162 } DConfClientChange;
164 static gboolean
165 dconf_client_dispatch_change_signal (gpointer user_data)
167 DConfClientChange *change = user_data;
169 if (change->is_writability)
171 /* We know that the engine does it this way... */
172 g_assert (change->changes[0][0] == '\0' && change->changes[1] == NULL);
174 g_signal_emit (change->client,
175 dconf_client_signals[SIGNAL_WRITABILITY_CHANGED], 0,
176 change->prefix);
179 g_signal_emit (change->client, dconf_client_signals[SIGNAL_CHANGED], 0,
180 change->prefix, change->changes, change->tag);
182 g_object_unref (change->client);
183 g_free (change->prefix);
184 g_strfreev (change->changes);
185 g_free (change->tag);
186 g_slice_free (DConfClientChange, change);
188 return G_SOURCE_REMOVE;
191 void
192 dconf_engine_change_notify (DConfEngine *engine,
193 const gchar *prefix,
194 const gchar * const *changes,
195 const gchar * tag,
196 gboolean is_writability,
197 gpointer origin_tag,
198 gpointer user_data)
200 GWeakRef *weak_ref = user_data;
201 DConfClientChange *change;
202 DConfClient *client;
204 client = g_weak_ref_get (weak_ref);
206 if (client == NULL)
207 return;
209 g_return_if_fail (DCONF_IS_CLIENT (client));
211 change = g_slice_new (DConfClientChange);
212 change->client = client;
213 change->prefix = g_strdup (prefix);
214 change->changes = g_strdupv ((gchar **) changes);
215 change->tag = g_strdup (tag);
216 change->is_writability = is_writability;
218 g_main_context_invoke (client->context, dconf_client_dispatch_change_signal, change);
221 static void
222 dconf_client_free_weak_ref (gpointer data)
224 GWeakRef *weak_ref = data;
226 g_weak_ref_clear (weak_ref);
227 g_slice_free (GWeakRef, weak_ref);
231 * dconf_client_new:
233 * Creates a new #DConfClient.
235 * Returns: (transfer full): a new #DConfClient
237 DConfClient *
238 dconf_client_new (void)
240 DConfClient *client;
241 GWeakRef *weak_ref;
243 client = g_object_new (DCONF_TYPE_CLIENT, NULL);
244 weak_ref = g_slice_new (GWeakRef);
245 g_weak_ref_init (weak_ref, client);
246 client->engine = dconf_engine_new (NULL, weak_ref, dconf_client_free_weak_ref);
247 client->context = g_main_context_ref_thread_default ();
249 return client;
253 * dconf_client_read:
254 * @client: a #DConfClient
255 * @key: the key to read the value of
257 * Reads the current value of @key.
259 * If @key exists, its value is returned. Otherwise, %NULL is returned.
261 * If there are outstanding "fast" changes in progress they may affect
262 * the result of this call.
264 * Returns: (transfer full) (nullable): a #GVariant, or %NULL
266 GVariant *
267 dconf_client_read (DConfClient *client,
268 const gchar *key)
270 g_return_val_if_fail (DCONF_IS_CLIENT (client), NULL);
272 return dconf_engine_read (client->engine, DCONF_READ_FLAGS_NONE, NULL, key);
276 * DConfReadFlags:
277 * @DCONF_READ_FLAGS_NONE: no flags
278 * @DCONF_READ_DEFAULT_VALUE: read the default value, ignoring any
279 * values in writable databases or any queued changes. This is
280 * effectively equivalent to asking what value would be read after a
281 * reset was written for the key in question.
282 * @DCONF_READ_USER_VALUE: read the user value, ignoring any system
283 * databases, including ignoring locks. It is even possible to read
284 * "invisible" values in the user database in this way, which would
285 * have normally been ignored because of locks.
287 * Since: 0.26
291 * dconf_client_read_full:
292 * @client: a #DConfClient
293 * @key: the key to read the default value of
294 * @flags: #DConfReadFlags
295 * @read_through: a #GQueue of #DConfChangeset
297 * Reads the current value of @key.
299 * If @flags contains %DCONF_READ_USER_VALUE then only the user value
300 * will be read. Locks are ignored, which means that it is possible to
301 * use this API to read "invisible" user values which are hidden by
302 * system locks.
304 * If @flags contains %DCONF_READ_DEFAULT_VALUE then only non-user
305 * values will be read. The result will be exactly equivalent to the
306 * value that would be read if the current value of the key were to be
307 * reset.
309 * Flags may not contain both %DCONF_READ_USER_VALUE and
310 * %DCONF_READ_DEFAULT_VALUE.
312 * If @read_through is non-%NULL, %DCONF_READ_DEFAULT_VALUE is not
313 * given then @read_through is checked for the key in question, subject
314 * to the restriction that the key in question is writable. This
315 * effectively answers the question of "what would happen if these
316 * changes were committed".
318 * If there are outstanding "fast" changes in progress they may affect
319 * the result of this call.
321 * If @flags is %DCONF_READ_FLAGS_NONE and @read_through is %NULL then
322 * this call is exactly equivalent to dconf_client_read().
324 * Returns: (transfer full) (nullable): a #GVariant, or %NULL
326 * Since: 0.26
328 GVariant *
329 dconf_client_read_full (DConfClient *client,
330 const gchar *key,
331 DConfReadFlags flags,
332 const GQueue *read_through)
334 g_return_val_if_fail (DCONF_IS_CLIENT (client), NULL);
336 return dconf_engine_read (client->engine, flags, read_through, key);
340 * dconf_client_list:
341 * @client: a #DConfClient
342 * @dir: the dir to list the contents of
343 * @length: the length of the returned list
345 * Gets the list of all dirs and keys immediately under @dir.
347 * If @length is non-%NULL then it will be set to the length of the
348 * returned array. In any case, the array is %NULL-terminated.
350 * IF there are outstanding "fast" changes in progress then this call
351 * may return inaccurate results with respect to those outstanding
352 * changes.
354 * Returns: (transfer full) (not nullable): an array of strings, never %NULL.
356 gchar **
357 dconf_client_list (DConfClient *client,
358 const gchar *dir,
359 gint *length)
361 g_return_val_if_fail (DCONF_IS_CLIENT (client), NULL);
363 return dconf_engine_list (client->engine, dir, length);
367 * dconf_client_list_locks:
368 * @client: a #DConfClient
369 * @dir: the dir to limit results to
370 * @length: the length of the returned list.
372 * Lists all locks under @dir in effect for @client.
374 * If no locks are in effect, an empty list is returned. If no keys are
375 * writable at all then a list containing @dir is returned.
377 * The returned list will be %NULL-terminated.
379 * Returns: (transfer full) (not nullable): an array of strings, never %NULL.
381 * Since: 0.26
383 gchar **
384 dconf_client_list_locks (DConfClient *client,
385 const gchar *dir,
386 gint *length)
388 g_return_val_if_fail (DCONF_IS_CLIENT (client), NULL);
389 g_return_val_if_fail (dconf_is_dir (dir, NULL), NULL);
391 return dconf_engine_list_locks (client->engine, dir, length);
395 * dconf_client_is_writable:
396 * @client: a #DConfClient
397 * @key: the key to check for writability
399 * Checks if @key is writable (ie: the key has no locks).
401 * This call does not verify that writing to the key will actually be
402 * successful. It only checks that the database is writable and that
403 * there are no locks affecting @key. Other issues (such as a full disk
404 * or an inability to connect to the bus and start the service) may
405 * cause the write to fail.
407 * Returns: %TRUE if @key is writable
409 gboolean
410 dconf_client_is_writable (DConfClient *client,
411 const gchar *key)
413 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
415 return dconf_engine_is_writable (client->engine, key);
419 * dconf_client_write_fast:
420 * @client: a #DConfClient
421 * @key: the key to write to
422 * @value: a #GVariant, the value to write. If it has a floating reference it's
423 * consumed.
424 * @error: a pointer to a %NULL #GError, or %NULL
426 * Writes @value to the given @key, or reset @key to its default value.
428 * If @value is %NULL then @key is reset to its default value (which may
429 * be completely unset), otherwise @value becomes the new value.
431 * This call merely queues up the write and returns immediately, without
432 * blocking. The only errors that can be detected or reported at this
433 * point are attempts to write to read-only keys. If the application
434 * exits immediately after this function returns then the queued call
435 * may never be sent; see dconf_client_sync().
437 * A local copy of the written value is kept so that calls to
438 * dconf_client_read() that occur before the service actually makes the
439 * change will return the new value.
441 * If the write is queued then a change signal will be directly emitted.
442 * If this function is being called from the main context of @client
443 * then the signal is emitted before this function returns; otherwise it
444 * is scheduled on the main context.
446 * Returns: %TRUE if the write was queued
448 gboolean
449 dconf_client_write_fast (DConfClient *client,
450 const gchar *key,
451 GVariant *value,
452 GError **error)
454 DConfChangeset *changeset;
455 gboolean success;
457 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
459 changeset = dconf_changeset_new_write (key, value);
460 success = dconf_engine_change_fast (client->engine, changeset, NULL, error);
461 dconf_changeset_unref (changeset);
463 return success;
467 * dconf_client_write_sync:
468 * @client: a #DConfClient
469 * @key: the key to write to
470 * @value: a #GVariant, the value to write. If it has a floating reference it's
471 * consumed.
472 * @tag: (out) (optional) (not nullable) (transfer full): the tag from this write
473 * @cancellable: a #GCancellable, or %NULL
474 * @error: a pointer to a %NULL #GError, or %NULL
476 * Write @value to the given @key, or reset @key to its default value.
478 * If @value is %NULL then @key is reset to its default value (which may
479 * be completely unset), otherwise @value becomes the new value.
481 * This call blocks until the write is complete. This call will
482 * therefore detect and report all cases of failure. If the modified
483 * key is currently being watched then a signal will be emitted from the
484 * main context of @client (once the signal arrives from the service).
486 * If @tag is non-%NULL then it is set to the unique tag associated with
487 * this write. This is the same tag that will appear in the following
488 * change signal.
490 * Returns: %TRUE on success, else %FALSE with @error set
492 gboolean
493 dconf_client_write_sync (DConfClient *client,
494 const gchar *key,
495 GVariant *value,
496 gchar **tag,
497 GCancellable *cancellable,
498 GError **error)
500 DConfChangeset *changeset;
501 gboolean success;
503 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
505 changeset = dconf_changeset_new_write (key, value);
506 success = dconf_engine_change_sync (client->engine, changeset, tag, error);
507 dconf_changeset_unref (changeset);
509 return success;
513 * dconf_client_change_fast:
514 * @client: a #DConfClient
515 * @changeset: the changeset describing the requested change
516 * @error: a pointer to a %NULL #GError, or %NULL
518 * Performs the change operation described by @changeset.
520 * Once @changeset is passed to this call it can no longer be modified.
522 * This call merely queues up the write and returns immediately, without
523 * blocking. The only errors that can be detected or reported at this
524 * point are attempts to write to read-only keys. If the application
525 * exits immediately after this function returns then the queued call
526 * may never be sent; see dconf_client_sync().
528 * A local copy of the written value is kept so that calls to
529 * dconf_client_read() that occur before the service actually makes the
530 * change will return the new value.
532 * If the write is queued then a change signal will be directly emitted.
533 * If this function is being called from the main context of @client
534 * then the signal is emitted before this function returns; otherwise it
535 * is scheduled on the main context.
537 * Returns: %TRUE if the requested changed was queued
539 gboolean
540 dconf_client_change_fast (DConfClient *client,
541 DConfChangeset *changeset,
542 GError **error)
544 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
546 return dconf_engine_change_fast (client->engine, changeset, NULL, error);
550 * dconf_client_change_sync:
551 * @client: a #DConfClient
552 * @changeset: the changeset describing the requested change
553 * @tag: (out) (optional) (not nullable) (transfer full): the tag from this write
554 * @cancellable: a #GCancellable, or %NULL
555 * @error: a pointer to a %NULL #GError, or %NULL
557 * Performs the change operation described by @changeset.
559 * Once @changeset is passed to this call it can no longer be modified.
561 * This call blocks until the change is complete. This call will
562 * therefore detect and report all cases of failure. If any of the
563 * modified keys are currently being watched then a signal will be
564 * emitted from the main context of @client (once the signal arrives
565 * from the service).
567 * If @tag is non-%NULL then it is set to the unique tag associated with
568 * this change. This is the same tag that will appear in the following
569 * change signal. If @changeset makes no changes then @tag may be
570 * non-unique (eg: the empty string may be used for empty changesets).
572 * Returns: %TRUE on success, else %FALSE with @error set
574 gboolean
575 dconf_client_change_sync (DConfClient *client,
576 DConfChangeset *changeset,
577 gchar **tag,
578 GCancellable *cancellable,
579 GError **error)
581 g_return_val_if_fail (DCONF_IS_CLIENT (client), FALSE);
583 return dconf_engine_change_sync (client->engine, changeset, tag, error);
587 * dconf_client_watch_fast:
588 * @client: a #DConfClient
589 * @path: a path to watch
591 * Requests change notifications for @path.
593 * If @path is a key then the single key is monitored. If @path is a
594 * dir then all keys under the dir are monitored.
596 * This function queues the watch request with D-Bus and returns
597 * immediately. There is a very slim chance that the dconf database
598 * could change before the watch is actually established. If that is
599 * the case then a synthetic change signal will be emitted.
601 * Errors are silently ignored.
603 void
604 dconf_client_watch_fast (DConfClient *client,
605 const gchar *path)
607 g_return_if_fail (DCONF_IS_CLIENT (client));
609 dconf_engine_watch_fast (client->engine, path);
613 * dconf_client_watch_sync:
614 * @client: a #DConfClient
615 * @path: a path to watch
617 * Requests change notifications for @path.
619 * If @path is a key then the single key is monitored. If @path is a
620 * dir then all keys under the dir are monitored.
622 * This function submits each of the various watch requests that are
623 * required to monitor a key and waits until each of them returns. By
624 * the time this function returns, the watch has been established.
626 * Errors are silently ignored.
628 void
629 dconf_client_watch_sync (DConfClient *client,
630 const gchar *path)
632 g_return_if_fail (DCONF_IS_CLIENT (client));
634 dconf_engine_watch_sync (client->engine, path);
638 * dconf_client_unwatch_fast:
639 * @client: a #DConfClient
640 * @path: a path previously watched
642 * Cancels the effect of a previous call to dconf_client_watch_fast().
644 * This call returns immediately.
646 * It is still possible that change signals are received after this call
647 * had returned (watching guarantees notification of changes, but
648 * unwatching does not guarantee no notifications).
650 void
651 dconf_client_unwatch_fast (DConfClient *client,
652 const gchar *path)
654 g_return_if_fail (DCONF_IS_CLIENT (client));
656 dconf_engine_unwatch_fast (client->engine, path);
660 * dconf_client_unwatch_sync:
661 * @client: a #DConfClient
662 * @path: a path previously watched
664 * Cancels the effect of a previous call to dconf_client_watch_sync().
666 * This function submits each of the various unwatch requests and waits
667 * until each of them returns. It is still possible that change signals
668 * are received after this call has returned (watching guarantees
669 * notification of changes, but unwatching does not guarantee no
670 * notifications).
672 void
673 dconf_client_unwatch_sync (DConfClient *client,
674 const gchar *path)
676 g_return_if_fail (DCONF_IS_CLIENT (client));
678 dconf_engine_unwatch_sync (client->engine, path);
682 * dconf_client_sync:
683 * @client: a #DConfClient
685 * Blocks until all outstanding "fast" change or write operations have
686 * been submitted to the service.
688 * Applications should generally call this before exiting on any
689 * #DConfClient that they wrote to.
691 void
692 dconf_client_sync (DConfClient *client)
694 g_return_if_fail (DCONF_IS_CLIENT (client));
696 dconf_engine_sync (client->engine);