]> git.street.me.uk Git - andy/viking.git/blobdiff - src/bingmapsource.c
Add function to return counts of available routing engines.
[andy/viking.git] / src / bingmapsource.c
index 81ba1fd472838791dd112aa9e737473b8f79bcff..c999ac754aa6f6215246c1bcae432dc72a41bbf9 100644 (file)
@@ -5,7 +5,7 @@
  * 
  * viking is free software: you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
- * Free Software Foundation, either version 3 of the License, or
+ * Free Software Foundation, either version 2 of the License, or
  * (at your option) any later version.
  * 
  * viking is distributed in the hope that it will be useful, but
@@ -55,7 +55,8 @@
 /* Format for URL */
 #define URL_ATTR_FMT "http://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/0,0?zl=1&mapVersion=v1&key=%s&include=ImageryProviders&output=xml"
 
-static gchar *_get_uri ( VikMapSourceDefault *self, MapCoord *src );
+static gchar *bget_uri ( VikMapSourceDefault *self, MapCoord *src );
+static gchar *bget_hostname ( VikMapSourceDefault *self );
 static void _get_copyright (VikMapSource * self, LatLonBBox bbox, gdouble zoom, void (*fct)(VikViewport*,const gchar*), void *data);
 static const GdkPixbuf *_get_logo ( VikMapSource *self );
 static int _load_attributions ( BingMapSource *self );
@@ -72,10 +73,13 @@ struct _Attribution
 typedef struct _BingMapSourcePrivate BingMapSourcePrivate;
 struct _BingMapSourcePrivate
 {
+       gchar *hostname;
+       gchar *url;
        gchar *api_key;
        GList *attributions;
        /* Current attribution, when parsing */
        gchar *attribution;
+       gboolean loading_attributions;
 };
 
 /* The pixbuf to store the logo */
@@ -88,6 +92,8 @@ enum
 {
        PROP_0,
 
+       PROP_HOSTNAME,
+       PROP_URL,
        PROP_API_KEY,
 };
 
@@ -99,9 +105,12 @@ bing_map_source_init (BingMapSource *self)
        /* initialize the object here */
        BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self);
 
+       priv->hostname = NULL;
+       priv->url = NULL;
        priv->api_key = NULL;
        priv->attributions = NULL;
        priv->attribution = NULL;
+       priv->loading_attributions = FALSE;
 }
 
 static void
@@ -110,6 +119,10 @@ bing_map_source_finalize (GObject *object)
        BingMapSource *self = BING_MAP_SOURCE (object);
        BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self);
 
+       g_free (priv->hostname);
+       priv->hostname = NULL;
+       g_free (priv->url);
+       priv->url = NULL;
        g_free (priv->api_key);
        priv->api_key = NULL;
 
@@ -127,6 +140,16 @@ _set_property (GObject      *object,
 
        switch (property_id)
        {
+       case PROP_HOSTNAME:
+               g_free (priv->hostname);
+               priv->hostname = g_value_dup_string (value);
+               break;
+
+       case PROP_URL:
+               g_free (priv->url);
+               priv->url = g_value_dup_string (value);
+               break;
+
        case PROP_API_KEY:
                priv->api_key = g_strdup (g_value_get_string (value));
                break;
@@ -149,6 +172,14 @@ _get_property (GObject    *object,
 
        switch (property_id)
        {
+       case PROP_HOSTNAME:
+               g_value_set_string (value, priv->hostname);
+               break;
+
+       case PROP_URL:
+               g_value_set_string (value, priv->url);
+               break;
+
        case PROP_API_KEY:
                g_value_set_string (value, priv->api_key);
                break;
@@ -168,14 +199,29 @@ bing_map_source_class_init (BingMapSourceClass *klass)
        VikMapSourceDefaultClass* grandparent_class = VIK_MAP_SOURCE_DEFAULT_CLASS (klass);
        VikMapSourceClass* base_class = VIK_MAP_SOURCE_CLASS (klass);
        GParamSpec *pspec = NULL;
-               
+
        /* Overiding methods */
        object_class->set_property = _set_property;
        object_class->get_property = _get_property;
-       grandparent_class->get_uri = _get_uri;
+       grandparent_class->get_uri = bget_uri;
+       grandparent_class->get_hostname = bget_hostname;
        base_class->get_logo      = _get_logo;
        base_class->get_copyright = _get_copyright;
 
+       pspec = g_param_spec_string ("hostname",
+                                    "Hostname",
+                                    "The hostname of the map server",
+                                    "<no-set>" /* default value */,
+                                    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+       g_object_class_install_property (object_class, PROP_HOSTNAME, pspec);
+
+       pspec = g_param_spec_string ("url",
+                                    "URL",
+                                    "The template of the tiles' URL",
+                                    "<no-set>" /* default value */,
+                                    G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+       g_object_class_install_property (object_class, PROP_URL, pspec);
+
        pspec = g_param_spec_string ("api-key",
                                      "API key",
                                      "The API key to access Bing",
@@ -214,17 +260,26 @@ compute_quad_tree(int zoom, int tilex, int tiley)
 }
 
 static gchar *
-_get_uri( VikMapSourceDefault *self, MapCoord *src )
+bget_uri( VikMapSourceDefault *self, MapCoord *src )
 {
        g_return_val_if_fail (BING_IS_MAP_SOURCE(self), NULL);
 
-       /* BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE(self); */
+       BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE(self);
        gchar *quadtree = compute_quad_tree (17 - src->scale, src->x, src->y);
-       gchar *uri = g_strdup_printf ( "/tiles/a%s.%s?g=587", quadtree, "jpeg");
+       gchar *uri = g_strdup_printf ( priv->url, quadtree );
        g_free (quadtree);
        return uri;
 } 
 
+static gchar *
+bget_hostname( VikMapSourceDefault *self )
+{
+       g_return_val_if_fail (BING_IS_MAP_SOURCE(self), NULL);
+
+       BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE(self);
+       return g_strdup( priv->hostname );
+}
+
 static const GdkPixbuf *
 _get_logo( VikMapSource *self )
 {
@@ -243,8 +298,12 @@ _get_copyright(VikMapSource * self, LatLonBBox bbox, gdouble zoom, void (*fct)(V
 
        /* Loop over all known attributions */
        GList *attribution = priv->attributions;
-       if (attribution == NULL) {
-               _async_load_attributions (BING_MAP_SOURCE (self));
+       if (attribution == NULL && g_strcmp0 ("<no-set>", priv->api_key)) {
+               if ( ! priv->loading_attributions )
+                       _async_load_attributions (BING_MAP_SOURCE (self));
+               else
+                       // Wait until attributions loaded before processing them
+                       return;
        }
        while (attribution != NULL) {
                struct _Attribution *current = (struct _Attribution*)attribution->data;
@@ -261,7 +320,7 @@ _get_copyright(VikMapSource * self, LatLonBBox bbox, gdouble zoom, void (*fct)(V
 
 /* Called for open tags <foo bar="baz"> */
 static void
-_start_element (GMarkupParseContext *context,
+bstart_element (GMarkupParseContext *context,
                 const gchar         *element_name,
                 const gchar        **attribute_names,
                 const gchar        **attribute_values,
@@ -273,7 +332,7 @@ _start_element (GMarkupParseContext *context,
        const gchar *element = g_markup_parse_context_get_element (context);
        if (strcmp (element, "CoverageArea") == 0) {
                /* New Attribution */
-               struct _Attribution *attribution = g_malloc (sizeof(struct _Attribution));
+               struct _Attribution *attribution = g_malloc0 (sizeof(struct _Attribution));
                priv->attributions = g_list_append (priv->attributions, attribution);
                attribution->attribution = g_strdup (priv->attribution);
        }
@@ -282,7 +341,7 @@ _start_element (GMarkupParseContext *context,
 /* Called for character data */
 /* text is not nul-terminated */
 static void
-_text (GMarkupParseContext *context,
+btext (GMarkupParseContext *context,
        const gchar         *text,
        gsize                text_len,  
        gpointer             user_data,
@@ -298,33 +357,31 @@ _text (GMarkupParseContext *context,
        int len = g_slist_length ((GSList *)stack);
 
        const gchar *parent = len > 1 ? g_slist_nth_data ((GSList *)stack, 1) : NULL;
-       
        if (strcmp (element, "Attribution") == 0) {
                g_free (priv->attribution);
                priv->attribution = g_strdup (textl);
-       } else if (parent != NULL && strcmp (parent, "CoverageArea") == 0) {
-               if (strcmp (element, "ZoomMin") == 0) {
-                       attribution->minZoom = atoi (textl);
-               } else if (strcmp (element, "ZoomMax") == 0) {
-                       attribution->maxZoom = atoi (textl);
-               }
-       } else if (parent != NULL && strcmp (parent, "BoundingBox") == 0) {
-               if (strcmp (element, "SouthLatitude") == 0) {
-                       attribution->bounds.south = g_ascii_strtod (textl, NULL);
-               } else if (strcmp (element, "WestLongitude") == 0) {
-                       attribution->bounds.west = g_ascii_strtod (textl, NULL);
-               } else if (strcmp (element, "NorthLatitude") == 0) {
-                       attribution->bounds.north = g_ascii_strtod (textl, NULL);
-               } else if (strcmp (element, "EastLongitude") == 0) {
-                       attribution->bounds.east = g_ascii_strtod (textl, NULL);
+       }
+       else {
+               if ( attribution ) {
+                       if (parent != NULL && strcmp (parent, "CoverageArea") == 0) {
+                               if (strcmp (element, "ZoomMin") == 0) {
+                                       attribution->minZoom = atoi (textl);
+                               } else if (strcmp (element, "ZoomMax") == 0) {
+                                       attribution->maxZoom = atoi (textl);
+                               }
+                       } else if (parent != NULL && strcmp (parent, "BoundingBox") == 0) {
+                               if (strcmp (element, "SouthLatitude") == 0) {
+                                       attribution->bounds.south = g_ascii_strtod (textl, NULL);
+                               } else if (strcmp (element, "WestLongitude") == 0) {
+                                       attribution->bounds.west = g_ascii_strtod (textl, NULL);
+                               } else if (strcmp (element, "NorthLatitude") == 0) {
+                                       attribution->bounds.north = g_ascii_strtod (textl, NULL);
+                               } else if (strcmp (element, "EastLongitude") == 0) {
+                                       attribution->bounds.east = g_ascii_strtod (textl, NULL);
+                               }
+                       }
                }
        }
-       if (attribution)
-               g_debug("Current attribution %s from %d to %d %g %g %g %g",
-                       attribution->attribution,
-                       attribution->minZoom, attribution->maxZoom,
-                       attribution->bounds.south, attribution->bounds.north, attribution->bounds.west, attribution->bounds.east);
-
        g_free(textl);
 }
 
@@ -343,9 +400,9 @@ _parse_file_for_attributions(BingMapSource *self, gchar *filename)
                return FALSE;
        
        /* setup context parse (ie callbacks) */
-       xml_parser.start_element = &_start_element;
+       xml_parser.start_element = &bstart_element;
        xml_parser.end_element = NULL;
-       xml_parser.text = &_text;
+       xml_parser.text = &btext;
        xml_parser.passthrough = NULL;
        xml_parser.error = NULL;
        
@@ -385,6 +442,15 @@ _parse_file_for_attributions(BingMapSource *self, gchar *filename)
        xml_context = NULL;
        fclose (file);
 
+       if (vik_debug) {
+               GList *attribution = priv->attributions;
+               while (attribution != NULL) {
+                       struct _Attribution *aa = (struct _Attribution*)attribution->data;
+                       g_debug ("Bing Attribution: %s from %d to %d %g %g %g %g", aa->attribution, aa->minZoom, aa->maxZoom, aa->bounds.south, aa->bounds.north, aa->bounds.east, aa->bounds.west);
+                       attribution = attribution->next;
+               }
+       }
+
        return TRUE;
 }
 
@@ -394,20 +460,25 @@ _load_attributions ( BingMapSource *self )
        int ret = 0;  /* OK */
 
        BingMapSourcePrivate *priv = BING_MAP_SOURCE_GET_PRIVATE (self);
+       priv->loading_attributions = TRUE;
        gchar *uri = g_strdup_printf(URL_ATTR_FMT, priv->api_key);
 
        gchar *tmpname = a_download_uri_to_tmp_file ( uri, vik_map_source_default_get_download_options(VIK_MAP_SOURCE_DEFAULT(self)) );
+       if ( !tmpname ) {
+               ret = -1;
+               goto done;
+       }
 
        g_debug("%s: %s", __FUNCTION__, tmpname);
        if (!_parse_file_for_attributions(self, tmpname)) {
                ret = -1;
-               goto done;
        }
 
+       (void)g_remove(tmpname);
+       g_free(tmpname);
 done:
+       priv->loading_attributions = FALSE;
        g_free(uri);
-       g_remove(tmpname);
-       g_free(tmpname);
        return ret;
 }
 
@@ -442,13 +513,14 @@ _load_attributions_thread ( BingMapSource *self, gpointer threaddata )
 static void
 _async_load_attributions ( BingMapSource *self )
 {
-       a_background_thread ( /*VIK_GTK_WINDOW_FROM_WIDGET(vp)*/NULL,
-                           _("Bing attribution Loading"),
-                           (vik_thr_func) _load_attributions_thread,
-                           self,
-                           NULL,
-                           NULL,
-                           1 );
+       a_background_thread ( BACKGROUND_POOL_REMOTE,
+                             /*VIK_GTK_WINDOW_FROM_WIDGET(vp)*/NULL,
+                             _("Bing attribution Loading"),
+                             (vik_thr_func) _load_attributions_thread,
+                             self,
+                             NULL,
+                             NULL,
+                             1 );
      
 }
 
@@ -463,15 +535,19 @@ _async_load_attributions ( BingMapSource *self )
  * Returns: a newly allocated BingMapSource GObject.
  */
 BingMapSource *
-bing_map_source_new_with_id (guint8 id, const gchar *label, const gchar *key)
+bing_map_source_new_with_id (guint16 id, const gchar *label, const gchar *key)
 {
        /* initialize settings here */
        return g_object_new(BING_TYPE_MAP_SOURCE,
                            "id", id,
                                                "label", label,
+                                               "name", "Bing-Aerial",
                                                "hostname", "ecn.t2.tiles.virtualearth.net",
+                                               "url", "/tiles/a%s.jpeg?g=587",
                                                "api-key", key,
                                                "check-file-server-time", TRUE,
+                                               "zoom-min", 0,
+                                               "zoom-max", 19, // NB: Might be regionally different rather than the same across the world
                                                "copyright", "© 2011 Microsoft Corporation and/or its suppliers",
                                                "license", "Microsoft Bing Maps Specific",
                                                "license-url", "http://www.microsoft.com/maps/assets/docs/terms.aspx",