]> git.street.me.uk Git - andy/viking.git/blob - src/datasource_gps.c
Prevent the program grinding to a halt if trying to deal with thousands of tiles
[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 static gboolean last_get_tracks = TRUE;
45 static gboolean last_get_routes = TRUE;
46 static gboolean last_get_waypoints = TRUE;
47
48 static gpointer datasource_gps_init_func ( );
49 static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file, gpointer not_used );
50 static void datasource_gps_cleanup ( gpointer user_data );
51 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
52 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
53 static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
54 static void datasource_gps_off ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
55
56 VikDataSourceInterface vik_datasource_gps_interface = {
57   N_("Acquire from GPS"),
58   N_("Acquired from GPS"),
59   VIK_DATASOURCE_CREATENEWLAYER,
60   VIK_DATASOURCE_INPUTTYPE_NONE,
61   TRUE,
62   TRUE,
63   TRUE,
64   (VikDataSourceInitFunc)               datasource_gps_init_func,
65   (VikDataSourceCheckExistenceFunc)     NULL,
66   (VikDataSourceAddSetupWidgetsFunc)    datasource_gps_add_setup_widgets,
67   (VikDataSourceGetCmdStringFunc)       datasource_gps_get_cmd_string,
68   (VikDataSourceProcessFunc)        a_babel_convert_from,
69   (VikDataSourceProgressFunc)           datasource_gps_progress,
70   (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
71   (VikDataSourceCleanupFunc)            datasource_gps_cleanup,
72   (VikDataSourceOffFunc)                datasource_gps_off
73 };
74
75 /*********************************************************
76  * Definitions and routines for acquiring data from GPS
77  *********************************************************/
78
79 /* widgets in setup dialog specific to GPS */
80 /* widgets in progress dialog specific to GPS */
81 /* also counts needed for progress */
82 typedef struct {
83   /* setup dialog */
84   GtkWidget *proto_l;
85   GtkComboBox *proto_b;
86   GtkWidget *ser_l;
87   GtkComboBox *ser_b;
88   GtkWidget *off_request_l;
89   GtkCheckButton *off_request_b;
90   GtkWidget *get_tracks_l;
91   GtkCheckButton *get_tracks_b;
92   GtkWidget *get_routes_l;
93   GtkCheckButton *get_routes_b;
94   GtkWidget *get_waypoints_l;
95   GtkCheckButton *get_waypoints_b;
96
97   /* progress dialog */
98   GtkWidget *gps_label;
99   GtkWidget *ver_label;
100   GtkWidget *id_label;
101   GtkWidget *wp_label;
102   GtkWidget *trk_label;
103   GtkWidget *rte_label;
104   GtkWidget *progress_label;
105   vik_gps_xfer_type progress_type;
106
107   /* state */
108   int total_count;
109   int count;
110 } gps_user_data_t;
111
112 static gpointer datasource_gps_init_func ()
113 {
114   return g_malloc (sizeof(gps_user_data_t));
115 }
116
117 /**
118  * datasource_gps_get_protocol:
119  *
120  * Method to get the communication protocol of the GPS device from the widget structure
121  */
122 gchar* datasource_gps_get_protocol ( gpointer user_data )
123 {
124   // Uses the list of supported devices
125   gps_user_data_t *w = (gps_user_data_t *)user_data;
126   last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
127   if (a_babel_device_list)
128     return ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
129
130   return NULL;
131 }
132
133 /**
134  * datasource_gps_get_descriptor:
135  *
136  * Method to get the descriptor from the widget structure
137  * "Everything is a file"
138  * Could actually be normal file or a serial port
139  */
140 gchar* datasource_gps_get_descriptor ( gpointer user_data )
141 {
142   gps_user_data_t *w = (gps_user_data_t *)user_data;
143   return gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
144 }
145
146 /**
147  * datasource_gps_get_do_tracks:
148  *
149  * Method to get the track handling behaviour from the widget structure
150  */
151 gboolean datasource_gps_get_do_tracks ( gpointer user_data )
152 {
153   gps_user_data_t *w = (gps_user_data_t *)user_data;
154   last_get_tracks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_tracks_b));
155   return last_get_tracks;
156 }
157
158 /**
159  * datasource_gps_get_do_routes:
160  *
161  * Method to get the route handling behaviour from the widget structure
162  */
163 gboolean datasource_gps_get_do_routes ( gpointer user_data )
164 {
165   gps_user_data_t *w = (gps_user_data_t *)user_data;
166   last_get_routes = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_routes_b));
167   return last_get_routes;
168 }
169
170 /**
171  * datasource_gps_get_do_waypoints:
172  *
173  * Method to get the waypoint handling behaviour from the widget structure
174  */
175 gboolean datasource_gps_get_do_waypoints ( gpointer user_data )
176 {
177   gps_user_data_t *w = (gps_user_data_t *)user_data;
178   last_get_waypoints = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b));
179   return last_get_waypoints;
180 }
181
182 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file, gpointer not_used )
183 {
184   char *device = NULL;
185   char *tracks = NULL;
186   char *routes = NULL;
187   char *waypoints = NULL;
188
189   if (gps_acquire_in_progress) {
190     *babelargs = *input_file = NULL;
191   }
192   
193   gps_acquire_in_progress = TRUE;
194
195   device = datasource_gps_get_protocol ( user_data );
196
197   if ( datasource_gps_get_do_tracks ( user_data ) )
198     tracks = "-t";
199   else
200     tracks = "";
201
202   if ( datasource_gps_get_do_routes ( user_data ) )
203     routes = "-r";
204   else
205     routes = "";
206
207   if ( datasource_gps_get_do_waypoints ( user_data ) )
208     waypoints = "-w";
209   else
210     waypoints = "";
211
212   *babelargs = g_strdup_printf("-D 9 %s %s %s -i %s", tracks, routes, waypoints, device);
213   /* device points to static content => no free */
214   device = NULL;
215   tracks = NULL;
216   routes = NULL;
217   waypoints = NULL;
218
219   *input_file = g_strdup(datasource_gps_get_descriptor(user_data));
220
221   g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
222 }
223
224 /**
225  * datasource_gps_get_off:
226  *
227  * Method to get the off behaviour from the widget structure
228  */
229 gboolean datasource_gps_get_off ( gpointer user_data )
230 {
231   gps_user_data_t *w = (gps_user_data_t *)user_data;
232   return gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b));
233 }
234
235 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
236 {
237   char *ser = NULL;
238   char *device = NULL;
239   gps_user_data_t *w = (gps_user_data_t *)user_data;
240
241   if (gps_acquire_in_progress) {
242     *babelargs = *input_file = NULL;
243   }
244
245   /* See if we should turn off the device */
246   if (!datasource_gps_get_off ( user_data )){
247     return;
248   }
249   
250   if (!a_babel_device_list)
251     return;
252   last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
253   device = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
254   if (!strcmp(device, "garmin")) {
255     device = "garmin,power_off";
256   }
257   else if (!strcmp(device, "navilink")) {
258     device = "navilink,power_off";
259   }
260   else {
261     return;
262   }
263
264   *babelargs = g_strdup_printf("-i %s", device);
265   /* device points to static content => no free */
266   device = NULL;
267   
268   ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
269   *input_file = g_strdup(ser);
270 }
271
272
273 static void datasource_gps_cleanup ( gpointer user_data )
274 {
275   g_free ( user_data );
276   gps_acquire_in_progress = FALSE;
277 }
278
279 /**
280  * datasource_gps_clean_up:
281  *
282  * External method to tidy up
283  */
284 void datasource_gps_clean_up ( gpointer user_data )
285 {
286   datasource_gps_cleanup ( user_data );
287 }
288
289 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
290 {
291   gchar *s = NULL;
292   gdk_threads_enter();
293   if (w->running) {
294     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
295     const gchar *tmp_str;
296     switch (gps_data->progress_type) {
297     case WPT: tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt); gps_data->total_count = cnt; break;
298     case TRK: tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt); gps_data->total_count = cnt; break;
299     default:
300       {
301         // 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
302         gint mycnt = (cnt / 2) + 1;
303         tmp_str = ngettext("Downloading %d routepoint...", "Downloading %d routepoints...", mycnt);
304         gps_data->total_count = mycnt;
305         break;
306       }
307     }
308     s = g_strdup_printf(tmp_str, cnt);
309     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
310     gtk_widget_show ( gps_data->progress_label );
311   }
312   g_free(s); s = NULL;
313   gdk_threads_leave();
314 }
315
316 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
317 {
318   gchar *s = NULL;
319   gdk_threads_enter();
320   if (w->running) {
321     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
322
323     if (cnt < gps_data->total_count) {
324       switch (gps_data->progress_type) {
325       case WPT: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "waypoints"); break;
326       case TRK: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "trackpoints"); break;
327       default: s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, "routepoints"); break;
328       }
329     } else {
330       switch (gps_data->progress_type) {
331       case WPT: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "waypoints"); break;
332       case TRK: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "trackpoints"); break;
333       default: s = g_strdup_printf(_("Downloaded %d %s."), cnt, "routepoints"); break;
334       }
335     }
336     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
337   }
338   g_free(s); s = NULL;
339   gdk_threads_leave();
340 }
341
342 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
343 {
344   gchar *s = NULL;
345   gdk_threads_enter();
346   if (w->running) {
347     s = g_strdup_printf(_("GPS Device: %s"), info);
348     gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
349   }
350   g_free(s); s = NULL;
351   gdk_threads_leave();
352 }
353
354 /* 
355  * This routine relies on gpsbabel's diagnostic output to display the progress information. 
356  * These outputs differ when different GPS devices are used, so we will need to test
357  * them on several and add the corresponding support.
358  */
359 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
360 {
361   gchar *line;
362   gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
363
364   switch(c) {
365   case BABEL_DIAG_OUTPUT:
366     line = (gchar *)data;
367
368     gdk_threads_enter();
369     if (w->running) {
370       gtk_label_set_text ( GTK_LABEL(w->status), _("Status: Working...") );
371     }
372     gdk_threads_leave();
373
374     /* tells us the type of items that will follow */
375     if (strstr(line, "Xfer Wpt")) {
376       gps_data->progress_label = gps_data->wp_label;
377       gps_data->progress_type = WPT;
378     }
379     if (strstr(line, "Xfer Trk")) {
380       gps_data->progress_label = gps_data->trk_label;
381       gps_data->progress_type = TRK;
382     }
383     if (strstr(line, "Xfer Rte")) {
384       gps_data->progress_label = gps_data->rte_label;
385       gps_data->progress_type = RTE;
386     }
387
388     if (strstr(line, "PRDDAT")) {
389       gchar **tokens = g_strsplit(line, " ", 0);
390       gchar info[128];
391       int ilen = 0;
392       int i;
393       int n_tokens = 0;
394
395       while (tokens[n_tokens])
396         n_tokens++;
397
398       if (n_tokens > 8) {
399         for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
400           guint ch;
401           sscanf(tokens[i], "%x", &ch);
402           info[ilen++] = ch;
403         }
404         info[ilen++] = 0;
405         set_gps_info(info, w);
406       }
407       g_strfreev(tokens);
408     }
409     /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
410     if (strstr(line, "Unit:")) {
411       gchar **tokens = g_strsplit(line, "\t", 0);
412       int n_tokens = 0;
413       while (tokens[n_tokens])
414         n_tokens++;
415
416       if (n_tokens > 1) {
417         set_gps_info(tokens[1], w);
418       }
419       g_strfreev(tokens);
420     }
421     /* tells us how many items there will be */
422     if (strstr(line, "RECORD")) {
423       int lsb, msb, cnt;
424
425       if (strlen(line) > 20) {
426        sscanf(line+17, "%x", &lsb); 
427        sscanf(line+20, "%x", &msb);
428        cnt = lsb + msb * 256;
429        set_total_count(cnt, w);
430        gps_data->count = 0;
431       }
432     }
433     if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") || strstr(line, "RTEHDR") || strstr(line, "RTEWPT") ) {
434       gps_data->count++;
435       set_current_count(gps_data->count, w);
436     }
437     break;
438   case BABEL_DONE:
439     break;
440   default:
441     break;
442   }
443 }
444
445 void append_element (gpointer elem, gpointer user_data)
446 {
447   GtkComboBox *combo = GTK_COMBO_BOX (user_data);
448   const gchar *text = ((BabelDevice*)elem)->label;
449   gtk_combo_box_append_text (combo, text);
450 }
451
452 static gint find_entry = -1;
453 static gint garmin_entry = -1;
454
455 static void find_garmin (gpointer elem, gpointer user_data)
456 {
457   const gchar *name = ((BabelDevice*)elem)->name;
458   find_entry++;
459   if (!strcmp(name, "garmin")) {
460     garmin_entry = find_entry;
461   }
462 }
463
464 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
465 {
466   gps_user_data_t *w = (gps_user_data_t *)user_data;
467   GtkTable *box, *data_type_box;
468
469   w->proto_l = gtk_label_new (_("GPS Protocol:"));
470   w->proto_b = GTK_COMBO_BOX(gtk_combo_box_new_text ());
471   g_list_foreach (a_babel_device_list, append_element, w->proto_b);
472
473   // Maintain default to Garmin devices (assumed most popular/numerous device)
474   if ( last_active < 0 ) {
475     find_entry = -1;
476     g_list_foreach (a_babel_device_list, find_garmin, NULL);
477     if ( garmin_entry < 0 )
478       // Not found - so set it to the first entry
479       last_active = 0;
480     else
481       // Found
482       last_active = garmin_entry;
483   }
484
485   gtk_combo_box_set_active (w->proto_b, last_active);
486   g_object_ref(w->proto_b);
487
488   w->ser_l = gtk_label_new (_("Serial Port:"));
489   w->ser_b = GTK_COMBO_BOX(gtk_combo_box_entry_new_text ());
490 #ifdef WINDOWS
491   gtk_combo_box_append_text (w->ser_b, "com1");
492 #else
493   /* Here just try to see if the device is available which gets passed onto gpsbabel
494      List USB devices first as these will generally only be present if autogenerated by udev or similar
495      User is still able to set their own free text entry */
496   if (g_access ("/dev/ttyUSB0", R_OK) == 0)
497     gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB0");
498   if (g_access ("/dev/ttyUSB1", R_OK) == 0)
499     gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB1");
500   if (g_access ("/dev/ttyS0", R_OK) == 0)
501     gtk_combo_box_append_text (w->ser_b, "/dev/ttyS0");
502   if (g_access ("/dev/ttyS1", R_OK) == 0)
503     gtk_combo_box_append_text (w->ser_b, "/dev/ttyS1");
504 #endif
505   gtk_combo_box_append_text (w->ser_b, "usb:");
506   gtk_combo_box_set_active (w->ser_b, 0);
507   g_object_ref(w->ser_b);
508
509   w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
510   w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
511
512   w->get_tracks_l = gtk_label_new (_("Tracks:"));
513   w->get_tracks_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
514   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_tracks_b), last_get_tracks);
515
516   w->get_routes_l = gtk_label_new (_("Routes:"));
517   w->get_routes_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
518   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_routes_b), last_get_routes);
519
520   w->get_waypoints_l = gtk_label_new (_("Waypoints:"));
521   w->get_waypoints_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
522   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b), last_get_waypoints);
523
524   box = GTK_TABLE(gtk_table_new(2, 4, FALSE));
525   data_type_box = GTK_TABLE(gtk_table_new(4, 1, FALSE));
526
527   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
528   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
529   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
530   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
531   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_l), 0, 1, 0, 1);
532   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_b), 1, 2, 0, 1);
533   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_l), 2, 3, 0, 1);
534   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_b), 3, 4, 0, 1);
535   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_l), 4, 5, 0, 1);
536   gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_b), 5, 6, 0, 1);
537   gtk_table_attach_defaults(box, GTK_WIDGET(data_type_box), 0, 2, 2, 3);
538   gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 3, 4);
539   gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 3, 4);
540   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
541
542   gtk_widget_show_all ( dialog );
543 }
544
545 /**
546  * datasource_gps_setup:
547  * @dialog: The GTK dialog. The caller is responsible for managing the dialog creation/deletion
548  * @xfer: The default type of items enabled for transfer, others disabled.
549  * @xfer_all: When specified all items are enabled for transfer.
550  *
551  * Returns: A gpointer to the private structure for GPS progress/information widgets
552  *          Pass this pointer back into the other exposed datasource_gps_X functions
553  */
554 gpointer datasource_gps_setup ( GtkWidget *dialog, vik_gps_xfer_type xfer, gboolean xfer_all )
555 {
556   gps_user_data_t *w_gps = (gps_user_data_t *)datasource_gps_init_func();
557   datasource_gps_add_setup_widgets ( dialog, NULL, w_gps );
558
559   gboolean way = xfer_all;
560   gboolean trk = xfer_all;
561   gboolean rte = xfer_all;
562
563   // Selectively turn bits on
564   if ( !xfer_all ) {
565     switch (xfer) {
566     case WPT: way = TRUE; break;
567     case RTE: rte = TRUE; break;
568     default: trk = TRUE; break;
569     }
570   }
571
572   // Apply
573   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_tracks_b), trk );
574   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_l), trk );
575   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_b), trk );
576
577   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_routes_b), rte );
578   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_l), rte );
579   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_b), rte );
580
581   gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_waypoints_b), way );
582   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_l), way );
583   gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_b), way );
584
585   return (gpointer)w_gps;
586 }
587
588 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
589 {
590   GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel, *rtelabel;
591
592   gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
593
594   gpslabel = gtk_label_new (_("GPS device: N/A"));
595   verlabel = gtk_label_new ("");
596   idlabel = gtk_label_new ("");
597   wplabel = gtk_label_new ("");
598   trklabel = gtk_label_new ("");
599   rtelabel = gtk_label_new ("");
600
601   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
602   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
603   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
604   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), rtelabel, FALSE, FALSE, 5 );
605
606   gtk_widget_show_all ( dialog );
607
608   w_gps->gps_label = gpslabel;
609   w_gps->id_label = idlabel;
610   w_gps->ver_label = verlabel;
611   w_gps->progress_label = w_gps->wp_label = wplabel;
612   w_gps->trk_label = trklabel;
613   w_gps->rte_label = rtelabel;
614   w_gps->total_count = -1;
615 }