summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZeeshan Ali (Khattak) <zeeshanak@gnome.org>2015-10-06 16:38:56 +0100
committerZeeshan Ali (Khattak) <zeeshanak@gnome.org>2015-10-09 14:44:41 +0100
commitaf336ae4682c6f698474c73a4c19037cdb1cb13d (patch)
treec4a6b11b4b7be13c6c00cee30786e6a9c5654d84
parent7d1289e2147a0bde59f21720c29afadf46032ce9 (diff)
downloadgeoclue-af336ae4682c6f698474c73a4c19037cdb1cb13d.tar.gz
lib: Add helper API for quickly fetching location
Add API that makes it dead simple to fetch the location. https://bugs.freedesktop.org/show_bug.cgi?id=68658
-rw-r--r--libgeoclue/gclue-helpers.c254
-rw-r--r--libgeoclue/gclue-helpers.h14
2 files changed, 268 insertions, 0 deletions
diff --git a/libgeoclue/gclue-helpers.c b/libgeoclue/gclue-helpers.c
index be30864..3d52715 100644
--- a/libgeoclue/gclue-helpers.c
+++ b/libgeoclue/gclue-helpers.c
@@ -257,3 +257,257 @@ gclue_client_proxy_create_sync (const char *desktop_id,
return client;
}
+
+typedef struct {
+ GClueClient *client;
+
+ gulong notify_id;
+} FetchLocationData;
+
+static void
+fetch_location_data_free (FetchLocationData *data)
+{
+ g_clear_object (&data->client);
+ g_slice_free (FetchLocationData, data);
+}
+
+static void
+on_location_proxy_ready (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GClueLocation *location;
+ GTask *task = G_TASK (user_data);
+ GError *error = NULL;
+
+ location = gclue_location_proxy_new_for_bus_finish (res, &error);
+ if (error != NULL) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+
+ return;
+ }
+
+ g_task_return_pointer (task, location, g_object_unref);
+ g_object_unref (task);
+}
+
+static void
+on_location_updated (GClueClient *client,
+ const char *old_location,
+ const char *new_location,
+ gpointer user_data)
+{
+ GTask *task = G_TASK (user_data);
+ FetchLocationData *data;
+
+ if (new_location == NULL || g_strcmp0 (new_location, "/") == 0)
+ return;
+
+ data = g_task_get_task_data (task);
+ g_signal_handler_disconnect (client, data->notify_id);
+
+ gclue_location_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
+ G_DBUS_PROXY_FLAGS_NONE,
+ BUS_NAME,
+ new_location,
+ g_task_get_cancellable (task),
+ on_location_proxy_ready,
+ task);
+}
+
+static void
+on_client_started (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GTask *task = G_TASK (user_data);
+ GClueClient *client = GCLUE_CLIENT (source_object);
+ GError *error = NULL;
+
+ gclue_client_call_start_finish (client, res, &error);
+ if (error != NULL) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ }
+}
+
+static void
+on_client_created (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GTask *task = G_TASK (user_data);
+ FetchLocationData *data;
+ GClueClient *client;
+ GError *error = NULL;
+
+ client = gclue_client_proxy_create_finish (res, &error);
+ if (error != NULL) {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+
+ return;
+ }
+
+ data = g_task_get_task_data (task);
+
+ data->client = client; /* Take ref */
+ data->notify_id =
+ g_signal_connect (client,
+ "location-updated",
+ G_CALLBACK (on_location_updated),
+ task);
+
+ gclue_client_call_start (client,
+ g_task_get_cancellable (task),
+ on_client_started,
+ task);
+}
+
+/**
+ * gclue_fetch_location:
+ * @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.
+ * @callback: A #GAsyncReadyCallback to call when the results are ready.
+ * @user_data: User data to pass to @callback.
+ *
+ * A utility function that takes care of the typical steps of creating a
+ * #GClueClientProxy instance, starting it, waiting till we have a location fix
+ * and then creating a #GClueLocation instance for it. Use
+ * #gclue_fetch_location_finish() to get the #GClueLocation and (optionally) the
+ * #GClueClient instances created.
+ *
+ * While most applications will find this function very useful, it is most
+ * useful for applications that simply want to get the current location as
+ * quickly as possible and do not care about accuracy (much).
+ *
+ * See #gclue_fetch_location_sync() for the synchronous, blocking version
+ * of this function.
+ */
+void
+gclue_fetch_location (const char *desktop_id,
+ GClueAccuracyLevel accuracy_level,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ GTask *task;
+ FetchLocationData *data;
+
+ task = g_task_new (NULL,
+ cancellable,
+ callback,
+ user_data);
+ data = g_slice_new0 (FetchLocationData);
+ g_task_set_task_data (task,
+ data,
+ (GDestroyNotify) fetch_location_data_free);
+
+ gclue_client_proxy_create (desktop_id,
+ accuracy_level,
+ cancellable,
+ on_client_created,
+ task);
+}
+
+/**
+ * gclue_fetch_location_finish:
+ * @client: (transfer full) (allow-none): Return location for #GClueClient or
+ * %NULL.
+ * @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_fetch_location(). Use @client
+ * parameter to get created and started client. You can then connect to either
+ * #GClueClient::location-updated signal or notify signal for
+ * #GClueClient:location property on the provided client instance to be notified
+ * of location updates.
+ *
+ * Returns: (transfer full) (type GClueLocation): The fetched location object
+ * or %NULL if @error is set.
+ */
+GClueLocation *
+gclue_fetch_location_finish (GClueClient **client,
+ GAsyncResult *result,
+ GError **error)
+{
+ GTask *task;
+ FetchLocationData *data;
+
+ g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
+
+ task = G_TASK (result);
+ data = g_task_get_task_data (task);
+
+ if (client != NULL)
+ *client = g_object_ref (data->client);
+
+ return g_task_propagate_pointer (task, error);
+}
+
+typedef struct {
+ GClueLocation *location;
+ GClueClient **client;
+ GError **error;
+
+ GMainLoop *main_loop;
+} FetchLocationSyncData;
+
+static void
+on_fetch_location (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ FetchLocationSyncData *data = (FetchLocationSyncData *) user_data;
+
+ data->location = gclue_fetch_location_finish (data->client,
+ res,
+ data->error);
+
+ g_main_loop_quit (data->main_loop);
+}
+
+/**
+ * gclue_fetch_location_sync:
+ * @desktop_id: The desktop file id (the basename of the desktop file).
+ * @accuracy_level: The requested accuracy level as #GClueAccuracyLevel.
+ * @client: (transfer full) (allow-none): Return location for #GClueClient or
+ * %NULL.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * The synchronous and blocking version of #gclue_fetch_location().
+ *
+ * Returns: (transfer full) (type GClueLocation): The fetched location object
+ * or %NULL if @error is set.
+ */
+GClueLocation *
+gclue_fetch_location_sync (const char *desktop_id,
+ GClueAccuracyLevel accuracy_level,
+ GClueClient **client,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GClueLocation *location;
+ FetchLocationSyncData *data = g_slice_new0 (FetchLocationSyncData);
+
+ data->client = client;
+ data->error = error;
+ data->main_loop = g_main_loop_new (NULL, FALSE);
+ gclue_fetch_location (desktop_id,
+ accuracy_level,
+ cancellable,
+ on_fetch_location,
+ data);
+
+ g_main_loop_run (data->main_loop);
+ g_main_loop_unref (data->main_loop);
+
+ location = data->location;
+ g_slice_free (FetchLocationSyncData, data);
+
+ return location;
+}
diff --git a/libgeoclue/gclue-helpers.h b/libgeoclue/gclue-helpers.h
index 86c172f..fcbe6ff 100644
--- a/libgeoclue/gclue-helpers.h
+++ b/libgeoclue/gclue-helpers.h
@@ -42,6 +42,20 @@ GClueClient * gclue_client_proxy_create_sync (const char *desktop_id
GCancellable *cancellable,
GError **error);
+void gclue_fetch_location (const char *desktop_id,
+ GClueAccuracyLevel accuracy_level,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+GClueLocation * gclue_fetch_location_finish (GClueClient **client,
+ GAsyncResult *result,
+ GError **error);
+GClueLocation * gclue_fetch_location_sync (const char *desktop_id,
+ GClueAccuracyLevel accuracy_level,
+ GClueClient **client,
+ GCancellable *cancellable,
+ GError **error);
+
G_END_DECLS
#endif /* #ifndef __GCLUE_HELPERS_H__*/