diff options
-rw-r--r-- | config.tests/geoclue-satellite/geoclue-satellite.pro | 6 | ||||
-rw-r--r-- | config.tests/geoclue-satellite/main.cpp | 49 | ||||
-rw-r--r-- | config.tests/geoclue/geoclue.pro | 2 | ||||
-rw-r--r-- | config.tests/geoclue/main.cpp | 10 | ||||
-rw-r--r-- | qtlocation.pro | 1 | ||||
-rw-r--r-- | src/plugins/position/geoclue/geoclue.pro | 18 | ||||
-rw-r--r-- | src/plugins/position/geoclue/plugin-satellite.json | 7 | ||||
-rw-r--r-- | src/plugins/position/geoclue/qgeocluemaster.cpp | 163 | ||||
-rw-r--r-- | src/plugins/position/geoclue/qgeocluemaster.h | 69 | ||||
-rw-r--r-- | src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp | 181 | ||||
-rw-r--r-- | src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h | 17 | ||||
-rw-r--r-- | src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp | 17 | ||||
-rw-r--r-- | src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h | 12 | ||||
-rw-r--r-- | src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp | 259 | ||||
-rw-r--r-- | src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h | 93 |
15 files changed, 772 insertions, 132 deletions
diff --git a/config.tests/geoclue-satellite/geoclue-satellite.pro b/config.tests/geoclue-satellite/geoclue-satellite.pro new file mode 100644 index 00000000..1ebc2e84 --- /dev/null +++ b/config.tests/geoclue-satellite/geoclue-satellite.pro @@ -0,0 +1,6 @@ +TEMPLATE = app +unix { + CONFIG += link_pkgconfig + PKGCONFIG += geoclue +} +SOURCES += main.cpp diff --git a/config.tests/geoclue-satellite/main.cpp b/config.tests/geoclue-satellite/main.cpp new file mode 100644 index 00000000..c642e106 --- /dev/null +++ b/config.tests/geoclue-satellite/main.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd, author: Aaron McCarthy <aaron.mccarthy@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <geoclue/geoclue-satellite.h> + +int main() +{ + GeoclueSatellite satellite; + + return 0; +} diff --git a/config.tests/geoclue/geoclue.pro b/config.tests/geoclue/geoclue.pro index 4d05166c..1ebc2e84 100644 --- a/config.tests/geoclue/geoclue.pro +++ b/config.tests/geoclue/geoclue.pro @@ -1,6 +1,6 @@ TEMPLATE = app unix { CONFIG += link_pkgconfig - PKGCONFIG += geoclue gconf-2.0 + PKGCONFIG += geoclue } SOURCES += main.cpp diff --git a/config.tests/geoclue/main.cpp b/config.tests/geoclue/main.cpp index 3a868d70..c286775c 100644 --- a/config.tests/geoclue/main.cpp +++ b/config.tests/geoclue/main.cpp @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -40,13 +42,15 @@ ****************************************************************************/ #include <geoclue/geoclue-position.h> -#include <gconf/gconf-client.h> +#include <geoclue/geoclue-velocity.h> int main() { GType type = geoclue_position_get_type(); - GConfClient *client = gconf_client_get_default(); - g_object_unref(client); + GeocluePosition position; + + type = geoclue_velocity_get_type(); + GeoclueVelocity velocity; return 0; } diff --git a/qtlocation.pro b/qtlocation.pro index bb0ecf84..d3a1ba65 100644 --- a/qtlocation.pro +++ b/qtlocation.pro @@ -1,5 +1,6 @@ load(configure) qtCompileTest(geoclue) +qtCompileTest(geoclue-satellite) qtCompileTest(gypsy) load(qt_parts) diff --git a/src/plugins/position/geoclue/geoclue.pro b/src/plugins/position/geoclue/geoclue.pro index 0ed31781..b6a80c69 100644 --- a/src/plugins/position/geoclue/geoclue.pro +++ b/src/plugins/position/geoclue/geoclue.pro @@ -6,16 +6,26 @@ load(qt_plugin) HEADERS += \ qgeopositioninfosource_geocluemaster_p.h \ - qgeopositioninfosourcefactory_geoclue.h + qgeopositioninfosourcefactory_geoclue.h \ + qgeocluemaster.h SOURCES += \ qgeopositioninfosource_geocluemaster.cpp \ - qgeopositioninfosourcefactory_geoclue.cpp + qgeopositioninfosourcefactory_geoclue.cpp \ + qgeocluemaster.cpp + +config_geoclue-satellite { + DEFINES += HAS_SATELLITE + + HEADERS += qgeosatelliteinfosource_geocluemaster.h + SOURCES += qgeosatelliteinfosource_geocluemaster.cpp +} INCLUDEPATH += $$QT.location.includes CONFIG += link_pkgconfig -PKGCONFIG += geoclue gconf-2.0 +PKGCONFIG += geoclue OTHER_FILES += \ - plugin.json + plugin.json \ + plugin-satellite.json diff --git a/src/plugins/position/geoclue/plugin-satellite.json b/src/plugins/position/geoclue/plugin-satellite.json new file mode 100644 index 00000000..59e190f1 --- /dev/null +++ b/src/plugins/position/geoclue/plugin-satellite.json @@ -0,0 +1,7 @@ +{ + "Keys": ["geoclue"], + "Provider": "geoclue", + "Position": true, + "Satellite": true, + "Priority": 1000 +} diff --git a/src/plugins/position/geoclue/qgeocluemaster.cpp b/src/plugins/position/geoclue/qgeocluemaster.cpp new file mode 100644 index 00000000..e8444cef --- /dev/null +++ b/src/plugins/position/geoclue/qgeocluemaster.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd, author: Aaron McCarthy <aaron.mccarthy@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeocluemaster.h" + +#include <QtCore/QByteArray> +#include <QtCore/QMetaMethod> + +QT_BEGIN_NAMESPACE + +namespace +{ + +void position_provider_changed(GeoclueMasterClient *client, char *name, char *description, + char *service, char *path, gpointer userdata) +{ + Q_UNUSED(client) + Q_UNUSED(name) + Q_UNUSED(description) + + const QByteArray pService = QByteArray(service); + const QByteArray pPath = QByteArray(path); + + QObject *o = static_cast<QObject *>(userdata); + + QMetaObject::invokeMethod(o, "positionProviderChanged", Qt::QueuedConnection, + Q_ARG(QByteArray, pService), Q_ARG(QByteArray, pPath)); +} + +} + +QGeoclueMaster::QGeoclueMaster(QObject *handler) +: m_client(0), m_masterPosition(0), m_handler(handler) +{ +} + +QGeoclueMaster::~QGeoclueMaster() +{ + releaseMasterClient(); +} + +bool QGeoclueMaster::createMasterClient(GeoclueAccuracyLevel accuracy, GeoclueResourceFlags resourceFlags) +{ + GeoclueMaster *master = geoclue_master_get_default(); + if (!master) { + qCritical("QGeoclueMaster error creating GeoclueMaster"); + return false; + } + + GError *error = 0; + + m_client = geoclue_master_create_client(master, 0, &error); + g_object_unref (master); + + if (!m_client) { + qCritical("QGeoclueMaster error creating GeoclueMasterClient."); + if (error) { + qCritical("Geoclue error: %s", error->message); + g_error_free(error); + } + return false; + } + + g_signal_connect(G_OBJECT(m_client), "position-provider-changed", + G_CALLBACK(position_provider_changed), m_handler); + + if (!geoclue_master_client_set_requirements(m_client, accuracy, 0, true, + resourceFlags, &error)) { + qCritical("QGeoclueMaster geoclue set_requirements failed."); + if (error) { + qCritical ("Geoclue error: %s", error->message); + g_error_free (error); + } + g_object_unref(m_client); + m_client = 0; + return false; + } + + // Need to create the master position interface even though it will not be used, otherwise + // GetPositionProvider always returns empty strings. + m_masterPosition = geoclue_master_client_create_position(m_client, 0); + if (!m_masterPosition) { + qCritical("QGeoclueMaster failed to get master position object"); + g_object_unref(m_client); + m_client = 0; + return false; + } + + char *service = 0; + char *path = 0; + + if (!geoclue_master_client_get_position_provider(m_client, 0, 0, &service, &path, 0) || + !qstrlen(service) || !qstrlen(path)) { + qCritical("QGeoclueMaster failed to get position provider service/path"); + g_object_unref(m_masterPosition); + m_masterPosition = 0; + g_object_unref(m_client); + m_client = 0; + return false; + } + + const QByteArray pService = QByteArray(service); + const QByteArray pPath = QByteArray(path); + + QMetaObject::invokeMethod(m_handler, "positionProviderChanged", Q_ARG(QByteArray, pService), + Q_ARG(QByteArray, pPath)); + + return true; +} + +void QGeoclueMaster::releaseMasterClient() +{ + if (m_masterPosition) { + g_object_unref(m_masterPosition); + m_masterPosition = 0; + } + if (m_client) { + g_signal_handlers_disconnect_by_func(G_OBJECT(m_client), (void *)position_provider_changed, + m_handler); + g_object_unref(m_client); + m_client = 0; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeocluemaster.h b/src/plugins/position/geoclue/qgeocluemaster.h new file mode 100644 index 00000000..0ebedb33 --- /dev/null +++ b/src/plugins/position/geoclue/qgeocluemaster.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd, author: Aaron McCarthy <aaron.mccarthy@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOCLUEMASTER_H +#define QGEOCLUEMASTER_H + +#include <QtCore/QObject> + +#include <geoclue/geoclue-master.h> + +QT_BEGIN_NAMESPACE + +class QGeoclueMaster +{ +public: + QGeoclueMaster(QObject *handler); + virtual ~QGeoclueMaster(); + + bool createMasterClient(GeoclueAccuracyLevel accuracy, GeoclueResourceFlags resourceFlags); + void releaseMasterClient(); + +private: + GeoclueMasterClient *m_client; + GeocluePosition *m_masterPosition; + + QObject *m_handler; +}; + +QT_END_NAMESPACE + +#endif // QGEOCLUEMASTER_H diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp index 920c5be8..04f23c21 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp +++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster.cpp @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -39,14 +41,15 @@ ** ****************************************************************************/ +#include "qgeopositioninfosource_geocluemaster_p.h" + #include <QtCore> #ifdef Q_LOCATION_GEOCLUE_DEBUG #include <QDebug> #endif -#include "qgeopositioninfosource_geocluemaster_p.h" -#include <gconf/gconf-client.h> +#include <dbus/dbus-glib.h> QT_BEGIN_NAMESPACE @@ -120,10 +123,9 @@ static void position_callback (GeocluePosition *pos, } QGeoPositionInfoSourceGeoclueMaster::QGeoPositionInfoSourceGeoclueMaster(QObject *parent) - : QGeoPositionInfoSource(parent), m_updateInterval(0), m_preferredResources(GEOCLUE_RESOURCE_ALL), - m_preferredAccuracy(GEOCLUE_ACCURACY_LEVEL_NONE), - m_client(0), m_pos(0), m_vel(0), m_lastPositionIsFresh(false), m_lastVelocityIsFresh(false), - m_lastVelocity(0), m_lastPositionFromSatellite(false), m_methods(AllPositioningMethods) +: QGeoPositionInfoSource(parent), QGeoclueMaster(this), m_updateInterval(0), m_pos(0), m_vel(0), + m_lastPositionIsFresh(false), m_lastVelocityIsFresh(false), m_lastVelocity(0), + m_lastPositionFromSatellite(false), m_methods(AllPositioningMethods) { m_requestTimer.setSingleShot(true); QObject::connect(&m_requestTimer, SIGNAL(timeout()), this, SLOT(requestUpdateTimeout())); @@ -136,8 +138,6 @@ QGeoPositionInfoSourceGeoclueMaster::~QGeoPositionInfoSourceGeoclueMaster() g_object_unref (m_pos); if (m_vel) g_object_unref(m_vel); - if (m_client) - g_object_unref (m_client); } void QGeoPositionInfoSourceGeoclueMaster::velocityUpdateFailed() @@ -229,58 +229,31 @@ void QGeoPositionInfoSourceGeoclueMaster::regularUpdateSucceeded(GeocluePosition #endif } -bool QGeoPositionInfoSourceGeoclueMaster::tryGPS() -{ - // Check if the gconf value is set properly - GConfClient *client; - gchar *device_name; - client = gconf_client_get_default(); - device_name = gconf_client_get_string(client, "/apps/geoclue/master/org.freedesktop.Geoclue.GPSDevice", NULL); - QString deviceName(QString::fromLatin1(device_name)); - g_object_unref(client); - g_free(device_name); - - if (deviceName.isEmpty()) { - return false; - } else { - // Check if the device exists (does nothing if a bluetooth address) - if (deviceName.trimmed().at(0) == '/' && QFile::exists(deviceName.trimmed())) { - return true; - } - return false; - } -} - -int QGeoPositionInfoSourceGeoclueMaster::init() +bool QGeoPositionInfoSourceGeoclueMaster::init() { g_type_init (); - // Check if there is sense to try GPS - if (tryGPS()) { - m_preferredResources = GEOCLUE_RESOURCE_GPS; - m_preferredAccuracy = GEOCLUE_ACCURACY_LEVEL_DETAILED; - if (configurePositionSource() != -1) { - return 0; - } else { - // If not successful, try to get any resource - m_preferredResources = GEOCLUE_RESOURCE_ALL; - m_preferredAccuracy = GEOCLUE_ACCURACY_LEVEL_NONE; - return configurePositionSource(); - } - } else { - return configurePositionSource(); - } + + return configurePositionSource(GEOCLUE_ACCURACY_LEVEL_NONE, GEOCLUE_RESOURCE_ALL); } -int QGeoPositionInfoSourceGeoclueMaster::configurePositionSource() +bool QGeoPositionInfoSourceGeoclueMaster::configurePositionSource(GeoclueAccuracyLevel accuracy, + GeoclueResourceFlags resourceFlags) { - GeoclueMaster *master(0); - GError *error = 0; // Free potential previous sources, because new requirements can't be set for the client // (creating a position object after changing requirements seems to fail). - if (m_client) { - g_object_unref (m_client); - m_client = 0; - } + cleanupPositionSource(); + releaseMasterClient(); + + if (!createMasterClient(accuracy, resourceFlags)) + return false; + + // createMasterClient() will call positionProviderChanged() slot on success, which sets m_pos + // and possibly m_vel. Return true if m_pos is set. + return m_pos; +} + +void QGeoPositionInfoSourceGeoclueMaster::cleanupPositionSource() +{ if (m_pos) { g_object_unref(m_pos); m_pos = 0; @@ -289,56 +262,6 @@ int QGeoPositionInfoSourceGeoclueMaster::configurePositionSource() g_object_unref(m_vel); m_vel = 0; } - - master = geoclue_master_get_default (); - if (!master) { - qCritical ("QGeoPositionInfoSourceGeoclueMaster error creating GeoclueMaster"); - return -1; - } - - m_client = geoclue_master_create_client (master, NULL, &error); - g_object_unref (master); - - if (!m_client) { - qCritical ("QGeoPositionInfoSourceGeoclueMaster error creating GeoclueMasterClient."); - if (error) { - qCritical ("Geoclue error: %s", error->message); - g_error_free (error); - } - return -1; - } - - if (!geoclue_master_client_set_requirements (m_client, - m_preferredAccuracy, // min_accuracy - 0, // min_time - true, // require_updates (signals) - m_preferredResources, - &error)){ - qCritical ("QGeoPositionInfoSourceGeoclueMaster geoclue set_requirements failed."); - if (error) { - qCritical ("Geoclue error: %s", error->message); - g_error_free (error); - } - g_object_unref (m_client); - m_client = 0; - return -1; - } - m_pos = geoclue_master_client_create_position (m_client, NULL); - if (!m_pos) { - qCritical("QGeoPositionInfoSourceGeoclueMaster failed to get a position object"); - g_object_unref (m_client); - m_client = 0; - return -1; - } - // Succeeding velocity is not mandatory. Master does not provide abstraction - // for velocity provider, hence request Gypsy provider directly. - m_vel = geoclue_velocity_new("org.freedesktop.Geoclue.Providers.Gypsy", - "/org/freedesktop/Geoclue/Providers/Gypsy"); -#ifdef Q_LOCATION_GEOCLUE_DEBUG - if (m_vel == NULL) - qDebug("QGeoPositionInfoSourceGeoclueMaster velocity provider (Gypsy) not available."); -#endif - return 0; } void QGeoPositionInfoSourceGeoclueMaster::setUpdateInterval(int msec) @@ -359,18 +282,16 @@ void QGeoPositionInfoSourceGeoclueMaster::setPreferredPositioningMethods(Positio if (previousPreferredPositioningMethods == preferredPositioningMethods()) return; + bool status; switch (preferredPositioningMethods()) { case SatellitePositioningMethods: - m_preferredResources = GEOCLUE_RESOURCE_GPS; - m_preferredAccuracy = GEOCLUE_ACCURACY_LEVEL_DETAILED; + status = configurePositionSource(GEOCLUE_ACCURACY_LEVEL_DETAILED, GEOCLUE_RESOURCE_GPS); break; case NonSatellitePositioningMethods: - m_preferredResources = (GeoclueResourceFlags)(GEOCLUE_RESOURCE_CELL | GEOCLUE_RESOURCE_NETWORK); - m_preferredAccuracy = GEOCLUE_ACCURACY_LEVEL_NONE; + status = configurePositionSource(GEOCLUE_ACCURACY_LEVEL_NONE, GeoclueResourceFlags(GEOCLUE_RESOURCE_CELL | GEOCLUE_RESOURCE_NETWORK)); break; case AllPositioningMethods: - m_preferredResources = GEOCLUE_RESOURCE_ALL; - m_preferredAccuracy = GEOCLUE_ACCURACY_LEVEL_NONE; + status = configurePositionSource(GEOCLUE_ACCURACY_LEVEL_NONE, GEOCLUE_RESOURCE_ALL); break; default: qWarning("GeoPositionInfoSourceGeoClueMaster unknown preferred method."); @@ -378,16 +299,15 @@ void QGeoPositionInfoSourceGeoclueMaster::setPreferredPositioningMethods(Positio } #ifdef Q_LOCATION_GEOCLUE_DEBUG - qDebug() << "QGeoPositionInfoSourceGeoclueMaster requested to set methods to, and set them to: " << methods << m_preferredResources; + qDebug() << "QGeoPositionInfoSourceGeoclueMaster requested to set methods to, and set them to: " << methods; #endif m_lastPositionIsFresh = false; m_lastVelocityIsFresh = false; - int status = configurePositionSource(); // If updates ongoing, connect to the new objects if (m_updateTimer.isActive()) { - if (status != -1) { + if (status) { g_signal_connect (G_OBJECT (m_pos), "position-changed", G_CALLBACK (position_changed),this); if (m_vel) { @@ -402,7 +322,7 @@ void QGeoPositionInfoSourceGeoclueMaster::setPreferredPositioningMethods(Positio } // If a request ongoing, ask it from new object if (m_requestTimer.isActive()) { - if ( status != -1) { + if (status) { geoclue_position_get_position_async (m_pos, (GeocluePositionCallback)position_callback, this); @@ -518,6 +438,41 @@ void QGeoPositionInfoSourceGeoclueMaster::startUpdatesTimeout() } } +void QGeoPositionInfoSourceGeoclueMaster::positionProviderChanged(const QByteArray &service, const QByteArray &path) +{ + if (m_pos) { + if (service == dbus_g_proxy_get_bus_name(m_pos->provider.proxy) && + path == dbus_g_proxy_get_path(m_pos->provider.proxy)) { + // Provider hasn't actually changed. This can happen when first connecting as + // createMasterClient() will emit a signal independent of the DBus signal. + return; + } + + cleanupPositionSource(); + } + + m_pos = geoclue_position_new(service.constData(), path.constData()); + if (!m_pos) + qCritical("QGeoPositionInfoSourceGeoclueMaster failed to get a position object"); + + if (m_pos) + g_signal_connect(G_OBJECT(m_pos), "position-changed", G_CALLBACK(position_changed), this); + + // Succeeding velocity is not mandatory. Master does not provide abstraction + // for velocity provider, hence directly get the current provider. + m_vel = geoclue_velocity_new(service.constData(), path.constData()); +#ifdef Q_LOCATION_GEOCLUE_DEBUG + if (!m_vel) + qDebug("QGeoPositionInfoSourceGeoclueMaster velocity provider not available."); +#endif + + if (m_vel) + g_signal_connect(G_OBJECT(m_vel), "velocity-changed", G_CALLBACK(velocity_changed), this); + + // Get the current position immediately. + geoclue_position_get_position_async(m_pos, position_callback, this); +} + // Helper function to convert data into a QGeoPositionInfo QGeoPositionInfo QGeoPositionInfoSourceGeoclueMaster::geoclueToPositionInfo( GeocluePositionFields fields, diff --git a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h index 8266aece..0adf004b 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h +++ b/src/plugins/position/geoclue/qgeopositioninfosource_geocluemaster_p.h @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -53,8 +55,9 @@ // We mean it. // +#include "qgeocluemaster.h" + #include <qgeopositioninfosource.h> -#include <geoclue/geoclue-master.h> #include <geoclue/geoclue-velocity.h> #include <QTimer> @@ -62,7 +65,7 @@ QT_BEGIN_NAMESPACE -class QGeoPositionInfoSourceGeoclueMaster : public QGeoPositionInfoSource +class QGeoPositionInfoSourceGeoclueMaster : public QGeoPositionInfoSource, public QGeoclueMaster { Q_OBJECT public: @@ -82,7 +85,7 @@ public: PositioningMethods supportedPositioningMethods() const; void setPreferredPositioningMethods(PositioningMethods methods); int minimumUpdateInterval() const; - int init(); + bool init(); void singleUpdateFailed(); void singleUpdateSucceeded(GeocluePositionFields fields, @@ -111,10 +114,11 @@ public slots: private slots: void requestUpdateTimeout(); void startUpdatesTimeout(); + void positionProviderChanged(const QByteArray &service, const QByteArray &path); private: - bool tryGPS(); - int configurePositionSource(); + bool configurePositionSource(GeoclueAccuracyLevel accuracy, GeoclueResourceFlags resourceFlags); + void cleanupPositionSource(); QGeoPositionInfo geoclueToPositionInfo(GeocluePositionFields fields, int timestamp, double latitude, @@ -123,9 +127,6 @@ private: GeoclueAccuracy * accuracy); private: int m_updateInterval; - GeoclueResourceFlags m_preferredResources; - GeoclueAccuracyLevel m_preferredAccuracy; - GeoclueMasterClient *m_client; GeocluePosition *m_pos; GeoclueVelocity *m_vel; QTimer m_updateTimer; diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp index 5ad3dd58..0395e5b6 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp +++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.cpp @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -41,11 +43,12 @@ #include "qgeopositioninfosourcefactory_geoclue.h" #include "qgeopositioninfosource_geocluemaster_p.h" +#include "qgeosatelliteinfosource_geocluemaster.h" QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGeoclue::positionInfoSource(QObject *parent) { QGeoPositionInfoSourceGeoclueMaster *src = new QGeoPositionInfoSourceGeoclueMaster(parent); - if (src->init() < 0) { + if (!src->init()) { delete src; src = 0; } @@ -54,8 +57,18 @@ QGeoPositionInfoSource *QGeoPositionInfoSourceFactoryGeoclue::positionInfoSource QGeoSatelliteInfoSource *QGeoPositionInfoSourceFactoryGeoclue::satelliteInfoSource(QObject *parent) { - Q_UNUSED(parent); +#ifdef HAS_SATELLITE + QGeoSatelliteInfoSourceGeoclueMaster *src = new QGeoSatelliteInfoSourceGeoclueMaster(parent); + if (!src->init() < 0) { + delete src; + src = 0; + } + return src; +#else + Q_UNUSED(parent) + return 0; +#endif } QGeoAreaMonitor *QGeoPositionInfoSourceFactoryGeoclue::areaMonitor(QObject *parent) diff --git a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h index e18c27e8..4eedaf81 100644 --- a/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h +++ b/src/plugins/position/geoclue/qgeopositioninfosourcefactory_geoclue.h @@ -1,5 +1,7 @@ /**************************************************************************** ** +** Copyright (C) 2013 Jolla Ltd. +** Contact: Aaron McCarthy <aaron.mccarthy@jollamobile.com> ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** @@ -45,11 +47,19 @@ #include <QObject> #include <qgeopositioninfosourcefactory.h> +#ifdef HAS_SATELLITE +#define PLUGIN_JSON "plugin-satellite.json" +#else +#define PLUGIN_JSON "plugin.json" +#endif + class QGeoPositionInfoSourceFactoryGeoclue : public QObject, public QGeoPositionInfoSourceFactory { Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.qt.position.sourcefactory/5.0" - FILE "plugin.json") + FILE PLUGIN_JSON) + Q_INTERFACES(QGeoPositionInfoSourceFactory) public: diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp new file mode 100644 index 00000000..276b0278 --- /dev/null +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.cpp @@ -0,0 +1,259 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd, author: Aaron McCarthy <aaron.mccarthy@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgeosatelliteinfosource_geocluemaster.h" + +#define MINIMUM_UPDATE_INTERVAL 1000 + +QT_BEGIN_NAMESPACE + +namespace +{ + +void satellite_changed(GeoclueSatellite *satellite, int timestamp, int satellite_used, + int satellite_visible, GArray *used_prn, GPtrArray *sat_info, + gpointer userdata) +{ + Q_UNUSED(satellite) + + QGeoSatelliteInfoSourceGeoclueMaster *source = + static_cast<QGeoSatelliteInfoSourceGeoclueMaster *>(userdata); + + QList<int> usedPrns; + for (unsigned int i = 0; i < used_prn->len; ++i) + usedPrns.append(g_array_index(used_prn, int, i)); + + QList<QGeoSatelliteInfo> satInfos; + for (unsigned int i = 0; i < sat_info->len; ++i) { + GValueArray *a = static_cast<GValueArray *>(g_ptr_array_index(sat_info, i)); + + QGeoSatelliteInfo satInfo; + + satInfo.setSatelliteIdentifier(g_value_get_int(g_value_array_get_nth(a, 0))); + satInfo.setAttribute(QGeoSatelliteInfo::Elevation, + g_value_get_int(g_value_array_get_nth(a, 1))); + satInfo.setAttribute(QGeoSatelliteInfo::Azimuth, + g_value_get_int(g_value_array_get_nth(a, 2))); + satInfo.setSignalStrength(g_value_get_int(g_value_array_get_nth(a, 3))); + + satInfos.append(satInfo); + } + + source->satelliteChanged(timestamp, satellite_used, satellite_visible, usedPrns, satInfos); +} + +void satellite_callback(GeoclueSatellite *satellite, int timestamp, int satellite_used, + int satellite_visible, GArray *used_prn, GPtrArray *sat_info, + GError *error, gpointer userdata) +{ + Q_UNUSED(satellite) + + if (error) + g_error_free(error); + + QGeoSatelliteInfoSourceGeoclueMaster *source = + static_cast<QGeoSatelliteInfoSourceGeoclueMaster *>(userdata); + + QList<int> usedPrns; + for (unsigned int i = 0; i < used_prn->len; ++i) + usedPrns.append(g_array_index(used_prn, int, i)); + + QList<QGeoSatelliteInfo> satInfos; + for (unsigned int i = 0; i < sat_info->len; ++i) { + GValueArray *a = static_cast<GValueArray *>(g_ptr_array_index(sat_info, i)); + + QGeoSatelliteInfo satInfo; + + satInfo.setSatelliteIdentifier(g_value_get_int(g_value_array_get_nth(a, 0))); + satInfo.setAttribute(QGeoSatelliteInfo::Elevation, + g_value_get_int(g_value_array_get_nth(a, 1))); + satInfo.setAttribute(QGeoSatelliteInfo::Azimuth, + g_value_get_int(g_value_array_get_nth(a, 2))); + satInfo.setSignalStrength(g_value_get_int(g_value_array_get_nth(a, 3))); + + satInfos.append(satInfo); + } + + source->requestUpdateFinished(timestamp, satellite_used, satellite_visible, usedPrns, satInfos); +} + +} + +QGeoSatelliteInfoSourceGeoclueMaster::QGeoSatelliteInfoSourceGeoclueMaster(QObject *parent) +: QGeoSatelliteInfoSource(parent), QGeoclueMaster(this), m_sat(0) +{ + m_requestTimer.setSingleShot(true); + connect(&m_requestTimer, SIGNAL(timeout()), this, SIGNAL(requestTimeout())); +} + +QGeoSatelliteInfoSourceGeoclueMaster::~QGeoSatelliteInfoSourceGeoclueMaster() +{ + cleanupSatelliteSource(); +} + +bool QGeoSatelliteInfoSourceGeoclueMaster::init() +{ + g_type_init(); + + return configureSatelliteSource(); +} + +int QGeoSatelliteInfoSourceGeoclueMaster::minimumUpdateInterval() const +{ + return MINIMUM_UPDATE_INTERVAL; +} + +QGeoSatelliteInfoSource::Error QGeoSatelliteInfoSourceGeoclueMaster::error() const +{ + return UnknownSourceError; +} + +void QGeoSatelliteInfoSourceGeoclueMaster::startUpdates() +{ + if (!m_sat) + return; + + g_signal_connect(G_OBJECT(m_sat), "satellite-changed", G_CALLBACK(satellite_changed), this); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::stopUpdates() +{ + if (!m_sat) + g_signal_handlers_disconnect_by_func(G_OBJECT(m_sat), gpointer(satellite_changed), this); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdate(int timeout) +{ + if ((timeout < minimumUpdateInterval() && timeout != 0) || !m_sat) { + emit requestTimeout(); + return; + } + + if (m_requestTimer.isActive()) + return; + + m_requestTimer.start(qMax(timeout, minimumUpdateInterval())); + geoclue_satellite_get_satellite_async(m_sat, satellite_callback, this); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::satelliteChanged(int timestamp, int satellitesUsed, + int satellitesVisible, + const QList<int> &usedPrn, + const QList<QGeoSatelliteInfo> &satInfos) +{ + Q_UNUSED(timestamp) + + QList<QGeoSatelliteInfo> inUse; + + foreach (const QGeoSatelliteInfo &si, satInfos) + if (usedPrn.contains(si.satelliteIdentifier())) + inUse.append(si); + + if (satInfos.length() != satellitesVisible) { + qWarning("QGeoSatelliteInfoSourceGeoclueMaster number of in view QGeoSatelliteInfos (%d) " + "does not match expected number of in view satellites (%d).", satInfos.length(), + satellitesVisible); + } + + if (inUse.length() != satellitesUsed) { + qWarning("QGeoSatelliteInfoSourceGeoclueMaster number of in use QGeoSatelliteInfos (%d) " + "does not match expected number of in use satellites (%d).", inUse.length(), + satellitesUsed); + } + + m_inView = satInfos; + emit satellitesInViewUpdated(m_inView); + + m_inUse = inUse; + emit satellitesInUseUpdated(m_inUse); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::requestUpdateFinished(int timestamp, int satellitesUsed, + int satellitesVisible, + const QList<int> &usedPrn, + const QList<QGeoSatelliteInfo> &satInfos) +{ + m_requestTimer.stop(); + satelliteChanged(timestamp, satellitesUsed, satellitesVisible, usedPrn, satInfos); +} + +void QGeoSatelliteInfoSourceGeoclueMaster::positionProviderChanged(const QByteArray &service, const QByteArray &path) +{ + if (m_sat) { + if (service == dbus_g_proxy_get_bus_name(m_sat->provider.proxy) && + path == dbus_g_proxy_get_path(m_sat->provider.proxy)) { + // Provider hasn't actually changed. This can happen when first connecting as + // createMasterClient() will emit a signal independent of the DBus signal. + return; + } + + cleanupSatelliteSource(); + } + + m_sat = geoclue_satellite_new(service.constData(), path.constData()); + if (!m_sat) + qCritical("QGeoSatelliteInfoSourceGeoclueMaster failed to get a satellite object"); + else + g_signal_connect(G_OBJECT(m_sat), "satellite-changed", G_CALLBACK(satellite_changed), this); +} + +bool QGeoSatelliteInfoSourceGeoclueMaster::configureSatelliteSource() +{ + cleanupSatelliteSource(); + releaseMasterClient(); + + if (!createMasterClient(GEOCLUE_ACCURACY_LEVEL_DETAILED, GEOCLUE_RESOURCE_GPS)) + return false; + + // createMasterClient() will call positionProviderChanged() slot on success, which sets m_pos + // and possibly m_vel. Return true if m_pos is set. + return m_sat; +} + +void QGeoSatelliteInfoSourceGeoclueMaster::cleanupSatelliteSource() +{ + if (m_sat) { + g_object_unref(m_sat); + m_sat = 0; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h new file mode 100644 index 00000000..60f4fe48 --- /dev/null +++ b/src/plugins/position/geoclue/qgeosatelliteinfosource_geocluemaster.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Jolla Ltd, author: Aaron McCarthy <aaron.mccarthy@jollamobile.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtLocation module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGEOSATELLITEINFOSOURCE_GEOCLUEMASTER_H +#define QGEOSATELLITEINFOSOURCE_GEOCLUEMASTER_H + +#include "qgeocluemaster.h" + +#include <geoclue/geoclue-satellite.h> + +#include <QtCore/qcompilerdetection.h> +#include <QtCore/QTimer> +#include <QtLocation/QGeoSatelliteInfoSource> + +QT_BEGIN_NAMESPACE + +class QGeoSatelliteInfoSourceGeoclueMaster : public QGeoSatelliteInfoSource, public QGeoclueMaster +{ + Q_OBJECT + +public: + explicit QGeoSatelliteInfoSourceGeoclueMaster(QObject *parent = 0); + ~QGeoSatelliteInfoSourceGeoclueMaster(); + + bool init(); + + int minimumUpdateInterval() const Q_DECL_OVERRIDE; + Error error() const Q_DECL_OVERRIDE; + + void startUpdates() Q_DECL_OVERRIDE; + void stopUpdates() Q_DECL_OVERRIDE; + void requestUpdate(int timeout = 0) Q_DECL_OVERRIDE; + + void satelliteChanged(int timestamp, int satellitesUsed, int satellitesVisible, + const QList<int> &usedPrn, const QList<QGeoSatelliteInfo> &satInfos); + + void requestUpdateFinished(int timestamp, int satellitesUsed, int satellitesVisible, + const QList<int> &usedPrn, const QList<QGeoSatelliteInfo> &satInfos); + +private slots: + void positionProviderChanged(const QByteArray &service, const QByteArray &path); + +private: + bool configureSatelliteSource(); + void cleanupSatelliteSource(); + + GeoclueSatellite *m_sat; + QTimer m_requestTimer; + QList<QGeoSatelliteInfo> m_inView; + QList<QGeoSatelliteInfo> m_inUse; +}; + +QT_END_NAMESPACE + +#endif // QGEOSATELLITEINFOSOURCE_GEOCLUEMASTER_H |