From 7b3479e34ba8ee93508df7b3b6b9d7fe9a257a27 Mon Sep 17 00:00:00 2001 From: Evan Battaglia Date: Fri, 25 Nov 2005 22:22:17 +0000 Subject: [PATCH] Data sources core structure, google directions --- ChangeLog | 5 + TODO | 7 +- src/Makefile.am | 5 +- src/acquire.c | 249 +++++++++++++++------------------------- src/acquire.h | 40 ++++++- src/babel.c | 20 ++-- src/babel.h | 8 +- src/datasource_google.c | 79 +++++++++++++ src/datasource_gps.c | 217 ++++++++++++++++++++++++++++++++++ src/datasources.h | 5 + src/menu.xml.h | 6 +- src/vikwindow.c | 12 +- 12 files changed, 476 insertions(+), 177 deletions(-) create mode 100644 src/datasource_google.c create mode 100644 src/datasource_gps.c create mode 100644 src/datasources.h diff --git a/ChangeLog b/ChangeLog index 2290a596..6d1869aa 100644 --- 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 * src/gpx.c (gpx_dtostr): add better GPX export Evan Battaglia : diff --git a/TODO b/TODO index 7432d73c..b3fcf06b 100644 --- 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 diff --git a/src/Makefile.am b/src/Makefile.am index 814ab7b5..b8f55be7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -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@ diff --git a/src/acquire.c b/src/acquire.c index 1da404c9..1d127131 100644 --- a/src/acquire.c +++ b/src/acquire.c @@ -24,148 +24,51 @@ #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>.*/\\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 ); } + diff --git a/src/acquire.h b/src/acquire.h index cd196022..bef7b34b 100644 --- a/src/acquire.h +++ b/src/acquire.h @@ -22,6 +22,44 @@ #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 diff --git a/src/babel.c b/src/babel.c index 734a9773..0cbd6b3f 100644 --- a/src/babel.c +++ b/src/babel.c @@ -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 ); } diff --git a/src/babel.h b/src/babel.h index 46b81da2..ba41a878 100644 --- a/src/babel.h +++ b/src/babel.h @@ -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 index 00000000..9324bb7a --- /dev/null +++ b/src/datasource_google.c @@ -0,0 +1,79 @@ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2003-2005, Evan Battaglia + * + * 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 +#include + +#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>.*/\\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 index 00000000..09f7ee2a --- /dev/null +++ b/src/datasource_gps.c @@ -0,0 +1,217 @@ +/* + * viking -- GPS Data and Topo Analyzer, Explorer, and Manager + * + * Copyright (C) 2003-2005, Evan Battaglia + * + * 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 +#include + +#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 index 00000000..297ef301 --- /dev/null +++ b/src/datasources.h @@ -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 diff --git a/src/menu.xml.h b/src/menu.xml.h index 832e7103..33b4cac8 100644 --- a/src/menu.xml.h +++ b/src/menu.xml.h @@ -8,10 +8,14 @@ static const char *menu_xml = " " " " " " - " " " " " " " " + " " + " " + " " + " " + " " " " " " " " diff --git a/src/vikwindow.c b/src/vikwindow.c index a9fe0dfd..6166f178 100644 --- a/src/vikwindow.c +++ b/src/vikwindow.c @@ -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", "N", "New file", (GCallback)newwindow_cb }, { "Open", GTK_STOCK_OPEN, "_Open", "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", "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 }, -- 2.39.5