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
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"
34 * SECTION: empathy-geoclue-helper
35 * @title: EmpathyGeoclueHelper
36 * @short_description: TODO
42 * EmpathyGeoclueHelper:
44 * Data structure representing a #EmpathyGeoclueHelper.
50 * EmpathyGeoclueHelperClass:
52 * The class of a #EmpathyGeoclueHelper.
57 static void async_initable_iface_init (GAsyncInitableIface
*iface
);
59 G_DEFINE_TYPE_WITH_CODE (EmpathyGeoclueHelper
, empathy_geoclue_helper
,
61 G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE
, async_initable_iface_init
));
65 PROP_DISTANCE_THRESHOLD
= 1,
76 static guint signals
[LAST_SIGNAL
];
78 struct _EmpathyGeoclueHelperPriv
80 guint distance_threshold
;
81 GClueLocation
*location
;
88 empathy_geoclue_helper_get_property (GObject
*object
,
93 EmpathyGeoclueHelper
*self
= EMPATHY_GEOCLUE_HELPER (object
);
97 case PROP_DISTANCE_THRESHOLD
:
98 g_value_set_uint (value
, self
->priv
->distance_threshold
);
101 g_value_set_object (value
, self
->priv
->location
);
104 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
110 empathy_geoclue_helper_set_property (GObject
*object
,
115 EmpathyGeoclueHelper
*self
= EMPATHY_GEOCLUE_HELPER (object
);
119 case PROP_DISTANCE_THRESHOLD
:
120 self
->priv
->distance_threshold
= g_value_get_uint (value
);
123 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, property_id
, pspec
);
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
;
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
);
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
;
169 empathy_geoclue_helper_class_init (
170 EmpathyGeoclueHelperClass
*klass
)
172 GObjectClass
*oclass
= G_OBJECT_CLASS (klass
);
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:
188 spec
= g_param_spec_uint ("distance-threshold", "distance-threshold",
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:
201 spec
= g_param_spec_object ("location", "location", "GClueLocation",
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
214 signals
[SIG_LOCATION_CHANGED
] = g_signal_new ("location-changed",
215 G_OBJECT_CLASS_TYPE (klass
),
219 1, GCLUE_TYPE_LOCATION
);
221 g_type_class_add_private (klass
, sizeof (EmpathyGeoclueHelperPriv
));
225 empathy_geoclue_helper_init (EmpathyGeoclueHelper
*self
)
227 self
->priv
= G_TYPE_INSTANCE_GET_PRIVATE (self
,
228 EMPATHY_TYPE_GEOCLUE_HELPER
, EmpathyGeoclueHelperPriv
);
232 location_cb (GObject
*source
,
233 GAsyncResult
*result
,
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");
254 location_updated_cb (GClueClient
*client
,
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
);
265 client_start_cb (GObject
*source
,
266 GAsyncResult
*result
,
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
);
281 self
->priv
->started
= TRUE
;
283 g_task_return_boolean (task
, TRUE
);
284 g_object_unref (task
);
288 client_cb (GObject
*source
,
289 GAsyncResult
*result
,
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
);
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
,
312 g_task_return_boolean (task
, TRUE
);
315 g_object_unref (task
);
319 get_client_cb (GObject
*source
,
320 GAsyncResult
*result
,
323 GTask
*task
= user_data
;
324 GError
*error
= NULL
;
327 if (!gclue_manager_call_get_client_finish (GCLUE_MANAGER (source
), &path
,
330 DEBUG ("GetClient failed: %s", error
->message
);
331 g_task_return_error (task
, error
);
332 g_object_unref (task
);
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
);
343 manager_cb (GObject
*source
,
344 GAsyncResult
*result
,
347 GTask
*task
= user_data
;
348 GError
*error
= NULL
;
351 mgr
= gclue_manager_proxy_new_for_bus_finish (result
, &error
);
354 DEBUG ("Failed to create Geoclue manager: %s", error
->message
);
355 g_task_return_error (task
, error
);
356 g_object_unref (task
);
360 gclue_manager_call_get_client (mgr
, NULL
, get_client_cb
, task
);
361 g_object_unref (mgr
);
365 empathy_geoclue_helper_start_async (EmpathyGeoclueHelper
*self
,
366 GAsyncReadyCallback callback
,
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
);
380 gclue_client_call_start (self
->priv
->client
, NULL
, client_start_cb
, task
);
384 empathy_geoclue_helper_start_finish (EmpathyGeoclueHelper
*self
,
385 GAsyncResult
*result
,
388 g_return_val_if_fail (g_task_is_valid (result
, self
), FALSE
);
390 return g_task_propagate_boolean (G_TASK (result
), error
);
394 empathy_geoclue_helper_get_location (EmpathyGeoclueHelper
*self
)
396 return self
->priv
->location
;
400 empathy_geoclue_helper_init_async (GAsyncInitable
*initable
,
402 GCancellable
*cancellable
,
403 GAsyncReadyCallback callback
,
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
);
416 empathy_geoclue_helper_init_finish (GAsyncInitable
*initable
,
417 GAsyncResult
*result
,
420 g_return_val_if_fail (g_task_is_valid (result
, initable
), FALSE
);
422 return g_task_propagate_boolean (G_TASK (result
), error
);
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
;
433 empathy_geoclue_helper_new_async (guint distance_threshold
,
434 GAsyncReadyCallback callback
,
437 g_async_initable_new_async (EMPATHY_TYPE_GEOCLUE_HELPER
,
438 G_PRIORITY_DEFAULT
, NULL
, callback
, user_data
,
439 "distance-threshold", distance_threshold
,
443 EmpathyGeoclueHelper
*
444 empathy_geoclue_helper_new_finish (GAsyncResult
*result
,
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
),
453 g_object_unref (source_object
);
456 return EMPATHY_GEOCLUE_HELPER (object
);
462 new_started_cb (GObject
*source
,
463 GAsyncResult
*result
,
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
);
477 /* pass ownership of self to g_task_return_error */
478 g_task_return_pointer (new_started_task
, self
, g_object_unref
);
481 g_object_unref (new_started_task
);
485 new_started_init_cb (GObject
*source
,
486 GAsyncResult
*result
,
489 GTask
*new_started_task
= user_data
;
490 EmpathyGeoclueHelper
*self
;
491 GError
*error
= NULL
;
493 self
= empathy_geoclue_helper_new_finish (result
, &error
);
496 g_task_return_error (new_started_task
, error
);
497 g_object_unref (new_started_task
);
501 /* Pass owernship of 'self' to new_started_cb */
502 empathy_geoclue_helper_start_async (self
, new_started_cb
, new_started_task
);
506 empathy_geoclue_helper_new_started_async (guint distance_threshold
,
507 GAsyncReadyCallback callback
,
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
,
518 EmpathyGeoclueHelper
*
519 empathy_geoclue_helper_new_started_finish (GAsyncResult
*result
,
522 g_return_val_if_fail (g_task_is_valid (result
, NULL
), NULL
);
524 return g_task_propagate_pointer (G_TASK (result
), error
);