diff options
author | Kibum Kim <kb0929.kim@samsung.com> | 2012-01-07 00:46:29 +0900 |
---|---|---|
committer | Kibum Kim <kb0929.kim@samsung.com> | 2012-01-07 00:46:29 +0900 |
commit | 0c44dc6cd8d3ede16172f22fa2b7c6af4459e55d (patch) | |
tree | 327fd58b5a721a2ecf835f2eccffde08cdbc4070 /.pc | |
parent | 9f11ee482a4a28d6e85613ac5c765c588fdf20aa (diff) | |
download | geoclue-0c44dc6cd8d3ede16172f22fa2b7c6af4459e55d.tar.gz geoclue-0c44dc6cd8d3ede16172f22fa2b7c6af4459e55d.tar.bz2 geoclue-0c44dc6cd8d3ede16172f22fa2b7c6af4459e55d.zip |
Git init
Diffstat (limited to '.pc')
81 files changed, 14144 insertions, 0 deletions
diff --git a/.pc/.quilt_patches b/.pc/.quilt_patches new file mode 100755 index 0000000..6857a8d --- /dev/null +++ b/.pc/.quilt_patches @@ -0,0 +1 @@ +debian/patches diff --git a/.pc/.quilt_series b/.pc/.quilt_series new file mode 100755 index 0000000..c206706 --- /dev/null +++ b/.pc/.quilt_series @@ -0,0 +1 @@ +series diff --git a/.pc/.version b/.pc/.version new file mode 100755 index 0000000..0cfbf08 --- /dev/null +++ b/.pc/.version @@ -0,0 +1 @@ +2 diff --git a/.pc/applied-patches b/.pc/applied-patches new file mode 100755 index 0000000..43feb46 --- /dev/null +++ b/.pc/applied-patches @@ -0,0 +1,2 @@ +tizen.patch +geoclue_0.12.0-20slp2.patch diff --git a/.pc/geoclue_0.12.0-20slp2.patch/.timestamp b/.pc/geoclue_0.12.0-20slp2.patch/.timestamp new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/geoclue_0.12.0-20slp2.patch/.timestamp diff --git a/.pc/geoclue_0.12.0-20slp2.patch/configure.ac b/.pc/geoclue_0.12.0-20slp2.patch/configure.ac new file mode 100755 index 0000000..5a72d82 --- /dev/null +++ b/.pc/geoclue_0.12.0-20slp2.patch/configure.ac @@ -0,0 +1,197 @@ +AC_PREREQ(2.59) +AC_INIT(geoclue, 0.12.0, http://geoclue.freedesktop.org) + +AC_CONFIG_SRCDIR(geoclue/gc-iface-geoclue.c) +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE([1.9 foreign]) +GEOCLUE_VERSION=0.12.0 + +AC_PROG_CC +AC_ISC_POSIX + +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_GCC_TRADITIONAL +AM_PROG_LIBTOOL + +#GTK_DOC_CHECK(1.0) +AC_CHECK_PROGS(XSLT, xsltproc) + +AC_ARG_ENABLE(system-bus, + [AC_HELP_STRING([--enable-system-bus], + [Use the system bus instead of session bus])], + enable_system_bus="$enableval", + enable_system_bus=no) + +AM_CONDITIONAL(USE_SYSTEM_BUS, test x$enable_system_bus = xyes) +if test x$enable_system_bus = xyes; then + AC_DEFINE(GEOCLUE_DBUS_BUS, DBUS_BUS_SYSTEM, Use the system bus) +else + AC_DEFINE(GEOCLUE_DBUS_BUS, DBUS_BUS_SESSION, Use the session bus) +fi + +PKG_CHECK_MODULES(GEOCLUE, [ + glib-2.0 + gobject-2.0 + dbus-glib-1 >= 0.60 + libxml-2.0 +]) +AC_SUBST(GEOCLUE_LIBS) +AC_SUBST(GEOCLUE_CFLAGS) + +PKG_CHECK_MODULES(MASTER, [ + gconf-2.0 +]) +AC_SUBST(MASTER_LIBS) +AC_SUBST(MASTER_CFLAGS) + +AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool) +AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal) + +DBUS_SERVICES_DIR="${datadir}/dbus-1/services" +AC_SUBST(DBUS_SERVICES_DIR) +AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for D-Bus is]) + +CFLAGS="$CFLAGS -g -Wall -Werror -Wno-format" + +# ----------------------------------------------------------- +# gtk+ +# ----------------------------------------------------------- +AC_ARG_ENABLE(gtk, + AS_HELP_STRING([--enable-gtk=@<:@no/yes/auto@:>@], + [build with gtk support]), , + enable_gtk=no) + +if test "x$enable_gtk" != "xno"; then + PKG_CHECK_MODULES(GTK, + [ + gtk+-2.0 + ], have_gtk="yes", have_gtk="no") + + if test "x$have_gtk" = "xyes"; then + AC_DEFINE(HAVE_GTK, 1, [Define if you have gtk+]) + fi +else + have_gtk=no +fi + +if test "x$enable_gtk" = "xyes" -a "x$have_gtk" != "xyes"; then + AC_MSG_ERROR(["Couldn't find gtk dependencies."]) +fi + +AM_CONDITIONAL(HAVE_GTK, test "x$have_gtk" = "xyes") +AC_SUBST(GTK_LIBS) +AC_SUBST(GTK_CFLAGS) + +# ----------------------------------------------------------- +# connectivity +# ----------------------------------------------------------- + +CONNECTIVITY="None" + +AC_ARG_ENABLE(conic, + AS_HELP_STRING([--enable-conic=@<:@no/yes/auto@:>@], + [build with conic support]), , + enable_conic=auto) + +if test "x$enable_conic" != "xno"; then + PKG_CHECK_MODULES(CONIC, + [ + conic + ], have_conic="yes", have_conic="no") + + if test "x$have_conic" = "xyes"; then + CONNECTIVITY="Maemo LibConIC" + CONNECTIVITY_LIBS=${CONIC_LIBS} + CONNECTIVITY_CFLAGS=${CONIC_CFLAGS} + AC_DEFINE(HAVE_CONIC, 1, [define if libconic is installed]) + fi +else + have_conic=no +fi + +if test "x$enable_conic" = "xyes" -a "x$have_conic" != "xyes"; then + AC_MSG_ERROR(["Couldn't find conic dependencies."]) +fi + +AC_ARG_ENABLE(networkmanager, + AS_HELP_STRING([--enable-networkmanager=@<:@no/yes/auto@:>@], + [build with NetworkManager support]), , + enable_networkmanager=auto) + +if test "x$enable_networkmanager" != "xno"; then + PKG_CHECK_MODULES(NETWORK_MANAGER, + [ + NetworkManager libnm_glib + ], have_networkmanager="yes", have_networkmanager="no") + + if test "x$have_networkmanager" = "xyes"; then + CONNECTIVITY="Network Manager" + CONNECTIVITY_LIBS=${NETWORK_MANAGER_LIBS} + CONNECTIVITY_CFLAGS=${NETWORK_MANAGER_CFLAGS} + AC_DEFINE(HAVE_NETWORK_MANAGER, 1, [define if Network Manager is installed]) + fi +else + have_networkmanager=no +fi + +if test "x$enable_networkmanager" = "xyes" -a "x$have_networkmanager" != "xyes"; then + AC_MSG_ERROR(["Couldn't find Network Manager dependencies."]) +fi + +AC_SUBST(CONNECTIVITY_LIBS) +AC_SUBST(CONNECTIVITY_CFLAGS) + +PROVIDER_SUBDIRS="nominatim" + +AC_ARG_ENABLE(gpsd, + AS_HELP_STRING([--enable-gpsd=@<:@no/yes/auto@:>@], + [build with gpsd support]), , + enable_gpsd=auto) + +if test "x$enable_gpsd" != "xno"; then + PKG_CHECK_MODULES(GPSD, [libgps >= 2.91], have_gpsd="yes", have_gpsd="no") + if test "x$have_gpsd" = "xyes"; then + PROVIDER_SUBDIRS="$PROVIDER_SUBDIRS gpsd" + else + NO_BUILD_PROVIDERS="$NO_BUILD_PROVIDERS gpsd" + fi +else + have_gpsd=no +fi + +if test "x$enable_gpsd" = "xyes" -a "x$have_gpsd" != "xyes"; then + AC_MSG_ERROR(["Couldn't find gpsd dependencies - libgps >= 2.90."]) +fi +AC_SUBST(GPSD_LIBS) +AC_SUBST(GPSD_CFLAGS) + +AC_SUBST(PROVIDER_SUBDIRS) +AC_SUBST(NO_BUILD_PROVIDERS) + +AC_CONFIG_FILES([ +geoclue.pc +Makefile +interfaces/Makefile +geoclue/Makefile +providers/Makefile +providers/gpsd/Makefile +providers/nominatim/Makefile +src/Makefile +]) +#docs/Makefile +#docs/reference/Makefile +#docs/tools/Makefile + +AC_OUTPUT + +echo "" +echo "Geoclue ${VERSION} has been configured as follows: " +echo "---------------------------------------------------" +echo "Source code location: ${srcdir}" +echo "Compiler: ${CC}" +echo "Network connectivity: ${CONNECTIVITY}" +echo "Providers: ${PROVIDER_SUBDIRS}" +echo "Excluded providers: ${NO_BUILD_PROVIDERS}" +echo "" diff --git a/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/Makefile.am b/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/Makefile.am new file mode 100755 index 0000000..0c45f40 --- /dev/null +++ b/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/Makefile.am @@ -0,0 +1,36 @@ +libexec_PROGRAMS = geoclue-gpsd + +geoclue_gpsd_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) \ + $(GPSD_CFLAGS) + +geoclue_gpsd_LDFLAGS = \ + -Wl,--warn-unresolved-symbols + +geoclue_gpsd_LDADD = \ + $(GEOCLUE_LIBS) \ + $(GPSD_LIBS) \ + -lm \ + $(top_builddir)/geoclue/libgeoclue.la + +geoclue_gpsd_SOURCES = \ + geoclue-gpsd.c + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-gpsd.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Gpsd.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + @sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/geoclue-gpsd.c b/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/geoclue-gpsd.c new file mode 100755 index 0000000..5eefad2 --- /dev/null +++ b/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/geoclue-gpsd.c @@ -0,0 +1,497 @@ +/* + * Geoclue + * geoclue-gpsd.c - Geoclue Position backend for gpsd + * + * Authors: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/* TODO: + * + * call to gps_set_callback blocks for a long time if + * BT device is not present. + * + **/ + +#include <config.h> + +#include <math.h> +#include <gps.h> +#include <string.h> + +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-velocity.h> + +typedef struct gps_data_t gps_data; +typedef struct gps_fix_t gps_fix; + +/* only listing used tags */ +typedef enum { + NMEA_NONE, + NMEA_GSA, + NMEA_GGA, + NMEA_GSV, + NMEA_RMC +} NmeaTag; + + +typedef struct { + GcProvider parent; + + char *host; + char *port; + + gps_data *gpsdata; + + gps_fix *last_fix; + + GeoclueStatus last_status; + GeocluePositionFields last_pos_fields; + GeoclueAccuracy *last_accuracy; + GeoclueVelocityFields last_velo_fields; + + GMainLoop *loop; + +} GeoclueGpsd; + +typedef struct { + GcProviderClass parent_class; +} GeoclueGpsdClass; + +static void geoclue_gpsd_position_init (GcIfacePositionClass *iface); +static void geoclue_gpsd_velocity_init (GcIfaceVelocityClass *iface); + +#define GEOCLUE_TYPE_GPSD (geoclue_gpsd_get_type ()) +#define GEOCLUE_GPSD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GPSD, GeoclueGpsd)) + +G_DEFINE_TYPE_WITH_CODE (GeoclueGpsd, geoclue_gpsd, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_gpsd_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_VELOCITY, + geoclue_gpsd_velocity_init)) + +static void geoclue_gpsd_stop_gpsd (GeoclueGpsd *self); +static gboolean geoclue_gpsd_start_gpsd (GeoclueGpsd *self); + + +/* defining global GeoclueGpsd because gpsd does not support "user_data" + * pointers in callbacks */ +GeoclueGpsd *gpsd; + + + +/* Geoclue interface */ +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *status = gpsd->last_status; + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (provider); + + g_main_loop_quit (gpsd->loop); +} + +static void +geoclue_gpsd_set_status (GeoclueGpsd *self, GeoclueStatus status) +{ + if (status != self->last_status) { + self->last_status = status; + + /* make position and velocity invalid if no fix */ + if (status != GEOCLUE_STATUS_AVAILABLE) { + self->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + self->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + } + g_debug("status changed [%d]", status); + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (self), + status); + } +} + +static gboolean +set_options (GcIfaceGeoclue *gc, + GHashTable *options, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + char *port, *host; + gboolean changed = FALSE; + + host = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSHost"); + port = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSPort"); + + if (port == NULL) { + port = DEFAULT_GPSD_PORT; + } + + /* new values? */ + if (g_strcmp0 (host, gpsd->host) != 0 || + g_strcmp0 (port, gpsd->port) != 0) { + changed = TRUE; + } + + if (!changed) { + return TRUE; + } + + /* update private values with new ones, restart gpsd */ + g_free (gpsd->port); + gpsd->port = NULL; + g_free (gpsd->host); + gpsd->host = NULL; + + geoclue_gpsd_stop_gpsd (gpsd); + + if (host == NULL) { + return TRUE; + } + + gpsd->port = g_strdup (port); + gpsd->host = g_strdup (host); + if (!geoclue_gpsd_start_gpsd (gpsd)) { + geoclue_gpsd_set_status (gpsd, GEOCLUE_STATUS_ERROR); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_FAILED, "Gpsd not found"); + return FALSE; + } + return TRUE; +} + +static void +finalize (GObject *object) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (object); + + geoclue_gpsd_stop_gpsd (gpsd); + g_free (gpsd->last_fix); + geoclue_accuracy_free (gpsd->last_accuracy); + + g_free (gpsd->port); + if (gpsd->host) { + g_free (gpsd->host); + } + + ((GObjectClass *) geoclue_gpsd_parent_class)->finalize (object); +} + +static void +geoclue_gpsd_class_init (GeoclueGpsdClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + GcProviderClass *p_class = (GcProviderClass *) klass; + + o_class->finalize = finalize; + + p_class->get_status = get_status; + p_class->set_options = set_options; + p_class->shutdown = shutdown; +} + + +static gboolean +equal_or_nan (double a, double b) +{ + if (isnan (a) && isnan (b)) { + return TRUE; + } + return a == b; +} + +static void +geoclue_gpsd_update_position (GeoclueGpsd *gpsd) +{ + if(gpsd->last_status != GEOCLUE_STATUS_AVAILABLE) + return; + + gps_fix *fix = &gpsd->gpsdata->fix; + gps_fix *last_fix = gpsd->last_fix; + + + if (isnan(fix->time)==0){ + last_fix->time = fix->time; + } + if (equal_or_nan (fix->latitude, last_fix->latitude) && + equal_or_nan (fix->longitude, last_fix->longitude) && + equal_or_nan (fix->altitude, last_fix->altitude)) { + return; + } + /* save values */ + if (fix->mode >= MODE_2D && isnan(fix->latitude)==0) { + last_fix->latitude = fix->latitude; + } + if (fix->mode >= MODE_2D && isnan(fix->longitude)==0) { + last_fix->longitude = fix->longitude; + } + if (fix->mode == MODE_3D && isnan(fix->altitude)==0){ + last_fix->altitude = fix->altitude; + } + + if (isnan(fix->epx)==0){ + last_fix->epx = fix->epx; + } + if (isnan(fix->epy)==0){ + last_fix->epy = fix->epy; + } + if (isnan(fix->epv)==0){ + last_fix->epv = fix->epv; + } + geoclue_accuracy_set_details (gpsd->last_accuracy, + GEOCLUE_ACCURACY_LEVEL_DETAILED, + sqrt(pow(last_fix->epx, 2)+pow(last_fix->epy, 2)), fix->epv); + gpsd->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + gpsd->last_pos_fields |= (isnan (fix->latitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_LATITUDE; + gpsd->last_pos_fields |= (isnan (fix->longitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_LONGITUDE; + gpsd->last_pos_fields |= (isnan (fix->altitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_ALTITUDE; + + g_debug("Update position: %lf, %lf, %lf, fields:0x%x, Accuracy level: %d, vert:%lf hori:%lf", + last_fix->latitude, last_fix->longitude, last_fix->altitude, gpsd->last_pos_fields, + GEOCLUE_ACCURACY_LEVEL_DETAILED, sqrt(pow(last_fix->epx, 2)+pow(last_fix->epy, 2)), fix->epv); + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (gpsd), gpsd->last_pos_fields, + (int)(last_fix->time+0.5), + last_fix->latitude, last_fix->longitude, last_fix->altitude, + gpsd->last_accuracy); + +} + +static void +geoclue_gpsd_update_velocity (GeoclueGpsd *gpsd) +{ + if(gpsd->last_status != GEOCLUE_STATUS_AVAILABLE) + return; + + gps_fix *fix = &gpsd->gpsdata->fix; + gps_fix *last_fix = gpsd->last_fix; + + if (isnan(fix->time)==0){ + last_fix->time = fix->time; + } + if (equal_or_nan (fix->track, last_fix->track) && + equal_or_nan (fix->speed, last_fix->speed) && + equal_or_nan (fix->climb, last_fix->climb)) { + return; + } + if (fix->mode >= MODE_2D && isnan(fix->track)==0){ + last_fix->track = fix->track; + } + if (fix->mode >= MODE_2D && isnan(fix->speed)==0){ + last_fix->speed = fix->speed; + } + if (fix->mode >= MODE_3D && isnan(fix->climb)==0){ + last_fix->climb = fix->climb; + } + + g_debug("Update velocity: %lf, %lf, %lf", last_fix->track, last_fix->speed, last_fix->climb); + gpsd->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + gpsd->last_velo_fields |= (isnan (last_fix->track)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_DIRECTION; + gpsd->last_velo_fields |= (isnan (last_fix->speed)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_SPEED; + gpsd->last_velo_fields |= (isnan (last_fix->climb)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_CLIMB; + + gc_iface_velocity_emit_velocity_changed + (GC_IFACE_VELOCITY (gpsd), gpsd->last_velo_fields, + (int)(last_fix->time+0.5), + last_fix->speed, last_fix->track, last_fix->climb); +} + +static void +geoclue_gpsd_update_status (GeoclueGpsd *gpsd) +{ + GeoclueStatus status; + + /* gpsdata->online is supposedly always up-to-date */ + if (gpsd->gpsdata->online <= 0) { + status = GEOCLUE_STATUS_UNAVAILABLE; + } else if (gpsd->gpsdata->set & STATUS_SET) { + gpsd->gpsdata->set &= ~(STATUS_SET); + if (gpsd->gpsdata->status > 0) { + status = GEOCLUE_STATUS_AVAILABLE; + } else { + status = GEOCLUE_STATUS_ACQUIRING; + } + } else { + status = GEOCLUE_STATUS_AVAILABLE; + return; + } + + geoclue_gpsd_set_status (gpsd, status); +} + +static void +gpsd_raw_hook (gps_data *gpsdata, char *message, size_t len) +{ + if(gpsdata == NULL) + return; + + geoclue_gpsd_update_status (gpsd); + geoclue_gpsd_update_position (gpsd); + geoclue_gpsd_update_velocity (gpsd); +} + +static void +geoclue_gpsd_stop_gpsd (GeoclueGpsd *self) +{ + if (self->gpsdata) { + gps_close (self->gpsdata); + self->gpsdata = NULL; + } +} + +static gboolean +geoclue_gpsd_start_gpsd (GeoclueGpsd *self) +{ + self->gpsdata = gps_open (self->host, self->port); + if (self->gpsdata) { + gps_stream(self->gpsdata, WATCH_ENABLE | WATCH_NEWSTYLE, NULL); + gps_set_raw_hook (self->gpsdata, gpsd_raw_hook); + return TRUE; + } else { + g_warning ("gps_open() failed, is gpsd running (host=%s,port=%s)?", self->host, self->port); + return FALSE; + } +} + +gboolean +gpsd_poll(gpointer data) +{ + GeoclueGpsd *self = (GeoclueGpsd*)data; + if (self->gpsdata) { + if (gps_poll(self->gpsdata) < 0) { + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ERROR); + geoclue_gpsd_stop_gpsd(self); + return FALSE; + } + } + return TRUE; +} + +static void +geoclue_gpsd_init (GeoclueGpsd *self) +{ + self->gpsdata = NULL; + self->last_fix = g_new0 (gps_fix, 1); + + self->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + self->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + self->last_accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); + + gc_provider_set_details (GC_PROVIDER (self), + "org.freedesktop.Geoclue.Providers.Gpsd", + "/org/freedesktop/Geoclue/Providers/Gpsd", + "Gpsd", "Gpsd provider"); + + self->port = g_strdup (DEFAULT_GPSD_PORT); + self->host = g_strdup ("localhost"); + + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ACQUIRING); + if (!geoclue_gpsd_start_gpsd (self)) { + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ERROR); + } +} + +static gboolean +get_position (GcIfacePosition *gc, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *timestamp = (int)(gpsd->last_fix->time+0.5); + *latitude = gpsd->last_fix->latitude; + *longitude = gpsd->last_fix->longitude; + *altitude = gpsd->last_fix->altitude; + *fields = gpsd->last_pos_fields; + *accuracy = geoclue_accuracy_copy (gpsd->last_accuracy); + + return TRUE; +} + +static void +geoclue_gpsd_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = get_position; +} + +static gboolean +get_velocity (GcIfaceVelocity *gc, + GeoclueVelocityFields *fields, + int *timestamp, + double *speed, + double *direction, + double *climb, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *timestamp = (int)(gpsd->last_fix->time+0.5); + *speed = gpsd->last_fix->speed; + *direction = gpsd->last_fix->track; + *climb = gpsd->last_fix->climb; + *fields = gpsd->last_velo_fields; + + return TRUE; +} + +static void +geoclue_gpsd_velocity_init (GcIfaceVelocityClass *iface) +{ + iface->get_velocity = get_velocity; +} + +int +main (int argc, + char **argv) +{ + g_type_init (); + + gpsd = g_object_new (GEOCLUE_TYPE_GPSD, NULL); + + gpsd->loop = g_main_loop_new (NULL, TRUE); + g_timeout_add(500, gpsd_poll, (gpointer)gpsd); + + g_main_loop_run (gpsd->loop); + + g_main_loop_unref (gpsd->loop); + g_object_unref (gpsd); + + return 0; +} diff --git a/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/setting.c b/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/setting.c new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/setting.c diff --git a/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/setting.h b/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/setting.h new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/geoclue_0.12.0-20slp2.patch/providers/gpsd/setting.h diff --git a/.pc/tizen.patch/.timestamp b/.pc/tizen.patch/.timestamp new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/.timestamp diff --git a/.pc/tizen.patch/AUTHORS b/.pc/tizen.patch/AUTHORS new file mode 100755 index 0000000..e39077f --- /dev/null +++ b/.pc/tizen.patch/AUTHORS @@ -0,0 +1,3 @@ +Keith Preston <keithpre@gmail.com> +Jussi Kukkonen <jku@o-hand.com> +Iain Holmes <Iain@openedhand.com> diff --git a/.pc/tizen.patch/Makefile.am b/.pc/tizen.patch/Makefile.am new file mode 100755 index 0000000..87a8b1c --- /dev/null +++ b/.pc/tizen.patch/Makefile.am @@ -0,0 +1,12 @@ +SUBDIRS = interfaces geoclue src providers example test docs + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = geoclue.pc + +DISTCLEANFILES = \ + geoclue.pc + +EXTRA_DIST = \ + geoclue.pc.in + +DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc diff --git a/.pc/tizen.patch/autogen.sh b/.pc/tizen.patch/autogen.sh new file mode 100755 index 0000000..326c76a --- /dev/null +++ b/.pc/tizen.patch/autogen.sh @@ -0,0 +1,45 @@ +#! /bin/sh + +LIBTOOLIZE=libtoolize +AUTOMAKE=automake +ACLOCAL=aclocal +AUTOCONF=autoconf +AUTOHEADER=autoheader +GTKDOCIZE=gtkdocize + +# Check for binaries + +[ "x$(which ${LIBTOOLIZE})x" = "xx" ] && { + echo "${LIBTOOLIZE} not found. Please install it." + exit 1 +} + +[ "x$(which ${AUTOMAKE})x" = "xx" ] && { + echo "${AUTOMAKE} not found. Please install it." + exit 1 +} + +[ "x$(which ${ACLOCAL})x" = "xx" ] && { + echo "${ACLOCAL} not found. Please install it." + exit 1 +} + +[ "x$(which ${AUTOCONF})x" = "xx" ] && { + echo "${AUTOCONF} not found. Please install it." + exit 1 +} + +[ "x$(which ${GTKDOCIZE})x" = "xx" ] && { + echo "${GTKDOCIZE} not found. Please install it." + exit 1 +} + +gtkdocize || exit 1 + +"${ACLOCAL}" \ +&& "${LIBTOOLIZE}" \ +&& "${AUTOHEADER}" \ +&& "${AUTOMAKE}" --add-missing \ +&& "${AUTOCONF}" + +$(dirname "${0}")/configure "$@" diff --git a/.pc/tizen.patch/configure.ac b/.pc/tizen.patch/configure.ac new file mode 100755 index 0000000..ec24938 --- /dev/null +++ b/.pc/tizen.patch/configure.ac @@ -0,0 +1,283 @@ +AC_PREREQ(2.59) +AC_INIT(geoclue, 0.12.0, http://geoclue.freedesktop.org) + +AC_CONFIG_SRCDIR(geoclue/gc-iface-geoclue.c) +AM_CONFIG_HEADER(config.h) +AM_INIT_AUTOMAKE([1.9 foreign]) +GEOCLUE_VERSION=0.12.0 + +# Enable silent build when available (Automake 1.11) +m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])]) + +AC_PROG_CC +AC_ISC_POSIX + +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_GCC_TRADITIONAL +AM_PROG_LIBTOOL +GLIB_GSETTINGS + +GTK_DOC_CHECK(1.0) +AC_CHECK_PROGS(XSLT, xsltproc) + +AC_ARG_ENABLE(system-bus, + [AC_HELP_STRING([--enable-system-bus], + [Use the system bus instead of session bus])], + enable_system_bus="$enableval", + enable_system_bus=no) + +AM_CONDITIONAL(USE_SYSTEM_BUS, test x$enable_system_bus = xyes) +if test x$enable_system_bus = xyes; then + AC_DEFINE(GEOCLUE_DBUS_BUS, DBUS_BUS_SYSTEM, Use the system bus) +else + AC_DEFINE(GEOCLUE_DBUS_BUS, DBUS_BUS_SESSION, Use the session bus) +fi + +PKG_CHECK_MODULES(GEOCLUE, [ + glib-2.0 + gobject-2.0 + dbus-glib-1 >= 0.86 + libxml-2.0 +]) +AC_SUBST(GEOCLUE_LIBS) +AC_SUBST(GEOCLUE_CFLAGS) + +PKG_CHECK_MODULES(MASTER, [ + gio-2.0 >= 2.25.7 + glib-2.0 +]) +AC_SUBST(MASTER_LIBS) +AC_SUBST(MASTER_CFLAGS) + +AC_PATH_PROG(DBUS_BINDING_TOOL, dbus-binding-tool) +AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal) + +DBUS_SERVICES_DIR="${datadir}/dbus-1/services" +AC_SUBST(DBUS_SERVICES_DIR) +AC_DEFINE_UNQUOTED(DBUS_SERVICES_DIR, "$DBUS_SERVICES_DIR", [Where services dir for D-Bus is]) + +CFLAGS="$CFLAGS -g -Wall -Werror -Wno-format" + +# ----------------------------------------------------------- +# gtk+ +# ----------------------------------------------------------- +AC_ARG_ENABLE(gtk, + AS_HELP_STRING([--enable-gtk=@<:@no/yes/auto@:>@], + [build with gtk support]), , + enable_gtk=auto) + +if test "x$enable_gtk" != "xno"; then + PKG_CHECK_MODULES(GTK, + [ + gtk+-2.0 + ], have_gtk="yes", have_gtk="no") + + if test "x$have_gtk" = "xyes"; then + AC_DEFINE(HAVE_GTK, 1, [Define if you have gtk+]) + fi +else + have_gtk=no +fi + +if test "x$enable_gtk" = "xyes" -a "x$have_gtk" != "xyes"; then + AC_MSG_ERROR([Couldn't find gtk dependencies.]) +fi + +AM_CONDITIONAL(HAVE_GTK, test "x$have_gtk" = "xyes") +AC_SUBST(GTK_LIBS) +AC_SUBST(GTK_CFLAGS) + +# ----------------------------------------------------------- +# connectivity +# ----------------------------------------------------------- + +CONNECTIVITY="None" + +AC_ARG_ENABLE(conic, + AS_HELP_STRING([--enable-conic=@<:@no/yes/auto@:>@], + [build with conic support]), , + enable_conic=auto) + +if test "x$enable_conic" != "xno"; then + PKG_CHECK_MODULES(CONIC, + [ + conic + ], have_conic="yes", have_conic="no") + + if test "x$have_conic" = "xyes"; then + CONNECTIVITY="Maemo LibConIC" + CONNECTIVITY_LIBS=${CONIC_LIBS} + CONNECTIVITY_CFLAGS=${CONIC_CFLAGS} + AC_DEFINE(HAVE_CONIC, 1, [define if libconic is installed]) + fi +else + have_conic=no +fi + +if test "x$enable_conic" = "xyes" -a "x$have_conic" != "xyes"; then + AC_MSG_ERROR([Couldn't find conic dependencies.]) +fi + +AC_ARG_ENABLE(connman, + AS_HELP_STRING([--enable-connman=@<:@no/yes/auto@:>@], + [build with connman support]), , + enable_connman=auto) + +if test "x$enable_connman" != "xno"; then + CONNECTIVITY="ConnMan" + AC_DEFINE(HAVE_CONNMAN, 1, [define if libconmann is installed]) +else + have_connman=no +fi + +AC_ARG_ENABLE(networkmanager, + AS_HELP_STRING([--enable-networkmanager=@<:@no/yes/auto@:>@], + [build with NetworkManager support]), , + enable_networkmanager=auto) + +if test "x$enable_networkmanager" != "xno"; then + PKG_CHECK_MODULES(NETWORK_MANAGER, + [ + NetworkManager libnm-glib libnm-util + ], have_networkmanager="yes", have_networkmanager="no") + + if test "x$have_networkmanager" = "xyes"; then + CONNECTIVITY="Network Manager" + CONNECTIVITY_LIBS=${NETWORK_MANAGER_LIBS} + CONNECTIVITY_CFLAGS=${NETWORK_MANAGER_CFLAGS} + AC_DEFINE(HAVE_NETWORK_MANAGER, 1, [define if Network Manager is installed]) + fi +else + have_networkmanager=no +fi + +if test "x$enable_networkmanager" = "xyes" -a "x$have_networkmanager" != "xyes"; then + AC_MSG_ERROR([Couldn't find Network Manager dependencies.]) +fi + +AC_SUBST(CONNECTIVITY_LIBS) +AC_SUBST(CONNECTIVITY_CFLAGS) + +PROVIDER_SUBDIRS="example hostip geonames nominatim manual plazes localnet yahoo gsmloc" + +# ----------------------------------------------------------- +# gypsy / gpsd / skyhook +# ----------------------------------------------------------- + +GYPSY_REQUIRED=0.7.1 +AC_ARG_ENABLE(gypsy, + AS_HELP_STRING([--enable-gypsy=@<:@no/yes/auto@:>@], + [build with gypsy support]), , + enable_gypsy=auto) + +if test "x$enable_gypsy" != "xno"; then + PKG_CHECK_MODULES(GYPSY, + [ + gypsy >= $GYPSY_REQUIRED + ], have_gypsy="yes", have_gypsy="no") + + if test "x$have_gypsy" = "xyes"; then + PROVIDER_SUBDIRS="$PROVIDER_SUBDIRS gypsy" + else + NO_BUILD_PROVIDERS="$NO_BUILD_PROVIDERS gypsy" + fi + else + have_gypsy=no +fi + +if test "x$enable_gypsy" = "xyes" -a "x$have_gypsy" != "xyes"; then + AC_MSG_ERROR([Couldn't find gypsy dependencies.]) +fi +AC_SUBST(GYPSY_LIBS) +AC_SUBST(GYPSY_CFLAGS) + +AC_ARG_ENABLE(gpsd, + AS_HELP_STRING([--enable-gpsd=@<:@no/yes/auto@:>@], + [build with gpsd support]), , + enable_gpsd=auto) + +if test "x$enable_gpsd" != "xno"; then + PKG_CHECK_MODULES(GPSD, [libgps >= 2.91], have_gpsd="yes", have_gpsd="no") + if test "x$have_gpsd" = "xyes"; then + PROVIDER_SUBDIRS="$PROVIDER_SUBDIRS gpsd" + else + NO_BUILD_PROVIDERS="$NO_BUILD_PROVIDERS gpsd" + fi +else + have_gpsd=no +fi + +if test "x$enable_gpsd" = "xyes" -a "x$have_gpsd" != "xyes"; then + AC_MSG_ERROR([Couldn't find gpsd dependencies - libgps >= 2.90.]) +fi +AC_SUBST(GPSD_LIBS) +AC_SUBST(GPSD_CFLAGS) + +AC_ARG_ENABLE(skyhook, + AS_HELP_STRING([--enable-skyhook=@<:@no/yes/auto@:>@], + [build with skyhook support]), , + enable_skyhook=auto) + +if test "x$enable_skyhook" != "xno"; then + PKG_CHECK_MODULES(SKYHOOK, [ + libsoup-gnome-2.4 + ], have_skyhook=yes, have_skyhook=no) + + if test "x$have_skyhook" = "xyes"; then + PROVIDER_SUBDIRS="$PROVIDER_SUBDIRS skyhook" + GPSD_LIBS="-lgps" + else + NO_BUILD_PROVIDERS="$NO_BUILD_PROVIDERS skyhook" + fi + else + have_skyhook=no +fi + +if test "x$enable_skyhook" = "xyes" -a "x$have_skyhook" != "xyes"; then + AC_MSG_ERROR([Couldn't find gpsd dependencies.]) +fi +AC_SUBST(SKYHOOK_LIBS) +AC_SUBST(SKYHOOK_CFLAGS) + +AC_SUBST(PROVIDER_SUBDIRS) +AC_SUBST(NO_BUILD_PROVIDERS) + +AC_CONFIG_FILES([ +geoclue.pc +Makefile +docs/Makefile +docs/reference/Makefile +docs/tools/Makefile +interfaces/Makefile +geoclue/Makefile +example/Makefile +test/Makefile +providers/Makefile +providers/example/Makefile +providers/gypsy/Makefile +providers/gpsd/Makefile +providers/hostip/Makefile +providers/geonames/Makefile +providers/manual/Makefile +providers/nominatim/Makefile +providers/plazes/Makefile +providers/localnet/Makefile +providers/yahoo/Makefile +providers/gsmloc/Makefile +providers/skyhook/Makefile +src/Makefile +]) + +AC_OUTPUT + +echo "" +echo "Geoclue ${VERSION} has been configured as follows: " +echo "---------------------------------------------------" +echo "Source code location: ${srcdir}" +echo "Compiler: ${CC}" +echo "Network connectivity: ${CONNECTIVITY}" +echo "Providers: ${PROVIDER_SUBDIRS}" +echo "Excluded providers: ${NO_BUILD_PROVIDERS}" +echo "" diff --git a/.pc/tizen.patch/example/Makefile.am b/.pc/tizen.patch/example/Makefile.am new file mode 100755 index 0000000..16d3fec --- /dev/null +++ b/.pc/tizen.patch/example/Makefile.am @@ -0,0 +1,23 @@ +noinst_PROGRAMS = \ + position-example \ + position-async-example \ + master-example \ + master-pos-example \ + address-example \ + geocode-example \ + revgeocode-example \ + common-example + +common_example_SOURCES = common-example.c +position_example_SOURCES = position-example.c +position_async_example_SOURCES = position-async-example.c +address_example_SOURCES = address-example.c +geocode_example_SOURCES = geocode-example.c +revgeocode_example_SOURCES = revgeocode-example.c +master_example_SOURCES = master-example.c +master_pos_example_SOURCES = master-pos-example.c + +AM_CFLAGS = $(GEOCLUE_CFLAGS) +LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la diff --git a/.pc/tizen.patch/example/master-pos-example.c b/.pc/tizen.patch/example/master-pos-example.c new file mode 100755 index 0000000..4966c58 --- /dev/null +++ b/.pc/tizen.patch/example/master-pos-example.c @@ -0,0 +1,173 @@ +/* + * Geoclue + * master-example.c - Example using the Master client API + * + * Authors: Iain Holmes <iain@openedhand.com> + * Jussi Kukkonen <jku@o-hand.com> + * Copyright 2008 by Garmin Ltd. or its subsidiaries + * 2008 OpenedHand Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + +/* This example shows typical GPS-like usage. Following params are + * given to geoclue_master_client_set_requirements(): + * min_accuracy = GEOCLUE_ACCURACY_LEVEL_DETAILED + * We require the highest level of accuracy + * min_time = 0 + * No limit on frequency of position-changed signals + * (this is not actually implemented yet) + * require_updates = TRUE + * We need position-changed signals + * allowed_resources = GEOCLUE_RESOURCE_ALL + * Any available resource can be used + * + * Geoclue master will try to select a suitable provider based on these + * requirements -- currently only Gypsy and Gpsd providers fulfill + * the above requiremens. Gpsd-provider should work out-of-the-box as + * long as gpsd is running in the default port. Gypsy provider requires + * that you set device name in the options: see README for details. + * + */ + +#include <string.h> + +#include <geoclue/geoclue-master.h> +#include <geoclue/geoclue-position.h> + +static void +provider_changed_cb (GeoclueMasterClient *client, + char *iface, + char *name, + char *description, + gpointer userdata) +{ + if (strlen (name) == 0) { + g_print ("No provider available\n"); + } else { + g_print ("now using provider: %s\n", name); + } +} + +static void +position_callback (GeocluePosition *pos, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy *accuracy, + GError *error, + gpointer userdata) +{ + if (error) { + g_printerr ("Error getting initial position: %s\n", error->message); + g_error_free (error); + } else { + if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE && + fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) { + GeoclueAccuracyLevel level; + + geoclue_accuracy_get_details (accuracy, &level, NULL, NULL); + g_print ("Initial position (accuracy %d):\n", level); + g_print ("\t%f, %f\n", latitude, longitude); + } else { + g_print ("Initial position not available.\n"); + } + } +} + + +static void +position_changed_cb (GeocluePosition *position, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy *accuracy, + gpointer userdata) +{ + if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE && + fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) { + GeoclueAccuracyLevel level; + + geoclue_accuracy_get_details (accuracy, &level, NULL, NULL); + g_print ("got position (accuracy level %d):\n", level); + g_print ("\t%f, %f\n", latitude, longitude); + + } else { + g_print ("position emitted, but latitude and longitude are not valid.\n"); + } +} + +int +main (int argc, + char **argv) +{ + GError *error = NULL; + GMainLoop *mainloop; + GeoclueMaster *master; + GeoclueMasterClient *client; + GeocluePosition *position; + + g_type_init (); + + master = geoclue_master_get_default (); + client = geoclue_master_create_client (master, NULL, NULL); + g_object_unref (master); + + g_signal_connect (G_OBJECT (client), "position-provider-changed", + G_CALLBACK (provider_changed_cb), NULL); + + /* We want provider that has detailed accuracy and emits signals. + * The provider is allowed to use any resources available. */ + if (!geoclue_master_client_set_requirements (client, + GEOCLUE_ACCURACY_LEVEL_LOCALITY, + 0, TRUE, + GEOCLUE_RESOURCE_ALL, + NULL)){ + g_printerr ("Setting requirements failed"); + g_object_unref (client); + return 1; + } + + position = geoclue_master_client_create_position (client, &error); + if (!position) { + g_warning ("Creating GeocluePosition failed: %s", error->message); + g_error_free (error); + g_object_unref (client); + return 1; + } + + g_signal_connect (G_OBJECT (position), "position-changed", + G_CALLBACK (position_changed_cb), NULL); + + geoclue_position_get_position_async (position, + (GeocluePositionCallback) position_callback, + NULL); + + mainloop = g_main_loop_new (NULL, FALSE); + g_main_loop_run (mainloop); + + g_main_loop_unref (mainloop); + g_object_unref (client); + g_object_unref (position); + + return 0; +} diff --git a/.pc/tizen.patch/example/position-example.c b/.pc/tizen.patch/example/position-example.c new file mode 100755 index 0000000..2e13627 --- /dev/null +++ b/.pc/tizen.patch/example/position-example.c @@ -0,0 +1,165 @@ +/* + * Geoclue + * position-example.c - Example using the Position client API + * + * Author: Jussi Kukkonen <jku@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <glib.h> +#include <geoclue/geoclue-position.h> + +static void +position_changed_cb (GeocluePosition *position, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy *accuracy, + gpointer userdata) +{ + if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE && + fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) { + + GeoclueAccuracyLevel level; + double horiz_acc; + + geoclue_accuracy_get_details (accuracy, &level, &horiz_acc, NULL); + g_print ("Current position:\n"); + g_print ("\t%f, %f\n", latitude, longitude); + g_print ("\tAccuracy level %d (%.0f meters)\n", level, horiz_acc); + + } else { + g_print ("Latitude and longitude not available.\n"); + } +} + +static void +unset_and_free_gvalue (gpointer val) +{ + g_value_unset (val); + g_free (val); +} + +static GHashTable * +parse_options (int argc, + char **argv) +{ + GHashTable *options; + int i; + + options = g_hash_table_new_full (g_str_hash, g_str_equal, + NULL, unset_and_free_gvalue); + + for (i = 2; i < argc; i += 2) { + GValue *val = g_new0(GValue, 1); + g_value_init (val, G_TYPE_STRING); + g_value_set_string(val, argv[i + 1]); + g_hash_table_insert (options, argv[i], val); + } + + return options; +} + +int main (int argc, char** argv) +{ + gchar *service, *path; + GeocluePosition *pos = NULL; + GeocluePositionFields fields; + int timestamp; + double lat, lon; + GeoclueAccuracy *accuracy = NULL; + GMainLoop *mainloop; + GError *error = NULL; + + g_type_init(); + + if (argc < 2 || argc % 2 != 0) { + g_printerr ("Usage:\n position-example <provider_name> [option value]\n"); + return 1; + } + + g_print ("Using provider '%s'\n", argv[1]); + service = g_strdup_printf ("org.freedesktop.Geoclue.Providers.%s", argv[1]); + path = g_strdup_printf ("/org/freedesktop/Geoclue/Providers/%s", argv[1]); + + mainloop = g_main_loop_new (NULL, FALSE); + + /* Create new GeocluePosition */ + pos = geoclue_position_new (service, path); + if (pos == NULL) { + g_printerr ("Error while creating GeocluePosition object.\n"); + return 1; + } + + g_free (service); + g_free (path); + + if (argc > 2) { + GHashTable *options; + + options = parse_options (argc, argv); + if (!geoclue_provider_set_options (GEOCLUE_PROVIDER (pos), options, &error)) { + g_printerr ("Error setting options: %s\n", + error->message); + g_error_free (error); + error = NULL; + } + g_hash_table_destroy (options); + } + + /* Query current position. We're not interested in altitude + this time, so leave it NULL. Same can be done with all other + arguments that aren't interesting to the client */ + fields = geoclue_position_get_position (pos, ×tamp, + &lat, &lon, NULL, + &accuracy, &error); + if (error) { + g_printerr ("Error getting position: %s\n", error->message); + g_error_free (error); + g_object_unref (pos); + return 1; + } + + /* Print out coordinates if they are valid */ + if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE && + fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) { + + GeoclueAccuracyLevel level; + double horiz_acc; + + geoclue_accuracy_get_details (accuracy, &level, &horiz_acc, NULL); + g_print ("Current position:\n"); + g_print ("\t%f, %f\n", lat, lon); + g_print ("\tAccuracy level %d (%.0f meters)\n", level, horiz_acc); + + } else { + g_print ("Latitude and longitude not available.\n"); + } + + geoclue_accuracy_free (accuracy); + + g_signal_connect (G_OBJECT (pos), "position-changed", + G_CALLBACK (position_changed_cb), NULL); + + g_main_loop_run (mainloop); + return 0; + +} diff --git a/.pc/tizen.patch/geoclue/Makefile.am b/.pc/tizen.patch/geoclue/Makefile.am new file mode 100755 index 0000000..5f3dcf1 --- /dev/null +++ b/.pc/tizen.patch/geoclue/Makefile.am @@ -0,0 +1,175 @@ +lib_LTLIBRARIES = libgeoclue.la + +nodist_libgeoclue_la_SOURCES = \ + geoclue-marshal.c \ + geoclue-marshal.h \ + gc-iface-address-bindings.h \ + gc-iface-address-glue.h \ + gc-iface-geoclue-bindings.h \ + gc-iface-geoclue-glue.h \ + gc-iface-geocode-bindings.h \ + gc-iface-geocode-glue.h \ + gc-iface-master-bindings.h \ + gc-iface-master-client-bindings.h \ + gc-iface-position-bindings.h \ + gc-iface-position-glue.h \ + gc-iface-reverse-geocode-bindings.h \ + gc-iface-reverse-geocode-glue.h \ + gc-iface-velocity-bindings.h \ + gc-iface-velocity-glue.h + +BUILT_SOURCES = \ + $(nodist_libgeoclue_la_SOURCES) \ + geoclue-enum-types.h \ + geoclue-enum-types.c + +libgeoclue_la_SOURCES = \ + geoclue-accuracy.c \ + geoclue-address.c \ + geoclue-address-details.c \ + geoclue-provider.c \ + geoclue-error.c \ + geoclue-geocode.c \ + geoclue-master.c \ + geoclue-master-client.c \ + geoclue-position.c \ + geoclue-reverse-geocode.c \ + geoclue-types.c \ + geoclue-velocity.c \ + gc-provider.c \ + gc-web-service.c \ + gc-iface-address.c \ + gc-iface-geoclue.c \ + gc-iface-geocode.c \ + gc-iface-position.c \ + gc-iface-reverse-geocode.c \ + gc-iface-velocity.c \ + geoclue-enum-types.c + +libgeoclue_la_LIBADD = \ + $(GEOCLUE_LIBS) + +libgeoclue_la_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_headers = \ + gc-iface-address.h \ + gc-iface-geoclue.h \ + gc-iface-geocode.h \ + gc-iface-position.h \ + gc-iface-reverse-geocode.h \ + gc-iface-velocity.h \ + gc-provider.h \ + gc-web-service.h \ + geoclue-accuracy.h \ + geoclue-address.h \ + geoclue-address-details.h \ + geoclue-provider.h \ + geoclue-error.h \ + geoclue-geocode.h \ + geoclue-master.h \ + geoclue-master-client.h \ + geoclue-position.h \ + geoclue-reverse-geocode.h \ + geoclue-types.h \ + geoclue-velocity.h \ + geoclue-enum-types.h + +libgeoclue_includedir = $(includedir)/geoclue +libgeoclue_include_HEADERS = \ + $(geoclue_headers) + +EXTRA_DIST = \ + geoclue-marshal.list + +CLEANFILES = $(BUILT_SOURCES) \ + stamp-gc-iface-address-glue.h \ + stamp-gc-iface-geoclue-glue.h \ + stamp-gc-iface-geocode-glue.h \ + stamp-gc-iface-position-glue.h \ + stamp-gc-iface-reverse-geocode-glue.h \ + stamp-gc-iface-velocity-glue.h + +DISTCLEANFILES = \ + $(nodist_libgeoclue_la_SOURCES) \ + geoclue-enum-types.h \ + geoclue-enum-types.c + +geoclue-marshal.h: geoclue-marshal.list $(GLIB_GENMARSHAL) + $(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=geoclue_marshal > $@ +geoclue-marshal.c: geoclue-marshal.list geoclue-marshal.h $(GLIB_GENMARSHAL) + $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=geoclue_marshal $(srcdir)/geoclue-marshal.list --header --body > $@ + +%-glue.h: stamp-%-glue.h + @true + +stamp-gc-iface-address-glue.h: ../interfaces/gc-iface-address.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=gc_iface_address --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +stamp-gc-iface-geoclue-glue.h: ../interfaces/gc-iface-geoclue.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=gc_iface_geoclue --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +stamp-gc-iface-geocode-glue.h: ../interfaces/gc-iface-geocode.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=gc_iface_geocode --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +stamp-gc-iface-position-glue.h: ../interfaces/gc-iface-position.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=gc_iface_position --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +stamp-gc-iface-reverse-geocode-glue.h: ../interfaces/gc-iface-reverse-geocode.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=gc_iface_reverse_geocode --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +stamp-gc-iface-velocity-glue.h: ../interfaces/gc-iface-velocity.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=gc_iface_velocity --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +%-bindings.h: stamp-%-bindings.h + @true +stamp-%-bindings.h: ../interfaces/%.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --mode=glib-client --prefix=geoclue $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +geoclue_headers_to_scan_for_enums = geoclue-error.h +# Generate the enums source code, with glib-mkenums: +# This is based on the same Makefile.am stuff in pango: +geoclue_built_headers = geoclue-enum-types.h +geoclue_built_cfiles = geoclue-enum-types.c + +geoclue-enum-types.h: $(geoclue_headers_to_scan_for_enums) Makefile + $(AM_V_GEN) (cd $(srcdir) && glib-mkenums \ + --fhead "#ifndef __GEOCLUE_ENUM_TYPES_H__\n#define __GEOCLUE_ENUM_TYPES_H__\n\n#include <glib-object.h>\n\nG_BEGIN_DECLS\n" \ + --fprod "/* enumerations from \"@filename@\" */\n" \ + --vhead "GType @enum_name@_get_type (void);\n#define GEOCLUE_TYPE_@ENUMSHORT@ (@enum_name@_get_type())\n" \ + --ftail "G_END_DECLS\n\n#endif /* __GEOCLUE_ENUM_TYPES_H__ */" \ + $(geoclue_headers_to_scan_for_enums)) > $@ + +geoclue-enum-types.c: $(geoclue_headers_to_scan_for_enums) Makefile geoclue-enum-types.h + $(AM_V_GEN) (cd $(srcdir) && glib-mkenums \ + --fhead "#include <geoclue-error.h>\n" \ + --fhead "#include \"geoclue-enum-types.h\"\n" \ + --fhead "#include <glib-object.h>" \ + --fprod "\n/* enumerations from \"@filename@\" */" \ + --vhead "GType\n@enum_name@_get_type (void)\n{\n static GType etype = 0;\n if (etype == 0) {\n static const G@Type@Value values[] = {" \ + --vprod " { @VALUENAME@, \"@VALUENAME@\", \"@valuenick@\" }," \ + --vtail " { 0, NULL, NULL }\n };\n etype = g_@type@_register_static (\"@EnumName@\", values);\n }\n return etype;\n}\n" \ + $(geoclue_headers_to_scan_for_enums)) > $@ diff --git a/.pc/tizen.patch/geoclue/gc-iface-nmea.c b/.pc/tizen.patch/geoclue/gc-iface-nmea.c new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/gc-iface-nmea.c diff --git a/.pc/tizen.patch/geoclue/gc-iface-nmea.h b/.pc/tizen.patch/geoclue/gc-iface-nmea.h new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/gc-iface-nmea.h diff --git a/.pc/tizen.patch/geoclue/gc-iface-satellite.c b/.pc/tizen.patch/geoclue/gc-iface-satellite.c new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/gc-iface-satellite.c diff --git a/.pc/tizen.patch/geoclue/gc-iface-satellite.h b/.pc/tizen.patch/geoclue/gc-iface-satellite.h new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/gc-iface-satellite.h diff --git a/.pc/tizen.patch/geoclue/gc-provider.c b/.pc/tizen.patch/geoclue/gc-provider.c new file mode 100755 index 0000000..c5a56f2 --- /dev/null +++ b/.pc/tizen.patch/geoclue/gc-provider.c @@ -0,0 +1,317 @@ +/* + * Geoclue + * gc-provider.c - A provider object that handles the basic D-Bus required for + * a provider. + * + * Author: Iain Holmes <iain@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * SECTION:gc-provider + * @short_description: Abstract class to derive Geoclue providers from. + * + * #GcProvider is an abstract class that all Geoclue providers should + * derive from. It takes care of setting up the provider D-Bus service, + * and also implements #GcIfaceGeoclue interface (derived classes still + * need to implement the functionality). + * + * Derived classes should define the #GcIfaceGeoclue methods in their + * class_init() and call gc_provider_set_details() in init() + * + */ +#include <config.h> + +#include <string.h> +#include <glib-object.h> + +#include <dbus/dbus.h> +#include <dbus/dbus-glib-bindings.h> +#include <dbus/dbus-glib-lowlevel.h> + +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-provider.h> + + +typedef struct { + char *name; + char *description; + + GHashTable *connections; +} GcProviderPrivate; + +#define GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GC_TYPE_PROVIDER, GcProviderPrivate)) + +static void gc_provider_geoclue_init (GcIfaceGeoclueClass *iface); + +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GcProvider, gc_provider, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_GEOCLUE, + gc_provider_geoclue_init)) + +static void +finalize (GObject *object) +{ + GcProviderPrivate *priv = GET_PRIVATE (object); + + g_free (priv->name); + g_free (priv->description); + + ((GObjectClass *) gc_provider_parent_class)->finalize (object); +} + +static void +dispose (GObject *object) +{ + GcProviderPrivate *priv = GET_PRIVATE (object); + + g_hash_table_destroy (priv->connections); + + ((GObjectClass *) gc_provider_parent_class)->dispose (object); +} + +static void +gc_provider_class_init (GcProviderClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->finalize = finalize; + o_class->dispose = dispose; + + klass->shutdown = NULL; + + g_type_class_add_private (klass, sizeof (GcProviderPrivate)); +} + +static void +gc_provider_init (GcProvider *provider) +{ + GError *error = NULL; + GcProviderPrivate *priv = GET_PRIVATE (provider); + + provider->connection = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error); + if (provider->connection == NULL) { + g_warning ("%s was unable to create a connection to D-Bus: %s", + G_OBJECT_TYPE_NAME (provider), error->message); + g_error_free (error); + } + + priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); +} + + +static void +gc_provider_shutdown (GcProvider *provider) +{ + GC_PROVIDER_GET_CLASS (provider)->shutdown (provider); +} + + +static gboolean +get_provider_info (GcIfaceGeoclue *geoclue, + gchar **name, + gchar **description, + GError **error) +{ + GcProvider *provider = GC_PROVIDER (geoclue); + GcProviderPrivate *priv = GET_PRIVATE (provider); + + if (name) { + *name = g_strdup (priv->name); + } + if (description) { + *description = g_strdup (priv->description); + } + + return TRUE; +} + +static gboolean +get_status (GcIfaceGeoclue *geoclue, + GeoclueStatus *status, + GError **error) +{ + GcProviderClass *klass; + + klass = GC_PROVIDER_GET_CLASS (geoclue); + if (klass->get_status) { + return klass->get_status (geoclue, status, error); + } else { + *error = g_error_new (GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_IMPLEMENTED, + "get_status is not implemented"); + return FALSE; + } +} + +static gboolean +set_options (GcIfaceGeoclue *geoclue, + GHashTable *options, + GError **error) +{ + GcProviderClass *klass; + + klass = GC_PROVIDER_GET_CLASS (geoclue); + if (klass->set_options) { + return klass->set_options (geoclue, options, error); + } + + /* It is not an error to not have a SetOptions implementation */ + return TRUE; +} + +static gboolean +gc_provider_remove_client (GcProvider *provider, const char *client) +{ + int *pcount; + GcProviderPrivate *priv = GET_PRIVATE (provider); + + pcount = g_hash_table_lookup (priv->connections, client); + if (!pcount) { + return FALSE; + } + + (*pcount)--; + if (*pcount == 0) { + g_hash_table_remove (priv->connections, client); + } + if (g_hash_table_size (priv->connections) == 0) { + gc_provider_shutdown (provider); + } + return TRUE; +} + +static void +add_reference (GcIfaceGeoclue *geoclue, + DBusGMethodInvocation *context) +{ + GcProviderPrivate *priv = GET_PRIVATE (geoclue); + char *sender; + int *pcount; + + /* Update the hash of open connections */ + sender = dbus_g_method_get_sender (context); + pcount = g_hash_table_lookup (priv->connections, sender); + if (!pcount) { + pcount = g_malloc0 (sizeof (int)); + g_hash_table_insert (priv->connections, sender, pcount); + } + (*pcount)++; + + dbus_g_method_return (context); +} + +static void +remove_reference (GcIfaceGeoclue *geoclue, + DBusGMethodInvocation *context) +{ + GcProvider *provider = GC_PROVIDER (geoclue); + char *sender; + + sender = dbus_g_method_get_sender (context); + if (!gc_provider_remove_client (provider, sender)) { + g_warning ("Unreffed by client that has not been referenced"); + } + + g_free (sender); + + dbus_g_method_return (context); +} + +static void +name_owner_changed (DBusGProxy *proxy, + const char *name, + const char *prev_owner, + const char *new_owner, + GcProvider *provider) +{ + if (strcmp (new_owner, "") == 0 && strcmp (name, prev_owner) == 0) { + if (gc_provider_remove_client (provider, prev_owner)) { + g_warning ("Impolite client %s disconnected without unreferencing\n", prev_owner); + } + } +} + +static void +gc_provider_geoclue_init (GcIfaceGeoclueClass *iface) +{ + iface->get_provider_info = get_provider_info; + iface->get_status = get_status; + iface->set_options = set_options; + iface->add_reference = add_reference; + iface->remove_reference = remove_reference; +} + + +/** + * gc_provider_set_details: + * @provider: A #GcProvider object + * @service: The service name to be requested + * @path: The path the object should be registered at + * @name: The provider name + * @description: The description of the provider + * + * Requests ownership of the @service name, and if that succeeds registers + * @provider at @path. @name should be the name of the provider (e.g. + * "Hostip"), @description should be a short description of the provider + * (e.g. "Web service based Position & Address provider (http://hostip.info)"). + */ +void +gc_provider_set_details (GcProvider *provider, + const char *service, + const char *path, + const char *name, + const char *description) +{ + GcProviderPrivate *priv = GET_PRIVATE (provider); + GError *error = NULL; + DBusGProxy *driver; + guint request_ret; + + g_return_if_fail (GC_IS_PROVIDER (provider)); + g_return_if_fail (provider->connection != NULL); + g_return_if_fail (service != NULL); + g_return_if_fail (path != NULL); + + driver = dbus_g_proxy_new_for_name (provider->connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + + if (!org_freedesktop_DBus_request_name (driver, service, 0, + &request_ret, &error)) { + g_warning ("%s was unable to register service %s: %s", + G_OBJECT_TYPE_NAME (provider), service, + error->message); + g_error_free (error); + return; + } + + dbus_g_proxy_add_signal (driver, "NameOwnerChanged", + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (driver, "NameOwnerChanged", + G_CALLBACK (name_owner_changed), + provider, NULL); + + dbus_g_connection_register_g_object (provider->connection, + path, G_OBJECT (provider)); + + priv->name = g_strdup (name); + priv->description = g_strdup (description); +} diff --git a/.pc/tizen.patch/geoclue/gc-web-service.c b/.pc/tizen.patch/geoclue/gc-web-service.c new file mode 100755 index 0000000..298e2ad --- /dev/null +++ b/.pc/tizen.patch/geoclue/gc-web-service.c @@ -0,0 +1,442 @@ +/* + * Geoclue + * gc-web-service.c - A web service helper object for geoclue providers + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * + * Copyright 2007 Jussi Kukkonen (from old geoclue_web_service.c) + * Copyright 2007, 2008 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * SECTION:gc-web-service + * @short_description: Web service helper object for Geoclue providers. + * + * #GcWebService is a web service abstraction for Geoclue provider + * implementations. It handles basic http stuff and xml parsing + * (although the raw data is available through + * gc_web_service_get_response() as well). + * + * At the moment xml parsing functions only exist for double and + * char-array data types. Adding new functions is trivial, though. + * <informalexample> + * <programlisting> + * . . . + * + * #GcWebService *web_service; + * web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL); + * gc_web_service_set_base_url (web_service, "http://example.org"); + * + * / * Add namespaces if needed * / + * gc_web_service_add_namespace (web_service, + * "ns_name", "http://example.org/ns"); + * + * . . . + * + * / * Fetch document "http://api.example.org?key1=val1&key2=val2" * / + * if (!gc_web_service_query (web_service, + * "key1", "val1" + * "key2", val2" + * (char *)0)) { + * / * error * / + * return; + * } + * + * / * Use XPath expressions to parse the xml in fetched document * / + * gchar *str; + * if (gc_web_service_get_string (web_service, + * &str, "//path/to/element")) { + * g_debug("got string: %s", str); + * } + * + * gdouble number; + * if (gc_web_service_get_double (web_service, + * &number, "//path/to/another/element")) { + * g_debug("got double: %f", number); + * } + * + * . . . + * + * g_object_unref (G_OBJECT (web_service)); + * </programlisting> + * </informalexample> + */ + +#include <stdarg.h> +#include <glib-object.h> + +#include <libxml/nanohttp.h> +#include <libxml/xpathInternals.h> +#include <libxml/uri.h> /* for xmlURIEscapeStr */ + +#include "gc-web-service.h" +#include "geoclue-error.h" + +G_DEFINE_TYPE (GcWebService, gc_web_service, G_TYPE_OBJECT) + +typedef struct _XmlNamespace { + gchar *name; + gchar *uri; +}XmlNamespace; + +/* GFunc, use with g_list_foreach */ +static void +gc_web_service_register_ns (gpointer data, gpointer user_data) +{ + GcWebService *self = (GcWebService *)user_data; + XmlNamespace *ns = (XmlNamespace *)data; + + xmlXPathRegisterNs (self->xpath_ctx, + (xmlChar*)ns->name, (xmlChar*)ns->uri); +} + +/* GFunc, use with g_list_foreach */ +static void +gc_web_service_free_ns (gpointer data, gpointer user_data) +{ + XmlNamespace *ns = (XmlNamespace *)data; + + g_free (ns->name); + g_free (ns->uri); + g_free (ns); +} + + +/* Register namespaces listed in self->namespaces */ +static void +gc_web_service_register_namespaces (GcWebService *self) +{ + g_assert (self->xpath_ctx); + g_list_foreach (self->namespaces, (GFunc)gc_web_service_register_ns, self); +} + +static void +gc_web_service_reset (GcWebService *self) +{ + g_free (self->response); + self->response = NULL; + self->response_length = 0; + + if (self->xpath_ctx) { + if (self->xpath_ctx->doc) { + xmlFreeDoc (self->xpath_ctx->doc); + } + xmlXPathFreeContext (self->xpath_ctx); + self->xpath_ctx = NULL; + } +} + +/* Parse data (self->response), build xpath context and register + * namespaces. Nothing will be done if xpath context exists already. */ +static gboolean +gc_web_service_build_xpath_context (GcWebService *self) +{ + xmlDocPtr doc; + xmlChar *tmp; + + /* don't rebuild if there's no need */ + if (self->xpath_ctx) { + return TRUE; + } + + /* make sure response is NULL-terminated */ + tmp = xmlStrndup(self->response, self->response_length); + doc = xmlParseDoc (tmp); + if (!doc) { + /* TODO: error handling */ + g_free (tmp); + return FALSE; + } + xmlFree (tmp); + + self->xpath_ctx = xmlXPathNewContext(doc); + if (!self->xpath_ctx) { + /* TODO: error handling */ + return FALSE; + } + gc_web_service_register_namespaces (self); + return TRUE; +} + +/* fetch data from url, save into self->response */ +static gboolean +gc_web_service_fetch (GcWebService *self, gchar *url, GError **error) +{ + void* ctxt = NULL; + gint len; + xmlChar buf[1024]; + xmlBuffer *output; + + g_assert (url); + + gc_web_service_reset (self); + + xmlNanoHTTPInit(); + ctxt = xmlNanoHTTPMethod (url, "GET", NULL, NULL, NULL, 0); + if (!ctxt) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "xmlNanoHTTPMethod did not get a response from %s\n", url); + return FALSE; + } + + output = xmlBufferCreate (); + while ((len = xmlNanoHTTPRead (ctxt, buf, sizeof(buf))) > 0) { + if (xmlBufferAdd (output, buf, len) != 0) { + xmlNanoHTTPClose(ctxt); + xmlBufferFree (output); + + g_set_error_literal (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_FAILED, + "libxml error (xmlBufferAdd failed)"); + + return FALSE; + } + } + xmlNanoHTTPClose(ctxt); + + self->response_length = xmlBufferLength (output); + self->response = g_memdup (xmlBufferContent (output), self->response_length); + xmlBufferFree (output); + + return TRUE; +} + +static xmlXPathObject* +gc_web_service_get_xpath_object (GcWebService *self, gchar* xpath) +{ + xmlXPathObject *obj = NULL; + + g_return_val_if_fail (xpath, FALSE); + + /* parse the doc if not parsed yet and register namespaces */ + if (!gc_web_service_build_xpath_context (self)) { + return FALSE; + } + g_assert (self->xpath_ctx); + + obj = xmlXPathEvalExpression ((xmlChar*)xpath, self->xpath_ctx); + if (obj && + (!obj->nodesetval || xmlXPathNodeSetIsEmpty (obj->nodesetval))) { + xmlXPathFreeObject (obj); + obj = NULL; + } + return obj; +} + +static void +gc_web_service_init (GcWebService *self) +{ + self->response = NULL; + self->response_length = 0; + self->xpath_ctx = NULL; + self->namespaces = NULL; + self->base_url = NULL; +} + + +static void +gc_web_service_finalize (GObject *obj) +{ + GcWebService *self = (GcWebService *) obj; + + gc_web_service_reset (self); + + g_free (self->base_url); + + g_list_foreach (self->namespaces, (GFunc)gc_web_service_free_ns, NULL); + g_list_free (self->namespaces); + + ((GObjectClass *) gc_web_service_parent_class)->finalize (obj); +} + +static void +gc_web_service_class_init (GcWebServiceClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + o_class->finalize = gc_web_service_finalize; +} + +/** + * gc_web_service_set_base_url: + * @self: The #GcWebService object + * @url: base url + * + * Sets base url for the web service. Must be called before calls to + * gc_web_service_get_* -methods. + */ +void +gc_web_service_set_base_url (GcWebService *self, gchar *url) +{ + g_assert (url); + + gc_web_service_reset (self); + + g_free (self->base_url); + self->base_url = g_strdup (url); +} + +/** + * gc_web_service_add_namespace: + * @self: The #GcWebService object + * @namespace: Namespace name + * @uri: Namespace uri + * + * Adds an xml namespace that will be used in all following calls to + * gc_web_service_get_*-functions. + * + * Return value: %TRUE on success. + */ +gboolean +gc_web_service_add_namespace (GcWebService *self, gchar *namespace, gchar *uri) +{ + XmlNamespace *ns; + + g_return_val_if_fail (self->base_url, FALSE); + + ns = g_new0 (XmlNamespace,1); + ns->name = g_strdup (namespace); + ns->uri = g_strdup (uri); + self->namespaces = g_list_prepend (self->namespaces, ns); + return TRUE; +} + +/** + * gc_web_service_query: + * @self: A #GcWebService object + * @Varargs: NULL-terminated list of key-value gchar* pairs + * + * Fetches data from the web. The url is constructed using the + * optional arguments as GET parameters (see example in the + * Description-section). Data should be read using + * gc_web_service_get_* -functions. + * + * Return value: %TRUE on success. + */ +gboolean +gc_web_service_query (GcWebService *self, GError **error, ...) +{ + va_list list; + gchar *key, *value, *esc_value, *tmp, *url; + gboolean first_pair = TRUE; + + g_return_val_if_fail (self->base_url, FALSE); + + url = g_strdup (self->base_url); + + /* read the arguments one key-value pair at a time, + add the pairs to url as "?key1=value1&key2=value2&..." */ + va_start (list, error); + key = va_arg (list, char*); + while (key) { + value = va_arg (list, char*); + esc_value = (gchar *)xmlURIEscapeStr ((xmlChar *)value, (xmlChar *)":"); + + if (first_pair) { + tmp = g_strdup_printf ("%s?%s=%s", url, key, esc_value); + first_pair = FALSE; + } else { + tmp = g_strdup_printf ("%s&%s=%s", url, key, esc_value); + } + g_free (esc_value); + g_free (url); + url = tmp; + key = va_arg (list, char*); + } + va_end (list); + + if (!gc_web_service_fetch (self, url, error)) { + g_free (url); + return FALSE; + } + g_free (url); + + return TRUE; +} + +/** + * gc_web_service_get_double: + * @self: A #GcWebService object + * @value: Pointer to returned value + * @xpath: XPath expression to find the value + * + * Extracts a @value from the data that was fetched in the last call + * to gc_web_service_query() using XPath expression @xpath. Returned + * value is the first match. + * + * Return value: %TRUE if a value was found. + */ +gboolean +gc_web_service_get_double (GcWebService *self, gdouble *value, gchar *xpath) +{ + xmlXPathObject *obj; + + obj = gc_web_service_get_xpath_object (self, xpath); + if (!obj) { + return FALSE; + } + *value = xmlXPathCastNodeSetToNumber (obj->nodesetval); + xmlXPathFreeObject (obj); + return TRUE; +} + +/** + * gc_web_service_get_string: + * @self: The #GcWebService object + * @value: pointer to newly allocated string + * @xpath: XPath expression used to find the value + * + * Extracts a @value from the data that was fetched in the last call + * to gc_web_service_query() using XPath expression @xpath (returned + * value is the first match). + * + * Return value: %TRUE if a value was found. + */ +gboolean +gc_web_service_get_string (GcWebService *self, gchar **value, gchar* xpath) +{ + xmlXPathObject *obj; + + obj = gc_web_service_get_xpath_object (self, xpath); + if (!obj) { + return FALSE; + } + *value = (char*)xmlXPathCastNodeSetToString (obj->nodesetval); + xmlXPathFreeObject (obj); + return TRUE; +} + +/** + * gc_web_service_get_response: + * @self: The #GcWebService object + * @response: returned guchar array + * @response_length: length of the returned array + * + * Returns the raw data fetched with the last call to + * gc_web_service_query(). Data may be unterminated. + * + * Return value: %TRUE on success. + */ +gboolean +gc_web_service_get_response (GcWebService *self, guchar **response, gint *response_length) +{ + *response = g_memdup (self->response, self->response_length); + *response_length = self->response_length; + return TRUE; +} diff --git a/.pc/tizen.patch/geoclue/geoclue-marshal.list b/.pc/tizen.patch/geoclue/geoclue-marshal.list new file mode 100755 index 0000000..233b7e0 --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-marshal.list @@ -0,0 +1,7 @@ +VOID:INT,INT +VOID:INT,INT,DOUBLE,DOUBLE,DOUBLE,BOXED +VOID:INT,INT,DOUBLE,DOUBLE,DOUBLE +VOID:INT,DOUBLE,DOUBLE +VOID:INT,POINTER,BOXED +VOID:INT,BOXED,BOXED +VOID:STRING,STRING,STRING,STRING diff --git a/.pc/tizen.patch/geoclue/geoclue-master-client.c b/.pc/tizen.patch/geoclue/geoclue-master-client.c new file mode 100755 index 0000000..811b65a --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-master-client.c @@ -0,0 +1,724 @@ +/* + * Geoclue + * geoclue-master-client.c - Client API for accessing the Geoclue Master process + * + * Author: Iain Holmes <iain@openedhand.com> + * Copyright 2008 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * SECTION:geoclue-master-client + * @short_description: Geoclue MasterClient API + * + * #GeoclueMasterClient is part of the Geoclue public C client API. It uses + * D-Bus to communicate with the actual Master service. + * + * #GeoclueMasterClient is used to control the client specific behaviour + * of Geoclue Master. Chapter "Master provider: simple example in C" contains a + * more complete example, but here are the main parts: + * + * <informalexample> + * <programlisting> + * GeoclueMaster *master; + * GeoclueMasterClient *client; + * GeoclueAddress *address; + * + * ... + * + * master = geoclue_master_get_default (); + * client = geoclue_master_create_client (master, NULL, NULL); + * + * if (!geoclue_master_client_set_requirements (client, + * GEOCLUE_ACCURACY_LEVEL_NONE, + * 0, FALSE, + * GEOCLUE_RESOURCE_NETWORK, + * &error)) { + * / * handle error * / + * } + * + * address = geoclue_master_client_create_address (client, error); + * if (!address) { + * / * handle error * / + * } + * + * / * Now we can use address just like we'd use a normal address provider, + * but GeoclueMasterClient makes sure that underneath the provider + * that best matches our requirements is used * / + * </programlisting> + * </informalexample> + */ + +#include <config.h> + +#include <glib-object.h> + +#include <geoclue/geoclue-marshal.h> +#include <geoclue/geoclue-master.h> +#include <geoclue/geoclue-master-client.h> +#include <geoclue/geoclue-types.h> +#include <geoclue/geoclue-accuracy.h> + +#include "gc-iface-master-client-bindings.h" + +typedef struct _GeoclueMasterClientPrivate { + DBusGProxy *proxy; + char *object_path; +} GeoclueMasterClientPrivate; + +enum { + PROP_0, + PROP_PATH +}; + +enum { + ADDRESS_PROVIDER_CHANGED, + POSITION_PROVIDER_CHANGED, + INVALIDATED, + LAST_SIGNAL +}; + + +static guint32 signals[LAST_SIGNAL] = {0, }; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_MASTER_CLIENT, GeoclueMasterClientPrivate)) + +G_DEFINE_TYPE_WITH_CODE (GeoclueMasterClient, geoclue_master_client, G_TYPE_OBJECT, geoclue_types_init ();); + + +typedef struct _GeoclueMasterClientAsyncData { + GeoclueMasterClient *client; + GCallback callback; + gpointer userdata; +} GeoclueMasterClientAsyncData; + + +static void +finalize (GObject *object) +{ + G_OBJECT_CLASS (geoclue_master_client_parent_class)->finalize (object); +} + +static void +dispose (GObject *object) +{ + + G_OBJECT_CLASS (geoclue_master_client_parent_class)->dispose (object); +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeoclueMasterClientPrivate *priv; + + priv = GET_PRIVATE (object); + + switch (prop_id) { + case PROP_PATH: + priv->object_path = g_value_dup_string (value); + break; + + default: + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ +} + +static void +address_provider_changed (DBusGProxy *proxy, + char *name, + char *description, + char *service, + char *path, + GeoclueMasterClient *client) +{ + g_signal_emit (client, signals[ADDRESS_PROVIDER_CHANGED], 0, + name, description, service, path); +} + +static void +position_provider_changed (DBusGProxy *proxy, + char *name, + char *description, + char *service, + char *path, + GeoclueMasterClient *client) +{ + g_signal_emit (client, signals[POSITION_PROVIDER_CHANGED], 0, + name, description, service, path); +} + +static void +proxy_destroyed (DBusGProxy *proxy, + gpointer user_data) +{ + g_signal_emit (user_data, signals[INVALIDATED], 0); +} + +static GObject * +constructor (GType type, + guint n_props, + GObjectConstructParam *props) +{ + GeoclueMasterClient *client; + GeoclueMasterClientPrivate *priv; + DBusGConnection *connection; + GObject *object; + GError *error = NULL; + + object = G_OBJECT_CLASS (geoclue_master_client_parent_class)->constructor (type, n_props, props); + client = GEOCLUE_MASTER_CLIENT (object); + priv = GET_PRIVATE (client); + + connection = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error); + if (!connection) { + g_warning ("Failed to open connection to bus: %s", + error->message); + g_error_free (error); + + priv->proxy = NULL; + return object; + } + + priv->proxy = dbus_g_proxy_new_for_name_owner (connection, + GEOCLUE_MASTER_DBUS_SERVICE, + priv->object_path, + GEOCLUE_MASTER_CLIENT_DBUS_INTERFACE, + &error); + if (!priv->proxy) { + g_warning ("Failed to create proxy to %s: %s", + priv->object_path, + error->message); + g_error_free (error); + + return object; + } + + g_signal_connect (priv->proxy, "destroy", + G_CALLBACK (proxy_destroyed), object); + + dbus_g_proxy_add_signal (priv->proxy, "AddressProviderChanged", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "AddressProviderChanged", + G_CALLBACK (address_provider_changed), + object, NULL); + + dbus_g_proxy_add_signal (priv->proxy, "PositionProviderChanged", + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->proxy, "PositionProviderChanged", + G_CALLBACK (position_provider_changed), + object, NULL); + return object; +} + +static void +geoclue_master_client_class_init (GeoclueMasterClientClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->finalize = finalize; + o_class->dispose = dispose; + o_class->constructor = constructor; + o_class->set_property = set_property; + o_class->get_property = get_property; + + g_type_class_add_private (klass, sizeof (GeoclueMasterClientPrivate)); + + g_object_class_install_property + (o_class, PROP_PATH, + g_param_spec_string ("object-path", + "Object path", + "The DBus path to the object", + "", + G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NAME)); + + /** + * GeoclueMasterClient::address-provider-changed: + * @client: the #GeoclueMasterClient object emitting the signal + * @name: name of the new provider (e.g. "Hostip") or %NULL if there is no provider + * @description: a short description of the new provider or %NULL if there is no provider + * @service: D-Bus service name of the new provider or %NULL if there is no provider + * @path: D-Bus object path name of the new provider or %NULL if there is no provider + * + * The address-provider-changed signal is emitted each time the used address provider + * changes. + **/ + signals[ADDRESS_PROVIDER_CHANGED] = + g_signal_new ("address-provider-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GeoclueMasterClientClass, address_provider_changed), + NULL, NULL, + geoclue_marshal_VOID__STRING_STRING_STRING_STRING, + G_TYPE_NONE, 4, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + /** + * GeoclueMasterClient::position-provider-changed: + * @client: the #GeoclueMasterClient object emitting the signal + * @name: name of the new provider (e.g. "Hostip") or %NULL if there is no provider + * @description: a short description of the new provider or %NULL if there is no provider + * @service: D-Bus service name of the new provider or %NULL if there is no provider + * @path: D-Bus object path name of the new provider or %NULL if there is no provider + * + * The position-provider-changed signal is emitted each time the used position provider + * changes. + **/ + signals[POSITION_PROVIDER_CHANGED] = + g_signal_new ("position-provider-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GeoclueMasterClientClass, position_provider_changed), + NULL, NULL, + geoclue_marshal_VOID__STRING_STRING_STRING_STRING, + G_TYPE_NONE, 4, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + /** + * GeoclueMasterClient::invalidated: + * @client: the #GeoclueMasterClient object emitting the signal + * + * The client has been invalidated. This is emitted when Geoclue Dbus + * services disappear unexpectedly (possibly due to a crash). Upon + * receiving this signal, you should unref your client and create a new + * one. + **/ + signals[INVALIDATED] = + g_signal_new ("invalidated", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GeoclueMasterClientClass, invalidated), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); +} + +static void +geoclue_master_client_init (GeoclueMasterClient *client) +{ +} + +/** + * geoclue_master_client_set_requirements: + * @client: A #GeoclueMasterClient + * @min_accuracy: The required minimum accuracy as a #GeoclueAccuracyLevel. + * @min_time: The minimum time between update signals in seconds + * @require_updates: Whether the updates (signals) are required. Only applies to interfaces with signals + * @allowed_resources: The resources that are allowed to be used as a #GeoclueResourceFlags + * @error: A pointer to returned #GError or %NULL. + * + * Sets the criteria that should be used when selecting the used provider + * + * Return value: %TRUE on success + */ +gboolean +geoclue_master_client_set_requirements (GeoclueMasterClient *client, + GeoclueAccuracyLevel min_accuracy, + int min_time, + gboolean require_updates, + GeoclueResourceFlags allowed_resources, + GError **error) +{ + GeoclueMasterClientPrivate *priv; + + priv = GET_PRIVATE (client); + if (!org_freedesktop_Geoclue_MasterClient_set_requirements + (priv->proxy, min_accuracy, min_time, require_updates, allowed_resources, error)) { + return FALSE; + } + + return TRUE; +} + +static void +set_requirements_callback (DBusGProxy *proxy, + GError *error, + GeoclueMasterClientAsyncData *data) +{ + (*(GeoclueSetRequirementsCallback)data->callback) (data->client, + error, + data->userdata); + g_free (data); +} + +/** + * GeoclueSetRequirementsCallback: + * @client: A #GeoclueMasterClient object + * @error: Error as #Gerror (may be %NULL) + * @userdata: User data pointer set in geoclue_master_client_set_requirements_async() + * + * Callback function for geoclue_master_client_set_requirements_async(). + */ + +/** + * geoclue_master_client_set_requirements_async: + * @client: A #GeoclueMasterClient + * @min_accuracy: The required minimum accuracy as a #GeoclueAccuracyLevel. + * @min_time: The minimum time between update signals (currently not implemented) + * @require_updates: Whether the updates (signals) are required. Only applies to interfaces with signals + * @allowed_resources: The resources that are allowed to be used as a #GeoclueResourceFlags + * @callback: #GeoclueSetRequirementsCallback function to call when requirements have been set + * @userdata: User data pointer + * + * Asynchronous version of geoclue_master_client_set_requirements(). + */ +void +geoclue_master_client_set_requirements_async (GeoclueMasterClient *client, + GeoclueAccuracyLevel min_accuracy, + int min_time, + gboolean require_updates, + GeoclueResourceFlags allowed_resources, + GeoclueSetRequirementsCallback callback, + gpointer userdata) +{ + GeoclueMasterClientPrivate *priv = GET_PRIVATE (client); + GeoclueMasterClientAsyncData *data; + + data = g_new (GeoclueMasterClientAsyncData, 1); + data->client = client; + data->callback = G_CALLBACK (callback); + data->userdata = userdata; + + org_freedesktop_Geoclue_MasterClient_set_requirements_async + (priv->proxy, + min_accuracy, + min_time, + require_updates, + allowed_resources, + (org_freedesktop_Geoclue_MasterClient_set_requirements_reply)set_requirements_callback, + data); +} + +/** + * geoclue_master_client_create_address: + * @client: A #GeoclueMasterClient + * @error: A pointer to returned #GError or %NULL. + * + * Starts the GeoclueMasterClient address provider and returns + * a #GeoclueAddress that uses the same D-Bus object as the #GeoclueMasterClient. + * + * Return value: New #GeoclueAddress or %NULL on error + */ +GeoclueAddress * +geoclue_master_client_create_address (GeoclueMasterClient *client, + GError **error) +{ + GeoclueMasterClientPrivate *priv; + + priv = GET_PRIVATE (client); + + if (!org_freedesktop_Geoclue_MasterClient_address_start (priv->proxy, error)) { + return NULL; + } + + return geoclue_address_new (GEOCLUE_MASTER_DBUS_SERVICE, priv->object_path); +} + +static void +address_start_async_callback (DBusGProxy *proxy, + GError *error, + GeoclueMasterClientAsyncData *data) +{ + GeoclueMasterClientPrivate *priv = GET_PRIVATE (data->client); + GeoclueAddress *address = NULL; + + if (!error) { + address = geoclue_address_new (GEOCLUE_MASTER_DBUS_SERVICE, priv->object_path); + } + + (*(CreateAddressCallback)data->callback) (data->client, + address, + error, + data->userdata); + g_free (data); +} + +/** + * CreateAddressCallback: + * @client: A #GeoclueMasterClient object + * @address: returned #GeoclueAddress + * @error: Error as #Gerror (may be %NULL) + * @userdata: User data pointer set in geoclue_master_client_create_address_async() + * + * Callback function for geoclue_master_client_create_address_async(). + */ + +/** + * geoclue_master_client_create_address_async: + * @client: A #GeoclueMasterClient object + * @callback: A #CreateAddressCallback function that should be called when return values are available + * @userdata: pointer for user specified data + * + * Function returns (essentially) immediately and calls @callback when it has started the address provider + * and a #GeoclueAddress is available. + */ +void +geoclue_master_client_create_address_async (GeoclueMasterClient *client, + CreateAddressCallback callback, + gpointer userdata) +{ + GeoclueMasterClientPrivate *priv = GET_PRIVATE (client); + GeoclueMasterClientAsyncData *data; + + data = g_new (GeoclueMasterClientAsyncData, 1); + data->client = client; + data->callback = G_CALLBACK (callback); + data->userdata = userdata; + + org_freedesktop_Geoclue_MasterClient_address_start_async + (priv->proxy, + (org_freedesktop_Geoclue_MasterClient_address_start_reply)address_start_async_callback, + data); +} + + +/** + * geoclue_master_client_create_position: + * @client: A #GeoclueMasterClient + * @error: A pointer to returned #GError or %NULL. + * + * Starts the GeoclueMasterClient position provider and returns + * a #GeocluePosition that uses the same D-Bus object as the #GeoclueMasterClient. + * + * Return value: New #GeocluePosition or %NULL on error + */ +GeocluePosition * +geoclue_master_client_create_position (GeoclueMasterClient *client, + GError **error) +{ + GeoclueMasterClientPrivate *priv; + + priv = GET_PRIVATE (client); + + if (!org_freedesktop_Geoclue_MasterClient_position_start (priv->proxy, error)) { + return NULL; + } + return geoclue_position_new (GEOCLUE_MASTER_DBUS_SERVICE, priv->object_path); +} + + +static void +position_start_async_callback (DBusGProxy *proxy, + GError *error, + GeoclueMasterClientAsyncData *data) +{ + GeoclueMasterClientPrivate *priv = GET_PRIVATE (data->client); + GeocluePosition *position = NULL; + + if (!error) { + position = geoclue_position_new (GEOCLUE_MASTER_DBUS_SERVICE, priv->object_path); + } + + (*(CreatePositionCallback)data->callback) (data->client, + position, + error, + data->userdata); + g_free (data); +} + +/** + * CreatePositionCallback: + * @client: A #GeoclueMasterClient object + * @position: returned #GeocluePosition + * @error: Error as #Gerror (may be %NULL) + * @userdata: User data pointer set in geoclue_master_client_create_position_async() + * + * Callback function for geoclue_master_client_create_position_async(). + */ + +/** + * geoclue_master_client_create_position_async: + * @client: A #GeoclueMasterClient object + * @callback: A #CreatePositionCallback function that should be called when return values are available + * @userdata: pointer for user specified data + * + * Function returns (essentially) immediately and calls @callback when it has started the position provider + * and a #GeocluePosition is available. + */ +void +geoclue_master_client_create_position_async (GeoclueMasterClient *client, + CreatePositionCallback callback, + gpointer userdata) +{ + GeoclueMasterClientPrivate *priv = GET_PRIVATE (client); + GeoclueMasterClientAsyncData *data; + + data = g_new (GeoclueMasterClientAsyncData, 1); + data->client = client; + data->callback = G_CALLBACK (callback); + data->userdata = userdata; + + org_freedesktop_Geoclue_MasterClient_position_start_async + (priv->proxy, + (org_freedesktop_Geoclue_MasterClient_position_start_reply)position_start_async_callback, + data); +} + + +/** + * geoclue_master_client_get_address_provider: + * @client: A #GeoclueMasterClient + * @name: Pointer to returned provider name or %NULL + * @description: Pointer to returned provider description or %NULL + * @service: Pointer to returned D-Bus service name or %NULL + * @path: Pointer to returned D-Bus object path or %NULL + * @error: Pointer to returned #GError or %NULL + * + * Gets name and other information for the currently used address provider. + * + * Return value: %TRUE on success + */ +gboolean geoclue_master_client_get_address_provider (GeoclueMasterClient *client, + char **name, + char **description, + char **service, + char **path, + GError **error) +{ + GeoclueMasterClientPrivate *priv; + + priv = GET_PRIVATE (client); + if (!org_freedesktop_Geoclue_MasterClient_get_address_provider + (priv->proxy, name, description, service, path, error)) { + return FALSE; + } + + return TRUE; +} + +static void +get_provider_callback (DBusGProxy *proxy, + char * name, + char * description, + char * service, + char * path, + GError *error, + GeoclueMasterClientAsyncData *data) +{ + + (*(GeoclueGetProviderCallback)data->callback) (data->client, + name, + description, + service, + path, + error, + data->userdata); + g_free (data); +} + +/** + * geoclue_master_client_get_address_provider_async: + * @client: A #GeoclueMasterClient + * @callback: A #GeoclueGetProviderCallback function that will be called when return values are available + * @userdata: pointer for user specified data + * + * Gets name and other information for the currently used address provider asynchronously. + */ +void +geoclue_master_client_get_address_provider_async (GeoclueMasterClient *client, + GeoclueGetProviderCallback callback, + gpointer userdata) +{ + GeoclueMasterClientPrivate *priv = GET_PRIVATE (client); + GeoclueMasterClientAsyncData *data; + + data = g_new (GeoclueMasterClientAsyncData, 1); + data->client = client; + data->callback = G_CALLBACK (callback); + data->userdata = userdata; + + org_freedesktop_Geoclue_MasterClient_get_address_provider_async + (priv->proxy, + (org_freedesktop_Geoclue_MasterClient_get_address_provider_reply)get_provider_callback, + data); +} + + +/** + * geoclue_master_client_get_position_provider: + * @client: A #GeoclueMasterClient + * @name: Pointer to returned provider name or %NULL + * @description: Pointer to returned provider description or %NULL + * @service: Pointer to returned D-Bus service name or %NULL + * @path: Pointer to returned D-Bus object path or %NULL + * @error: Pointer to returned #GError or %NULL + * + * Gets name and other information for the currently used position provider. + * + * Return value: %TRUE on success + */ +gboolean geoclue_master_client_get_position_provider (GeoclueMasterClient *client, + char **name, + char **description, + char **service, + char **path, + GError **error) +{ + GeoclueMasterClientPrivate *priv; + + priv = GET_PRIVATE (client); + if (!org_freedesktop_Geoclue_MasterClient_get_position_provider + (priv->proxy, name, description, service, path, error)) { + return FALSE; + } + + return TRUE; +} + +/** + * geoclue_master_client_get_position_provider_async: + * @client: A #GeoclueMasterClient + * @callback: A #GeoclueGetProviderCallback function that will be called when return values are available + * @userdata: pointer for user specified data + * + * Gets name and other information for the currently used position provider asynchronously. + */ +void +geoclue_master_client_get_position_provider_async (GeoclueMasterClient *client, + GeoclueGetProviderCallback callback, + gpointer userdata) +{ + GeoclueMasterClientPrivate *priv = GET_PRIVATE (client); + GeoclueMasterClientAsyncData *data; + + data = g_new (GeoclueMasterClientAsyncData, 1); + data->client = client; + data->callback = G_CALLBACK (callback); + data->userdata = userdata; + + org_freedesktop_Geoclue_MasterClient_get_position_provider_async + (priv->proxy, + (org_freedesktop_Geoclue_MasterClient_get_position_provider_reply)get_provider_callback, + data); +} diff --git a/.pc/tizen.patch/geoclue/geoclue-nmea.c b/.pc/tizen.patch/geoclue/geoclue-nmea.c new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-nmea.c diff --git a/.pc/tizen.patch/geoclue/geoclue-nmea.h b/.pc/tizen.patch/geoclue/geoclue-nmea.h new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-nmea.h diff --git a/.pc/tizen.patch/geoclue/geoclue-provider.c b/.pc/tizen.patch/geoclue/geoclue-provider.c new file mode 100755 index 0000000..98a613b --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-provider.c @@ -0,0 +1,550 @@ +/* + * Geoclue + * geoclue-provider.c - Client object for accessing Geoclue Providers + * + * Authors: Iain Holmes <iain@openedhand.com> + * Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * 2008 OpenedHand Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * SECTION:geoclue-provider + * @short_description: Common client API for Geoclue providers + * + * #GeoclueProvider contains the methods and signals common to all Geoclue + * providers. It is part of the public C client API which uses D-Bus + * to communicate with the actual provider. + * + * A #GeoclueProvider is not explicitly created. Instead any provider + * object can be cast to #GeoclueProvider. Using a #GeocluePosition as + * example here: + * <informalexample> + * <programlisting> + * GeocluePosition *pos; + * char *name; + * GError *error; + * + * pos = geoclue_position_new ("org.freedesktop.Geoclue.Providers.Example", + * "/org/freedesktop/Geoclue/Providers/Example"); + * + * if (geoclue_provider_get_provider_info (GEOCLUE_PROVIDER (pos), + * &name, NULL, &error)) { + * g_print ("name = %s", name); + * } + * </programlisting> + * </informalexample> + * + * #GeoclueProvider can be used to obtain generic + * information about the provider and to set provider + * options. + */ +#include <config.h> + +#include <geoclue/geoclue-provider.h> +#include "gc-iface-geoclue-bindings.h" + +typedef struct _GeoclueProviderAsyncData { + GeoclueProvider *provider; + GCallback callback; + gpointer userdata; +} GeoclueProviderAsyncData; + +typedef struct _GeoclueProviderPrivate { + DBusGProxy *geoclue_proxy; + + char *service; + char *path; + char *interface; +} GeoclueProviderPrivate; + +enum { + PROP_0, + PROP_SERVICE, + PROP_PATH, + PROP_INTERFACE +}; + +enum { + STATUS_CHANGED, + LAST_SIGNAL +}; +static guint32 signals[LAST_SIGNAL] = {0, }; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_PROVIDER, GeoclueProviderPrivate)) +G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GeoclueProvider, geoclue_provider, G_TYPE_OBJECT, geoclue_types_init ();); + +#define GEOCLUE_INTERFACE_NAME "org.freedesktop.Geoclue" + + +static void +status_changed (DBusGProxy *proxy, + GeoclueStatus status, + GeoclueProvider *provider) +{ + g_signal_emit (provider, signals[STATUS_CHANGED], 0, status); +} + +static void +add_reference_callback (DBusGProxy *proxy, GError *error, gpointer userdata) +{ + if (error) { + g_printerr ("Could not reference provider: %s", error->message); + g_error_free (error); + } +} + +static void +remove_reference_callback (DBusGProxy *proxy, GError *error, gpointer userdata) +{ + if (error) { + g_printerr ("Could not unreference provider: %s", error->message); + g_error_free (error); + } +} + +static void +finalize (GObject *object) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (object); + + g_free (priv->service); + g_free (priv->path); + g_free (priv->interface); + + G_OBJECT_CLASS (geoclue_provider_parent_class)->finalize (object); +} + +static void +dispose (GObject *object) +{ + GeoclueProvider *provider = GEOCLUE_PROVIDER (object); + GeoclueProviderPrivate *priv = GET_PRIVATE (object); + + org_freedesktop_Geoclue_remove_reference_async (priv->geoclue_proxy, + remove_reference_callback, + NULL); + if (priv->geoclue_proxy) { + g_object_unref (priv->geoclue_proxy); + priv->geoclue_proxy = NULL; + } + + if (provider->proxy) { + g_object_unref (provider->proxy); + provider->proxy = NULL; + } + + G_OBJECT_CLASS (geoclue_provider_parent_class)->dispose (object); +} + +static GObject * +constructor (GType type, + guint n_props, + GObjectConstructParam *props) +{ + GObject *object; + GeoclueProvider *provider; + GeoclueProviderPrivate *priv; + DBusGConnection *connection; + GError *error = NULL; + + object = G_OBJECT_CLASS (geoclue_provider_parent_class)->constructor + (type, n_props, props); + provider = GEOCLUE_PROVIDER (object); + priv = GET_PRIVATE (provider); + + connection = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error); + if (connection == NULL) { + g_printerr ("Failed to open connection to bus: %s\n", + error->message); + g_error_free (error); + provider->proxy = NULL; + priv->geoclue_proxy = NULL; + + return object; + } + + /* proxy for the requested interface */ + provider->proxy = dbus_g_proxy_new_for_name (connection, + priv->service, priv->path, + priv->interface); + + /* proxy for org.freedesktop.Geoclue */ + priv->geoclue_proxy = dbus_g_proxy_new_for_name (connection, + priv->service, priv->path, + GEOCLUE_INTERFACE_NAME); + org_freedesktop_Geoclue_add_reference_async (priv->geoclue_proxy, + add_reference_callback, + NULL); + dbus_g_proxy_add_signal (priv->geoclue_proxy, "StatusChanged", + G_TYPE_INT, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->geoclue_proxy, "StatusChanged", + G_CALLBACK (status_changed), + object, NULL); + + return object; +} + +static void +set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (object); + + switch (prop_id) { + case PROP_SERVICE: + priv->service = g_value_dup_string (value); + break; + + case PROP_PATH: + priv->path = g_value_dup_string (value); + break; + + case PROP_INTERFACE: + priv->interface = g_value_dup_string (value); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + switch (prop_id) { + default: + break; + } +} + +static void +geoclue_provider_class_init (GeoclueProviderClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->finalize = finalize; + o_class->dispose = dispose; + o_class->constructor = constructor; + o_class->set_property = set_property; + o_class->get_property = get_property; + + g_type_class_add_private (klass, sizeof (GeoclueProviderPrivate)); + + g_object_class_install_property + (o_class, PROP_SERVICE, + g_param_spec_string ("service", "Service", + "The D-Bus service this object represents", + "", G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NAME)); + g_object_class_install_property + (o_class, PROP_PATH, + g_param_spec_string ("path", "Path", + "The D-Bus path to this provider", + "", G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NAME)); + g_object_class_install_property + (o_class, PROP_INTERFACE, + g_param_spec_string ("interface", "Interface", + "The D-Bus interface implemented by the object", + "", G_PARAM_WRITABLE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_NICK | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NAME)); + + /** + * GeoclueProvider::status-changed: + * @provider: the provider object emitting the signal + * @status: New provider status as #GeoclueStatus + * + * The status-changed signal is emitted each time the provider + * status changes + **/ + signals[STATUS_CHANGED] = g_signal_new ("status-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GeoclueProviderClass, status_changed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); + +} + +static void +geoclue_provider_init (GeoclueProvider *provider) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (provider); + + provider->proxy = NULL; + priv->geoclue_proxy = NULL; +} + +/** + * geoclue_provider_get_status: + * @provider: A #GeoclueProvider object + * @status: Pointer for returned status as #GeoclueStatus + * @error: Pointer for returned #GError or %NULL + * + * Obtains the current status of the provider. + * + * Return value: %TRUE on success + */ +gboolean +geoclue_provider_get_status (GeoclueProvider *provider, + GeoclueStatus *status, + GError **error) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (provider); + int i; + + if (status == NULL) { + return TRUE; + } + + if (!org_freedesktop_Geoclue_get_status (priv->geoclue_proxy, + &i, error)) { + return FALSE; + } + *status = i; + return TRUE; +} + +static void +get_status_async_callback (DBusGProxy *proxy, + GeoclueStatus status, + GError *error, + GeoclueProviderAsyncData *data) +{ + (*(GeoclueProviderStatusCallback)data->callback) (data->provider, + status, + error, + data->userdata); + g_free (data); + +} + +/** + * GeoclueProviderStatusCallback: + * @provider: A #GeoclueProvider object + * @status: A #GeoclueStatus + * @error: Error as #GError or %NULL + * @userdata: User data pointer set in geoclue_provider_get_status_async() + * + * Callback function for geoclue_provider_get_status_async(). + */ + +/** + * geoclue_provider_get_status_async: + * @provider: A #GeoclueProvider object + * @callback: A #GeoclueProviderStatusCallback function that will be called when return values are available + * @userdata: pointer for user specified data + * + * Asynchronous version of geoclue_provider_get_status(). Function returns + * (essentially) immediately and calls @callback when status is available or + * when there is an error. + */ +void +geoclue_provider_get_status_async (GeoclueProvider *provider, + GeoclueProviderStatusCallback callback, + gpointer userdata) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (provider); + GeoclueProviderAsyncData *data; + + data = g_new (GeoclueProviderAsyncData, 1); + data->provider = provider; + data->callback = G_CALLBACK (callback); + data->userdata = userdata; + + org_freedesktop_Geoclue_get_status_async + (priv->geoclue_proxy, + (org_freedesktop_Geoclue_get_status_reply)get_status_async_callback, + data); +} + + +/** + * geoclue_provider_set_options: + * @provider: A #GeoclueProvider object + * @options: A #GHashTable containing the options + * @error: Pointer for returned #GError or %NULL + * + * Sets the options on the provider. + * + * Return value: %TRUE if setting options succeeded + */ +gboolean +geoclue_provider_set_options (GeoclueProvider *provider, + GHashTable *options, + GError **error) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (provider); + + if (options == NULL) { + return TRUE; + } + + return org_freedesktop_Geoclue_set_options (priv->geoclue_proxy, + options, error); +} + +static void +set_options_async_callback (DBusGProxy *proxy, + GError *error, + GeoclueProviderAsyncData *data) +{ + (*(GeoclueProviderOptionsCallback)data->callback) (data->provider, + error, + data->userdata); + g_free (data); +} + +/** + * GeoclueProviderOptionsCallback: + * @provider: A #GeoclueProvider object + * @error: Error as #GError or %NULL + * @userdata: User data pointer set in geoclue_provider_set_options_async() + * + * Callback function for geoclue_provider_set_options_async(). + */ + +/** + * geoclue_provider_set_options_async: + * @provider: A #GeoclueProvider object + * @options: A #GHashTable of options + * @callback: A #GeoclueProviderOptionsCallback function that will be called when options are set + * @userdata: pointer for user specified data + * + * Asynchronous version of geoclue_provider_set_options(). Function returns + * (essentially) immediately and calls @callback when options have been set or + * when there is an error. + */ +void +geoclue_provider_set_options_async (GeoclueProvider *provider, + GHashTable *options, + GeoclueProviderOptionsCallback callback, + gpointer userdata) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (provider); + GeoclueProviderAsyncData *data; + + data = g_new (GeoclueProviderAsyncData, 1); + data->provider = provider; + data->callback = G_CALLBACK (callback); + data->userdata = userdata; + + org_freedesktop_Geoclue_set_options_async + (priv->geoclue_proxy, + options, + (org_freedesktop_Geoclue_set_options_reply)set_options_async_callback, + data); +} + +/** + * geoclue_provider_get_provider_info: + * @provider: A #GeoclueProvider object + * @name: Pointer for returned provider name or %NULL + * @description: Pointer for returned provider description or %NULL + * @error: Pointer for returned #GError or %NULL + * + * Obtains name and a short description of the provider. + * + * Return value: %TRUE on success + */ +gboolean +geoclue_provider_get_provider_info (GeoclueProvider *provider, + char **name, + char **description, + GError **error) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (provider); + + return org_freedesktop_Geoclue_get_provider_info (priv->geoclue_proxy, + name, description, + error); +} + +static void +get_provider_info_async_callback (DBusGProxy *proxy, + char *name, + char *description, + GError *error, + GeoclueProviderAsyncData *data) +{ + (*(GeoclueProviderInfoCallback)data->callback) (data->provider, + name, + description, + error, + data->userdata); + g_free (data); +} + +/** + * GeoclueProviderInfoCallback: + * @provider: A #GeoclueProvider object + * @name: Name of the provider + * @description: one-line description of the provider + * @error: Error as #GError or %NULL + * @userdata: User data pointer set in geoclue_provider_get_provider_info_async() + * + * Callback function for geoclue_provider_get_provider_info_async(). + */ + +/** + * geoclue_provider_get_provider_info_async: + * @provider: A #GeoclueProvider object + * @callback: A #GeoclueProviderInfoCallback function that will be called when info is available + * @userdata: pointer for user specified data + * + * Asynchronous version of geoclue_provider_get_provider_info(). Function returns + * (essentially) immediately and calls @callback when info is available or + * when there is an error. + */ +void +geoclue_provider_get_provider_info_async (GeoclueProvider *provider, + GeoclueProviderInfoCallback callback, + gpointer userdata) +{ + GeoclueProviderPrivate *priv = GET_PRIVATE (provider); + GeoclueProviderAsyncData *data; + + data = g_new (GeoclueProviderAsyncData, 1); + data->provider = provider; + data->callback = G_CALLBACK (callback); + data->userdata = userdata; + + org_freedesktop_Geoclue_get_provider_info_async + (priv->geoclue_proxy, + (org_freedesktop_Geoclue_get_provider_info_reply)get_provider_info_async_callback, + data); +} diff --git a/.pc/tizen.patch/geoclue/geoclue-satellite-info.h b/.pc/tizen.patch/geoclue/geoclue-satellite-info.h new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-satellite-info.h diff --git a/.pc/tizen.patch/geoclue/geoclue-satellite.c b/.pc/tizen.patch/geoclue/geoclue-satellite.c new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-satellite.c diff --git a/.pc/tizen.patch/geoclue/geoclue-satellite.h b/.pc/tizen.patch/geoclue/geoclue-satellite.h new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-satellite.h diff --git a/.pc/tizen.patch/geoclue/geoclue-types.c b/.pc/tizen.patch/geoclue/geoclue-types.c new file mode 100755 index 0000000..1ac6b15 --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-types.c @@ -0,0 +1,76 @@ +/* + * Geoclue + * geoclue-types.c - + * + * Author: Iain Holmes <iain@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <geoclue/geoclue-marshal.h> +#include <geoclue/geoclue-types.h> +#include <geoclue/geoclue-accuracy.h> +#include <geoclue/geoclue-error.h> + +static gboolean initted = FALSE; + +void +geoclue_types_init (void) +{ + if (initted != FALSE) + return; + + dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE, + G_TYPE_NONE, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_INVALID); + dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_BOXED, + G_TYPE_NONE, + G_TYPE_INT, + G_TYPE_INT, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_BOXED, + G_TYPE_INVALID); + + dbus_g_object_register_marshaller (geoclue_marshal_VOID__INT_BOXED_BOXED, + G_TYPE_NONE, + G_TYPE_INT, + G_TYPE_BOXED, + G_TYPE_BOXED, + G_TYPE_INVALID); + + dbus_g_object_register_marshaller (geoclue_marshal_VOID__STRING_STRING_STRING_STRING, + G_TYPE_NONE, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_INVALID); + + dbus_g_error_domain_register (GEOCLUE_ERROR, + GEOCLUE_ERROR_DBUS_INTERFACE, + GEOCLUE_TYPE_ERROR); + + initted = TRUE; +} diff --git a/.pc/tizen.patch/geoclue/geoclue-types.h b/.pc/tizen.patch/geoclue/geoclue-types.h new file mode 100755 index 0000000..c28862a --- /dev/null +++ b/.pc/tizen.patch/geoclue/geoclue-types.h @@ -0,0 +1,195 @@ +/* + * Geoclue + * geoclue-types.h - Types for Geoclue + * + * Author: Iain Holmes <iain@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _GEOCLUE_TYPES_H +#define _GEOCLUE_TYPES_H + +#include <geoclue/geoclue-error.h> + +/** + * SECTION:geoclue-types + * @short_description: Type definitions and defines useful for Geoclue clients + **/ + + +/** + * GeoclueStatus + * + * defines the provider status + **/ +typedef enum { + GEOCLUE_STATUS_ERROR, + GEOCLUE_STATUS_UNAVAILABLE, + GEOCLUE_STATUS_ACQUIRING, + GEOCLUE_STATUS_AVAILABLE +} GeoclueStatus; + +/** + * GeoclueAccuracyLevel: + * + * Enum values used to define the approximate accuracy of + * Position or Address information. These are ordered in + * from lowest accuracy possible to highest accuracy possible. + * geoclue_accuracy_get_details() can be used to get get the + * current accuracy. It is up to the provider to set the + * accuracy based on analysis of its queries. + **/ +typedef enum { + GEOCLUE_ACCURACY_LEVEL_NONE = 0, + GEOCLUE_ACCURACY_LEVEL_COUNTRY, + GEOCLUE_ACCURACY_LEVEL_REGION, + GEOCLUE_ACCURACY_LEVEL_LOCALITY, + GEOCLUE_ACCURACY_LEVEL_POSTALCODE, + GEOCLUE_ACCURACY_LEVEL_STREET, + GEOCLUE_ACCURACY_LEVEL_DETAILED, +} GeoclueAccuracyLevel; + +/** + * GeocluePositionFields: + * + * #GeocluePositionFields is a bitfield that defines the validity of + * Position values. + * + * Example: + * <informalexample> + * <programlisting> + * GeocluePositionFields fields; + * fields = geoclue_position_get_position (. . .); + * + * if (fields & GEOCLUE_POSITION_FIELDS_LATITUDE && + * fields & GEOCLUE_POSITION_FIELDS_LONGITUDE) { + * g_print("latitude and longitude are valid"); + * } + * </programlisting> + * </informalexample> + **/ +typedef enum { + GEOCLUE_POSITION_FIELDS_NONE = 0, + GEOCLUE_POSITION_FIELDS_LATITUDE = 1 << 0, + GEOCLUE_POSITION_FIELDS_LONGITUDE = 1 << 1, + GEOCLUE_POSITION_FIELDS_ALTITUDE = 1 << 2 +} GeocluePositionFields; + +/** + * GeoclueVelocityFields: + * + * GeoclueVelocityFields is a bitfield that defines the validity of + * Velocity values. + **/ +typedef enum { + GEOCLUE_VELOCITY_FIELDS_NONE = 0, + GEOCLUE_VELOCITY_FIELDS_SPEED = 1 << 0, + GEOCLUE_VELOCITY_FIELDS_DIRECTION = 1 << 1, + GEOCLUE_VELOCITY_FIELDS_CLIMB = 1 << 2 +} GeoclueVelocityFields; + +/** + * GEOCLUE_ADDRESS_KEY_COUNTRYCODE: + * + * A key for address hashtables. The hash value should be a ISO 3166 two + * letter country code. + * + * The used hash keys match the elements of XEP-0080 (XMPP protocol + * extension for user location), see + * <ulink url="http://www.xmpp.org/extensions/xep-0080.html"> + * http://www.xmpp.org/extensions/xep-0080.html</ulink> + */ +#define GEOCLUE_ADDRESS_KEY_COUNTRYCODE "countrycode" +/** + * GEOCLUE_ADDRESS_KEY_COUNTRY: + * + * A key for address hashtables. The hash value should be a name of a country. + */ +#define GEOCLUE_ADDRESS_KEY_COUNTRY "country" +/** + * GEOCLUE_ADDRESS_KEY_REGION: + * + * A key for address hashtables. The hash value should be a name of an + * administrative region of a nation, e.g. province or + * US state. + */ +#define GEOCLUE_ADDRESS_KEY_REGION "region" +/** + * GEOCLUE_ADDRESS_KEY_LOCALITY: + * + * A key for address hashtables. The hash value should be a name of a town + * or city. + */ +#define GEOCLUE_ADDRESS_KEY_LOCALITY "locality" +/** + * GEOCLUE_ADDRESS_KEY_AREA: + * + * A key for address hashtables. The hash value should be a name of an + * area, such as neighborhood or campus. + */ +#define GEOCLUE_ADDRESS_KEY_AREA "area" +/** + * GEOCLUE_ADDRESS_KEY_POSTALCODE: + * + * A key for address hashtables. The hash value should be a code used for + * postal delivery. + */ +#define GEOCLUE_ADDRESS_KEY_POSTALCODE "postalcode" +/** + * GEOCLUE_ADDRESS_KEY_STREET: + * + * A key for address hashtables. The hash value should be a partial or full street + * address. + */ +#define GEOCLUE_ADDRESS_KEY_STREET "street" + +/** + * GeoclueResourceFlags: + * + * bitfield that represents a set of physical resources. + * + **/ +typedef enum _GeoclueResourceFlags { + GEOCLUE_RESOURCE_NONE = 0, + GEOCLUE_RESOURCE_NETWORK = 1 << 0, + GEOCLUE_RESOURCE_CELL = 1 << 1, + GEOCLUE_RESOURCE_GPS = 1 << 2, + + GEOCLUE_RESOURCE_ALL = (1 << 10) - 1 +} GeoclueResourceFlags; + + +/** + * GeoclueNetworkStatus: + * + * Enumeration for current network status. + * + **/ +typedef enum { + GEOCLUE_CONNECTIVITY_UNKNOWN, + GEOCLUE_CONNECTIVITY_OFFLINE, + GEOCLUE_CONNECTIVITY_ACQUIRING, + GEOCLUE_CONNECTIVITY_ONLINE, +} GeoclueNetworkStatus; + + + +void geoclue_types_init (void); + +#endif diff --git a/.pc/tizen.patch/gtk-doc.make b/.pc/tizen.patch/gtk-doc.make new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/gtk-doc.make diff --git a/.pc/tizen.patch/interfaces/Makefile.am b/.pc/tizen.patch/interfaces/Makefile.am new file mode 100755 index 0000000..094d45c --- /dev/null +++ b/.pc/tizen.patch/interfaces/Makefile.am @@ -0,0 +1,25 @@ +%.xml: %-full.xml + $(AM_V_GEN) $(XSLT) -o $@ $(top_srcdir)/docs/tools/spec-strip-docs.xsl $< + +noinst_DATA = \ + gc-iface-geoclue.xml \ + gc-iface-position.xml \ + gc-iface-address.xml \ + gc-iface-geocode.xml \ + gc-iface-master.xml \ + gc-iface-master-client.xml \ + gc-iface-reverse-geocode.xml \ + gc-iface-velocity.xml + +BUILT_SOURCES = $(noinst_DATA) +CLEANFILES = $(BUILT_SOURCES) + +EXTRA_DIST = \ + gc-iface-geoclue-full.xml \ + gc-iface-position-full.xml \ + gc-iface-address-full.xml \ + gc-iface-geocode-full.xml \ + gc-iface-master-full.xml \ + gc-iface-master-client-full.xml \ + gc-iface-reverse-geocode-full.xml \ + gc-iface-velocity-full.xml diff --git a/.pc/tizen.patch/interfaces/gc-iface-geoclue-full.xml b/.pc/tizen.patch/interfaces/gc-iface-geoclue-full.xml new file mode 100755 index 0000000..e2bded1 --- /dev/null +++ b/.pc/tizen.patch/interfaces/gc-iface-geoclue-full.xml @@ -0,0 +1,64 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd"> + + <interface name="org.freedesktop.Geoclue"> + <doc:doc> + <doc:para>Geoclue interface contains methods + and signals common to all providers (and all providers + must implement at least this interface).</doc:para> + </doc:doc> + + <method name="GetProviderInfo"> + <arg type="s" name="Name" direction="out"> + <doc:doc> + <doc:summary>The provider name</doc:summary> + </doc:doc> + </arg> + <arg type="s" name="Description" direction="out"> + <doc:doc> + <doc:summary>Short description of the provider</doc:summary> + </doc:doc> + </arg> + </method> + + <method name="GetStatus"> + <arg type="i" name="status" direction="out" > + <doc:doc> + <doc:summary>Current provider status, as GeoclueStatus</doc:summary> + </doc:doc> + </arg> + </method> + + <signal name="StatusChanged"> + <arg type="i" name="status" direction="out"> + <doc:doc> + <doc:summary>Current provider status, as GeoclueStatus</doc:summary> + </doc:doc> + </arg> + </signal> + + <method name="SetOptions"> + <arg type="a{sv}" name="options" direction="in" /> + </method> + + <method name="AddReference"> + <doc:doc> + <doc:description>Increase the reference count on the provider. + Provider may shutdown if reference count reaches zero, so + using AddReference()/RemoveReference is important for clients needing server + persistence -- basically any client that uses SetOptions() or connects to + signals.</doc:description> + </doc:doc> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + </method> + + <method name="RemoveReference"> + <doc:doc> + <doc:description>Decrease the reference count on the provider</doc:description> + </doc:doc> + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> + </method> + </interface> +</node> + diff --git a/.pc/tizen.patch/interfaces/gc-iface-nmea-full.xml b/.pc/tizen.patch/interfaces/gc-iface-nmea-full.xml new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/interfaces/gc-iface-nmea-full.xml diff --git a/.pc/tizen.patch/interfaces/gc-iface-satellite-full.xml b/.pc/tizen.patch/interfaces/gc-iface-satellite-full.xml new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/interfaces/gc-iface-satellite-full.xml diff --git a/.pc/tizen.patch/packaging/geoclue.spec b/.pc/tizen.patch/packaging/geoclue.spec new file mode 100755 index 0000000..e69de29 --- /dev/null +++ b/.pc/tizen.patch/packaging/geoclue.spec diff --git a/.pc/tizen.patch/providers/example/Makefile.am b/.pc/tizen.patch/providers/example/Makefile.am new file mode 100755 index 0000000..bb052fc --- /dev/null +++ b/.pc/tizen.patch/providers/example/Makefile.am @@ -0,0 +1,30 @@ +libexec_PROGRAMS = geoclue-example + +geoclue_example_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_example_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +geoclue_example_SOURCES = \ + geoclue-example.c + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-example.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Example.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/example/geoclue-example.c b/.pc/tizen.patch/providers/example/geoclue-example.c new file mode 100755 index 0000000..a7ef6f7 --- /dev/null +++ b/.pc/tizen.patch/providers/example/geoclue-example.c @@ -0,0 +1,168 @@ +/* + * Geoclue + * geoclue-example.c - Example provider which doesn't do anything. + * + * Author: Iain Holmes <iain@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-position.h> + +typedef struct { + GcProvider parent; + + GMainLoop *loop; +} GeoclueExample; + +typedef struct { + GcProviderClass parent_class; +} GeoclueExampleClass; + +#define GEOCLUE_TYPE_EXAMPLE (geoclue_example_get_type ()) +#define GEOCLUE_EXAMPLE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_EXAMPLE, GeoclueExample)) + +static void geoclue_example_position_init (GcIfacePositionClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueExample, geoclue_example, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_example_position_init)) + + +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + *status = GEOCLUE_STATUS_AVAILABLE; + + return TRUE; +} + +static void +print_option (gpointer key, + gpointer value, + gpointer data) +{ + if (G_VALUE_TYPE (value) == G_TYPE_STRING) + g_print (" %s - %s\n", key, g_value_get_string (value)); + else + g_print (" %s - %d\n", key, g_value_get_int (value)); +} + +static gboolean +set_options (GcIfaceGeoclue *gc, + GHashTable *options, + GError **error) +{ + g_print ("Options received---\n"); + g_hash_table_foreach (options, print_option, NULL); + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueExample *example = GEOCLUE_EXAMPLE (provider); + + g_main_loop_quit (example->loop); +} + +static void +geoclue_example_class_init (GeoclueExampleClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *) klass; + + p_class->get_status = get_status; + p_class->set_options = set_options; + p_class->shutdown = shutdown; +} + +static void +geoclue_example_init (GeoclueExample *example) +{ + gc_provider_set_details (GC_PROVIDER (example), + "org.freedesktop.Geoclue.Providers.Example", + "/org/freedesktop/Geoclue/Providers/Example", + "Example", "Example provider"); +} + +static gboolean +get_position (GcIfacePosition *gc, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + *timestamp = time (NULL); + + /* We're not emitting location details here because we don't want + geoclue to accidently use this as a source */ + *fields = GEOCLUE_POSITION_FIELDS_NONE; + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0); + return TRUE; +} + +static void +geoclue_example_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = get_position; +} + +static gboolean +emit_position_signal (gpointer data) +{ + GeoclueExample *example = data; + GeoclueAccuracy *accuracy; + + accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, + 0.0, 0.0); + + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (example), + GEOCLUE_POSITION_FIELDS_NONE, + time (NULL), 0.0, 0.0, 0.0, accuracy); + + geoclue_accuracy_free (accuracy); + + return TRUE; +} + +int +main (int argc, + char **argv) +{ + GeoclueExample *example; + + g_type_init (); + + example = g_object_new (GEOCLUE_TYPE_EXAMPLE, NULL); + + g_timeout_add (5000, emit_position_signal, example); + + example->loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (example->loop); + + return 0; +} diff --git a/.pc/tizen.patch/providers/geonames/Makefile.am b/.pc/tizen.patch/providers/geonames/Makefile.am new file mode 100755 index 0000000..55f31e3 --- /dev/null +++ b/.pc/tizen.patch/providers/geonames/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-geonames + +NOINST_H_FILES = \ + geoclue-geonames.h + +geoclue_geonames_SOURCES = \ + $(NOINST_H_FILES) \ + geoclue-geonames.c + +geoclue_geonames_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_geonames_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-geonames.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Geonames.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/gpsd/Makefile.am b/.pc/tizen.patch/providers/gpsd/Makefile.am new file mode 100755 index 0000000..cc2764e --- /dev/null +++ b/.pc/tizen.patch/providers/gpsd/Makefile.am @@ -0,0 +1,32 @@ +libexec_PROGRAMS = geoclue-gpsd + +geoclue_gpsd_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) \ + $(GPSD_CFLAGS) + +geoclue_gpsd_LDADD = \ + $(GEOCLUE_LIBS) \ + $(GPSD_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +geoclue_gpsd_SOURCES = \ + geoclue-gpsd.c + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-gpsd.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Gpsd.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/gpsd/geoclue-gpsd.c b/.pc/tizen.patch/providers/gpsd/geoclue-gpsd.c new file mode 100755 index 0000000..dba91be --- /dev/null +++ b/.pc/tizen.patch/providers/gpsd/geoclue-gpsd.c @@ -0,0 +1,519 @@ +/* + * Geoclue + * geoclue-gpsd.c - Geoclue Position backend for gpsd + * + * Authors: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/* TODO: + * + * call to gps_set_callback blocks for a long time if + * BT device is not present. + * + **/ + +#include <config.h> + +#include <math.h> +#include <gps.h> +#include <string.h> + +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-velocity.h> + +typedef struct gps_data_t gps_data; +typedef struct gps_fix_t gps_fix; + +/* only listing used tags */ +typedef enum { + NMEA_NONE, + NMEA_GSA, + NMEA_GGA, + NMEA_GSV, + NMEA_RMC +} NmeaTag; + + +typedef struct { + GcProvider parent; + + char *host; + char *port; + + gps_data *gpsdata; + + gps_fix *last_fix; + + GeoclueStatus last_status; + GeocluePositionFields last_pos_fields; + GeoclueAccuracy *last_accuracy; + GeoclueVelocityFields last_velo_fields; + + GMainLoop *loop; + +} GeoclueGpsd; + +typedef struct { + GcProviderClass parent_class; +} GeoclueGpsdClass; + +static void geoclue_gpsd_position_init (GcIfacePositionClass *iface); +static void geoclue_gpsd_velocity_init (GcIfaceVelocityClass *iface); + +#define GEOCLUE_TYPE_GPSD (geoclue_gpsd_get_type ()) +#define GEOCLUE_GPSD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GPSD, GeoclueGpsd)) + +G_DEFINE_TYPE_WITH_CODE (GeoclueGpsd, geoclue_gpsd, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_gpsd_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_VELOCITY, + geoclue_gpsd_velocity_init)) + +static void geoclue_gpsd_stop_gpsd (GeoclueGpsd *self); +static gboolean geoclue_gpsd_start_gpsd (GeoclueGpsd *self); + + +/* defining global GeoclueGpsd because gpsd does not support "user_data" + * pointers in callbacks */ +GeoclueGpsd *gpsd; + + + +/* Geoclue interface */ +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *status = gpsd->last_status; + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (provider); + + g_main_loop_quit (gpsd->loop); +} + +static void +geoclue_gpsd_set_status (GeoclueGpsd *self, GeoclueStatus status) +{ + if (status != self->last_status) { + self->last_status = status; + + /* make position and velocity invalid if no fix */ + if (status != GEOCLUE_STATUS_AVAILABLE) { + self->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + self->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + } + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (self), + status); + } +} + +static gboolean +set_options (GcIfaceGeoclue *gc, + GHashTable *options, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + GValue *port_value, *host_value; + const char *port, *host; + gboolean changed = FALSE; + + host_value = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSHost"); + host = host_value ? g_value_get_string (host_value) : NULL; + port_value = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSPort"); + port = port_value ? g_value_get_string (port_value) : NULL; + + if (port == NULL) { + port = DEFAULT_GPSD_PORT; + } + + /* new values? */ + if (g_strcmp0 (host, gpsd->host) != 0 || + g_strcmp0 (port, gpsd->port) != 0) { + changed = TRUE; + } + + if (!changed) { + return TRUE; + } + + /* update private values with new ones, restart gpsd */ + g_free (gpsd->port); + gpsd->port = NULL; + g_free (gpsd->host); + gpsd->host = NULL; + + geoclue_gpsd_stop_gpsd (gpsd); + + if (host == NULL) { + return TRUE; + } + + gpsd->port = g_strdup (port); + gpsd->host = g_strdup (host); + if (!geoclue_gpsd_start_gpsd (gpsd)) { + geoclue_gpsd_set_status (gpsd, GEOCLUE_STATUS_ERROR); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_FAILED, "Gpsd not found"); + return FALSE; + } + return TRUE; +} + +static void +finalize (GObject *object) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (object); + + geoclue_gpsd_stop_gpsd (gpsd); + g_free (gpsd->last_fix); + geoclue_accuracy_free (gpsd->last_accuracy); + + g_free (gpsd->port); + if (gpsd->host) { + g_free (gpsd->host); + } + + ((GObjectClass *) geoclue_gpsd_parent_class)->finalize (object); +} + +static void +geoclue_gpsd_class_init (GeoclueGpsdClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + GcProviderClass *p_class = (GcProviderClass *) klass; + + o_class->finalize = finalize; + + p_class->get_status = get_status; + p_class->set_options = set_options; + p_class->shutdown = shutdown; +} + + +static gboolean +equal_or_nan (double a, double b) +{ + if (isnan (a) && isnan (b)) { + return TRUE; + } + return a == b; +} + +static void +geoclue_gpsd_update_position (GeoclueGpsd *gpsd, NmeaTag nmea_tag) +{ + gps_fix *fix = &gpsd->gpsdata->fix; + gps_fix *last_fix = gpsd->last_fix; + + last_fix->time = fix->time; + + /* If a flag is not set, bail out.*/ + if (!((gpsd->gpsdata->set & LATLON_SET) || (gpsd->gpsdata->set & ALTITUDE_SET))) { + return; + } + gpsd->gpsdata->set &= ~(LATLON_SET | ALTITUDE_SET); + + if (equal_or_nan (fix->latitude, last_fix->latitude) && + equal_or_nan (fix->longitude, last_fix->longitude) && + equal_or_nan (fix->altitude, last_fix->altitude)) { + /* position has not changed */ + return; + } + + /* save values */ + last_fix->latitude = fix->latitude; + last_fix->longitude = fix->longitude; + last_fix->altitude = fix->altitude; + + /* Could use fix.eph for accuracy, but eph is + * often NaN... what then? + * Could also use fix mode (2d/3d) to decide vertical accuracy, + * but gpsd updates that so erratically that I couldn't + * be arsed so far */ + geoclue_accuracy_set_details (gpsd->last_accuracy, + GEOCLUE_ACCURACY_LEVEL_DETAILED, + 24, 60); + + gpsd->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + gpsd->last_pos_fields |= (isnan (fix->latitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_LATITUDE; + gpsd->last_pos_fields |= (isnan (fix->longitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_LONGITUDE; + gpsd->last_pos_fields |= (isnan (fix->altitude)) ? + 0 : GEOCLUE_POSITION_FIELDS_ALTITUDE; + + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (gpsd), gpsd->last_pos_fields, + (int)(last_fix->time+0.5), + last_fix->latitude, last_fix->longitude, last_fix->altitude, + gpsd->last_accuracy); + +} + +static void +geoclue_gpsd_update_velocity (GeoclueGpsd *gpsd, NmeaTag nmea_tag) +{ + gps_fix *fix = &gpsd->gpsdata->fix; + gps_fix *last_fix = gpsd->last_fix; + gboolean changed = FALSE; + + /* at least with my devices, gpsd updates + * - climb on GGA, GSA and GSV messages (speed and track are set to NaN). + * - speed and track on RMC message (climb is set to NaN). + * + * couldn't think of an smart way to handle this, I don't think there is one + */ + + if (((gpsd->gpsdata->set & TRACK_SET) || (gpsd->gpsdata->set & SPEED_SET)) && + nmea_tag == NMEA_RMC) { + + gpsd->gpsdata->set &= ~(TRACK_SET | SPEED_SET); + + last_fix->time = fix->time; + + if (!equal_or_nan (fix->track, last_fix->track) || + !equal_or_nan (fix->speed, last_fix->speed)){ + + /* velocity has changed */ + changed = TRUE; + last_fix->track = fix->track; + last_fix->speed = fix->speed; + } + } else if ((gpsd->gpsdata->set & CLIMB_SET) && + (nmea_tag == NMEA_GGA || + nmea_tag == NMEA_GSA || + nmea_tag == NMEA_GSV)) { + + gpsd->gpsdata->set &= ~(CLIMB_SET); + + last_fix->time = fix->time; + + if (!equal_or_nan (fix->climb, last_fix->climb)){ + + /* velocity has changed */ + changed = TRUE; + last_fix->climb = fix->climb; + } + } + + if (changed) { + gpsd->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + gpsd->last_velo_fields |= (isnan (last_fix->track)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_DIRECTION; + gpsd->last_velo_fields |= (isnan (last_fix->speed)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_SPEED; + gpsd->last_velo_fields |= (isnan (last_fix->climb)) ? + 0 : GEOCLUE_VELOCITY_FIELDS_CLIMB; + + gc_iface_velocity_emit_velocity_changed + (GC_IFACE_VELOCITY (gpsd), gpsd->last_velo_fields, + (int)(last_fix->time+0.5), + last_fix->speed, last_fix->track, last_fix->climb); + } +} + +static void +geoclue_gpsd_update_status (GeoclueGpsd *gpsd, NmeaTag nmea_tag) +{ + GeoclueStatus status; + + /* gpsdata->online is supposedly always up-to-date */ + if (gpsd->gpsdata->online <= 0) { + status = GEOCLUE_STATUS_UNAVAILABLE; + } else if (gpsd->gpsdata->set & STATUS_SET) { + gpsd->gpsdata->set &= ~(STATUS_SET); + + if (gpsd->gpsdata->status > 0) { + status = GEOCLUE_STATUS_AVAILABLE; + } else { + status = GEOCLUE_STATUS_ACQUIRING; + } + } else { + return; + } + + geoclue_gpsd_set_status (gpsd, status); +} + +static void +gpsd_raw_hook (struct gps_data_t *gpsdata, char *message, size_t len) +{ + char *tag_str = gpsd->gpsdata->tag; + NmeaTag nmea_tag = NMEA_NONE; + + if (tag_str[0] == 'G' && tag_str[1] == 'S' && tag_str[2] == 'A') { + nmea_tag = NMEA_GSA; + } else if (tag_str[0] == 'G' && tag_str[1] == 'G' && tag_str[2] == 'A') { + nmea_tag = NMEA_GGA; + } else if (tag_str[0] == 'G' && tag_str[1] == 'S' && tag_str[2] == 'V') { + nmea_tag = NMEA_GSV; + } else if (tag_str[0] == 'R' && tag_str[1] == 'M' && tag_str[2] == 'C') { + nmea_tag = NMEA_RMC; + } + + geoclue_gpsd_update_status (gpsd, nmea_tag); + geoclue_gpsd_update_position (gpsd, nmea_tag); + geoclue_gpsd_update_velocity (gpsd, nmea_tag); +} + +static void +geoclue_gpsd_stop_gpsd (GeoclueGpsd *self) +{ + if (self->gpsdata) { + gps_close (self->gpsdata); + self->gpsdata = NULL; + } +} + +static gboolean +geoclue_gpsd_start_gpsd (GeoclueGpsd *self) +{ + self->gpsdata = gps_open (self->host, self->port); + if (self->gpsdata) { + gps_stream(self->gpsdata, WATCH_ENABLE | WATCH_NMEA | POLL_NONBLOCK, NULL); + gps_set_raw_hook (self->gpsdata, gpsd_raw_hook); + return TRUE; + } else { + g_warning ("gps_open() failed, is gpsd running (host=%s,port=%s)?", self->host, self->port); + return FALSE; + } +} + +gboolean +gpsd_poll(gpointer data) +{ + GeoclueGpsd *self = (GeoclueGpsd*)data; + if (self->gpsdata) { + if (gps_poll(self->gpsdata) < 0) { + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ERROR); + geoclue_gpsd_stop_gpsd(self); + return FALSE; + } + } + return TRUE; +} + +static void +geoclue_gpsd_init (GeoclueGpsd *self) +{ + self->gpsdata = NULL; + self->last_fix = g_new0 (gps_fix, 1); + + self->last_pos_fields = GEOCLUE_POSITION_FIELDS_NONE; + self->last_velo_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + self->last_accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); + + gc_provider_set_details (GC_PROVIDER (self), + "org.freedesktop.Geoclue.Providers.Gpsd", + "/org/freedesktop/Geoclue/Providers/Gpsd", + "Gpsd", "Gpsd provider"); + + self->port = g_strdup (DEFAULT_GPSD_PORT); + self->host = NULL; + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ACQUIRING); + if (!geoclue_gpsd_start_gpsd (self)) { + geoclue_gpsd_set_status (self, GEOCLUE_STATUS_ERROR); + } +} + +static gboolean +get_position (GcIfacePosition *gc, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *timestamp = (int)(gpsd->last_fix->time+0.5); + *latitude = gpsd->last_fix->latitude; + *longitude = gpsd->last_fix->longitude; + *altitude = gpsd->last_fix->altitude; + *fields = gpsd->last_pos_fields; + *accuracy = geoclue_accuracy_copy (gpsd->last_accuracy); + + return TRUE; +} + +static void +geoclue_gpsd_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = get_position; +} + +static gboolean +get_velocity (GcIfaceVelocity *gc, + GeoclueVelocityFields *fields, + int *timestamp, + double *speed, + double *direction, + double *climb, + GError **error) +{ + GeoclueGpsd *gpsd = GEOCLUE_GPSD (gc); + + *timestamp = (int)(gpsd->last_fix->time+0.5); + *speed = gpsd->last_fix->speed; + *direction = gpsd->last_fix->track; + *climb = gpsd->last_fix->climb; + *fields = gpsd->last_velo_fields; + + return TRUE; +} + +static void +geoclue_gpsd_velocity_init (GcIfaceVelocityClass *iface) +{ + iface->get_velocity = get_velocity; +} + +int +main (int argc, + char **argv) +{ + g_type_init (); + + gpsd = g_object_new (GEOCLUE_TYPE_GPSD, NULL); + + gpsd->loop = g_main_loop_new (NULL, TRUE); + g_timeout_add(500, gpsd_poll, (gpointer)gpsd); + + g_main_loop_run (gpsd->loop); + + g_main_loop_unref (gpsd->loop); + g_object_unref (gpsd); + + return 0; +} diff --git a/.pc/tizen.patch/providers/gsmloc/Makefile.am b/.pc/tizen.patch/providers/gsmloc/Makefile.am new file mode 100755 index 0000000..1820f8c --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/Makefile.am @@ -0,0 +1,77 @@ +libexec_PROGRAMS = \ + geoclue-gsmloc + +nodist_geoclue_gsmloc_SOURCES = \ + ofono-marshal.c \ + ofono-marshal.h \ + ofono-manager-bindings.h \ + ofono-modem-bindings.h \ + ofono-network-registration-bindings.h \ + ofono-network-operator-bindings.h \ + mm-marshal.c \ + mm-marshal.h + +BUILT_SOURCES = \ + $(nodist_geoclue_gsmloc_SOURCES) + +geoclue_gsmloc_SOURCES = \ + mcc.h \ + geoclue-gsmloc.c \ + geoclue-gsmloc-ofono.c \ + geoclue-gsmloc-ofono.h \ + geoclue-gsmloc-mm.c \ + geoclue-gsmloc-mm.h + + +geoclue_gsmloc_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_gsmloc_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-gsmloc.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Gsmloc.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + ofono-marshal.list \ + ofono-manager.xml \ + ofono-modem.xml \ + ofono-network-operator.xml \ + ofono-network-registration.xml \ + mm-marshal.list \ + $(service_in_files) \ + $(providers_DATA) + +CLEANFILES = \ + $(BUILT_SOURCES) + +DISTCLEANFILES = \ + $(service_DATA) + +%-bindings.h: stamp-%-bindings.h + @true +stamp-%-bindings.h: %.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --mode=glib-client $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +ofono-marshal.h: ofono-marshal.list $(GLIB_GENMARSHAL) + $(GLIB_GENMARSHAL) $< --header --prefix=ofono_marshal > $@ +ofono-marshal.c: ofono-marshal.list ofono-marshal.h $(GLIB_GENMARSHAL) + $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=ofono_marshal $(srcdir)/ofono-marshal.list --header --body >> $@ + +mm-marshal.h: mm-marshal.list $(GLIB_GENMARSHAL) + $(AM_V_GEN) $(GLIB_GENMARSHAL) $< --header --prefix=mm_marshal > $@ +mm-marshal.c: mm-marshal.list mm-marshal.h $(GLIB_GENMARSHAL) + $(AM_V_GEN) $(GLIB_GENMARSHAL) --prefix=mm_marshal $(srcdir)/mm-marshal.list --header --body >> $@ diff --git a/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.c b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.c new file mode 100755 index 0000000..bd882d1 --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.c @@ -0,0 +1,779 @@ +/* + * Geoclue + * geoclue-gsmloc-mm.c - An Address/Position provider for ModemManager + * + * Author: Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include <config.h> + +#include <unistd.h> +#include <string.h> +#include <errno.h> +#include <stdlib.h> + +#include <glib-object.h> +#include <dbus/dbus.h> +#include <dbus/dbus-glib-bindings.h> + +#include "geoclue-gsmloc-mm.h" + +#include "mm-marshal.h" + +#define MM_DBUS_SERVICE "org.freedesktop.ModemManager" +#define MM_DBUS_PATH "/org/freedesktop/ModemManager" +#define MM_DBUS_INTERFACE "org.freedesktop.ModemManager" +#define MM_DBUS_LOC_INTERFACE "org.freedesktop.ModemManager.Modem.Location" +#define DBUS_PROPS_INTERFACE "org.freedesktop.DBus.Properties" +#define MM_DBUS_MODEM_INTERFACE "org.freedesktop.ModemManager.Modem" + +G_DEFINE_TYPE (GeoclueGsmlocMm, geoclue_gsmloc_mm, G_TYPE_OBJECT) + +#define GEOCLUE_GSMLOC_MM_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GEOCLUE_TYPE_GSMLOC_MM, GeoclueGsmlocMmPrivate)) + +typedef struct { + char *path; + + DBusGProxy *loc_proxy; + DBusGProxy *props_proxy; + DBusGProxy *modem_proxy; + + gboolean got_enabled; + gboolean enabled; + gboolean enabling; + + gboolean got_loc_enabled; + gboolean loc_enabled; + gboolean loc_enabling; + gboolean got_initial_loc; + + /* Whether the modem signals its location or whether we + * have to poll for it. + */ + gboolean signals; + guint loc_idle; + + gboolean has_location; + + gpointer owner; +} Modem; + +typedef struct { + DBusGConnection *bus; + DBusGProxy *dbus_proxy; + + /* Listens for device add/remove events */ + DBusGProxy *mm_proxy; + DBusGProxy *props_proxy; + + /* List of Modem objects */ + GSList *modems; +} GeoclueGsmlocMmPrivate; + +enum { + PROP_0, + PROP_AVAILABLE, +}; + +enum { + NETWORK_DATA_CHANGED, + LAST_SIGNAL +}; +static guint signals[LAST_SIGNAL] = {0}; + +#define LOC_CAP_GSM_LACCI 0x02 + +gboolean mm_debug = FALSE; + +#define debugmsg(fmt, args...) \ + { if (mm_debug) { g_debug (fmt, ##args); } } + + +static gboolean +is_available (GeoclueGsmlocMm *self) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + GSList *iter; + + for (iter = priv->modems; iter; iter = g_slist_next (iter)) { + Modem *modem = iter->data; + + if (modem->enabled && modem->loc_enabled && modem->has_location) + return TRUE; + } + + return FALSE; +} + +static Modem * +find_modem (GeoclueGsmlocMm *self, const char *path) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + GSList *iter; + + g_return_val_if_fail (path != NULL, NULL); + + for (iter = priv->modems; iter; iter = g_slist_next (iter)) { + Modem *modem = iter->data; + + if (strcmp (path, modem->path) == 0) + return modem; + } + + return NULL; +} + +static void +recheck_available (GeoclueGsmlocMm *self) +{ + g_object_notify (G_OBJECT (self), "available"); +} + +static void +location_update (GeoclueGsmlocMm *self, const char *loc) +{ + char **components = NULL; + char *dec_lac = NULL, *dec_cid = NULL; + unsigned long int num; + + components = g_strsplit (loc, ",", 0); + if (!components || g_strv_length (components) < 4) { + g_warning ("%s: invalid GSM LAC/CI location: '%s'", __func__, loc); + goto out; + } + + /* convert lac to decimal */ + errno = 0; + num = strtoul (components[2], NULL, 16); + if (errno != 0) { + g_warning ("%s: cannot convert LAC '%s' to decimal!", + __func__, components[2]); + goto out; + } + dec_lac = g_strdup_printf ("%u", num); + + /* convert cell id to decimal */ + errno = 0; + num = strtoul (components[3], NULL, 16); + if (errno != 0) { + g_warning ("%s: cannot convert Cell ID '%s' to decimal!", + __func__, components[3]); + goto out; + } + dec_cid = g_strdup_printf ("%u", num); + + debugmsg ("%s: emitting location: %s/%s/%s/%s", + __func__, components[0], components[1], dec_lac, dec_cid); + g_signal_emit (G_OBJECT (self), signals[NETWORK_DATA_CHANGED], 0, + components[0], /* MCC */ + components[1], /* MNC */ + dec_lac, /* LAC */ + dec_cid); /* CID */ + +out: + if (components) + g_strfreev (components); + g_free (dec_lac); + g_free (dec_cid); +} + +static void +modem_location_update (Modem *modem, GHashTable *locations) +{ + GValue *lacci; + + /* GSMLOC only handles GSM LAC/CI location info */ + lacci = g_hash_table_lookup (locations, GUINT_TO_POINTER (LOC_CAP_GSM_LACCI)); + if (!lacci) + return; + if (!G_VALUE_HOLDS_STRING (lacci)) { + g_warning ("%s: GSM LAC/CI location member not a string!", __func__); + return; + } + + debugmsg ("%s: GSM LAC/CI: %s", __func__, g_value_get_string (lacci)); + location_update (modem->owner, g_value_get_string (lacci)); +} + +#define DBUS_TYPE_LOCATIONS (dbus_g_type_get_map ("GHashTable", G_TYPE_UINT, G_TYPE_VALUE)) +#define DBUS_TYPE_G_MAP_OF_VARIANT (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE)) + +static void +loc_poll_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GError *error = NULL; + GHashTable *locations = NULL; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_LOCATIONS, &locations, + G_TYPE_INVALID)) { + g_warning ("%s: failed to get location: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + modem_location_update ((Modem *) user_data, locations); + g_hash_table_destroy (locations); +} + +static gboolean +modem_loc_poll (gpointer user_data) +{ + Modem *modem = user_data; + + dbus_g_proxy_begin_call (modem->loc_proxy, "GetLocation", + loc_poll_cb, modem, NULL, + G_TYPE_INVALID); + + return TRUE; +} + +static void +modem_loc_enable_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + Modem *modem = user_data; + GError *error = NULL; + + modem->loc_enabling = FALSE; + if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) { + g_warning ("%s: failed to enable modem location services: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } +} + +static void +modem_try_loc_enable (Modem *modem) +{ + /* Don't enable location services if we don't have all the modem's + * status yet or if location services are already enabled. + */ + + if (!modem->got_loc_enabled || + !modem->enabled || + !modem->has_location || + !modem->got_loc_enabled || + modem->loc_enabled || + modem->loc_enabling) + return; + + modem->loc_enabling = TRUE; + debugmsg ("%s: (%s) enabling location services...", __func__, modem->path); + dbus_g_proxy_begin_call (modem->loc_proxy, "Enable", + modem_loc_enable_cb, modem, NULL, + G_TYPE_BOOLEAN, TRUE, /* enable */ + G_TYPE_BOOLEAN, TRUE, /* signal location changes */ + G_TYPE_INVALID); +} + +static void +modem_enable_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + Modem *modem = user_data; + GError *error = NULL; + + modem->enabling = FALSE; + if (!dbus_g_proxy_end_call (proxy, call, &error, G_TYPE_INVALID)) { + g_warning ("%s: failed to enable modem: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + /* enable location services */ + modem_try_loc_enable (modem); +} + +static void +modem_properties_changed (DBusGProxy *proxy, + const char *interface, + GHashTable *props, + gpointer user_data) +{ + Modem *modem = user_data; + GValue *value; + gboolean old_avail = modem->enabled && modem->loc_enabled && modem->has_location; + gboolean new_avail; + + if (strcmp (interface, MM_DBUS_MODEM_INTERFACE) == 0) { + value = g_hash_table_lookup (props, "Enabled"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + modem->enabled = g_value_get_boolean (value); + modem->got_enabled = TRUE; + debugmsg ("%s: (%s) modem %s", __func__, modem->path, + modem->enabled ? "enabled" : "disabled"); + } + } else if (strcmp (interface, MM_DBUS_LOC_INTERFACE) == 0) { + value = g_hash_table_lookup (props, "Enabled"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + modem->loc_enabled = g_value_get_boolean (value); + modem->got_loc_enabled = TRUE; + debugmsg ("%s: (%s) modem location services %s", + __func__, modem->path, + modem->loc_enabled ? "enabled" : "disabled"); + } + + value = g_hash_table_lookup (props, "SignalsLocation"); + if (value && G_VALUE_HOLDS_BOOLEAN (value)) { + modem->signals = g_value_get_boolean (value); + debugmsg ("%s: (%s) modem %s signal location updates", + __func__, modem->path, + modem->signals ? "will" : "does not"); + } + + value = g_hash_table_lookup (props, "Capabilities"); + if (value && G_VALUE_HOLDS_UINT (value)) { + debugmsg ("%s: (%s) modem location capabilities: 0x%X", + __func__, modem->path, + g_value_get_uint (value)); + + if (g_value_get_uint (value) & LOC_CAP_GSM_LACCI) + modem->has_location = TRUE; + } + + value = g_hash_table_lookup (props, "Location"); + if (value && G_VALUE_HOLDS_BOXED (value)) + modem_location_update (modem, (GHashTable *) g_value_get_boxed (value)); + } + + new_avail = modem->enabled && modem->loc_enabled && modem->has_location; + + /* If the modem doesn't signal its location, start polling for the + * location now. + */ + if (new_avail && !modem->signals && !modem->loc_idle) { + modem->loc_idle = g_timeout_add_seconds (20, modem_loc_poll, modem); + /* Kick off a quick location request */ + modem_loc_poll (modem); + } + + /* If the modem is no longer enabled, or it now signals its location + * then we no longer need to poll. + */ + if ((!new_avail || modem->signals) && modem->loc_idle) + g_source_remove (modem->loc_idle); + + /* Tell the manager to recheck availability of location info */ + if (old_avail != new_avail) + recheck_available (modem->owner); + + /* If we've successfully retrieved modem properties and the modem + * isn't enabled, do that now. + */ + if (modem->got_enabled && !modem->enabled && !modem->enabling) { + debugmsg ("%s: (%s) enabling...", __func__, modem->path); + modem->enabling = TRUE; + dbus_g_proxy_begin_call (modem->modem_proxy, "Enable", + modem_enable_cb, modem, NULL, + G_TYPE_BOOLEAN, TRUE, G_TYPE_INVALID); + } + + /* If the modem was already enabled but location services weren't, + * enable them now. + */ + modem_try_loc_enable (modem); + + /* After location is enabled, try to get the location ASAP */ + if (modem->has_location && modem->loc_enabled && !modem->got_initial_loc) { + modem->got_initial_loc = TRUE; + modem_loc_poll (modem); + } +} + +static void +modem_props_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GError *error = NULL; + GHashTable *props = NULL; + Modem *modem = user_data; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + g_warning ("%s: failed to get modem interface properties: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + modem_properties_changed (modem->loc_proxy, MM_DBUS_MODEM_INTERFACE, props, modem); + g_hash_table_destroy (props); +} + +static void +loc_props_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GError *error = NULL; + GHashTable *props = NULL; + Modem *modem = user_data; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + DBUS_TYPE_G_MAP_OF_VARIANT, &props, + G_TYPE_INVALID)) { + g_warning ("%s: failed to get location interface properties: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + modem_properties_changed (modem->loc_proxy, MM_DBUS_LOC_INTERFACE, props, modem); + g_hash_table_destroy (props); + + /* Now that we know the device supports location services, get basic + * modem properties and start grabbing location info. + */ + dbus_g_proxy_begin_call (modem->props_proxy, "GetAll", + modem_props_cb, modem, NULL, + G_TYPE_STRING, MM_DBUS_MODEM_INTERFACE, G_TYPE_INVALID); +} + +static Modem * +modem_new (DBusGConnection *bus, const char *path, gpointer owner) +{ + Modem *modem; + + modem = g_slice_new0 (Modem); + modem->owner = owner; + modem->path = g_strdup (path); + + modem->loc_proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + path, + MM_DBUS_LOC_INTERFACE); + + modem->modem_proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + path, + MM_DBUS_MODEM_INTERFACE); + + /* Listen for property changes */ + modem->props_proxy = dbus_g_proxy_new_for_name (bus, + MM_DBUS_SERVICE, + path, + "org.freedesktop.DBus.Properties"); + dbus_g_object_register_marshaller (mm_marshal_VOID__STRING_BOXED, + G_TYPE_NONE, + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_add_signal (modem->props_proxy, "MmPropertiesChanged", + G_TYPE_STRING, DBUS_TYPE_G_MAP_OF_VARIANT, + G_TYPE_INVALID); + dbus_g_proxy_connect_signal (modem->props_proxy, "MmPropertiesChanged", + G_CALLBACK (modem_properties_changed), + modem, + NULL); + + debugmsg ("%s: (%s) modem created", __func__, path); + + /* Check if the Location interface is actually supported before doing + * anything with the modem, because if it's not, we don't care about + * the modem at all. + */ + dbus_g_proxy_begin_call (modem->props_proxy, "GetAll", + loc_props_cb, modem, NULL, + G_TYPE_STRING, MM_DBUS_LOC_INTERFACE, G_TYPE_INVALID); + + return modem; +} + +static void +modem_free (Modem *modem) +{ + + debugmsg ("%s: (%s) modem removed", __func__, modem->path); + + g_free (modem->path); + g_object_unref (modem->loc_proxy); + g_object_unref (modem->modem_proxy); + g_object_unref (modem->props_proxy); + + if (modem->loc_idle) + g_source_remove (modem->loc_idle); + + memset (modem, 0, sizeof (Modem)); + g_slice_free (Modem, modem); +} + +static void +modem_added (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + GeoclueGsmlocMm *self = GEOCLUE_GSMLOC_MM (user_data); + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + Modem *modem; + + if (!find_modem (self, path)) { + modem = modem_new (priv->bus, path, self); + priv->modems = g_slist_prepend (priv->modems, modem); + } +} + +static void +enumerate_modems_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer user_data) +{ + GPtrArray *modems; + GError *error = NULL; + int i; + + if (!dbus_g_proxy_end_call (proxy, call, &error, + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), &modems, + G_TYPE_INVALID)) { + g_warning ("%s: failed to enumerate modems: (%d) %s", + __func__, + error ? error->code : -1, + error && error->message ? error->message : "(unknown)"); + g_clear_error (&error); + return; + } + + for (i = 0; i < modems->len; i++) { + char *path = g_ptr_array_index (modems, i); + + modem_added (NULL, path, GEOCLUE_GSMLOC_MM (user_data)); + g_free (path); + } + g_ptr_array_free (modems, TRUE); +} + +static void +enumerate_modems (GeoclueGsmlocMm *self) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + + dbus_g_proxy_begin_call (priv->mm_proxy, "EnumerateDevices", + enumerate_modems_cb, self, NULL, + G_TYPE_INVALID); +} + +static void +modem_removed (DBusGProxy *proxy, const char *path, gpointer user_data) +{ + GeoclueGsmlocMm *self = GEOCLUE_GSMLOC_MM (user_data); + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + Modem *modem; + + modem = find_modem (self, path); + if (modem) { + gboolean old_available = is_available (self); + + priv->modems = g_slist_remove (priv->modems, modem); + modem_free (modem); + if (is_available (self) != old_available) + g_object_notify (G_OBJECT (self), "available"); + } +} + +static void +kill_modems (GeoclueGsmlocMm *self) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + gboolean old_available = is_available (self); + GSList *iter; + + /* Kill all modems */ + for (iter = priv->modems; iter; iter = g_slist_next (iter)) + modem_free ((Modem *) iter->data); + g_slist_free (priv->modems); + priv->modems = NULL; + + /* No more modems; clearly location is no longer available */ + if (old_available) + g_object_notify (G_OBJECT (self), "available"); +} + +static void +name_owner_changed (DBusGProxy *proxy, + const char *name, + const char *old_owner, + const char *new_owner, + gpointer user_data) +{ + gboolean old_owner_good; + gboolean new_owner_good; + + if (strcmp (MM_DBUS_SERVICE, name) != 0) + return; + + old_owner_good = (old_owner && strlen (old_owner)); + new_owner_good = (new_owner && strlen (new_owner)); + + if (!old_owner_good && new_owner_good) { + debugmsg ("ModemManager appeared"); + enumerate_modems (GEOCLUE_GSMLOC_MM (user_data)); + } else if (old_owner_good && !new_owner_good) { + debugmsg ("ModemManager disappeared"); + kill_modems (GEOCLUE_GSMLOC_MM (user_data)); + } +} + +GeoclueGsmlocMm * +geoclue_gsmloc_mm_new (void) +{ + return (GeoclueGsmlocMm *) g_object_new (GEOCLUE_TYPE_GSMLOC_MM, NULL); +} + +static gboolean +mm_alive (DBusGProxy *proxy) +{ + char *owner = NULL; + gboolean owned = FALSE; + GError *error = NULL; + + if (dbus_g_proxy_call_with_timeout (proxy, + "GetNameOwner", 2000, &error, + G_TYPE_STRING, MM_DBUS_SERVICE, + G_TYPE_INVALID, + G_TYPE_STRING, &owner, + G_TYPE_INVALID)) { + owned = !!owner; + g_free (owner); + } + return owned; +} + +static void +geoclue_gsmloc_mm_init (GeoclueGsmlocMm *self) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (self); + + if (getenv ("GEOCLUE_GSMLOC_MM_DEBUG")) + mm_debug = TRUE; + + priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, NULL); + if (!priv->bus) { + g_warning ("Failed to acquire a connection to the D-Bus system bus."); + return; + } + + priv->dbus_proxy = dbus_g_proxy_new_for_name (priv->bus, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + /* Handle ModemManager restarts */ + dbus_g_proxy_add_signal (priv->dbus_proxy, "NameOwnerChanged", + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->dbus_proxy, "NameOwnerChanged", + G_CALLBACK (name_owner_changed), + self, NULL); + + priv->mm_proxy = dbus_g_proxy_new_for_name (priv->bus, + MM_DBUS_SERVICE, + MM_DBUS_PATH, + MM_DBUS_INTERFACE); + g_assert (priv->mm_proxy); + + dbus_g_proxy_add_signal (priv->mm_proxy, "DeviceAdded", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->mm_proxy, "DeviceAdded", + G_CALLBACK (modem_added), self, NULL); + dbus_g_proxy_add_signal (priv->mm_proxy, "DeviceRemoved", + DBUS_TYPE_G_OBJECT_PATH, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (priv->mm_proxy, "DeviceRemoved", + G_CALLBACK (modem_removed), self, NULL); + + if (mm_alive (priv->dbus_proxy)) { + debugmsg ("ModemManager is alive"); + enumerate_modems (self); + } +} + +static void +dispose (GObject *object) +{ + GeoclueGsmlocMmPrivate *priv = GEOCLUE_GSMLOC_MM_GET_PRIVATE (object); + + kill_modems (GEOCLUE_GSMLOC_MM (object)); + + /* Stop listening to ModemManager */ + if (priv->mm_proxy) { + g_object_unref (priv->mm_proxy); + priv->mm_proxy = NULL; + } + + if (priv->props_proxy) { + g_object_unref (priv->props_proxy); + priv->props_proxy = NULL; + } + + if (priv->dbus_proxy) { + g_object_unref (priv->dbus_proxy); + priv->dbus_proxy = NULL; + } + + G_OBJECT_CLASS (geoclue_gsmloc_mm_parent_class)->dispose (object); +} + +static void +get_property (GObject *object, guint prop_id, + GValue *value, GParamSpec *pspec) +{ + switch (prop_id) { + case PROP_AVAILABLE: + g_value_set_boolean (value, is_available (GEOCLUE_GSMLOC_MM (object))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +geoclue_gsmloc_mm_class_init (GeoclueGsmlocMmClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + g_type_class_add_private (klass, sizeof (GeoclueGsmlocMmPrivate)); + + /* virtual methods */ + object_class->get_property = get_property; + object_class->dispose = dispose; + + /* properties */ + g_object_class_install_property + (object_class, PROP_AVAILABLE, + g_param_spec_boolean ("available", + "Available", + "Whether any mobile broadband device is " + "providing location information at this " + "time.", + FALSE, + G_PARAM_READABLE)); + + /* signals */ + signals[NETWORK_DATA_CHANGED] = + g_signal_new ("network-data-changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, 0, + NULL, NULL, + mm_marshal_VOID__STRING_STRING_STRING_STRING, + G_TYPE_NONE, 4, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); +} + diff --git a/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.h b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.h new file mode 100755 index 0000000..8daf1eb --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc-mm.h @@ -0,0 +1,56 @@ +/* + * Geoclue + * geoclue-gsmloc-mm.h - An Address/Position provider for ModemManager + * + * Author: Dan Williams <dcbw@redhat.com> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#ifndef _GEOCLUE_GSMLOC_MM +#define _GEOCLUE_GSMLOC_MM + +#include <glib-object.h> + +G_BEGIN_DECLS + +#define GEOCLUE_TYPE_GSMLOC_MM (geoclue_gsmloc_mm_get_type ()) + +#define GEOCLUE_GSMLOC_MM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GSMLOC_MM, GeoclueGsmlocMm)) +#define GEOCLUE_GSMLOC_MM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEOCLUE_TYPE_GSMLOC_MM, GeoclueGsmlocMmClass)) +#define GEOCLUE_IS_GSMLOC_MM(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_GSMLOC_MM)) +#define GEOCLUE_IS_GSMLOC_MM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GEOCLUE_TYPE_GSMLOC_MM)) + +typedef struct _GeoclueGsmlocMm { + GObject parent; +} GeoclueGsmlocMm; + +typedef struct _GeoclueGsmlocMmClass { + GObjectClass parent_class; + + void (*network_data_changed) (GeoclueGsmlocMm *mm, + char *mcc, char *mnc, + char *lac, char *cid); +} GeoclueGsmlocMmClass; + +GType geoclue_gsmloc_mm_get_type (void); + +GeoclueGsmlocMm *geoclue_gsmloc_mm_new (void); + +G_END_DECLS + +#endif /* _GEOCLUE_GSMLOC_MM */ + diff --git a/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc.c b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc.c new file mode 100755 index 0000000..6d8b5ba --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/geoclue-gsmloc.c @@ -0,0 +1,459 @@ +/* + * Geoclue + * geoclue-gsmloc.c - A GSM cell based Position provider + * + * Author: Jussi Kukkonen <jku@linux.intel.com> + * Copyright 2008 by Garmin Ltd. or its subsidiaries + * 2010 Intel Corporation + * 2010 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + + /** + * Gsmloc provider is a position and address provider that uses GSM cell + * location and the webservice http://www.opencellid.org/ (a similar service + * used to live at gsmloc.org, hence the name). The web service does not + * provide any address data: that is done with a + * "mobile country code -> ISO country code" lookup table: as a result address + * will only ever have country code and country fields. + * + * Gsmloc requires the oFono or ModemManager telephony stacks to work -- more + * IMSI data sources could be added fairly easily. + **/ + +#include <config.h> + +#include <time.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <glib-object.h> +#include <dbus/dbus-glib-bindings.h> + +#include <geoclue/gc-web-service.h> +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-address.h> + +/* ofono implementation */ +#include "geoclue-gsmloc-ofono.h" + +/* ModemManager implementation */ +#include "geoclue-gsmloc-mm.h" + +/* country code list */ +#include "mcc.h" + +#define GEOCLUE_DBUS_SERVICE_GSMLOC "org.freedesktop.Geoclue.Providers.Gsmloc" +#define GEOCLUE_DBUS_PATH_GSMLOC "/org/freedesktop/Geoclue/Providers/Gsmloc" + +#define OPENCELLID_URL "http://www.opencellid.org/cell/get" +#define OPENCELLID_LAT "/rsp/cell/@lat" +#define OPENCELLID_LON "/rsp/cell/@lon" +#define OPENCELLID_CID "/rsp/cell/@cellId" + +#define GEOCLUE_TYPE_GSMLOC (geoclue_gsmloc_get_type ()) +#define GEOCLUE_GSMLOC(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GSMLOC, GeoclueGsmloc)) + +typedef struct _GeoclueGsmloc GeoclueGsmloc; + +struct _GeoclueGsmloc { + GcProvider parent; + GMainLoop *loop; + GcWebService *web_service; + + GeoclueGsmlocOfono *ofono; + GeoclueGsmlocMm *mm; + + /* current data */ + char *mcc; + char *mnc; + char *lac; + char *cid; + GeocluePositionFields last_position_fields; + GeoclueAccuracyLevel last_accuracy_level; + double last_lat; + double last_lon; + + GHashTable *address; +}; + +typedef struct _GeoclueGsmlocClass { + GcProviderClass parent_class; +} GeoclueGsmlocClass; + + +static void geoclue_gsmloc_init (GeoclueGsmloc *gsmloc); +static void geoclue_gsmloc_position_init (GcIfacePositionClass *iface); +static void geoclue_gsmloc_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueGsmloc, geoclue_gsmloc, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_gsmloc_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + geoclue_gsmloc_address_init)) + + +/* Geoclue interface implementation */ +static gboolean +geoclue_gsmloc_get_status (GcIfaceGeoclue *iface, + GeoclueStatus *status, + GError **error) +{ + GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (iface); + gboolean ofono_available; + gboolean mm_available; + + g_object_get (gsmloc->ofono, "available", &ofono_available, NULL); + g_object_get (gsmloc->mm, "available", &mm_available, NULL); + + if (!ofono_available && !mm_available) { + *status = GEOCLUE_STATUS_ERROR; + } else if (!gsmloc->mcc || !gsmloc->mnc || + !gsmloc->lac || !gsmloc->cid) { + *status = GEOCLUE_STATUS_UNAVAILABLE; + } else { + *status = GEOCLUE_STATUS_AVAILABLE; + } + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (provider); + g_main_loop_quit (gsmloc->loop); +} + +static gboolean +geoclue_gsmloc_query_opencellid (GeoclueGsmloc *gsmloc) +{ + double lat, lon; + GeocluePositionFields fields = GEOCLUE_POSITION_FIELDS_NONE; + GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE; + + if (gsmloc->mcc && gsmloc->mnc && + gsmloc->lac && gsmloc->cid) { + + if (gc_web_service_query (gsmloc->web_service, NULL, + "mcc", gsmloc->mcc, + "mnc", gsmloc->mnc, + "lac", gsmloc->lac, + "cellid", gsmloc->cid, + (char *)0)) { + + if (gc_web_service_get_double (gsmloc->web_service, + &lat, OPENCELLID_LAT)) { + fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + } + if (gc_web_service_get_double (gsmloc->web_service, + &lon, OPENCELLID_LON)) { + fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + } + + if (fields != GEOCLUE_POSITION_FIELDS_NONE) { + char *retval_cid; + /* if cellid is not present, location is for the local area code. + * the accuracy might be an overstatement -- I have no idea how + * big LACs typically are */ + level = GEOCLUE_ACCURACY_LEVEL_LOCALITY; + if (gc_web_service_get_string (gsmloc->web_service, + &retval_cid, OPENCELLID_CID)) { + if (retval_cid && strlen (retval_cid) != 0) { + level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE; + } + g_free (retval_cid); + } + } + } + } + + if (fields != gsmloc->last_position_fields || + (fields != GEOCLUE_POSITION_FIELDS_NONE && + (lat != gsmloc->last_lat || + lon != gsmloc->last_lon || + level != gsmloc->last_accuracy_level))) { + GeoclueAccuracy *acc; + + /* position changed */ + + gsmloc->last_position_fields = fields; + gsmloc->last_accuracy_level = level; + gsmloc->last_lat = lat; + gsmloc->last_lon = lon; + + acc = geoclue_accuracy_new (gsmloc->last_accuracy_level, 0.0, 0.0); + gc_iface_position_emit_position_changed (GC_IFACE_POSITION (gsmloc), + fields, + time (NULL), + lat, lon, 0.0, + acc); + geoclue_accuracy_free (acc); + return TRUE; + } + + return FALSE; +} + +static void +geoclue_gsmloc_update_address (GeoclueGsmloc *gsmloc) +{ + char *countrycode = NULL; + const char *old_countrycode; + gboolean changed = FALSE; + GeoclueAccuracy *acc; + + if (gsmloc->mcc) { + gint64 i; + i = g_ascii_strtoll (gsmloc->mcc, NULL, 10); + if (i > 0 && i < 800 && mcc_country_codes[i]) { + countrycode = mcc_country_codes[i]; + } + } + + old_countrycode = g_hash_table_lookup (gsmloc->address, + GEOCLUE_ADDRESS_KEY_COUNTRYCODE); + if (g_strcmp0 (old_countrycode, countrycode) != 0) { + changed = TRUE; + } + + if (countrycode) { + g_hash_table_insert (gsmloc->address, + GEOCLUE_ADDRESS_KEY_COUNTRYCODE, g_strdup (countrycode)); + acc = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_COUNTRY, 0.0, 0.0); + } else { + g_hash_table_remove (gsmloc->address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE); + g_hash_table_remove (gsmloc->address, GEOCLUE_ADDRESS_KEY_COUNTRY); + acc = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0); + } + geoclue_address_details_set_country_from_code (gsmloc->address); + + if (changed) { + gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (gsmloc), + time (NULL), + gsmloc->address, + acc); + + } + geoclue_accuracy_free (acc); +} +static void +geoclue_gsmloc_set_cell (GeoclueGsmloc *gsmloc, + const char *mcc, const char *mnc, + const char *lac, const char *cid) +{ + g_free (gsmloc->mcc); + g_free (gsmloc->mnc); + g_free (gsmloc->lac); + g_free (gsmloc->cid); + + gsmloc->mcc = g_strdup (mcc); + gsmloc->mnc = g_strdup (mnc); + gsmloc->lac = g_strdup (lac); + gsmloc->cid = g_strdup (cid); + + geoclue_gsmloc_update_address (gsmloc); + geoclue_gsmloc_query_opencellid (gsmloc); +} + +static void +network_data_changed_cb (gpointer connection_manager, + const char *mcc, const char *mnc, + const char *lac, const char *cid, + GeoclueGsmloc *gsmloc) +{ + if (g_strcmp0 (mcc, gsmloc->mcc) != 0 || + g_strcmp0 (mnc, gsmloc->mnc) != 0 || + g_strcmp0 (lac, gsmloc->lac) != 0 || + g_strcmp0 (cid, gsmloc->cid) != 0) { + + /* new cell data, do a opencellid lookup */ + geoclue_gsmloc_set_cell (gsmloc, mcc, mnc, lac, cid); + } +} + +/* Position interface implementation */ + +static gboolean +geoclue_gsmloc_get_position (GcIfacePosition *iface, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGsmloc *gsmloc; + + gsmloc = (GEOCLUE_GSMLOC (iface)); + + if (gsmloc->last_position_fields == GEOCLUE_POSITION_FIELDS_NONE) { + /* re-query in case there was a network problem */ + geoclue_gsmloc_query_opencellid (gsmloc); + } + + if (timestamp) { + *timestamp = time (NULL); + } + + if (fields) { + *fields = gsmloc->last_position_fields; + } + if (latitude) { + *latitude = gsmloc->last_lat; + } + if (longitude) { + *longitude = gsmloc->last_lon; + } + if (accuracy) { + *accuracy = geoclue_accuracy_new (gsmloc->last_accuracy_level, 0, 0); + } + + return TRUE; +} + +/* Address interface implementation */ +static gboolean +geoclue_gsmloc_get_address (GcIfaceAddress *iface, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGsmloc *obj = GEOCLUE_GSMLOC (iface); + + if (address) { + *address = geoclue_address_details_copy (obj->address); + } + if (accuracy) { + GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE; + if (g_hash_table_lookup (obj->address, GEOCLUE_ADDRESS_KEY_COUNTRY)) { + level = GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } + *accuracy = geoclue_accuracy_new (level, 0.0, 0.0); + } + if (timestamp) { + *timestamp = time (NULL); + } + + return TRUE; +} + + +static void +geoclue_gsmloc_dispose (GObject *obj) +{ + GeoclueGsmloc *gsmloc = GEOCLUE_GSMLOC (obj); + + if (gsmloc->ofono) { + g_signal_handlers_disconnect_by_func (gsmloc->ofono, + network_data_changed_cb, + gsmloc); + g_object_unref (gsmloc->ofono); + gsmloc->ofono = NULL; + } + + if (gsmloc->mm) { + g_signal_handlers_disconnect_by_func (gsmloc->mm, + network_data_changed_cb, + gsmloc); + g_object_unref (gsmloc->mm); + gsmloc->mm = NULL; + } + + if (gsmloc->address) { + g_hash_table_destroy (gsmloc->address); + gsmloc->address = NULL; + } + + ((GObjectClass *) geoclue_gsmloc_parent_class)->dispose (obj); +} + + +/* Initialization */ + +static void +geoclue_gsmloc_class_init (GeoclueGsmlocClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *)klass; + GObjectClass *o_class = (GObjectClass *)klass; + + p_class->shutdown = shutdown; + p_class->get_status = geoclue_gsmloc_get_status; + + o_class->dispose = geoclue_gsmloc_dispose; +} + +static void +geoclue_gsmloc_init (GeoclueGsmloc *gsmloc) +{ + gsmloc->address = geoclue_address_details_new (); + + gc_provider_set_details (GC_PROVIDER (gsmloc), + GEOCLUE_DBUS_SERVICE_GSMLOC, + GEOCLUE_DBUS_PATH_GSMLOC, + "Gsmloc", "GSM cell based position provider"); + + gsmloc->web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL); + gc_web_service_set_base_url (gsmloc->web_service, OPENCELLID_URL); + + geoclue_gsmloc_set_cell (gsmloc, NULL, NULL, NULL, NULL); + + gsmloc->address = geoclue_address_details_new (); + + /* init ofono*/ + gsmloc->ofono = geoclue_gsmloc_ofono_new (); + g_signal_connect (gsmloc->ofono, "network-data-changed", + G_CALLBACK (network_data_changed_cb), gsmloc); + + /* init mm */ + gsmloc->mm = geoclue_gsmloc_mm_new (); + g_signal_connect (gsmloc->mm, "network-data-changed", + G_CALLBACK (network_data_changed_cb), gsmloc); +} + +static void +geoclue_gsmloc_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = geoclue_gsmloc_get_position; +} + +static void +geoclue_gsmloc_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = geoclue_gsmloc_get_address; +} + +int +main() +{ + g_type_init(); + + GeoclueGsmloc *o = g_object_new (GEOCLUE_TYPE_GSMLOC, NULL); + o->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (o->loop); + + g_main_loop_unref (o->loop); + g_object_unref (o); + + return 0; +} diff --git a/.pc/tizen.patch/providers/gsmloc/mm-marshal.list b/.pc/tizen.patch/providers/gsmloc/mm-marshal.list new file mode 100755 index 0000000..d2ce65a --- /dev/null +++ b/.pc/tizen.patch/providers/gsmloc/mm-marshal.list @@ -0,0 +1,2 @@ +VOID:STRING,STRING,STRING,STRING +VOID:STRING,BOXED diff --git a/.pc/tizen.patch/providers/gypsy/Makefile.am b/.pc/tizen.patch/providers/gypsy/Makefile.am new file mode 100755 index 0000000..937bf06 --- /dev/null +++ b/.pc/tizen.patch/providers/gypsy/Makefile.am @@ -0,0 +1,32 @@ +libexec_PROGRAMS = geoclue-gypsy + +geoclue_gypsy_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) \ + $(GYPSY_CFLAGS) + +geoclue_gypsy_LDADD = \ + $(GEOCLUE_LIBS) \ + $(GYPSY_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +geoclue_gypsy_SOURCES = \ + geoclue-gypsy.c + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-gypsy.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Gypsy.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/gypsy/geoclue-gypsy.c b/.pc/tizen.patch/providers/gypsy/geoclue-gypsy.c new file mode 100755 index 0000000..bc390ce --- /dev/null +++ b/.pc/tizen.patch/providers/gypsy/geoclue-gypsy.c @@ -0,0 +1,623 @@ +/* + * Geoclue + * geoclue-gypsy.c - Geoclue backend for Gypsy which provides the Position. + * + * Authors: Iain Holmes <iain@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <gypsy/gypsy-control.h> +#include <gypsy/gypsy-device.h> +#include <gypsy/gypsy-position.h> +#include <gypsy/gypsy-course.h> +#include <gypsy/gypsy-accuracy.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-velocity.h> + +typedef struct { + GcProvider parent; + + char *device_name; + guint baud_rate; + + GypsyControl *control; + GypsyDevice *device; + GypsyPosition *position; + GypsyCourse *course; + GypsyAccuracy *acc; + + GMainLoop *loop; + + int timestamp; + + GeoclueStatus status; + + /* Cached so we don't have to make D-Bus method calls all the time */ + GypsyPositionFields position_fields; + double latitude; + double longitude; + double altitude; + + GypsyCourseFields course_fields; + double speed; + double direction; + double climb; + + GeoclueAccuracy *accuracy; +} GeoclueGypsy; + +typedef struct { + GcProviderClass parent_class; +} GeoclueGypsyClass; + +static void geoclue_gypsy_position_init (GcIfacePositionClass *iface); +static void geoclue_gypsy_velocity_init (GcIfaceVelocityClass *iface); + +#define GEOCLUE_TYPE_GYPSY (geoclue_gypsy_get_type ()) +#define GEOCLUE_GYPSY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_GYPSY, GeoclueGypsy)) + +G_DEFINE_TYPE_WITH_CODE (GeoclueGypsy, geoclue_gypsy, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_gypsy_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_VELOCITY, + geoclue_gypsy_velocity_init)) + + +/* GcIfaceGeoclue methods */ + +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc); + + *status = gypsy->status; + + return TRUE; +} + + +/* Compare the two fields and return TRUE if they have changed */ +static gboolean +compare_field (GypsyPositionFields fields_a, + double value_a, + GypsyPositionFields fields_b, + double value_b, + GypsyPositionFields field) +{ + /* If both fields are valid, compare the values */ + if ((fields_a & field) && (fields_b & field)) { + if (value_a == value_b) { + return FALSE; + } else { + return TRUE; + } + } + + /* Otherwise return if both the fields set are the same */ + return ((fields_a & field) != (fields_b & field)); +} + +static GeocluePositionFields +gypsy_position_to_geoclue (GypsyPositionFields fields) +{ + GeocluePositionFields gc_fields = GEOCLUE_POSITION_FIELDS_NONE; + + gc_fields |= (fields & GYPSY_POSITION_FIELDS_LATITUDE) ? GEOCLUE_POSITION_FIELDS_LATITUDE : 0; + gc_fields |= (fields & GYPSY_POSITION_FIELDS_LONGITUDE) ? GEOCLUE_POSITION_FIELDS_LONGITUDE : 0; + gc_fields |= (fields & GYPSY_POSITION_FIELDS_ALTITUDE) ? GEOCLUE_POSITION_FIELDS_ALTITUDE : 0; + + return gc_fields; +} + +static GeoclueVelocityFields +gypsy_course_to_geoclue (GypsyCourseFields fields) +{ + GeoclueVelocityFields gc_fields = GEOCLUE_VELOCITY_FIELDS_NONE; + + gc_fields |= (fields & GYPSY_COURSE_FIELDS_SPEED) ? GEOCLUE_VELOCITY_FIELDS_SPEED : 0; + gc_fields |= (fields & GYPSY_COURSE_FIELDS_DIRECTION) ? GEOCLUE_VELOCITY_FIELDS_DIRECTION : 0; + gc_fields |= (fields & GYPSY_COURSE_FIELDS_CLIMB) ? GEOCLUE_VELOCITY_FIELDS_CLIMB : 0; + + return gc_fields; +} + +static void +position_changed (GypsyPosition *position, + GypsyPositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueGypsy *gypsy) +{ + gboolean changed = FALSE; + + g_print ("Gypsy position changed\n"); + gypsy->timestamp = timestamp; + if (compare_field (gypsy->position_fields, gypsy->latitude, + fields, latitude, GYPSY_POSITION_FIELDS_LATITUDE)) { + if (fields | GYPSY_POSITION_FIELDS_LATITUDE) { + gypsy->position_fields |= GYPSY_POSITION_FIELDS_LATITUDE; + gypsy->latitude = latitude; + changed = TRUE; + } + } + + if (compare_field (gypsy->position_fields, gypsy->longitude, + fields, longitude, GYPSY_POSITION_FIELDS_LONGITUDE)) { + if (fields | GYPSY_POSITION_FIELDS_LONGITUDE) { + gypsy->position_fields |= GYPSY_POSITION_FIELDS_LONGITUDE; + gypsy->longitude = longitude; + changed = TRUE; + } + } + + if (compare_field (gypsy->position_fields, gypsy->altitude, + fields, altitude, GYPSY_POSITION_FIELDS_ALTITUDE)) { + if (fields | GYPSY_POSITION_FIELDS_ALTITUDE) { + gypsy->position_fields |= GYPSY_POSITION_FIELDS_ALTITUDE; + gypsy->altitude = altitude; + changed = TRUE; + } + } + + if (changed) { + GeocluePositionFields fields; + + g_print ("Emitting signal\n"); + fields = gypsy_position_to_geoclue (gypsy->position_fields); + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (gypsy), fields, + timestamp, gypsy->latitude, gypsy->longitude, + gypsy->altitude, gypsy->accuracy); + } +} + +static void +course_changed (GypsyCourse *course, + GypsyCourseFields fields, + int timestamp, + double speed, + double direction, + double climb, + GeoclueGypsy *gypsy) +{ + gboolean changed = FALSE; + + gypsy->timestamp = timestamp; + if (compare_field (gypsy->course_fields, gypsy->speed, + fields, speed, GYPSY_COURSE_FIELDS_SPEED)) { + if (fields & GYPSY_COURSE_FIELDS_SPEED) { + gypsy->course_fields |= GYPSY_COURSE_FIELDS_SPEED; + gypsy->speed = speed; + changed = TRUE; + } + } + + if (compare_field (gypsy->course_fields, gypsy->direction, + fields, direction, GYPSY_COURSE_FIELDS_DIRECTION)) { + if (fields & GYPSY_COURSE_FIELDS_DIRECTION) { + gypsy->course_fields |= GYPSY_COURSE_FIELDS_DIRECTION; + gypsy->direction = direction; + changed = TRUE; + } + } + + if (compare_field (gypsy->course_fields, gypsy->climb, + fields, climb, GYPSY_COURSE_FIELDS_CLIMB)) { + if (fields & GYPSY_COURSE_FIELDS_CLIMB) { + gypsy->course_fields |= GYPSY_COURSE_FIELDS_CLIMB; + gypsy->climb = climb; + changed = TRUE; + } + } + + if (changed) { + GeoclueVelocityFields fields; + + fields = gypsy_course_to_geoclue (gypsy->course_fields); + gc_iface_velocity_emit_velocity_changed + (GC_IFACE_VELOCITY (gypsy), fields, + timestamp, gypsy->speed, gypsy->direction, gypsy->climb); + } +} + +static void +accuracy_changed (GypsyAccuracy *accuracy, + GypsyAccuracyFields fields, + double pdop, + double hdop, + double vdop, + GeoclueGypsy *gypsy) +{ + gboolean changed = FALSE; + GeoclueAccuracyLevel level; + double horiz, vert; + + geoclue_accuracy_get_details (gypsy->accuracy, &level, &horiz, &vert); + if (fields & (GYPSY_ACCURACY_FIELDS_HORIZONTAL | + GYPSY_ACCURACY_FIELDS_VERTICAL)){ + if (level != GEOCLUE_ACCURACY_LEVEL_DETAILED || + horiz != hdop || vert != vdop) { + changed = TRUE; + } + + geoclue_accuracy_set_details (gypsy->accuracy, + GEOCLUE_ACCURACY_LEVEL_DETAILED, + hdop, vdop); + } else { + + if (level != GEOCLUE_ACCURACY_LEVEL_NONE || + horiz != 0.0 || vert != 0.0) { + changed = TRUE; + } + + geoclue_accuracy_set_details (gypsy->accuracy, + GEOCLUE_ACCURACY_LEVEL_NONE, + 0.0, 0.0); + } + + if (changed) { + GeocluePositionFields fields; + + fields = gypsy_position_to_geoclue (gypsy->position_fields); + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (gypsy), fields, + gypsy->timestamp, gypsy->latitude, gypsy->longitude, + gypsy->altitude, gypsy->accuracy); + } +} + +static void +connection_changed (GypsyDevice *device, + gboolean connected, + GeoclueGypsy *gypsy) +{ + if (connected == FALSE && + gypsy->status != GEOCLUE_STATUS_UNAVAILABLE) { + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (gypsy), + gypsy->status); + } +} + +static void +fix_status_changed (GypsyDevice *device, + GypsyDeviceFixStatus status, + GeoclueGypsy *gypsy) +{ + gboolean changed = FALSE; + + switch (status) { + case GYPSY_DEVICE_FIX_STATUS_INVALID: + if (gypsy->status != GEOCLUE_STATUS_UNAVAILABLE) { + changed = TRUE; + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + } + break; + + case GYPSY_DEVICE_FIX_STATUS_NONE: + if (gypsy->status != GEOCLUE_STATUS_ACQUIRING) { + changed = TRUE; + gypsy->status = GEOCLUE_STATUS_ACQUIRING; + } + break; + + case GYPSY_DEVICE_FIX_STATUS_2D: + case GYPSY_DEVICE_FIX_STATUS_3D: + if (gypsy->status != GEOCLUE_STATUS_AVAILABLE) { + changed = TRUE; + gypsy->status = GEOCLUE_STATUS_AVAILABLE; + } + break; + } + + if (changed) { + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (gypsy), + gypsy->status); + } +} + +static void +get_initial_status (GeoclueGypsy *gypsy) +{ + gboolean connected; + GypsyDeviceFixStatus status; + GError *error = NULL; + + connected = gypsy_device_get_connection_status (gypsy->device, &error); + if (connected == FALSE) { + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + g_print ("Initial status - %d (disconnected)\n", gypsy->status); + return; + } + + status = gypsy_device_get_fix_status (gypsy->device, &error); + switch (status) { + case GYPSY_DEVICE_FIX_STATUS_INVALID: + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + break; + + case GYPSY_DEVICE_FIX_STATUS_NONE: + gypsy->status = GEOCLUE_STATUS_ACQUIRING; + break; + + case GYPSY_DEVICE_FIX_STATUS_2D: + case GYPSY_DEVICE_FIX_STATUS_3D: + gypsy->status = GEOCLUE_STATUS_AVAILABLE; + break; + } + + g_print ("Initial status - %d (connected)\n", gypsy->status); +} + +static gboolean +set_options (GcIfaceGeoclue *gc, + GHashTable *options, + GError **error) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc); + GValue *device_value, *baud_rate_value; + const char *device_name; + char *path; + int baud_rate; + + device_value = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSDevice"); + device_name = device_value ? g_value_get_string (device_value) : NULL; + baud_rate_value = g_hash_table_lookup (options, + "org.freedesktop.Geoclue.GPSBaudRate"); + baud_rate = baud_rate_value ? g_value_get_int (baud_rate_value) : 0; + + if (g_strcmp0 (gypsy->device_name, device_name) == 0 && + gypsy->baud_rate == baud_rate) + return TRUE; + + /* Disconnect from the old device, if any */ + if (gypsy->device != NULL) { + g_object_unref (gypsy->device); + gypsy->device = NULL; + } + + g_free (gypsy->device_name); + gypsy->device_name = NULL; + + if (device_name == NULL || *device_name == '\0') { + return TRUE; + } + + gypsy->device_name = g_strdup (device_name); + gypsy->baud_rate = baud_rate; + g_print ("Gypsy provider using '%s' at %d bps\n", gypsy->device_name, gypsy->baud_rate); + path = gypsy_control_create (gypsy->control, gypsy->device_name, + error); + if (*error != NULL) { + g_print ("Error - %s?\n", (*error)->message); + gypsy->status = GEOCLUE_STATUS_ERROR; + return FALSE; + } + + /* If we've got here, then we are out of the ERROR condition */ + gypsy->status = GEOCLUE_STATUS_UNAVAILABLE; + + gypsy->device = gypsy_device_new (path); + g_signal_connect (gypsy->device, "connection-changed", + G_CALLBACK (connection_changed), gypsy); + g_signal_connect (gypsy->device, "fix-status-changed", + G_CALLBACK (fix_status_changed), gypsy); + + gypsy->position = gypsy_position_new (path); + g_signal_connect (gypsy->position, "position-changed", + G_CALLBACK (position_changed), gypsy); + gypsy->course = gypsy_course_new (path); + g_signal_connect (gypsy->course, "course-changed", + G_CALLBACK (course_changed), gypsy); + gypsy->acc = gypsy_accuracy_new (path); + g_signal_connect (gypsy->acc, "accuracy-changed", + G_CALLBACK (accuracy_changed), gypsy); + + g_debug ("starting device"); + if (gypsy->baud_rate != 0) { + GHashTable *goptions; + GValue speed_val = { 0, }; + GError *err = NULL; + + g_value_init (&speed_val, G_TYPE_UINT); + g_value_set_uint (&speed_val, gypsy->baud_rate); + goptions = g_hash_table_new (g_str_hash, + g_str_equal); + g_hash_table_insert (goptions, "BaudRate", &speed_val); + if (!gypsy_device_set_start_options (gypsy->device, + goptions, + &err)) { + g_warning ("Error: %s", err->message); + g_error_free (err); + } + g_hash_table_destroy (goptions); + } + gypsy_device_start (gypsy->device, error); + if (*error != NULL) { + g_print ("Error - %s?\n", (*error)->message); + gypsy->status = GEOCLUE_STATUS_ERROR; + g_free (path); + return FALSE; + } + get_initial_status (gypsy); + g_free (path); + + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (provider); + + g_main_loop_quit (gypsy->loop); +} + +static void +finalize (GObject *object) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (object); + + geoclue_accuracy_free (gypsy->accuracy); + g_free (gypsy->device_name); + + ((GObjectClass *) geoclue_gypsy_parent_class)->finalize (object); +} + +static void +dispose (GObject *object) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (object); + + if (gypsy->control) { + g_object_unref (gypsy->control); + gypsy->control = NULL; + } + + if (gypsy->device) { + g_object_unref (gypsy->device); + gypsy->device = NULL; + } + + if (gypsy->position) { + g_object_unref (gypsy->position); + gypsy->position = NULL; + } + + ((GObjectClass *) geoclue_gypsy_parent_class)->dispose (object); +} + +static void +geoclue_gypsy_class_init (GeoclueGypsyClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + GcProviderClass *p_class = (GcProviderClass *) klass; + + o_class->finalize = finalize; + o_class->dispose = dispose; + + p_class->get_status = get_status; + p_class->set_options = set_options; + p_class->shutdown = shutdown; +} + +static void +geoclue_gypsy_init (GeoclueGypsy *gypsy) +{ + gypsy->status = GEOCLUE_STATUS_ERROR; + gypsy->control = gypsy_control_get_default (); + + gc_provider_set_details (GC_PROVIDER (gypsy), + "org.freedesktop.Geoclue.Providers.Gypsy", + "/org/freedesktop/Geoclue/Providers/Gypsy", + "Gypsy", "Gypsy provider"); + + gypsy->position_fields = GYPSY_POSITION_FIELDS_NONE; + + gypsy->accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, + 0.0, 0.0); +} + +static gboolean +get_position (GcIfacePosition *gc, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueGypsy *gypsy = GEOCLUE_GYPSY (gc); + GeoclueAccuracyLevel level; + double horizontal, vertical; + + *timestamp = gypsy->timestamp; + + *fields = GEOCLUE_POSITION_FIELDS_NONE; + if (gypsy->position_fields & GYPSY_POSITION_FIELDS_LATITUDE) { + *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + *latitude = gypsy->latitude; + } + if (gypsy->position_fields & GYPSY_POSITION_FIELDS_LONGITUDE) { + *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + *longitude = gypsy->longitude; + } + if (gypsy->position_fields & GYPSY_POSITION_FIELDS_ALTITUDE) { + *fields |= GEOCLUE_POSITION_FIELDS_ALTITUDE; + *altitude = gypsy->altitude; + } + + geoclue_accuracy_get_details (gypsy->accuracy, &level, + &horizontal, &vertical); + *accuracy = geoclue_accuracy_new (level, horizontal, vertical); + + return TRUE; +} + +static void +geoclue_gypsy_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = get_position; +} + +static gboolean +get_velocity (GcIfaceVelocity *gc, + GeoclueVelocityFields *fields, + int *timestamp, + double *speed, + double *direction, + double *climb, + GError **error) +{ + return TRUE; +} + +static void +geoclue_gypsy_velocity_init (GcIfaceVelocityClass *iface) +{ + iface->get_velocity = get_velocity; +} + +int +main (int argc, + char **argv) +{ + GeoclueGypsy *gypsy; + + g_type_init (); + + gypsy = g_object_new (GEOCLUE_TYPE_GYPSY, NULL); + + gypsy->loop = g_main_loop_new (NULL, TRUE); + g_main_loop_run (gypsy->loop); + + /* Unref the object so that gypsy-daemon knows we've shutdown */ + g_object_unref (gypsy); + return 0; +} diff --git a/.pc/tizen.patch/providers/hostip/Makefile.am b/.pc/tizen.patch/providers/hostip/Makefile.am new file mode 100755 index 0000000..1131187 --- /dev/null +++ b/.pc/tizen.patch/providers/hostip/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-hostip + +NOINST_H_FILES = \ + geoclue-hostip.h + +geoclue_hostip_SOURCES = \ + $(NOINST_H_FILES) \ + geoclue-hostip.c + +geoclue_hostip_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_hostip_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-hostip.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Hostip.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/localnet/Makefile.am b/.pc/tizen.patch/providers/localnet/Makefile.am new file mode 100755 index 0000000..382f1b2 --- /dev/null +++ b/.pc/tizen.patch/providers/localnet/Makefile.am @@ -0,0 +1,56 @@ +libexec_PROGRAMS = geoclue-localnet + +noinst_DATA = \ + geoclue-localnet.xml + +nodist_geoclue_localnet_SOURCES = \ + geoclue-localnet-glue.h + +BUILT_SOURCES = \ + $(nodist_geoclue_localnet_SOURCES) + +geoclue_localnet_SOURCES = \ + geoclue-localnet.c + +geoclue_localnet_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + $(GEOCLUE_CFLAGS) + +geoclue_localnet_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/src/libconnectivity.la \ + $(top_builddir)/geoclue/libgeoclue.la + + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-localnet.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Localnet.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +CLEANFILES = \ + stamp-geoclue-localnet-glue.h + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) \ + $(noinst_DATA) + +DISTCLEANFILES = \ + $(service_DATA) \ + $(nodist_geoclue_localnet_SOURCES) + +%-glue.h: stamp-%-glue.h + @true + +stamp-geoclue-localnet-glue.h: geoclue-localnet.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=geoclue_localnet --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) diff --git a/.pc/tizen.patch/providers/localnet/geoclue-localnet.c b/.pc/tizen.patch/providers/localnet/geoclue-localnet.c new file mode 100755 index 0000000..b834b75 --- /dev/null +++ b/.pc/tizen.patch/providers/localnet/geoclue-localnet.c @@ -0,0 +1,512 @@ +/** + * + * Expects to find a keyfile in user config dir + * (~/.config/geoclue-localnet-gateways). + * + * The keyfile should contain entries like this: + * + * [00:1D:7E:55:8D:80] + * country=Finland + * street=Solnantie 24 + * locality=Helsinki + * + * Only address interface is supported so far. + * + * Any application that can obtain a reliable address can submit it + * to localnet provider through the D-Bus API -- it will then be provided + * whenever connected to the same router: + * org.freedesktop.Geoclue.Localnet.SetAddress + * org.freedesktop.Geoclue.Localnet.SetAddressFields + * + * SetAddress allows setting the current address as a GeoclueAddress, + * while SetAddressFields is a convenience version with separate + * address fields. Shell example using SetAddressFields: + * + dbus-send --print-reply --type=method_call \ + --dest=org.freedesktop.Geoclue.Providers.Localnet \ + /org/freedesktop/Geoclue/Providers/Localnet \ + org.freedesktop.Geoclue.Localnet.SetAddressFields \ + string: \ + string:"Finland" \ + string: \ + string:"Helsinki" \ + string: \ + string: \ + string:"Solnantie 24" + + * This would make the provider save the specified address with current + * router mac address. It will provide the address to clients whenever + * the computer is connected to the same router again. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <dbus/dbus-glib-bindings.h> +#include <dbus/dbus.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-address.h> + +#include "connectivity.h" + +#define KEYFILE_NAME "geoclue-localnet-gateways" + +typedef struct { + char *mac; + GHashTable *address; + GeoclueAccuracy *accuracy; +} Gateway; + + +typedef struct { + GcProvider parent; + + GMainLoop *loop; + GeoclueConnectivity *conn; + + char *keyfile_name; + GSList *gateways; +} GeoclueLocalnet; + +typedef struct { + GcProviderClass parent_class; +} GeoclueLocalnetClass; + +#define GEOCLUE_TYPE_LOCALNET (geoclue_localnet_get_type ()) +#define GEOCLUE_LOCALNET(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_LOCALNET, GeoclueLocalnet)) + +static void geoclue_localnet_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueLocalnet, geoclue_localnet, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + geoclue_localnet_address_init)) + +static gboolean geoclue_localnet_set_address (GeoclueLocalnet *localnet, GHashTable *address, GError **error); +static gboolean geoclue_localnet_set_address_fields (GeoclueLocalnet *localnet, char *country_code, char *country, char *region, char *locality, char *area, char *postalcode, char *street, GError **error); +#include "geoclue-localnet-glue.h" + + +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + *status = GEOCLUE_STATUS_AVAILABLE; + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueLocalnet *localnet; + + localnet = GEOCLUE_LOCALNET (provider); + g_main_loop_quit (localnet->loop); +} + +static void +free_gateway_list (GSList *gateways) +{ + GSList *l; + + l = gateways; + while (l) { + Gateway *gw; + + gw = l->data; + g_free (gw->mac); + g_hash_table_destroy (gw->address); + geoclue_accuracy_free (gw->accuracy); + g_free (gw); + + l = l->next; + } + g_slist_free (gateways); +} + +static void +finalize (GObject *object) +{ + GeoclueLocalnet *localnet; + + localnet = GEOCLUE_LOCALNET (object); + + if (localnet->conn != NULL) { + g_object_unref (localnet->conn); + localnet->conn = NULL; + } + g_free (localnet->keyfile_name); + free_gateway_list (localnet->gateways); + + G_OBJECT_CLASS (geoclue_localnet_parent_class)->finalize (object); +} + +static void +geoclue_localnet_class_init (GeoclueLocalnetClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *) klass; + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->finalize = finalize; + + p_class->get_status = get_status; + p_class->shutdown = shutdown; + + dbus_g_object_type_install_info (geoclue_localnet_get_type (), + &dbus_glib_geoclue_localnet_object_info); + +} + +static void +geoclue_localnet_load_gateways_from_keyfile (GeoclueLocalnet *localnet, + GKeyFile *keyfile) +{ + char **groups; + char **g; + GError *error = NULL; + + groups = g_key_file_get_groups (keyfile, NULL); + g = groups; + while (*g) { + GeoclueAccuracyLevel level; + char **keys; + char **k; + Gateway *gateway = g_new0 (Gateway, 1); + + gateway->mac = g_ascii_strdown (*g, -1); + gateway->address = geoclue_address_details_new (); + + /* read all keys in the group as address fields */ + keys = g_key_file_get_keys (keyfile, *g, + NULL, &error); + if (error) { + g_warning ("Could not load keys for group [%s] from %s: %s", + *g, localnet->keyfile_name, error->message); + g_error_free (error); + error = NULL; + } + + k = keys; + while (*k) { + char *value; + + value = g_key_file_get_string (keyfile, *g, *k, NULL); + g_hash_table_insert (gateway->address, + *k, value); + k++; + } + g_free (keys); + + level = geoclue_address_details_get_accuracy_level (gateway->address); + gateway->accuracy = geoclue_accuracy_new (level, 0, 0); + + localnet->gateways = g_slist_prepend (localnet->gateways, gateway); + + g++; + } + g_strfreev (groups); +} + +static Gateway * +geoclue_localnet_find_gateway (GeoclueLocalnet *localnet, char *mac) +{ + GSList *l; + + l = localnet->gateways; + /* eww, should be using a hashtable or something here */ + while (l) { + Gateway *gw = l->data; + + if (g_ascii_strcasecmp (gw->mac, mac) == 0) { + return gw; + } + + l = l->next; + } + + return NULL; +} + +static void +geoclue_localnet_init (GeoclueLocalnet *localnet) +{ + const char *dir; + GKeyFile *keyfile; + GError *error = NULL; + + gc_provider_set_details (GC_PROVIDER (localnet), + "org.freedesktop.Geoclue.Providers.Localnet", + "/org/freedesktop/Geoclue/Providers/Localnet", + "Localnet", "provides Address based on current gateway mac address and a local address file (which can be updated through D-Bus)"); + + + localnet->gateways = NULL; + + /* load known addresses from keyfile */ + dir = g_get_user_config_dir (); + g_mkdir_with_parents (dir, 0755); + localnet->keyfile_name = g_build_filename (dir, KEYFILE_NAME, NULL); + + keyfile = g_key_file_new (); + if (!g_key_file_load_from_file (keyfile, localnet->keyfile_name, + G_KEY_FILE_NONE, &error)) { + g_warning ("Could not load keyfile %s: %s", + localnet->keyfile_name, error->message); + g_error_free (error); + } + geoclue_localnet_load_gateways_from_keyfile (localnet, keyfile); + g_key_file_free (keyfile); + + localnet->conn = geoclue_connectivity_new (); +} + +typedef struct { + GKeyFile *keyfile; + char *group_name; +} localnet_keyfile_group; + +static void +add_address_detail_to_keyfile (char *key, char *value, + localnet_keyfile_group *group) +{ + g_key_file_set_string (group->keyfile, group->group_name, + key, value); +} + +static gboolean +geoclue_localnet_set_address (GeoclueLocalnet *localnet, + GHashTable *details, + GError **error) +{ + char *str, *mac; + GKeyFile *keyfile; + GError *int_err = NULL; + localnet_keyfile_group *keyfile_group; + Gateway *gw; + + if (!details) { + /* TODO set error */ + return FALSE; + } + + mac = geoclue_connectivity_get_router_mac (localnet->conn); + if (!mac) { + g_warning ("Couldn't get current gateway mac address"); + /* TODO set error */ + return FALSE; + } + /* reload keyfile just in case it's changed */ + keyfile = g_key_file_new (); + if (!g_key_file_load_from_file (keyfile, localnet->keyfile_name, + G_KEY_FILE_NONE, &int_err)) { + g_warning ("Could not load keyfile %s: %s", + localnet->keyfile_name, int_err->message); + g_error_free (int_err); + int_err = NULL; + } + + /* remove old group (if exists) and add new to GKeyFile */ + g_key_file_remove_group (keyfile, mac, NULL); + + keyfile_group = g_new0 (localnet_keyfile_group, 1); + keyfile_group->keyfile = keyfile; + keyfile_group->group_name = mac; + g_hash_table_foreach (details, (GHFunc) add_address_detail_to_keyfile, keyfile_group); + g_free (keyfile_group); + + /* save keyfile*/ + str = g_key_file_to_data (keyfile, NULL, &int_err); + if (int_err) { + g_warning ("Failed to get keyfile data as string: %s", int_err->message); + g_error_free (int_err); + g_key_file_free (keyfile); + g_free (mac); + /* TODO set error */ + return FALSE; + } + + g_file_set_contents (localnet->keyfile_name, str, -1, &int_err); + g_free (str); + if (int_err) { + g_warning ("Failed to save keyfile: %s", int_err->message); + g_error_free (int_err); + g_key_file_free (keyfile); + g_free (mac); + /* TODO set error */ + return FALSE; + } + + /* re-parse keyfile */ + free_gateway_list (localnet->gateways); + localnet->gateways = NULL; + geoclue_localnet_load_gateways_from_keyfile (localnet, keyfile); + g_key_file_free (keyfile); + + gw = geoclue_localnet_find_gateway (localnet, mac); + g_free (mac); + + if (gw) { + gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (localnet), + time (NULL), gw->address, gw->accuracy); + } else { + /* empty address -- should emit anyway? */ + } + return TRUE; +} + +static gboolean +geoclue_localnet_set_address_fields (GeoclueLocalnet *localnet, + char *country_code, + char *country, + char *region, + char *locality, + char *area, + char *postalcode, + char *street, + GError **error) +{ + GHashTable *address; + gboolean ret; + + address = geoclue_address_details_new (); + if (country_code && (strlen (country_code) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRYCODE), + g_strdup (country_code)); + if (!country) { + geoclue_address_details_set_country_from_code (address); + } + } + if (country && (strlen (country) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRY), + g_strdup (country)); + } + if (region && (strlen (region) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_REGION), + g_strdup (region)); + } + if (locality && (strlen (locality) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_LOCALITY), + g_strdup (locality)); + } + if (area && (strlen (area) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_AREA), + g_strdup (area)); + } + if (postalcode && (strlen (postalcode) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_POSTALCODE), + g_strdup (postalcode)); + } + if (street && (strlen (street) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_STREET), + g_strdup (street)); + } + + ret = geoclue_localnet_set_address (localnet, + address, + error); + g_hash_table_destroy (address); + return ret; +} + +static gboolean +get_address (GcIfaceAddress *gc, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueLocalnet *localnet; + char *mac; + Gateway *gw; + + localnet = GEOCLUE_LOCALNET (gc); + + /* we may be trying to read /proc/net/arp right after network connection. + * It's sometimes not up yet, try a couple of times */ + mac = geoclue_connectivity_get_router_mac (localnet->conn); + + if (!mac) { + g_warning ("Couldn't get current gateway mac address"); + if (error) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, "Could not get current gateway mac address"); + } + return FALSE; + } + + gw = geoclue_localnet_find_gateway (localnet, mac); + g_free (mac); + + if (timestamp) { + *timestamp = time(NULL); + } + if (address) { + if (gw) { + *address = geoclue_address_details_copy (gw->address); + } else { + *address = geoclue_address_details_new (); + } + } + if (accuracy) { + if (gw) { + *accuracy = geoclue_accuracy_copy (gw->accuracy); + } else { + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); + } + } + return TRUE; +} + +static void +geoclue_localnet_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = get_address; +} + +int +main (int argc, + char **argv) +{ + GeoclueLocalnet *localnet; + + g_type_init (); + + localnet = g_object_new (GEOCLUE_TYPE_LOCALNET, NULL); + localnet->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (localnet->loop); + + g_main_loop_unref (localnet->loop); + g_object_unref (localnet); + + return 0; +} diff --git a/.pc/tizen.patch/providers/manual/Makefile.am b/.pc/tizen.patch/providers/manual/Makefile.am new file mode 100755 index 0000000..231e042 --- /dev/null +++ b/.pc/tizen.patch/providers/manual/Makefile.am @@ -0,0 +1,54 @@ +libexec_PROGRAMS = geoclue-manual + +noinst_DATA = \ + geoclue-manual.xml + +nodist_geoclue_manual_SOURCES = \ + geoclue-manual-glue.h + +BUILT_SOURCES = \ + $(nodist_geoclue_manual_SOURCES) + +geoclue_manual_SOURCES = \ + geoclue-manual.c + +geoclue_manual_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_manual_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-manual.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Manual.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +CLEANFILES = \ + stamp-geoclue-manual-glue.h + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) \ + $(noinst_DATA) + +DISTCLEANFILES = \ + $(service_DATA) \ + $(nodist_geoclue_manual_SOURCES) + +%-glue.h: stamp-%-glue.h + @true + +stamp-geoclue-manual-glue.h: geoclue-manual.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=geoclue_manual --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) diff --git a/.pc/tizen.patch/providers/manual/geoclue-manual.c b/.pc/tizen.patch/providers/manual/geoclue-manual.c new file mode 100755 index 0000000..2b6620a --- /dev/null +++ b/.pc/tizen.patch/providers/manual/geoclue-manual.c @@ -0,0 +1,365 @@ +/* + * Geoclue + * geoclue-manual.c - Manual address provider + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2008 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** Geoclue manual provider + * + * This is an address provider which gets its address data from user + * input. No UI is included, any application may query the address from + * the user and submit it to manual provider through the D-Bus API: + * org.freedesktop.Geoclue.Manual.SetAddress + * org.freedesktop.Geoclue.Manual.SetAddressFields + * + * SetAddress allows setting the current address as a GeoclueAddress, + * while SetAddressFields is a convenience version with separate + * address fields. Shell example using SetAddressFields: + * + * dbus-send --print-reply --type=method_call \ + * --dest=org.freedesktop.Geoclue.Providers.Manual \ + * /org/freedesktop/Geoclue/Providers/Manual \ + * org.freedesktop.Geoclue.Manual.SetAddressFields \ + * int32:7200 \ + * string: \ + * string:"Finland" \ + * string: \ + * string:"Helsinki" \ + * string: \ + * string: \ + * string:"Solnantie 24" + * + * This would make the provider emit a AddressChanged signal with + * accuracy level GEOCLUE_ACCURACY_STREET. Unless new SetAddress* calls + * are made, provider will emit another signal in two hours (7200 sec), + * with empty address and GEOCLUE_ACCURACY_NONE. + **/ + +#include <config.h> +#include <string.h> +#include <dbus/dbus-glib-bindings.h> +#include <dbus/dbus.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-address.h> + +typedef struct { + GcProvider parent; + + GMainLoop *loop; + + guint event_id; + + int timestamp; + GHashTable *address; + GeoclueAccuracy *accuracy; +} GeoclueManual; + +typedef struct { + GcProviderClass parent_class; +} GeoclueManualClass; + +#define GEOCLUE_TYPE_MANUAL (geoclue_manual_get_type ()) +#define GEOCLUE_MANUAL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_MANUAL, GeoclueManual)) + +static void geoclue_manual_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueManual, geoclue_manual, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + geoclue_manual_address_init)) + +static gboolean +geoclue_manual_set_address (GeoclueManual *manual, + int valid_until, + GHashTable *address, + GError **error); + +static gboolean +geoclue_manual_set_address_fields (GeoclueManual *manual, + int valid_until, + char *country_code, + char *country, + char *region, + char *locality, + char *area, + char *postalcode, + char *street, + GError **error); + +#include "geoclue-manual-glue.h" + + +static GeoclueAccuracyLevel +get_accuracy_for_address (GHashTable *address) +{ + if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_STREET)) { + return GEOCLUE_ACCURACY_LEVEL_STREET; + } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_POSTALCODE)) { + return GEOCLUE_ACCURACY_LEVEL_POSTALCODE; + } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_LOCALITY)) { + return GEOCLUE_ACCURACY_LEVEL_LOCALITY; + } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_REGION)) { + return GEOCLUE_ACCURACY_LEVEL_REGION; + } else if (g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRY) || + g_hash_table_lookup (address, GEOCLUE_ADDRESS_KEY_COUNTRYCODE)) { + return GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } + return GEOCLUE_ACCURACY_LEVEL_NONE; +} + +static gboolean +get_status (GcIfaceGeoclue *gc, + GeoclueStatus *status, + GError **error) +{ + GeoclueAccuracyLevel level; + + geoclue_accuracy_get_details (GEOCLUE_MANUAL (gc)->accuracy, + &level, NULL, NULL); + if (level == GEOCLUE_ACCURACY_LEVEL_NONE) { + *status = GEOCLUE_STATUS_UNAVAILABLE; + } else { + *status = GEOCLUE_STATUS_AVAILABLE; + } + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeoclueManual *manual; + + manual = GEOCLUE_MANUAL (provider); + g_main_loop_quit (manual->loop); +} + +gboolean +validity_ended (GeoclueManual *manual) +{ + manual->event_id = 0; + g_hash_table_remove_all (manual->address); + geoclue_accuracy_set_details (manual->accuracy, + GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); + + gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (manual), + manual->timestamp, + manual->address, + manual->accuracy); + return FALSE; +} + + +static void +geoclue_manual_set_address_common (GeoclueManual *manual, + int valid_for, + GHashTable *address) +{ + if (manual->event_id > 0) { + g_source_remove (manual->event_id); + } + + manual->timestamp = time (NULL); + + g_hash_table_destroy (manual->address); + manual->address = address; + + geoclue_accuracy_set_details (manual->accuracy, + get_accuracy_for_address (address), + 0, 0); + + gc_iface_address_emit_address_changed (GC_IFACE_ADDRESS (manual), + manual->timestamp, + manual->address, + manual->accuracy); + + if (valid_for > 0) { + manual->event_id = g_timeout_add (valid_for * 1000, + (GSourceFunc)validity_ended, + manual); + } +} + +static gboolean +geoclue_manual_set_address (GeoclueManual *manual, + int valid_for, + GHashTable *address, + GError **error) +{ + geoclue_manual_set_address_common (manual, + valid_for, + geoclue_address_details_copy (address)); + return TRUE; +} + +static gboolean +geoclue_manual_set_address_fields (GeoclueManual *manual, + int valid_for, + char *country_code, + char *country, + char *region, + char *locality, + char *area, + char *postalcode, + char *street, + GError **error) +{ + GHashTable *address; + + address = geoclue_address_details_new (); + if (country_code && (strlen (country_code) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRYCODE), + g_strdup (country_code)); + } + if (country && (strlen (country) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_COUNTRY), + g_strdup (country)); + } + if (region && (strlen (region) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_REGION), + g_strdup (region)); + } + if (locality && (strlen (locality) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_LOCALITY), + g_strdup (locality)); + } + if (area && (strlen (area) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_AREA), + g_strdup (area)); + } + if (postalcode && (strlen (postalcode) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_POSTALCODE), + g_strdup (postalcode)); + } + if (street && (strlen (street) > 0)) { + g_hash_table_insert (address, + g_strdup (GEOCLUE_ADDRESS_KEY_STREET), + g_strdup (street)); + } + + geoclue_manual_set_address_common (manual, + valid_for, + address); + return TRUE; +} + + +static void +finalize (GObject *object) +{ + GeoclueManual *manual; + + manual = GEOCLUE_MANUAL (object); + + g_hash_table_destroy (manual->address); + geoclue_accuracy_free (manual->accuracy); + + ((GObjectClass *) geoclue_manual_parent_class)->finalize (object); +} + +static void +geoclue_manual_class_init (GeoclueManualClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + GcProviderClass *p_class = (GcProviderClass *) klass; + + o_class->finalize = finalize; + + p_class->get_status = get_status; + p_class->shutdown = shutdown; + + dbus_g_object_type_install_info (geoclue_manual_get_type (), + &dbus_glib_geoclue_manual_object_info); +} + +static void +geoclue_manual_init (GeoclueManual *manual) +{ + gc_provider_set_details (GC_PROVIDER (manual), + "org.freedesktop.Geoclue.Providers.Manual", + "/org/freedesktop/Geoclue/Providers/Manual", + "Manual", "Manual provider"); + + manual->address = geoclue_address_details_new (); + manual->accuracy = + geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0, 0); +} + +static gboolean +get_address (GcIfaceAddress *gc, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueManual *manual = GEOCLUE_MANUAL (gc); + GeoclueAccuracyLevel level; + + geoclue_accuracy_get_details (manual->accuracy, &level, NULL, NULL); + if (level == GEOCLUE_ACCURACY_LEVEL_NONE) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "No manual address set"); + return FALSE; + } + + if (timestamp) { + *timestamp = manual->timestamp; + } + if (address) { + *address = geoclue_address_details_copy (manual->address); + } + if (accuracy) { + *accuracy = geoclue_accuracy_copy (manual->accuracy); + } + + return TRUE; +} + +static void +geoclue_manual_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = get_address; +} + +int +main (int argc, + char **argv) +{ + GeoclueManual *manual; + + g_type_init (); + + manual = g_object_new (GEOCLUE_TYPE_MANUAL, NULL); + manual->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (manual->loop); + + g_main_loop_unref (manual->loop); + g_object_unref (manual); + + return 0; +} diff --git a/.pc/tizen.patch/providers/nominatim/Makefile.am b/.pc/tizen.patch/providers/nominatim/Makefile.am new file mode 100755 index 0000000..f723ac9 --- /dev/null +++ b/.pc/tizen.patch/providers/nominatim/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-nominatim + +NOINST_H_FILES = \ + geoclue-nominatim.h + +geoclue_nominatim_SOURCES = \ + $(NOINST_H_FILES) \ + geoclue-nominatim.c + +geoclue_nominatim_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_nominatim_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-nominatim.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Nominatim.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/plazes/Makefile.am b/.pc/tizen.patch/providers/plazes/Makefile.am new file mode 100755 index 0000000..dc9fb47 --- /dev/null +++ b/.pc/tizen.patch/providers/plazes/Makefile.am @@ -0,0 +1,33 @@ +libexec_PROGRAMS = \ + geoclue-plazes + +geoclue_plazes_SOURCES = \ + geoclue-plazes.c + +geoclue_plazes_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + $(GEOCLUE_CFLAGS) + +geoclue_plazes_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/src/libconnectivity.la \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-plazes.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Plazes.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/plazes/geoclue-plazes.c b/.pc/tizen.patch/providers/plazes/geoclue-plazes.c new file mode 100755 index 0000000..be44d90 --- /dev/null +++ b/.pc/tizen.patch/providers/plazes/geoclue-plazes.c @@ -0,0 +1,377 @@ +/* + * Geoclue + * geoclue-plazes.c - A plazes.com-based Address/Position provider + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2008 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <time.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <glib-object.h> +#include <dbus/dbus-glib-bindings.h> + +#include <geoclue/gc-web-service.h> +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-address.h> + +#include "connectivity.h" + +#define GEOCLUE_DBUS_SERVICE_PLAZES "org.freedesktop.Geoclue.Providers.Plazes" +#define GEOCLUE_DBUS_PATH_PLAZES "/org/freedesktop/Geoclue/Providers/Plazes" +#define PLAZES_URL "http://plazes.com/suggestions.xml" +#define PLAZES_KEY_MAC "mac_address" +#define PLAZES_LAT_XPATH "//plaze/latitude" +#define PLAZES_LON_XPATH "//plaze/longitude" + +#define GEOCLUE_TYPE_PLAZES (geoclue_plazes_get_type ()) +#define GEOCLUE_PLAZES(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_PLAZES, GeocluePlazes)) + +typedef struct _GeocluePlazes { + GcProvider parent; + GMainLoop *loop; + GeoclueConnectivity *conn; + GcWebService *web_service; + GeoclueStatus last_status; +} GeocluePlazes; + +typedef struct _GeocluePlazesClass { + GcProviderClass parent_class; +} GeocluePlazesClass; + + +static void geoclue_plazes_init (GeocluePlazes *plazes); +static void geoclue_plazes_position_init (GcIfacePositionClass *iface); +static void geoclue_plazes_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeocluePlazes, geoclue_plazes, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_plazes_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + geoclue_plazes_address_init)) + + +/* Geoclue interface implementation */ +static gboolean +geoclue_plazes_get_status (GcIfaceGeoclue *iface, + GeoclueStatus *status, + GError **error) +{ + GeocluePlazes *plazes = GEOCLUE_PLAZES (iface); + + *status = plazes->last_status; + return TRUE; +} + +static void +shutdown (GcProvider *provider) +{ + GeocluePlazes *plazes = GEOCLUE_PLAZES (provider); + g_main_loop_quit (plazes->loop); +} + +static void +geoclue_plazes_set_status (GeocluePlazes *self, GeoclueStatus status) +{ + if (status != self->last_status) { + self->last_status = status; + gc_iface_geoclue_emit_status_changed (GC_IFACE_GEOCLUE (self), status); + } +} + +static char * +mac_strdown (char *mac) +{ + guint i; + for (i = 0; mac[i] != '\0' ; i++) { + if (g_ascii_isalpha (mac[i])) + mac[i] = g_ascii_tolower (mac[i]); + } + return mac; +} +/* Position interface implementation */ + +static gboolean +geoclue_plazes_get_position (GcIfacePosition *iface, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeocluePlazes *plazes; + char *mac, *mac_lc; + + plazes = (GEOCLUE_PLAZES (iface)); + + *fields = GEOCLUE_POSITION_FIELDS_NONE; + if (timestamp) { + *timestamp = time (NULL); + } + + mac = geoclue_connectivity_get_router_mac (plazes->conn); + if (mac == NULL) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Router mac address query failed"); + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR); + return FALSE; + } + + mac = mac_strdown (mac); + + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ACQUIRING); + + mac_lc = g_ascii_strdown (mac, -1); + g_free (mac); + if (!gc_web_service_query (plazes->web_service, error, + PLAZES_KEY_MAC, mac, + (char *)0)) { + g_free (mac_lc); + // did not get a reply; we can try again later + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Did not get reply from server"); + return FALSE; + } + + g_free (mac); + + if (latitude && gc_web_service_get_double (plazes->web_service, + latitude, PLAZES_LAT_XPATH)) { + *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + } + if (longitude && gc_web_service_get_double (plazes->web_service, + longitude, PLAZES_LON_XPATH)) { + *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + } + + if (accuracy) { + /* Educated guess. Plazes are typically hand pointed on + * a map, or geocoded from address, so should be fairly + * accurate */ + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_STREET, 0, 0); + } + + if (!(*fields & GEOCLUE_POSITION_FIELDS_LATITUDE && + *fields & GEOCLUE_POSITION_FIELDS_LONGITUDE)) { + + // we got a reply, but could not exploit it. It would probably be the + // same next time. + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Could not understand reply from server"); + return FALSE; + } + + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE); + + return TRUE; +} + +/* Address interface implementation */ + +static gboolean +geoclue_plazes_get_address (GcIfaceAddress *iface, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + + GeocluePlazes *plazes = GEOCLUE_PLAZES (iface); + char *mac, *mac_lc; + + GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE; + + if (timestamp) { + *timestamp = time (NULL); + } + + mac = geoclue_connectivity_get_router_mac (plazes->conn); + + if (mac == NULL) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Router mac address query failed"); + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR); + return FALSE; + } + + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ACQUIRING); + + mac_lc = g_ascii_strdown (mac, -1); + g_free (mac); + if (!gc_web_service_query (plazes->web_service, error, + PLAZES_KEY_MAC, mac_lc, + (char *)0)) { + g_free (mac_lc); + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Did not get reply from server"); + return FALSE; + } + g_free (mac_lc); + + if (address) { + char *str; + + *address = geoclue_address_details_new (); + + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/country")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_COUNTRY, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/country_code")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_COUNTRYCODE, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/city")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_LOCALITY, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_LOCALITY; + } + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/zip_code")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_POSTALCODE, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE; + } + if (gc_web_service_get_string (plazes->web_service, + &str, "//plaze/address")) { + geoclue_address_details_insert (*address, + GEOCLUE_ADDRESS_KEY_STREET, + str); + g_free (str); + level = GEOCLUE_ACCURACY_LEVEL_STREET; + } + } + + if (level == GEOCLUE_ACCURACY_LEVEL_NONE) { + // we got a reply, but could not exploit it. It would probably be the + // same next time. + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_ERROR); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Could not understand reply from server"); + return FALSE; + } + + if (accuracy) { + *accuracy = geoclue_accuracy_new (level, 0, 0); + } + + return TRUE; +} + +static void +geoclue_plazes_finalize (GObject *obj) +{ + GeocluePlazes *plazes = GEOCLUE_PLAZES (obj); + + if (plazes->conn != NULL) { + g_object_unref (plazes->conn); + plazes->conn = NULL; + } + g_object_unref (plazes->web_service); + + ((GObjectClass *) geoclue_plazes_parent_class)->finalize (obj); +} + + +/* Initialization */ + +static void +geoclue_plazes_class_init (GeocluePlazesClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *)klass; + GObjectClass *o_class = (GObjectClass *)klass; + + p_class->shutdown = shutdown; + p_class->get_status = geoclue_plazes_get_status; + + o_class->finalize = geoclue_plazes_finalize; +} + +static void +geoclue_plazes_init (GeocluePlazes *plazes) +{ + gc_provider_set_details (GC_PROVIDER (plazes), + GEOCLUE_DBUS_SERVICE_PLAZES, + GEOCLUE_DBUS_PATH_PLAZES, + "Plazes", "Plazes.com based provider, uses gateway mac address to locate"); + + plazes->conn = geoclue_connectivity_new (); + plazes->web_service = g_object_new (GC_TYPE_WEB_SERVICE, NULL); + gc_web_service_set_base_url (plazes->web_service, PLAZES_URL); + geoclue_plazes_set_status (plazes, GEOCLUE_STATUS_AVAILABLE); +} + +static void +geoclue_plazes_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = geoclue_plazes_get_position; +} + +static void +geoclue_plazes_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = geoclue_plazes_get_address; +} + +int +main() +{ + g_type_init(); + + GeocluePlazes *o = g_object_new (GEOCLUE_TYPE_PLAZES, NULL); + o->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (o->loop); + + g_main_loop_unref (o->loop); + g_object_unref (o); + + return 0; +} diff --git a/.pc/tizen.patch/providers/skyhook/Makefile.am b/.pc/tizen.patch/providers/skyhook/Makefile.am new file mode 100755 index 0000000..a6e2107 --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/Makefile.am @@ -0,0 +1,35 @@ +libexec_PROGRAMS = \ + geoclue-skyhook + +geoclue_skyhook_SOURCES = \ + geoclue-skyhook.c + +geoclue_skyhook_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + -I$(top_srcdir)/src \ + $(GEOCLUE_CFLAGS) \ + $(SKYHOOK_CFLAGS) + +geoclue_skyhook_LDADD = \ + $(GEOCLUE_LIBS) \ + $(SKYHOOK_LIBS) \ + $(top_builddir)/src/libconnectivity.la \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-skyhook.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Skyhook.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c new file mode 100755 index 0000000..5af7b45 --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.c @@ -0,0 +1,303 @@ +/* + * Geoclue + * geoclue-skyhook.c - A skyhook.com-based Address/Position provider + * + * Author: Bastien Nocera <hadess@hadess.net> + * Copyright 2009 Bastien Nocera + */ + +#include <config.h> + +#include <time.h> +#include <string.h> +#include <errno.h> + +#include <glib-object.h> +#include <dbus/dbus-glib-bindings.h> +#include <libsoup/soup.h> +#include <libxml/xpathInternals.h> + +#include <geoclue/gc-web-service.h> +#include <geoclue/gc-provider.h> +#include <geoclue/geoclue-error.h> +#include <geoclue/gc-iface-position.h> + +#include "connectivity.h" + +#define GEOCLUE_DBUS_SERVICE_SKYHOOK "org.freedesktop.Geoclue.Providers.Skyhook" +#define GEOCLUE_DBUS_PATH_SKYHOOK "/org/freedesktop/Geoclue/Providers/Skyhook" +#define SKYHOOK_URL "https://api.skyhookwireless.com/wps2/location" +#define SKYHOOK_LAT_XPATH "//prefix:latitude" +#define SKYHOOK_LON_XPATH "//prefix:longitude" +#define USER_AGENT "Geoclue "VERSION + +#define GEOCLUE_TYPE_SKYHOOK (geoclue_skyhook_get_type ()) +#define GEOCLUE_SKYHOOK(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_SKYHOOK, GeoclueSkyhook)) + +#define QUERY_START "<?xml version=\'1.0\'?><LocationRQ xmlns=\'http://skyhookwireless.com/wps/2005\' version=\'2.6\' street-address-lookup=\'full\'><authentication version=\'2.0\'><simple><username>beta</username><realm>js.loki.com</realm></simple></authentication>" +#define QUERY_AP "<access-point><mac>%s</mac><signal-strength>%d</signal-strength></access-point>" +#define QUERY_END "</LocationRQ>" + +typedef struct _GeoclueSkyhook { + GcProvider parent; + GMainLoop *loop; + SoupSession *session; + GeoclueConnectivity *conn; +} GeoclueSkyhook; + +typedef struct _GeoclueSkyhookClass { + GcProviderClass parent_class; +} GeoclueSkyhookClass; + + +static void geoclue_skyhook_init (GeoclueSkyhook *skyhook); +static void geoclue_skyhook_position_init (GcIfacePositionClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueSkyhook, geoclue_skyhook, GC_TYPE_PROVIDER, + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + geoclue_skyhook_position_init)) + + +/* Geoclue interface implementation */ +static gboolean +geoclue_skyhook_get_status (GcIfaceGeoclue *iface, + GeoclueStatus *status, + GError **error) +{ + /* Assume available so long as all the requirements are satisfied + ie: Network is available */ + *status = GEOCLUE_STATUS_AVAILABLE; + return TRUE; +} + +static void +_shutdown (GcProvider *provider) +{ + GeoclueSkyhook *skyhook = GEOCLUE_SKYHOOK (provider); + g_main_loop_quit (skyhook->loop); +} + +static void +add_ap (gpointer key, + gpointer value, + gpointer data) +{ + char *mac; + char **split; + + /* Remove the ":" */ + split = g_strsplit (key, ":", -1); + mac = g_strjoinv ("", split); + g_strfreev (split); + + g_string_append_printf (data, QUERY_AP, mac, GPOINTER_TO_INT (value)); + g_free (mac); +} + +static char * +create_post_query (GeoclueConnectivity *conn) +{ + GHashTable *ht; + GString *str; + + ht = geoclue_connectivity_get_aps (conn); + if (ht == NULL) + return NULL; + str = g_string_new (QUERY_START); + g_hash_table_foreach (ht, add_ap, str); + g_string_append (str, QUERY_END); + g_hash_table_destroy (ht); + + return g_string_free (str, FALSE); +} + +static gboolean +get_double (xmlXPathContext *xpath_ctx, char *xpath, gdouble *value) +{ + xmlXPathObject *obj = NULL; + + obj = xmlXPathEvalExpression (BAD_CAST (xpath), xpath_ctx); + if (obj && + (!obj->nodesetval || xmlXPathNodeSetIsEmpty (obj->nodesetval))) { + xmlXPathFreeObject (obj); + return FALSE; + } + *value = xmlXPathCastNodeSetToNumber (obj->nodesetval); + xmlXPathFreeObject (obj); + return TRUE; +} + +static gboolean +parse_response (const char *body, gdouble *latitude, gdouble *longitude) +{ + xmlDocPtr doc; + xmlXPathContext *xpath_ctx; + gboolean ret = TRUE; + + doc = xmlParseDoc (BAD_CAST (body)); + if (!doc) + return FALSE; + + xpath_ctx = xmlXPathNewContext(doc); + if (!xpath_ctx) { + xmlFreeDoc (doc); + return FALSE; + } + xmlXPathRegisterNs (xpath_ctx, BAD_CAST ("prefix"), BAD_CAST("http://skyhookwireless.com/wps/2005")); + if (get_double (xpath_ctx, SKYHOOK_LAT_XPATH, latitude) == FALSE) { + ret = FALSE; + } else if (get_double (xpath_ctx, SKYHOOK_LON_XPATH, longitude) == FALSE) { + ret = FALSE; + } + xmlXPathFreeContext (xpath_ctx); + xmlFreeDoc (doc); + + return ret; +} + +/* Position interface implementation */ + +static gboolean +geoclue_skyhook_get_position (GcIfacePosition *iface, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GeoclueSkyhook *skyhook; + char *query; + SoupMessage *msg; + + skyhook = (GEOCLUE_SKYHOOK (iface)); + + *fields = GEOCLUE_POSITION_FIELDS_NONE; + if (timestamp) + *timestamp = time (NULL); + + query = create_post_query (skyhook->conn); + if (query == NULL) { + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Router mac address query failed"); + /* TODO: set status == error ? */ + return FALSE; + } + + msg = soup_message_new ("POST", SKYHOOK_URL); + soup_message_headers_append (msg->request_headers, "User-Agent", USER_AGENT); + soup_message_set_request (msg, + "text/xml", + SOUP_MEMORY_TAKE, + query, + strlen (query)); + soup_session_send_message (skyhook->session, msg); + if (msg->response_body == NULL || msg->response_body->data == NULL) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Failed to query web service"); + return FALSE; + } + + if (strstr (msg->response_body->data, "<error>") != NULL) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Web service returned an error"); + return FALSE; + } + + if (parse_response (msg->response_body->data, latitude, longitude) == FALSE) { + g_object_unref (msg); + g_set_error (error, GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Couldn't parse response from web service"); + return FALSE; + } + + if (latitude) + *fields |= GEOCLUE_POSITION_FIELDS_LATITUDE; + if (longitude) + *fields |= GEOCLUE_POSITION_FIELDS_LONGITUDE; + + if (accuracy) { + if (*fields == GEOCLUE_POSITION_FIELDS_NONE) { + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, + 0, 0); + } else { + /* Educated guess. Skyhook are typically hand pointed on + * a map, or geocoded from address, so should be fairly + * accurate */ + *accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_STREET, + 0, 0); + } + } + + return TRUE; +} + +static void +geoclue_skyhook_finalize (GObject *obj) +{ + GeoclueSkyhook *skyhook = GEOCLUE_SKYHOOK (obj); + + if (skyhook->conn != NULL) { + g_object_unref (skyhook->conn); + skyhook->conn = NULL; + } + g_object_unref (skyhook->session); + + ((GObjectClass *) geoclue_skyhook_parent_class)->finalize (obj); +} + + +/* Initialization */ + +static void +geoclue_skyhook_class_init (GeoclueSkyhookClass *klass) +{ + GcProviderClass *p_class = (GcProviderClass *)klass; + GObjectClass *o_class = (GObjectClass *)klass; + + p_class->shutdown = _shutdown; + p_class->get_status = geoclue_skyhook_get_status; + + o_class->finalize = geoclue_skyhook_finalize; +} + +static void +geoclue_skyhook_init (GeoclueSkyhook *skyhook) +{ + gc_provider_set_details (GC_PROVIDER (skyhook), + GEOCLUE_DBUS_SERVICE_SKYHOOK, + GEOCLUE_DBUS_PATH_SKYHOOK, + "Skyhook", "Skyhook.com based provider, uses gateway mac address to locate"); + skyhook->session = soup_session_sync_new (); + skyhook->conn = geoclue_connectivity_new (); +} + +static void +geoclue_skyhook_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = geoclue_skyhook_get_position; +} + +int +main() +{ + g_type_init(); + g_thread_init (NULL); + + GeoclueSkyhook *o = g_object_new (GEOCLUE_TYPE_SKYHOOK, NULL); + o->loop = g_main_loop_new (NULL, TRUE); + + g_main_loop_run (o->loop); + + g_main_loop_unref (o->loop); + g_object_unref (o); + + return 0; +} diff --git a/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider new file mode 100755 index 0000000..1e0fcde --- /dev/null +++ b/.pc/tizen.patch/providers/skyhook/geoclue-skyhook.provider @@ -0,0 +1,8 @@ +[Geoclue Provider] +Name=Skyhook +Service=org.freedesktop.Geoclue.Providers.Skyhook +Path=/org/freedesktop/Geoclue/Providers/Skyhook +Accuracy=Street +Requires=RequiresNetwork +Provides=ProvidesCacheableOnConnection +Interfaces=org.freedesktop.Geoclue.Position diff --git a/.pc/tizen.patch/providers/yahoo/Makefile.am b/.pc/tizen.patch/providers/yahoo/Makefile.am new file mode 100755 index 0000000..fee408b --- /dev/null +++ b/.pc/tizen.patch/providers/yahoo/Makefile.am @@ -0,0 +1,31 @@ +libexec_PROGRAMS = \ + geoclue-yahoo + +geoclue_yahoo_SOURCES = \ + geoclue-yahoo.c + +geoclue_yahoo_CFLAGS = \ + -I$(top_srcdir) \ + -I$(top_builddir) \ + $(GEOCLUE_CFLAGS) + +geoclue_yahoo_LDADD = \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +providersdir = $(datadir)/geoclue-providers +providers_DATA = geoclue-yahoo.provider + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Providers.Yahoo.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(providers_DATA) + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/src/Makefile.am b/.pc/tizen.patch/src/Makefile.am new file mode 100755 index 0000000..ebb5f22 --- /dev/null +++ b/.pc/tizen.patch/src/Makefile.am @@ -0,0 +1,90 @@ +libexec_PROGRAMS = geoclue-master +noinst_LTLIBRARIES = libconnectivity.la +noinst_PROGRAMS = test-connectivity + +AM_CFLAGS = \ + -I$(top_srcdir) \ + -I$(srcdir) \ + -I$(top_builddir) \ + -DGEOCLUE_PROVIDERS_DIR=\""$(datadir)/geoclue-providers"\" \ + $(GEOCLUE_CFLAGS) \ + $(MASTER_CFLAGS) \ + $(CONNECTIVITY_CFLAGS) + +geoclue_master_LDADD = \ + $(top_builddir)/geoclue/libgeoclue.la \ + libconnectivity.la \ + $(GEOCLUE_LIBS) \ + $(MASTER_LIBS) + +NOINST_H_FILES = \ + main.h \ + master.h \ + master-provider.h \ + client.h + +libconnectivity_la_SOURCES = \ + connectivity.h \ + connectivity-networkmanager.h \ + connectivity-conic.h \ + connectivity-connman.h \ + connectivity.c \ + connectivity-networkmanager.c \ + connectivity-conic.c \ + connectivity-connman.c + +libconnectivity_la_LIBADD = $(CONNECTIVITY_LIBS) + +test_connectivity_SOURCES = test-connectivity.c +test_connectivity_LDADD = libconnectivity.la $(GEOCLUE_LIBS) + +geoclue_master_SOURCES = \ + $(NOINST_H_FILES) \ + client.c \ + main.c \ + master.c \ + master-provider.c + +BUILT_SOURCES = \ + gc-iface-master-glue.h \ + gc-iface-master-client-glue.h + +%-glue.h: stamp-%-glue.h + @true +stamp-gc-iface-master-glue.h: ../interfaces/gc-iface-master.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=gc_iface_master --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +stamp-gc-iface-master-client-glue.h: ../interfaces/gc-iface-master-client.xml + $(AM_V_GEN) $(DBUS_BINDING_TOOL) --prefix=gc_iface_master_client --mode=glib-server $< > xgen-$(@F) \ + && (cmp -s xgen-$(@F) $(@F:stamp-%=%) || cp xgen-$(@F) $(@F:stamp-%=%)) \ + && rm -f xgen-$(@F) \ + && echo timestamp > $(@F) + +servicedir = $(DBUS_SERVICES_DIR) +service_in_files = org.freedesktop.Geoclue.Master.service.in +service_DATA = $(service_in_files:.service.in=.service) + +$(service_DATA): $(service_in_files) Makefile + $(AM_V_GEN) sed -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@ + +convertdir = $(datadir)/GConf/gsettings +convert_DATA = geoclue + +gsettings_SCHEMAS = org.freedesktop.Geoclue.gschema.xml +@GSETTINGS_RULES@ + +EXTRA_DIST = \ + $(service_in_files) \ + $(gsettings_SCHEMAS) \ + $(convert_DATA) + +CLEANFILES = \ + $(BUILT_SOURCES) \ + stamp-gc-iface-master-glue.h \ + stamp-gc-iface-master-client-glue.h + +DISTCLEANFILES = \ + $(service_DATA) diff --git a/.pc/tizen.patch/src/client.c b/.pc/tizen.patch/src/client.c new file mode 100755 index 0000000..dbe5361 --- /dev/null +++ b/.pc/tizen.patch/src/client.c @@ -0,0 +1,994 @@ +/* + * Geoclue + * client.c - Geoclue Master Client + * + * Authors: Iain Holmes <iain@openedhand.com> + * Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries + * 2008 OpenedHand Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** TODO + * + * might want to write a testing-provider with a gui for + * choosing what to emit... + * + **/ + + +#include <config.h> + +#include <geoclue/geoclue-error.h> +#include <geoclue/geoclue-marshal.h> + +#include <geoclue/gc-provider.h> +#include <geoclue/gc-iface-position.h> +#include <geoclue/gc-iface-address.h> + +#include "client.h" + +#define GEOCLUE_POSITION_INTERFACE_NAME "org.freedesktop.Geoclue.Position" +#define GEOCLUE_ADDRESS_INTERFACE_NAME "org.freedesktop.Geoclue.Address" + +enum { + ADDRESS_PROVIDER_CHANGED, + POSITION_PROVIDER_CHANGED, + LAST_SIGNAL +}; +static guint32 signals[LAST_SIGNAL] = {0, }; + + +enum { + POSITION_CHANGED, /* signal id of current provider */ + ADDRESS_CHANGED, /* signal id of current provider */ + LAST_PRIVATE_SIGNAL +}; + +typedef struct _GcMasterClientPrivate { + guint32 signals[LAST_PRIVATE_SIGNAL]; + + GeoclueAccuracyLevel min_accuracy; + int min_time; + gboolean require_updates; + GeoclueResourceFlags allowed_resources; + + gboolean position_started; + GcMasterProvider *position_provider; + GList *position_providers; + gboolean position_provider_choice_in_progress; + time_t last_position_changed; + + gboolean address_started; + GcMasterProvider *address_provider; + GList *address_providers; + gboolean address_provider_choice_in_progress; + time_t last_address_changed; + +} GcMasterClientPrivate; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GC_TYPE_MASTER_CLIENT, GcMasterClientPrivate)) + + + +static gboolean gc_iface_master_client_set_requirements (GcMasterClient *client, + GeoclueAccuracyLevel min_accuracy, + int min_time, + gboolean require_updates, + GeoclueResourceFlags allowed_resources, + GError **error); +static gboolean gc_iface_master_client_position_start (GcMasterClient *client, GError **error); +static gboolean gc_iface_master_client_address_start (GcMasterClient *client, GError **error); +static gboolean gc_iface_master_client_get_address_provider (GcMasterClient *client, + char **name, + char **description, + char **service, + char **path, + GError **error); +static gboolean gc_iface_master_client_get_position_provider (GcMasterClient *client, + char **name, + char **description, + char **service, + char **path, + GError **error); + +static void gc_master_client_geoclue_init (GcIfaceGeoclueClass *iface); +static void gc_master_client_position_init (GcIfacePositionClass *iface); +static void gc_master_client_address_init (GcIfaceAddressClass *iface); + +G_DEFINE_TYPE_WITH_CODE (GcMasterClient, gc_master_client, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE(GC_TYPE_IFACE_GEOCLUE, + gc_master_client_geoclue_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_POSITION, + gc_master_client_position_init) + G_IMPLEMENT_INTERFACE (GC_TYPE_IFACE_ADDRESS, + gc_master_client_address_init)) + +#include "gc-iface-master-client-glue.h" + + +static gboolean status_change_requires_provider_change (GList *provider_list, + GcMasterProvider *current_provider, + GcMasterProvider *changed_provider, + GeoclueStatus status); +static void gc_master_client_emit_position_changed (GcMasterClient *client); +static void gc_master_client_emit_address_changed (GcMasterClient *client); +static gboolean gc_master_client_choose_position_provider (GcMasterClient *client, + GList *providers); +static gboolean gc_master_client_choose_address_provider (GcMasterClient *client, + GList *providers); + + +static void +status_changed (GcMasterProvider *provider, + GeoclueStatus status, + GcMasterClient *client) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + g_debug ("client: provider %s status changed: %d", gc_master_provider_get_name (provider), status); + + /* change providers if needed (and if we're not choosing provider already) */ + + if (!priv->position_provider_choice_in_progress && + status_change_requires_provider_change (priv->position_providers, + priv->position_provider, + provider, status) && + gc_master_client_choose_position_provider (client, + priv->position_providers)) { + + /* we have a new position provider, force-emit position_changed */ + gc_master_client_emit_position_changed (client); + } + + if (!priv->address_provider_choice_in_progress && + status_change_requires_provider_change (priv->address_providers, + priv->address_provider, + provider, status) && + gc_master_client_choose_address_provider (client, + priv->address_providers)) { + + /* we have a new address provider, force-emit address_changed */ + gc_master_client_emit_address_changed (client); + } +} + +static void +accuracy_changed (GcMasterProvider *provider, + GcInterfaceFlags interface, + GeoclueAccuracyLevel level, + GcMasterClient *client) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + GcInterfaceAccuracy *accuracy_data; + + accuracy_data = g_new0 (GcInterfaceAccuracy, 1); + g_debug ("client: %s accuracy changed (%d)", + gc_master_provider_get_name (provider), level); + + accuracy_data->interface = interface; + accuracy_data->accuracy_level = priv->min_accuracy; + switch (interface) { + case GC_IFACE_POSITION: + priv->position_providers = + g_list_sort_with_data (priv->position_providers, + (GCompareDataFunc)gc_master_provider_compare, + accuracy_data); + if (priv->position_provider_choice_in_progress) { + g_debug (" ...but provider choice in progress"); + } else if (gc_master_client_choose_position_provider (client, + priv->position_providers)) { + gc_master_client_emit_position_changed (client); + } + break; + + case GC_IFACE_ADDRESS: + priv->address_providers = + g_list_sort_with_data (priv->address_providers, + (GCompareDataFunc)gc_master_provider_compare, + accuracy_data); + if (priv->address_provider_choice_in_progress) { + g_debug (" ...but provider choice in progress"); + } else if (gc_master_client_choose_address_provider (client, + priv->address_providers)) { + gc_master_client_emit_address_changed (client); + } + break; + + default: + g_assert_not_reached (); + } + g_free (accuracy_data); +} + +static void +position_changed (GcMasterProvider *provider, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy *accuracy, + GcMasterClient *client) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + time_t now; + + now = time (NULL); + if (priv->min_time > (now - priv->last_position_changed)) { + /* NOTE: currently no-one makes sure there is an emit + * after min_time */ + return; + } + priv->last_position_changed = now; + + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (client), + fields, + timestamp, + latitude, longitude, altitude, + accuracy); +} + +static void +address_changed (GcMasterProvider *provider, + int timestamp, + GHashTable *details, + GeoclueAccuracy *accuracy, + GcMasterClient *client) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + time_t now; + + now = time (NULL); + if (priv->min_time > (now - priv->last_address_changed)) { + /* NOTE: currently no-one makes sure there is an emit + * after min_time */ + return; + } + priv->last_address_changed = now; + + gc_iface_address_emit_address_changed + (GC_IFACE_ADDRESS (client), + timestamp, + details, + accuracy); +} + +/*if changed_provider status changes, do we need to choose a new provider? */ +static gboolean +status_change_requires_provider_change (GList *provider_list, + GcMasterProvider *current_provider, + GcMasterProvider *changed_provider, + GeoclueStatus status) +{ + if (!provider_list) { + return FALSE; + + } else if (current_provider == NULL) { + return (status == GEOCLUE_STATUS_AVAILABLE); + + } else if (current_provider == changed_provider) { + return (status != GEOCLUE_STATUS_AVAILABLE); + + }else if (status != GEOCLUE_STATUS_AVAILABLE) { + return FALSE; + + } + + while (provider_list) { + GcMasterProvider *p = provider_list->data; + if (p == current_provider) { + /* not interested in worse-than-current providers */ + return FALSE; + } + if (p == changed_provider) { + /* changed_provider is better than current */ + return (status == GEOCLUE_STATUS_AVAILABLE); + } + provider_list = provider_list->next; + } + return FALSE; +} + +static void +gc_master_client_connect_common_signals (GcMasterClient *client, GList *providers) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + GList *l; + + /* connect to common signals if the provider is not already connected */ + l = providers; + while (l) { + GcMasterProvider *p = l->data; + if (!g_list_find (priv->address_providers, p) && + !g_list_find (priv->position_providers, p)) { + g_debug ("client: connecting to '%s' accuracy-changed and status-changed", gc_master_provider_get_name (p)); + g_signal_connect (G_OBJECT (p), + "status-changed", + G_CALLBACK (status_changed), + client); + g_signal_connect (G_OBJECT (p), + "accuracy-changed", + G_CALLBACK (accuracy_changed), + client); + } + l = l->next; + } +} + +static void +gc_master_client_unsubscribe_providers (GcMasterClient *client, GList *provider_list, GcInterfaceFlags iface) +{ + while (provider_list) { + GcMasterProvider *provider = provider_list->data; + + gc_master_provider_unsubscribe (provider, client, iface); + provider_list = provider_list->next; + } + +} + +/* get_best_provider will return the best provider with status == GEOCLUE_STATUS_AVAILABLE. + * It will also "subscribe" to that provider and all better ones, and unsubscribe from worse.*/ +static GcMasterProvider * +gc_master_client_get_best_provider (GcMasterClient *client, + GList **provider_list, + GcInterfaceFlags iface) +{ + GList *l = *provider_list; + /* TODO: should maybe choose a acquiring provider if better ones are are not available */ + + g_debug ("client: choosing best provider"); + + while (l) { + GcMasterProvider *provider = l->data; + + g_debug (" ...trying provider %s", gc_master_provider_get_name (provider)); + if (gc_master_provider_subscribe (provider, client, iface)) { + /* provider was started, so accuracy may have changed + (which re-sorts provider lists), restart provider selection */ + /* TODO re-think this: restarting provider selection leads to potentially + never-ending looping */ + g_debug (" ...started %s (status %d), re-starting provider selection", + gc_master_provider_get_name (provider), + gc_master_provider_get_status (provider)); + l = *provider_list; + continue; + } + /* provider did not need to be started */ + + /* TODO: currently returning even providers that are worse than priv->min_accuracy, + * if nothing else is available */ + if (gc_master_provider_get_status (provider) == GEOCLUE_STATUS_AVAILABLE) { + /* unsubscribe from all providers worse than this */ + gc_master_client_unsubscribe_providers (client, l->next, iface); + return provider; + } + l = l->next; + } + + /* no provider found */ + gc_master_client_unsubscribe_providers (client, *provider_list, iface); + return NULL; +} + +static void +gc_master_client_emit_position_changed (GcMasterClient *client) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + GeocluePositionFields fields; + int timestamp; + double latitude, longitude, altitude; + GeoclueAccuracy *accuracy = NULL; + GError *error = NULL; + + + if (priv->position_provider == NULL) { + accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0); + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (client), + GEOCLUE_POSITION_FIELDS_NONE, + time (NULL), + 0.0, 0.0, 0.0, + accuracy); + geoclue_accuracy_free (accuracy); + return; + } + + fields = gc_master_provider_get_position + (priv->position_provider, + ×tamp, + &latitude, &longitude, &altitude, + &accuracy, + &error); + if (error) { + /*TODO what now?*/ + g_warning ("client: failed to get position from %s: %s", + gc_master_provider_get_name (priv->position_provider), + error->message); + g_error_free (error); + return; + } + gc_iface_position_emit_position_changed + (GC_IFACE_POSITION (client), + fields, + timestamp, + latitude, longitude, altitude, + accuracy); +} + +static void +gc_master_client_emit_address_changed (GcMasterClient *client) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + int timestamp; + GHashTable *details = NULL; + GeoclueAccuracy *accuracy = NULL; + GError *error = NULL; + + if (priv->address_provider == NULL) { + accuracy = geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0.0, 0.0); + details = g_hash_table_new (g_str_hash, g_str_equal); + gc_iface_address_emit_address_changed + (GC_IFACE_ADDRESS (client), + time (NULL), + details, + accuracy); + g_hash_table_destroy (details); + geoclue_accuracy_free (accuracy); + return; + } + if (!gc_master_provider_get_address + (priv->address_provider, + ×tamp, + &details, + &accuracy, + &error)) { + /*TODO what now?*/ + g_warning ("client: failed to get address from %s: %s", + gc_master_provider_get_name (priv->address_provider), + error->message); + g_error_free (error); + return; + } + gc_iface_address_emit_address_changed + (GC_IFACE_ADDRESS (client), + timestamp, + details, + accuracy); +} + +/* return true if a _new_ provider was chosen */ +static gboolean +gc_master_client_choose_position_provider (GcMasterClient *client, + GList *providers) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + GcMasterProvider *new_p; + + /* choose and start provider */ + priv->position_provider_choice_in_progress = TRUE; + new_p = gc_master_client_get_best_provider (client, + &priv->position_providers, + GC_IFACE_POSITION); + priv->position_provider_choice_in_progress = FALSE; + + if (priv->position_provider && new_p == priv->position_provider) { + return FALSE; + } + + if (priv->signals[POSITION_CHANGED] > 0) { + g_signal_handler_disconnect (priv->position_provider, + priv->signals[POSITION_CHANGED]); + priv->signals[POSITION_CHANGED] = 0; + } + + priv->position_provider = new_p; + + if (priv->position_provider == NULL) { + g_debug ("client: position provider changed (to NULL)"); + g_signal_emit (client, signals[POSITION_PROVIDER_CHANGED], 0, + NULL, NULL, NULL, NULL); + return TRUE; + } + + g_debug ("client: position provider changed (to %s)", gc_master_provider_get_name (priv->position_provider)); + g_signal_emit (client, signals[POSITION_PROVIDER_CHANGED], 0, + gc_master_provider_get_name (priv->position_provider), + gc_master_provider_get_description (priv->position_provider), + gc_master_provider_get_service (priv->position_provider), + gc_master_provider_get_path (priv->position_provider)); + priv->signals[POSITION_CHANGED] = + g_signal_connect (G_OBJECT (priv->position_provider), + "position-changed", + G_CALLBACK (position_changed), + client); + return TRUE; +} + +/* return true if a _new_ provider was chosen */ +static gboolean +gc_master_client_choose_address_provider (GcMasterClient *client, + GList *providers) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + GcMasterProvider *new_p; + + + /* choose and start provider */ + priv->address_provider_choice_in_progress = TRUE; + new_p = gc_master_client_get_best_provider (client, + &priv->address_providers, + GC_IFACE_ADDRESS); + priv->address_provider_choice_in_progress = FALSE; + + if (priv->address_provider != NULL && new_p == priv->address_provider) { + /* keep using the same provider */ + return FALSE; + } + + if (priv->address_provider && priv->signals[ADDRESS_CHANGED] > 0) { + g_signal_handler_disconnect (priv->address_provider, + priv->signals[ADDRESS_CHANGED]); + priv->signals[ADDRESS_CHANGED] = 0; + } + + priv->address_provider = new_p; + + if (priv->address_provider == NULL) { + g_debug ("client: address provider changed (to NULL)"); + g_signal_emit (client, signals[ADDRESS_PROVIDER_CHANGED], 0, + NULL, NULL, NULL, NULL); + return TRUE; + } + + g_debug ("client: address provider changed (to %s)", gc_master_provider_get_name (priv->address_provider)); + g_signal_emit (client, signals[ADDRESS_PROVIDER_CHANGED], 0, + gc_master_provider_get_name (priv->address_provider), + gc_master_provider_get_description (priv->address_provider), + gc_master_provider_get_service (priv->address_provider), + gc_master_provider_get_path (priv->address_provider)); + priv->signals[ADDRESS_CHANGED] = + g_signal_connect (G_OBJECT (priv->address_provider), + "address-changed", + G_CALLBACK (address_changed), + client); + return TRUE; +} + +static void +gc_master_provider_set_position_providers (GcMasterClient *client, + GList *providers) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + GcInterfaceAccuracy *accuracy_data; + + accuracy_data = g_new0(GcInterfaceAccuracy, 1); + accuracy_data->interface = GC_IFACE_POSITION; + accuracy_data->accuracy_level = priv->min_accuracy; + + gc_master_client_connect_common_signals (client, providers); + priv->position_providers = + g_list_sort_with_data (providers, + (GCompareDataFunc)gc_master_provider_compare, + accuracy_data); + + g_free (accuracy_data); +} + +static void +gc_master_provider_set_address_providers (GcMasterClient *client, + GList *providers) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + GcInterfaceAccuracy *accuracy_data; + + accuracy_data = g_new0(GcInterfaceAccuracy, 1); + accuracy_data->interface = GC_IFACE_ADDRESS; + accuracy_data->accuracy_level = priv->min_accuracy; + + gc_master_client_connect_common_signals (client, providers); + priv->address_providers = + g_list_sort_with_data (providers, + (GCompareDataFunc)gc_master_provider_compare, + accuracy_data); + + g_free (accuracy_data); +} + +static void +gc_master_client_init_position_providers (GcMasterClient *client) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + GList *providers; + + if (!priv->position_started) { + return; + } + + /* TODO: free priv->position_providers */ + + providers = gc_master_get_providers (GC_IFACE_POSITION, + priv->min_accuracy, + priv->require_updates, + priv->allowed_resources, + NULL); + g_debug ("client: %d position providers matching requirements found, now choosing current provider", + g_list_length (providers)); + + gc_master_provider_set_position_providers (client, providers); + gc_master_client_choose_position_provider (client, priv->position_providers); +} +static void +gc_master_client_init_address_providers (GcMasterClient *client) +{ + GList *providers; + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + if (!priv->address_started) { + return; + } + + /* TODO: free priv->address_providers */ + + providers = gc_master_get_providers (GC_IFACE_ADDRESS, + priv->min_accuracy, + priv->require_updates, + priv->allowed_resources, + NULL); + g_debug ("client: %d address providers matching requirements found, now choosing current provider", + g_list_length (providers)); + + gc_master_provider_set_address_providers (client, providers); + gc_master_client_choose_address_provider (client, priv->address_providers); +} + +static gboolean +gc_iface_master_client_set_requirements (GcMasterClient *client, + GeoclueAccuracyLevel min_accuracy, + int min_time, + gboolean require_updates, + GeoclueResourceFlags allowed_resources, + GError **error) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + priv->min_accuracy = min_accuracy; + priv->min_time = min_time; + priv->require_updates = require_updates; + priv->allowed_resources = allowed_resources; + + gc_master_client_init_position_providers (client); + gc_master_client_init_address_providers (client); + + return TRUE; +} + + +static gboolean +gc_iface_master_client_position_start (GcMasterClient *client, + GError **error) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + if (priv->position_providers) { + if (error) { + *error = g_error_new (GEOCLUE_ERROR, + GEOCLUE_ERROR_FAILED, + "Position interface already started"); + } + return FALSE; + } + + priv->position_started = TRUE; + + gc_master_client_init_position_providers (client); + + return TRUE; +} + +static gboolean +gc_iface_master_client_address_start (GcMasterClient *client, + GError **error) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + if (priv->address_providers) { + if (error) { + *error = g_error_new (GEOCLUE_ERROR, + GEOCLUE_ERROR_FAILED, + "Address interface already started"); + } + return FALSE; + } + + priv->address_started = TRUE; + gc_master_client_init_address_providers (client); + return TRUE; +} + +static void +get_master_provider_details (GcMasterProvider *provider, + char **name, + char **description, + char **service, + char **path) +{ + if (name) { + if (!provider) { + *name = NULL; + } else { + *name = g_strdup (gc_master_provider_get_name (provider)); + } + } + if (description) { + if (!provider) { + *description = NULL; + } else { + *description = g_strdup (gc_master_provider_get_description (provider)); + } + } + if (service) { + if (!provider) { + *service = NULL; + } else { + *service = g_strdup (gc_master_provider_get_service (provider)); + } + } + if (path) { + if (!provider) { + *path = NULL; + } else { + *path = g_strdup (gc_master_provider_get_path (provider)); + } + } +} + + +static gboolean +gc_iface_master_client_get_address_provider (GcMasterClient *client, + char **name, + char **description, + char **service, + char **path, + GError **error) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + get_master_provider_details (priv->address_provider, + name, description, service, path); + return TRUE; +} + +static gboolean +gc_iface_master_client_get_position_provider (GcMasterClient *client, + char **name, + char **description, + char **service, + char **path, + GError **error) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + get_master_provider_details (priv->position_provider, + name, description, service, path); + return TRUE; +} + +static void +finalize (GObject *object) +{ + GcMasterClient *client = GC_MASTER_CLIENT (object); + GcMasterClientPrivate *priv = GET_PRIVATE (object); + + /* do not free contents of the lists, Master takes care of them */ + if (priv->position_providers) { + gc_master_client_unsubscribe_providers (client, priv->position_providers, GC_IFACE_ALL); + g_list_free (priv->position_providers); + priv->position_providers = NULL; + } + if (priv->address_providers) { + gc_master_client_unsubscribe_providers (client, priv->address_providers, GC_IFACE_ALL); + g_list_free (priv->address_providers); + priv->address_providers = NULL; + } + + ((GObjectClass *) gc_master_client_parent_class)->finalize (object); +} + +static void +gc_master_client_class_init (GcMasterClientClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->finalize = finalize; + + g_type_class_add_private (klass, sizeof (GcMasterClientPrivate)); + + signals[ADDRESS_PROVIDER_CHANGED] = + g_signal_new ("address-provider-changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, 0, + NULL, NULL, + geoclue_marshal_VOID__STRING_STRING_STRING_STRING, + G_TYPE_NONE, 4, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + signals[POSITION_PROVIDER_CHANGED] = + g_signal_new ("position-provider-changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, 0, + NULL, NULL, + geoclue_marshal_VOID__STRING_STRING_STRING_STRING, + G_TYPE_NONE, 4, + G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + + dbus_g_object_type_install_info (gc_master_client_get_type (), + &dbus_glib_gc_iface_master_client_object_info); + + +} + +static void +gc_master_client_init (GcMasterClient *client) +{ + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + priv->position_provider_choice_in_progress = FALSE; + priv->address_provider_choice_in_progress = FALSE; + + priv->position_started = FALSE; + priv->position_provider = NULL; + priv->position_providers = NULL; + + priv->address_started = FALSE; + priv->address_provider = NULL; + priv->address_providers = NULL; +} + +static gboolean +get_position (GcIfacePosition *iface, + GeocluePositionFields *fields, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GcMasterClient *client = GC_MASTER_CLIENT (iface); + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + if (priv->position_provider == NULL) { + if (error) { + *error = g_error_new (GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Geoclue master client has no usable Position providers"); + } + return FALSE; + } + + *fields = gc_master_provider_get_position + (priv->position_provider, + timestamp, + latitude, longitude, altitude, + accuracy, + error); + return (!*error); +} + +static gboolean +get_address (GcIfaceAddress *iface, + int *timestamp, + GHashTable **address, + GeoclueAccuracy **accuracy, + GError **error) +{ + GcMasterClient *client = GC_MASTER_CLIENT (iface); + GcMasterClientPrivate *priv = GET_PRIVATE (client); + + if (priv->address_provider == NULL) { + if (error) { + *error = g_error_new (GEOCLUE_ERROR, + GEOCLUE_ERROR_NOT_AVAILABLE, + "Geoclue master client has no usable Address providers"); + } + return FALSE; + } + + return gc_master_provider_get_address + (priv->address_provider, + timestamp, + address, + accuracy, + error); +} + +static gboolean +get_status (GcIfaceGeoclue *geoclue, + GeoclueStatus *status, + GError **error) +{ + /* not really meaningful */ + *status = GEOCLUE_STATUS_AVAILABLE; + return TRUE; +} + +static gboolean +set_options (GcIfaceGeoclue *geoclue, + GHashTable *options, + GError **error) +{ + /* not meaningful, options come from master */ + + /* It is not an error to not have a SetOptions implementation */ + return TRUE; +} + +static gboolean +get_provider_info (GcIfaceGeoclue *geoclue, + gchar **name, + gchar **description, + GError **error) +{ + if (name) { + *name = g_strdup ("Geoclue Master"); + } + if (description) { + *description = g_strdup ("Meta-provider that internally uses what ever provider is the best "); + } + return TRUE; +} + +static void +add_reference (GcIfaceGeoclue *geoclue, + DBusGMethodInvocation *context) +{ + /* TODO implement if needed */ + dbus_g_method_return (context); +} + +static void +remove_reference (GcIfaceGeoclue *geoclue, + DBusGMethodInvocation *context) +{ + /* TODO implement if needed */ + dbus_g_method_return (context); +} + +static void +gc_master_client_geoclue_init (GcIfaceGeoclueClass *iface) +{ + iface->get_provider_info = get_provider_info; + iface->get_status = get_status; + iface->set_options = set_options; + iface->add_reference = add_reference; + iface->remove_reference = remove_reference; +} + +static void +gc_master_client_position_init (GcIfacePositionClass *iface) +{ + iface->get_position = get_position; +} + +static void +gc_master_client_address_init (GcIfaceAddressClass *iface) +{ + iface->get_address = get_address; +} diff --git a/.pc/tizen.patch/src/connectivity-connman.c b/.pc/tizen.patch/src/connectivity-connman.c new file mode 100755 index 0000000..42ccce0 --- /dev/null +++ b/.pc/tizen.patch/src/connectivity-connman.c @@ -0,0 +1,739 @@ +/* + * Geoclue + * connectivity-connman.c + * + * Author: Javier Fernandez <jfernandez@igalia.com> + * Copyright (C) 2010 Igalia S.L + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include <config.h> + +#ifdef HAVE_CONNMAN + +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> +#include "connectivity-connman.h" + +#define CONNMAN_SERVICE "org.moblin.connman" +#define CONNMAN_MANAGER_PATH "/" +#define CONNMAN_MANAGER_INTERFACE CONNMAN_SERVICE ".Manager" +#define CONNMAN_TECHNOLOGY_INTERFACE CONNMAN_SERVICE ".Technology" +#define CONNMAN_DEVICE_INTERFACE CONNMAN_SERVICE ".Device" +#define CONNMAN_NETWORK_INTERFACE CONNMAN_SERVICE ".Network" +#define CONNMAN_SERVICE_INTERFACE CONNMAN_SERVICE ".Service" + +typedef void (*ConnmanFunc) (GeoclueConnman *self, + const gchar *path, + gpointer out); + +static void geoclue_connman_connectivity_init (GeoclueConnectivityInterface *iface); + +static int _strength_to_dbm (int strength); +static char *_get_mac_for_gateway (const char *gateway); +static char *_mac_strup (char *mac); +static gchar *_get_gateway (GeoclueConnman *self, const gchar *service); +static void _get_best_ap (GeoclueConnman *self, const gchar *network); +static void _get_aps_info (GeoclueConnman *self, const gchar *network, GHashTable **out); +static const GPtrArray *_get_technologies (GeoclueConnman *self, GHashTable **props); +static const GPtrArray *_get_services (GeoclueConnman *self, GHashTable **props); +static const GPtrArray *_get_devices (GeoclueConnman *self, GHashTable **props, const gchar *technology); +static const GPtrArray *_get_networks (GeoclueConnman *self, GHashTable **props, const gchar *device, const gchar *type_filter); +static void _explore_available_aps (GeoclueConnman *self, ConnmanFunc func, gpointer out); + + +G_DEFINE_TYPE_WITH_CODE (GeoclueConnman, geoclue_connman, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GEOCLUE_TYPE_CONNECTIVITY, + geoclue_connman_connectivity_init)) + + +/* GeoclueConnectivity iface methods */ +static int +_get_status (GeoclueConnectivity *iface) +{ + GeoclueConnman *connman = GEOCLUE_CONNMAN (iface); + + return connman->status; +} + +static char * +_get_ap_mac (GeoclueConnectivity *iface) +{ + GeoclueConnman *connman = GEOCLUE_CONNMAN (iface); + + return g_strdup (connman->cache_ap_mac); +} + +static GHashTable * +_get_aps (GeoclueConnectivity *iface) +{ + GeoclueConnman *self = GEOCLUE_CONNMAN (iface); + GHashTable *ht = NULL; + + /* Explore the active networks to collect the APs. */ + _explore_available_aps (self, (ConnmanFunc) _get_aps_info, &ht); + + return ht; +} + +static char * +_get_router_mac (GeoclueConnectivity *iface) +{ + GeoclueConnman *self = GEOCLUE_CONNMAN (iface); + GHashTable *props = NULL; + const GPtrArray *servs = NULL; + const gchar *serv = NULL; + gchar *gateway = NULL; + char *mac = NULL; + guint i; + + /* Get available services and iterate over them */ + /* to get the MAC of the connected router. */ + servs = _get_services (self, &props); + if (servs != NULL) { + for (i = 0; gateway == NULL && servs->len; i++) { + serv = g_ptr_array_index (servs, i); + gateway = _get_gateway (self, serv); + } + } + + /* Check the result. */ + if (gateway != NULL) { + mac = _get_mac_for_gateway (gateway); + g_free (gateway); + } + + /* Free */ + g_hash_table_destroy (props); + + return mac; +} + +/* internal private GObject methods */ +static void +dispose (GObject *object) +{ + GeoclueConnman *self = GEOCLUE_CONNMAN (object); + + g_object_unref (self->client); + self->client = NULL; + + dbus_g_connection_unref (self->conn); + self->conn = NULL; + + g_free (self->cache_ap_mac); + self->cache_ap_mac = NULL; + + ((GObjectClass *) geoclue_connman_parent_class)->dispose (object); +} + +static void +geoclue_connman_class_init (GeoclueConnmanClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->dispose = dispose; +} + +static int +_strength_to_dbm (int strength) +{ + /* Hackish linear strength to dBm conversion. + * 0% is -90 dBm + * 100% is -20 dBm */ + return (strength * 0.7) - 90; +} + +static char * +_get_mac_for_gateway (const char *gateway) +{ + char *cmd, *out, *mac, **split; + + cmd = g_strdup_printf ("ip neigh show %s", gateway); + + if (g_spawn_command_line_sync (cmd, &out, NULL, NULL, NULL) == FALSE) { + g_free (out); + g_free (cmd); + return NULL; + } + g_free (cmd); + + /* 192.168.1.1 dev eth0 lladdr 00:00:00:00:00:00 STALE */ + split = g_strsplit (out, " ", -1); + g_free (out); + + if (split == NULL) + return NULL; + if (g_strv_length (split) != 6) { + g_strfreev (split); + return NULL; + } + mac = g_strdup (split[4]); + g_strfreev (split); + + return _mac_strup (mac); +} + +static char * +_mac_strup (char *mac) +{ + guint i; + + g_assert (mac != NULL); + + for (i = 0; mac[i] != '\0' ; i++) { + if (g_ascii_isalpha (mac[i])) + mac[i] = g_ascii_toupper (mac[i]); + } + return mac; +} + +static GeoclueNetworkStatus +connmanstatus_to_geocluenetworkstatus (const gchar *status) +{ + if (g_strcmp0 (status, "online")) { + return GEOCLUE_CONNECTIVITY_OFFLINE; + } else { + return GEOCLUE_CONNECTIVITY_ONLINE; + } +} + +static gchar * +_get_gateway (GeoclueConnman *self, + const gchar *service) +{ + DBusGProxy *proxy = NULL; + GHashTable *props = NULL; + gchar *gateway = NULL; + const GHashTable *ht = NULL; + const GValue *value = NULL; + const gchar *msg = NULL; + GError *error = NULL; + + /* Create proxy. */ + proxy = dbus_g_proxy_new_for_name (self->conn, + CONNMAN_SERVICE, + service, + CONNMAN_SERVICE_INTERFACE); + if (proxy == NULL) { + g_warning ("%s was unable to create connection to Service iface.", + G_OBJECT_TYPE_NAME (self)); + return NULL; + } + + /* Get Service properties to get the gateway address. */ + if (dbus_g_proxy_call (proxy, "GetProperties", + &error, + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &props, + G_TYPE_INVALID)) { + + /* Get the mac of the connected router. */ + value = g_hash_table_lookup (props, "IPv4"); + if (value != NULL) { + ht = g_value_get_boxed (value); + value = g_hash_table_lookup ((GHashTable *) ht, "Gateway"); + if (value != NULL) { + gateway = g_value_dup_string (value); + } + } + } else { + msg = "Error getting Service properties: %s"; + if (error != NULL) { + g_warning (msg, error->message); + g_error_free (error); + } else { + g_warning (msg, "Unknown error"); + } + } + + /* Free */ + g_hash_table_destroy (props); + g_object_unref (proxy); + + return gateway; +} + +static void +_get_aps_info (GeoclueConnman *self, + const gchar *network, + GHashTable **out) +{ + DBusGProxy *proxy = NULL; + GHashTable *props = NULL; + gchar *ap_mac = NULL; + const gchar *msg = NULL; + GError *error = NULL; + int strength; + + g_assert (out != NULL); + + /* Create proxy. */ + proxy = dbus_g_proxy_new_for_name (self->conn, + CONNMAN_SERVICE, + network, + CONNMAN_NETWORK_INTERFACE); + if (proxy == NULL) { + g_warning ("%s was unable to create connection to Network iface.", + G_OBJECT_TYPE_NAME (self)); + return; + } + + /* Collect available APs into a HasTable. */ + if (dbus_g_proxy_call (proxy, "GetProperties", + &error, + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &props, + G_TYPE_INVALID)) { + + /* Store the AP information. */ + ap_mac = g_value_dup_string (g_hash_table_lookup (props, "Address")); + strength = g_value_get_uchar (g_hash_table_lookup (props, "Strength")); + if (ap_mac != NULL) { + /* Create storage for the first case. */ + if (*out == NULL) { + *out = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, NULL); + } + g_hash_table_insert (*out, ap_mac, + GINT_TO_POINTER (_strength_to_dbm (strength))); + } + } else { + msg = "Error getting Network properties: %s"; + if (error != NULL) { + g_warning (msg, error->message); + g_error_free (error); + } else { + g_warning (msg, "Unknown error"); + } + } + + /* Free */ + g_hash_table_destroy (props); + g_object_unref (proxy); +} + +static void +_get_best_ap (GeoclueConnman *self, + const gchar *network) +{ + DBusGProxy *proxy = NULL; + GHashTable *props = NULL; + const gchar *msg = NULL; + GError *error = NULL; + int strength; + + /* Create proxy. */ + proxy = dbus_g_proxy_new_for_name (self->conn, + CONNMAN_SERVICE, + network, + CONNMAN_NETWORK_INTERFACE); + + if (proxy == NULL) { + g_warning ("%s was unable to create connection to Network iface.", + G_OBJECT_TYPE_NAME (self)); + return; + } + + /* Evaluate Network properties and update best AP. */ + if (dbus_g_proxy_call (proxy, "GetProperties", + &error, + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + &props, + G_TYPE_INVALID)) { + + strength = g_value_get_uchar (g_hash_table_lookup (props, "Strength")); + if (strength > self->ap_strength) { + g_free (self->cache_ap_mac); + self->cache_ap_mac = g_value_dup_string (g_hash_table_lookup (props, "Address")); + self->ap_strength = strength; + } + } else { + msg = "Error getting Network properties: %s"; + if (error != NULL) { + g_warning (msg, error->message); + g_error_free (error); + } else { + g_warning (msg, "Unknown error"); + } + } + + /* Free */ + g_hash_table_destroy (props); + g_object_unref (proxy); +} + +static const GPtrArray * +_get_networks (GeoclueConnman *self, + GHashTable **props, + const gchar *device, + const gchar *type_filter) +{ + DBusGProxy *proxy = NULL; + const GPtrArray *nets = NULL; + const GValue *value = NULL; + const gchar *type = NULL; + const gchar *msg = NULL; + GError *error = NULL; + + /* Create proxy. */ + proxy = dbus_g_proxy_new_for_name (self->conn, + CONNMAN_SERVICE, + device, + CONNMAN_DEVICE_INTERFACE); + + if (proxy == NULL) { + g_warning ("%s was unable to create connection to Device iface.", + G_OBJECT_TYPE_NAME (self)); + return NULL; + } + + /* Get available Networks for a specific Device. */ + if (dbus_g_proxy_call (proxy, "GetProperties", + &error, + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + props, + G_TYPE_INVALID)) { + + /* Check only specific networks. */ + if (type_filter != NULL) { + type = g_value_get_string (g_hash_table_lookup (*props, "Type")); + if (g_strcmp0 (type, type_filter)) { + goto frees; + } + } + value = g_hash_table_lookup (*props, "Networks"); + nets = g_value_get_boxed (value); + } else { + msg = "Error getting Device properties: %s"; + if (error != NULL) { + g_warning (msg, error->message); + g_error_free (error); + } else { + g_warning (msg, "Unknown error"); + } + } + + /* Free */ + frees: + g_object_unref (proxy); + + return nets; +} + +static const GPtrArray * +_get_devices (GeoclueConnman *self, + GHashTable **props, + const gchar *technology) +{ + DBusGProxy *proxy = NULL; + const GPtrArray *devs = NULL; + const GValue *value = NULL; + const gchar *msg = NULL; + GError *error = NULL; + + /* Create proxy. */ + proxy = dbus_g_proxy_new_for_name (self->conn, + CONNMAN_SERVICE, + technology, + CONNMAN_TECHNOLOGY_INTERFACE); + + if (proxy == NULL) { + g_warning ("%s was unable to create connection to Technology iface.", + G_OBJECT_TYPE_NAME (self)); + return NULL; + } + + /* Get available Devices for a specific Technology. */ + if (dbus_g_proxy_call (proxy, "GetProperties", + &error, + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + props, + G_TYPE_INVALID)) { + + value = g_hash_table_lookup (*props, "Devices"); + devs = g_value_get_boxed (value); + } else { + msg = "Error getting Technologies properties: %s"; + if (error != NULL) { + g_warning (msg, error->message); + g_error_free (error); + } else { + g_warning (msg, "Unknown error"); + } + } + + /* Free */ + g_object_unref (proxy); + + return devs; +} + +static const GPtrArray * +_get_technologies (GeoclueConnman *self, + GHashTable **props) +{ + const GPtrArray *techs = NULL; + const GValue *value = NULL; + const gchar *msg = NULL; + GError *error = NULL; + + /* Get available technologies (Wifi, Eth, ...). */ + if (dbus_g_proxy_call (self->client, "GetProperties", + &error, + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + props, + G_TYPE_INVALID)) { + + value = g_hash_table_lookup (*props, "Technologies"); + techs = g_value_get_boxed (value); + } else { + msg = "Error getting Manager properties: %s"; + if (error != NULL) { + g_warning (msg, error->message); + g_error_free (error); + } else { + g_warning (msg, "Unknown error"); + } + } + + return techs; +} + +static const GPtrArray * +_get_services (GeoclueConnman *self, + GHashTable **props) +{ + const GPtrArray *servs = NULL; + const GValue *value = NULL; + const gchar *msg = NULL; + GError *error = NULL; + + /* Get available services. */ + if (dbus_g_proxy_call (self->client, "GetProperties", + &error, + G_TYPE_INVALID, + dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_VALUE), + props, + G_TYPE_INVALID)) { + + value = g_hash_table_lookup (*props, "Services"); + servs = g_value_get_boxed (value); + } else { + msg = "Error getting Manager properties: %s"; + if (error != NULL) { + g_warning (msg, error->message); + g_error_free (error); + } else { + g_warning (msg, "Unknown error"); + } + } + + return servs; +} + +static void +_explore_available_aps (GeoclueConnman *self, + ConnmanFunc func, + gpointer out) +{ + GHashTable *mgr_props = NULL; + GHashTable *tech_props = NULL; + GHashTable *dev_props = NULL; + const GPtrArray *techs = NULL; + const GPtrArray *devs = NULL; + const GPtrArray *nets = NULL; + const gchar *tech = NULL; + const gchar *dev = NULL; + const gchar *net = NULL; + guint i, j, k; + + techs = _get_technologies (self, &mgr_props); + if (techs == NULL) { + goto frees; + } + for (i = 0; i < techs->len; i++) { + tech = g_ptr_array_index (techs, i); + devs = _get_devices (self, &tech_props, tech); + if (devs == NULL) { + continue; + } + for (j = 0; j < devs->len; j++) { + dev = g_ptr_array_index (devs, j); + nets = _get_networks (self, &dev_props, dev, "wifi"); + if (nets == NULL) { + continue; + } + for (k = 0; k < nets->len; k++) { + net = g_ptr_array_index (nets, k); + + /* Perform specific actions. */ + func (self, net, out); + } + } + } + + /* Free */ + frees: + if (mgr_props != NULL) { + g_hash_table_destroy (mgr_props); + } + if (tech_props != NULL) { + g_hash_table_destroy (tech_props); + } + if (dev_props != NULL) { + g_hash_table_destroy (dev_props); + } +} + +static void +_cache_ap_mac (GeoclueConnman *self) +{ + /* Cleanup the cache. */ + g_free (self->cache_ap_mac); + self->cache_ap_mac = NULL; + self->ap_strength = 0; + + /* Explore the active networks to get the best AP. */ + _explore_available_aps (self, (ConnmanFunc) _get_best_ap, NULL); +} + + + +static void +_geoclue_connman_state_changed (DBusGProxy *proxy, + const gchar *status, + gpointer userdata) +{ + GeoclueConnman *self = GEOCLUE_CONNMAN (userdata); + GeoclueNetworkStatus gc_status; + + gc_status = connmanstatus_to_geocluenetworkstatus (status); + + if (gc_status != self->status) { + /* Update status. */ + self->status = gc_status; + + /* Update AP cache. */ + _cache_ap_mac (self); + + /* Notification. */ + geoclue_connectivity_emit_status_changed (GEOCLUE_CONNECTIVITY (self), + self->status); + } +} + + +static void +_method_call_notify_cb (DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + GeoclueConnman *self = GEOCLUE_CONNMAN (user_data); + const gchar *msg = NULL; + GError *error = NULL; + gchar *state = NULL; + + /* Collect output data. */ + if (dbus_g_proxy_end_call (proxy, + call, + &error, + G_TYPE_STRING, + &state, + G_TYPE_INVALID)) { + + /* Set current status. */ + _geoclue_connman_state_changed (proxy, + (const gchar *) state, + self); + } else { + msg = "%s was unable to get the current network status: %s."; + if (error != NULL) { + g_warning (msg, G_OBJECT_TYPE_NAME (self), + error->message); + g_error_free (error); + } else { + g_warning (msg, G_OBJECT_TYPE_NAME (self), + "Unknown error"); + } + } + + /* Free */ + g_free (state); +} + +static void +geoclue_connman_init (GeoclueConnman *self) +{ + GError *error = NULL; + + /* Get DBus connection to the System bus. */ + self->conn = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); + if (self->conn == NULL) { + g_warning ("%s was unable to create a connection to D-Bus: %s", + G_OBJECT_TYPE_NAME (self), error->message); + g_error_free (error); + return; + } + + /* Create proxy. */ + self->client = dbus_g_proxy_new_for_name (self->conn, + CONNMAN_SERVICE, + CONNMAN_MANAGER_PATH, + CONNMAN_MANAGER_INTERFACE); + + if (self->client == NULL) { + g_warning ("%s was unable to create connection to Connman Manager.", + G_OBJECT_TYPE_NAME (self)); + return; + } + + /* Get current state (async). */ + dbus_g_proxy_begin_call (self->client, "GetState", + _method_call_notify_cb, + self, + NULL, + G_TYPE_INVALID, + G_TYPE_STRING); + + /* Be aware of State changes. */ + dbus_g_proxy_add_signal (self->client, "StateChanged", + G_TYPE_STRING, G_TYPE_INVALID); + dbus_g_proxy_connect_signal (self->client, + "StateChanged", + G_CALLBACK (_geoclue_connman_state_changed), + self, + NULL); +} + + +static void +geoclue_connman_connectivity_init (GeoclueConnectivityInterface *iface) +{ + iface->get_status = _get_status; + iface->get_ap_mac = _get_ap_mac; + iface->get_router_mac = _get_router_mac; + iface->get_aps = _get_aps; +} + +#endif /* HAVE_CONNMAN*/ diff --git a/.pc/tizen.patch/src/connectivity-connman.h b/.pc/tizen.patch/src/connectivity-connman.h new file mode 100755 index 0000000..24c5907 --- /dev/null +++ b/.pc/tizen.patch/src/connectivity-connman.h @@ -0,0 +1,56 @@ +/* + * Geoclue + * connectivity-connman.h + * + * Author: Javier Fernandez <jfernandez@igalia.com> + * Copyright (C) 2010 Igalia S.L + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _CONNECTIVITY_CONNMAN_H +#define _CONNECTIVITY_CONNMAN_H + +#include <glib-object.h> +#include <dbus/dbus-glib.h> +#include "connectivity.h" + +G_BEGIN_DECLS + +#define GEOCLUE_TYPE_CONNMAN (geoclue_connman_get_type ()) +#define GEOCLUE_CONNMAN(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_CONNMAN, GeoclueConnman)) + +typedef struct { + GObject parent; + + /* private */ + GeoclueNetworkStatus status; + DBusGConnection *conn; + DBusGProxy *client; + gchar *cache_ap_mac; + int ap_strength; +} GeoclueConnman; + +typedef struct { + GObjectClass parent_class; +} GeoclueConnmanClass; + +GType geoclue_connman_get_type (void); + +G_END_DECLS + +#endif diff --git a/.pc/tizen.patch/src/connectivity-networkmanager.c b/.pc/tizen.patch/src/connectivity-networkmanager.c new file mode 100755 index 0000000..09630a0 --- /dev/null +++ b/.pc/tizen.patch/src/connectivity-networkmanager.c @@ -0,0 +1,369 @@ +/* + * Geoclue + * geoclue-networkmanager.c + * + * Authors: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include <config.h> + +#ifdef HAVE_NETWORK_MANAGER + + +#include <dbus/dbus-glib.h> +#include <string.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <NetworkManager.h> /*for DBus strings */ + +#include <nm-client.h> +#include <nm-device-wifi.h> +#include <nm-setting-ip4-config.h> + +#if !defined(NM_CHECK_VERSION) +#define NM_CHECK_VERSION(x,y,z) 0 +#endif + +#include "connectivity-networkmanager.h" + +static void geoclue_networkmanager_connectivity_init (GeoclueConnectivityInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (GeoclueNetworkManager, geoclue_networkmanager, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (GEOCLUE_TYPE_CONNECTIVITY, + geoclue_networkmanager_connectivity_init)) + + +/* GeoclueConnectivity iface method */ +static int +get_status (GeoclueConnectivity *iface) +{ + GeoclueNetworkManager *nm = GEOCLUE_NETWORKMANAGER (iface); + + return nm->status; +} + +static char * +get_ap_mac (GeoclueConnectivity *iface) +{ + GeoclueNetworkManager *self = GEOCLUE_NETWORKMANAGER (iface); + + return g_strdup (self->cache_ap_mac); +} + +static int +strength_to_dbm (int strength) +{ + /* Hackish linear strength to dBm conversion. + * 0% is -90 dBm + * 100% is -20 dBm */ + return (strength * 0.7) - 90; +} + +static GHashTable * +get_aps (GeoclueConnectivity *iface) +{ + GeoclueNetworkManager *self = GEOCLUE_NETWORKMANAGER (iface); + const GPtrArray *devices; + GHashTable *ht; + guint i; + + devices = nm_client_get_devices (self->client); + if (devices == NULL) + return NULL; + + ht = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, NULL); + + for (i = 0; i < devices->len; i++) { + NMDevice *device = g_ptr_array_index (devices, i); + if (NM_IS_DEVICE_WIFI (device)) { + const GPtrArray *aps; + guint j; + + aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device)); + if (aps == NULL || aps->len == 0) + continue; + for (j = 0; j < aps->len; j++) { + NMAccessPoint *ap = NM_ACCESS_POINT (g_ptr_array_index (aps, j)); + char *ap_mac; + int strength; + + ap_mac = g_strdup (nm_access_point_get_hw_address (ap)); + strength = nm_access_point_get_strength (ap); + g_hash_table_insert (ht, ap_mac, GINT_TO_POINTER (strength_to_dbm (strength))); + } + } + } + if (g_hash_table_size (ht) == 0) { + g_hash_table_destroy (ht); + return NULL; + } + + return ht; +} + +static char * +mac_strup (char *mac) +{ + guint i; + for (i = 0; mac[i] != '\0' ; i++) { + if (g_ascii_isalpha (mac[i])) + mac[i] = g_ascii_toupper (mac[i]); + } + return mac; +} + +static char * +get_mac_for_gateway (const char *gateway) +{ + char *cmd, *out, *mac, **split; + + cmd = g_strdup_printf ("ip neigh show %s", gateway); + + if (g_spawn_command_line_sync (cmd, &out, NULL, NULL, NULL) == FALSE) { + g_free (out); + g_free (cmd); + return NULL; + } + g_free (cmd); + + /* 192.168.1.1 dev eth0 lladdr 00:00:00:00:00:00 STALE */ + split = g_strsplit (out, " ", -1); + g_free (out); + + if (split == NULL) + return NULL; + if (g_strv_length (split) != 6) { + g_strfreev (split); + return NULL; + } + mac = g_strdup (split[4]); + g_strfreev (split); + + return mac_strup (mac); +} + +static gchar * +ip4_address_as_string (guint32 ip) +{ + struct in_addr tmp_addr; + char buf[INET_ADDRSTRLEN+1]; + + memset (&buf, '\0', sizeof (buf)); + tmp_addr.s_addr = ip; + + if (inet_ntop (AF_INET, &tmp_addr, buf, INET_ADDRSTRLEN)) + return g_strdup (buf); + + return NULL; +} + +static char * +get_router_mac (GeoclueConnectivity *iface) +{ + GeoclueNetworkManager *self = GEOCLUE_NETWORKMANAGER (iface); + const GPtrArray *devices; + char *gateway, *mac; + guint i; + + devices = nm_client_get_devices (self->client); + if (devices == NULL) + return NULL; + + gateway = NULL; + + for (i = 0; i < devices->len; i++) { + NMDevice *device = g_ptr_array_index (devices, i); + NMIP4Config *cfg4; + GSList *iter; + + if (nm_device_get_state (device) != NM_DEVICE_STATE_ACTIVATED) + continue; + + cfg4 = nm_device_get_ip4_config (device); + if (cfg4 == NULL) + continue; + + for (iter = (GSList *) nm_ip4_config_get_addresses (cfg4); iter; iter = g_slist_next (iter)) { + NMIP4Address *addr = (NMIP4Address *) iter->data; + + gateway = ip4_address_as_string (nm_ip4_address_get_gateway (addr)); + if (gateway != NULL) + break; + } + } + if (gateway == NULL) + return NULL; + + mac = get_mac_for_gateway (gateway); + g_free (gateway); + + return mac; +} + +static void +get_best_ap (GeoclueNetworkManager *self, NMDevice *device) +{ + const GPtrArray *aps; + guint i; + + aps = nm_device_wifi_get_access_points (NM_DEVICE_WIFI (device)); + if (aps == NULL || aps->len == 0) + return; + for (i = 0; i < aps->len; i++) { + NMAccessPoint *ap = NM_ACCESS_POINT (g_ptr_array_index (aps, i)); + int strength; + + strength = nm_access_point_get_strength (ap); + if (strength > self->ap_strength) { + g_free (self->cache_ap_mac); + self->cache_ap_mac = g_strdup (nm_access_point_get_hw_address (ap)); + self->ap_strength = strength; + } + } +} + +static void +cache_ap_mac (GeoclueNetworkManager *self) +{ + const GPtrArray *devices; + guint i; + + devices = nm_client_get_devices (self->client); + + g_free (self->cache_ap_mac); + self->cache_ap_mac = NULL; + self->ap_strength = 0; + + for (i = 0; devices != NULL && i < devices->len; i++) { + NMDevice *device = g_ptr_array_index (devices, i); + if (NM_IS_DEVICE_WIFI (device)) { + get_best_ap (self, device); + } + } +} + +static void +dispose (GObject *object) +{ + GeoclueNetworkManager *self = GEOCLUE_NETWORKMANAGER (object); + + g_free (self->cache_ap_mac); + self->cache_ap_mac = NULL; + g_object_unref (self->client); + self->client = NULL; + ((GObjectClass *) geoclue_networkmanager_parent_class)->dispose (object); +} + +static void +geoclue_networkmanager_class_init (GeoclueNetworkManagerClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->dispose = dispose; +} + +static GeoclueNetworkStatus +nmstate_to_geocluenetworkstatus (NMState status) +{ + switch (status) { + case NM_STATE_UNKNOWN: + return GEOCLUE_CONNECTIVITY_UNKNOWN; + case NM_STATE_ASLEEP: + case NM_STATE_DISCONNECTED: +#if NM_CHECK_VERSION(0,8,992) + case NM_STATE_DISCONNECTING: +#endif + return GEOCLUE_CONNECTIVITY_OFFLINE; + case NM_STATE_CONNECTING: + return GEOCLUE_CONNECTIVITY_ACQUIRING; +#if NM_CHECK_VERSION(0,8,992) + case NM_STATE_CONNECTED_LOCAL: + case NM_STATE_CONNECTED_SITE: + case NM_STATE_CONNECTED_GLOBAL: +#else + case NM_STATE_CONNECTED: +#endif + return GEOCLUE_CONNECTIVITY_ONLINE; + default: + g_warning ("Unknown NMStatus: %d", status); + return GEOCLUE_CONNECTIVITY_UNKNOWN; + } +} + +static void +update_status (GeoclueNetworkManager *self, gboolean do_signal) +{ + GeoclueNetworkStatus old_status; + NMState state; + + old_status = self->status; + + if (nm_client_get_manager_running (self->client)) { + state = nm_client_get_state (self->client); + self->status = nmstate_to_geocluenetworkstatus (state); + cache_ap_mac (self); + } else { + self->status = GEOCLUE_CONNECTIVITY_OFFLINE; + } + + if ((self->status != old_status) && do_signal) { + geoclue_connectivity_emit_status_changed (GEOCLUE_CONNECTIVITY (self), + self->status); + } +} + +static void +nm_update_status_cb (GObject *obj, GParamSpec *spec, gpointer userdata) +{ + update_status (GEOCLUE_NETWORKMANAGER (userdata), TRUE); +} + +static void +geoclue_networkmanager_init (GeoclueNetworkManager *self) +{ + self->status = GEOCLUE_CONNECTIVITY_UNKNOWN; + self->client = nm_client_new (); + if (self->client == NULL) { + g_warning ("%s was unable to create a connection to NetworkManager", + G_OBJECT_TYPE_NAME (self)); + return; + } + + g_signal_connect (G_OBJECT (self->client), "notify::running", + G_CALLBACK (nm_update_status_cb), self); + g_signal_connect (G_OBJECT (self->client), "notify::state", + G_CALLBACK (nm_update_status_cb), self); + + /* get initial status */ + update_status (self, FALSE); +} + +static void +geoclue_networkmanager_connectivity_init (GeoclueConnectivityInterface *iface) +{ + iface->get_status = get_status; + iface->get_ap_mac = get_ap_mac; + iface->get_router_mac = get_router_mac; + iface->get_aps = get_aps; +} + +#endif /* HAVE_NETWORK_MANAGER */ diff --git a/.pc/tizen.patch/src/connectivity-networkmanager.h b/.pc/tizen.patch/src/connectivity-networkmanager.h new file mode 100755 index 0000000..d2e5cae --- /dev/null +++ b/.pc/tizen.patch/src/connectivity-networkmanager.h @@ -0,0 +1,56 @@ +/* + * Geoclue + * connectivity-networkmanager.h + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _CONNECTIVITY_NETWORKMANAGER_H +#define _CONNECTIVITY_NETWORKMANAGER_H + +#include <glib-object.h> +#include <nm-client.h> +#include "connectivity.h" + + +G_BEGIN_DECLS + +#define GEOCLUE_TYPE_NETWORKMANAGER (geoclue_networkmanager_get_type ()) +#define GEOCLUE_NETWORKMANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_NETWORKMANAGER, GeoclueNetworkManager)) + +typedef struct { + GObject parent; + + /* private */ + GeoclueNetworkStatus status; + NMClient *client; + char *cache_ap_mac; + int ap_strength; +} GeoclueNetworkManager; + +typedef struct { + GObjectClass parent_class; +} GeoclueNetworkManagerClass; + +GType geoclue_networkmanager_get_type (void); + +G_END_DECLS + +#endif diff --git a/.pc/tizen.patch/src/connectivity.c b/.pc/tizen.patch/src/connectivity.c new file mode 100755 index 0000000..96d83ab --- /dev/null +++ b/.pc/tizen.patch/src/connectivity.c @@ -0,0 +1,276 @@ +/* + * Geoclue + * geoclue-connectivity.c + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ +#include <config.h> + +#include <glib.h> +#include <string.h> +#include <stdio.h> + +#include "connectivity.h" + +#ifdef HAVE_NETWORK_MANAGER +#include "connectivity-networkmanager.h" +#else +#ifdef HAVE_CONIC +#include "connectivity-conic.h" +#else +#ifdef HAVE_CONNMAN +#include "connectivity-connman.h" +#endif +#endif +#endif + +#define DEFAULT_DBM -50 + +enum { + STATUS_CHANGED, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL] = {0}; + +static void +geoclue_connectivity_base_init (gpointer klass) +{ + static gboolean initialized = FALSE; + + if (initialized) { + return; + } + + initialized = TRUE; + signals[STATUS_CHANGED] = g_signal_new ("status-changed", + G_OBJECT_CLASS_TYPE (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GeoclueConnectivityInterface, + status_changed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, G_TYPE_INT); +} + +GType +geoclue_connectivity_get_type (void) +{ + static GType type = 0; + + if (!type) { + const GTypeInfo info = { + sizeof (GeoclueConnectivityInterface), + geoclue_connectivity_base_init, + NULL, + }; + + type = g_type_register_static (G_TYPE_INTERFACE, + "GeoclueConnectivity", + &info, 0); + } + + return type; +} + +GeoclueConnectivity * +geoclue_connectivity_new (void) +{ + GeoclueConnectivity *connectivity = NULL; + +#ifdef HAVE_NETWORK_MANAGER + connectivity = GEOCLUE_CONNECTIVITY (g_object_new (GEOCLUE_TYPE_NETWORKMANAGER, NULL)); +#else +#ifdef HAVE_CONIC + connectivity = GEOCLUE_CONNECTIVITY (g_object_new (GEOCLUE_TYPE_CONIC, NULL)); +#else +#ifdef HAVE_CONNMAN + connectivity = GEOCLUE_CONNECTIVITY (g_object_new (GEOCLUE_TYPE_CONNMAN, NULL)); +#endif +#endif +#endif + return connectivity; +} + +GeoclueNetworkStatus +geoclue_connectivity_get_status (GeoclueConnectivity *self) +{ + return GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_status (self); +} + +/* Parse /proc/net/route to get default gateway address and then parse + * /proc/net/arp to find matching mac address. + * + * There are some problems with this. First, it's IPv4 only. + * Second, there must be a way to do this with ioctl, but that seemed really + * complicated... even /usr/sbin/arp parses /proc/net/arp + * + * returns: + * 1 : on success + * 0 : no success, no errors + * <0 : error + */ +static int +get_router_mac_fallback (char **mac) +{ + char *content; + char **lines, **entry; + GError *error = NULL; + char *route_gateway = NULL; + + g_assert (*mac == NULL); + + if (!g_file_get_contents ("/proc/net/route", &content, NULL, &error)) { + g_warning ("Failed to read /proc/net/route: %s", error->message); + g_error_free (error); + return -1; + } + + lines = g_strsplit (content, "\n", 0); + g_free (content); + entry = lines + 1; + + while (*entry && strlen (*entry) > 0) { + char dest[9]; + char gateway[9]; + if (sscanf (*entry, + "%*s %8[0-9A-Fa-f] %8[0-9A-Fa-f] %*s", + dest, gateway) != 2) { + g_warning ("Failed to parse /proc/net/route entry '%s'", *entry); + } else if (strcmp (dest, "00000000") == 0) { + route_gateway = g_strdup (gateway); + break; + } + entry++; + } + g_strfreev (lines); + + if (!route_gateway) { + g_warning ("Failed to find default route in /proc/net/route"); + return -1; + } + + if (!g_file_get_contents ("/proc/net/arp", &content, NULL, &error)) { + g_warning ("Failed to read /proc/net/arp: %s", error->message); + g_error_free (error); + return -1; + } + + lines = g_strsplit (content, "\n", 0); + g_free (content); + entry = lines+1; + while (*entry && strlen (*entry) > 0) { + char hwa[100]; + char *arp_gateway; + int ip[4]; + + if (sscanf(*entry, + "%d.%d.%d.%d 0x%*x 0x%*x %100s %*s %*s\n", + &ip[0], &ip[1], &ip[2], &ip[3], hwa) != 5) { + g_warning ("Failed to parse /proc/net/arp entry '%s'", *entry); + } else { + arp_gateway = g_strdup_printf ("%02X%02X%02X%02X", ip[3], ip[2], ip[1], ip[0]); + if (strcmp (arp_gateway, route_gateway) == 0) { + g_free (arp_gateway); + *mac = g_strdup (hwa); + break; + } + g_free (arp_gateway); + + } + entry++; + } + g_free (route_gateway); + g_strfreev (lines); + + return *mac ? 1 : 0; +} + +static char * +mac_strup (char *mac) +{ + guint i; + for (i = 0; mac[i] != '\0' ; i++) { + if (g_ascii_isalpha (mac[i])) + mac[i] = g_ascii_toupper (mac[i]); + } + return mac; +} + +char * +geoclue_connectivity_get_router_mac (GeoclueConnectivity *self) +{ + if (self == NULL || + GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_router_mac == NULL) { + char *mac = NULL; + guint i; + int ret_val; + + for (i = 0; i < 5; i++) { + ret_val = get_router_mac_fallback (&mac); + if (ret_val < 0) + return NULL; + else if (ret_val == 1) + break; + g_usleep (G_USEC_PER_SEC / 10); + } + return mac_strup (mac); + } + + return GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_router_mac (self); +} + +char * +geoclue_connectivity_get_ap_mac (GeoclueConnectivity *self) +{ + if (self != NULL && + GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_ap_mac != NULL) + return GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_ap_mac (self); + + /* Hack when not using NetworkManager */ + return geoclue_connectivity_get_router_mac (self); +} + +GHashTable * +geoclue_connectivity_get_aps (GeoclueConnectivity *self) +{ + char *ap; + GHashTable *ht; + + if (self != NULL && + GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_aps != NULL) + return GEOCLUE_CONNECTIVITY_GET_INTERFACE (self)->get_aps (self); + + /* Fallback if the backend does not support get_aps */ + ap = geoclue_connectivity_get_ap_mac (self); + if (ap == NULL) + return NULL; + ht = g_hash_table_new_full (g_str_hash, g_str_equal, + (GDestroyNotify) g_free, NULL); + g_hash_table_insert (ht, ap, GINT_TO_POINTER (DEFAULT_DBM)); + return NULL; +} + +void +geoclue_connectivity_emit_status_changed (GeoclueConnectivity *self, + GeoclueNetworkStatus status) +{ + g_signal_emit (self, signals[STATUS_CHANGED], 0, status); +} diff --git a/.pc/tizen.patch/src/connectivity.h b/.pc/tizen.patch/src/connectivity.h new file mode 100755 index 0000000..76afbd9 --- /dev/null +++ b/.pc/tizen.patch/src/connectivity.h @@ -0,0 +1,73 @@ +/* + * Geoclue + * geoclue-connectivity.h + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef _GEOCLUE_CONNECTIVITY_H +#define _GEOCLUE_CONNECTIVITY_H + +#include <glib-object.h> +#include <geoclue/geoclue-types.h> + +G_BEGIN_DECLS + + +#define GEOCLUE_TYPE_CONNECTIVITY (geoclue_connectivity_get_type ()) +#define GEOCLUE_CONNECTIVITY(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_CONNECTIVITY, GeoclueConnectivity)) +#define GEOCLUE_IS_CONNECTIVITY(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GEOCLUE_TYPE_CONNECTIVITY)) +#define GEOCLUE_CONNECTIVITY_GET_INTERFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), GEOCLUE_TYPE_CONNECTIVITY, GeoclueConnectivityInterface)) + +typedef struct _GeoclueConnectivity GeoclueConnectivity; +typedef struct _GeoclueConnectivityInterface GeoclueConnectivityInterface; + +struct _GeoclueConnectivityInterface { + GTypeInterface parent; + + /* signals */ + void (* status_changed) (GeoclueConnectivity *self, + GeoclueNetworkStatus status); + + /* vtable */ + int (*get_status) (GeoclueConnectivity *self); + GHashTable * (*get_aps) (GeoclueConnectivity *self); + char * (*get_ap_mac) (GeoclueConnectivity *self); + char * (*get_router_mac) (GeoclueConnectivity *self); +}; + +GType geoclue_connectivity_get_type (void); + +GeoclueConnectivity *geoclue_connectivity_new (void); + +GeoclueNetworkStatus geoclue_connectivity_get_status (GeoclueConnectivity *self); + +char *geoclue_connectivity_get_ap_mac (GeoclueConnectivity *self); +char *geoclue_connectivity_get_router_mac (GeoclueConnectivity *self); + +GHashTable *geoclue_connectivity_get_aps (GeoclueConnectivity *self); + +void +geoclue_connectivity_emit_status_changed (GeoclueConnectivity *self, + GeoclueNetworkStatus status); + +G_END_DECLS + +#endif diff --git a/.pc/tizen.patch/src/geoclue b/.pc/tizen.patch/src/geoclue new file mode 100755 index 0000000..03bde7f --- /dev/null +++ b/.pc/tizen.patch/src/geoclue @@ -0,0 +1,3 @@ +[org.freedesktop.Geoclue] +gps-baudrate = /apps/geoclue/master/org.freedesktop.Geoclue.GPSBaudRate +gps-device = /apps/geoclue/master/org.freedesktop.Geoclue.GPSDevice diff --git a/.pc/tizen.patch/src/main.c b/.pc/tizen.patch/src/main.c new file mode 100755 index 0000000..22668e6 --- /dev/null +++ b/.pc/tizen.patch/src/main.c @@ -0,0 +1,231 @@ +/* + * Geoclue + * main.c - Master process + * + * Author: Iain Holmes <iain@openedhand.com> + * Copyright 2007 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <glib.h> +#include <gio/gio.h> + +#include <dbus/dbus-protocol.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-bindings.h> + +#include "master.h" + +static GMainLoop *mainloop; +static GHashTable *options; +static GSettings *settings; +static GcMaster *master; + + +#define GEOCLUE_SCHEMA_NAME "org.freedesktop.Geoclue" +#define GEOCLUE_MASTER_NAME "org.freedesktop.Geoclue.Master" + +static GValue * +gvariant_value_to_value (GVariant *value) +{ + GValue *gvalue; + const GVariantType *type; + + g_return_val_if_fail (value != NULL, NULL); + type = g_variant_get_type (value); + + if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_STRING)) { + const char *str; + + gvalue = g_new0 (GValue, 1); + str = g_variant_get_string (value, NULL); + + /* Don't add empty strings in the hashtable */ + if (str != NULL && str[0] == '\0') + str = NULL; + + g_value_init (gvalue, G_TYPE_STRING); + g_value_set_string (gvalue, str); + } else if (g_variant_type_is_subtype_of (type, G_VARIANT_TYPE_UINT32)) { + int i; + + gvalue = g_new0 (GValue, 1); + i = g_variant_get_uint32 (value); + g_value_init (gvalue, G_TYPE_INT); + g_value_set_int (gvalue, i); + } else { + gvalue = NULL; + g_warning ("Value is of unknown type"); + } + + return gvalue; +} + +static void +debug_print_key (gboolean init, + const char *key, + GValue *gvalue) +{ + const char *message; + char *string; + + if (init) + message = "GSettings key '%s' initialised to '%s'"; + else + message = "GSettings key '%s' changed to '%s'"; + + if (G_VALUE_TYPE (gvalue) == G_TYPE_STRING) { + string = g_value_dup_string (gvalue); + } else if (G_VALUE_TYPE (gvalue) == G_TYPE_INT) { + string = g_strdup_printf ("%d", g_value_get_int (gvalue)); + } else { + return; + } + + g_message (message, key, string); + g_free (string); +} + +static void +gsettings_key_changed (GSettings *settings, + char *key, + gpointer user_data) +{ + GVariant *v; + GValue *gvalue; + + v = g_settings_get_value (settings, key); + gvalue = gvariant_value_to_value (v); + if (gvalue == NULL) { + g_variant_unref (v); + return; + } + + debug_print_key (FALSE, key, gvalue); + + g_hash_table_insert (options, g_strdup (key), gvalue); + + g_signal_emit_by_name (G_OBJECT (master), "options-changed", options); +} + +static void +free_gvalue (GValue *value) +{ + if (value == NULL) + return; + g_value_unset (value); + g_free (value); +} + +static GHashTable * +load_options (void) +{ + GHashTable *ht = NULL; + guint i; + const char const * keys[] = { + "gps-baudrate", + "gps-device" + }; + + /* Setup keys monitoring */ + g_signal_connect (G_OBJECT (settings), "changed", + G_CALLBACK (gsettings_key_changed), NULL); + + ht = g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, (GDestroyNotify) free_gvalue); + + g_print ("Master options:\n"); + for (i = 0; i < G_N_ELEMENTS (keys); i++) { + GVariant *v; + GValue *gvalue; + const char *key = keys[i]; + + v = g_settings_get_value (settings, key); + gvalue = gvariant_value_to_value (v); + + if (gvalue == NULL) { + g_variant_unref (v); + continue; + } + + debug_print_key (TRUE, key, gvalue); + + g_hash_table_insert (ht, g_strdup (key), gvalue); + g_variant_unref (v); + } + + return ht; + } + +GHashTable * +geoclue_get_main_options (void) +{ + return options; +} + +int +main (int argc, + char **argv) +{ + DBusGConnection *conn; + DBusGProxy *proxy; + GError *error = NULL; + guint32 request_name_ret; + + g_type_init (); + + mainloop = g_main_loop_new (NULL, FALSE); + + conn = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error); + if (!conn) { + g_error ("Error getting bus: %s", error->message); + return 1; + } + + proxy = dbus_g_proxy_new_for_name (conn, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS); + if (!org_freedesktop_DBus_request_name (proxy, GEOCLUE_MASTER_NAME, + 0, &request_name_ret, &error)) { + g_error ("Error registering D-Bus service %s: %s", + GEOCLUE_MASTER_NAME, error->message); + return 1; + } + + /* Just quit if master is already running */ + if (request_name_ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + return 1; + } + + /* Load options */ + settings = g_settings_new (GEOCLUE_SCHEMA_NAME); + options = load_options (); + + master = g_object_new (GC_TYPE_MASTER, NULL); + dbus_g_connection_register_g_object (conn, + "/org/freedesktop/Geoclue/Master", + G_OBJECT (master)); + + g_main_loop_run (mainloop); + return 0; +} diff --git a/.pc/tizen.patch/src/master-provider.c b/.pc/tizen.patch/src/master-provider.c new file mode 100755 index 0000000..e4ea053 --- /dev/null +++ b/.pc/tizen.patch/src/master-provider.c @@ -0,0 +1,1309 @@ +/* + * Geoclue + * master-provider.c - Provider object for master and master client + * + * Author: Jussi Kukkonen <jku@o-hand.com> + * + * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries + * 2008 OpenedHand Ltd + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +/** + * Provider object for GcMaster. Takes care of cacheing + * queried data. + * + * Should probably start/stop the actual providers as needed + * in the future + * + * Cache could also be used to save "stale" data for situations when + * current data is not available (MasterClient api would have to + * have a "allowOldData" setting) + * + * TODO: + * figure out what to do if get_* returns GEOCLUE_ERROR_NOT_AVAILABLE. + * Should try again, but when? + * + * implement velocity + * + * implement other (non-updating) ifaces + **/ + +#include <string.h> + +#include "main.h" +#include "master-provider.h" +#include <geoclue/geoclue-position.h> +#include <geoclue/geoclue-address.h> +#include <geoclue/geoclue-marshal.h> + +typedef enum _GeoclueProvideFlags { + GEOCLUE_PROVIDE_NONE = 0, + GEOCLUE_PROVIDE_UPDATES = 1 << 0, /* will send *-changed signals */ + GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION = 1 << 1, /* data can be queried on new connection, and cached until connection ends */ +} GeoclueProvideFlags; + +typedef struct _GcPositionCache { + int timestamp; + GeocluePositionFields fields; + double latitude; + double longitude; + double altitude; + GeoclueAccuracy *accuracy; + GError *error; +} GcPositionCache; + +typedef struct _GcAddressCache { + int timestamp; + GHashTable *details; + GeoclueAccuracy *accuracy; + GError *error; +} GcAddressCache; + +typedef struct _GcMasterProviderPrivate { + char *name; + char *description; + + char *service; + char *path; + GcInterfaceFlags interfaces; + + GList *position_clients; /* list of clients currently using this provider */ + GList *address_clients; + + GeoclueAccuracyLevel expected_accuracy; + + GeoclueResourceFlags required_resources; + GeoclueProvideFlags provides; + + GeoclueStatus master_status; /* net_status and status affect this */ + GeoclueNetworkStatus net_status; + + GeoclueStatus status; /* cached status from actual provider */ + + GeocluePosition *position; + GcPositionCache position_cache; + + GeoclueAddress *address; + GcAddressCache address_cache; + +} GcMasterProviderPrivate; + +enum { + STATUS_CHANGED, + ACCURACY_CHANGED, + POSITION_CHANGED, + ADDRESS_CHANGED, + LAST_SIGNAL +}; +static guint32 signals[LAST_SIGNAL] = {0, }; + +#define GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GC_TYPE_MASTER_PROVIDER, GcMasterProviderPrivate)) + +G_DEFINE_TYPE (GcMasterProvider, gc_master_provider, G_TYPE_OBJECT) + +static void +copy_error (GError **target, GError *source) +{ + if (*target) { + g_error_free (*target); + *target = NULL; + } + if (source) { + *target = g_error_copy (source); + + /* If the error type is a D-Bus remote exception, + * don't lose the "magic" sauce after the message string. + * See the code in gerror_to_dbus_error_message() in dbus-glib */ + if (source->domain == DBUS_GERROR && + source->code == DBUS_GERROR_REMOTE_EXCEPTION) { + int len; + g_free ((*target)->message); + len = strlen (source->message); + len += strlen (source->message + len + 1); + len += 2; + (*target)->message = g_memdup (source->message, len); + } + } +} + +static GeoclueProvider* +gc_master_provider_get_provider (GcMasterProvider *master_provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (master_provider); + + if (priv->address) { + return GEOCLUE_PROVIDER (priv->address); + } + if (priv->position) { + return GEOCLUE_PROVIDER (priv->position); + } + return NULL; +} + +static gboolean +gc_master_provider_is_running (GcMasterProvider *master_provider) +{ + return (gc_master_provider_get_provider (master_provider) != NULL); +} + +static void +gc_master_provider_handle_new_position_accuracy (GcMasterProvider *provider, + GeoclueAccuracy *accuracy) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + GeoclueAccuracyLevel old_level; + GeoclueAccuracyLevel new_level = GEOCLUE_ACCURACY_LEVEL_NONE; + double new_hor_acc, new_vert_acc; + + geoclue_accuracy_get_details (priv->position_cache.accuracy, + &old_level, NULL, NULL); + if (accuracy) { + geoclue_accuracy_get_details (accuracy, + &new_level, &new_hor_acc, &new_vert_acc); + } + geoclue_accuracy_set_details (priv->position_cache.accuracy, + new_level, new_hor_acc, new_vert_acc); + + if (old_level != new_level) { + g_signal_emit (provider, signals[ACCURACY_CHANGED], 0, + GC_IFACE_POSITION, new_level); + } +} + +static void +gc_master_provider_handle_new_address_accuracy (GcMasterProvider *provider, + GeoclueAccuracy *accuracy) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + GeoclueAccuracyLevel old_level; + GeoclueAccuracyLevel new_level = GEOCLUE_ACCURACY_LEVEL_NONE; + double new_hor_acc, new_vert_acc; + + geoclue_accuracy_get_details (priv->address_cache.accuracy, + &old_level, NULL, NULL); + if (accuracy) { + geoclue_accuracy_get_details (accuracy, + &new_level, &new_hor_acc, &new_vert_acc); + } + geoclue_accuracy_set_details (priv->address_cache.accuracy, + new_level, new_hor_acc, new_vert_acc); + + if (old_level != new_level) { + g_signal_emit (provider, signals[ACCURACY_CHANGED], 0, + GC_IFACE_ADDRESS, new_level); + } +} + +static void +gc_master_provider_set_position (GcMasterProvider *provider, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy *accuracy, + GError *error) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + priv->position_cache.timestamp = timestamp; + priv->position_cache.fields = fields; + priv->position_cache.latitude = latitude; + priv->position_cache.longitude = longitude; + priv->position_cache.altitude = altitude; + + copy_error (&priv->position_cache.error, error); + + /* emit accuracy-changed if needed, so masterclient can re-choose providers + * before we emit position-changed */ + gc_master_provider_handle_new_position_accuracy (provider, accuracy); + + if (!error) { + g_signal_emit (provider, signals[POSITION_CHANGED], 0, + fields, timestamp, + latitude, longitude, altitude, + priv->position_cache.accuracy); + } +} + +static void +gc_master_provider_set_address (GcMasterProvider *provider, + int timestamp, + GHashTable *details, + GeoclueAccuracy *accuracy, + GError *error) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + priv->address_cache.timestamp = timestamp; + + g_hash_table_destroy (priv->address_cache.details); + if (details) { + priv->address_cache.details = geoclue_address_details_copy (details); + }else { + priv->address_cache.details = geoclue_address_details_new (); + } + copy_error (&priv->address_cache.error, error); + + /* emit accuracy-changed if needed, so masterclient can re-choose providers + * before we emit position-changed */ + gc_master_provider_handle_new_address_accuracy (provider, accuracy); + + if (!error) { + g_signal_emit (provider, signals[ADDRESS_CHANGED], 0, + priv->address_cache.timestamp, + priv->address_cache.details, + priv->address_cache.accuracy); + } +} + + + +static GeoclueResourceFlags +parse_resource_strings (char **flags) +{ + GeoclueResourceFlags resources = GEOCLUE_RESOURCE_NONE; + int i; + + for (i = 0; flags[i]; i++) { + if (strcmp (flags[i], "RequiresNetwork") == 0) { + resources |= GEOCLUE_RESOURCE_NETWORK; + } else if (strcmp (flags[i], "RequiresCell") == 0) { + resources |= GEOCLUE_RESOURCE_CELL; + } else if (strcmp (flags[i], "RequiresGPS") == 0) { + resources |= GEOCLUE_RESOURCE_GPS; + } + } + + return resources; +} + +static GeoclueProvideFlags +parse_provide_strings (char **flags) +{ + GeoclueProvideFlags provides = GEOCLUE_PROVIDE_NONE; + int i; + + for (i = 0; flags[i]; i++) { + if (strcmp (flags[i], "ProvidesUpdates") == 0) { + provides |= GEOCLUE_PROVIDE_UPDATES; + } else if (strcmp (flags[i], "ProvidesCacheableOnConnection") == 0) { + provides |= GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION; + } + } + + return provides; +} + +static GcInterfaceFlags +parse_interface_strings (char **strs) +{ + GcInterfaceFlags ifaces = GC_IFACE_GEOCLUE; + int i; + + for (i = 0; strs[i]; i++) { + if (strcmp (strs[i], GEOCLUE_POSITION_INTERFACE_NAME) == 0) { + ifaces |= GC_IFACE_POSITION; + } else if (strcmp (strs[i], GEOCLUE_ADDRESS_INTERFACE_NAME) == 0) { + ifaces |= GC_IFACE_ADDRESS; + } + } + return ifaces; +} + +static GeoclueAccuracyLevel +parse_accuracy_string (char *str) +{ + GeoclueAccuracyLevel level = GEOCLUE_ACCURACY_LEVEL_NONE; + if (!str || strcmp (str, "None") == 0) { + level = GEOCLUE_ACCURACY_LEVEL_NONE; + } else if (strcmp (str, "Country") == 0) { + level = GEOCLUE_ACCURACY_LEVEL_COUNTRY; + } else if (strcmp (str, "Region") == 0) { + level = GEOCLUE_ACCURACY_LEVEL_REGION; + } else if (strcmp (str, "Locality") == 0) { + level = GEOCLUE_ACCURACY_LEVEL_LOCALITY; + } else if (strcmp (str, "Postalcode") == 0) { + level = GEOCLUE_ACCURACY_LEVEL_POSTALCODE; + } else if (strcmp (str, "Street") == 0) { + level = GEOCLUE_ACCURACY_LEVEL_STREET; + } else if (strcmp (str, "Detailed") == 0) { + level = GEOCLUE_ACCURACY_LEVEL_DETAILED; + } else { + g_warning ("'%s' is not a recognised accuracy level value", str); + } + return level; +} + +static void +gc_master_provider_handle_error (GcMasterProvider *provider, GError *error) +{ + GcMasterProviderPrivate *priv; + + g_assert (error); + + priv = GET_PRIVATE (provider); + g_debug ("%s handling error %d", priv->name, error->code); + + /* web service providers that are unavailable */ + if (priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION && + error->code == GEOCLUE_ERROR_NOT_AVAILABLE) { + priv->master_status = GEOCLUE_STATUS_UNAVAILABLE; + /* TODO set timer to re-check availability */ + } +} + +/* Sets master_status based on provider status and net_status + * Should be called whenever priv->status or priv->net_status change */ +static void +gc_master_provider_handle_status_change (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + GeoclueStatus new_master_status; + + /* calculate new master status */ + if (priv->required_resources & GEOCLUE_RESOURCE_NETWORK || + priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION) { + switch (priv->net_status) { + case GEOCLUE_CONNECTIVITY_UNKNOWN: + /* falling through */ + case GEOCLUE_CONNECTIVITY_OFFLINE: + new_master_status = GEOCLUE_STATUS_UNAVAILABLE; + break; + case GEOCLUE_CONNECTIVITY_ACQUIRING: + if (priv->status == GEOCLUE_STATUS_AVAILABLE){ + new_master_status = GEOCLUE_STATUS_ACQUIRING; + } else { + new_master_status = priv->status; + } + break; + case GEOCLUE_CONNECTIVITY_ONLINE: + new_master_status = priv->status; + break; + default: + g_assert_not_reached (); + } + + } else { + new_master_status = priv->status; + } + + if (new_master_status != priv->master_status) { + priv->master_status = new_master_status; + + g_signal_emit (provider, signals[STATUS_CHANGED], 0, new_master_status); + } +} + + +static void +gc_master_provider_update_cache (GcMasterProvider *master_provider) +{ + GcMasterProviderPrivate *priv; + + priv = GET_PRIVATE (master_provider); + + if ((!(priv->provides & GEOCLUE_PROVIDE_UPDATES)) || + (!gc_master_provider_get_provider (master_provider))) { + /* non-cacheable provider or provider not running */ + return; + } + + g_debug ("%s: Updating cache ", priv->name); + priv->master_status = GEOCLUE_STATUS_ACQUIRING; + g_signal_emit (master_provider, signals[STATUS_CHANGED], 0, priv->master_status); + + if (priv->position) { + int timestamp; + double lat, lon, alt; + GeocluePositionFields fields; + GeoclueAccuracy *accuracy = NULL; + GError *error = NULL; + + fields = geoclue_position_get_position (priv->position, + ×tamp, + &lat, &lon, &alt, + &accuracy, + &error); + if (error){ + g_warning ("Error updating position cache: %s", error->message); + gc_master_provider_handle_error (master_provider, error); + } + gc_master_provider_set_position (master_provider, + fields, timestamp, + lat, lon, alt, + accuracy, error); + } + + if (priv->address) { + int timestamp; + GHashTable *details = NULL; + GeoclueAccuracy *accuracy = NULL; + GError *error = NULL; + + if (!geoclue_address_get_address (priv->address, + ×tamp, + &details, + &accuracy, + &error)) { + g_warning ("Error updating address cache: %s", error->message); + gc_master_provider_handle_error (master_provider, error); + } + gc_master_provider_set_address (master_provider, + timestamp, + details, + accuracy, + error); + } + + gc_master_provider_handle_status_change (master_provider); +} + +/* signal handlers for the actual providers signals */ + +static void +provider_status_changed (GeoclueProvider *provider, + GeoclueStatus status, + GcMasterProvider *master_provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (master_provider); + + priv->status = status; + gc_master_provider_handle_status_change (master_provider); +} + +static void +position_changed (GeocluePosition *position, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy *accuracy, + GcMasterProvider *provider) +{ + /* is there a situation when we'd need to check against cache + * if data has really changed? probably not */ + gc_master_provider_set_position (provider, + fields, timestamp, + latitude, longitude, altitude, + accuracy, NULL); +} + +static void +address_changed (GeoclueAddress *address, + int timestamp, + GHashTable *details, + GeoclueAccuracy *accuracy, + GcMasterProvider *provider) +{ + /* is there a situation when we'd need to check against cache + * if data has really changed? probably not */ + gc_master_provider_set_address (provider, + timestamp, + details, + accuracy, + NULL); +} + + +static void +finalize (GObject *object) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (object); + + geoclue_accuracy_free (priv->position_cache.accuracy); + geoclue_accuracy_free (priv->address_cache.accuracy); + if (priv->position_cache.error) { + g_error_free (priv->position_cache.error); + } + if (priv->address_cache.error) { + g_error_free (priv->address_cache.error); + } + + g_free (priv->name); + g_free (priv->description); + g_free (priv->service); + g_free (priv->path); + + g_free (priv->position_clients); + g_free (priv->address_clients); + + G_OBJECT_CLASS (gc_master_provider_parent_class)->finalize (object); +} + +static void +dispose (GObject *object) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (object); + + if (priv->position) { + g_object_unref (priv->position); + priv->position = NULL; + } + + if (priv->address) { + g_object_unref (priv->address); + priv->address = NULL; + } + if (priv->address_cache.details) { + g_hash_table_destroy (priv->address_cache.details); + priv->address_cache.details = NULL; + } + + G_OBJECT_CLASS (gc_master_provider_parent_class)->dispose (object); +} + +static void +gc_master_provider_class_init (GcMasterProviderClass *klass) +{ + GObjectClass *o_class = (GObjectClass *) klass; + + o_class->finalize = finalize; + o_class->dispose = dispose; + + g_type_class_add_private (klass, sizeof (GcMasterProviderPrivate)); + + signals[STATUS_CHANGED] = g_signal_new ("status-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GcMasterProviderClass, status_changed), + NULL, NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, 1, + G_TYPE_INT); + signals[ACCURACY_CHANGED] = g_signal_new ("accuracy-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GcMasterProviderClass, accuracy_changed), + NULL, NULL, + geoclue_marshal_VOID__INT_INT, + G_TYPE_NONE, 2, + G_TYPE_INT, G_TYPE_INT); + signals[POSITION_CHANGED] = g_signal_new ("position-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GcMasterProviderClass, position_changed), + NULL, NULL, + geoclue_marshal_VOID__INT_INT_DOUBLE_DOUBLE_DOUBLE_BOXED, + G_TYPE_NONE, 6, + G_TYPE_INT, G_TYPE_INT, + G_TYPE_DOUBLE, G_TYPE_DOUBLE, G_TYPE_DOUBLE, + G_TYPE_POINTER); + signals[ADDRESS_CHANGED] = g_signal_new ("address-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GcMasterProviderClass, address_changed), + NULL, NULL, + geoclue_marshal_VOID__INT_BOXED_BOXED, + G_TYPE_NONE, 3, + G_TYPE_INT, + G_TYPE_POINTER, + G_TYPE_POINTER); +} + +static void +gc_master_provider_init (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + priv->position_clients = NULL; + priv->address_clients = NULL; + + priv->master_status = GEOCLUE_STATUS_UNAVAILABLE; + + priv->position = NULL; + priv->position_cache.accuracy = + geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0 ,0); + priv->position_cache.error = NULL; + + priv->address = NULL; + priv->address_cache.accuracy = + geoclue_accuracy_new (GEOCLUE_ACCURACY_LEVEL_NONE, 0 ,0); + priv->address_cache.details = geoclue_address_details_new (); + priv->address_cache.error = NULL; +} + +#if DEBUG_INFO +static void +gc_master_provider_dump_position (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv; + GeocluePositionFields fields; + int time; + double lat, lon, alt; + GError *error = NULL; + + priv = GET_PRIVATE (provider); + + + g_print (" Position Information:\n"); + g_print (" ---------------------\n"); + + fields = gc_master_provider_get_position (provider, + &time, + &lat, &lon, &alt, + NULL, &error); + if (error) { + g_print (" Error: %s", error->message); + g_error_free (error); + return; + } + g_print (" Timestamp: %d\n", time); + g_print (" Latitude: %.2f %s\n", lat, + fields & GEOCLUE_POSITION_FIELDS_LATITUDE ? "" : "(not set)"); + g_print (" Longitude: %.2f %s\n", lon, + fields & GEOCLUE_POSITION_FIELDS_LONGITUDE ? "" : "(not set)"); + g_print (" Altitude: %.2f %s\n", alt, + fields & GEOCLUE_POSITION_FIELDS_ALTITUDE ? "" : "(not set)"); + +} + +static void +dump_address_key_and_value (char *key, char *value, GHashTable *target) +{ + g_print (" %s: %s\n", key, value); +} + +static void +gc_master_provider_dump_address (GcMasterProvider *provider) +{ + int time; + GHashTable *details; + GError *error = NULL; + + g_print (" Address Information:\n"); + g_print (" --------------------\n"); + if (!gc_master_provider_get_address (provider, + &time, + &details, + NULL, &error)) { + g_print (" Error: %s", error->message); + g_error_free (error); + return; + } + g_print (" Timestamp: %d\n", time); + g_hash_table_foreach (details, (GHFunc)dump_address_key_and_value, NULL); + +} + +static void +gc_master_provider_dump_required_resources (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv; + + priv = GET_PRIVATE (provider); + g_print (" Requires\n"); + if (priv->required_resources & GEOCLUE_RESOURCE_GPS) { + g_print (" - GPS\n"); + } + + if (priv->required_resources & GEOCLUE_RESOURCE_NETWORK) { + g_print (" - Network\n"); + } +} + +static void +gc_master_provider_dump_provides (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv; + + priv = GET_PRIVATE (provider); + g_print (" Provides\n"); + if (priv->provides & GEOCLUE_PROVIDE_UPDATES) { + g_print (" - Updates\n"); + } + if (priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION) { + g_print (" - Cacheable on network connection\n"); + } +} + +static void +gc_master_provider_dump_provider_details (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv; + + priv = GET_PRIVATE (provider); + g_print ("\n Name - %s\n", priv->name); + g_print (" Description - %s\n", priv->description); + g_print (" Service - %s\n", priv->service); + g_print (" Path - %s\n", priv->path); + g_print (" Accuracy level - %d\n", priv->expected_accuracy); + g_print (" Provider is currently %srunning, status %d\n", + gc_master_provider_get_provider (master_provider) ? "" : "not ", + priv->master_status); + gc_master_provider_dump_required_resources (provider); + gc_master_provider_dump_provides (provider); + + + if (priv->interfaces & GC_IFACE_POSITION) { + g_print (" Interface - Position\n"); + gc_master_provider_dump_position (provider); + } + if (priv->interfaces & GC_IFACE_ADDRESS) { + g_print (" Interface - Address\n"); + gc_master_provider_dump_address (provider); + } +} +#endif + +static gboolean +gc_master_provider_initialize_geoclue (GcMasterProvider *master_provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (master_provider); + GeoclueProvider *geoclue; + GError *error = NULL; + + geoclue = gc_master_provider_get_provider (master_provider); + + if (!geoclue_provider_set_options (geoclue, + geoclue_get_main_options (), + &error)) { + g_warning ("Error setting provider options: %s\n", error->message); + g_error_free (error); + return FALSE; + } + + /* priv->name has been read from .provider-file earlier... + * could ask the provider anyway, just to be consistent */ + if (!geoclue_provider_get_provider_info (geoclue, NULL, + &priv->description, &error)) { + g_warning ("Error getting provider info: %s\n", error->message); + g_error_free (error); + return FALSE; + } + + g_signal_connect (G_OBJECT (geoclue), "status-changed", + G_CALLBACK (provider_status_changed), master_provider); + + + if (!geoclue_provider_get_status (geoclue, &priv->status, &error)) { + g_warning ("Error getting provider status: %s\n", error->message); + g_error_free (error); + return FALSE; + } + return TRUE; +} + +static gboolean +gc_master_provider_initialize_interfaces (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv; + + priv = GET_PRIVATE (provider); + + if (priv->interfaces <= GC_IFACE_GEOCLUE) { + g_warning ("No interfaces defined for %s", priv->name); + return FALSE; + } + + if (priv->interfaces & GC_IFACE_POSITION) { + g_assert (priv->position == NULL); + + priv->position = geoclue_position_new (priv->service, + priv->path); + g_signal_connect (G_OBJECT (priv->position), "position-changed", + G_CALLBACK (position_changed), provider); + } + if (priv->interfaces & GC_IFACE_ADDRESS) { + g_assert (priv->address == NULL); + + priv->address = geoclue_address_new (priv->service, + priv->path); + g_signal_connect (G_OBJECT (priv->address), "address-changed", + G_CALLBACK (address_changed), provider); + } + + if (!gc_master_provider_initialize_geoclue (provider)) { + return FALSE; + } + + return TRUE; +} + + +static gboolean +gc_master_provider_initialize (GcMasterProvider *provider) +{ + if (!gc_master_provider_initialize_interfaces (provider)) { + return FALSE; + } + + gc_master_provider_update_cache (provider); +#if DEBUG_INFO + gc_master_provider_dump_provider_details (provider); +#endif + return TRUE; +} + +static void +gc_master_provider_deinitialize (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + if (priv->position) { + g_object_unref (priv->position); + priv->position = NULL; + } + if (priv->address) { + g_object_unref (priv->address); + priv->address = NULL; + } + g_debug ("deinited %s", priv->name); +} + +static void +network_status_changed (gpointer *connectivity, + GeoclueNetworkStatus status, + GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv; + + priv = GET_PRIVATE (provider); + + priv->net_status = status; + /* update connection-cacheable providers */ + if (status == GEOCLUE_CONNECTIVITY_ONLINE && + priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION) { + /* intialize to fill cache (this will handle status change) */ + if (gc_master_provider_initialize (provider)) { + gc_master_provider_deinitialize (provider); + } + } else { + gc_master_provider_handle_status_change (provider); + } +} + +/* for updating cache on providers that are not running */ +static gboolean +update_cache_and_deinit (GcMasterProvider *provider) +{ + /* fill cache */ + if (gc_master_provider_initialize (provider)) { + gc_master_provider_deinitialize (provider); + } + return FALSE; +} + + +/* public methods (for GcMaster and GcMasterClient) */ + +/* Loads provider details from 'filename' */ +GcMasterProvider * +gc_master_provider_new (const char *filename, + GeoclueConnectivity *connectivity) +{ + GcMasterProvider *provider; + GcMasterProviderPrivate *priv; + GKeyFile *keyfile; + GError *error = NULL; + gboolean ret; + char *accuracy_str; + char **flags, **interfaces; + + keyfile = g_key_file_new (); + ret = g_key_file_load_from_file (keyfile, filename, + G_KEY_FILE_NONE, &error); + if (ret == FALSE) { + g_warning ("Error loading %s: %s", filename, error->message); + g_error_free (error); + g_key_file_free (keyfile); + return NULL; + } + + provider = g_object_new (GC_TYPE_MASTER_PROVIDER, NULL); + priv = GET_PRIVATE (provider); + + priv->name = g_key_file_get_value (keyfile, "Geoclue Provider", + "Name", NULL); + priv->service = g_key_file_get_value (keyfile, "Geoclue Provider", + "Service", NULL); + priv->path = g_key_file_get_value (keyfile, "Geoclue Provider", + "Path", NULL); + + accuracy_str = g_key_file_get_value (keyfile, "Geoclue Provider", + "Accuracy", NULL); + priv->expected_accuracy = parse_accuracy_string (accuracy_str); + if (accuracy_str){ + g_free (accuracy_str); + } + + /* set cached accuracies to a default value */ + geoclue_accuracy_set_details (priv->position_cache.accuracy, + priv->expected_accuracy, 0.0, 0.0); + geoclue_accuracy_set_details (priv->address_cache.accuracy, + priv->expected_accuracy, 0.0, 0.0); + + + flags = g_key_file_get_string_list (keyfile, "Geoclue Provider", + "Requires", NULL, NULL); + if (flags != NULL) { + priv->required_resources = parse_resource_strings (flags); + g_strfreev (flags); + } else { + priv->required_resources = GEOCLUE_RESOURCE_NONE; + } + + flags = g_key_file_get_string_list (keyfile, "Geoclue Provider", + "Provides", NULL, NULL); + if (flags != NULL) { + priv->provides = parse_provide_strings (flags); + g_strfreev (flags); + } else { + priv->provides = GEOCLUE_PROVIDE_NONE; + } + + if (!connectivity && + (priv->required_resources & GEOCLUE_RESOURCE_NETWORK)) { + priv->provides &= ~GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION; + priv->net_status = GEOCLUE_CONNECTIVITY_ONLINE; + priv->status = GEOCLUE_STATUS_AVAILABLE; + gc_master_provider_handle_status_change (provider); + } + + if (connectivity && + (priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION)) { + + /* we have network status events: mark network provider + * with update flag, set the callback and set use_cache */ + priv->provides |= GEOCLUE_PROVIDE_UPDATES; + + g_signal_connect (connectivity, + "status-changed", + G_CALLBACK (network_status_changed), + provider); + priv->net_status = geoclue_connectivity_get_status (connectivity); + } + + priv->interfaces = GC_IFACE_GEOCLUE; + interfaces = g_key_file_get_string_list (keyfile, + "Geoclue Provider", + "Interfaces", + NULL, NULL); + if (interfaces) { + priv->interfaces = parse_interface_strings (interfaces); + g_strfreev (interfaces); + } + + if (priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION && + priv->net_status == GEOCLUE_CONNECTIVITY_ONLINE) { + /* do this as idle so we can return without waiting for http queries */ + g_idle_add ((GSourceFunc)update_cache_and_deinit, provider); + } + return provider; +} + +/* client calls this when it wants to use the provider. + Returns true if provider was actually started, and + client should assume accuracy has changed. + Returns false if provider was not started (it was either already + running or starting the provider failed). */ +gboolean +gc_master_provider_subscribe (GcMasterProvider *provider, + gpointer client, + GcInterfaceFlags interface) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + gboolean started = FALSE; + + /* decide wether to run initialize or not */ + if (!gc_master_provider_is_running (provider)) { + if (!(priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION)) { + started = gc_master_provider_initialize (provider); + } + } + + /* add subscription */ + if (interface & GC_IFACE_POSITION) { + if (!g_list_find (priv->position_clients, client)) { + priv->position_clients = g_list_prepend (priv->position_clients, client); + } + } + if (interface & GC_IFACE_ADDRESS) { + if (!g_list_find (priv->address_clients, client)) { + priv->address_clients = g_list_prepend (priv->address_clients, client); + } + } + + return started; +} + +/* client calls this when it does not intend to use the provider */ +void +gc_master_provider_unsubscribe (GcMasterProvider *provider, + gpointer client, + GcInterfaceFlags interface) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + if (interface & GC_IFACE_POSITION) { + priv->position_clients = g_list_remove (priv->position_clients, client); + } + if (interface & GC_IFACE_ADDRESS) { + priv->address_clients = g_list_remove (priv->address_clients, client); + } + + if (!priv->position_clients && + !priv->address_clients) { + /* no one is using this provider, shutdown... */ + /* not clearing cached accuracies on purpose */ + g_debug ("%s without clients", priv->name); + + /* gc_master_provider_deinitialize (provider); */ + } +} + + +GeocluePositionFields +gc_master_provider_get_position (GcMasterProvider *provider, + int *timestamp, + double *latitude, + double *longitude, + double *altitude, + GeoclueAccuracy **accuracy, + GError **error) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + g_assert (priv->position || + priv->provides & GEOCLUE_PROVIDE_CACHEABLE_ON_CONNECTION); + + if (priv->provides & GEOCLUE_PROVIDE_UPDATES) { + if (timestamp != NULL) { + *timestamp = priv->position_cache.timestamp; + } + if (latitude != NULL) { + *latitude = priv->position_cache.latitude; + } + if (longitude != NULL) { + *longitude = priv->position_cache.longitude; + } + if (altitude != NULL) { + *altitude = priv->position_cache.altitude; + } + if (accuracy != NULL) { + *accuracy = geoclue_accuracy_copy (priv->position_cache.accuracy); + } + if (error != NULL) { + g_assert (!*error); + copy_error (error, priv->position_cache.error); + } + return priv->position_cache.fields; + } else { + return geoclue_position_get_position (priv->position, + timestamp, + latitude, + longitude, + altitude, + accuracy, + error); + } +} + +gboolean +gc_master_provider_get_address (GcMasterProvider *provider, + int *timestamp, + GHashTable **details, + GeoclueAccuracy **accuracy, + GError **error) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + if (priv->provides & GEOCLUE_PROVIDE_UPDATES) { + + if (timestamp != NULL) { + *timestamp = priv->address_cache.timestamp; + } + if (details != NULL) { + *details = geoclue_address_details_copy (priv->address_cache.details); + } + if (accuracy != NULL) { + *accuracy = geoclue_accuracy_copy (priv->address_cache.accuracy); + } + if (error != NULL) { + g_assert (!*error); + copy_error (error, priv->address_cache.error); + } + return (!priv->address_cache.error); + } else { + g_assert (priv->address); + return geoclue_address_get_address (priv->address, + timestamp, + details, + accuracy, + error); + } +} + +gboolean +gc_master_provider_is_good (GcMasterProvider *provider, + GcInterfaceFlags iface_type, + GeoclueAccuracyLevel min_accuracy, + gboolean need_update, + GeoclueResourceFlags allowed_resources) +{ + GcMasterProviderPrivate *priv; + GcInterfaceFlags supported_ifaces; + GeoclueProvideFlags required_flags = GEOCLUE_PROVIDE_NONE; + + priv = GET_PRIVATE (provider); + + if (need_update) { + required_flags |= GEOCLUE_PROVIDE_UPDATES; + } + + supported_ifaces = priv->interfaces; + + /* provider must provide all that is required and + * cannot require a resource that is not allowed */ + /* TODO: really, we need to change some of those terms... */ + + return (((supported_ifaces & iface_type) == iface_type) && + ((priv->provides & required_flags) == required_flags) && + (priv->expected_accuracy >= min_accuracy) && + ((priv->required_resources & (~allowed_resources)) == 0)); +} + +void +gc_master_provider_update_options (GcMasterProvider *provider) +{ + GeoclueProvider *geoclue; + GError *error = NULL; + + geoclue = gc_master_provider_get_provider (provider); + + if (!geoclue_provider_set_options (geoclue, + geoclue_get_main_options (), + &error)) { + g_warning ("Error setting provider options: %s\n", error->message); + g_error_free (error); + } +} + +GeoclueStatus +gc_master_provider_get_status (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + return priv->master_status; +} + +GeoclueAccuracyLevel +gc_master_provider_get_accuracy (GcMasterProvider *provider, GcInterfaceFlags iface) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + GeoclueAccuracyLevel acc_level; + + switch (iface) { + case GC_IFACE_POSITION: + geoclue_accuracy_get_details (priv->position_cache.accuracy, + &acc_level, NULL, NULL); + break; + case GC_IFACE_ADDRESS: + geoclue_accuracy_get_details (priv->address_cache.accuracy, + &acc_level, NULL, NULL); + break; + default: + g_assert_not_reached (); + } + return acc_level; +} + +/*returns a reference, but is not meant for editing...*/ +char * +gc_master_provider_get_name (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + return priv->name; +} +char * +gc_master_provider_get_description (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + return priv->description; +} +char * +gc_master_provider_get_service (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + return priv->service; +} +char * +gc_master_provider_get_path (GcMasterProvider *provider) +{ + GcMasterProviderPrivate *priv = GET_PRIVATE (provider); + + return priv->path; +} + +/* GCompareDataFunc for sorting providers by accuracy and required resources */ +int +gc_master_provider_compare (GcMasterProvider *a, + GcMasterProvider *b, + GcInterfaceAccuracy *iface_min_accuracy) +{ + int diff; + GeoclueAccuracy *acc_a, *acc_b; + GeoclueAccuracyLevel level_a, level_b, min_level; + + + GcMasterProviderPrivate *priv_a = GET_PRIVATE (a); + GcMasterProviderPrivate *priv_b = GET_PRIVATE (b); + + /* get the current accuracylevels */ + switch (iface_min_accuracy->interface) { + case GC_IFACE_POSITION: + acc_a = priv_a->position_cache.accuracy; + acc_b = priv_b->position_cache.accuracy; + break; + case GC_IFACE_ADDRESS: + acc_a = priv_a->address_cache.accuracy; + acc_b = priv_b->address_cache.accuracy; + break; + default: + g_warning("iface: %d", iface_min_accuracy->interface); + g_assert_not_reached (); + } + + + geoclue_accuracy_get_details (acc_a, &level_a, NULL, NULL); + geoclue_accuracy_get_details (acc_b, &level_b, NULL, NULL); + min_level = iface_min_accuracy->accuracy_level; + + /* sort by resource requirements and accuracy, but only if both + * providers meet the minimum accuracy requirement */ + if ((level_b >= min_level) && + (level_a >= min_level)) { + diff = priv_a->required_resources - priv_b->required_resources; + if (diff != 0 ) { + return diff; + } + return level_b - level_a; + } + + /* one or both do not meet req's, sort by accuracy */ + return level_b - level_a; +} diff --git a/.pc/tizen.patch/src/master.c b/.pc/tizen.patch/src/master.c new file mode 100755 index 0000000..7877e61 --- /dev/null +++ b/.pc/tizen.patch/src/master.c @@ -0,0 +1,211 @@ +/* + * Geoclue + * master.c - Master process + * + * Authors: Iain Holmes <iain@openedhand.com> + * Jussi Kukkonen <jku@o-hand.com> + * Copyright 2007-2008 by Garmin Ltd. or its subsidiaries + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <config.h> + +#include <string.h> + +#include "main.h" +#include "master.h" +#include "client.h" +#include "master-provider.h" + +#ifdef HAVE_NETWORK_MANAGER +#include "connectivity-networkmanager.h" +#else +#ifdef HAVE_CONIC +#include "connectivity-conic.h" +#else +#ifdef HAVE_CONNMAN +#include "connectivity-connman.h" +#endif +#endif +#endif + +enum { + OPTIONS_CHANGED, + LAST_SIGNAL +}; + +static guint32 signals[LAST_SIGNAL] = {0, }; + +G_DEFINE_TYPE (GcMaster, gc_master, G_TYPE_OBJECT); + +static GList *providers = NULL; + +static gboolean gc_iface_master_create (GcMaster *master, + const char **object_path, + GError **error); + +#include "gc-iface-master-glue.h" + +#define GEOCLUE_MASTER_PATH "/org/freedesktop/Geoclue/Master/client" +static gboolean +gc_iface_master_create (GcMaster *master, + const char **object_path, + GError **error) +{ + static guint32 serial = 0; + GcMasterClient *client; + char *path; + + path = g_strdup_printf ("%s%d", GEOCLUE_MASTER_PATH, serial++); + client = g_object_new (GC_TYPE_MASTER_CLIENT, NULL); + dbus_g_connection_register_g_object (master->connection, path, + G_OBJECT (client)); + + if (object_path) { + *object_path = path; + } + return TRUE; +} + +static void +gc_master_class_init (GcMasterClass *klass) +{ + dbus_g_object_type_install_info (gc_master_get_type (), + &dbus_glib_gc_iface_master_object_info); + + signals[OPTIONS_CHANGED] = g_signal_new ("options-changed", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_FIRST | + G_SIGNAL_NO_RECURSE, + G_STRUCT_OFFSET (GcMasterClass, options_changed), + NULL, NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, 1, + G_TYPE_HASH_TABLE); +} + +/* Load the provider details out of a keyfile */ +static void +gc_master_add_new_provider (GcMaster *master, + const char *filename) +{ + GcMasterProvider *provider; + + provider = gc_master_provider_new (filename, + master->connectivity); + + if (!provider) { + g_warning ("Loading from %s failed", filename); + return; + } + + providers = g_list_prepend (providers, provider); +} + +/* Scan a directory for .provider files */ +#define PROVIDER_EXTENSION ".provider" + +static void +gc_master_load_providers (GcMaster *master) +{ + GDir *dir; + GError *error = NULL; + const char *filename; + + dir = g_dir_open (GEOCLUE_PROVIDERS_DIR, 0, &error); + if (dir == NULL) { + g_warning ("Error opening %s: %s\n", GEOCLUE_PROVIDERS_DIR, + error->message); + g_error_free (error); + return; + } + + filename = g_dir_read_name (dir); + if (!filename) { + g_print ("No providers found in %s\n", dir); + } else { + g_print ("Found providers:\n"); + } + while (filename) { + char *fullname, *ext; + + g_print (" %s\n", filename); + ext = strrchr (filename, '.'); + if (ext == NULL || strcmp (ext, PROVIDER_EXTENSION) != 0) { + g_print (" - Ignored\n"); + filename = g_dir_read_name (dir); + continue; + } + + fullname = g_build_filename (GEOCLUE_PROVIDERS_DIR, + filename, NULL); + gc_master_add_new_provider (master, fullname); + g_free (fullname); + + filename = g_dir_read_name (dir); + } + + g_dir_close (dir); +} + +static void +gc_master_init (GcMaster *master) +{ + GError *error = NULL; + + + master->connection = dbus_g_bus_get (GEOCLUE_DBUS_BUS, &error); + if (master->connection == NULL) { + g_warning ("Could not get %s: %s", GEOCLUE_DBUS_BUS, + error->message); + g_error_free (error); + } + + master->connectivity = geoclue_connectivity_new (); + + gc_master_load_providers (master); +} + + +GList * +gc_master_get_providers (GcInterfaceFlags iface_type, + GeoclueAccuracyLevel min_accuracy, + gboolean can_update, + GeoclueResourceFlags allowed, + GError **error) +{ + GList *l, *p = NULL; + + if (providers == NULL) { + return NULL; + } + + for (l = providers; l; l = l->next) { + GcMasterProvider *provider = l->data; + + if (gc_master_provider_is_good (provider, + iface_type, + min_accuracy, + can_update, + allowed)) { + p = g_list_prepend (p, provider); + } + } + + return p; +} diff --git a/.pc/tizen.patch/src/org.freedesktop.Geoclue.gschema.xml b/.pc/tizen.patch/src/org.freedesktop.Geoclue.gschema.xml new file mode 100755 index 0000000..94ff65d --- /dev/null +++ b/.pc/tizen.patch/src/org.freedesktop.Geoclue.gschema.xml @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8"?> +<schemalist> + <schema path="/apps/geoclue/" id="org.freedesktop.Geoclue"> + <key type="u" name="gps-baudrate"> + <default>0</default> + <summary>The baud rate for the attached GPS device</summary> + <description>The baud rate for the attached GPS device.</description> + </key> + <key type="s" name="gps-device"> + <default>''</default> + <summary>The device node or Bluetooth address for the attached GPS device</summary> + <description>The device node or Bluetooth address for the attached GPS device.</description> + </key> + </schema> +</schemalist> diff --git a/.pc/tizen.patch/src/test-connectivity.c b/.pc/tizen.patch/src/test-connectivity.c new file mode 100755 index 0000000..c8b7cf6 --- /dev/null +++ b/.pc/tizen.patch/src/test-connectivity.c @@ -0,0 +1,97 @@ + +#include <connectivity.h> + +static void +print_ap (gpointer key, + gpointer value, + gpointer data) +{ + g_message ("\t%s : %d dBm", + key, + GPOINTER_TO_INT (value)); +} + +static void +print_aps (GeoclueConnectivity *conn) +{ + GHashTable *ht; + + ht = geoclue_connectivity_get_aps (conn); + if (ht == NULL) { + g_message ("No Access Points available"); + return; + } + g_message ("APs:"); + g_hash_table_foreach (ht, print_ap, NULL); +} + +static void +print_if_avail (GeoclueConnectivity *self, + GeoclueNetworkStatus status) +{ + char *router, *ap; + if (status != GEOCLUE_CONNECTIVITY_ONLINE) + return; + print_aps (self); + ap = geoclue_connectivity_get_ap_mac (self); + g_message ("AP is '%s'", ap ? ap : "Unavailable"); + g_free (ap); + + router = geoclue_connectivity_get_router_mac (self); + g_message ("Router is '%s'", router); + g_free (router); +} + +static void +status_changed_cb (GeoclueConnectivity *self, + GeoclueNetworkStatus status, + gpointer data) +{ + const char *str; + + switch (status) { + case GEOCLUE_CONNECTIVITY_UNKNOWN: + str = "GEOCLUE_CONNECTIVITY_UNKNOWN"; + break; + case GEOCLUE_CONNECTIVITY_OFFLINE: + str = "GEOCLUE_CONNECTIVITY_OFFLINE"; + break; + case GEOCLUE_CONNECTIVITY_ACQUIRING: + str = "GEOCLUE_CONNECTIVITY_ACQUIRING"; + break; + case GEOCLUE_CONNECTIVITY_ONLINE: + str = "GEOCLUE_CONNECTIVITY_ONLINE"; + break; + default: + g_assert_not_reached (); + } + + g_message ("Connectivity status switch to '%s'", str); + + print_if_avail (self, status); +} + +int main (int argc, char **argv) +{ + GMainLoop *mainloop; + GeoclueConnectivity *conn; + char *router; + + g_type_init (); + mainloop = g_main_loop_new (NULL, FALSE); + conn = geoclue_connectivity_new (); + + if (conn == NULL) { + router = geoclue_connectivity_get_router_mac (conn); + g_message ("Router MAC is detected as '%s'", router ? router : "empty"); + + return 1; + } + print_if_avail (conn, geoclue_connectivity_get_status (conn)); + g_signal_connect (conn, "status-changed", + G_CALLBACK (status_changed_cb), NULL); + + g_main_loop_run (mainloop); + + return 0; +} diff --git a/.pc/tizen.patch/test/Makefile.am b/.pc/tizen.patch/test/Makefile.am new file mode 100755 index 0000000..4ca96e5 --- /dev/null +++ b/.pc/tizen.patch/test/Makefile.am @@ -0,0 +1,18 @@ +if HAVE_GTK + +noinst_PROGRAMS = geoclue-test-gui + +geoclue_test_gui_LDADD = \ + $(GTK_LIBS) \ + $(GEOCLUE_LIBS) \ + $(top_builddir)/geoclue/libgeoclue.la + +geoclue_test_gui_CFLAGS= \ + -DGEOCLUE_PROVIDERS_DIR=\""$(datadir)/geoclue-providers"\" \ + $(GTK_CFLAGS) \ + $(GEOCLUE_CFLAGS) + +geoclue_test_gui_SOURCES = \ + geoclue-test-gui.c + +endif diff --git a/.pc/tizen.patch/test/geoclue-test-gui.c b/.pc/tizen.patch/test/geoclue-test-gui.c new file mode 100755 index 0000000..c85452f --- /dev/null +++ b/.pc/tizen.patch/test/geoclue-test-gui.c @@ -0,0 +1,937 @@ +/* + * Geoclue + * client-test-gui.c - Geoclue Test GUI + * + * Authors: Jussi Kukkonen <jku@linux.intel.com> + * + * Copyright 2008 OpenedHand Ltd + * 2008 Intel Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include <time.h> +#include <string.h> + +#include <glib-object.h> +#include <gtk/gtk.h> + +#include <geoclue/geoclue-master.h> +#include <geoclue/geoclue-master-client.h> +#include <geoclue/geoclue-address.h> +#include <geoclue/geoclue-position.h> + +enum { + COL_ADDRESS_PROVIDER = 0, + COL_ADDRESS_PROVIDER_NAME, + COL_ADDRESS_IS_MASTER, + COL_ADDRESS_COUNTRY, + COL_ADDRESS_COUNTRYCODE, + COL_ADDRESS_REGION, + COL_ADDRESS_LOCALITY, + COL_ADDRESS_AREA, + COL_ADDRESS_POSTALCODE, + COL_ADDRESS_STREET, + NUM_ADDRESS_COLS +}; +enum { + COL_POSITION_PROVIDER = 0, + COL_POSITION_PROVIDER_NAME, + COL_POSITION_IS_MASTER, + COL_POSITION_LAT, + COL_POSITION_LON, + COL_POSITION_ALT, + NUM_POSITION_COLS +}; + + +#define GEOCLUE_TYPE_TEST_GUI geoclue_test_gui_get_type() +#define GEOCLUE_TEST_GUI(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GEOCLUE_TYPE_TEST_GUI, GeoclueTestGui)) +#define GEOCLUE_TEST_GUI_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GEOCLUE_TYPE_TEST_GUI, GeoclueTestGuiClass)) +#define GEOCLUE_TEST_GUI_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GEOCLUE_TYPE_TEST_GUI, GeoclueTestGuiClass)) + +typedef struct { + GObject parent; + + GtkWidget *window; + GtkTextBuffer *buffer; + + GeoclueMasterClient *client; + char *master_client_path; + GeoclueAccuracyLevel master_accuracy; + GeoclueResourceFlags master_resources; + + GtkListStore *position_store; + GList *position_providers; /* PositionProviders, first one is master */ + + GtkListStore *address_store; + GList *address_providers; /* AddressProviders, first one is master */ +} GeoclueTestGui; + +typedef struct { + GObjectClass parent_class; +} GeoclueTestGuiClass; + +G_DEFINE_TYPE (GeoclueTestGui, geoclue_test_gui, G_TYPE_OBJECT) + + +static void +geoclue_test_gui_dispose (GObject *object) +{ + + G_OBJECT_CLASS (geoclue_test_gui_parent_class)->dispose (object); +} + + +static void +geoclue_test_gui_class_init (GeoclueTestGuiClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = geoclue_test_gui_dispose; +} + + +static void +geoclue_test_gui_master_log_message (GeoclueTestGui *gui, char *message) +{ + GtkTextIter iter; + char *line; + time_t rawtime; + struct tm *timeinfo; + char time_buffer [20]; + + time (&rawtime); + timeinfo = localtime (&rawtime); + + strftime (time_buffer, 19, "%X", timeinfo); + line = g_strdup_printf ("%s: %s\n", time_buffer, message); + + gtk_text_buffer_get_end_iter (gui->buffer, &iter); + gtk_text_buffer_insert (gui->buffer, &iter, line, -1); + + g_free (line); +} + +static gboolean +get_matching_tree_iter (GtkTreeModel *model, GeoclueProvider *provider, GtkTreeIter *iter) +{ + GeoclueProvider *p = NULL; + gboolean valid; + + g_assert (model); + g_assert (provider); + + valid = gtk_tree_model_get_iter_first (model, iter); + while (valid) { + gtk_tree_model_get (model, iter, + COL_ADDRESS_PROVIDER, &p, + -1); + if (p == provider) { + return TRUE; + } + + valid = gtk_tree_model_iter_next (model, iter); + } + + return FALSE; +} + +static void +update_address (GeoclueTestGui *gui, GeoclueAddress *address, GHashTable *details) +{ + GtkTreeIter iter; + + g_assert (details); + + if (get_matching_tree_iter (GTK_TREE_MODEL (gui->address_store), + GEOCLUE_PROVIDER (address), + &iter)) { + gtk_list_store_set (gui->address_store, &iter, + COL_ADDRESS_COUNTRY, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_COUNTRY), + COL_ADDRESS_COUNTRYCODE, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_COUNTRYCODE), + COL_ADDRESS_REGION, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_REGION), + COL_ADDRESS_LOCALITY, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_LOCALITY), + COL_ADDRESS_AREA, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_AREA), + COL_ADDRESS_POSTALCODE, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_POSTALCODE), + COL_ADDRESS_STREET, g_hash_table_lookup (details, GEOCLUE_ADDRESS_KEY_STREET), + -1); + } +} + + +static void +update_position (GeoclueTestGui *gui, GeocluePosition *position, + double lat, double lon, double alt) +{ + GtkTreeIter iter; + + if (get_matching_tree_iter (GTK_TREE_MODEL (gui->position_store), + GEOCLUE_PROVIDER (position), + &iter)) { + gtk_list_store_set (gui->position_store, &iter, + COL_POSITION_LAT, lat, + COL_POSITION_LON, lon, + COL_POSITION_ALT, alt, + -1); + } +} + + +static void +address_changed (GeoclueAddress *address, + int timestamp, + GHashTable *details, + GeoclueAccuracy *accuracy, + GeoclueTestGui *gui) +{ + update_address (gui, address, details); +} + + +static void +position_changed (GeocluePosition *position, + GeocluePositionFields fields, + int timestamp, + double latitude, + double longitude, + double altitude, + GeoclueAccuracy *accuracy, + GeoclueTestGui *gui) +{ + update_position (gui, position, latitude, longitude, altitude); +} + +typedef struct { + GeoclueTestGui *gui; + char *name; +} cb_data; + +static void +position_callback (GeocluePosition *position, + GeocluePositionFields fields, + int timestamp, + double lat, double lon, double alt, + GeoclueAccuracy *accuracy, + GError *error, + cb_data *data) +{ + if (error) { + g_warning ("Error getting position from %s: %s\n", data->name, error->message); + g_error_free (error); + lat = lon = alt = 0.0/0.0; + } + + update_position (data->gui, position, lat, lon, alt); + + g_free (data->name); + g_free (data); +} + +static void +address_callback (GeoclueAddress *address, + int timestamp, + GHashTable *details, + GeoclueAccuracy *accuracy, + GError *error, + cb_data *data) +{ + if (error) { + g_warning ("Error getting address for %s: %s\n", data->name, error->message); + g_error_free (error); + details = geoclue_address_details_new (); + } + + update_address (data->gui, address, details); + + g_free (data->name); + g_free (data); +} + +static void +info_callback (GeoclueProvider *provider, + char *name, + char *description, + GError *error, + gpointer userdata) +{ + GtkTreeIter iter; + GeoclueTestGui *gui = GEOCLUE_TEST_GUI (userdata); + cb_data *data; + + if (error) { + g_warning ("Error getting provider info: %s\n", error->message); + g_error_free (error); + return; + } + + if (get_matching_tree_iter (GTK_TREE_MODEL (gui->address_store), + provider, + &iter)) { + /* skip master, that's handled in master_*_provider_changed */ + if (strcmp (name, "Geoclue Master") != 0) { + gtk_list_store_set (gui->address_store, &iter, + COL_ADDRESS_PROVIDER_NAME, name, + -1); + } + + data = g_new0 (cb_data, 1); + data->gui = gui; + data->name = g_strdup (name); + geoclue_address_get_address_async (GEOCLUE_ADDRESS (provider), + (GeoclueAddressCallback)address_callback, + data); + } + + if (get_matching_tree_iter (GTK_TREE_MODEL (gui->position_store), + provider, + &iter)) { + /* skip master, that's handled in master_*_provider_changed */ + if (strcmp (name, "Geoclue Master") != 0) { + gtk_list_store_set (gui->position_store, &iter, + COL_POSITION_PROVIDER_NAME, name, + -1); + } + + data = g_new0 (cb_data, 1); + data->gui = gui; + data->name = g_strdup (name); + geoclue_position_get_position_async (GEOCLUE_POSITION (provider), + (GeocluePositionCallback)position_callback, + data); + } +} + +static void +add_to_address_store (GeoclueTestGui *gui, GeoclueAddress *address, gboolean is_master) +{ + GtkTreeIter iter; + + g_assert (gui->address_store); + g_assert (address); + + if (is_master) { + /* master is already on the first line */ + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gui->address_store), &iter); + } else { + gtk_list_store_append (gui->address_store, &iter); + } + gtk_list_store_set (gui->address_store, &iter, + COL_ADDRESS_PROVIDER, address, + COL_ADDRESS_IS_MASTER, is_master, + -1); + + g_signal_connect (G_OBJECT (address), "address-changed", + G_CALLBACK (address_changed), gui); + + /* callback will call get_address */ + geoclue_provider_get_provider_info_async (GEOCLUE_PROVIDER (address), + info_callback, + gui); +} + +static gboolean +get_next_provider (GDir *dir, char **name, char **service, char **path, char **ifaces) +{ + const char *filename; + char *fullname; + GKeyFile *keyfile; + gboolean ret; + GError *error; + + filename = g_dir_read_name (dir); + if (!filename) { + return FALSE; + } + + fullname = g_build_filename (GEOCLUE_PROVIDERS_DIR, + filename, NULL); + keyfile = g_key_file_new (); + ret = g_key_file_load_from_file (keyfile, fullname, + G_KEY_FILE_NONE, &error); + g_free (fullname); + + if (!ret) { + g_warning ("Error loading %s: %s", filename, error->message); + g_error_free (error); + } else { + *name = g_key_file_get_value (keyfile, "Geoclue Provider", + "Name", NULL); + + *service = g_key_file_get_value (keyfile, "Geoclue Provider", + "Service", NULL); + *path = g_key_file_get_value (keyfile, "Geoclue Provider", + "Path", NULL); + *ifaces = g_key_file_get_value (keyfile, "Geoclue Provider", + "Interfaces", NULL); + } + + g_key_file_free (keyfile); + return TRUE; +} + +static void +add_to_position_store (GeoclueTestGui *gui, GeocluePosition *position, gboolean is_master) +{ + GtkTreeIter iter; + + g_assert (gui->position_store); + g_assert (position); + + if (is_master) { + /* master is already on the first line */ + gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gui->position_store), &iter); + } else { + gtk_list_store_append (gui->position_store, &iter); + } + gtk_list_store_set (gui->position_store, &iter, + COL_POSITION_PROVIDER, position, + COL_POSITION_IS_MASTER, is_master, + -1); + + g_signal_connect (G_OBJECT (position), "position-changed", + G_CALLBACK (position_changed), gui); + + /* callback will call get_position */ + geoclue_provider_get_provider_info_async (GEOCLUE_PROVIDER (position), + info_callback, + gui); +} + + +static GtkWidget * +get_address_tree_view (GeoclueTestGui *gui) +{ + GtkTreeView *view; + GtkCellRenderer *renderer; + + view = GTK_TREE_VIEW (gtk_tree_view_new ()); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + "Provider", + renderer, + "text", + COL_ADDRESS_PROVIDER_NAME, + NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + GEOCLUE_ADDRESS_KEY_COUNTRY, + renderer, + "text", + COL_ADDRESS_COUNTRY, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + GEOCLUE_ADDRESS_KEY_COUNTRYCODE, + renderer, + "text", + COL_ADDRESS_COUNTRYCODE, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + GEOCLUE_ADDRESS_KEY_REGION, + renderer, + "text", + COL_ADDRESS_REGION, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + GEOCLUE_ADDRESS_KEY_LOCALITY, + renderer, + "text", + COL_ADDRESS_LOCALITY, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + GEOCLUE_ADDRESS_KEY_AREA, + renderer, + "text", + COL_ADDRESS_AREA, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + GEOCLUE_ADDRESS_KEY_POSTALCODE, + renderer, + "text", + COL_ADDRESS_POSTALCODE, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + GEOCLUE_ADDRESS_KEY_STREET, + renderer, + "text", + COL_ADDRESS_STREET, + NULL); + + gui->address_store = gtk_list_store_new (NUM_ADDRESS_COLS, + G_TYPE_POINTER, + G_TYPE_STRING, + G_TYPE_BOOLEAN, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING, + G_TYPE_STRING); + + gtk_tree_view_set_model (view, GTK_TREE_MODEL(gui->address_store)); + + return GTK_WIDGET (view); +} + + +static GtkWidget * +get_position_tree_view (GeoclueTestGui *gui) +{ + GtkTreeView *view; + GtkCellRenderer *renderer; + + view = GTK_TREE_VIEW (gtk_tree_view_new ()); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + "Provider", + renderer, + "text", + COL_POSITION_PROVIDER_NAME, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + "latitude", + renderer, + "text", + COL_POSITION_LAT, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + "longitude", + renderer, + "text", + COL_POSITION_LON, + NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_insert_column_with_attributes (view, -1, + "altitude", + renderer, + "text", + COL_POSITION_ALT, + NULL); + + gui->position_store = gtk_list_store_new (NUM_POSITION_COLS, + G_TYPE_POINTER, + G_TYPE_STRING, + G_TYPE_BOOLEAN, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE, + G_TYPE_DOUBLE); + + gtk_tree_view_set_model (view, GTK_TREE_MODEL(gui->position_store)); + + return GTK_WIDGET (view); +} + +static void +master_position_provider_changed (GeoclueMasterClient *client, + char *name, + char *description, + char *service, + char *path, + GeoclueTestGui *gui) +{ + GtkTreeIter iter; + char *msg; + + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gui->position_store), + &iter)) { + gtk_list_store_set (gui->position_store, &iter, + COL_POSITION_PROVIDER_NAME, g_strdup_printf ("Master (%s)", name), + -1); + } + msg = g_strdup_printf ("Master: position provider changed: %s", name); + geoclue_test_gui_master_log_message (gui, msg); + g_free (msg); +} + +static void +master_address_provider_changed (GeoclueMasterClient *client, + char *name, + char *description, + char *service, + char *path, + GeoclueTestGui *gui) +{ + GtkTreeIter iter; + char *msg; + + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (gui->address_store), + &iter)) { + gtk_list_store_set (gui->address_store, &iter, + COL_ADDRESS_PROVIDER_NAME, g_strdup_printf ("Master (%s)", name), + -1); + } + msg = g_strdup_printf ("Master: address provider changed: %s", name); + geoclue_test_gui_master_log_message (gui, msg); + g_free (msg); +} + +static void +set_requirements_callback (GeoclueMasterClient *client, + GError *error, + gpointer userdata) +{ + if (error) { + g_printerr ("Setting requirements failed : %s", error->message); + g_error_free (error); + } +} + +static void +update_master_requirements (GeoclueTestGui *gui) +{ + geoclue_master_client_set_requirements_async (gui->client, + gui->master_accuracy, + 0, + FALSE, + gui->master_resources, + set_requirements_callback, + NULL); +} + +static void +create_address_callback (GeoclueMasterClient *client, + GeoclueAddress *address, + GError *error, + gpointer userdata) +{ + GeoclueTestGui *gui = GEOCLUE_TEST_GUI (userdata); + + if (error) { + g_printerr ("Master Client: Failed to create address: %s", error->message); + g_error_free (error); + return; + } + add_to_address_store (gui, address, TRUE); +} + +static void +create_position_callback (GeoclueMasterClient *client, + GeocluePosition *position, + GError *error, + gpointer userdata) +{ + GeoclueTestGui *gui = GEOCLUE_TEST_GUI (userdata); + + if (error) { + g_printerr ("Master Client: Failed to create position: %s", error->message); + g_error_free (error); + return; + } + add_to_position_store (gui, position, TRUE); +} + + +static void +create_client_callback (GeoclueMaster *master, + GeoclueMasterClient *client, + char *object_path, + GError *error, + gpointer userdata) +{ + GDir *dir; + char *name, *path, *service, *ifaces; + GtkTreeIter iter; + GeoclueTestGui *gui = GEOCLUE_TEST_GUI (userdata); + + if (error) { + g_printerr ("Failed to create master client: %s", error->message); + g_error_free (error); + return; + } + + gui->client = client; + + g_signal_connect (G_OBJECT (gui->client), "position-provider-changed", + G_CALLBACK (master_position_provider_changed), gui); + g_signal_connect (G_OBJECT (gui->client), "address-provider-changed", + G_CALLBACK (master_address_provider_changed), gui); + update_master_requirements (gui); + + /* add master providers to the lists */ + gtk_list_store_append (gui->position_store, &iter); + geoclue_master_client_create_position_async (gui->client, + create_position_callback, + gui); + gtk_list_store_append (gui->address_store, &iter); + geoclue_master_client_create_address_async (gui->client, + create_address_callback, + gui); + + /* add individual providers based on files in GEOCLUE_PROVIDERS_DIR */ + dir = g_dir_open (GEOCLUE_PROVIDERS_DIR, 0, &error); + if (!dir) { + g_warning ("Error opening %s: %s\n", + GEOCLUE_PROVIDERS_DIR, error->message); + g_error_free (error); + return; + } + + name = service = path = ifaces = NULL; + while (get_next_provider (dir, &name, &service, &path, &ifaces)) { + if (ifaces && strstr (ifaces, "org.freedesktop.Geoclue.Position")) { + add_to_position_store (gui, geoclue_position_new (service, path), FALSE); + } + if (ifaces && strstr (ifaces, "org.freedesktop.Geoclue.Address")) { + add_to_address_store (gui, geoclue_address_new (service, path), FALSE); + } + g_free (name); + g_free (path); + g_free (service); + g_free (ifaces); + } + + g_dir_close (dir); + g_object_unref (master); +} + +static void +geoclue_test_gui_load_providers (GeoclueTestGui *gui) +{ + GeoclueMaster *master; + + master = geoclue_master_get_default (); + geoclue_master_create_client_async (master, + create_client_callback, + gui); +} + +static void +accuracy_combo_changed (GtkComboBox *combo, GeoclueTestGui *gui) +{ + GtkTreeIter iter; + + if (gtk_combo_box_get_active_iter (combo, &iter)) { + GtkTreeModel *model; + + model = gtk_combo_box_get_model (combo); + gtk_tree_model_get (model, &iter, 0, &gui->master_accuracy, -1); + + update_master_requirements (gui); + } +} + +static void +gps_check_toggled (GtkCheckButton *btn, GeoclueTestGui *gui) +{ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn))) { + gui->master_resources |= GEOCLUE_RESOURCE_GPS; + } else { + gui->master_resources &= ~GEOCLUE_RESOURCE_GPS; + } + update_master_requirements (gui); +} + +static void +network_check_toggled (GtkCheckButton *btn, GeoclueTestGui *gui) +{ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn))) { + gui->master_resources |= GEOCLUE_RESOURCE_NETWORK; + } else { + gui->master_resources &= ~GEOCLUE_RESOURCE_NETWORK; + } + update_master_requirements (gui); +} + +static void +cell_check_toggled (GtkCheckButton *btn, GeoclueTestGui *gui) +{ + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (btn))) { + gui->master_resources |= GEOCLUE_RESOURCE_CELL; + } else { + gui->master_resources &= ~GEOCLUE_RESOURCE_CELL; + } + update_master_requirements (gui); +} + +static GtkWidget* +get_accuracy_combo (GeoclueTestGui *gui) +{ + GtkListStore *store; + GtkWidget *combo; + GtkTreeIter iter; + GtkCellRenderer *renderer; + + store = gtk_list_store_new (2, G_TYPE_UINT, G_TYPE_STRING); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, GEOCLUE_ACCURACY_LEVEL_COUNTRY, + 1, "Country", + -1); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, GEOCLUE_ACCURACY_LEVEL_REGION, + 1, "Region", + -1); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, GEOCLUE_ACCURACY_LEVEL_LOCALITY, + 1, "Locality", + -1); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, GEOCLUE_ACCURACY_LEVEL_POSTALCODE, + 1, "Postalcode", + -1); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, GEOCLUE_ACCURACY_LEVEL_STREET, + 1, "Street", + -1); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, GEOCLUE_ACCURACY_LEVEL_DETAILED, + 1, "Detailed", + -1); + + combo = gtk_combo_box_new_with_model (GTK_TREE_MODEL (store)); + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (combo), renderer, TRUE); + gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (combo), renderer, + "text", 1, NULL); + + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); + gui->master_accuracy = GEOCLUE_ACCURACY_LEVEL_COUNTRY; + + return combo; +} + + +static void +geoclue_test_gui_init (GeoclueTestGui *gui) +{ + GtkWidget *address_view; + GtkWidget *position_view; + GtkWidget *notebook; + GtkWidget *box; + GtkWidget *frame; + GtkWidget *hbox, *vbox; + GtkWidget *label; + GtkWidget *combo, *check; + GtkWidget *scrolled_win; + GtkWidget *view; + + gui->window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + g_signal_connect (G_OBJECT (gui->window), "destroy", + G_CALLBACK (gtk_main_quit), NULL); + + view = gtk_text_view_new (); + gtk_widget_set_size_request (GTK_WIDGET (view), 500, 200); + g_object_set (G_OBJECT (view), "editable", FALSE, NULL); + gui->buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); + + + box = gtk_vbox_new (FALSE, 8); + gtk_container_add (GTK_CONTAINER (gui->window), box); + + frame = gtk_frame_new ("Master settings"); + gtk_box_pack_start (GTK_BOX (box), frame, FALSE, FALSE, 4); + + + hbox = gtk_hbox_new (FALSE, 24); + gtk_container_add (GTK_CONTAINER (frame), hbox); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 8); + label = gtk_label_new ("Required accuracy level:"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + combo = get_accuracy_combo (gui); + g_signal_connect (combo, "changed", + G_CALLBACK (accuracy_combo_changed), gui); + gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0); + + vbox = gtk_vbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0); + label = gtk_label_new ("Allow resources:"); + gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0); + + check = gtk_check_button_new_with_label ("Network"); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), TRUE); + gui->master_resources |= GEOCLUE_RESOURCE_NETWORK; + g_signal_connect (check, "toggled", + G_CALLBACK (network_check_toggled), gui); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + + check = gtk_check_button_new_with_label ("GPS"); + g_signal_connect (check, "toggled", + G_CALLBACK (gps_check_toggled), gui); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + + check = gtk_check_button_new_with_label ("Cell"); + g_signal_connect (check, "toggled", + G_CALLBACK (cell_check_toggled), gui); + gtk_box_pack_start (GTK_BOX (vbox), check, FALSE, FALSE, 0); + + notebook = gtk_notebook_new (); + gtk_box_pack_start (GTK_BOX (box), notebook, FALSE, FALSE, 0); + gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), TRUE); + gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), TRUE); + + address_view = get_address_tree_view (gui); + label = gtk_label_new ("Address"); + gtk_notebook_append_page (GTK_NOTEBOOK (notebook), address_view, label); + + position_view = get_position_tree_view (gui); + label = gtk_label_new ("Position"); + gtk_notebook_append_page (GTK_NOTEBOOK (notebook), position_view, label); + + + hbox = gtk_hbox_new (FALSE, 0); + gtk_box_pack_start (GTK_BOX (box), hbox, FALSE, FALSE, 0); + label = gtk_label_new ("Master log"); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + scrolled_win = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win), + GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_container_add (GTK_CONTAINER (box), scrolled_win); + gtk_container_add (GTK_CONTAINER (scrolled_win), view); + + geoclue_test_gui_load_providers (gui); + + geoclue_test_gui_master_log_message (gui, "Started Geoclue test UI"); + + gtk_widget_show_all (gui->window); +} + + +int main (int argc, char **argv) +{ + GeoclueTestGui *gui; + + gtk_init (&argc, &argv); + + gui = g_object_new (GEOCLUE_TYPE_TEST_GUI, NULL); + gtk_main (); + + g_object_unref (gui); + + return 0; +} |