* viking -- GPS Data and Topo Analyzer, Explorer, and Manager
*
* Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
+ * Copyright (C) 2006-2008, Quy Tonthat <qtonthat@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
#include "icons/icons.h"
#include "babel.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
-#include <glib.h>
+#include <glib/gstdio.h>
#include <glib/gprintf.h>
#include <glib/gi18n.h>
#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
static void vik_gps_layer_realize ( VikGpsLayer *val, VikTreeview *vt, GtkTreeIter *layer_iter );
static void vik_gps_layer_free ( VikGpsLayer *val );
static void vik_gps_layer_draw ( VikGpsLayer *val, gpointer data );
-VikGpsLayer *vik_gps_layer_new ();
+static VikGpsLayer *vik_gps_layer_new ( VikViewport *vp );
static void gps_layer_marshall( VikGpsLayer *val, guint8 **data, gint *len );
static VikGpsLayer *gps_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
-static gboolean gps_layer_set_param ( VikGpsLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp );
-static VikLayerParamData gps_layer_get_param ( VikGpsLayer *vgl, guint16 id );
+static gboolean gps_layer_set_param ( VikGpsLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation );
+static VikLayerParamData gps_layer_get_param ( VikGpsLayer *vgl, guint16 id, gboolean is_file_operation );
+
+static const gchar* gps_layer_tooltip ( VikGpsLayer *vgl );
static void gps_layer_change_coord_mode ( VikGpsLayer *val, VikCoordMode mode );
static void gps_layer_add_menu_items( VikGpsLayer *vtl, GtkMenu *menu, gpointer vlp );
static void gps_empty_download_cb( gpointer layer_and_vlp[2] );
static void gps_empty_all_cb( gpointer layer_and_vlp[2] );
#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
+static void gps_empty_realtime_cb( gpointer layer_and_vlp[2] );
static void gps_start_stop_tracking_cb( gpointer layer_and_vlp[2] );
static void realtime_tracking_draw(VikGpsLayer *vgl, VikViewport *vp);
#endif
-typedef enum {GARMIN_P = 0, MAGELLAN_P, NUM_PROTOCOLS} vik_gps_proto;
-static gchar * params_protocols[] = {"Garmin", "Magellan", NULL};
-static gchar * protocols_args[] = {"garmin", "magellan"};
+typedef enum {GARMIN_P = 0, MAGELLAN_P, DELORME_P, NAVILINK_P, NUM_PROTOCOLS} vik_gps_proto;
+static gchar * params_protocols[] = {"Garmin", "Magellan", "DeLorme", "NAViLink", NULL};
+static gchar * protocols_args[] = {"garmin", "magellan", "delbin", "navilink"};
/*#define NUM_PROTOCOLS (sizeof(params_protocols)/sizeof(params_protocols[0]) - 1) */
#ifdef WINDOWS
static gchar * params_ports[] = {"com1", "usb:", NULL};
#else
static gchar * params_ports[] = {"/dev/ttyS0", "/dev/ttyS1", "/dev/ttyUSB0", "/dev/ttyUSB1", "usb:", NULL};
#endif
-#define NUM_PORTS (sizeof(params_ports)/sizeof(params_ports[0]) - 1)
+/* NUM_PORTS not actually used */
+/* #define NUM_PORTS (sizeof(params_ports)/sizeof(params_ports[0]) - 1) */
/* Compatibility with previous versions */
#ifdef WINDOWS
static gchar * old_params_ports[] = {"com1", "usb:", NULL};
GtkWidget *wp_label;
GtkWidget *progress_label;
GtkWidget *trk_label;
+ VikViewport *vvp;
+#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
+ gboolean realtime_tracking;
+#endif
} GpsSession;
static void gps_session_delete(GpsSession *sess);
params_groups,
sizeof(params_groups)/sizeof(params_groups[0]),
- VIK_MENU_ITEM_ALL & ~(VIK_MENU_ITEM_CUT|VIK_MENU_ITEM_COPY),
+ VIK_MENU_ITEM_ALL,
(VikLayerFuncCreate) vik_gps_layer_create,
(VikLayerFuncRealize) vik_gps_layer_realize,
(VikLayerFuncSublayerRenameRequest) NULL,
(VikLayerFuncSublayerToggleVisible) NULL,
+ (VikLayerFuncSublayerTooltip) NULL,
+ (VikLayerFuncLayerTooltip) gps_layer_tooltip,
+ (VikLayerFuncLayerSelected) NULL,
(VikLayerFuncMarshall) gps_layer_marshall,
(VikLayerFuncUnmarshall) gps_layer_unmarshall,
(VikLayerFuncWriteFileData) NULL,
(VikLayerFuncDeleteItem) NULL,
+ (VikLayerFuncCutItem) NULL,
(VikLayerFuncCopyItem) NULL,
(VikLayerFuncPasteItem) NULL,
(VikLayerFuncFreeCopiedItem) NULL,
(VikLayerFuncDragDropRequest) gps_layer_drag_drop_request,
+
+ (VikLayerFuncSelectClick) NULL,
};
enum {TRW_DOWNLOAD=0, TRW_UPLOAD,
return rv;
}
+static const gchar* gps_layer_tooltip ( VikGpsLayer *vgl )
+{
+ return params_protocols[vgl->protocol_id];
+}
+
/* "Copy" */
static void gps_layer_marshall( VikGpsLayer *vgl, guint8 **data, gint *datalen )
{
len -= sizeof(gint) + alm_size; \
data += sizeof(gint) + alm_size;
- VikGpsLayer *rv = vik_gps_layer_new();
+ VikGpsLayer *rv = vik_gps_layer_new(vvp);
VikLayer *child_layer;
gint i;
#undef alm_next
}
-static gboolean gps_layer_set_param ( VikGpsLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp )
+static gboolean gps_layer_set_param ( VikGpsLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp, gboolean is_file_operation )
{
switch ( id )
{
return TRUE;
}
-static VikLayerParamData gps_layer_get_param ( VikGpsLayer *vgl, guint16 id )
+static VikLayerParamData gps_layer_get_param ( VikGpsLayer *vgl, guint16 id, gboolean is_file_operation )
{
VikLayerParamData rv;
switch ( id )
vgl->protocol_id = 0;
vgl->serial_port = NULL;
+#ifndef WINDOWS
+ /* Attempt to auto set default USB serial port entry */
+ /* Ordered to make lowest device favourite if available */
+ if (g_access ("/dev/ttyUSB1", R_OK) == 0) {
+ if (vgl->serial_port != NULL)
+ g_free (vgl->serial_port);
+ vgl->serial_port = g_strdup ("/dev/ttyUSB1");
+ }
+ if (g_access ("/dev/ttyUSB0", R_OK) == 0) {
+ if (vgl->serial_port != NULL)
+ g_free (vgl->serial_port);
+ vgl->serial_port = g_strdup ("/dev/ttyUSB0");
+ }
+#endif
+
return vgl;
}
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( _("Upload to GPS") );
+ item = gtk_menu_item_new_with_mnemonic ( _("_Upload to GPS") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(gps_upload_cb), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( _("Download from GPS") );
+ item = gtk_menu_item_new_with_mnemonic ( _("Download from _GPS") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(gps_download_cb), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
- item = gtk_menu_item_new_with_label ( vgl->realtime_tracking ?
- "Stop realtime tracking" :
- "Start realtime tracking" );
+ item = gtk_menu_item_new_with_mnemonic ( vgl->realtime_tracking ?
+ "_Stop Realtime Tracking" :
+ "_Start Realtime Tracking" );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(gps_start_stop_tracking_cb), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
item = gtk_menu_item_new();
gtk_menu_shell_append ( GTK_MENU_SHELL(menu), item );
gtk_widget_show ( item );
+
+ item = gtk_menu_item_new_with_mnemonic ( _("Empty _Realtime") );
+ g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(gps_empty_realtime_cb), pass_along );
+ gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
+ gtk_widget_show ( item );
#endif /* VIK_CONFIG_REALTIME_GPS_TRACKING */
- item = gtk_menu_item_new_with_label ( _("Empty Upload") );
+ item = gtk_menu_item_new_with_mnemonic ( _("E_mpty Upload") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(gps_empty_upload_cb), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( _("Empty Download") );
+ item = gtk_menu_item_new_with_mnemonic ( _("_Empty Download") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(gps_empty_download_cb), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
- item = gtk_menu_item_new_with_label ( _("Empty All") );
+ item = gtk_menu_item_new_with_mnemonic ( _("Empty _All") );
g_signal_connect_swapped ( G_OBJECT(item), "activate", G_CALLBACK(gps_empty_all_cb), pass_along );
gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
gtk_widget_show ( item );
static void disconnect_layer_signal ( VikLayer *vl, VikGpsLayer *vgl )
{
- g_assert(DISCONNECT_UPDATE_SIGNAL(vl,vgl)==1);
+ guint number_handlers = DISCONNECT_UPDATE_SIGNAL(vl,vgl);
+ if ( number_handlers != 1 ) {
+ /*
+ NB It's not fatal if this gives 2 for example! Hence removal of the g_assert
+ This happens when copied GPS layer is deleted (not sure why the number_handlers would be 2)
+ I don't think there's any side effects and certainly better than the program just aborting
+ */
+ g_warning(_("Unexpected number of disconnected handlers: %d"), number_handlers);
+ }
}
static void vik_gps_layer_free ( VikGpsLayer *vgl )
}
g_strfreev(tokens);
}
+ /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
+ if (strstr(line, "Unit:")) {
+ gchar **tokens = g_strsplit(line, "\t", 0);
+ int n_tokens = 0;
+ while (tokens[n_tokens])
+ n_tokens++;
+
+ if (n_tokens > 1) {
+ set_gps_info(tokens[1], sess);
+ }
+ g_strfreev(tokens);
+ }
if (strstr(line, "RECORD")) {
int lsb, msb, cnt;
gtk_label_set_text ( GTK_LABEL(sess->status_label), _("Done.") );
gtk_dialog_set_response_sensitive ( GTK_DIALOG(sess->dialog), GTK_RESPONSE_ACCEPT, TRUE );
gtk_dialog_set_response_sensitive ( GTK_DIALOG(sess->dialog), GTK_RESPONSE_REJECT, FALSE );
+
+ /* Do not change the view if we are following the current GPS position */
+#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
+ if (!sess->realtime_tracking)
+#endif
+ {
+ if (sess->vvp) {
+ /* View the data available */
+ vik_trw_layer_auto_set_view ( sess->vtl, sess->vvp) ;
+ vik_layer_emit_update ( VIK_LAYER(sess->vtl) );
+ }
+ }
} else {
/* canceled */
}
g_thread_exit(NULL);
}
-static gint gps_comm(VikTrwLayer *vtl, gps_dir dir, vik_gps_proto proto, gchar *port) {
+static gint gps_comm(VikTrwLayer *vtl, gps_dir dir, vik_gps_proto proto, gchar *port, gboolean tracking, VikViewport *vvp) {
GpsSession *sess = g_malloc(sizeof(GpsSession));
sess->mutex = g_mutex_new();
sess->cmd_args = g_strdup_printf("-D 9 -t -w -%c %s",
(dir == GPS_DOWN) ? 'i' : 'o', protocols_args[proto]);
sess->window_title = (dir == GPS_DOWN) ? _("GPS Download") : _("GPS Upload");
-
+ sess->vvp = vvp;
+#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
+ sess->realtime_tracking = tracking;
+#endif
sess->dialog = gtk_dialog_new_with_buttons ( "", VIK_GTK_WINDOW_FROM_LAYER(vtl), 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL );
gtk_dialog_set_response_sensitive ( GTK_DIALOG(sess->dialog),
GTK_RESPONSE_ACCEPT, FALSE );
/* TODO: starting gps read/write thread here */
g_thread_create((GThreadFunc)gps_comm_thread, sess, FALSE, NULL );
+ gtk_dialog_set_default_response ( GTK_DIALOG(sess->dialog), GTK_RESPONSE_ACCEPT );
gtk_dialog_run(GTK_DIALOG(sess->dialog));
gtk_widget_destroy(sess->dialog);
{
VikGpsLayer *vgl = (VikGpsLayer *)layer_and_vlp[0];
VikTrwLayer *vtl = vgl->trw_children[TRW_UPLOAD];
- gps_comm(vtl, GPS_UP, vgl->protocol_id, vgl->serial_port);
+ gps_comm(vtl, GPS_UP, vgl->protocol_id, vgl->serial_port, FALSE, NULL);
}
static void gps_download_cb( gpointer layer_and_vlp[2] )
{
VikGpsLayer *vgl = (VikGpsLayer *)layer_and_vlp[0];
VikTrwLayer *vtl = vgl->trw_children[TRW_DOWNLOAD];
- gps_comm(vtl, GPS_DOWN, vgl->protocol_id, vgl->serial_port);
+ VikWindow *vw = VIK_WINDOW(VIK_GTK_WINDOW_FROM_LAYER(vgl));
+ VikViewport *vvp = vik_window_viewport(vw);
+#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
+ gps_comm(vtl, GPS_DOWN, vgl->protocol_id, vgl->serial_port, vgl->realtime_tracking, vvp);
+#else
+ gps_comm(vtl, GPS_DOWN, vgl->protocol_id, vgl->serial_port, FALSE, vvp);
+#endif
}
static void gps_empty_upload_cb( gpointer layer_and_vlp[2] )
vik_trw_layer_delete_all_tracks ( vgl-> trw_children[TRW_DOWNLOAD]);
}
+#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
+static void gps_empty_realtime_cb( gpointer layer_and_vlp[2] )
+{
+ VikGpsLayer *vgl = (VikGpsLayer *)layer_and_vlp[0];
+ vik_trw_layer_delete_all_waypoints ( vgl-> trw_children[TRW_REALTIME]);
+ vik_trw_layer_delete_all_tracks ( vgl-> trw_children[TRW_REALTIME]);
+}
+#endif
+
static void gps_empty_all_cb( gpointer layer_and_vlp[2] )
{
VikGpsLayer *vgl = (VikGpsLayer *)layer_and_vlp[0];
vik_trw_layer_delete_all_tracks ( vgl-> trw_children[TRW_UPLOAD]);
vik_trw_layer_delete_all_waypoints ( vgl-> trw_children[TRW_DOWNLOAD]);
vik_trw_layer_delete_all_tracks ( vgl-> trw_children[TRW_DOWNLOAD]);
+#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
+ vik_trw_layer_delete_all_waypoints ( vgl-> trw_children[TRW_REALTIME]);
+ vik_trw_layer_delete_all_tracks ( vgl-> trw_children[TRW_REALTIME]);
+#endif
}
#ifdef VIK_CONFIG_REALTIME_GPS_TRACKING
vgl->first_realtime_trackpoint = FALSE;
create_realtime_trackpoint(vgl, FALSE);
+ gdk_threads_enter();
vik_layer_emit_update ( update_all ? VIK_LAYER(vgl) : VIK_LAYER(vgl->trw_children[TRW_REALTIME]));
+ gdk_threads_leave();
}
}