]> git.street.me.uk Git - andy/viking.git/blame - src/datasource_gps.c
Extract a UI module for babel
[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 481static gint find_entry = -1;
aa6dfd27 482static gint wanted_entry = -1;
3f6db253 483
aa6dfd27 484static void find_protocol (gpointer elem, gpointer user_data)
3f6db253
RN
485{
486 const gchar *name = ((BabelDevice*)elem)->name;
aa6dfd27 487 const gchar *protocol = user_data;
3f6db253 488 find_entry++;
aa6dfd27
RN
489 if (!strcmp(name, protocol)) {
490 wanted_entry = find_entry;
3f6db253
RN
491 }
492}
493
d80e59ba 494static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
65f0ccab
AF
495{
496 gps_user_data_t *w = (gps_user_data_t *)user_data;
d6c58ab9 497 GtkTable *box, *data_type_box;
65f0ccab 498
4c77d5e0 499 w->proto_l = gtk_label_new (_("GPS Protocol:"));
1bc1c05b 500 w->proto_b = vik_combo_box_text_new ();
8627bd99 501 g_list_foreach (a_babel_device_list, append_element, w->proto_b);
3f6db253 502
3f6db253
RN
503 if ( last_active < 0 ) {
504 find_entry = -1;
aa6dfd27
RN
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);
aa6dfd27
RN
511 }
512 else {
a8ae980e 513 // Attempt to maintain default to Garmin devices (assumed most popular/numerous device)
aa6dfd27 514 g_list_foreach (a_babel_device_list, find_protocol, "garmin");
aa6dfd27 515 }
a8ae980e
RN
516 // If not found set it to the first entry, otherwise use the entry
517 last_active = ( wanted_entry < 0 ) ? 0 : wanted_entry;
3f6db253
RN
518 }
519
1bc1c05b 520 gtk_combo_box_set_active (GTK_COMBO_BOX(w->proto_b), last_active);
65f0ccab
AF
521 g_object_ref(w->proto_b);
522
4c77d5e0 523 w->ser_l = gtk_label_new (_("Serial Port:"));
1bc1c05b
RN
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
aa6dfd27
RN
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
8d70f073 547#ifdef WINDOWS
aa6dfd27
RN
548 if ( gps_port && strcmp (gps_port, "com1") )
549 vik_combo_box_text_append (w->ser_b, "com1");
8d70f073 550#else
99163c34
RN
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 */
aa6dfd27
RN
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");
8d70f073 566#endif
aa6dfd27
RN
567 if ( gps_port && strcmp (gps_port, "usb:") )
568 vik_combo_box_text_append (w->ser_b, "usb:");
569
1bc1c05b 570 gtk_combo_box_set_active (GTK_COMBO_BOX(w->ser_b), 0);
65f0ccab
AF
571 g_object_ref(w->ser_b);
572
4136d029 573 w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
2b756ea0 574 w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
aa6dfd27
RN
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);
2b756ea0 579
d6c58ab9
RN
580 w->get_tracks_l = gtk_label_new (_("Tracks:"));
581 w->get_tracks_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
aa6dfd27
RN
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);
d6c58ab9 586
0d2b891f
RN
587 w->get_routes_l = gtk_label_new (_("Routes:"));
588 w->get_routes_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
aa6dfd27
RN
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);
0d2b891f 593
d6c58ab9
RN
594 w->get_waypoints_l = gtk_label_new (_("Waypoints:"));
595 w->get_waypoints_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
aa6dfd27
RN
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);
d6c58ab9
RN
600
601 box = GTK_TABLE(gtk_table_new(2, 4, FALSE));
602 data_type_box = GTK_TABLE(gtk_table_new(4, 1, FALSE));
603
65f0ccab
AF
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);
d6c58ab9
RN
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);
0d2b891f
RN
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);
d6c58ab9
RN
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);
9b082b39 617 gtk_box_pack_start ( GTK_BOX(gtk_dialog_get_content_area(GTK_DIALOG(dialog))), GTK_WIDGET(box), FALSE, FALSE, 5 );
65f0ccab
AF
618
619 gtk_widget_show_all ( dialog );
620}
621
d80e59ba
RN
622/**
623 * datasource_gps_setup:
624 * @dialog: The GTK dialog. The caller is responsible for managing the dialog creation/deletion
0d2b891f
RN
625 * @xfer: The default type of items enabled for transfer, others disabled.
626 * @xfer_all: When specified all items are enabled for transfer.
d80e59ba
RN
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 */
0d2b891f 631gpointer datasource_gps_setup ( GtkWidget *dialog, vik_gps_xfer_type xfer, gboolean xfer_all )
d80e59ba 632{
307abf54 633 gps_user_data_t *w_gps = (gps_user_data_t *)datasource_gps_init_func ( NULL );
aa6dfd27 634 w_gps->direction = GPS_UP;
d80e59ba
RN
635 datasource_gps_add_setup_widgets ( dialog, NULL, w_gps );
636
0d2b891f
RN
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 }
d80e59ba 648 }
0d2b891f
RN
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
d80e59ba
RN
663 return (gpointer)w_gps;
664}
665
65f0ccab 666void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
7b3479e3 667{
0d2b891f 668 GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel, *rtelabel;
7b3479e3 669
65f0ccab 670 gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
7b3479e3 671
4c77d5e0 672 gpslabel = gtk_label_new (_("GPS device: N/A"));
7b3479e3
EB
673 verlabel = gtk_label_new ("");
674 idlabel = gtk_label_new ("");
675 wplabel = gtk_label_new ("");
676 trklabel = gtk_label_new ("");
0d2b891f 677 rtelabel = gtk_label_new ("");
7b3479e3 678
9b082b39
RN
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 );
7b3479e3 683
7b3479e3
EB
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;
0d2b891f 691 w_gps->rte_label = rtelabel;
7b3479e3 692 w_gps->total_count = -1;
7b3479e3 693}