diff options
author | Zeeshan Ali (Khattak) <zeeshanak@gnome.org> | 2015-10-06 16:38:56 +0100 |
---|---|---|
committer | Zeeshan Ali (Khattak) <zeeshanak@gnome.org> | 2015-10-09 14:44:41 +0100 |
commit | af336ae4682c6f698474c73a4c19037cdb1cb13d (patch) | |
tree | c4a6b11b4b7be13c6c00cee30786e6a9c5654d84 | |
parent | 7d1289e2147a0bde59f21720c29afadf46032ce9 (diff) | |
download | geoclue-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.c | 254 | ||||
-rw-r--r-- | libgeoclue/gclue-helpers.h | 14 |
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__*/ |