Since we have a generic routing framework, we can replace
Google Routing feature by a more generic solution.

The user is now able to select the engine for the route
computation.

Signed-off-by: Guilhem Bonnefille <guilhem.bonnefi...@gmail.com>

---
 help/C/viking.xml         |   20 ++++++
 po/POTFILES.in            |    2 +-
 src/Makefile.am           |    2 +-
 src/babel.c               |   43 ++++++++++++
 src/babel.h               |    1 +
 src/datasource_google.c   |  128 ------------------------------------
 src/datasource_routing.c  |  159 +++++++++++++++++++++++++++++++++++++++++++++
 src/datasources.h         |    4 +-
 src/google.c              |    2 +
 src/menu.xml.h            |    4 +-
 src/vikrouting.c          |   14 ++++
 src/vikrouting.h          |    2 +-
 src/vikroutingengine.c    |   32 ++++++++-
 src/vikroutingengine.h    |    5 ++
 src/vikroutingwebengine.c |  124 +++++++++++++++++++++++++++++++++++
 src/viktrwlayer.c         |   19 ++----
 src/vikwindow.c           |   10 +--
 17 files changed, 414 insertions(+), 157 deletions(-)

diff --git a/help/C/viking.xml b/help/C/viking.xml
index 569509a..b3d0642 100644
--- a/help/C/viking.xml
+++ b/help/C/viking.xml
@@ -547,6 +547,16 @@ This gets <emphasis>interesting</emphasis> points from 
Wikipedia for the specifi
 </para>
 </section>
 
+<section>
+<title>From Routing</title>
+<para>
+<menuchoice><guimenu>File</guimenu><guimenuitem>Acquire</guimenuitem><guimenuitem>From
 Directions</guimenuitem></menuchoice>
+</para>
+<para>
+This gets a route from given directions.
+</para>
+</section>
+
 </section> <!-- End Acquire -->
 
 <section><title>Print</title>
@@ -2444,6 +2454,16 @@ Accept: */*
               <listitem><para>the part of the URL setting the end point 
location, parametrized in the spirit of C printf format, with 2 "%s" for 
coordinates (eg. "&amp;start=%s,%s")</para></listitem>
             </varlistentry>
             <varlistentry>
+              <term>url-start-dir</term>
+              <listitem><para>the part of the URL setting the starting point 
location for direction based routing, parametrized in the spirit of C printf 
format, with one "%s" for direction (eg. "&amp;start=%s")</para>
+                                               
<para>(Optional)</para></listitem>
+            </varlistentry>
+            <varlistentry>
+              <term>url-stop-dir</term>
+              <listitem><para>the part of the URL setting the end point 
location for direction based routing, parametrized in the spirit of C printf 
format, with one "%s" for direction (eg. "&amp;start=%s")</para>
+                                               
<para>(Optional)</para></listitem>
+            </varlistentry>
+            <varlistentry>
               <term>referer</term>
               <listitem><para>an URL to serve as referer for the HTTP request 
(eg. "http://hostname/";)</para></listitem>
             </varlistentry>
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 968dbe2..bc53f26 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -13,10 +13,10 @@ src/googlesearch.c
 src/datasource_file.c
 src/datasource_gc.c
 src/datasource_geotag.c
-src/datasource_google.c
 src/datasource_gps.c
 src/datasource_osm.c
 src/datasource_osm_my_traces.c
+src/datasource_routing.c
 src/datasource_wikipedia.c
 src/dem.c
 src/download.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 01e221d..25a3fd3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -108,7 +108,7 @@ libviking_a_SOURCES = \
        babel.c babel.h \
        datasource_file.c \
        datasource_gps.c datasource_gps.h \
-       datasource_google.c \
+       datasource_routing.c \
        datasource_gc.c \
        datasource_bfilter.c \
        datasource_wikipedia.c \
diff --git a/src/babel.c b/src/babel.c
index c5f8c61..5d30af9 100644
--- a/src/babel.c
+++ b/src/babel.c
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2003-2005, Evan Battaglia <gtoe...@gmx.net>
  * Copyright (C) 2006, Quy Tonthat <qtont...@gmail.com>
+ * Copyright (C) 2013, Guilhem Bonnefille <guilhem.bonnefi...@gmail.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -48,6 +49,11 @@
 #define BASH_LOCATION "/bin/bash"
 
 /**
+ * List of supported protocols.
+ */
+const gchar *PROTOS[] = { "http://";, "https://";, "ftp://";, NULL };
+
+/**
  * Path to gpsbabel
  */
 static gchar *gpsbabel_loc = NULL;
@@ -366,6 +372,43 @@ gboolean a_babel_convert_from_url ( VikTrwLayer *vt, const 
char *url, const char
   return ret;
 }
 
+/**
+ * a_babel_convert_from_url_or_shell:
+ * @vt: The #VikTrwLayer where to insert the collected data
+ * @url: the URL to fetch
+ * @cb:               Optional callback function. Same usage as in 
a_babel_convert().
+ * @user_data: passed along to cb
+ * @options:   download options. Maybe NULL.
+ *
+ * Download the file pointed by the URL and optionally uses GPSBabel to 
convert from input_file_type.
+ * If input_file_type is %NULL, doesn't use GPSBabel. Input must be GPX.
+ *
+ * Returns: %TRUE on successful invocation of GPSBabel or read of the GPX
+ *
+ */
+gboolean a_babel_convert_from_url_or_shell ( VikTrwLayer *vt, const char 
*input, const char *input_type, BabelStatusFunc cb, gpointer user_data, 
DownloadMapOptions *options )
+{
+  
+  /* Check nature of input */
+  gboolean isUrl = FALSE;
+  int i = 0;
+  for (i = 0 ; PROTOS[i] != NULL ; i++)
+  {
+    const gchar *proto = PROTOS[i];
+    if (strncmp (input, proto, strlen(proto)) == 0)
+    {
+      /* Procotol matches: save result */
+      isUrl = TRUE;
+    }
+  }
+  
+  /* Do the job */
+  if (isUrl)
+    return a_babel_convert_from_url (vt, input, input_type, cb, user_data, 
options);
+  else
+    return a_babel_convert_from_shellcommand (vt, input, input_type, cb, 
user_data, options);
+}
+
 static gboolean babel_general_convert_to( VikTrwLayer *vt, VikTrack *trk, 
BabelStatusFunc cb, gchar **args, const gchar *name_src, gpointer user_data )
 {
   // Now strips out invisible tracks and waypoints
diff --git a/src/babel.h b/src/babel.h
index a627d05..6fe4a07 100644
--- a/src/babel.h
+++ b/src/babel.h
@@ -99,6 +99,7 @@ gboolean a_babel_convert( VikTrwLayer *vt, const char 
*babelargs, BabelStatusFun
 gboolean a_babel_convert_from( VikTrwLayer *vt, const char *babelargs, const 
char *file, BabelStatusFunc cb, gpointer user_data, gpointer options );
 gboolean a_babel_convert_from_shellcommand ( VikTrwLayer *vt, const char 
*input_cmd, const char *input_file_type, BabelStatusFunc cb, gpointer 
user_data, gpointer options );
 gboolean a_babel_convert_from_url ( VikTrwLayer *vt, const char *url, const 
char *input_type, BabelStatusFunc cb, gpointer user_data, DownloadMapOptions 
*options );
+gboolean a_babel_convert_from_url_or_shell ( VikTrwLayer *vt, const char 
*input, const char *input_type, BabelStatusFunc cb, gpointer user_data, 
DownloadMapOptions *options );
 gboolean a_babel_convert_to( VikTrwLayer *vt, VikTrack *track, const char 
*babelargs, const char *file, BabelStatusFunc cb, gpointer user_data );
 
 void a_babel_init ();
diff --git a/src/datasource_google.c b/src/datasource_google.c
deleted file mode 100644
index 8f557d3..0000000
--- a/src/datasource_google.c
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
- *
- * Copyright (C) 2003-2005, Evan Battaglia <gtoe...@gmx.net>
- *
- * This program 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 2 of the License, or
- * (at your option) any later version.
- *
- * This program 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- */
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <string.h>
-
-#include <glib/gprintf.h>
-#include <glib/gi18n.h>
-
-#include "viking.h"
-#include "babel.h"
-#include "gpx.h"
-#include "acquire.h"
-
-#define GOOGLE_DIRECTIONS_STRING 
"maps.google.com/maps?q=from:%s+to:%s&output=js"
-
-typedef struct {
-  GtkWidget *from_entry, *to_entry;
-} datasource_google_widgets_t;
-
-static gchar *last_from_str = NULL;
-static gchar *last_to_str = NULL;
-
-static gpointer datasource_google_init ( acq_vik_t *avt );
-static void datasource_google_add_setup_widgets ( GtkWidget *dialog, 
VikViewport *vvp, gpointer user_data );
-static void datasource_google_get_cmd_string ( datasource_google_widgets_t 
*widgets, gchar **cmd, gchar **input_file_type, DownloadMapOptions *options );
-static void datasource_google_cleanup ( gpointer data );
-
-VikDataSourceInterface vik_datasource_google_interface = {
-  N_("Google Directions"),
-  N_("Google Directions"),
-  VIK_DATASOURCE_ADDTOLAYER,
-  VIK_DATASOURCE_INPUTTYPE_NONE,
-  TRUE,
-  TRUE,
-  TRUE,
-  (VikDataSourceInitFunc)              datasource_google_init,
-  (VikDataSourceCheckExistenceFunc)    NULL,
-  (VikDataSourceAddSetupWidgetsFunc)   datasource_google_add_setup_widgets,
-  (VikDataSourceGetCmdStringFunc)      datasource_google_get_cmd_string,
-  (VikDataSourceProcessFunc)            a_babel_convert_from_url,
-  (VikDataSourceProgressFunc)          NULL,
-  (VikDataSourceAddProgressWidgetsFunc)        NULL,
-  (VikDataSourceCleanupFunc)           datasource_google_cleanup,
-  (VikDataSourceOffFunc)                NULL,
-};
-
-static gpointer datasource_google_init ( acq_vik_t *avt )
-{
-  datasource_google_widgets_t *widgets = g_malloc(sizeof(*widgets));
-  return widgets;
-}
-
-static void datasource_google_add_setup_widgets ( GtkWidget *dialog, 
VikViewport *vvp, gpointer user_data )
-{
-  datasource_google_widgets_t *widgets = (datasource_google_widgets_t 
*)user_data;
-  GtkWidget *from_label, *to_label;
-  from_label = gtk_label_new (_("From:"));
-  widgets->from_entry = gtk_entry_new();
-  to_label = gtk_label_new (_("To:"));
-  widgets->to_entry = gtk_entry_new();
-  if (last_from_str)
-    gtk_entry_set_text(GTK_ENTRY(widgets->from_entry), last_from_str);
-  if (last_to_str)
-    gtk_entry_set_text(GTK_ENTRY(widgets->to_entry), last_to_str);
-
-  /* Packing all these widgets */
-  GtkBox *box = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
-  gtk_box_pack_start ( box, from_label, FALSE, FALSE, 5 );
-  gtk_box_pack_start ( box, widgets->from_entry, FALSE, FALSE, 5 );
-  gtk_box_pack_start ( box, to_label, FALSE, FALSE, 5 );
-  gtk_box_pack_start ( box, widgets->to_entry, FALSE, FALSE, 5 );
-  gtk_widget_show_all(dialog);
-}
-
-static void datasource_google_get_cmd_string ( datasource_google_widgets_t 
*widgets, gchar **cmd, gchar **input_file_type, DownloadMapOptions *options )
-{
-  /* TODO: special characters handling!!! */
-  gchar *from_quoted, *to_quoted;
-  gchar **from_split, **to_split;
-  from_quoted = g_shell_quote ( gtk_entry_get_text ( 
GTK_ENTRY(widgets->from_entry) ) );
-  to_quoted = g_shell_quote ( gtk_entry_get_text ( 
GTK_ENTRY(widgets->to_entry) ) );
-
-  from_split = g_strsplit( from_quoted, " ", 0);
-  to_split = g_strsplit( to_quoted, " ", 0);
-  from_quoted = g_strjoinv( "%20", from_split);
-  to_quoted = g_strjoinv( "%20", to_split);
-
-  *cmd = g_strdup_printf( GOOGLE_DIRECTIONS_STRING, from_quoted, to_quoted );
-  *input_file_type = g_strdup("google");
-  options = NULL;
-
-  g_free(last_from_str);
-  g_free(last_to_str);
-
-  last_from_str = g_strdup( gtk_entry_get_text ( 
GTK_ENTRY(widgets->from_entry) ));
-  last_to_str = g_strdup( gtk_entry_get_text ( GTK_ENTRY(widgets->to_entry) ));
-
-  g_free(from_quoted);
-  g_free(to_quoted);
-  g_strfreev(from_split);
-  g_strfreev(to_split);
-
-}
-
-static void datasource_google_cleanup ( gpointer data )
-{
-  g_free ( data );
-}
diff --git a/src/datasource_routing.c b/src/datasource_routing.c
new file mode 100644
index 0000000..4a8a1bc
--- /dev/null
+++ b/src/datasource_routing.c
@@ -0,0 +1,159 @@
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2003-2005, Evan Battaglia <gtoe...@gmx.net>
+ * Copyright (C) 2013, Guilhem Bonnefille <guilhem.bonnefi...@gmail.com>
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include <glib/gprintf.h>
+#include <glib/gi18n.h>
+
+#include "viking.h"
+#include "babel.h"
+#include "gpx.h"
+#include "acquire.h"
+#include "vikrouting.h"
+
+typedef struct {
+  GList *engines;
+  GtkWidget *engines_combo;
+  GtkWidget *from_entry, *to_entry;
+} datasource_routing_widgets_t;
+
+/* Memory of previous selection */
+static gint last_engine = 0;
+static gchar *last_from_str = NULL;
+static gchar *last_to_str = NULL;
+
+static gpointer datasource_routing_init ( acq_vik_t *avt );
+static void datasource_routing_add_setup_widgets ( GtkWidget *dialog, 
VikViewport *vvp, gpointer user_data );
+static void datasource_routing_get_cmd_string ( datasource_routing_widgets_t 
*widgets, gchar **cmd, gchar **input_file_type, DownloadMapOptions *options );
+static void datasource_routing_cleanup ( gpointer data );
+
+VikDataSourceInterface vik_datasource_routing_interface = {
+  N_("Directions"),
+  N_("Directions"),
+  VIK_DATASOURCE_ADDTOLAYER,
+  VIK_DATASOURCE_INPUTTYPE_NONE,
+  TRUE,
+  TRUE,
+  TRUE,
+  (VikDataSourceInitFunc)              datasource_routing_init,
+  (VikDataSourceCheckExistenceFunc)    NULL,
+  (VikDataSourceAddSetupWidgetsFunc)   datasource_routing_add_setup_widgets,
+  (VikDataSourceGetCmdStringFunc)      datasource_routing_get_cmd_string,
+  (VikDataSourceProcessFunc)            a_babel_convert_from_url_or_shell,
+  (VikDataSourceProgressFunc)          NULL,
+  (VikDataSourceAddProgressWidgetsFunc)        NULL,
+  (VikDataSourceCleanupFunc)           datasource_routing_cleanup,
+  (VikDataSourceOffFunc)                NULL,
+};
+
+static gpointer datasource_routing_init ( acq_vik_t *avt )
+{
+  datasource_routing_widgets_t *widgets = g_malloc(sizeof(*widgets));
+  /* Ensure NULL as GList functions adapt their behavior */
+  widgets->engines = NULL;
+  return widgets;
+}
+
+/*
+ * @see g_list_foreach()
+ */
+static void fill_engine_box (gpointer data, gpointer user_data)
+{
+  VikRoutingEngine *engine = (VikRoutingEngine*) data;
+  /* Only register engine supporting direction request */
+  gboolean ok = vik_routing_engine_supports_direction (engine);
+  if (ok)
+  {
+    datasource_routing_widgets_t *widgets = (datasource_routing_widgets_t*) 
user_data;
+    /* Add item in widget */
+    const gchar *label = vik_routing_engine_get_label (engine);
+    vik_combo_box_text_append (widgets->engines_combo, label);
+    /* Save engine in internal list */
+    widgets->engines = g_list_append ( widgets->engines, engine );
+  }
+}
+
+static void datasource_routing_add_setup_widgets ( GtkWidget *dialog, 
VikViewport *vvp, gpointer user_data )
+{
+  datasource_routing_widgets_t *widgets = (datasource_routing_widgets_t 
*)user_data;
+  GtkWidget *engine_label, *from_label, *to_label;
+  
+  /* Engine selector */
+  engine_label = gtk_label_new (_("Engine:"));
+  widgets->engines_combo = vik_combo_box_text_new ();
+  vik_routing_foreach_engine (fill_engine_box, widgets);
+  gtk_combo_box_set_active (GTK_COMBO_BOX (widgets->engines_combo), 
last_engine);
+  
+  /* From and To entries */
+  from_label = gtk_label_new (_("From:"));
+  widgets->from_entry = gtk_entry_new();
+  to_label = gtk_label_new (_("To:"));
+  widgets->to_entry = gtk_entry_new();
+  if (last_from_str)
+    gtk_entry_set_text(GTK_ENTRY(widgets->from_entry), last_from_str);
+  if (last_to_str)
+    gtk_entry_set_text(GTK_ENTRY(widgets->to_entry), last_to_str);
+  
+  /* Packing all these widgets */
+  GtkBox *box = GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog)));
+  gtk_box_pack_start ( box, engine_label, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( box, widgets->engines_combo, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( box, from_label, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( box, widgets->from_entry, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( box, to_label, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( box, widgets->to_entry, FALSE, FALSE, 5 );
+  gtk_widget_show_all(dialog);
+}
+
+static void datasource_routing_get_cmd_string ( datasource_routing_widgets_t 
*widgets, gchar **cmd, gchar **input_file_type, DownloadMapOptions *options )
+{
+  const gchar *from, *to;
+  
+  /* Retrieve directions */
+  from = gtk_entry_get_text ( GTK_ENTRY(widgets->from_entry) );
+  to = gtk_entry_get_text ( GTK_ENTRY(widgets->to_entry) );
+
+  /* Retrieve engine */
+  int active = gtk_combo_box_get_active ( 
GTK_COMBO_BOX(widgets->engines_combo) );
+  VikRoutingEngine *engine = g_list_nth_data ( widgets->engines, active );
+  
+  *cmd = vik_routing_engine_get_cmd_from_directions ( engine, from, to );
+  *input_file_type = g_strdup ( vik_routing_engine_get_format (engine) );
+  options = NULL;
+
+  /* Save last selection */
+  g_free ( last_from_str );
+  g_free ( last_to_str );
+
+  last_from_str = g_strdup( from );
+  last_to_str = g_strdup( to );
+}
+
+static void datasource_routing_cleanup ( gpointer data )
+{
+  g_list_free (((datasource_routing_widgets_t *)data)->engines );
+  g_free ( data );
+}
diff --git a/src/datasources.h b/src/datasources.h
index 445abce..10df1a6 100644
--- a/src/datasources.h
+++ b/src/datasources.h
@@ -27,9 +27,7 @@ G_BEGIN_DECLS
 
 extern VikDataSourceInterface vik_datasource_gps_interface;
 extern VikDataSourceInterface vik_datasource_file_interface;
-#ifdef VIK_CONFIG_GOOGLE
-extern VikDataSourceInterface vik_datasource_google_interface;
-#endif
+extern VikDataSourceInterface vik_datasource_routing_interface;
 #ifdef VIK_CONFIG_OPENSTREETMAP
 extern VikDataSourceInterface vik_datasource_osm_interface;
 extern VikDataSourceInterface vik_datasource_osm_my_traces_interface;
diff --git a/src/google.c b/src/google.c
index 32f5efb..2e1aa61 100644
--- a/src/google.c
+++ b/src/google.c
@@ -59,6 +59,8 @@ void google_init () {
     "url-base", "http://maps.google.com/maps?output=js&q=";,
     "url-start-ll", "from:%s,%s",
     "url-stop-ll", "+to:%s,%s",
+    "url-start-dir", "from:%s",
+    "url-stop-dir", "+to:%s",
     "referer", "http://maps.google.com/";,
     NULL);
   vik_routing_register ( VIK_ROUTING_ENGINE ( routing ) );
diff --git a/src/menu.xml.h b/src/menu.xml.h
index 56405c9..b2b169b 100644
--- a/src/menu.xml.h
+++ b/src/menu.xml.h
@@ -18,9 +18,7 @@ static const char *menu_xml =
        "      <menu action='Acquire'>"
        "        <menuitem action='AcquireGPS'/>"
        "        <menuitem action='AcquireGPSBabel'/>"
-#ifdef VIK_CONFIG_GOOGLE
-       "        <menuitem action='AcquireGoogle'/>"
-#endif
+       "        <menuitem action='AcquireRouting'/>"
 #ifdef VIK_CONFIG_OPENSTREETMAP
        "        <menuitem action='AcquireOSM'/>"
        "        <menuitem action='AcquireMyOSM'/>"
diff --git a/src/vikrouting.c b/src/vikrouting.c
index dc43a02..165a16a 100644
--- a/src/vikrouting.c
+++ b/src/vikrouting.c
@@ -72,6 +72,7 @@ vik_routing_prefs_init()
   a_preferences_register(prefs, tmp, VIKING_ROUTING_PARAMS_GROUP_KEY);
 }
 
+/* @see g_list_find_custom */
 static gint
 search_by_id (gconstpointer a,
               gconstpointer b)
@@ -208,3 +209,16 @@ vik_routing_unregister_all ()
   g_strfreev ( routing_engine_labels );
   g_strfreev ( routing_engine_ids );
 }
+
+/**
+ * vik_routing_foreach_engine:
+ * @func: the function to run on each element
+ * @user_data: user's data to give to each call of @func
+ * 
+ * Loop over all registered routing engines.
+ */
+void
+vik_routing_foreach_engine (GFunc func, gpointer user_data)
+{
+  g_list_foreach ( routing_engine_list, func, user_data );
+}
diff --git a/src/vikrouting.h b/src/vikrouting.h
index 1a98636..acb1e88 100644
--- a/src/vikrouting.h
+++ b/src/vikrouting.h
@@ -27,7 +27,6 @@
 
 G_BEGIN_DECLS
 
-
 /* Default */
 void vik_routing_default_find ( VikTrwLayer *vt, struct LatLon start, struct 
LatLon end );
 
@@ -35,6 +34,7 @@ void vik_routing_default_find ( VikTrwLayer *vt, struct 
LatLon start, struct Lat
 void vik_routing_prefs_init();
 void vik_routing_register( VikRoutingEngine *engine );
 void vik_routing_unregister_all ();
+void vik_routing_foreach_engine (GFunc func, gpointer user_data);
 
 G_END_DECLS
 
diff --git a/src/vikroutingengine.c b/src/vikroutingengine.c
index e0eb168..c06f264 100644
--- a/src/vikroutingengine.c
+++ b/src/vikroutingengine.c
@@ -141,7 +141,8 @@ vik_routing_engine_class_init ( VikRoutingEngineClass 
*klass )
 
   routing_class = VIK_ROUTING_ENGINE_CLASS ( klass );
   routing_class->find = NULL;
-
+  routing_class->supports_direction = NULL;
+  routing_class->get_cmd_from_directions = NULL;
 
   pspec = g_param_spec_string ("id",
                                "Identifier",
@@ -244,3 +245,32 @@ vik_routing_engine_get_format ( VikRoutingEngine *self )
 
   return priv->format;
 }
+
+/**
+ * vik_routing_engine_support_direction:
+ * 
+ * Returns: %TRUE if this engine supports the route finding based on directions
+ */
+gboolean
+vik_routing_engine_supports_direction ( VikRoutingEngine *self )
+{
+  VikRoutingEngineClass *klass;
+
+  g_return_val_if_fail ( VIK_IS_ROUTING_ENGINE (self), FALSE );
+  klass = VIK_ROUTING_ENGINE_GET_CLASS( self );
+  g_return_val_if_fail ( klass->supports_direction != NULL, FALSE );
+
+  return klass->supports_direction( self );
+}
+
+gchar *
+vik_routing_engine_get_cmd_from_directions ( VikRoutingEngine *self, const 
gchar *start, const gchar *end )
+{
+  VikRoutingEngineClass *klass;
+
+  g_return_val_if_fail ( VIK_IS_ROUTING_ENGINE (self), NULL );
+  klass = VIK_ROUTING_ENGINE_GET_CLASS( self );
+  g_return_val_if_fail ( klass->get_cmd_from_directions != NULL, NULL );
+
+  return klass->get_cmd_from_directions( self, start, end );
+}
diff --git a/src/vikroutingengine.h b/src/vikroutingengine.h
index ab707f6..a5da970 100644
--- a/src/vikroutingengine.h
+++ b/src/vikroutingengine.h
@@ -46,6 +46,8 @@ struct _VikRoutingEngineClass
 {
   GObjectClass object_class;
   int (*find)(VikRoutingEngine *self, VikTrwLayer *vt, struct LatLon start, 
struct LatLon end);
+  gchar *(*get_cmd_from_directions)(VikRoutingEngine *self, const gchar 
*start, const gchar *end);
+  gboolean (*supports_direction)(VikRoutingEngine *self);
 };
 
 GType vik_routing_engine_get_type ();
@@ -55,12 +57,15 @@ struct _VikRoutingEngine {
 };
 
 int vik_routing_engine_find ( VikRoutingEngine *self, VikTrwLayer *vt, struct 
LatLon start, struct LatLon end );
+gchar *vik_routing_engine_get_cmd_from_directions ( VikRoutingEngine *self, 
const gchar *start, const gchar *end );
 
 /* Acessors */
 gchar *vik_routing_engine_get_id ( VikRoutingEngine *self );
 gchar *vik_routing_engine_get_label ( VikRoutingEngine *self );
 gchar *vik_routing_engine_get_format ( VikRoutingEngine *self );
 
+gboolean vik_routing_engine_supports_direction ( VikRoutingEngine *self );
+
 G_END_DECLS
 
 #endif
diff --git a/src/vikroutingwebengine.c b/src/vikroutingwebengine.c
index bb809fe..b4cd635 100644
--- a/src/vikroutingwebengine.c
+++ b/src/vikroutingwebengine.c
@@ -43,15 +43,23 @@
 static void vik_routing_web_engine_finalize ( GObject *gob );
 
 static int vik_routing_web_engine_find ( VikRoutingEngine *self, VikTrwLayer 
*vtl, struct LatLon start, struct LatLon end );
+static gchar *vik_routing_web_engine_get_cmd_from_directions(VikRoutingEngine 
*self, const gchar *start, const gchar *end);
+static gboolean vik_routing_web_engine_supports_direction(VikRoutingEngine 
*self);
 
 typedef struct _VikRoutingWebEnginePrivate VikRoutingWebEnginePrivate;
 struct _VikRoutingWebEnginePrivate
 {
        gchar *url_base;
+       
+       /* LatLon */
        gchar *url_start_ll_fmt;
        gchar *url_stop_ll_fmt;
        gchar *url_via_ll_fmt;
 
+       /* Directions */
+       gchar *url_start_dir_fmt;
+       gchar *url_stop_dir_fmt;
+
        DownloadMapOptions options;
 };
 
@@ -63,10 +71,16 @@ enum
   PROP_0,
 
   PROP_URL_BASE,
+  
+  /* LatLon */
   PROP_URL_START_LL,
   PROP_URL_STOP_LL,
   PROP_URL_VIA_LL,
 
+  /* Direction */
+  PROP_URL_START_DIR,
+  PROP_URL_STOP_DIR,
+
   PROP_REFERER,
   PROP_FOLLOW_LOCATION,
 };
@@ -103,6 +117,16 @@ vik_routing_web_engine_set_property (GObject      *object,
       priv->url_via_ll_fmt = g_strdup(g_value_get_string (value));
       break;
 
+    case PROP_URL_START_DIR:
+      g_free (priv->url_start_dir_fmt);
+      priv->url_start_dir_fmt = g_strdup(g_value_get_string (value));
+      break;
+
+    case PROP_URL_STOP_DIR:
+      g_free (priv->url_stop_dir_fmt);
+      priv->url_stop_dir_fmt = g_strdup(g_value_get_string (value));
+      break;
+
     case PROP_REFERER:
       g_free (priv->options.referer);
       priv->options.referer = g_value_dup_string (value);
@@ -145,6 +169,14 @@ vik_routing_web_engine_get_property (GObject    *object,
       g_value_set_string (value, priv->url_via_ll_fmt);
       break;
 
+    case PROP_URL_START_DIR:
+      g_value_set_string (value, priv->url_start_dir_fmt);
+      break;
+
+    case PROP_URL_STOP_DIR:
+      g_value_set_string (value, priv->url_stop_dir_fmt);
+      break;
+
     case PROP_REFERER:
       g_value_set_string (value, priv->options.referer);
       break;
@@ -175,6 +207,8 @@ static void vik_routing_web_engine_class_init ( 
VikRoutingWebEngineClass *klass
   parent_class = VIK_ROUTING_ENGINE_CLASS (klass);
 
   parent_class->find = vik_routing_web_engine_find;
+  parent_class->supports_direction = vik_routing_web_engine_supports_direction;
+  parent_class->get_cmd_from_directions = 
vik_routing_web_engine_get_cmd_from_directions;
 
   /**
    * VikRoutingWebEngine:url-base:
@@ -229,6 +263,32 @@ static void vik_routing_web_engine_class_init ( 
VikRoutingWebEngineClass *klass
 
 
   /**
+   * VikRoutingWebEngine:url-start-dir:
+   *
+   * The part of the request hosting the end point.
+   */
+  pspec = g_param_spec_string ("url-start-dir",
+                               "Start part of the URL",
+                               "The part of the request hosting the start 
point",
+                               NULL /* default value */,
+                               G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+  g_object_class_install_property (object_class, PROP_URL_START_DIR, pspec);
+    
+
+  /**
+   * VikRoutingWebEngine:url-stop-dir:
+   *
+   * The part of the request hosting the end point.
+   */
+  pspec = g_param_spec_string ("url-stop-dir",
+                               "Stop part of the URL",
+                               "The part of the request hosting the end point",
+                               NULL /* default value */,
+                               G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
+  g_object_class_install_property (object_class, PROP_URL_STOP_DIR, pspec);
+
+
+  /**
    * VikRoutingWebEngine:referer:
    *
    * The REFERER string to use in HTTP request.
@@ -263,10 +323,16 @@ static void vik_routing_web_engine_init ( 
VikRoutingWebEngine *self )
   VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
 
   priv->url_base = NULL;
+  
+  /* LatLon */
   priv->url_start_ll_fmt = NULL;
   priv->url_stop_ll_fmt = NULL;
   priv->url_via_ll_fmt = NULL;
 
+  /* Directions */
+  priv->url_start_dir_fmt = NULL;
+  priv->url_stop_dir_fmt = NULL;
+
   priv->options.referer = NULL;
   priv->options.follow_location = 0;
   priv->options.check_file = NULL;
@@ -280,6 +346,8 @@ static void vik_routing_web_engine_finalize ( GObject *gob )
 
   g_free (priv->url_base);
   priv->url_base = NULL;
+  
+  /* LatLon */
   g_free (priv->url_start_ll_fmt);
   priv->url_start_ll_fmt = NULL;
   g_free (priv->url_stop_ll_fmt);
@@ -287,6 +355,12 @@ static void vik_routing_web_engine_finalize ( GObject *gob 
)
   g_free (priv->url_via_ll_fmt);
   priv->url_via_ll_fmt = NULL;
 
+  /* Directions */
+  g_free (priv->url_start_dir_fmt);
+  priv->url_start_dir_fmt = NULL;
+  g_free (priv->url_stop_dir_fmt);
+  priv->url_stop_dir_fmt = NULL;
+
   g_free (priv->options.referer);
   priv->options.referer = NULL;
 
@@ -319,6 +393,8 @@ vik_routing_web_engine_get_url_for_coords ( 
VikRoutingEngine *self, struct LatLo
        gchar *startURL;
        gchar *endURL;
        gchar *url;
+       
+       g_return_val_if_fail ( VIK_IS_ROUTING_WEB_ENGINE (self), NULL);
 
        VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( 
self );
 
@@ -329,6 +405,8 @@ vik_routing_web_engine_get_url_for_coords ( 
VikRoutingEngine *self, struct LatLo
        startURL = substitute_latlon ( priv->url_start_ll_fmt, start );
        endURL = substitute_latlon ( priv->url_stop_ll_fmt, end );
        url = g_strconcat ( priv->url_base, startURL, endURL, NULL );
+       
+       /* Free memory */
        g_free ( startURL );
        g_free ( endURL );
        
@@ -349,5 +427,51 @@ vik_routing_web_engine_find ( VikRoutingEngine *self, 
VikTrwLayer *vtl, struct L
   a_babel_convert_from_url ( vtl, uri, format, NULL, NULL, options );
 
   g_free(uri);
+
   return ret;
 }
+
+static gchar *
+vik_routing_web_engine_get_cmd_from_directions ( VikRoutingEngine *self, const 
gchar *start, const gchar *end )
+{
+  g_return_val_if_fail ( VIK_IS_ROUTING_WEB_ENGINE (self), NULL);
+
+  VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
+
+  g_return_val_if_fail ( priv->url_base != NULL, NULL);
+  g_return_val_if_fail ( priv->url_start_dir_fmt != NULL, NULL);
+  g_return_val_if_fail ( priv->url_stop_dir_fmt != NULL, NULL);
+
+  gchar *from_quoted, *to_quoted;
+  gchar **from_split, **to_split;
+  from_quoted = g_shell_quote ( start );
+  to_quoted = g_shell_quote ( end );
+
+  from_split = g_strsplit( from_quoted, " ", 0);
+  to_split = g_strsplit( to_quoted, " ", 0);
+
+  from_quoted = g_strjoinv( "%20", from_split);
+  to_quoted = g_strjoinv( "%20", to_split);
+
+  gchar *url_fmt = g_strconcat ( priv->url_base, priv->url_start_dir_fmt, 
priv->url_stop_dir_fmt, NULL );
+  gchar *url = g_strdup_printf ( url_fmt, from_quoted, to_quoted );
+
+  g_free ( url_fmt );
+
+  g_free(from_quoted);
+  g_free(to_quoted);
+  g_strfreev(from_split);
+  g_strfreev(to_split);
+
+  return url;
+}
+
+static gboolean
+vik_routing_web_engine_supports_direction ( VikRoutingEngine *self )
+{
+  g_return_val_if_fail ( VIK_IS_ROUTING_WEB_ENGINE (self), FALSE);
+
+  VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
+
+  return (priv->url_start_dir_fmt) != NULL;
+}
diff --git a/src/viktrwlayer.c b/src/viktrwlayer.c
index 78b2ff9..27629d7 100644
--- a/src/viktrwlayer.c
+++ b/src/viktrwlayer.c
@@ -298,9 +298,7 @@ static void trw_layer_geotagging_track ( gpointer 
pass_along[6] );
 static void trw_layer_geotagging ( gpointer lav[2] );
 #endif
 static void trw_layer_acquire_gps_cb ( gpointer lav[2] );
-#ifdef VIK_CONFIG_GOOGLE
-static void trw_layer_acquire_google_cb ( gpointer lav[2] );
-#endif
+static void trw_layer_acquire_routing_cb ( gpointer lav[2] );
 #ifdef VIK_CONFIG_OPENSTREETMAP
 static void trw_layer_acquire_osm_cb ( gpointer lav[2] );
 static void trw_layer_acquire_osm_my_traces_cb ( gpointer lav[2] );
@@ -3036,20 +3034,18 @@ static void trw_layer_acquire_gps_cb ( gpointer lav[2] )
   a_acquire ( vw, vlp, vvp, &vik_datasource_gps_interface, NULL, NULL );
 }
 
-#ifdef VIK_CONFIG_GOOGLE
 /*
- * Acquire into this TRW Layer from Google Directions
+ * Acquire into this TRW Layer from Directions
  */
-static void trw_layer_acquire_google_cb ( gpointer lav[2] )
+static void trw_layer_acquire_routing_cb ( gpointer lav[2] )
 {
   VikTrwLayer *vtl = VIK_TRW_LAYER(lav[0]);
   VikLayersPanel *vlp = VIK_LAYERS_PANEL(lav[1]);
   VikWindow *vw = (VikWindow *)(VIK_GTK_WINDOW_FROM_LAYER(vtl));
   VikViewport *vvp =  vik_window_viewport(vw);
 
-  a_acquire ( vw, vlp, vvp, &vik_datasource_google_interface, NULL, NULL );
+  a_acquire ( vw, vlp, vvp, &vik_datasource_routing_interface, NULL, NULL );
 }
-#endif
 
 #ifdef VIK_CONFIG_OPENSTREETMAP
 /*
@@ -3511,12 +3507,11 @@ static void trw_layer_add_menu_items ( VikTrwLayer 
*vtl, GtkMenu *menu, gpointer
   gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
   gtk_widget_show ( item );
 
-#ifdef VIK_CONFIG_GOOGLE
-  item = gtk_menu_item_new_with_mnemonic ( _("From Google _Directions...") );
-  g_signal_connect_swapped ( G_OBJECT(item), "activate", 
G_CALLBACK(trw_layer_acquire_google_cb), pass_along );
+  /* FIXME: only add menu when at least a routing engine has support for 
Directions */
+  item = gtk_menu_item_new_with_mnemonic ( _("From _Directions...") );
+  g_signal_connect_swapped ( G_OBJECT(item), "activate", 
G_CALLBACK(trw_layer_acquire_routing_cb), pass_along );
   gtk_menu_shell_append (GTK_MENU_SHELL (acquire_submenu), item);
   gtk_widget_show ( item );
-#endif
 
 #ifdef VIK_CONFIG_OPENSTREETMAP
   item = gtk_menu_item_new_with_mnemonic ( _("From _OSM Traces...") );
diff --git a/src/vikwindow.c b/src/vikwindow.c
index e7d7a95..3ecebfe 100644
--- a/src/vikwindow.c
+++ b/src/vikwindow.c
@@ -2695,12 +2695,10 @@ static void acquire_from_file ( GtkAction *a, VikWindow 
*vw )
   a_acquire(vw, vw->viking_vlp, vw->viking_vvp, 
&vik_datasource_file_interface, NULL, NULL );
 }
 
-#ifdef VIK_CONFIG_GOOGLE
-static void acquire_from_google ( GtkAction *a, VikWindow *vw )
+static void acquire_from_routing ( GtkAction *a, VikWindow *vw )
 {
-  a_acquire(vw, vw->viking_vlp, vw->viking_vvp, 
&vik_datasource_google_interface, NULL, NULL );
+  a_acquire(vw, vw->viking_vlp, vw->viking_vvp, 
&vik_datasource_routing_interface, NULL, NULL );
 }
-#endif
 
 #ifdef VIK_CONFIG_OPENSTREETMAP
 static void acquire_from_osm ( GtkAction *a, VikWindow *vw )
@@ -3435,9 +3433,7 @@ static GtkActionEntry entries[] = {
   { "Acquire",   GTK_STOCK_GO_DOWN,      N_("A_cquire"),                  
NULL,         NULL,                                               
(GCallback)NULL },
   { "AcquireGPS",   NULL,                N_("From _GPS..."),                   
  NULL,         N_("Transfer data from a GPS device"),              
(GCallback)acquire_from_gps      },
   { "AcquireGPSBabel",   NULL,                N_("Import File With 
GPS_Babel..."),               NULL,         N_("Import file via GPSBabel 
converter"),              (GCallback)acquire_from_file      },
-#ifdef VIK_CONFIG_GOOGLE
-  { "AcquireGoogle",   NULL,             N_("Google _Directions..."),     
NULL,         N_("Get driving directions from Google"),           
(GCallback)acquire_from_google   },
-#endif
+  { "AcquireRouting",   NULL,             N_("_Directions..."),     NULL,      
   N_("Get driving directions"),           (GCallback)acquire_from_routing   },
 #ifdef VIK_CONFIG_OPENSTREETMAP
   { "AcquireOSM",   NULL,                 N_("_OSM Traces..."),          NULL, 
        N_("Get traces from OpenStreetMap"),            
(GCallback)acquire_from_osm       },
   { "AcquireMyOSM", NULL,                 N_("_My OSM Traces..."),       NULL, 
        N_("Get Your Own Traces from OpenStreetMap"),   
(GCallback)acquire_from_my_osm    },
-- 
tg: (2190abb..) t/routing/datasource (depends on: master)

------------------------------------------------------------------------------
How ServiceNow helps IT people transform IT departments:
1. A cloud service to automate IT design, transition and operations
2. Dashboards that offer high-level views of enterprise services
3. A single system of record for all IT processes
http://p.sf.net/sfu/servicenow-d2d-j
_______________________________________________
Viking-devel mailing list
Viking-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/viking-devel
Viking home page: http://viking.sf.net/

Reply via email to