]> git.street.me.uk Git - andy/viking.git/blob - src/datasource_gps.c
Fix right click on a selected waypoint image starts to move it.
[andy/viking.git] / src / datasource_gps.c
1 /*
2  * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3  *
4  * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5  * Copyright (C) 2006, Alex Foobarian <foobarian@gmail.com>
6  * Copyright (C) 2012, Rob Norris <rw_norris@hotmail.com>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  *
22  */
23 #ifdef HAVE_CONFIG_H
24 #include "config.h"
25 #endif
26 #include <string.h>
27 #ifdef HAVE_UNISTD_H
28 #include <unistd.h>
29 #endif
30
31 #include <glib/gstdio.h>
32 #include <glib/gprintf.h>
33 #include <glib/gi18n.h>
34
35 #include "datasource_gps.h"
36 #include "viking.h"
37 #include "babel.h"
38 #include "gpx.h"
39 #include "acquire.h"
40
41 static gboolean gps_acquire_in_progress = FALSE;
42
43 static gint last_active = -1;
44
45 static gpointer datasource_gps_init_func ( acq_vik_t *avt );
46 static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file, gpointer not_used );
47 static void datasource_gps_cleanup ( gpointer user_data );
48 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
49 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
50 static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
51 static void datasource_gps_off ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
52
53 VikDataSourceInterface vik_datasource_gps_interface = {
54   N_("Acquire from GPS"),
55   N_("Acquired from GPS"),
56   VIK_DATASOURCE_CREATENEWLAYER,
57   VIK_DATASOURCE_INPUTTYPE_NONE,
58   TRUE,
59   TRUE,
60   TRUE,
61   (VikDataSourceInitFunc)               datasource_gps_init_func,
62   (VikDataSourceCheckExistenceFunc)     NULL,
63   (VikDataSourceAddSetupWidgetsFunc)    datasource_gps_add_setup_widgets,
64   (VikDataSourceGetCmdStringFunc)       datasource_gps_get_cmd_string,
65   (VikDataSourceProcessFunc)        a_babel_convert_from,
66   (VikDataSourceProgressFunc)           datasource_gps_progress,
67   (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
68   (VikDataSourceCleanupFunc)            datasource_gps_cleanup,
69   (VikDataSourceOffFunc)                datasource_gps_off
70 };
71
72 /*********************************************************
73  * Definitions and routines for acquiring data from GPS
74  *********************************************************/
75
76 /* widgets in setup dialog specific to GPS */
77 /* widgets in progress dialog specific to GPS */
78 /* also counts needed for progress */
79 typedef struct {
80   /* setup dialog */
81   GtkWidget *proto_l;
82   GtkWidget *proto_b;
83   GtkWidget *ser_l;
84   GtkWidget *ser_b;
85   GtkWidget *off_request_l;
86   GtkCheckButton *off_request_b;
87   GtkWidget *get_tracks_l;
88   GtkCheckButton *get_tracks_b;
89   GtkWidget *get_routes_l;
90   GtkCheckButton *get_routes_b;
91   GtkWidget *get_waypoints_l;
92   GtkCheckButton *get_waypoints_b;
93
94   /* progress dialog */
95   GtkWidget *gps_label;
96   GtkWidget *ver_label;
97   GtkWidget *id_label;
98   GtkWidget *wp_label;
99   GtkWidget *trk_label;
100   GtkWidget *rte_label;
101   GtkWidget *progress_label;
102   vik_gps_xfer_type progress_type;
103
104   /* state */
105   int total_count;
106   int count;
107   // Know which way xfer is so xfer setting types are only stored for download
108   vik_gps_dir direction;
109 } gps_user_data_t;
110
111 #define VIK_SETTINGS_GPS_GET_TRACKS "gps_download_tracks"
112 #define VIK_SETTINGS_GPS_GET_ROUTES "gps_download_routes"
113 #define VIK_SETTINGS_GPS_GET_WAYPOINTS "gps_download_waypoints"
114 #define VIK_SETTINGS_GPS_PROTOCOL "gps_protocol"
115 #define VIK_SETTINGS_GPS_PORT "gps_port"
116 #define VIK_SETTINGS_GPS_POWER_OFF "gps_power_off"
117
118 static gpointer datasource_gps_init_func ( acq_vik_t *avt )
119 {
120   gps_user_data_t *gps_ud = g_malloc (sizeof(gps_user_data_t));
121   gps_ud->direction = GPS_DOWN;
122   return gps_ud;
123 }
124
125 /**
126  * datasource_gps_get_protocol:
127  *
128  * Method to get the communication protocol of the GPS device from the widget structure
129  */
130 gchar* datasource_gps_get_protocol ( gpointer user_data )
131 {
132   // Uses the list of supported devices
133   gps_user_data_t *w = (gps_user_data_t *)user_data;
134   last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
135   if (a_babel_device_list) {
136     gchar *protocol = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
137     a_settings_set_string ( VIK_SETTINGS_GPS_PROTOCOL, protocol );
138     return protocol;
139   }
140
141   return NULL;
142 }
143
144 /**
145  * datasource_gps_get_descriptor:
146  *
147  * Method to get the descriptor from the widget structure
148  * "Everything is a file"
149  * Could actually be normal file or a serial port
150  */
151 gchar* datasource_gps_get_descriptor ( gpointer user_data )
152 {
153   gps_user_data_t *w = (gps_user_data_t *)user_data;
154
155 #if GTK_CHECK_VERSION (2, 24, 0)
156   gchar *descriptor = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w->ser_b));
157 #else
158   gchar *descriptor = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
159 #endif
160   a_settings_set_string ( VIK_SETTINGS_GPS_PORT, descriptor );
161   return descriptor;
162 }
163
164 /**
165  * datasource_gps_get_do_tracks:
166  *
167  * Method to get the track handling behaviour from the widget structure
168  */
169 gboolean datasource_gps_get_do_tracks ( gpointer user_data )
170 {
171   gps_user_data_t *w = (gps_user_data_t *)user_data;
172   gboolean get_tracks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_tracks_b));
173   if ( w->direction == GPS_DOWN )
174     a_settings_set_boolean ( VIK_SETTINGS_GPS_GET_TRACKS, get_tracks );
175   return get_tracks;
176 }
177
178 /**
179  * datasource_gps_get_do_routes:
180  *
181  * Method to get the route handling behaviour from the widget structure
182  */
183 gboolean datasource_gps_get_do_routes ( gpointer user_data )
184 {
185   gps_user_data_t *w = (gps_user_data_t *)user_data;
186   gboolean get_routes = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_routes_b));
187   if ( w->direction == GPS_DOWN )
188     a_settings_set_boolean ( VIK_SETTINGS_GPS_GET_ROUTES, get_routes );
189   return get_routes;
190 }
191
192 /**
193  * datasource_gps_get_do_waypoints:
194  *
195  * Method to get the waypoint handling behaviour from the widget structure
196  */
197 gboolean datasource_gps_get_do_waypoints ( gpointer user_data )
198 {
199   gps_user_data_t *w = (gps_user_data_t *)user_data;
200   gboolean get_waypoints = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b));
201   if ( w->direction == GPS_DOWN )
202     a_settings_set_boolean ( VIK_SETTINGS_GPS_GET_WAYPOINTS, get_waypoints );
203   return get_waypoints;
204 }
205
206 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file, gpointer not_used )
207 {
208   char *device = NULL;
209   char *tracks = NULL;
210   char *routes = NULL;
211   char *waypoints = NULL;
212
213   if (gps_acquire_in_progress) {
214     *babelargs = *input_file = NULL;
215   }
216   
217   gps_acquire_in_progress = TRUE;
218
219   device = datasource_gps_get_protocol ( user_data );
220
221   if ( datasource_gps_get_do_tracks ( user_data ) )
222     tracks = "-t";
223   else
224     tracks = "";
225
226   if ( datasource_gps_get_do_routes ( user_data ) )
227     routes = "-r";
228   else
229     routes = "";
230
231   if ( datasource_gps_get_do_waypoints ( user_data ) )
232     waypoints = "-w";
233   else
234     waypoints = "";
235
236   *babelargs = g_strdup_printf("-D 9 %s %s %s -i %s", tracks, routes, waypoints, device);
237   /* device points to static content => no free */
238   device = NULL;
239   tracks = NULL;
240   routes = NULL;
241   waypoints = NULL;
242
243   *input_file = g_strdup(datasource_gps_get_descriptor(user_data));
244
245   g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
246 }
247
248 /**
249  * datasource_gps_get_off:
250  *
251  * Method to get the off behaviour from the widget structure
252  */
253 gboolean datasource_gps_get_off ( gpointer user_data )
254 {
255   gps_user_data_t *w = (gps_user_data_t *)user_data;
256   gboolean power_off = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b));
257   a_settings_set_boolean ( VIK_SETTINGS_GPS_POWER_OFF, power_off );
258   return power_off;
259 }
260
261 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
262 {
263   char *ser = NULL;
264   char *device = NULL;
265   gps_user_data_t *w = (gps_user_data_t *)user_data;
266
267   if (gps_acquire_in_progress) {
268     *babelargs = *input_file = NULL;
269   }
270
271   /* See if we should turn off the device */
272   if (!datasource_gps_get_off ( user_data )){
273     return;
274   }
275   
276   if (!a_babel_device_list)
277     return;
278   last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
279   device = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
280   if (!strcmp(device, "garmin")) {
281     device = "garmin,power_off";
282   }
283   else if (!strcmp(device, "navilink")) {
284     device = "navilink,power_off";
285   }
286   else {
287     return;
288   }
289
290   *babelargs = g_strdup_printf("-i %s", device);
291   /* device points to static content => no free */
292   device = NULL;
293   
294 #if GTK_CHECK_VERSION (2, 24, 0)
295   ser = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w->ser_b));
296 #else
297   ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
298 #endif
299   *input_file = g_strdup(ser);
300 }
301
302
303 static void datasource_gps_cleanup ( gpointer user_data )
304 {
305   g_free ( user_data );
306   gps_acquire_in_progress = FALSE;
307 }
308
309 /**
310  * datasource_gps_clean_up:
311  *
312  * External method to tidy up
313  */
314 void datasource_gps_clean_up ( gpointer user_data )
315 {
316   datasource_gps_cleanup ( user_data );
317 }
318
319 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
320 {
321   gchar *s = NULL;
322   gdk_threads_enter();
323   if (w->running) {
324     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
325     const gchar *tmp_str;
326     switch (gps_data->progress_type) {
327     case WPT: tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt); gps_data->total_count = cnt; break;
328     case TRK: tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt); gps_data->total_count = cnt; break;
329     default:
330       {
331         // Maybe a gpsbabel bug/feature (upto at least v1.4.3 or maybe my Garmin device) but the count always seems x2 too many for routepoints
332         gint mycnt = (cnt / 2) + 1;
333         tmp_str = ngettext("Downloading %d routepoint...", "Downloading %d routepoints...", mycnt);
334         gps_data->total_count = mycnt;
335         break;
336       }
337     }
338     s = g_strdup_printf(tmp_str, cnt);
339     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
340     gtk_widget_show ( gps_data->progress_label );
341   }
342   g_free(s); s = NULL;
343   gdk_threads_leave();
344 }
345
346 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
347 {
348   gchar *s = NULL;
349   gdk_threads_enter();
350   if (w->running) {
351     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
352
353     if (cnt < gps_data->total_count) {
354       switch (gps_data->progress_type) {
355       case WPT: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "waypoints"); break;
356       case TRK: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "trackpoints"); break;
357       default: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "routepoints"); break;
358       }
359     } else {
360       switch (gps_data->progress_type) {
361       case WPT: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "waypoints"); break;
362       case TRK: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "trackpoints"); break;
363       default: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "routepoints"); break;
364       }
365     }
366     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
367   }
368   g_free(s); s = NULL;
369   gdk_threads_leave();
370 }
371
372 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
373 {
374   gchar *s = NULL;
375   gdk_threads_enter();
376   if (w->running) {
377     s = g_strdup_printf(_("GPS Device: %s"), info);
378     gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
379   }
380   g_free(s); s = NULL;
381   gdk_threads_leave();
382 }
383
384 /* 
385  * This routine relies on gpsbabel's diagnostic output to display the progress information. 
386  * These outputs differ when different GPS devices are used, so we will need to test
387  * them on several and add the corresponding support.
388  */
389 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
390 {
391   gchar *line;
392   gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
393
394   switch(c) {
395   case BABEL_DIAG_OUTPUT:
396     line = (gchar *)data;
397
398     gdk_threads_enter();
399     if (w->running) {
400       gtk_label_set_text ( GTK_LABEL(w->status), _("Status: Working...") );
401     }
402     gdk_threads_leave();
403
404     /* tells us the type of items that will follow */
405     if (strstr(line, "Xfer Wpt")) {
406       gps_data->progress_label = gps_data->wp_label;
407       gps_data->progress_type = WPT;
408     }
409     if (strstr(line, "Xfer Trk")) {
410       gps_data->progress_label = gps_data->trk_label;
411       gps_data->progress_type = TRK;
412     }
413     if (strstr(line, "Xfer Rte")) {
414       gps_data->progress_label = gps_data->rte_label;
415       gps_data->progress_type = RTE;
416     }
417
418     if (strstr(line, "PRDDAT")) {
419       gchar **tokens = g_strsplit(line, " ", 0);
420       gchar info[128];
421       int ilen = 0;
422       int i;
423       int n_tokens = 0;
424
425       while (tokens[n_tokens])
426         n_tokens++;
427
428       if (n_tokens > 8) {
429         for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
430           guint ch;
431           sscanf(tokens[i], "%x", &ch);
432           info[ilen++] = ch;
433         }
434         info[ilen++] = 0;
435         set_gps_info(info, w);
436       }
437       g_strfreev(tokens);
438     }
439     /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
440     if (strstr(line, "Unit:")) {
441       gchar **tokens = g_strsplit(line, "\t", 0);
442       int n_tokens = 0;
443       while (tokens[n_tokens])
444         n_tokens++;
445
446       if (n_tokens > 1) {
447         set_gps_info(tokens[1], w);
448       }
449       g_strfreev(tokens);
450     }
451     /* tells us how many items there will be */
452     if (strstr(line, "RECORD")) {
453       int lsb, msb, cnt;
454
455       if (strlen(line) > 20) {
456        sscanf(line+17, "%x", &lsb); 
457        sscanf(line+20, "%x", &msb);
458        cnt = lsb + msb * 256;
459        set_total_count(cnt, w);
460        gps_data->count = 0;
461       }
462     }
463     if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") || strstr(line, "RTEHDR") || strstr(line, "RTEWPT") ) {
464       gps_data->count++;
465       set_current_count(gps_data->count, w);
466     }
467     break;
468   case BABEL_DONE:
469     break;
470   default:
471     break;
472   }
473 }
474
475 void append_element (gpointer elem, gpointer user_data)
476 {
477   const gchar *text = ((BabelDevice*)elem)->label;
478   vik_combo_box_text_append (GTK_WIDGET(user_data), text);
479 }
480
481 static gint find_entry = -1;
482 static gint wanted_entry = -1;
483
484 static void find_protocol (gpointer elem, gpointer user_data)
485 {
486   const gchar *name = ((BabelDevice*)elem)->name;
487   const gchar *protocol = user_data;
488   find_entry++;
489   if (!strcmp(name, protocol)) {
490     wanted_entry = find_entry;
491   }
492 }
493
494 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
495 {
496   gps_user_data_t *w = (gps_user_data_t *)user_data;
497   GtkTable *box, *data_type_box;
498
499   w->proto_l = gtk_label_new (_("GPS Protocol:"));
500   w->proto_b = vik_combo_box_text_new ();
501   g_list_foreach (a_babel_device_list, append_element, w->proto_b);
502
503   if ( last_active < 0 ) {
504     find_entry = -1;
505     wanted_entry = -1;
506     gchar *protocol = NULL;
507     if ( a_settings_get_string ( VIK_SETTINGS_GPS_PROTOCOL, &protocol ) ) {
508       // Use setting
509       if ( protocol )
510         g_list_foreach (a_babel_device_list, find_protocol, protocol);
511     }
512     else {
513       // Attempt to maintain default to Garmin devices (assumed most popular/numerous device)
514       g_list_foreach (a_babel_device_list, find_protocol, "garmin");
515     }
516     // If not found set it to the first entry, otherwise use the entry
517     last_active = ( wanted_entry < 0 ) ? 0 : wanted_entry;
518   }
519
520   gtk_combo_box_set_active (GTK_COMBO_BOX(w->proto_b), last_active);
521   g_object_ref(w->proto_b);
522
523   w->ser_l = gtk_label_new (_("Serial Port:"));
524 #if GTK_CHECK_VERSION (2, 24, 0)
525   w->ser_b = gtk_combo_box_text_new_with_entry ();
526 #else
527   w->ser_b = gtk_combo_box_entry_new_text ();
528 #endif
529   // Value from the settings is promoted to the top
530   gchar *gps_port = NULL;
531   if ( a_settings_get_string ( VIK_SETTINGS_GPS_PORT, &gps_port ) ) {
532     // Use setting if available
533     if ( gps_port ) {
534 #ifndef WINDOWS
535       if ( !strncmp (gps_port, "/dev/tty", 6) ) {
536         if (g_access (gps_port, R_OK) == 0) {
537           vik_combo_box_text_append (w->ser_b, gps_port);
538         }
539       }
540       else
541 #endif
542         vik_combo_box_text_append (w->ser_b, gps_port);
543     }
544   }
545
546   // Note avoid appending the port selected from the settings
547 #ifdef WINDOWS
548   if ( gps_port && strcmp (gps_port, "com1") )
549     vik_combo_box_text_append (w->ser_b, "com1");
550 #else
551   /* Here just try to see if the device is available which gets passed onto gpsbabel
552      List USB devices first as these will generally only be present if autogenerated by udev or similar
553      User is still able to set their own free text entry */
554   if ( gps_port && strcmp (gps_port, "/dev/ttyUSB0") )
555     if (g_access ("/dev/ttyUSB0", R_OK) == 0)
556       vik_combo_box_text_append (w->ser_b, "/dev/ttyUSB0");
557   if ( gps_port && strcmp (gps_port, "/dev/ttyUSB1") )
558     if (g_access ("/dev/ttyUSB1", R_OK) == 0)
559       vik_combo_box_text_append (w->ser_b, "/dev/ttyUSB1");
560   if ( gps_port && strcmp (gps_port, "/dev/ttyS0") )
561     if (g_access ("/dev/ttyS0", R_OK) == 0)
562       vik_combo_box_text_append (w->ser_b, "/dev/ttyS0");
563   if ( gps_port && strcmp (gps_port, "/dev/ttyS1") )
564     if (g_access ("/dev/ttyS1", R_OK) == 0)
565       vik_combo_box_text_append (w->ser_b, "/dev/ttyS1");
566 #endif
567   if ( gps_port && strcmp (gps_port, "usb:") )
568     vik_combo_box_text_append (w->ser_b, "usb:");
569
570   gtk_combo_box_set_active (GTK_COMBO_BOX(w->ser_b), 0);
571   g_object_ref(w->ser_b);
572
573   w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
574   w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
575   gboolean power_off;
576   if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_POWER_OFF, &power_off ) )
577     power_off = FALSE;
578   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->off_request_b), power_off);
579
580   w->get_tracks_l = gtk_label_new (_("Tracks:"));
581   w->get_tracks_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
582   gboolean get_tracks;
583   if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_TRACKS, &get_tracks ) )
584     get_tracks = TRUE;
585   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_tracks_b), get_tracks);
586
587   w->get_routes_l = gtk_label_new (_("Routes:"));
588   w->get_routes_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
589   gboolean get_routes;
590   if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_ROUTES, &get_routes ) )
591     get_routes = FALSE;
592   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_routes_b), get_routes);
593
594   w->get_waypoints_l = gtk_label_new (_("Waypoints:"));
595   w->get_waypoints_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
596   gboolean get_waypoints;
597   if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_WAYPOINTS, &get_waypoints ) )
598     get_waypoints = TRUE;
599   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b), get_waypoints);
600
601   box = GTK_TABLE(gtk_table_new(2, 4, FALSE));
602   data_type_box = GTK_TABLE(gtk_table_new(4, 1, FALSE));
603
604   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
605   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
606   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
607   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
608   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_l), 0, 1, 0, 1);
609   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_b), 1, 2, 0, 1);
610   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_l), 2, 3, 0, 1);
611   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_b), 3, 4, 0, 1);
612   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_l), 4, 5, 0, 1);
613   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_b), 5, 6, 0, 1);
614   gtk_table_attach_defaults(box, GTK_WIDGET(data_type_box), 0, 2, 2, 3);
615   gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 3, 4);
616   gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 3, 4);
617   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(box), FALSE, FALSE, 5 );
618
619   gtk_widget_show_all ( dialog );
620 }
621
622 /**
623  * datasource_gps_setup:
624  * @dialog: The GTK dialog. The caller is responsible for managing the dialog creation/deletion
625  * @xfer: The default type of items enabled for transfer, others disabled.
626  * @xfer_all: When specified all items are enabled for transfer.
627  *
628  * Returns: A gpointer to the private structure for GPS progress/information widgets
629  *          Pass this pointer back into the other exposed datasource_gps_X functions
630  */
631 gpointer datasource_gps_setup ( GtkWidget *dialog, vik_gps_xfer_type xfer, gboolean xfer_all )
632 {
633   gps_user_data_t *w_gps = (gps_user_data_t *)datasource_gps_init_func ( NULL );
634   w_gps->direction = GPS_UP;
635   datasource_gps_add_setup_widgets ( dialog, NULL, w_gps );
636
637   gboolean way = xfer_all;
638   gboolean trk = xfer_all;
639   gboolean rte = xfer_all;
640
641   // Selectively turn bits on
642   if ( !xfer_all ) {
643     switch (xfer) {
644     case WPT: way = TRUE; break;
645     case RTE: rte = TRUE; break;
646     default: trk = TRUE; break;
647     }
648   }
649
650   // Apply
651   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_tracks_b), trk );
652   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_l), trk );
653   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_b), trk );
654
655   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_routes_b), rte );
656   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_l), rte );
657   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_b), rte );
658
659   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_waypoints_b), way );
660   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_l), way );
661   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_b), way );
662
663   return (gpointer)w_gps;
664 }
665
666 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
667 {
668   GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel, *rtelabel;
669
670   gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
671
672   gpslabel = gtk_label_new (_("GPS device: N/A"));
673   verlabel = gtk_label_new ("");
674   idlabel = gtk_label_new ("");
675   wplabel = gtk_label_new ("");
676   trklabel = gtk_label_new ("");
677   rtelabel = gtk_label_new ("");
678
679   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), gpslabel, FALSE, FALSE, 5 );
680   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), wplabel, FALSE, FALSE, 5 );
681   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), trklabel, FALSE, FALSE, 5 );
682   gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), rtelabel, FALSE, FALSE, 5 );
683
684   gtk_widget_show_all ( dialog );
685
686   w_gps->gps_label = gpslabel;
687   w_gps->id_label = idlabel;
688   w_gps->ver_label = verlabel;
689   w_gps->progress_label = w_gps->wp_label = wplabel;
690   w_gps->trk_label = trklabel;
691   w_gps->rte_label = rtelabel;
692   w_gps->total_count = -1;
693 }