3.12.12
[nijm-empathy.git] / libempathy-gtk / empathy-geoclue-helper.c
blob5cc750db1712b820ed3d846809e9e410acf3b348
1 /*
2 * empathy-geoclue-helper.c
4 * Copyright (C) 2013 Collabora Ltd. <http://www.collabora.co.uk/>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "config.h"
23 #include <gio/gio.h>
25 #include "empathy-geoclue-helper.h"
27 #define DEBUG_FLAG EMPATHY_DEBUG_LOCATION
28 #include "empathy-debug.h"
30 #define GEOCLUE_BUS_NAME "org.freedesktop.GeoClue2"
31 #define EMPATHY_DESKTOP_ID "empathy"
33 /**
34 * SECTION: empathy-geoclue-helper
35 * @title: EmpathyGeoclueHelper
36 * @short_description: TODO
38 * TODO
41 /**
42 * EmpathyGeoclueHelper:
44 * Data structure representing a #EmpathyGeoclueHelper.
46 * Since: UNRELEASED
49 /**
50 * EmpathyGeoclueHelperClass:
52 * The class of a #EmpathyGeoclueHelper.
54 * Since: UNRELEASED
57 static void async_initable_iface_init (GAsyncInitableIface *iface);
59 G_DEFINE_TYPE_WITH_CODE (EmpathyGeoclueHelper, empathy_geoclue_helper,
60 G_TYPE_OBJECT,
61 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init));
63 enum
65 PROP_DISTANCE_THRESHOLD = 1,
66 PROP_LOCATION,
67 N_PROPS
70 enum
72 SIG_LOCATION_CHANGED,
73 LAST_SIGNAL
76 static guint signals[LAST_SIGNAL];
78 struct _EmpathyGeoclueHelperPriv
80 guint distance_threshold;
81 GClueLocation *location;
83 gboolean started;
84 GClueClient *client;
87 static void
88 empathy_geoclue_helper_get_property (GObject *object,
89 guint property_id,
90 GValue *value,
91 GParamSpec *pspec)
93 EmpathyGeoclueHelper *self = EMPATHY_GEOCLUE_HELPER (object);
95 switch (property_id)
97 case PROP_DISTANCE_THRESHOLD:
98 g_value_set_uint (value, self->priv->distance_threshold);
99 break;
100 case PROP_LOCATION:
101 g_value_set_object (value, self->priv->location);
102 break;
103 default:
104 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
105 break;
109 static void
110 empathy_geoclue_helper_set_property (GObject *object,
111 guint property_id,
112 const GValue *value,
113 GParamSpec *pspec)
115 EmpathyGeoclueHelper *self = EMPATHY_GEOCLUE_HELPER (object);
117 switch (property_id)
119 case PROP_DISTANCE_THRESHOLD:
120 self->priv->distance_threshold = g_value_get_uint (value);
121 break;
122 default:
123 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
124 break;
128 static void
129 empathy_geoclue_helper_constructed (GObject *object)
131 //EmpathyGeoclueHelper *self = EMPATHY_GEOCLUE_HELPER (object);
132 void (*chain_up) (GObject *) =
133 ((GObjectClass *) empathy_geoclue_helper_parent_class)->constructed;
135 chain_up (object);
138 static void
139 empathy_geoclue_helper_dispose (GObject *object)
141 EmpathyGeoclueHelper *self = EMPATHY_GEOCLUE_HELPER (object);
142 void (*chain_up) (GObject *) =
143 ((GObjectClass *) empathy_geoclue_helper_parent_class)->dispose;
145 if (self->priv->started)
147 gclue_client_call_stop (self->priv->client, NULL, NULL, NULL);
149 self->priv->started = FALSE;
152 g_clear_object (&self->priv->location);
153 g_clear_object (&self->priv->client);
155 chain_up (object);
158 static void
159 empathy_geoclue_helper_finalize (GObject *object)
161 //EmpathyGeoclueHelper *self = EMPATHY_GEOCLUE_HELPER (object);
162 void (*chain_up) (GObject *) =
163 ((GObjectClass *) empathy_geoclue_helper_parent_class)->finalize;
165 chain_up (object);
168 static void
169 empathy_geoclue_helper_class_init (
170 EmpathyGeoclueHelperClass *klass)
172 GObjectClass *oclass = G_OBJECT_CLASS (klass);
173 GParamSpec *spec;
175 oclass->get_property = empathy_geoclue_helper_get_property;
176 oclass->set_property = empathy_geoclue_helper_set_property;
177 oclass->constructed = empathy_geoclue_helper_constructed;
178 oclass->dispose = empathy_geoclue_helper_dispose;
179 oclass->finalize = empathy_geoclue_helper_finalize;
182 * EmpathyGeoclueHelper:distance-threshold:
184 * TODO
186 * Since: UNRELEASED
188 spec = g_param_spec_uint ("distance-threshold", "distance-threshold",
189 "DistanceThreshold",
190 0, G_MAXUINT32, 0,
191 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
192 g_object_class_install_property (oclass, PROP_DISTANCE_THRESHOLD, spec);
195 * EmpathyGeoclueHelper:location:
197 * TODO
199 * Since: UNRELEASED
201 spec = g_param_spec_object ("location", "location", "GClueLocation",
202 GCLUE_TYPE_LOCATION,
203 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
204 g_object_class_install_property (oclass, PROP_LOCATION, spec);
207 * EmpathyGeoclueHelper::location-changed:
208 * @self: a #EmpathyGeoclueHelper
210 * TODO
212 * Since: UNRELEASED
214 signals[SIG_LOCATION_CHANGED] = g_signal_new ("location-changed",
215 G_OBJECT_CLASS_TYPE (klass),
216 G_SIGNAL_RUN_LAST,
217 0, NULL, NULL, NULL,
218 G_TYPE_NONE,
219 1, GCLUE_TYPE_LOCATION);
221 g_type_class_add_private (klass, sizeof (EmpathyGeoclueHelperPriv));
224 static void
225 empathy_geoclue_helper_init (EmpathyGeoclueHelper *self)
227 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
228 EMPATHY_TYPE_GEOCLUE_HELPER, EmpathyGeoclueHelperPriv);
231 static void
232 location_cb (GObject *source,
233 GAsyncResult *result,
234 gpointer user_data)
236 EmpathyGeoclueHelper *self = user_data;
237 GError *error = NULL;
239 g_clear_object (&self->priv->location);
241 self->priv->location = gclue_location_proxy_new_finish (result, &error);
242 if (self->priv->location == NULL)
244 DEBUG ("Failed to create Location proxy: %s", error->message);
245 g_error_free (error);
248 g_signal_emit (self, signals[SIG_LOCATION_CHANGED], 0, self->priv->location);
250 g_object_notify (G_OBJECT (self), "location");
253 static void
254 location_updated_cb (GClueClient *client,
255 const gchar *old,
256 const gchar *new,
257 EmpathyGeoclueHelper *self)
259 gclue_location_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
260 GEOCLUE_BUS_NAME, new,
261 NULL, location_cb, self);
264 static void
265 client_start_cb (GObject *source,
266 GAsyncResult *result,
267 gpointer user_data)
269 GTask *task = user_data;
270 EmpathyGeoclueHelper *self = g_task_get_source_object (task);
271 GClueClient *client = GCLUE_CLIENT (source);
272 GError *error = NULL;
274 if (!gclue_client_call_start_finish (client, result, &error))
276 DEBUG ("Failed to start Geoclue client: %s", error->message);
277 g_error_free (error);
278 return;
281 self->priv->started = TRUE;
283 g_task_return_boolean (task, TRUE);
284 g_object_unref (task);
287 static void
288 client_cb (GObject *source,
289 GAsyncResult *result,
290 gpointer user_data)
292 GTask *task = user_data;
293 EmpathyGeoclueHelper *self = g_task_get_source_object (task);
294 GError *error = NULL;
296 self->priv->client = gclue_client_proxy_new_for_bus_finish (result, &error);
297 if (self->priv->client == NULL)
299 DEBUG ("Failed to create Geoclue client: %s", error->message);
300 g_task_return_error (task, error);
301 goto out;
304 g_signal_connect_object (self->priv->client, "location-updated",
305 G_CALLBACK (location_updated_cb), self, 0);
307 g_object_set (self->priv->client,
308 "distance-threshold", self->priv->distance_threshold,
309 "desktop-id", EMPATHY_DESKTOP_ID,
310 NULL);
312 g_task_return_boolean (task, TRUE);
314 out:
315 g_object_unref (task);
318 static void
319 get_client_cb (GObject *source,
320 GAsyncResult *result,
321 gpointer user_data)
323 GTask *task = user_data;
324 GError *error = NULL;
325 gchar *path;
327 if (!gclue_manager_call_get_client_finish (GCLUE_MANAGER (source), &path,
328 result, &error))
330 DEBUG ("GetClient failed: %s", error->message);
331 g_task_return_error (task, error);
332 g_object_unref (task);
333 return;
336 gclue_client_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
337 GEOCLUE_BUS_NAME, path, NULL, client_cb, task);
339 g_free (path);
342 static void
343 manager_cb (GObject *source,
344 GAsyncResult *result,
345 gpointer user_data)
347 GTask *task = user_data;
348 GError *error = NULL;
349 GClueManager *mgr;
351 mgr = gclue_manager_proxy_new_for_bus_finish (result, &error);
352 if (mgr == NULL)
354 DEBUG ("Failed to create Geoclue manager: %s", error->message);
355 g_task_return_error (task, error);
356 g_object_unref (task);
357 return;
360 gclue_manager_call_get_client (mgr, NULL, get_client_cb, task);
361 g_object_unref (mgr);
364 void
365 empathy_geoclue_helper_start_async (EmpathyGeoclueHelper *self,
366 GAsyncReadyCallback callback,
367 gpointer user_data)
369 GTask *task;
371 task = g_task_new (self, NULL, callback, user_data);
373 if (self->priv->started)
375 g_task_return_boolean (task, TRUE);
376 g_object_unref (task);
377 return;
380 gclue_client_call_start (self->priv->client, NULL, client_start_cb, task);
383 gboolean
384 empathy_geoclue_helper_start_finish (EmpathyGeoclueHelper *self,
385 GAsyncResult *result,
386 GError **error)
388 g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
390 return g_task_propagate_boolean (G_TASK (result), error);
393 GClueLocation *
394 empathy_geoclue_helper_get_location (EmpathyGeoclueHelper *self)
396 return self->priv->location;
399 static void
400 empathy_geoclue_helper_init_async (GAsyncInitable *initable,
401 gint io_priority,
402 GCancellable *cancellable,
403 GAsyncReadyCallback callback,
404 gpointer user_data)
406 GTask *task;
408 task = g_task_new (initable, cancellable, callback, user_data);
410 gclue_manager_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE,
411 GEOCLUE_BUS_NAME, "/org/freedesktop/GeoClue2/Manager",
412 NULL, manager_cb, task);
415 static gboolean
416 empathy_geoclue_helper_init_finish (GAsyncInitable *initable,
417 GAsyncResult *result,
418 GError **error)
420 g_return_val_if_fail (g_task_is_valid (result, initable), FALSE);
422 return g_task_propagate_boolean (G_TASK (result), error);
425 static void
426 async_initable_iface_init (GAsyncInitableIface *iface)
428 iface->init_async = empathy_geoclue_helper_init_async;
429 iface->init_finish = empathy_geoclue_helper_init_finish;
432 void
433 empathy_geoclue_helper_new_async (guint distance_threshold,
434 GAsyncReadyCallback callback,
435 gpointer user_data)
437 g_async_initable_new_async (EMPATHY_TYPE_GEOCLUE_HELPER,
438 G_PRIORITY_DEFAULT, NULL, callback, user_data,
439 "distance-threshold", distance_threshold,
440 NULL);
443 EmpathyGeoclueHelper *
444 empathy_geoclue_helper_new_finish (GAsyncResult *result,
445 GError **error)
447 GObject *object, *source_object;
449 source_object = g_async_result_get_source_object (result);
451 object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object),
452 result, error);
453 g_object_unref (source_object);
455 if (object != NULL)
456 return EMPATHY_GEOCLUE_HELPER (object);
457 else
458 return NULL;
461 static void
462 new_started_cb (GObject *source,
463 GAsyncResult *result,
464 gpointer user_data)
466 EmpathyGeoclueHelper *self = EMPATHY_GEOCLUE_HELPER (source);
467 GTask *new_started_task = user_data;
468 GError *error = NULL;
470 if (!empathy_geoclue_helper_start_finish (self, result, &error))
472 g_task_return_error (new_started_task, error);
473 g_object_unref (self);
474 goto out;
477 /* pass ownership of self to g_task_return_error */
478 g_task_return_pointer (new_started_task, self, g_object_unref);
480 out:
481 g_object_unref (new_started_task);
484 static void
485 new_started_init_cb (GObject *source,
486 GAsyncResult *result,
487 gpointer user_data)
489 GTask *new_started_task = user_data;
490 EmpathyGeoclueHelper *self;
491 GError *error = NULL;
493 self = empathy_geoclue_helper_new_finish (result, &error);
494 if (self == NULL)
496 g_task_return_error (new_started_task, error);
497 g_object_unref (new_started_task);
498 return;
501 /* Pass owernship of 'self' to new_started_cb */
502 empathy_geoclue_helper_start_async (self, new_started_cb, new_started_task);
505 void
506 empathy_geoclue_helper_new_started_async (guint distance_threshold,
507 GAsyncReadyCallback callback,
508 gpointer user_data)
510 GTask *new_started_task;
512 new_started_task = g_task_new (NULL, NULL, callback, user_data);
514 empathy_geoclue_helper_new_async (distance_threshold, new_started_init_cb,
515 new_started_task);
518 EmpathyGeoclueHelper *
519 empathy_geoclue_helper_new_started_finish (GAsyncResult *result,
520 GError **error)
522 g_return_val_if_fail (g_task_is_valid (result, NULL), NULL);
524 return g_task_propagate_pointer (G_TASK (result), error);