]> git.street.me.uk Git - andy/viking.git/commitdiff
Data sources core structure, google directions
authorEvan Battaglia <gtoevan@gmx.net>
Fri, 25 Nov 2005 22:22:17 +0000 (22:22 +0000)
committerEvan Battaglia <gtoevan@gmx.net>
Fri, 25 Nov 2005 22:22:17 +0000 (22:22 +0000)
12 files changed:
ChangeLog
TODO
src/Makefile.am
src/acquire.c
src/acquire.h
src/babel.c
src/babel.h
src/datasource_google.c [new file with mode: 0644]
src/datasource_gps.c [new file with mode: 0644]
src/datasources.h [new file with mode: 0644]
src/menu.xml.h
src/vikwindow.c

index 2290a596dbaf13612e709178a5fdfae077519fda..6d1869aac98496774f3949849cbf2d9192f373b6 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2005-11-25
+       * Created "data sources" structure to easily add new data sources via GPS babel.
+          It's ugly now and there's a lot to be done, but I think 79-line datasources_google.c
+          shows the power of the approach.
+
 2005-11-23  Guilhem BONNEFILLE  <guilhem.bonnefille@gmail.com>
        * src/gpx.c (gpx_dtostr): add better GPX export
 Evan Battaglia <gtoevan@gmx.net>:
diff --git a/TODO b/TODO
index 7432d73c70eb9ba60d5de3bc1cafba36aa6dca9c..b3fcf06bc3ef9208e92c78aa003b1871749cf53a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -5,9 +5,12 @@ BEFORE RELEASE:
        acquire crashes, sometimes (???)
        google maps download stops (try auto-download), extra processes in background doing nothing
        GPSBABEL!!!
-               * Google (address -> WP and directions -> track)
-               * Geotoad
+               * Smooth over rough edges / ugliness / crashes
+               * Google address -> WP
+               * handling of special characters (both to wget/HTTP and shell) -- don't allow backdoor tricks
+               * ADD to a layer instead of make a new layer (maybe right click layer -> new track from Google or something)
                * Filter a TRW layer: simplify paths, get out waypoints inside a path, etc.
+               * Geotoad
 
 FEATURES:
        Paste GPX files into Viking -> TRW Layer
index 814ab7b5b452b979ab620213dae3bceede33e83c..b8f55be70d30fdac81212c5d98bb23ec2510cf49 100644 (file)
@@ -44,7 +44,10 @@ viking_SOURCES = main.c \
         gpx.c gpx.h \
        garminsymbols.c garminsymbols.h \
        acquire.c acquire.h \
-       babel.c babel.h
+       babel.c babel.h \
+       datasource_gps.c \
+       datasource_google.c \
+       datasources.h
 
 INCLUDES        = @GTK_CFLAGS@
 LDADD           = @GTK_LIBS@
index 1da404c96fdd9c03afd73869c162002fcc48e489..1d127131c9af64c7275dfee39d15af89694bb999 100644 (file)
 #include "viking.h"
 #include "babel.h"
 #include "gpx.h"
+#include "acquire.h"
 
-/*********************************************************
- * Definitions and routines for acquiring data from GPS
- *********************************************************/
-
-/* global data structure used to expose the progress dialog to the worker thread */
+/* passed along to worker thread */
 typedef struct {
-  VikWindow *vw;
-  VikLayersPanel *vlp;
-  VikViewport *vvp;
-  GtkWidget *dialog;
-  GtkWidget *status;
-  GtkWidget *gps_label;
-  GtkWidget *ver_label;
-  GtkWidget *id_label;
-  GtkWidget *wp_label;
-  GtkWidget *trk_label;
-  GtkWidget *progress_label;
-  gboolean ok;
-} acq_dialog_widgets_t;
-
-acq_dialog_widgets_t *w = NULL;
-int total_count = -1;
-int count;
-
-static void set_total_count(gint cnt)
-{
-  gchar s[128];
-  gdk_threads_enter();
-  if (w->ok) {
-    g_sprintf(s, "Downloading %d %s...", cnt, (w->progress_label == w->wp_label) ? "waypoints" : "trackpoints");
-    gtk_label_set_text ( GTK_LABEL(w->progress_label), s );
-    gtk_widget_show ( w->progress_label );
-    total_count = cnt;
-  }
-  gdk_threads_leave();
-}
-
-static void set_current_count(gint cnt)
-{
-  gchar s[128];
-  gdk_threads_enter();
-  if (w->ok) {
-    if (cnt < total_count) {
-      g_sprintf(s, "Downloaded %d out of %d %s...", cnt, total_count, (w->progress_label == w->wp_label) ? "waypoints" : "trackpoints");
-    } else {
-      g_sprintf(s, "Downloaded %d %s.", cnt, (w->progress_label == w->wp_label) ? "waypoints" : "trackpoints");
-    }    
-    gtk_label_set_text ( GTK_LABEL(w->progress_label), s );
-  }
-  gdk_threads_leave();
-}
+  acq_dialog_widgets_t *w;
+  VikDataSourceInterface *interface;
+  gchar *cmd;
+  gchar *extra;
+} w_and_interface_t;
 
-static void set_gps_info(const gchar *info)
-{
-  gchar s[256];
-  gdk_threads_enter();
-  if (w->ok) {
-    g_sprintf(s, "GPS Device: %s", info);
-    gtk_label_set_text ( GTK_LABEL(w->gps_label), s );
-  }
-  gdk_threads_leave();
-}
+extern VikDataSourceInterface vik_datasource_gps_interface;
+extern VikDataSourceInterface vik_datasource_google_interface;
 
-/* 
- * This routine relies on gpsbabel's diagnostic output to display the progress information. 
- * These outputs differ when different GPS devices are used, so we will need to test
- * them on several and add the corresponding support.
- */
-static void progress_func ( BabelProgressCode c, gpointer data )
-{
-  gchar *line;
-
-  switch(c) {
-  case BABEL_DIAG_OUTPUT:
-    line = (gchar *)data;
-
-    /* tells us how many items there will be */
-    if (strstr(line, "Xfer Wpt")) { 
-      w->progress_label = w->wp_label;
-    }
-    if (strstr(line, "Xfer Trk")) { 
-      w->progress_label = w->trk_label;
-    }
-    if (strstr(line, "PRDDAT")) {
-      gchar **tokens = g_strsplit(line, " ", 0);
-      gchar info[128];
-      int ilen = 0;
-      int i;
-
-      for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
-       guint ch;
-       sscanf(tokens[i], "%x", &ch);
-       info[ilen++] = ch;
-      }
-      info[ilen++] = 0;
-      set_gps_info(info);
-    }
-    if (strstr(line, "RECORD")) { 
-      int lsb, msb, cnt;
-
-      sscanf(line+17, "%x", &lsb); 
-      sscanf(line+20, "%x", &msb);
-      cnt = lsb + msb * 256;
-      set_total_count(cnt);
-      count = 0;
-    }
-    if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
-      count++;
-      set_current_count(count);
-    }
-    break;
-  case BABEL_DONE:
-    break;
-  default:
-    break;
-  }
-}
+/*********************************************************
+ * Definitions and routines for acquiring data from GPS
+ *********************************************************/
 
 /* this routine is the worker thread.  there is only one simultaneous download allowed */
-static void get_from_gps ( gpointer data )
+static void get_from_anything ( w_and_interface_t *wi )
 {
   VikTrwLayer *vtl;
-       
-  if ( w ) {
-    /* simultaneous downloads are not allowed, so we return.  */
-    g_free(data);
-    g_thread_exit ( NULL );
-    return;
-  }
 
-  w = data;
+  gchar *cmd = wi->cmd;
+  gchar *extra = wi->extra;
+  gboolean result;
+
+  acq_dialog_widgets_t *w = wi->w;
+  VikDataSourceInterface *interface = wi->interface;
+  g_free ( wi );
 
   gdk_threads_enter();
   vtl = VIK_TRW_LAYER ( vik_layer_create ( VIK_LAYER_TRW, w->vvp, NULL, FALSE ) );
-  vik_layer_rename ( VIK_LAYER ( vtl ), "Acquired from GPS" );
+  vik_layer_rename ( VIK_LAYER ( vtl ), interface->layer_title );
   gtk_label_set_text ( GTK_LABEL(w->status), "Working..." );
   gdk_threads_leave();
 
-  if (!a_babel_convert_from (vtl, "-D 9 -t -w -i garmin", progress_func, "/dev/ttyS0")) {
-//  if (!a_babel_convert_from (vtl, "-D 9 -t -w -i garmin", progress_func, "/dev/ttyS1")) {
-//  if (!a_babel_convert_from_shellcommand (vtl, "(wget -O - \"http://maps.google.com/maps?q=91214 to 94704&output=xml\" 2>/dev/null) | cat ~/vik/tools/temp.ggl | head -3 | tail -1 |  sed 's/.*<page>\\(.*\\)<\\/page>.*/<page>\\1<\\/page>/'", "google", progress_func)) {
+  if ( interface->type == VIK_DATASOURCE_GPSBABEL_DIRECT )
+    result = a_babel_convert_from (vtl, cmd, (BabelStatusFunc) interface->progress_func, extra, w);
+  else
+    result = a_babel_convert_from_shellcommand ( vtl, cmd, extra, (BabelStatusFunc) interface->progress_func, w);
+
+  g_free ( cmd );
+  g_free ( extra );
+
+  if (!result) {
     gdk_threads_enter();
     gtk_label_set_text ( GTK_LABEL(w->status), "Error: couldn't find gpsbabel." );
     gdk_threads_leave();
@@ -178,55 +81,87 @@ static void get_from_gps ( gpointer data )
     gtk_dialog_set_response_sensitive ( GTK_DIALOG(w->dialog), GTK_RESPONSE_ACCEPT, TRUE );
     gtk_dialog_set_response_sensitive ( GTK_DIALOG(w->dialog), GTK_RESPONSE_REJECT, FALSE );
   } else {
+    /* canceled */
     g_object_unref(vtl);
   }
-  g_free ( w );
-  w = NULL;
+
+  if ( interface->cleanup_func )
+    interface->cleanup_func ( w->specific_data );
+
+  if ( w->ok ) {
+    w->ok = FALSE;
+  } else {
+    g_free ( w );
+  }
+
   gdk_threads_leave();
   g_thread_exit ( NULL );
 }
 
-void a_acquire_from_gps ( VikWindow *vw, VikLayersPanel *vlp, VikViewport *vvp )
+
+void a_acquire ( VikWindow *vw, VikLayersPanel *vlp, VikViewport *vvp, VikDataSourceInterface *interface )
 {
-  GtkWidget *status, *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
   GtkWidget *dialog = NULL;
-  acq_dialog_widgets_t *w = g_malloc(sizeof(*w));
+  GtkWidget *status;
+  gchar *cmd, *extra;
+  acq_dialog_widgets_t *w;
+
+  w_and_interface_t *wi;
+
+  if ( interface->add_widgets_func ) {
+    gpointer first_dialog_data;
+    dialog = gtk_dialog_new_with_buttons ( "", NULL, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL );
+    first_dialog_data = interface->add_widgets_func(dialog);
+    if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
+      interface->first_cleanup_func(first_dialog_data);
+      gtk_widget_destroy(dialog);
+      return;
+    }
+    interface->get_cmd_string_func ( first_dialog_data, &cmd, &extra );
+    interface->first_cleanup_func(first_dialog_data);
+    gtk_widget_destroy(dialog);
+    dialog = NULL;
+  } else
+    interface->get_cmd_string_func ( NULL, &cmd, &extra );
+
+  if ( ! cmd )
+    return;
+
+  w = g_malloc(sizeof(*w));
+  wi = g_malloc(sizeof(*wi));
+  wi->w = w;
+  wi->interface = interface;
+  wi->cmd = cmd;
+  wi->extra = extra;
 
   dialog = gtk_dialog_new_with_buttons ( "", NULL, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL );
   gtk_dialog_set_response_sensitive ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT, FALSE );
 
-  status = gtk_label_new ("Status: detecting gpsbabel");
-  gpslabel = gtk_label_new ("GPS device: N/A");
-  verlabel = gtk_label_new ("Version: N/A");
-  idlabel = gtk_label_new ("ID: N/A");
-  wplabel = gtk_label_new ("WP");
-  trklabel = gtk_label_new ("TRK");
-
-  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), status, FALSE, FALSE, 5 );
-  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
-  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
-  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
-
-  gtk_window_set_title ( GTK_WINDOW(dialog), "Acquire data from GPS" );
-
-  gtk_widget_show ( status );
-  gtk_widget_show ( gpslabel );
-  gtk_widget_show ( dialog );
 
   w->dialog = dialog;
+  w->ok = TRUE;
+
+  status = gtk_label_new ("Status: detecting gpsbabel");
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), status, FALSE, FALSE, 5 );
+  gtk_widget_show_all(status);
   w->status = status;
-  w->gps_label = gpslabel;
-  w->id_label = idlabel;
-  w->ver_label = verlabel;
-  w->progress_label = w->wp_label = wplabel;
-  w->trk_label = trklabel;
+
   w->vw = vw;
   w->vlp = vlp;
   w->vvp = vvp;
-  w->ok = TRUE;
-  g_thread_create((GThreadFunc)get_from_gps, w, FALSE, NULL );
+  if ( interface->add_progress_widgets_func )
+    w->specific_data = interface->add_progress_widgets_func ( dialog );
+  else
+    w->specific_data = NULL;
+
+  g_thread_create((GThreadFunc)get_from_anything, wi, FALSE, NULL );
 
   gtk_dialog_run ( GTK_DIALOG(dialog) );
-  w->ok = FALSE;
+  if ( w->ok )
+    w->ok = FALSE; /* tell thread to stop. TODO: add mutex */
+  else {
+    g_free ( w ); /* thread has finished; free w */
+  }
   gtk_widget_destroy ( dialog );
 }
+
index cd196022e0b26d2ba00b6bbed1d817f984680b37..bef7b34b043fbf0cd3ccceffaf62637d9696c89b 100644 (file)
 #ifndef _VIKING_ACQUIRE_H
 #define _VIKING_ACQUIRE_H
 
-void a_acquire_from_gps ( VikWindow *vw, VikLayersPanel *vlp, VikViewport *vvp );
+/* global data structure used to expose the progress dialog to the worker thread */
+typedef struct {
+  GtkWidget *status;
+  VikWindow *vw;
+  VikLayersPanel *vlp;
+  VikViewport *vvp;
+  GtkWidget *dialog;
+  gboolean ok; /* if OK is false when we exit, we MUST free w */
+  gpointer specific_data;
+} acq_dialog_widgets_t;
+
+typedef enum { VIK_DATASOURCE_GPSBABEL_DIRECT, VIK_DATASOURCE_SHELL_CMD } vik_datasource_type_t;
+
+typedef gpointer (*VikDataSourceAddWidgetsFunc) ( GtkWidget *dialog );
+
+/* if VIK_DATASOURCE_GPSBABEL_DIRECT, babelargs and inputfile.
+   if VIK_DATASOURCE_SHELL_CMD, shellcmd and inputtype.
+   set both to NULL to signal refusal (ie already downloading) */
+typedef void (*VikDataSourceGetCmdStringFunc) ( gpointer widgets_data, gchar **babelargs_or_shellcmd, gchar **inputfile_or_inputtype );
+typedef void (*VikDataSourceFirstCleanupFunc) ( gpointer widgets_data );
+typedef void  (*VikDataSourceProgressFunc)  (gpointer c, gpointer data, acq_dialog_widgets_t *w);
+typedef gpointer  (*VikDataSourceAddProgressWidgetsFunc) ( GtkWidget *dialog );
+typedef void (*VikDataSourceCleanupFunc) ( gpointer progress_widgets_data );
+
+typedef struct {
+  const gchar *layer_title;
+  vik_datasource_type_t type;
+
+  VikDataSourceAddWidgetsFunc add_widgets_func; /* NULL if no first dialog */
+  VikDataSourceGetCmdStringFunc get_cmd_string_func; /* passed rv from above */
+  VikDataSourceFirstCleanupFunc first_cleanup_func; /* frees rv from addwidgets */
+
+  VikDataSourceProgressFunc progress_func;
+  VikDataSourceAddProgressWidgetsFunc add_progress_widgets_func;
+  VikDataSourceCleanupFunc cleanup_func;
+} VikDataSourceInterface;
+
+
+void a_acquire ( VikWindow *vw, VikLayersPanel *vlp, VikViewport *vvp, VikDataSourceInterface *interface );
 
 #endif
index 734a9773dd0665a857581bdd648b2d440677dd96..0cbd6b3f5cc491269e30236bf069ecc7f344e224 100644 (file)
@@ -27,7 +27,7 @@
 /* in the future we could have support for other shells (change command strings), or not use a shell at all */
 #define BASH_LOCATION "/bin/bash"
 
-gboolean a_babel_convert( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb )
+gboolean a_babel_convert( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb, gpointer user_data )
 {
   int fd_src;
   FILE *f;
@@ -41,7 +41,7 @@ gboolean a_babel_convert( VikTrwLayer *vt, const char *babelargs, BabelStatusFun
     f = fdopen(fd_src, "w");
     a_gpx_write_file(vt, f);
     fclose(f);
-    ret = a_babel_convert_from ( vt, bargs, cb, name_src );
+    ret = a_babel_convert_from ( vt, bargs, cb, name_src, user_data );
   }
 
   g_free(bargs);
@@ -50,7 +50,7 @@ gboolean a_babel_convert( VikTrwLayer *vt, const char *babelargs, BabelStatusFun
   return ret;
 }
 
-gboolean babel_general_convert_from( VikTrwLayer *vt, BabelStatusFunc cb, gchar **args, const gchar *name_dst )
+gboolean babel_general_convert_from( VikTrwLayer *vt, BabelStatusFunc cb, gchar **args, const gchar *name_dst, gpointer user_data )
 {
   gboolean ret;
   GPid pid;
@@ -68,9 +68,11 @@ gboolean babel_general_convert_from( VikTrwLayer *vt, BabelStatusFunc cb, gchar
     setvbuf(diag, NULL, _IONBF, 0);
 
     while (fgets(line, sizeof(line), diag)) {
-      cb(BABEL_DIAG_OUTPUT, line);
+      if ( cb )
+        cb(BABEL_DIAG_OUTPUT, line, user_data);
     }
-    cb(BABEL_DONE, NULL);
+    if ( cb )
+      cb(BABEL_DONE, NULL, user_data);
     fclose(diag);
     waitpid(pid, NULL, 0);
     g_spawn_close_pid(pid);
@@ -84,7 +86,7 @@ gboolean babel_general_convert_from( VikTrwLayer *vt, BabelStatusFunc cb, gchar
   return ret;
 }
 
-gboolean a_babel_convert_from( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb, const char *from )
+gboolean a_babel_convert_from( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb, const char *from, gpointer user_data )
 {
   int fd_dst;
   gchar *name_dst;
@@ -105,7 +107,7 @@ gboolean a_babel_convert_from( VikTrwLayer *vt, const char *babelargs, BabelStat
     g_strlcat(cmd, name_dst, sizeof(cmd));
 
     args = g_strsplit(cmd, " ", 0);
-    ret = babel_general_convert_from ( vt, cb, args, name_dst );
+    ret = babel_general_convert_from ( vt, cb, args, name_dst, user_data );
     g_strfreev(args);
   }
 
@@ -114,7 +116,7 @@ gboolean a_babel_convert_from( VikTrwLayer *vt, const char *babelargs, BabelStat
   return ret;
 }
 
-gboolean a_babel_convert_from_shellcommand ( VikTrwLayer *vt, const char *input_cmd, const char *input_type, BabelStatusFunc cb )
+gboolean a_babel_convert_from_shellcommand ( VikTrwLayer *vt, const char *input_cmd, const char *input_type, BabelStatusFunc cb, gpointer user_data )
 {
   int fd_dst;
   gchar *name_dst;
@@ -134,7 +136,7 @@ gboolean a_babel_convert_from_shellcommand ( VikTrwLayer *vt, const char *input_
     args[2] = shell_command;
     args[3] = NULL;
 
-    ret = babel_general_convert_from ( vt, cb, args, name_dst );
+    ret = babel_general_convert_from ( vt, cb, args, name_dst, user_data );
     g_free ( args );
     g_free ( shell_command );
   }
index 46b81da2a2276ec83a0bd09f1d00e647b1c537ed..ba41a8788a63bc161942d1462eea88f8e68e2172 100644 (file)
@@ -28,7 +28,7 @@ typedef enum {
   BABEL_DONE,
 } BabelProgressCode;
 
-typedef void (*BabelStatusFunc)(BabelProgressCode, gpointer);
+typedef void (*BabelStatusFunc)(BabelProgressCode, gpointer, gpointer);
 
 /*
  * a_babel_convert modifies data in a trw layer using gpsbabel filters.  This routine is synchronous;
@@ -46,7 +46,7 @@ typedef void (*BabelStatusFunc)(BabelProgressCode, gpointer);
  *                   BABEL_DIAG_DONE: gpsbabel finished,
  *                 or NULL if no callback is needed.
  */
-int a_babel_convert( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb );
+int a_babel_convert( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb, gpointer user_data );
 
 /*
  * a_babel_convert_from loads data into a trw layer from a file, using gpsbabel.  This routine is synchronous;
@@ -60,8 +60,8 @@ int a_babel_convert( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb
  * 
  * cb             Optional callback function. Same usage as in a_babel_convert.
  */
-int a_babel_convert_from( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb, const char *file );
-gboolean a_babel_convert_from_shellcommand ( VikTrwLayer *vt, const char *input_cmd, const char *input_type, BabelStatusFunc cb );
+int a_babel_convert_from( VikTrwLayer *vt, const char *babelargs, BabelStatusFunc cb, const char *file, gpointer user_data );
+gboolean a_babel_convert_from_shellcommand ( VikTrwLayer *vt, const char *input_cmd, const char *input_type, BabelStatusFunc cb, gpointer user_data );
 
 
 #endif
diff --git a/src/datasource_google.c b/src/datasource_google.c
new file mode 100644 (file)
index 0000000..9324bb7
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@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
+ *
+ */
+#include <string.h>
+#include <glib/gprintf.h>
+
+#include "viking.h"
+#include "babel.h"
+#include "gpx.h"
+#include "acquire.h"
+
+#define GOOGLE_DIRECTIONS_STRING "(wget -O - \"http://maps.google.com/maps?q=%s to %s&output=xml\" 2>/dev/null) | head -3 | tail -1 | sed 's/.*<page>\\(.*\\)<\\/page>.*/<page>\\1<\\/page>/'"
+
+typedef struct {
+  GtkWidget *from_entry, *to_entry;
+} datasource_google_widgets_t;
+
+
+gpointer datasource_google_add_widgets ( GtkWidget *dialog );
+static void datasource_google_get_cmd_string ( datasource_google_widgets_t *widgets, gchar **cmd, gchar **input_type );        
+static void datasource_google_first_cleanup ( gpointer data );
+
+VikDataSourceInterface vik_datasource_google_interface = {
+  "Acquire from Google",
+  VIK_DATASOURCE_SHELL_CMD,
+  (VikDataSourceAddWidgetsFunc)                datasource_google_add_widgets,
+  (VikDataSourceGetCmdStringFunc)      datasource_google_get_cmd_string,
+  (VikDataSourceFirstCleanupFunc)      datasource_google_first_cleanup,
+  (VikDataSourceProgressFunc)          NULL,
+  (VikDataSourceAddProgressWidgetsFunc)        NULL,
+  (VikDataSourceCleanupFunc)           NULL
+};
+
+
+gpointer datasource_google_add_widgets ( GtkWidget *dialog )
+{
+  datasource_google_widgets_t *widgets = g_malloc(sizeof(*widgets));
+  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();
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), from_label, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), widgets->from_entry, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), to_label, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), widgets->to_entry, FALSE, FALSE, 5 );
+  gtk_widget_show_all(dialog);
+  return widgets;
+}
+
+static void datasource_google_get_cmd_string ( datasource_google_widgets_t *widgets, gchar **cmd, gchar **input_type )
+{
+  /* TODO: special characters handling!!! */
+  *cmd = g_strdup_printf( GOOGLE_DIRECTIONS_STRING, gtk_entry_get_text ( GTK_ENTRY(widgets->from_entry) ), gtk_entry_get_text ( GTK_ENTRY(widgets->to_entry) ) );
+  *input_type = g_strdup("google");
+
+}
+
+static void datasource_google_first_cleanup ( gpointer data )
+{
+  g_free ( data );
+}
diff --git a/src/datasource_gps.c b/src/datasource_gps.c
new file mode 100644 (file)
index 0000000..09f7ee2
--- /dev/null
@@ -0,0 +1,217 @@
+/*
+ * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
+ *
+ * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@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
+ *
+ */
+#include <string.h>
+#include <glib/gprintf.h>
+
+#include "viking.h"
+#include "babel.h"
+#include "gpx.h"
+#include "acquire.h"
+
+static gboolean gps_acquire_in_progress = FALSE;
+
+static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
+static void datasource_gps_cleanup ( gpointer data );
+static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
+gpointer datasource_gps_add_progress_widgets ( GtkWidget *dialog );
+
+VikDataSourceInterface vik_datasource_gps_interface = {
+  "Acquire from GPS",
+  VIK_DATASOURCE_GPSBABEL_DIRECT,
+  (VikDataSourceAddWidgetsFunc)                NULL,
+  (VikDataSourceGetCmdStringFunc)      datasource_gps_get_cmd_string,
+  (VikDataSourceFirstCleanupFunc)      NULL,
+  (VikDataSourceProgressFunc)          datasource_gps_progress,
+  (VikDataSourceAddProgressWidgetsFunc)        datasource_gps_add_progress_widgets,
+  (VikDataSourceCleanupFunc)           datasource_gps_cleanup
+};
+
+/*********************************************************
+ * Definitions and routines for acquiring data from GPS
+ *********************************************************/
+
+/* widgets in progress dialog specific to GPS */
+/* also counts needed for progress */
+typedef struct {
+  GtkWidget *gps_label;
+  GtkWidget *ver_label;
+  GtkWidget *id_label;
+  GtkWidget *wp_label;
+  GtkWidget *trk_label;
+  GtkWidget *progress_label;
+  int total_count;
+  int count;
+} gps_acq_dialog_widgets_t;
+
+static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file )
+{
+  if (gps_acquire_in_progress) {
+    *babelargs = *input_file = NULL;
+  }
+
+ gps_acquire_in_progress = TRUE;
+ *babelargs = g_strdup_printf("%s", "-D 9 -t -w -i garmin");
+ *input_file = g_strdup_printf("%s", "/dev/ttyS1" );
+}
+
+static void datasource_gps_cleanup ( gpointer data )
+{
+  g_free ( data );
+  gps_acquire_in_progress = FALSE;
+}
+
+static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
+{
+  gchar s[128];
+  gdk_threads_enter();
+  if (w->ok) {
+    gps_acq_dialog_widgets_t *gps_data = (gps_acq_dialog_widgets_t *)w->specific_data;
+    g_sprintf(s, "Downloading %d %s...", cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
+    gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
+    gtk_widget_show ( gps_data->progress_label );
+    gps_data->total_count = cnt;
+  }
+  gdk_threads_leave();
+}
+
+static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
+{
+  gchar s[128];
+  gdk_threads_enter();
+  if (w->ok) {
+    gps_acq_dialog_widgets_t *gps_data = (gps_acq_dialog_widgets_t *)w->specific_data;
+
+    if (cnt < gps_data->total_count) {
+      g_sprintf(s, "Downloaded %d out of %d %s...", cnt, gps_data->total_count, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
+    } else {
+      g_sprintf(s, "Downloaded %d %s.", cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
+    }    
+    gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
+  }
+  gdk_threads_leave();
+}
+
+static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
+{
+  gchar s[256];
+  gdk_threads_enter();
+  if (w->ok) {
+    g_sprintf(s, "GPS Device: %s", info);
+    gtk_label_set_text ( GTK_LABEL(((gps_acq_dialog_widgets_t *)w->specific_data)->gps_label), s );
+  }
+  gdk_threads_leave();
+}
+
+/* 
+ * This routine relies on gpsbabel's diagnostic output to display the progress information. 
+ * These outputs differ when different GPS devices are used, so we will need to test
+ * them on several and add the corresponding support.
+ */
+static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
+{
+  gchar *line;
+  gps_acq_dialog_widgets_t *gps_data = (gps_acq_dialog_widgets_t *)w->specific_data;
+
+  /* TODO: move to datasource.c */
+  gdk_threads_enter ();
+  if (!w->ok) {
+    g_free ( w );
+    w = NULL;
+    gps_acquire_in_progress = FALSE;
+    gdk_threads_leave();
+    g_thread_exit ( NULL );
+  }
+  gdk_threads_leave ();
+
+  switch(c) {
+  case BABEL_DIAG_OUTPUT:
+    line = (gchar *)data;
+
+    /* tells us how many items there will be */
+    if (strstr(line, "Xfer Wpt")) { 
+      gps_data->progress_label = gps_data->wp_label;
+    }
+    if (strstr(line, "Xfer Trk")) { 
+      gps_data->progress_label = gps_data->trk_label;
+    }
+    if (strstr(line, "PRDDAT")) {
+      gchar **tokens = g_strsplit(line, " ", 0);
+      gchar info[128];
+      int ilen = 0;
+      int i;
+
+      for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
+       guint ch;
+       sscanf(tokens[i], "%x", &ch);
+       info[ilen++] = ch;
+      }
+      info[ilen++] = 0;
+      set_gps_info(info, w);
+    }
+    if (strstr(line, "RECORD")) { 
+      int lsb, msb, cnt;
+
+      sscanf(line+17, "%x", &lsb); 
+      sscanf(line+20, "%x", &msb);
+      cnt = lsb + msb * 256;
+      set_total_count(cnt, w);
+      gps_data->count = 0;
+    }
+    if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
+      gps_data->count++;
+      set_current_count(gps_data->count, w);
+    }
+    break;
+  case BABEL_DONE:
+    break;
+  default:
+    break;
+  }
+}
+
+gpointer datasource_gps_add_progress_widgets ( GtkWidget *dialog )
+{
+  GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
+
+  gps_acq_dialog_widgets_t *w_gps = g_malloc(sizeof(*w_gps));
+
+  gpslabel = gtk_label_new ("GPS device: N/A");
+  verlabel = gtk_label_new ("");
+  idlabel = gtk_label_new ("");
+  wplabel = gtk_label_new ("");
+  trklabel = gtk_label_new ("");
+
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
+  gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
+
+  gtk_window_set_title ( GTK_WINDOW(dialog), "Acquire data from GPS" );
+
+  gtk_widget_show_all ( dialog );
+
+  w_gps->gps_label = gpslabel;
+  w_gps->id_label = idlabel;
+  w_gps->ver_label = verlabel;
+  w_gps->progress_label = w_gps->wp_label = wplabel;
+  w_gps->trk_label = trklabel;
+  w_gps->total_count = -1;
+  return w_gps;
+}
diff --git a/src/datasources.h b/src/datasources.h
new file mode 100644 (file)
index 0000000..297ef30
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef __VIK_DATASOURCES_H
+#define __VIK_DATASOURCES_H
+extern VikDataSourceInterface vik_datasource_gps_interface;
+extern VikDataSourceInterface vik_datasource_google_interface;
+#endif
index 832e7103308d7382c35e15ae3e82c78f4bf92328..33b4cac80620346901266515a6088de880235440 100644 (file)
@@ -8,10 +8,14 @@ static const char *menu_xml =
        "      <menuitem action='New'/>"
        "      <menuitem action='Open'/>"
        "      <menuitem action='Append'/>"
-       "      <menuitem action='Acquire'/>"
        "      <menuitem action='Save'/>"
        "      <menuitem action='SaveAs'/>"
        "      <separator/>"
+       "      <menu action='Acquire'>"
+       "        <menuitem action='AcquireGPS'/>"
+       "        <menuitem action='AcquireGoogle'/>"
+       "      </menu>"
+       "      <separator/>"
        "      <menuitem action='GenImg'/>"
        "      <menuitem action='GenImgDir'/>"
        "      <separator/>"
index a9fe0dfd6cb73765044b4e549d15bab7140b5228..6166f1782ed369d54e1d650b1303581cd3f8a68f 100644 (file)
@@ -21,6 +21,7 @@
 #include "viking.h"
 #include "background.h"
 #include "acquire.h"
+#include "datasources.h"
 
 #define VIKING_TITLE " - Viking " VIKING_VERSION " " VIKING_VERSION_NAME " " VIKING_URL
 
@@ -907,7 +908,12 @@ static gboolean save_file ( GtkAction *a, VikWindow *vw )
 
 static void acquire_from_gps ( GtkAction *a, VikWindow *vw )
 {
-  a_acquire_from_gps(vw, vw->viking_vlp, vw->viking_vvp );
+  a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_gps_interface );
+}
+
+static void acquire_from_google ( GtkAction *a, VikWindow *vw )
+{
+  a_acquire(vw, vw->viking_vlp, vw->viking_vvp, &vik_datasource_google_interface );
 }
 
 static void clear_cb ( GtkAction *a, VikWindow *vw )
@@ -1303,7 +1309,9 @@ static GtkActionEntry entries[] = {
   { "New",       GTK_STOCK_NEW,          "_New",                          "<control>N", "New file",                                     (GCallback)newwindow_cb          },
   { "Open",      GTK_STOCK_OPEN,         "_Open",                         "<control>O", "Open a file",                                  (GCallback)load_file             },
   { "Append",    GTK_STOCK_ADD,          "A_ppend File",                  NULL,         "Append data from a different file",            (GCallback)load_file             },
-  { "Acquire",   NULL,                   "A_cquire from GPS",             NULL,         "Transfer data from a GPS device",              (GCallback)acquire_from_gps      },
+  { "Acquire", NULL, "A_cquire", 0, 0, 0 },
+  { "AcquireGPS",   NULL,                "From _GPS",                    NULL,         "Transfer data from a GPS device",              (GCallback)acquire_from_gps      },
+  { "AcquireGoogle",   NULL,             "Google _Directions",           NULL,         "Get driving directions from Google",           (GCallback)acquire_from_google      },
   { "Save",      GTK_STOCK_SAVE,         "_Save",                         "<control>S", "Save the file",                                (GCallback)save_file             },
   { "SaveAs",    GTK_STOCK_SAVE_AS,      "Save _As",                      NULL,         "Save the file under different name",           (GCallback)save_file_as          },
   { "GenImg",    GTK_STOCK_CLEAR,        "_Generate Image File",          NULL,         "Save a snapshot of the workspace into a file", (GCallback)draw_to_image_file_cb },