X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/8cf048bdcfc9bb814b004549ff9319201fe22030..e044ae9e96b95fc6e58b4f05f759e5fc59bb79ab:/src/acquire.c?ds=sidebyside diff --git a/src/acquire.c b/src/acquire.c index 1da404c9..1c47a151 100644 --- a/src/acquire.c +++ b/src/acquire.c @@ -24,209 +24,188 @@ #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>.*/\\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 ); } +