]> git.street.me.uk Git - andy/viking.git/blobdiff - src/vikgpslayer.c
When manually creating a track, automatically give it a default name.
[andy/viking.git] / src / vikgpslayer.c
index d06f5a322e498a995f5492e809c3092a7790e44e..d3e877ba50923fdd9c047a6233d043d10d7e9ee8 100644 (file)
 #include "icons/icons.h"
 #include "babel.h"
 
 #include "icons/icons.h"
 #include "babel.h"
 
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
 #ifdef HAVE_STRING_H
 #include <string.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
 #include <glib/gprintf.h>
 #include <glib/gi18n.h>
 #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 );
 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 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
 #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 {
 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},
 
 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},
 
 #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]),
 
   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,
 
   (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 vehicle_position;
 #endif /* VIK_CONFIG_REALTIME_GPS_TRACKING */
   guint protocol_id;
-  guint serial_port_id;
+  gchar *serial_port;
 };
 
 GType vik_gps_layer_get_type ()
 };
 
 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;
   
   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;
 
   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:
         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;
       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->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:
       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->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;
 }
 
   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 )
 {
 
 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 )
 }
 
 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);
     }
       }
       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;
 
     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];
 {
   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];
 }
 
 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] )
 }
 
 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;
     }
       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 */
       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;
 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) {
   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 */
   }
 
     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;
   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);
   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");
   gps_query(&vgl->vgpsd->gpsd, "w+x");
+#endif
   return FALSE;  /* no longer called by timeout */
 }
 
   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);
   }
   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;
   }
 
     vgl->vgpsd = NULL;
   }