]> git.street.me.uk Git - andy/viking.git/blame - src/datasource_gps.c
Fix incorrectly updating files during geotagging that are read only.
[andy/viking.git] / src / datasource_gps.c
CommitLineData
7b3479e3
EB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
a482007a 5 * Copyright (C) 2006, Alex Foobarian <foobarian@gmail.com>
d80e59ba 6 * Copyright (C) 2012, Rob Norris <rw_norris@hotmail.com>
7b3479e3
EB
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 */
8aad4ca3
GB
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
7b3479e3 26#include <string.h>
99163c34
RN
27#ifdef HAVE_UNISTD_H
28#include <unistd.h>
29#endif
4c77d5e0 30
99163c34 31#include <glib/gstdio.h>
7b3479e3 32#include <glib/gprintf.h>
4c77d5e0 33#include <glib/gi18n.h>
7b3479e3 34
d80e59ba 35#include "datasource_gps.h"
7b3479e3
EB
36#include "viking.h"
37#include "babel.h"
38#include "gpx.h"
39#include "acquire.h"
40
41static gboolean gps_acquire_in_progress = FALSE;
42
3f6db253 43static gint last_active = -1;
8627bd99 44
307abf54 45static gpointer datasource_gps_init_func ( acq_vik_t *avt );
ed691ed1 46static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file, gpointer not_used );
65f0ccab 47static void datasource_gps_cleanup ( gpointer user_data );
7b3479e3 48static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
65f0ccab
AF
49static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
50static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
2b756ea0 51static void datasource_gps_off ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
7b3479e3
EB
52
53VikDataSourceInterface vik_datasource_gps_interface = {
4c77d5e0
GB
54 N_("Acquire from GPS"),
55 N_("Acquired from GPS"),
805d282e 56 VIK_DATASOURCE_CREATENEWLAYER,
28c82d8b
EB
57 VIK_DATASOURCE_INPUTTYPE_NONE,
58 TRUE,
d2525524 59 TRUE,
b2aa700f 60 TRUE,
65f0ccab 61 (VikDataSourceInitFunc) datasource_gps_init_func,
92255687 62 (VikDataSourceCheckExistenceFunc) NULL,
65f0ccab 63 (VikDataSourceAddSetupWidgetsFunc) datasource_gps_add_setup_widgets,
7b3479e3 64 (VikDataSourceGetCmdStringFunc) datasource_gps_get_cmd_string,
eb3f9398 65 (VikDataSourceProcessFunc) a_babel_convert_from,
7b3479e3
EB
66 (VikDataSourceProgressFunc) datasource_gps_progress,
67 (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
2b756ea0
RN
68 (VikDataSourceCleanupFunc) datasource_gps_cleanup,
69 (VikDataSourceOffFunc) datasource_gps_off
7b3479e3
EB
70};
71
72/*********************************************************
73 * Definitions and routines for acquiring data from GPS
74 *********************************************************/
75
65f0ccab 76/* widgets in setup dialog specific to GPS */
7b3479e3
EB
77/* widgets in progress dialog specific to GPS */
78/* also counts needed for progress */
79typedef struct {
65f0ccab
AF
80 /* setup dialog */
81 GtkWidget *proto_l;
1bc1c05b 82 GtkWidget *proto_b;
65f0ccab 83 GtkWidget *ser_l;
1bc1c05b 84 GtkWidget *ser_b;
2b756ea0
RN
85 GtkWidget *off_request_l;
86 GtkCheckButton *off_request_b;
d6c58ab9
RN
87 GtkWidget *get_tracks_l;
88 GtkCheckButton *get_tracks_b;
0d2b891f
RN
89 GtkWidget *get_routes_l;
90 GtkCheckButton *get_routes_b;
d6c58ab9
RN
91 GtkWidget *get_waypoints_l;
92 GtkCheckButton *get_waypoints_b;
65f0ccab
AF
93
94 /* progress dialog */
7b3479e3
EB
95 GtkWidget *gps_label;
96 GtkWidget *ver_label;
97 GtkWidget *id_label;
98 GtkWidget *wp_label;
99 GtkWidget *trk_label;
0d2b891f 100 GtkWidget *rte_label;
7b3479e3 101 GtkWidget *progress_label;
0d2b891f 102 vik_gps_xfer_type progress_type;
65f0ccab
AF
103
104 /* state */
7b3479e3
EB
105 int total_count;
106 int count;
aa6dfd27
RN
107 // Know which way xfer is so xfer setting types are only stored for download
108 vik_gps_dir direction;
65f0ccab
AF
109} gps_user_data_t;
110
aa6dfd27
RN
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
307abf54 118static gpointer datasource_gps_init_func ( acq_vik_t *avt )
65f0ccab 119{
aa6dfd27
RN
120 gps_user_data_t *gps_ud = g_malloc (sizeof(gps_user_data_t));
121 gps_ud->direction = GPS_DOWN;
122 return gps_ud;
65f0ccab 123}
7b3479e3 124
d80e59ba
RN
125/**
126 * datasource_gps_get_protocol:
127 *
128 * Method to get the communication protocol of the GPS device from the widget structure
129 */
130gchar* 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));
aa6dfd27
RN
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 }
d80e59ba
RN
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 */
151gchar* datasource_gps_get_descriptor ( gpointer user_data )
152{
153 gps_user_data_t *w = (gps_user_data_t *)user_data;
1bc1c05b
RN
154
155#if GTK_CHECK_VERSION (2, 24, 0)
aa6dfd27 156 gchar *descriptor = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(w->ser_b));
1bc1c05b 157#else
aa6dfd27 158 gchar *descriptor = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
1bc1c05b 159#endif
aa6dfd27
RN
160 a_settings_set_string ( VIK_SETTINGS_GPS_PORT, descriptor );
161 return descriptor;
d80e59ba
RN
162}
163
164/**
165 * datasource_gps_get_do_tracks:
166 *
167 * Method to get the track handling behaviour from the widget structure
168 */
169gboolean datasource_gps_get_do_tracks ( gpointer user_data )
170{
171 gps_user_data_t *w = (gps_user_data_t *)user_data;
aa6dfd27
RN
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;
d80e59ba
RN
176}
177
0d2b891f
RN
178/**
179 * datasource_gps_get_do_routes:
180 *
181 * Method to get the route handling behaviour from the widget structure
182 */
183gboolean datasource_gps_get_do_routes ( gpointer user_data )
184{
185 gps_user_data_t *w = (gps_user_data_t *)user_data;
aa6dfd27
RN
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;
0d2b891f
RN
190}
191
d80e59ba
RN
192/**
193 * datasource_gps_get_do_waypoints:
194 *
195 * Method to get the waypoint handling behaviour from the widget structure
196 */
197gboolean datasource_gps_get_do_waypoints ( gpointer user_data )
198{
199 gps_user_data_t *w = (gps_user_data_t *)user_data;
aa6dfd27
RN
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;
d80e59ba
RN
204}
205
ed691ed1 206static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file, gpointer not_used )
7b3479e3 207{
cf7fdc15 208 char *device = NULL;
d6c58ab9 209 char *tracks = NULL;
0d2b891f 210 char *routes = NULL;
d6c58ab9 211 char *waypoints = NULL;
65f0ccab 212
7b3479e3
EB
213 if (gps_acquire_in_progress) {
214 *babelargs = *input_file = NULL;
215 }
65f0ccab
AF
216
217 gps_acquire_in_progress = TRUE;
218
d80e59ba 219 device = datasource_gps_get_protocol ( user_data );
2b756ea0 220
d80e59ba 221 if ( datasource_gps_get_do_tracks ( user_data ) )
d6c58ab9
RN
222 tracks = "-t";
223 else
224 tracks = "";
d80e59ba 225
0d2b891f
RN
226 if ( datasource_gps_get_do_routes ( user_data ) )
227 routes = "-r";
228 else
229 routes = "";
230
d80e59ba 231 if ( datasource_gps_get_do_waypoints ( user_data ) )
d6c58ab9
RN
232 waypoints = "-w";
233 else
234 waypoints = "";
235
0d2b891f 236 *babelargs = g_strdup_printf("-D 9 %s %s %s -i %s", tracks, routes, waypoints, device);
cf7fdc15
GB
237 /* device points to static content => no free */
238 device = NULL;
d6c58ab9 239 tracks = NULL;
0d2b891f 240 routes = NULL;
d6c58ab9
RN
241 waypoints = NULL;
242
d80e59ba 243 *input_file = g_strdup(datasource_gps_get_descriptor(user_data));
7b3479e3 244
4c77d5e0 245 g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
7b3479e3
EB
246}
247
d80e59ba
RN
248/**
249 * datasource_gps_get_off:
250 *
251 * Method to get the off behaviour from the widget structure
252 */
253gboolean datasource_gps_get_off ( gpointer user_data )
254{
255 gps_user_data_t *w = (gps_user_data_t *)user_data;
aa6dfd27
RN
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;
d80e59ba 259}
2b756ea0
RN
260
261static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
262{
2b756ea0
RN
263 char *ser = NULL;
264 char *device = NULL;
2b756ea0
RN
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 */
d80e59ba 272 if (!datasource_gps_get_off ( user_data )){
2b756ea0
RN
273 return;
274 }
275
78f6c63d
RN
276 if (!a_babel_device_list)
277 return;
8627bd99
GB
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")) {
2b756ea0 281 device = "garmin,power_off";
4136d029 282 }
8627bd99 283 else if (!strcmp(device, "navilink")) {
4136d029
RN
284 device = "navilink,power_off";
285 }
286 else {
2b756ea0
RN
287 return;
288 }
289
290 *babelargs = g_strdup_printf("-i %s", device);
291 /* device points to static content => no free */
292 device = NULL;
293
1bc1c05b
RN
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
2b756ea0 297 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
1bc1c05b 298#endif
2b756ea0
RN
299 *input_file = g_strdup(ser);
300}
301
302
65f0ccab 303static void datasource_gps_cleanup ( gpointer user_data )
7b3479e3 304{
65f0ccab 305 g_free ( user_data );
7b3479e3
EB
306 gps_acquire_in_progress = FALSE;
307}
308
d80e59ba
RN
309/**
310 * datasource_gps_clean_up:
311 *
312 * External method to tidy up
313 */
314void datasource_gps_clean_up ( gpointer user_data )
315{
316 datasource_gps_cleanup ( user_data );
317}
318
7b3479e3
EB
319static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
320{
cf7fdc15 321 gchar *s = NULL;
7b3479e3 322 gdk_threads_enter();
b2aa700f 323 if (w->running) {
65f0ccab 324 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
97634600 325 const gchar *tmp_str;
0d2b891f
RN
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 }
97634600 338 s = g_strdup_printf(tmp_str, cnt);
7b3479e3
EB
339 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
340 gtk_widget_show ( gps_data->progress_label );
7b3479e3 341 }
cf7fdc15 342 g_free(s); s = NULL;
7b3479e3
EB
343 gdk_threads_leave();
344}
345
346static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
347{
cf7fdc15 348 gchar *s = NULL;
7b3479e3 349 gdk_threads_enter();
b2aa700f 350 if (w->running) {
65f0ccab 351 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
7b3479e3
EB
352
353 if (cnt < gps_data->total_count) {
0d2b891f
RN
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 }
7b3479e3 359 } else {
0d2b891f
RN
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 }
7b3479e3
EB
366 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
367 }
cf7fdc15 368 g_free(s); s = NULL;
7b3479e3
EB
369 gdk_threads_leave();
370}
371
372static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
373{
cf7fdc15 374 gchar *s = NULL;
7b3479e3 375 gdk_threads_enter();
b2aa700f 376 if (w->running) {
4c77d5e0 377 s = g_strdup_printf(_("GPS Device: %s"), info);
65f0ccab 378 gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
7b3479e3 379 }
cf7fdc15 380 g_free(s); s = NULL;
7b3479e3
EB
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 */
389static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
390{
391 gchar *line;
65f0ccab 392 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
7b3479e3 393
7b3479e3
EB
394 switch(c) {
395 case BABEL_DIAG_OUTPUT:
396 line = (gchar *)data;
397
8d0586c6 398 gdk_threads_enter();
b2aa700f 399 if (w->running) {
8d0586c6
RN
400 gtk_label_set_text ( GTK_LABEL(w->status), _("Status: Working...") );
401 }
402 gdk_threads_leave();
403
0d2b891f
RN
404 /* tells us the type of items that will follow */
405 if (strstr(line, "Xfer Wpt")) {
7b3479e3 406 gps_data->progress_label = gps_data->wp_label;
0d2b891f 407 gps_data->progress_type = WPT;
7b3479e3 408 }
0d2b891f 409 if (strstr(line, "Xfer Trk")) {
7b3479e3 410 gps_data->progress_label = gps_data->trk_label;
0d2b891f
RN
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;
7b3479e3 416 }
0d2b891f 417
7b3479e3
EB
418 if (strstr(line, "PRDDAT")) {
419 gchar **tokens = g_strsplit(line, " ", 0);
420 gchar info[128];
421 int ilen = 0;
422 int i;
c83b5ad9
QT
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);
7b3479e3 436 }
c83b5ad9 437 g_strfreev(tokens);
7b3479e3 438 }
0a3f9142
RN
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 }
0d2b891f
RN
451 /* tells us how many items there will be */
452 if (strstr(line, "RECORD")) {
7b3479e3
EB
453 int lsb, msb, cnt;
454
c83b5ad9
QT
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 }
7b3479e3 462 }
0d2b891f 463 if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") || strstr(line, "RTEHDR") || strstr(line, "RTEWPT") ) {
7b3479e3
EB
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
8627bd99
GB
475void append_element (gpointer elem, gpointer user_data)
476{
8627bd99 477 const gchar *text = ((BabelDevice*)elem)->label;
1bc1c05b 478 vik_combo_box_text_append (GTK_WIDGET(user_data), text);
8627bd99
GB
479}
480
3f6db253
RN
481static gint find_entry = -1;
482static gint garmin_entry = -1;
aa6dfd27 483static gint wanted_entry = -1;
3f6db253 484
aa6dfd27 485static void find_protocol (gpointer elem, gpointer user_data)
3f6db253
RN
486{
487 const gchar *name = ((BabelDevice*)elem)->name;
aa6dfd27 488 const gchar *protocol = user_data;
3f6db253 489 find_entry++;
aa6dfd27
RN
490 if (!strcmp(name, protocol)) {
491 wanted_entry = find_entry;
3f6db253
RN
492 }
493}
494
d80e59ba 495static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
65f0ccab
AF
496{
497 gps_user_data_t *w = (gps_user_data_t *)user_data;
d6c58ab9 498 GtkTable *box, *data_type_box;
65f0ccab 499
4c77d5e0 500 w->proto_l = gtk_label_new (_("GPS Protocol:"));
1bc1c05b 501 w->proto_b = vik_combo_box_text_new ();
8627bd99 502 g_list_foreach (a_babel_device_list, append_element, w->proto_b);
3f6db253 503
3f6db253
RN
504 if ( last_active < 0 ) {
505 find_entry = -1;
aa6dfd27
RN
506 wanted_entry = -1;
507 gchar *protocol = NULL;
508 if ( a_settings_get_string ( VIK_SETTINGS_GPS_PROTOCOL, &protocol ) ) {
509 // Use setting
510 if ( protocol )
511 g_list_foreach (a_babel_device_list, find_protocol, protocol);
512 // If not found set it to the first entry, otherwise use the entry
513 last_active = ( wanted_entry < 0 ) ? 0 : wanted_entry;
514 }
515 else {
516 // Maintain default to Garmin devices (assumed most popular/numerous device)
517 garmin_entry = -1;
518 g_list_foreach (a_babel_device_list, find_protocol, "garmin");
519 last_active = ( garmin_entry < 0 ) ? 0 : garmin_entry;
520 }
3f6db253
RN
521 }
522
1bc1c05b 523 gtk_combo_box_set_active (GTK_COMBO_BOX(w->proto_b), last_active);
65f0ccab
AF
524 g_object_ref(w->proto_b);
525
4c77d5e0 526 w->ser_l = gtk_label_new (_("Serial Port:"));
1bc1c05b
RN
527#if GTK_CHECK_VERSION (2, 24, 0)
528 w->ser_b = gtk_combo_box_text_new_with_entry ();
529#else
530 w->ser_b = gtk_combo_box_entry_new_text ();
531#endif
aa6dfd27
RN
532 // Value from the settings is promoted to the top
533 gchar *gps_port = NULL;
534 if ( a_settings_get_string ( VIK_SETTINGS_GPS_PORT, &gps_port ) ) {
535 // Use setting if available
536 if ( gps_port ) {
537#ifndef WINDOWS
538 if ( !strncmp (gps_port, "/dev/tty", 6) ) {
539 if (g_access (gps_port, R_OK) == 0) {
540 vik_combo_box_text_append (w->ser_b, gps_port);
541 }
542 }
543 else
544#endif
545 vik_combo_box_text_append (w->ser_b, gps_port);
546 }
547 }
548
549 // Note avoid appending the port selected from the settings
8d70f073 550#ifdef WINDOWS
aa6dfd27
RN
551 if ( gps_port && strcmp (gps_port, "com1") )
552 vik_combo_box_text_append (w->ser_b, "com1");
8d70f073 553#else
99163c34
RN
554 /* Here just try to see if the device is available which gets passed onto gpsbabel
555 List USB devices first as these will generally only be present if autogenerated by udev or similar
556 User is still able to set their own free text entry */
aa6dfd27
RN
557 if ( gps_port && strcmp (gps_port, "/dev/ttyUSB0") )
558 if (g_access ("/dev/ttyUSB0", R_OK) == 0)
559 vik_combo_box_text_append (w->ser_b, "/dev/ttyUSB0");
560 if ( gps_port && strcmp (gps_port, "/dev/ttyUSB1") )
561 if (g_access ("/dev/ttyUSB1", R_OK) == 0)
562 vik_combo_box_text_append (w->ser_b, "/dev/ttyUSB1");
563 if ( gps_port && strcmp (gps_port, "/dev/ttyS0") )
564 if (g_access ("/dev/ttyS0", R_OK) == 0)
565 vik_combo_box_text_append (w->ser_b, "/dev/ttyS0");
566 if ( gps_port && strcmp (gps_port, "/dev/ttyS1") )
567 if (g_access ("/dev/ttyS1", R_OK) == 0)
568 vik_combo_box_text_append (w->ser_b, "/dev/ttyS1");
8d70f073 569#endif
aa6dfd27
RN
570 if ( gps_port && strcmp (gps_port, "usb:") )
571 vik_combo_box_text_append (w->ser_b, "usb:");
572
1bc1c05b 573 gtk_combo_box_set_active (GTK_COMBO_BOX(w->ser_b), 0);
65f0ccab
AF
574 g_object_ref(w->ser_b);
575
4136d029 576 w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
2b756ea0 577 w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
aa6dfd27
RN
578 gboolean power_off;
579 if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_POWER_OFF, &power_off ) )
580 power_off = FALSE;
581 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->off_request_b), power_off);
2b756ea0 582
d6c58ab9
RN
583 w->get_tracks_l = gtk_label_new (_("Tracks:"));
584 w->get_tracks_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
aa6dfd27
RN
585 gboolean get_tracks;
586 if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_TRACKS, &get_tracks ) )
587 get_tracks = TRUE;
588 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_tracks_b), get_tracks);
d6c58ab9 589
0d2b891f
RN
590 w->get_routes_l = gtk_label_new (_("Routes:"));
591 w->get_routes_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
aa6dfd27
RN
592 gboolean get_routes;
593 if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_ROUTES, &get_routes ) )
594 get_routes = FALSE;
595 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_routes_b), get_routes);
0d2b891f 596
d6c58ab9
RN
597 w->get_waypoints_l = gtk_label_new (_("Waypoints:"));
598 w->get_waypoints_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
aa6dfd27
RN
599 gboolean get_waypoints;
600 if ( ! a_settings_get_boolean ( VIK_SETTINGS_GPS_GET_WAYPOINTS, &get_waypoints ) )
601 get_waypoints = TRUE;
602 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b), get_waypoints);
d6c58ab9
RN
603
604 box = GTK_TABLE(gtk_table_new(2, 4, FALSE));
605 data_type_box = GTK_TABLE(gtk_table_new(4, 1, FALSE));
606
65f0ccab
AF
607 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
608 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
609 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
610 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
d6c58ab9
RN
611 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_l), 0, 1, 0, 1);
612 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_b), 1, 2, 0, 1);
0d2b891f
RN
613 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_l), 2, 3, 0, 1);
614 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_routes_b), 3, 4, 0, 1);
615 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_l), 4, 5, 0, 1);
616 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_b), 5, 6, 0, 1);
d6c58ab9
RN
617 gtk_table_attach_defaults(box, GTK_WIDGET(data_type_box), 0, 2, 2, 3);
618 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 3, 4);
619 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 3, 4);
9b082b39 620 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(box), FALSE, FALSE, 5 );
65f0ccab
AF
621
622 gtk_widget_show_all ( dialog );
623}
624
d80e59ba
RN
625/**
626 * datasource_gps_setup:
627 * @dialog: The GTK dialog. The caller is responsible for managing the dialog creation/deletion
0d2b891f
RN
628 * @xfer: The default type of items enabled for transfer, others disabled.
629 * @xfer_all: When specified all items are enabled for transfer.
d80e59ba
RN
630 *
631 * Returns: A gpointer to the private structure for GPS progress/information widgets
632 * Pass this pointer back into the other exposed datasource_gps_X functions
633 */
0d2b891f 634gpointer datasource_gps_setup ( GtkWidget *dialog, vik_gps_xfer_type xfer, gboolean xfer_all )
d80e59ba 635{
307abf54 636 gps_user_data_t *w_gps = (gps_user_data_t *)datasource_gps_init_func ( NULL );
aa6dfd27 637 w_gps->direction = GPS_UP;
d80e59ba
RN
638 datasource_gps_add_setup_widgets ( dialog, NULL, w_gps );
639
0d2b891f
RN
640 gboolean way = xfer_all;
641 gboolean trk = xfer_all;
642 gboolean rte = xfer_all;
643
644 // Selectively turn bits on
645 if ( !xfer_all ) {
646 switch (xfer) {
647 case WPT: way = TRUE; break;
648 case RTE: rte = TRUE; break;
649 default: trk = TRUE; break;
650 }
d80e59ba 651 }
0d2b891f
RN
652
653 // Apply
654 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_tracks_b), trk );
655 gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_l), trk );
656 gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_tracks_b), trk );
657
658 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_routes_b), rte );
659 gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_l), rte );
660 gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_routes_b), rte );
661
662 gtk_toggle_button_set_active ( GTK_TOGGLE_BUTTON(w_gps->get_waypoints_b), way );
663 gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_l), way );
664 gtk_widget_set_sensitive ( GTK_WIDGET(w_gps->get_waypoints_b), way );
665
d80e59ba
RN
666 return (gpointer)w_gps;
667}
668
65f0ccab 669void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
7b3479e3 670{
0d2b891f 671 GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel, *rtelabel;
7b3479e3 672
65f0ccab 673 gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
7b3479e3 674
4c77d5e0 675 gpslabel = gtk_label_new (_("GPS device: N/A"));
7b3479e3
EB
676 verlabel = gtk_label_new ("");
677 idlabel = gtk_label_new ("");
678 wplabel = gtk_label_new ("");
679 trklabel = gtk_label_new ("");
0d2b891f 680 rtelabel = gtk_label_new ("");
7b3479e3 681
9b082b39
RN
682 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), gpslabel, FALSE, FALSE, 5 );
683 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), wplabel, FALSE, FALSE, 5 );
684 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), trklabel, FALSE, FALSE, 5 );
685 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), rtelabel, FALSE, FALSE, 5 );
7b3479e3 686
7b3479e3
EB
687 gtk_widget_show_all ( dialog );
688
689 w_gps->gps_label = gpslabel;
690 w_gps->id_label = idlabel;
691 w_gps->ver_label = verlabel;
692 w_gps->progress_label = w_gps->wp_label = wplabel;
693 w_gps->trk_label = trklabel;
0d2b891f 694 w_gps->rte_label = rtelabel;
7b3479e3 695 w_gps->total_count = -1;
7b3479e3 696}