[gnome-clocks/wip/geolocation: 40/40] Port geolocation support to geoclue and geocode-glib



commit b644d9eb5e46574675f14ec7883edad63d384ad8
Author: Evgeny Bobkin <evgen ibqn gmail com>
Date:   Fri Sep 6 13:13:03 2013 +0200

    Port geolocation support to geoclue and geocode-glib

 Makefile.am                  |    8 +-
 configure.ac                 |    3 +-
 src/geoclue.vala             |  176 ++++++++++++++++++++++++++++++++++
 src/geocode-glib-1.0.vapi    |  214 ++++++++++++++++++++++++++++++++++++++++++
 src/geolocation-info.vala    |   61 ------------
 src/geolocation-monitor.vala |  151 -----------------------------
 src/geolocation-utils.vala   |   61 ------------
 src/world.vala               |   48 +++++-----
 8 files changed, 415 insertions(+), 307 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index de228bb..255a8c4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -94,9 +94,6 @@ AM_VALAFLAGS = \
        --pkg libcanberra \
        --pkg libnotify \
        --pkg gio-2.0 \
-       --pkg libsoup-2.4 \
-       --pkg json-glib-1.0 \
-       --thread \
        --gresources  $(top_srcdir)/data/gnome-clocks.gresource.xml
 
 bin_PROGRAMS = gnome-clocks
@@ -118,9 +115,7 @@ VALA_SOURCES = \
        src/timer.vala \
        src/utils.vala \
        src/widgets.vala \
-       src/geolocation-monitor.vala \
-       src/geolocation-info.vala \
-       src/geolocation-utils.vala \
+       src/geoclue.vala \
        src/main.vala
 
 gnome_clocks_SOURCES = \
@@ -128,6 +123,7 @@ gnome_clocks_SOURCES = \
        $(VALA_SOURCES) \
        src/cutils.c \
        src/gnome-desktop-3.0.vapi \
+       src/geocode-glib-1.0.vapi \
        src/config.vapi
 
 AM_CFLAGS = \
diff --git a/configure.ac b/configure.ac
index aedd1e1..9fc5557 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,8 +56,7 @@ PKG_CHECK_MODULES(CLOCKS, [
     gweather-3.0 >= 3.9.91
     gnome-desktop-3.0 >= 3.7.90
     libnotify >= 0.7.0
-    libsoup-2.4 >= 2.43.90
-    json-glib-1.0 >= 0.16.1
+    geocode-glib-1.0
 ])
 
 AC_CONFIG_FILES([
diff --git a/src/geoclue.vala b/src/geoclue.vala
new file mode 100644
index 0000000..afb2769
--- /dev/null
+++ b/src/geoclue.vala
@@ -0,0 +1,176 @@
+namespace Clocks {
+
+namespace GClue {
+
+[DBus (name = "org.freedesktop.GeoClue2.Manager")]
+private interface Manager : Object {
+    public abstract async void get_client (out string client_path) throws IOError;
+}
+
+[DBus (name = "org.freedesktop.GeoClue2.Client")]
+private interface Client : Object {
+    public abstract string location { owned get; }
+    public abstract uint distance_threshold { get; set; }
+    public abstract async void start () throws IOError;
+    public abstract async void stop () throws IOError;
+    public signal void location_updated (string old_path, string new_path);
+}
+
+[DBus (name = "org.freedesktop.GeoClue2.Location")]
+public interface Location : Object {
+    public abstract double latitude { get; }
+    public abstract double longitude { get; }
+    public abstract double accuracy { get; }
+    public abstract string description { owned get; }
+}
+
+public class GeoInfo : Object {
+    public signal void location_changed (GWeather.Location location);
+    public GClue.Location? geo_location { get; private set; default = null; }
+    private string? country_code;
+
+    public GeoInfo () {
+        country_code = null;
+    }
+
+    public async void seek () {
+        GClue.Manager manager;
+        GClue.Client client;
+
+        string? client_path = null;
+
+        try {
+            manager = yield Bus.get_proxy (GLib.BusType.SYSTEM,
+                                           "org.freedesktop.GeoClue2",
+                                           "/org/freedesktop/GeoClue2/Manager");
+        } catch (IOError e) {
+            warning ("Failed to connect to GeoClue2 Manager service: %s", e.message);
+            return;
+        }
+
+        try {
+            yield manager.get_client (out client_path);
+        } catch (IOError e) {
+            warning ("Failed to connect to GeoClue2 Manager service: %s", e.message);
+            return;
+        }
+
+        if (client_path == null) {
+            warning ("The client path is not set");
+            return;
+        }
+
+        try {
+            client = yield Bus.get_proxy (GLib.BusType.SYSTEM,
+                                          "org.freedesktop.GeoClue2",
+                                          client_path);
+        } catch (IOError e) {
+            warning ("Failed to connect to GeoClue2 Client service: %s", e.message);
+            return;
+        }
+
+        client.location_updated.connect (on_location_updated);
+
+        try {
+            yield client.start ();
+        } catch (IOError e) {
+            warning ("Failed to start client: %s", e.message);
+            return;
+        }
+    }
+
+    public async void on_location_updated (string old_path, string new_path) {
+        GClue.Location location;
+        try {
+            location = yield Bus.get_proxy (GLib.BusType.SYSTEM,
+                                            "org.freedesktop.GeoClue2",
+                                            new_path);
+        } catch (IOError e) {
+            warning ("Failed to connect to GeoClue2 Location service: %s", e.message);
+            return;
+        }
+
+        this.geo_location = location;
+
+        yield seek_country_code ();
+
+        location_changed (search_locations ());
+    }
+
+    private async void seek_country_code () {
+        Geocode.Location location = new Geocode.Location (geo_location.latitude, geo_location.longitude);
+        Geocode.Reverse reverse = new Geocode.Reverse.for_location (location);
+
+        try {
+            Geocode.Place place = yield reverse.resolve_async ();
+
+            country_code = place.get_country_code ();
+
+            // Reverse geocoding returns country code which is not uppercased
+            country_code = country_code.up ();
+        } catch (IOError e) {
+            warning ("Failed to obtain country code: %s", e.message);
+        }
+    }
+
+    private double deg_to_rad (double deg) {
+        return Math.PI / 180.0d * deg;
+    }
+
+    private double get_distance (double latitude1, double longitude1, double latitude2, double longitude2) {
+        const double radius = 6372.795;
+
+        double lat1 = deg_to_rad (latitude1);
+        double lat2 = deg_to_rad (latitude2);
+        double lon1 = deg_to_rad (longitude1);
+        double lon2 = deg_to_rad (longitude2);
+
+        return Math.acos (Math.cos (lat1) * Math.cos (lat2) * Math.cos (lon1 - lon2) + Math.sin (lat1) * 
Math.sin (lat2)) * radius;
+    }
+
+    private void search_locations_helper (GWeather.Location location, ref double minimal_distance,  ref 
GWeather.Location? found_location) {
+        if (this.country_code != null) {
+            string? loc_country_code = location.get_country ();
+            if (loc_country_code != null) {
+                if (loc_country_code != this.country_code) {
+                    return;
+                }
+            }
+        }
+
+        GWeather.Location? [] locations = location.get_children ();
+        if (locations != null) {
+            for (int i = 0; i < locations.length; i++) {
+                if (locations[i].get_level () == GWeather.LocationLevel.CITY) {
+                    if (locations[i].has_coords ()) {
+                        double latitude, longitude, distance;
+
+                        locations[i].get_coords (out latitude, out longitude);
+                        distance = get_distance (geo_location.latitude, geo_location.longitude, latitude, 
longitude);
+
+                        if (distance < minimal_distance) {
+                            found_location = locations[i];
+                            minimal_distance = distance;
+                        }
+                    }
+                }
+
+                search_locations_helper (locations[i], ref minimal_distance, ref found_location);
+            }
+        }
+    }
+
+    private GWeather.Location? search_locations () {
+        GWeather.Location locations = GWeather.Location.get_world ();
+        GWeather.Location? found_location = null;
+        double minimal_distance = 1000.0d;
+
+        search_locations_helper (locations, ref minimal_distance, ref found_location);
+
+        return found_location;
+    }
+}
+
+} // GClue
+
+} // Clocks
diff --git a/src/geocode-glib-1.0.vapi b/src/geocode-glib-1.0.vapi
new file mode 100644
index 0000000..54d029e
--- /dev/null
+++ b/src/geocode-glib-1.0.vapi
@@ -0,0 +1,214 @@
+/* geocode-glib-1.0.vapi generated by vapigen, AND modifyied by me!!! */
+
+[CCode (cprefix = "Geocode", gir_namespace = "GeocodeGlib", gir_version = "1.0", lower_case_cprefix = 
"geocode__")]
+namespace Geocode {
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", type_id = "geocode_forward_get_type ()")]
+       public class Forward : GLib.Object {
+               [CCode (has_construct_function = false)]
+               protected Forward ();
+               [CCode (cname = "geocode_forward_new_for_params", has_construct_function = false)]
+               public Forward.for_params (GLib.HashTable<string,GLib.Value?> @params);
+               [CCode (cname = "geocode_forward_new_for_string", has_construct_function = false)]
+               public Forward.for_string (string str);
+               [CCode (cname = "geocode_forward_search")]
+               public GLib.List<weak Geocode.Place> search () throws GLib.IOError;
+               [CCode (cname = "geocode_forward_search_async")]
+               public async GLib.List<weak Geocode.Place> search_async (GLib.Cancellable? cancellable = 
null) throws GLib.IOError;
+               [CCode (cname = "geocode_forward_set_answer_count")]
+               public void set_answer_count (uint count);
+       }
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", type_id = "geocode_location_get_type ()")]
+       public class Location : GLib.Object {
+               [CCode (cname = "geocode_location_new", has_construct_function = false)]
+               public Location (double latitude, double longitude, double accuracy = 
Geocode.LOCATION_ACCURACY_UNKNOWN);
+               [CCode (cname = "geocode_location_get_accuracy")]
+               public double get_accuracy ();
+               [CCode (cname = "geocode_location_get_description")]
+               public unowned string get_description ();
+               [CCode (cname = "geocode_location_get_distance_from")]
+               public double get_distance_from (Geocode.Location locb);
+               [CCode (cname = "geocode_location_get_latitude")]
+               public double get_latitude ();
+               [CCode (cname = "geocode_location_get_longitude")]
+               public double get_longitude ();
+               [CCode (cname = "geocode_location_get_timestamp")]
+               public uint64 get_timestamp ();
+               [CCode (cname = "geocode_location_set_description")]
+               public void set_description (string description);
+               [CCode (cname = "geocode_location_new_with_description", has_construct_function = false)]
+               public Location.with_description (double latitude, double longitude, double accuracy, string 
description);
+               [NoAccessorMethod]
+               public double accuracy { get; construct; }
+               [NoAccessorMethod]
+               public string description { owned get; set; }
+               [NoAccessorMethod]
+               public double latitude { get; construct; }
+               [NoAccessorMethod]
+               public double longitude { get; construct; }
+               [NoAccessorMethod]
+               public uint64 timestamp { get; }
+       }
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", type_id = "geocode_place_get_type ()")]
+       public class Place : GLib.Object {
+               [CCode (cname = "geocode_place_new", has_construct_function = false)]
+               public Place (string name, Geocode.PlaceType place_type);
+               [CCode (cname = "geocode_place_get_administrative_area")]
+               public unowned string get_administrative_area ();
+               [CCode (cname = "geocode_place_get_area")]
+               public unowned string get_area ();
+               [CCode (cname = "geocode_place_get_building")]
+               public unowned string get_building ();
+               [CCode (cname = "geocode_place_get_continent")]
+               public unowned string get_continent ();
+               [CCode (cname = "geocode_place_get_country")]
+               public unowned string get_country ();
+               [CCode (cname = "geocode_place_get_country_code")]
+               public unowned string get_country_code ();
+               [CCode (cname = "geocode_place_get_county")]
+               public unowned string get_county ();
+               [CCode (cname = "geocode_place_get_location")]
+               public unowned Geocode.Location get_location ();
+               [CCode (cname = "geocode_place_get_name")]
+               public unowned string get_name ();
+               [CCode (cname = "geocode_place_get_place_type")]
+               public Geocode.PlaceType get_place_type ();
+               [CCode (cname = "geocode_place_get_postal_code")]
+               public unowned string get_postal_code ();
+               [CCode (cname = "geocode_place_get_state")]
+               public unowned string get_state ();
+               [CCode (cname = "geocode_place_get_street")]
+               public unowned string get_street ();
+               [CCode (cname = "geocode_place_get_street_address")]
+               public unowned string get_street_address ();
+               [CCode (cname = "geocode_place_get_town")]
+               public unowned string get_town ();
+               [CCode (cname = "geocode_place_set_administrative_area")]
+               public void set_administrative_area (string admin_area);
+               [CCode (cname = "geocode_place_set_area")]
+               public void set_area (string area);
+               [CCode (cname = "geocode_place_set_building")]
+               public void set_building (string building);
+               [CCode (cname = "geocode_place_set_continent")]
+               public void set_continent (string continent);
+               [CCode (cname = "geocode_place_set_country")]
+               public void set_country (string country);
+               [CCode (cname = "geocode_place_set_country_code")]
+               public void set_country_code (string country_code);
+               [CCode (cname = "geocode_place_set_county")]
+               public void set_county (string county);
+               [CCode (cname = "geocode_place_set_location")]
+               public void set_location (Geocode.Location location);
+               [CCode (cname = "geocode_place_set_name")]
+               public void set_name (string name);
+               [CCode (cname = "geocode_place_set_postal_code")]
+               public void set_postal_code (string postal_code);
+               [CCode (cname = "geocode_place_set_state")]
+               public void set_state (string state);
+               [CCode (cname = "geocode_place_set_street")]
+               public void set_street (string street);
+               [CCode (cname = "geocode_place_set_street_address")]
+               public void set_street_address (string street_address);
+               [CCode (cname = "geocode_place_set_town")]
+               public void set_town (string town);
+               [CCode (cname = "geocode_place_new_with_location", has_construct_function = false)]
+               public Place.with_location (string name, Geocode.PlaceType place_type, Geocode.Location 
location);
+               [NoAccessorMethod]
+               public string administrative_area { owned get; set; }
+               [NoAccessorMethod]
+               public string area { owned get; set; }
+               [NoAccessorMethod]
+               public string building { owned get; set; }
+               [NoAccessorMethod]
+               public string continent { owned get; set; }
+               [NoAccessorMethod]
+               public string country { owned get; set; }
+               [NoAccessorMethod]
+               public string country_code { owned get; set; }
+               [NoAccessorMethod]
+               public string county { owned get; set; }
+               [NoAccessorMethod]
+               public GLib.Icon icon { owned get; set; }
+               [NoAccessorMethod]
+               public Geocode.Location location { owned get; set; }
+               [NoAccessorMethod]
+               public string name { owned get; set; }
+               [NoAccessorMethod]
+               public Geocode.PlaceType place_type { get; construct; }
+               [NoAccessorMethod]
+               public string postal_code { owned get; set; }
+               [NoAccessorMethod]
+               public string state { owned get; set; }
+               [NoAccessorMethod]
+               public string street { owned get; set; }
+               [NoAccessorMethod]
+               public string street_address { owned get; set; }
+               [NoAccessorMethod]
+               public string town { owned get; set; }
+       }
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", type_id = "geocode_reverse_get_type ()")]
+       public class Reverse : GLib.Object {
+               [CCode (has_construct_function = false)]
+               protected Reverse ();
+               [CCode (cname = "geocode_reverse_new_for_location", has_construct_function = false)]
+               public Reverse.for_location (Geocode.Location location);
+               [CCode (cname = "geocode_reverse_resolve")]
+               public Geocode.Place resolve () throws GLib.Error;
+               [CCode (cname = "geocode_reverse_resolve_async")]
+               public async Geocode.Place resolve_async (GLib.Cancellable? cancellable = null) throws 
GLib.IOError;
+       }
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cprefix = "GEOCODE_PLACE_TYPE_", type_id = 
"geocode_place_type_get_type ()")]
+       public enum PlaceType {
+               UNKNOWN,
+               BUILDING,
+               STREET,
+               TOWN,
+               STATE,
+               COUNTY,
+               LOCAL_ADMINISTRATIVE_AREA,
+               POSTAL_CODE,
+               COUNTRY,
+               ISLAND,
+               AIRPORT,
+               RAILWAY_STATION,
+               BUS_STOP,
+               MOTORWAY,
+               DRAINAGE,
+               LAND_FEATURE,
+               MISCELLANEOUS,
+               SUPERNAME,
+               POINT_OF_INTEREST,
+               SUBURB,
+               COLLOQUIAL,
+               ZONE,
+               HISTORICAL_STATE,
+               HISTORICAL_COUNTY,
+               CONTINENT,
+               TIME_ZONE,
+               ESTATE,
+               HISTORICAL_TOWN,
+               OCEAN,
+               SEA
+       }
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cprefix = "GEOCODE_ERROR_")]
+       public errordomain Error {
+               PARSE,
+               NOT_SUPPORTED,
+               NO_MATCHES,
+               INVALID_ARGUMENTS,
+               INTERNAL_SERVER
+       }
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cname = "GEOCODE_LOCATION_ACCURACY_CITY")]
+       public const int LOCATION_ACCURACY_CITY;
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cname = 
"GEOCODE_LOCATION_ACCURACY_CONTINENT")]
+       public const int LOCATION_ACCURACY_CONTINENT;
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cname = 
"GEOCODE_LOCATION_ACCURACY_COUNTRY")]
+       public const int LOCATION_ACCURACY_COUNTRY;
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cname = "GEOCODE_LOCATION_ACCURACY_REGION")]
+       public const int LOCATION_ACCURACY_REGION;
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cname = "GEOCODE_LOCATION_ACCURACY_STREET")]
+       public const int LOCATION_ACCURACY_STREET;
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cname = 
"GEOCODE_LOCATION_ACCURACY_UNKNOWN")]
+       public const int LOCATION_ACCURACY_UNKNOWN;
+       [CCode (cheader_filename = "geocode-glib/geocode-glib.h", cname = "geocode_error_quark")]
+       public static GLib.Quark error_quark ();
+}
diff --git a/src/world.vala b/src/world.vala
index cb3d619..8f5674d 100644
--- a/src/world.vala
+++ b/src/world.vala
@@ -362,36 +362,32 @@ public class MainPanel : Gtk.Stack, Clocks.Clock {
     }
 
     private async void use_geolocation () {
-        GeoInfo.LocationInfo? geo_location = null;
-        GWeather.Location? found_location = null;
-
-        GeoInfo.LocationMonitor monitor = new GeoInfo.LocationMonitor ();
-
-        try {
-            geo_location = yield monitor.search ();
-
-            found_location = GeoInfo.Utils.search_locations (geo_location);
-        } catch (IOError e) {
-            warning ("obtaining geolocation: %s", e.message);
-        }
-
-        if (found_location != null) {
-            bool not_included = true;
+        GClue.GeoInfo geo_info = new GClue.GeoInfo ();
+        
+        geo_info.location_changed.connect ((found_location) => {
+            if (found_location != null) {
+                bool not_included = true;
+            
+                stdout.printf ("name : %s\n", found_location.get_name());
+
+                foreach (Item i in locations) {
+                    stdout.printf ("name : %s\n", i.location.get_name());
+                    if (i.location == found_location) {
+                        not_included = false;
+                    }
+                }
 
-            foreach (Item i in locations) {
-                if (i.location == found_location) {
-                    not_included = false;
+                if (not_included) {
+                    var item = new Item (found_location);
+                    
+                    item.automatic = true;
+                    locations.append (item);
+                    content_view.add_first (item);
                 }
             }
+        });
 
-            if (not_included) {
-                var item = new Item (found_location);
-
-                item.automatic = true;
-                locations.append (item);
-                content_view.add_first (item);
-            }
-        }
+        yield geo_info.seek ();
     }
 
     public void activate_new () {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]