summaryrefslogtreecommitdiff
path: root/libgeoclue/gclue-helpers.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgeoclue/gclue-helpers.c')
-rw-r--r--libgeoclue/gclue-helpers.c221
1 files changed, 205 insertions, 16 deletions
diff --git a/libgeoclue/gclue-helpers.c b/libgeoclue/gclue-helpers.c
index 15ccc5b..bbb3809 100644
--- a/libgeoclue/gclue-helpers.c
+++ b/libgeoclue/gclue-helpers.c
@@ -35,20 +35,29 @@
*/
typedef struct {
- char *desktop_id;
- GClueAccuracyLevel accuracy_level;
+ char *desktop_id;
+ GClueAccuracyLevel accuracy_level;
+ GClueClientProxyCreateFlags flags;
+ GClueManager *manager;
gulong notify_id;
} ClientCreateData;
+typedef struct {
+ GClueManager *manager;
+ char *client_path;
+} ClientDestroyData;
+
static ClientCreateData *
-client_create_data_new (const char *desktop_id,
- GClueAccuracyLevel accuracy_level)
+client_create_data_new (const char *desktop_id,
+ GClueAccuracyLevel accuracy_level,
+ GClueClientProxyCreateFlags flags)
{
ClientCreateData *data = g_slice_new0 (ClientCreateData);
data->desktop_id = g_strdup (desktop_id);
data->accuracy_level = accuracy_level;
+ data->flags = flags;
return data;
}
@@ -56,10 +65,58 @@ client_create_data_new (const char *desktop_id,
static void
client_create_data_free (ClientCreateData *data)
{
+ g_clear_object (&data->manager);
g_free (data->desktop_id);
g_slice_free (ClientCreateData, data);
}
+static ClientDestroyData *
+client_destroy_data_new (GClueManager *manager,
+ const char *client_path)
+{
+ ClientDestroyData *data = g_slice_new0 (ClientDestroyData);
+
+ if (manager)
+ data->manager = g_object_ref (manager);
+ data->client_path = g_strdup (client_path);
+
+ return data;
+}
+
+static void
+on_delete_client_finished (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) error = NULL;
+ ClientDestroyData *data = user_data;
+
+ if (!gclue_manager_call_delete_client_finish (
+ GCLUE_MANAGER (source_object),
+ res,
+ &error)) {
+ g_warning ("GClue: Failed to automatically delete client: %s",
+ error->message);
+ }
+
+ g_clear_object (&data->manager);
+ g_clear_pointer (&data->client_path, g_free);
+ g_slice_free (ClientDestroyData, data);
+}
+
+static void
+on_client_destroyed (gpointer data,
+ GObject *where_the_object_was)
+{
+ ClientDestroyData *destroy_data = data;
+
+ gclue_manager_call_delete_client (destroy_data->manager,
+ destroy_data->client_path,
+ NULL,
+ on_delete_client_finished,
+ destroy_data);
+}
+
static void
on_client_proxy_ready (GObject *source_object,
GAsyncResult *res,
@@ -67,6 +124,7 @@ on_client_proxy_ready (GObject *source_object,
{
GTask *task = G_TASK (user_data);
ClientCreateData *data;
+ ClientDestroyData *destroy;
GClueClient *client;
GError *error = NULL;
@@ -82,6 +140,16 @@ on_client_proxy_ready (GObject *source_object,
gclue_client_set_desktop_id (client, data->desktop_id);
gclue_client_set_requested_accuracy_level (client, data->accuracy_level);
+ if (data->flags & GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE) {
+ destroy = client_destroy_data_new (
+ data->manager,
+ g_dbus_proxy_get_object_path (
+ G_DBUS_PROXY (client)));
+ g_object_weak_ref (G_OBJECT (client),
+ on_client_destroyed,
+ destroy);
+ }
+
g_task_return_pointer (task, client, g_object_unref);
g_object_unref (task);
}
@@ -124,6 +192,7 @@ on_manager_proxy_ready (GObject *source_object,
gpointer user_data)
{
GTask *task = G_TASK (user_data);
+ ClientCreateData *data;
GClueManager *manager;
GError *error = NULL;
@@ -135,12 +204,30 @@ on_manager_proxy_ready (GObject *source_object,
return;
}
+ data = g_task_get_task_data (task);
+ data->manager = g_object_ref (manager);
gclue_manager_call_get_client (manager,
g_task_get_cancellable (task),
on_get_client_ready,
task);
}
+static void
+on_client_proxy_full_finished (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GTask) task = user_data;
+ GClueClient *client;
+ GError *error = NULL;
+
+ client = gclue_client_proxy_create_finish (res, &error);
+ if (!client)
+ g_task_return_error (task, error);
+ else
+ g_task_return_pointer (task, client, g_object_unref);
+}
+
/**
* gclue_client_proxy_create:
* @desktop_id: The desktop file id (the basename of the desktop file).
@@ -150,7 +237,11 @@ on_manager_proxy_ready (GObject *source_object,
* @user_data: User data to pass to @callback.
*
* A utility function to create a #GClueClientProxy without having to deal with
- * a #GClueManager.
+ * a #GClueManager. See also gclue_client_proxy_create_full() which improves
+ * resource management.
+ *
+ * This is identitcal to calling gclue_client_proxy_create_full() without any
+ * flags set.
*
* See #gclue_client_proxy_create_sync() for the synchronous, blocking version
* of this function.
@@ -163,11 +254,102 @@ gclue_client_proxy_create (const char *desktop_id,
gpointer user_data)
{
GTask *task;
+
+ task = g_task_new (NULL, cancellable, callback, user_data);
+
+ gclue_client_proxy_create_full (desktop_id,
+ accuracy_level,
+ GCLUE_CLIENT_PROXY_CREATE_NONE,
+ cancellable,
+ on_client_proxy_full_finished,
+ task);
+}
+
+/**
+ * gclue_client_proxy_create_finish:
+ * @result: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to
+ * gclue_client_proxy_create().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with gclue_client_proxy_create().
+ *
+ * Returns: (transfer full) (type GClueClientProxy): The constructed proxy
+ * object or %NULL if @error is set.
+ */
+GClueClient *
+gclue_client_proxy_create_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+/**
+ * gclue_client_proxy_create_sync:
+ * @desktop_id: The desktop file id (the basename of the desktop file).
+ * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * The synchronous and blocking version of #gclue_client_proxy_create().
+ * See also gclue_client_proxy_create_full_sync() which improves resource
+ * management.
+ *
+ * This function is identical to calling gclue_client_proxy_create_full_sync()
+ * without any flags set.
+ *
+ * Returns: (transfer full) (type GClueClientProxy): The constructed proxy
+ * object or %NULL if @error is set.
+ */
+GClueClient *
+gclue_client_proxy_create_sync (const char *desktop_id,
+ GClueAccuracyLevel accuracy_level,
+ GCancellable *cancellable,
+ GError **error)
+{
+ return gclue_client_proxy_create_full_sync (
+ desktop_id,
+ accuracy_level,
+ GCLUE_CLIENT_PROXY_CREATE_NONE,
+ cancellable,
+ error);
+}
+
+/**
+ * gclue_client_proxy_create_full:
+ * @desktop_id: The desktop file id (the basename of the desktop file).
+ * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel.
+ * @flags: #GClueClientProxyCreateFlags to modify the creation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the results are ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * A utility function to create a #GClueClientProxy without having to deal with
+ * a #GClueManager.
+ *
+ * By setting the #GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE flag you can ensure
+ * that the client will be deleted again from the geoclue service when
+ * it is destroyed. This flag should be used unless you are doing explicit
+ * resource management.
+ *
+ * See #gclue_client_proxy_create_full_sync() for the synchronous, blocking
+ * version of this function.
+ */
+void
+gclue_client_proxy_create_full (const char *desktop_id,
+ GClueAccuracyLevel accuracy_level,
+ GClueClientProxyCreateFlags flags,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
ClientCreateData *data;
task = g_task_new (NULL, cancellable, callback, user_data);
- data = client_create_data_new (desktop_id, accuracy_level);
+ data = client_create_data_new (desktop_id, accuracy_level, flags);
g_task_set_task_data (task,
data,
(GDestroyNotify) client_create_data_free);
@@ -182,19 +364,19 @@ gclue_client_proxy_create (const char *desktop_id,
}
/**
- * gclue_client_proxy_create_finish:
+ * gclue_client_proxy_create_full_finish:
* @result: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to
* gclue_client_proxy_create().
* @error: Return location for error or %NULL.
*
- * Finishes an operation started with gclue_client_proxy_create().
+ * Finishes an operation started with gclue_client_proxy_create_full().
*
* Returns: (transfer full) (type GClueClientProxy): The constructed proxy
* object or %NULL if @error is set.
*/
GClueClient *
-gclue_client_proxy_create_finish (GAsyncResult *result,
- GError **error)
+gclue_client_proxy_create_full_finish (GAsyncResult *result,
+ GError **error)
{
g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
@@ -221,22 +403,29 @@ on_client_proxy_created (GObject *source_object,
}
/**
- * gclue_client_proxy_create_sync:
+ * gclue_client_proxy_create_full_sync:
* @desktop_id: The desktop file id (the basename of the desktop file).
* @accuracy_level: The requested accuracy level as #GClueAccuracyLevel.
+ * @flags: #GClueClientProxyCreateFlags to modify the creation.
* @cancellable: (allow-none): A #GCancellable or %NULL.
* @error: Return location for error or %NULL.
*
- * The synchronous and blocking version of #gclue_client_proxy_create().
+ * The synchronous and blocking version of #gclue_client_proxy_create_full().
+ *
+ * By setting the #GCLUE_CLIENT_PROXY_CREATE_AUTO_DELETE flag you can ensure
+ * that the client will be deleted again from the geoclue service when
+ * it is destroyed. This flag should be used unless you are doing explicit
+ * resource management.
*
* Returns: (transfer full) (type GClueClientProxy): The constructed proxy
* object or %NULL if @error is set.
*/
GClueClient *
-gclue_client_proxy_create_sync (const char *desktop_id,
- GClueAccuracyLevel accuracy_level,
- GCancellable *cancellable,
- GError **error)
+gclue_client_proxy_create_full_sync (const char *desktop_id,
+ GClueAccuracyLevel accuracy_level,
+ GClueClientProxyCreateFlags flags,
+ GCancellable *cancellable,
+ GError **error)
{
GClueClient *client;
ClientCreateSyncData *data = g_slice_new0 (ClientCreateSyncData);