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,
61 (VikDataSourceInitFunc) datasource_gps_init_func,
62 (VikDataSourceCheckExistenceFunc) NULL,
63 (VikDataSourceAddSetupWidgetsFunc) datasource_gps_add_setup_widgets,
64 (VikDataSourceGetCmdStringFunc) datasource_gps_get_cmd_string,
65 (VikDataSourceProgressFunc) datasource_gps_progress,
66 (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
67 (VikDataSourceCleanupFunc) datasource_gps_cleanup,
68 (VikDataSourceOffFunc) datasource_gps_off
71 /*********************************************************
72 * Definitions and routines for acquiring data from GPS
73 *********************************************************/
75 /* widgets in setup dialog specific to GPS */
76 /* widgets in progress dialog specific to GPS */
77 /* also counts needed for progress */
84 GtkWidget *off_request_l;
85 GtkCheckButton *off_request_b;
93 GtkWidget *progress_label;
100 static gpointer datasource_gps_init_func ()
102 return g_malloc (sizeof(gps_user_data_t));
105 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file )
110 #ifndef USE_NEW_COMBO_BOX
113 gps_user_data_t *w = (gps_user_data_t *)user_data;
115 if (gps_acquire_in_progress) {
116 *babelargs = *input_file = NULL;
119 gps_acquire_in_progress = TRUE;
121 #ifdef USE_NEW_COMBO_BOX
122 proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
124 proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
126 if (!strcmp(proto, "Garmin")) {
132 *babelargs = g_strdup_printf("-D 9 -t -w -i %s", device);
133 /* device points to static content => no free */
137 #ifdef USE_NEW_COMBO_BOX
138 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
140 ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
142 *input_file = g_strdup(ser);
144 g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
148 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
153 #ifndef USE_NEW_COMBO_BOX
156 gps_user_data_t *w = (gps_user_data_t *)user_data;
158 if (gps_acquire_in_progress) {
159 *babelargs = *input_file = NULL;
162 /* See if we should turn off the device */
163 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b))) {
167 #ifdef USE_NEW_COMBO_BOX
168 proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
170 proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
172 if (!strcmp(proto, "Garmin")) {
173 device = "garmin,power_off";
178 *babelargs = g_strdup_printf("-i %s", device);
179 /* device points to static content => no free */
183 #ifdef USE_NEW_COMBO_BOX
184 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
186 ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
188 *input_file = g_strdup(ser);
192 static void datasource_gps_cleanup ( gpointer user_data )
194 g_free ( user_data );
195 gps_acquire_in_progress = FALSE;
198 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
203 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
204 const gchar *tmp_str;
205 if (gps_data->progress_label == gps_data->wp_label)
206 tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt);
208 tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt);
209 s = g_strdup_printf(tmp_str, cnt);
210 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
211 gtk_widget_show ( gps_data->progress_label );
212 gps_data->total_count = cnt;
218 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
223 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
225 if (cnt < gps_data->total_count) {
226 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");
228 s = g_strdup_printf(_("Downloaded %d %s."), cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
230 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
236 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
241 s = g_strdup_printf(_("GPS Device: %s"), info);
242 gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
249 * This routine relies on gpsbabel's diagnostic output to display the progress information.
250 * These outputs differ when different GPS devices are used, so we will need to test
251 * them on several and add the corresponding support.
253 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
256 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
259 case BABEL_DIAG_OUTPUT:
260 line = (gchar *)data;
262 /* tells us how many items there will be */
263 if (strstr(line, "Xfer Wpt")) {
264 gps_data->progress_label = gps_data->wp_label;
266 if (strstr(line, "Xfer Trk")) {
267 gps_data->progress_label = gps_data->trk_label;
269 if (strstr(line, "PRDDAT")) {
270 gchar **tokens = g_strsplit(line, " ", 0);
276 while (tokens[n_tokens])
280 for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
282 sscanf(tokens[i], "%x", &ch);
286 set_gps_info(info, w);
290 /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
291 if (strstr(line, "Unit:")) {
292 gchar **tokens = g_strsplit(line, "\t", 0);
294 while (tokens[n_tokens])
298 set_gps_info(tokens[1], w);
302 if (strstr(line, "RECORD")) {
305 if (strlen(line) > 20) {
306 sscanf(line+17, "%x", &lsb);
307 sscanf(line+20, "%x", &msb);
308 cnt = lsb + msb * 256;
309 set_total_count(cnt, w);
313 if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
315 set_current_count(gps_data->count, w);
325 void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
327 gps_user_data_t *w = (gps_user_data_t *)user_data;
330 w->proto_l = gtk_label_new (_("GPS Protocol:"));
331 w->proto_b = GTK_COMBO_BOX(gtk_combo_box_new_text ());
332 gtk_combo_box_append_text (w->proto_b, "Garmin");
333 gtk_combo_box_append_text (w->proto_b, "Magellan");
334 gtk_combo_box_set_active (w->proto_b, 0);
335 g_object_ref(w->proto_b);
337 w->ser_l = gtk_label_new (_("Serial Port:"));
338 w->ser_b = GTK_COMBO_BOX(gtk_combo_box_entry_new_text ());
340 gtk_combo_box_append_text (w->ser_b, "com1");
342 /* Here just try to see if the device is available which gets passed onto gpsbabel
343 List USB devices first as these will generally only be present if autogenerated by udev or similar
344 User is still able to set their own free text entry */
345 if (g_access ("/dev/ttyUSB0", R_OK) == 0)
346 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB0");
347 if (g_access ("/dev/ttyUSB1", R_OK) == 0)
348 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB1");
349 if (g_access ("/dev/ttyS0", R_OK) == 0)
350 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS0");
351 if (g_access ("/dev/ttyS1", R_OK) == 0)
352 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS1");
354 gtk_combo_box_append_text (w->ser_b, "usb:");
355 gtk_combo_box_set_active (w->ser_b, 0);
356 g_object_ref(w->ser_b);
358 w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin Only)"));
359 w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
361 box = GTK_TABLE(gtk_table_new(2, 3, FALSE));
362 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
363 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
364 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
365 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
366 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 2, 3);
367 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 2, 3);
368 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
370 gtk_widget_show_all ( dialog );
373 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
375 GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
377 gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
379 gpslabel = gtk_label_new (_("GPS device: N/A"));
380 verlabel = gtk_label_new ("");
381 idlabel = gtk_label_new ("");
382 wplabel = gtk_label_new ("");
383 trklabel = gtk_label_new ("");
385 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
386 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
387 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
389 gtk_widget_show_all ( dialog );
391 w_gps->gps_label = gpslabel;
392 w_gps->id_label = idlabel;
393 w_gps->ver_label = verlabel;
394 w_gps->progress_label = w_gps->wp_label = wplabel;
395 w_gps->trk_label = trklabel;
396 w_gps->total_count = -1;