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 (VikDataSourceProcessFunc) NULL,
67 (VikDataSourceProgressFunc) datasource_gps_progress,
68 (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
69 (VikDataSourceCleanupFunc) datasource_gps_cleanup,
70 (VikDataSourceOffFunc) datasource_gps_off
73 /*********************************************************
74 * Definitions and routines for acquiring data from GPS
75 *********************************************************/
77 /* widgets in setup dialog specific to GPS */
78 /* widgets in progress dialog specific to GPS */
79 /* also counts needed for progress */
86 GtkWidget *off_request_l;
87 GtkCheckButton *off_request_b;
88 GtkWidget *get_tracks_l;
89 GtkCheckButton *get_tracks_b;
90 GtkWidget *get_waypoints_l;
91 GtkCheckButton *get_waypoints_b;
99 GtkWidget *progress_label;
106 static gpointer datasource_gps_init_func ()
108 return g_malloc (sizeof(gps_user_data_t));
111 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file )
116 char *waypoints = NULL;
117 gps_user_data_t *w = (gps_user_data_t *)user_data;
119 if (gps_acquire_in_progress) {
120 *babelargs = *input_file = NULL;
123 gps_acquire_in_progress = TRUE;
125 last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
126 if (a_babel_device_list)
127 device = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
129 last_get_tracks = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_tracks_b));
134 last_get_waypoints = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b));
135 if (last_get_waypoints)
140 *babelargs = g_strdup_printf("-D 9 %s %s -i %s", tracks, waypoints, device);
141 /* device points to static content => no free */
146 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
147 *input_file = g_strdup(ser);
149 g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
153 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
157 gps_user_data_t *w = (gps_user_data_t *)user_data;
159 if (gps_acquire_in_progress) {
160 *babelargs = *input_file = NULL;
163 /* See if we should turn off the device */
164 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b))) {
168 if (!a_babel_device_list)
170 last_active = gtk_combo_box_get_active(GTK_COMBO_BOX(w->proto_b));
171 device = ((BabelDevice*)g_list_nth_data(a_babel_device_list, last_active))->name;
172 if (!strcmp(device, "garmin")) {
173 device = "garmin,power_off";
175 else if (!strcmp(device, "navilink")) {
176 device = "navilink,power_off";
182 *babelargs = g_strdup_printf("-i %s", device);
183 /* device points to static content => no free */
186 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
187 *input_file = g_strdup(ser);
191 static void datasource_gps_cleanup ( gpointer user_data )
193 g_free ( user_data );
194 gps_acquire_in_progress = FALSE;
197 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
202 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
203 const gchar *tmp_str;
204 if (gps_data->progress_label == gps_data->wp_label)
205 tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt);
207 tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt);
208 s = g_strdup_printf(tmp_str, cnt);
209 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
210 gtk_widget_show ( gps_data->progress_label );
211 gps_data->total_count = cnt;
217 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
222 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
224 if (cnt < gps_data->total_count) {
225 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");
227 s = g_strdup_printf(_("Downloaded %d %s."), cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
229 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
235 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
240 s = g_strdup_printf(_("GPS Device: %s"), info);
241 gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
248 * This routine relies on gpsbabel's diagnostic output to display the progress information.
249 * These outputs differ when different GPS devices are used, so we will need to test
250 * them on several and add the corresponding support.
252 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
255 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
258 case BABEL_DIAG_OUTPUT:
259 line = (gchar *)data;
261 /* tells us how many items there will be */
262 if (strstr(line, "Xfer Wpt")) {
263 gps_data->progress_label = gps_data->wp_label;
265 if (strstr(line, "Xfer Trk")) {
266 gps_data->progress_label = gps_data->trk_label;
268 if (strstr(line, "PRDDAT")) {
269 gchar **tokens = g_strsplit(line, " ", 0);
275 while (tokens[n_tokens])
279 for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
281 sscanf(tokens[i], "%x", &ch);
285 set_gps_info(info, w);
289 /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
290 if (strstr(line, "Unit:")) {
291 gchar **tokens = g_strsplit(line, "\t", 0);
293 while (tokens[n_tokens])
297 set_gps_info(tokens[1], w);
301 if (strstr(line, "RECORD")) {
304 if (strlen(line) > 20) {
305 sscanf(line+17, "%x", &lsb);
306 sscanf(line+20, "%x", &msb);
307 cnt = lsb + msb * 256;
308 set_total_count(cnt, w);
312 if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
314 set_current_count(gps_data->count, w);
324 void append_element (gpointer elem, gpointer user_data)
326 GtkComboBox *combo = GTK_COMBO_BOX (user_data);
327 const gchar *text = ((BabelDevice*)elem)->label;
328 gtk_combo_box_append_text (combo, text);
331 static gint find_entry = -1;
332 static gint garmin_entry = -1;
334 static void find_garmin (gpointer elem, gpointer user_data)
336 const gchar *name = ((BabelDevice*)elem)->name;
338 if (!strcmp(name, "garmin")) {
339 garmin_entry = find_entry;
343 void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
345 gps_user_data_t *w = (gps_user_data_t *)user_data;
346 GtkTable *box, *data_type_box;
348 w->proto_l = gtk_label_new (_("GPS Protocol:"));
349 w->proto_b = GTK_COMBO_BOX(gtk_combo_box_new_text ());
350 g_list_foreach (a_babel_device_list, append_element, w->proto_b);
352 // Maintain default to Garmin devices (assumed most popular/numerous device)
353 if ( last_active < 0 ) {
355 g_list_foreach (a_babel_device_list, find_garmin, NULL);
356 if ( garmin_entry < 0 )
357 // Not found - so set it to the first entry
361 last_active = garmin_entry;
364 gtk_combo_box_set_active (w->proto_b, last_active);
365 g_object_ref(w->proto_b);
367 w->ser_l = gtk_label_new (_("Serial Port:"));
368 w->ser_b = GTK_COMBO_BOX(gtk_combo_box_entry_new_text ());
370 gtk_combo_box_append_text (w->ser_b, "com1");
372 /* Here just try to see if the device is available which gets passed onto gpsbabel
373 List USB devices first as these will generally only be present if autogenerated by udev or similar
374 User is still able to set their own free text entry */
375 if (g_access ("/dev/ttyUSB0", R_OK) == 0)
376 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB0");
377 if (g_access ("/dev/ttyUSB1", R_OK) == 0)
378 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB1");
379 if (g_access ("/dev/ttyS0", R_OK) == 0)
380 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS0");
381 if (g_access ("/dev/ttyS1", R_OK) == 0)
382 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS1");
384 gtk_combo_box_append_text (w->ser_b, "usb:");
385 gtk_combo_box_set_active (w->ser_b, 0);
386 g_object_ref(w->ser_b);
388 w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
389 w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
391 w->get_tracks_l = gtk_label_new (_("Tracks:"));
392 w->get_tracks_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
393 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_tracks_b), last_get_tracks);
395 w->get_waypoints_l = gtk_label_new (_("Waypoints:"));
396 w->get_waypoints_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
397 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w->get_waypoints_b), last_get_waypoints);
399 box = GTK_TABLE(gtk_table_new(2, 4, FALSE));
400 data_type_box = GTK_TABLE(gtk_table_new(4, 1, FALSE));
402 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
403 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
404 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
405 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
406 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_l), 0, 1, 0, 1);
407 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_tracks_b), 1, 2, 0, 1);
408 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_l), 2, 3, 0, 1);
409 gtk_table_attach_defaults(data_type_box, GTK_WIDGET(w->get_waypoints_b), 3, 4, 0, 1);
410 gtk_table_attach_defaults(box, GTK_WIDGET(data_type_box), 0, 2, 2, 3);
411 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 3, 4);
412 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 3, 4);
413 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
415 gtk_widget_show_all ( dialog );
418 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
420 GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
422 gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
424 gpslabel = gtk_label_new (_("GPS device: N/A"));
425 verlabel = gtk_label_new ("");
426 idlabel = gtk_label_new ("");
427 wplabel = gtk_label_new ("");
428 trklabel = gtk_label_new ("");
430 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
431 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
432 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
434 gtk_widget_show_all ( dialog );
436 w_gps->gps_label = gpslabel;
437 w_gps->id_label = idlabel;
438 w_gps->ver_label = verlabel;
439 w_gps->progress_label = w_gps->wp_label = wplabel;
440 w_gps->trk_label = trklabel;
441 w_gps->total_count = -1;