2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5 * Copyright (C) 2006, Alex Foobarian <foobarian@gmail.com>
6 * Copyright (C) 2010, Rob Norris <rw_norris@hotmail.com>
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.
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.
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
31 #include <glib/gstdio.h>
32 #include <glib/gprintf.h>
33 #include <glib/gi18n.h>
40 static gboolean gps_acquire_in_progress = FALSE;
42 static gint last_active = -1;
43 static gboolean last_get_tracks = TRUE;
44 static gboolean last_get_waypoints = TRUE;
46 static gpointer datasource_gps_init_func ( );
47 static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
48 static void datasource_gps_cleanup ( gpointer user_data );
49 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
50 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
51 static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
52 static void datasource_gps_off ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
54 VikDataSourceInterface vik_datasource_gps_interface = {
55 N_("Acquire from GPS"),
56 N_("Acquired from GPS"),
57 VIK_DATASOURCE_GPSBABEL_DIRECT,
58 VIK_DATASOURCE_CREATENEWLAYER,
59 VIK_DATASOURCE_INPUTTYPE_NONE,
62 (VikDataSourceInitFunc) datasource_gps_init_func,
63 (VikDataSourceCheckExistenceFunc) NULL,
64 (VikDataSourceAddSetupWidgetsFunc) datasource_gps_add_setup_widgets,
65 (VikDataSourceGetCmdStringFunc) datasource_gps_get_cmd_string,
66 (VikDataSourceProgressFunc) datasource_gps_progress,
67 (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
68 (VikDataSourceCleanupFunc) datasource_gps_cleanup,
69 (VikDataSourceOffFunc) datasource_gps_off
72 /*********************************************************
73 * Definitions and routines for acquiring data from GPS
74 *********************************************************/
76 /* widgets in setup dialog specific to GPS */
77 /* widgets in progress dialog specific to GPS */
78 /* also counts needed for progress */
85 GtkWidget *off_request_l;
86 GtkCheckButton *off_request_b;
87 GtkWidget *get_tracks_l;
88 GtkCheckButton *get_tracks_b;
89 GtkWidget *get_waypoints_l;
90 GtkCheckButton *get_waypoints_b;
98 GtkWidget *progress_label;
105 static gpointer datasource_gps_init_func ()
107 return g_malloc (sizeof(gps_user_data_t));
110 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file )
115 char *waypoints = NULL;
116 gps_user_data_t *w = (gps_user_data_t *)user_data;
118 if (gps_acquire_in_progress) {
119 *babelargs = *input_file = NULL;
122 gps_acquire_in_progress = TRUE;
124 last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
125 device = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
127 last_get_tracks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_tracks_b));
132 last_get_waypoints = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b));
133 if (last_get_waypoints)
138 *babelargs = g_strdup_printf("-D 9 %s %s -i %s", tracks, waypoints, device);
139 /* device points to static content => no free */
144 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
145 *input_file = g_strdup(ser);
147 g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
151 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
155 gps_user_data_t *w = (gps_user_data_t *)user_data;
157 if (gps_acquire_in_progress) {
158 *babelargs = *input_file = NULL;
161 /* See if we should turn off the device */
162 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b))) {
166 last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
167 device = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
168 if (!strcmp(device, "garmin")) {
169 device = "garmin,power_off";
171 else if (!strcmp(device, "navilink")) {
172 device = "navilink,power_off";
178 *babelargs = g_strdup_printf("-i %s", device);
179 /* device points to static content => no free */
182 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
183 *input_file = g_strdup(ser);
187 static void datasource_gps_cleanup ( gpointer user_data )
189 g_free ( user_data );
190 gps_acquire_in_progress = FALSE;
193 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
198 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
199 const gchar *tmp_str;
200 if (gps_data->progress_label == gps_data->wp_label)
201 tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt);
203 tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt);
204 s = g_strdup_printf(tmp_str, cnt);
205 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
206 gtk_widget_show ( gps_data->progress_label );
207 gps_data->total_count = cnt;
213 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
218 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
220 if (cnt < gps_data->total_count) {
221 s = g_strdup_printf(_("Downloaded %d out of %d %s..."), cnt, gps_data->total_count, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
223 s = g_strdup_printf(_("Downloaded %d %s."), cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
225 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
231 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
236 s = g_strdup_printf(_("GPS Device: %s"), info);
237 gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
244 * This routine relies on gpsbabel's diagnostic output to display the progress information.
245 * These outputs differ when different GPS devices are used, so we will need to test
246 * them on several and add the corresponding support.
248 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
251 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
254 case BABEL_DIAG_OUTPUT:
255 line = (gchar *)data;
257 /* tells us how many items there will be */
258 if (strstr(line, "Xfer Wpt")) {
259 gps_data->progress_label = gps_data->wp_label;
261 if (strstr(line, "Xfer Trk")) {
262 gps_data->progress_label = gps_data->trk_label;
264 if (strstr(line, "PRDDAT")) {
265 gchar **tokens = g_strsplit(line, " ", 0);
271 while (tokens[n_tokens])
275 for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
277 sscanf(tokens[i], "%x", &ch);
281 set_gps_info(info, w);
285 /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
286 if (strstr(line, "Unit:")) {
287 gchar **tokens = g_strsplit(line, "\t", 0);
289 while (tokens[n_tokens])
293 set_gps_info(tokens[1], w);
297 if (strstr(line, "RECORD")) {
300 if (strlen(line) > 20) {
301 sscanf(line+17, "%x", &lsb);
302 sscanf(line+20, "%x", &msb);
303 cnt = lsb + msb * 256;
304 set_total_count(cnt, w);
308 if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
310 set_current_count(gps_data->count, w);
320 void append_element (gpointer elem, gpointer user_data)
322 GtkComboBox *combo = GTK_COMBO_BOX (user_data);
323 const gchar *text = ((BabelDevice*)elem)->label;
324 gtk_combo_box_append_text (combo, text);
327 static gint find_entry = -1;
328 static gint garmin_entry = -1;
330 static void find_garmin (gpointer elem, gpointer user_data)
332 const gchar *name = ((BabelDevice*)elem)->name;
334 if (!strcmp(name, "garmin")) {
335 garmin_entry = find_entry;
339 void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
341 gps_user_data_t *w = (gps_user_data_t *)user_data;
342 GtkTable *box, *data_type_box;
344 w->proto_l = gtk_label_new (_("GPS Protocol:"));
345 w->proto_b = GTK_COMBO_BOX(gtk_combo_box_new_text ());
346 g_list_foreach (a_babel_device_list, append_element, w->proto_b);
348 // Maintain default to Garmin devices (assumed most popular/numerous device)
349 if ( last_active < 0 ) {
351 g_list_foreach (a_babel_device_list, find_garmin, NULL);
352 if ( garmin_entry < 0 )
353 // Not found - so set it to the first entry
357 last_active = garmin_entry;
360 gtk_combo_box_set_active (w->proto_b, last_active);
361 g_object_ref(w->proto_b);
363 w->ser_l = gtk_label_new (_("Serial Port:"));
364 w->ser_b = GTK_COMBO_BOX(gtk_combo_box_entry_new_text ());
366 gtk_combo_box_append_text (w->ser_b, "com1");
368 /* Here just try to see if the device is available which gets passed onto gpsbabel
369 List USB devices first as these will generally only be present if autogenerated by udev or similar
370 User is still able to set their own free text entry */
371 if (g_access ("/dev/ttyUSB0", R_OK) == 0)
372 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB0");
373 if (g_access ("/dev/ttyUSB1", R_OK) == 0)
374 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB1");
375 if (g_access ("/dev/ttyS0", R_OK) == 0)
376 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS0");
377 if (g_access ("/dev/ttyS1", R_OK) == 0)
378 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS1");
380 gtk_combo_box_append_text (w->ser_b, "usb:");
381 gtk_combo_box_set_active (w->ser_b, 0);
382 g_object_ref(w->ser_b);
384 w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
385 w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
387 w->get_tracks_l = gtk_label_new (_("Tracks:"));
388 w->get_tracks_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
389 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_tracks_b), last_get_tracks);
391 w->get_waypoints_l = gtk_label_new (_("Waypoints:"));
392 w->get_waypoints_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
393 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b), last_get_waypoints);
395 box = GTK_TABLE(gtk_table_new(2, 4, FALSE));
396 data_type_box = GTK_TABLE(gtk_table_new(4, 1, FALSE));
398 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
399 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
400 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
401 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
402 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_l), 0, 1, 0, 1);
403 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_b), 1, 2, 0, 1);
404 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_l), 2, 3, 0, 1);
405 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_b), 3, 4, 0, 1);
406 gtk_table_attach_defaults(box, GTK_WIDGET(data_type_box), 0, 2, 2, 3);
407 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 3, 4);
408 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 3, 4);
409 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
411 gtk_widget_show_all ( dialog );
414 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
416 GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
418 gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
420 gpslabel = gtk_label_new (_("GPS device: N/A"));
421 verlabel = gtk_label_new ("");
422 idlabel = gtk_label_new ("");
423 wplabel = gtk_label_new ("");
424 trklabel = gtk_label_new ("");
426 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
427 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
428 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
430 gtk_widget_show_all ( dialog );
432 w_gps->gps_label = gpslabel;
433 w_gps->id_label = idlabel;
434 w_gps->ver_label = verlabel;
435 w_gps->progress_label = w_gps->wp_label = wplabel;
436 w_gps->trk_label = trklabel;
437 w_gps->total_count = -1;