#include "viking.h"
#include "babel.h"
#include "gpx.h"
+#include "acquire.h"
+
+/* passed along to worker thread */
+typedef struct {
+ acq_dialog_widgets_t *w;
+ gchar *cmd;
+ gchar *extra;
+} w_and_interface_t;
+
+extern VikDataSourceInterface vik_datasource_gps_interface;
+extern VikDataSourceInterface vik_datasource_google_interface;
/*********************************************************
- * Definitions and routines for acquiring data from GPS
+ * Definitions and routines for acquiring data from Data Sources in general
*********************************************************/
-/* global data structure used to expose the progress dialog to the 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)
+static void progress_func ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
{
- 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_enter ();
+ if (!w->ok) {
+ if ( w->interface->cleanup_func )
+ w->interface->cleanup_func( w->user_data );
+ g_free ( w );
+ gdk_threads_leave();
+ g_thread_exit ( NULL );
}
- gdk_threads_leave();
-}
+ 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();
+ if ( w->interface->progress_func )
+ w->interface->progress_func ( (gpointer) c, data, w );
}
-static void set_gps_info(const gchar *info)
+/* this routine is the worker thread. there is only one simultaneous download allowed */
+static void get_from_anything ( w_and_interface_t *wi )
{
- 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();
-}
+ gchar *cmd = wi->cmd;
+ gchar *extra = wi->extra;
+ gboolean result;
+ VikTrwLayer *vtl;
-/*
- * 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;
+ gboolean creating_new_layer = TRUE;
- switch(c) {
- case BABEL_DIAG_OUTPUT:
- line = (gchar *)data;
+ acq_dialog_widgets_t *w = wi->w;
+ VikDataSourceInterface *interface = wi->w->interface;
+ g_free ( wi );
- /* 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);
+ gdk_threads_enter();
+ if (interface->mode == VIK_DATASOURCE_ADDTOLAYER) {
+ VikLayer *current_selected = vik_layers_panel_get_selected ( w->vlp );
+ if ( IS_VIK_TRW_LAYER(current_selected) ) {
+ vtl = VIK_TRW_LAYER(current_selected);
+ creating_new_layer = FALSE;
}
- break;
- case BABEL_DONE:
- break;
- default:
- break;
}
-}
-
-/* this routine is the worker thread. there is only one simultaneous download allowed */
-static void get_from_gps ( gpointer data )
-{
- VikTrwLayer *vtl;
-
- if ( w ) {
- /* simultaneous downloads are not allowed, so we return. */
- g_free(data);
- g_thread_exit ( NULL );
- return;
+ if ( creating_new_layer ) {
+ vtl = VIK_TRW_LAYER ( vik_layer_create ( VIK_LAYER_TRW, w->vvp, NULL, FALSE ) );
+ vik_layer_rename ( VIK_LAYER ( vtl ), interface->layer_title );
+ gtk_label_set_text ( GTK_LABEL(w->status), "Working..." );
}
+ gdk_threads_leave();
- w = data;
+ if ( interface->type == VIK_DATASOURCE_GPSBABEL_DIRECT )
+ result = a_babel_convert_from (vtl, cmd, (BabelStatusFunc) progress_func, extra, w);
+ else
+ result = a_babel_convert_from_shellcommand ( vtl, cmd, extra, (BabelStatusFunc) progress_func, w);
- 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" );
- gtk_label_set_text ( GTK_LABEL(w->status), "Working..." );
- gdk_threads_leave();
+ g_free ( cmd );
+ g_free ( extra );
- 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 (!result) {
gdk_threads_enter();
gtk_label_set_text ( GTK_LABEL(w->status), "Error: couldn't find gpsbabel." );
+ if ( creating_new_layer )
+ g_object_unref ( G_OBJECT ( vtl ) );
gdk_threads_leave();
}
+ else {
+ gdk_threads_enter();
+ if (w->ok) {
+ gtk_label_set_text ( GTK_LABEL(w->status), "Done." );
+ if ( creating_new_layer )
+ vik_aggregate_layer_add_layer( vik_layers_panel_get_top_layer(w->vlp), VIK_LAYER(vtl));
+ 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 */
+ if ( creating_new_layer )
+ g_object_unref(vtl);
+ }
+ }
+ if ( interface->cleanup_func )
+ interface->cleanup_func ( w->user_data );
- gdk_threads_enter();
- if (w->ok) {
- gtk_label_set_text ( GTK_LABEL(w->status), "Done." );
- vik_aggregate_layer_add_layer( vik_layers_panel_get_top_layer(w->vlp), VIK_LAYER(vtl));
- 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 );
+ if ( w->ok ) {
+ w->ok = FALSE;
} else {
- g_object_unref(vtl);
+ g_free ( w );
}
- g_free ( w );
- w = NULL;
+
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;
+ gpointer user_data;
+
+ w_and_interface_t *wi;
+
+ g_assert(interface->init_func);
+ user_data = interface->init_func();
+
+ if ( interface->check_existence_func ) {
+ gchar *error_str = interface->check_existence_func();
+ if ( error_str ) {
+ a_dialog_error_msg ( GTK_WINDOW(vw), error_str );
+ g_free ( error_str );
+ return;
+ }
+ }
- 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 );
+ if ( interface->add_setup_widgets_func ) {
+ dialog = gtk_dialog_new_with_buttons ( "", GTK_WINDOW(vw), 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL );
- 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");
+ interface->add_setup_widgets_func(dialog, vvp, user_data);
+ gtk_window_set_title ( GTK_WINDOW(dialog), interface->window_title );
- 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 );
+ if ( gtk_dialog_run ( GTK_DIALOG(dialog) ) != GTK_RESPONSE_ACCEPT ) {
+ interface->cleanup_func(user_data);
+ gtk_widget_destroy(dialog);
+ return;
+ }
+ interface->get_cmd_string_func ( user_data, &cmd, &extra );
+ gtk_widget_destroy(dialog);
+ dialog = NULL;
+ } else
+ interface->get_cmd_string_func ( user_data, &cmd, &extra );
+
+ if ( ! cmd )
+ return;
- gtk_window_set_title ( GTK_WINDOW(dialog), "Acquire data from GPS" );
+ w = g_malloc(sizeof(*w));
+ wi = g_malloc(sizeof(*wi));
+ wi->w = w;
+ wi->w->interface = interface;
+ wi->cmd = cmd;
+ wi->extra = extra;
+
+ dialog = gtk_dialog_new_with_buttons ( "", GTK_WINDOW(vw), 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 );
+ gtk_window_set_title ( GTK_WINDOW(dialog), interface->window_title );
- 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 ) {
+ interface->add_progress_widgets_func ( dialog, user_data );
+ }
+ w->user_data = user_data;
+
+
+ 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 );
}
+