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 #if GTK_CHECK_VERSION(2,6,0)
41 #define USE_NEW_COMBO_BOX
44 static gboolean gps_acquire_in_progress = FALSE;
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;
94 GtkWidget *progress_label;
101 static gpointer datasource_gps_init_func ()
103 return g_malloc (sizeof(gps_user_data_t));
106 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file )
111 #ifndef USE_NEW_COMBO_BOX
114 gps_user_data_t *w = (gps_user_data_t *)user_data;
116 if (gps_acquire_in_progress) {
117 *babelargs = *input_file = NULL;
120 gps_acquire_in_progress = TRUE;
122 #ifdef USE_NEW_COMBO_BOX
123 proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
125 proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
127 if (!strcmp(proto, "Garmin")) {
129 } else if (!strcmp(proto, "Magellan")) {
132 else if (!strcmp(proto, "DeLorme")) {
139 *babelargs = g_strdup_printf("-D 9 -t -w -i %s", device);
140 /* device points to static content => no free */
144 #ifdef USE_NEW_COMBO_BOX
145 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
147 ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
149 *input_file = g_strdup(ser);
151 g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
155 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
160 #ifndef USE_NEW_COMBO_BOX
163 gps_user_data_t *w = (gps_user_data_t *)user_data;
165 if (gps_acquire_in_progress) {
166 *babelargs = *input_file = NULL;
169 /* See if we should turn off the device */
170 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b))) {
174 #ifdef USE_NEW_COMBO_BOX
175 proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
177 proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
179 if (!strcmp(proto, "Garmin")) {
180 device = "garmin,power_off";
182 else if (!strcmp(proto, "NAViLink")) {
183 device = "navilink,power_off";
189 *babelargs = g_strdup_printf("-i %s", device);
190 /* device points to static content => no free */
194 #ifdef USE_NEW_COMBO_BOX
195 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
197 ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
199 *input_file = g_strdup(ser);
203 static void datasource_gps_cleanup ( gpointer user_data )
205 g_free ( user_data );
206 gps_acquire_in_progress = FALSE;
209 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
214 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
215 const gchar *tmp_str;
216 if (gps_data->progress_label == gps_data->wp_label)
217 tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt);
219 tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt);
220 s = g_strdup_printf(tmp_str, cnt);
221 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
222 gtk_widget_show ( gps_data->progress_label );
223 gps_data->total_count = cnt;
229 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
234 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
236 if (cnt < gps_data->total_count) {
237 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");
239 s = g_strdup_printf(_("Downloaded %d %s."), cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
241 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
247 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
252 s = g_strdup_printf(_("GPS Device: %s"), info);
253 gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
260 * This routine relies on gpsbabel's diagnostic output to display the progress information.
261 * These outputs differ when different GPS devices are used, so we will need to test
262 * them on several and add the corresponding support.
264 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
267 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
270 case BABEL_DIAG_OUTPUT:
271 line = (gchar *)data;
273 /* tells us how many items there will be */
274 if (strstr(line, "Xfer Wpt")) {
275 gps_data->progress_label = gps_data->wp_label;
277 if (strstr(line, "Xfer Trk")) {
278 gps_data->progress_label = gps_data->trk_label;
280 if (strstr(line, "PRDDAT")) {
281 gchar **tokens = g_strsplit(line, " ", 0);
287 while (tokens[n_tokens])
291 for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
293 sscanf(tokens[i], "%x", &ch);
297 set_gps_info(info, w);
301 /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
302 if (strstr(line, "Unit:")) {
303 gchar **tokens = g_strsplit(line, "\t", 0);
305 while (tokens[n_tokens])
309 set_gps_info(tokens[1], w);
313 if (strstr(line, "RECORD")) {
316 if (strlen(line) > 20) {
317 sscanf(line+17, "%x", &lsb);
318 sscanf(line+20, "%x", &msb);
319 cnt = lsb + msb * 256;
320 set_total_count(cnt, w);
324 if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
326 set_current_count(gps_data->count, w);
336 void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
338 gps_user_data_t *w = (gps_user_data_t *)user_data;
341 w->proto_l = gtk_label_new (_("GPS Protocol:"));
342 w->proto_b = GTK_COMBO_BOX(gtk_combo_box_new_text ());
343 gtk_combo_box_append_text (w->proto_b, "Garmin");
344 gtk_combo_box_append_text (w->proto_b, "Magellan");
345 gtk_combo_box_append_text (w->proto_b, "DeLorme");
346 gtk_combo_box_append_text (w->proto_b, "NAViLink");
347 gtk_combo_box_set_active (w->proto_b, 0);
348 g_object_ref(w->proto_b);
350 w->ser_l = gtk_label_new (_("Serial Port:"));
351 w->ser_b = GTK_COMBO_BOX(gtk_combo_box_entry_new_text ());
353 gtk_combo_box_append_text (w->ser_b, "com1");
355 /* Here just try to see if the device is available which gets passed onto gpsbabel
356 List USB devices first as these will generally only be present if autogenerated by udev or similar
357 User is still able to set their own free text entry */
358 if (g_access ("/dev/ttyUSB0", R_OK) == 0)
359 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB0");
360 if (g_access ("/dev/ttyUSB1", R_OK) == 0)
361 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB1");
362 if (g_access ("/dev/ttyS0", R_OK) == 0)
363 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS0");
364 if (g_access ("/dev/ttyS1", R_OK) == 0)
365 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS1");
367 gtk_combo_box_append_text (w->ser_b, "usb:");
368 gtk_combo_box_set_active (w->ser_b, 0);
369 g_object_ref(w->ser_b);
371 w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin/NAViLink Only)"));
372 w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
374 box = GTK_TABLE(gtk_table_new(2, 3, FALSE));
375 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
376 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
377 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
378 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
379 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 2, 3);
380 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 2, 3);
381 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
383 gtk_widget_show_all ( dialog );
386 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
388 GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
390 gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
392 gpslabel = gtk_label_new (_("GPS device: N/A"));
393 verlabel = gtk_label_new ("");
394 idlabel = gtk_label_new ("");
395 wplabel = gtk_label_new ("");
396 trklabel = gtk_label_new ("");
398 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
399 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
400 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
402 gtk_widget_show_all ( dialog );
404 w_gps->gps_label = gpslabel;
405 w_gps->id_label = idlabel;
406 w_gps->ver_label = verlabel;
407 w_gps->progress_label = w_gps->wp_label = wplabel;
408 w_gps->trk_label = trklabel;
409 w_gps->total_count = -1;