2 * position-publisher.c - Source for PositionPublisher
3 * Copyright (C) 2010 Guillaume Desmottes
4 * @author Guillaume Desmottes <gdesmott@gnome.org>
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 <telepathy-glib/dbus.h>
26 #include <telepathy-glib/interfaces.h>
28 #include <location/location-gps-device.h>
30 #include "connection-watcher.h"
31 #include "position-publisher.h"
33 G_DEFINE_TYPE(PositionPublisher, position_publisher, G_TYPE_OBJECT)
35 /* private structure */
36 typedef struct _PositionPublisherPrivate PositionPublisherPrivate;
38 struct _PositionPublisherPrivate
40 ConnectionWatcher *watcher;
41 LocationGPSDevice *gps_device;
45 gboolean dispose_has_run;
48 #define POSITION_PUBLISHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), POSITION_PUBLISHER_TYPE, PositionPublisherPrivate))
50 static void conn_invalidated_cb (TpProxy *conn,
54 PositionPublisher *self);
57 remove_connection (PositionPublisher *self,
60 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (self);
62 g_signal_handlers_disconnect_by_func (conn, G_CALLBACK (conn_invalidated_cb),
64 priv->connections = g_slist_remove (priv->connections, conn);
65 g_object_unref (conn);
69 set_location_cb (TpConnection *conn,
74 PositionPublisher *self = POSITION_PUBLISHER (weak_object);
78 g_print ("SetLocation failed: %s\n", error->message);
80 if (error->code == TP_ERROR_NOT_IMPLEMENTED)
82 g_print ("remove connection\n");
83 remove_connection (self, conn);
89 g_print ("SetLocation succeed\n");
93 publish_to_conn (PositionPublisher *self,
96 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (self);
98 if (priv->location == NULL)
101 tp_cli_connection_interface_location_call_set_location (conn, -1,
102 priv->location, set_location_cb, NULL, NULL, G_OBJECT (self));
106 publish_to_all (PositionPublisher *self)
108 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (self);
111 for (l = priv->connections; l != NULL; l = g_slist_next (l))
113 TpConnection *conn = l->data;
115 publish_to_conn (self, conn);
120 update_position (PositionPublisher *self,
126 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (self);
128 g_print ("update position: lat: %f lon: %f alt: %f accuracy: %f\n",
129 lat, lon, alt, accuracy);
131 if (priv->location != NULL)
132 g_hash_table_unref (priv->location);
134 priv->location = tp_asv_new (
135 "timestamp", G_TYPE_INT64, (gint64) time (NULL),
136 "lat", G_TYPE_DOUBLE, lat,
137 "lon", G_TYPE_DOUBLE, lon,
138 "alt", G_TYPE_DOUBLE, alt,
139 "accuracy", G_TYPE_DOUBLE, accuracy,
142 publish_to_all (self);
146 location_changed_cb (LocationGPSDevice *device,
147 PositionPublisher *self)
152 if (device->fix == NULL)
155 if (!(device->fix->fields & LOCATION_GPS_DEVICE_LATLONG_SET))
158 update_position (self, device->fix->latitude, device->fix->longitude,
159 device->fix->altitude, device->fix->eph / 100.0);
163 conn_invalidated_cb (TpProxy *conn,
167 PositionPublisher *self)
169 g_print ("connection %s invalidated; removing\n", tp_proxy_get_object_path (
172 remove_connection (self, TP_CONNECTION (conn));
176 connection_added_cb (ConnectionWatcher *watcher,
178 PositionPublisher *self)
180 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (self);
182 if (g_slist_find (priv->connections, conn) != NULL)
185 if (!tp_proxy_has_interface_by_id (conn,
186 TP_IFACE_QUARK_CONNECTION_INTERFACE_LOCATION))
189 priv->connections = g_slist_prepend (priv->connections, g_object_ref (conn));
191 g_signal_connect (conn, "invalidated",
192 G_CALLBACK (conn_invalidated_cb), self);
194 publish_to_conn (self, conn);
198 position_publisher_init (PositionPublisher *obj)
200 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (obj);
202 priv->watcher = connection_watcher_new ();
204 g_signal_connect (priv->watcher, "connection-added",
205 G_CALLBACK (connection_added_cb), obj);
207 priv->gps_device = g_object_new (LOCATION_TYPE_GPS_DEVICE, NULL);
209 g_signal_connect (priv->gps_device, "changed",
210 G_CALLBACK (location_changed_cb), obj);
212 priv->connections = NULL;
216 position_publisher_constructed (GObject *object)
218 PositionPublisher *self = POSITION_PUBLISHER (object);
219 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (self);
221 connection_watcher_start (priv->watcher);
223 if (G_OBJECT_CLASS (position_publisher_parent_class)->constructed)
224 G_OBJECT_CLASS (position_publisher_parent_class)->constructed (object);
227 static void position_publisher_dispose (GObject *object);
228 static void position_publisher_finalize (GObject *object);
231 position_publisher_class_init (PositionPublisherClass *position_publisher_class)
233 GObjectClass *object_class = G_OBJECT_CLASS (position_publisher_class);
235 g_type_class_add_private (position_publisher_class, sizeof (PositionPublisherPrivate));
237 object_class->dispose = position_publisher_dispose;
238 object_class->finalize = position_publisher_finalize;
240 object_class->constructed = position_publisher_constructed;
244 position_publisher_dispose (GObject *object)
246 PositionPublisher *self = POSITION_PUBLISHER (object);
247 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (self);
250 if (priv->dispose_has_run)
253 priv->dispose_has_run = TRUE;
255 g_object_unref (priv->watcher);
256 g_object_unref (priv->gps_device);
258 for (l = priv->connections; l != NULL; l = g_slist_next (l))
260 g_object_unref (l->data);
263 g_hash_table_unref (priv->location);
265 if (G_OBJECT_CLASS (position_publisher_parent_class)->dispose)
266 G_OBJECT_CLASS (position_publisher_parent_class)->dispose (object);
270 position_publisher_finalize (GObject *object)
272 PositionPublisher *self = POSITION_PUBLISHER (object);
273 PositionPublisherPrivate *priv = POSITION_PUBLISHER_GET_PRIVATE (self);
275 g_slist_free (priv->connections);
277 G_OBJECT_CLASS (position_publisher_parent_class)->finalize (object);
281 position_publisher_new (void)
283 return g_object_new (POSITION_PUBLISHER_TYPE,