2 * Copyright (C) 2008 Holger Hans Peter Freyther
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
21 #include "GeolocationServiceGtk.h"
22 #if ENABLE(GEOLOCATION)
25 #include "NotImplemented.h"
26 #include "PositionOptions.h"
27 #include <wtf/text/CString.h>
30 template<> void freeOwnedGPtr<GeoclueAccuracy>(GeoclueAccuracy* accuracy)
35 geoclue_accuracy_free(accuracy);
41 GeolocationService* GeolocationServiceGtk::create(GeolocationServiceClient* client)
43 return new GeolocationServiceGtk(client);
46 GeolocationService::FactoryFunction* GeolocationService::s_factoryFunction = &GeolocationServiceGtk::create;
48 GeolocationServiceGtk::GeolocationServiceGtk(GeolocationServiceClient* client)
49 : GeolocationService(client)
51 , m_geocluePosition(0)
55 , m_altitudeAccuracy(0.0)
60 GeolocationServiceGtk::~GeolocationServiceGtk()
63 g_object_unref(m_geoclueClient);
65 if (m_geocluePosition)
66 g_object_unref(m_geocluePosition);
70 // 1.) Initialize Geoclue with our requirements
71 // 2.) Try to get a GeocluePosition
72 // 3.) Update the Information and get the current position
74 // TODO: Also get GeoclueVelocity but there is no master client
77 bool GeolocationServiceGtk::startUpdating(PositionOptions* options)
79 ASSERT(!m_geoclueClient);
84 GOwnPtr<GError> error;
85 GeoclueMaster* master = geoclue_master_get_default();
86 GeoclueMasterClient* client = geoclue_master_create_client(master, 0, 0);
87 g_object_unref(master);
90 setError(PositionError::POSITION_UNAVAILABLE, "Could not connect to location provider.");
94 GeoclueAccuracyLevel accuracyLevel = GEOCLUE_ACCURACY_LEVEL_LOCALITY;
97 accuracyLevel = options->enableHighAccuracy() ? GEOCLUE_ACCURACY_LEVEL_DETAILED : GEOCLUE_ACCURACY_LEVEL_LOCALITY;
98 if (options->hasTimeout())
99 timeout = options->timeout();
102 gboolean result = geoclue_master_client_set_requirements(client, accuracyLevel, timeout,
103 false, GEOCLUE_RESOURCE_ALL, &error.outPtr());
106 setError(PositionError::POSITION_UNAVAILABLE, error->message);
107 g_object_unref(client);
111 m_geocluePosition = geoclue_master_client_create_position(client, &error.outPtr());
112 if (!m_geocluePosition) {
113 setError(PositionError::POSITION_UNAVAILABLE, error->message);
114 g_object_unref(client);
118 m_geoclueClient = client;
120 geoclue_position_get_position_async(m_geocluePosition, (GeocluePositionCallback)getPositionCallback, this);
122 g_signal_connect(G_OBJECT(m_geocluePosition), "position-changed",
123 G_CALLBACK(position_changed), this);
128 void GeolocationServiceGtk::stopUpdating()
130 if (!m_geoclueClient)
133 g_object_unref(m_geocluePosition);
134 g_object_unref(m_geoclueClient);
136 m_geocluePosition = 0;
140 void GeolocationServiceGtk::suspend()
142 // not available with geoclue
146 void GeolocationServiceGtk::resume()
148 // not available with geoclue
152 Geoposition* GeolocationServiceGtk::lastPosition() const
154 return m_lastPosition.get();
157 PositionError* GeolocationServiceGtk::lastError() const
159 return m_lastError.get();
162 void GeolocationServiceGtk::updatePosition()
166 RefPtr<Coordinates> coordinates = Coordinates::create(m_latitude, m_longitude,
167 true, m_altitude, m_accuracy,
168 true, m_altitudeAccuracy, false, 0.0, false, 0.0);
169 m_lastPosition = Geoposition::create(coordinates.release(), m_timestamp * 1000.0);
173 void GeolocationServiceGtk::getPositionCallback(GeocluePosition *position,
174 GeocluePositionFields fields,
179 GeoclueAccuracy* accuracy,
181 GeolocationServiceGtk* that)
184 that->setError(PositionError::POSITION_UNAVAILABLE, error->message);
188 position_changed(position, fields, timestamp, latitude, longitude, altitude, accuracy, that);
191 void GeolocationServiceGtk::position_changed(GeocluePosition*, GeocluePositionFields fields, int timestamp, double latitude, double longitude, double altitude, GeoclueAccuracy* accuracy, GeolocationServiceGtk* that)
193 if (!(fields & GEOCLUE_POSITION_FIELDS_LATITUDE && fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) {
194 that->setError(PositionError::POSITION_UNAVAILABLE, "Position could not be determined.");
198 that->m_timestamp = timestamp;
199 that->m_latitude = latitude;
200 that->m_longitude = longitude;
201 that->m_altitude = altitude;
203 GeoclueAccuracyLevel level;
204 geoclue_accuracy_get_details(accuracy, &level, &that->m_accuracy, &that->m_altitudeAccuracy);
205 that->updatePosition();
208 void GeolocationServiceGtk::setError(PositionError::ErrorCode errorCode, const char* message)
211 m_lastError = PositionError::create(errorCode, String::fromUTF8(message));
215 #endif // ENABLE(GEOLOCATION)