X-Git-Url: https://git.street.me.uk/andy/viking.git/blobdiff_plain/aceb8e9c7b3233d61807e7339fa29979b4fe62ee..e13ab673e45ea48de49661f7838e75925f405514:/src/vikgpslayer.c?ds=inline diff --git a/src/vikgpslayer.c b/src/vikgpslayer.c index d06f5a32..d3e877ba 100644 --- a/src/vikgpslayer.c +++ b/src/vikgpslayer.c @@ -31,10 +31,13 @@ #include "icons/icons.h" #include "babel.h" +#ifdef HAVE_UNISTD_H +#include +#endif #ifdef HAVE_STRING_H #include #endif -#include +#include #include #include #ifdef VIK_CONFIG_REALTIME_GPS_TRACKING @@ -52,7 +55,7 @@ static VikGpsLayer *vik_gps_layer_create (VikViewport *vp); 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 ); @@ -82,7 +85,15 @@ 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}; +#else +static gchar * old_params_ports[] = {"/dev/ttyS0", "/dev/ttyS1", "/dev/ttyUSB0", "/dev/ttyUSB1", "usb:", NULL}; +#endif +#define OLD_NUM_PORTS (sizeof(old_params_ports)/sizeof(old_params_ports[0]) - 1) typedef enum {GPS_DOWN=0, GPS_UP} gps_dir; typedef struct { @@ -131,7 +142,7 @@ enum { static VikLayerParam gps_layer_params[] = { { "gps_protocol", VIK_LAYER_PARAM_UINT, GROUP_DATA_MODE, N_("GPS Protocol:"), VIK_LAYER_WIDGET_COMBOBOX, params_protocols, NULL}, - { "gps_port", VIK_LAYER_PARAM_UINT, GROUP_DATA_MODE, N_("Serial Port:"), VIK_LAYER_WIDGET_COMBOBOX, params_ports, NULL}, + { "gps_port", VIK_LAYER_PARAM_STRING, GROUP_DATA_MODE, N_("Serial Port:"), VIK_LAYER_WIDGET_COMBOBOX, params_ports, NULL}, #ifdef VIK_CONFIG_REALTIME_GPS_TRACKING { "record_tracking", VIK_LAYER_PARAM_BOOLEAN, GROUP_REALTIME_MODE, N_("Recording tracks"), VIK_LAYER_WIDGET_CHECKBUTTON}, @@ -161,7 +172,7 @@ VikLayerInterface vik_gps_layer_interface = { 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, @@ -255,7 +266,7 @@ struct _VikGpsLayer { guint vehicle_position; #endif /* VIK_CONFIG_REALTIME_GPS_TRACKING */ guint protocol_id; - guint serial_port_id; + gchar *serial_port; }; GType vik_gps_layer_get_type () @@ -337,7 +348,7 @@ static VikGpsLayer *gps_layer_unmarshall( guint8 *data, gint len, VikViewport *v 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; @@ -371,8 +382,21 @@ static gboolean gps_layer_set_param ( VikGpsLayer *vgl, guint16 id, VikLayerPara g_warning(_("Unknown GPS Protocol")); break; case PARAM_PORT: - if (data.u < NUM_PORTS) - vgl->serial_port_id = data.u; + if (data.s) +{ + g_free(vgl->serial_port); + /* Compat: previous version stored serial_port as an array index */ + int index = data.s[0] - '0'; + if (data.s[0] != '\0' && + g_ascii_isdigit (data.s[0]) && + data.s[1] == '\0' && + index < OLD_NUM_PORTS) + /* It is a single digit: activate compatibility */ + vgl->serial_port = g_strdup(old_params_ports[index]); + else + vgl->serial_port = g_strdup(data.s); + g_debug("%s: %s", __FUNCTION__, vgl->serial_port); +} else g_warning(_("Unknown serial port device")); break; @@ -416,7 +440,8 @@ static VikLayerParamData gps_layer_get_param ( VikGpsLayer *vgl, guint16 id ) rv.u = vgl->protocol_id; break; case PARAM_PORT: - rv.u = vgl->serial_port_id; + rv.s = vgl->serial_port; + g_debug("%s: %s", __FUNCTION__, rv.s); break; #ifdef VIK_CONFIG_REALTIME_GPS_TRACKING case PARAM_GPSD_HOST: @@ -479,7 +504,22 @@ VikGpsLayer *vik_gps_layer_new (VikViewport *vp) vgl->gpsd_retry_interval = 10; #endif /* VIK_CONFIG_REALTIME_GPS_TRACKING */ vgl->protocol_id = 0; - vgl->serial_port_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; } @@ -580,7 +620,15 @@ static void gps_layer_add_menu_items( VikGpsLayer *vgl, GtkMenu *menu, gpointer 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 ) @@ -830,6 +878,18 @@ static void gps_download_progress_func(BabelProgressCode c, gpointer data, GpsSe } 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; @@ -1033,14 +1093,14 @@ static void gps_upload_cb( gpointer layer_and_vlp[2] ) { VikGpsLayer *vgl = (VikGpsLayer *)layer_and_vlp[0]; VikTrwLayer *vtl = vgl->trw_children[TRW_UPLOAD]; - gps_comm(vtl, GPS_UP, vgl->protocol_id, params_ports[vgl->serial_port_id]); + gps_comm(vtl, GPS_UP, vgl->protocol_id, vgl->serial_port); } 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, params_ports[vgl->serial_port_id]); + gps_comm(vtl, GPS_DOWN, vgl->protocol_id, vgl->serial_port); } static void gps_empty_upload_cb( gpointer layer_and_vlp[2] ) @@ -1226,7 +1286,7 @@ static void gpsd_raw_hook(VglGpsd *vgpsd, gchar *data) vik_viewport_set_center_coord(vvp, &vehicle_coord); update_all = TRUE; } - else { + else if (vgl->vehicle_position == VEHICLE_POSITION_ON_SCREEN) { const int hdiv = 6; const int vdiv = 6; const int px = 20; /* adjust ment in pixels to make sure vehicle is inside the box */ @@ -1289,15 +1349,23 @@ static gchar *make_track_name(VikTrwLayer *vtl) static gboolean rt_gpsd_try_connect(gpointer *data) { VikGpsLayer *vgl = (VikGpsLayer *)data; +#ifndef HAVE_GPS_OPEN_R struct gps_data_t *gpsd = gps_open(vgl->gpsd_host, vgl->gpsd_port); if (gpsd == NULL) { +#else + vgl->vgpsd = g_malloc(sizeof(VglGpsd)); + + if (gps_open_r(vgl->gpsd_host, vgl->gpsd_port, /*(struct gps_data_t *)*/vgl->vgpsd) != 0) { +#endif g_warning("Failed to connect to gpsd at %s (port %s). Will retry in %d seconds", vgl->gpsd_host, vgl->gpsd_port, vgl->gpsd_retry_interval); return TRUE; /* keep timer running */ } - vgl->vgpsd = g_realloc(gpsd, sizeof(VglGpsd)); +#ifndef HAVE_GPS_OPEN_R + vgl->vgpsd = realloc(gpsd, sizeof(VglGpsd)); +#endif vgl->vgpsd->vgl = vgl; vgl->realtime_fix.dirty = vgl->last_fix.dirty = FALSE; @@ -1317,7 +1385,11 @@ static gboolean rt_gpsd_try_connect(gpointer *data) vgl->realtime_io_channel = g_io_channel_unix_new(vgl->vgpsd->gpsd.gps_fd); vgl->realtime_io_watch_id = g_io_add_watch( vgl->realtime_io_channel, G_IO_IN | G_IO_ERR | G_IO_HUP, gpsd_data_available, vgl); +#if HAVE_GPS_STREAM + gps_stream(&vgl->vgpsd->gpsd, WATCH_ENABLE, NULL); +#else gps_query(&vgl->vgpsd->gpsd, "w+x"); +#endif return FALSE; /* no longer called by timeout */ } @@ -1371,6 +1443,11 @@ static void rt_gpsd_disconnect(VikGpsLayer *vgl) } if (vgl->vgpsd) { gps_close(&vgl->vgpsd->gpsd); +#ifdef HAVE_GPS_OPEN_R + g_free(vgl->vgpsd); +#else + free(vgl->vgpsd); +#endif vgl->vgpsd = NULL; }