2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 #include <glib/gstdio.h>
30 #include <glib/gprintf.h>
31 #include <glib/gi18n.h>
38 #if GTK_CHECK_VERSION(2,6,0)
39 #define USE_NEW_COMBO_BOX
42 static gboolean gps_acquire_in_progress = FALSE;
44 static gpointer datasource_gps_init_func ( );
45 static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
46 static void datasource_gps_cleanup ( gpointer user_data );
47 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
48 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
49 static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
50 static void datasource_gps_off ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
52 VikDataSourceInterface vik_datasource_gps_interface = {
53 N_("Acquire from GPS"),
54 N_("Acquired from GPS"),
55 VIK_DATASOURCE_GPSBABEL_DIRECT,
56 VIK_DATASOURCE_CREATENEWLAYER,
57 VIK_DATASOURCE_INPUTTYPE_NONE,
59 (VikDataSourceInitFunc) datasource_gps_init_func,
60 (VikDataSourceCheckExistenceFunc) NULL,
61 (VikDataSourceAddSetupWidgetsFunc) datasource_gps_add_setup_widgets,
62 (VikDataSourceGetCmdStringFunc) datasource_gps_get_cmd_string,
63 (VikDataSourceProgressFunc) datasource_gps_progress,
64 (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
65 (VikDataSourceCleanupFunc) datasource_gps_cleanup,
66 (VikDataSourceOffFunc) datasource_gps_off
69 /*********************************************************
70 * Definitions and routines for acquiring data from GPS
71 *********************************************************/
73 /* widgets in setup dialog specific to GPS */
74 /* widgets in progress dialog specific to GPS */
75 /* also counts needed for progress */
82 GtkWidget *off_request_l;
83 GtkCheckButton *off_request_b;
91 GtkWidget *progress_label;
98 static gpointer datasource_gps_init_func ()
100 return g_malloc (sizeof(gps_user_data_t));
103 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file )
108 #ifndef USE_NEW_COMBO_BOX
111 gps_user_data_t *w = (gps_user_data_t *)user_data;
113 if (gps_acquire_in_progress) {
114 *babelargs = *input_file = NULL;
117 gps_acquire_in_progress = TRUE;
119 #ifdef USE_NEW_COMBO_BOX
120 proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
122 proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
124 if (!strcmp(proto, "Garmin")) {
130 *babelargs = g_strdup_printf("-D 9 -t -w -i %s", device);
131 /* device points to static content => no free */
135 #ifdef USE_NEW_COMBO_BOX
136 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
138 ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
140 *input_file = g_strdup(ser);
142 g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
146 static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
151 #ifndef USE_NEW_COMBO_BOX
154 gps_user_data_t *w = (gps_user_data_t *)user_data;
156 if (gps_acquire_in_progress) {
157 *babelargs = *input_file = NULL;
160 /* See if we should turn off the device */
161 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b))) {
165 #ifdef USE_NEW_COMBO_BOX
166 proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
168 proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
170 if (!strcmp(proto, "Garmin")) {
171 device = "garmin,power_off";
176 *babelargs = g_strdup_printf("-i %s", device);
177 /* device points to static content => no free */
181 #ifdef USE_NEW_COMBO_BOX
182 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
184 ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
186 *input_file = g_strdup(ser);
190 static void datasource_gps_cleanup ( gpointer user_data )
192 g_free ( user_data );
193 gps_acquire_in_progress = FALSE;
196 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
201 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
202 const gchar *tmp_str;
203 if (gps_data->progress_label == gps_data->wp_label)
204 tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt);
206 tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt);
207 s = g_strdup_printf(tmp_str, cnt);
208 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
209 gtk_widget_show ( gps_data->progress_label );
210 gps_data->total_count = cnt;
216 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
221 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
223 if (cnt < gps_data->total_count) {
224 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");
226 s = g_strdup_printf(_("Downloaded %d %s."), cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
228 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
234 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
239 s = g_strdup_printf(_("GPS Device: %s"), info);
240 gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
247 * This routine relies on gpsbabel's diagnostic output to display the progress information.
248 * These outputs differ when different GPS devices are used, so we will need to test
249 * them on several and add the corresponding support.
251 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
254 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
257 case BABEL_DIAG_OUTPUT:
258 line = (gchar *)data;
260 /* tells us how many items there will be */
261 if (strstr(line, "Xfer Wpt")) {
262 gps_data->progress_label = gps_data->wp_label;
264 if (strstr(line, "Xfer Trk")) {
265 gps_data->progress_label = gps_data->trk_label;
267 if (strstr(line, "PRDDAT")) {
268 gchar **tokens = g_strsplit(line, " ", 0);
274 while (tokens[n_tokens])
278 for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
280 sscanf(tokens[i], "%x", &ch);
284 set_gps_info(info, w);
288 /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
289 if (strstr(line, "Unit:")) {
290 gchar **tokens = g_strsplit(line, "\t", 0);
292 while (tokens[n_tokens])
296 set_gps_info(tokens[1], w);
300 if (strstr(line, "RECORD")) {
303 if (strlen(line) > 20) {
304 sscanf(line+17, "%x", &lsb);
305 sscanf(line+20, "%x", &msb);
306 cnt = lsb + msb * 256;
307 set_total_count(cnt, w);
311 if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
313 set_current_count(gps_data->count, w);
323 void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
325 gps_user_data_t *w = (gps_user_data_t *)user_data;
328 w->proto_l = gtk_label_new (_("GPS Protocol:"));
329 w->proto_b = GTK_COMBO_BOX(gtk_combo_box_new_text ());
330 gtk_combo_box_append_text (w->proto_b, "Garmin");
331 gtk_combo_box_append_text (w->proto_b, "Magellan");
332 gtk_combo_box_set_active (w->proto_b, 0);
333 g_object_ref(w->proto_b);
335 w->ser_l = gtk_label_new (_("Serial Port:"));
336 w->ser_b = GTK_COMBO_BOX(gtk_combo_box_entry_new_text ());
338 gtk_combo_box_append_text (w->ser_b, "com1");
340 /* Here just try to see if the device is available which gets passed onto gpsbabel
341 List USB devices first as these will generally only be present if autogenerated by udev or similar
342 User is still able to set their own free text entry */
343 if (g_access ("/dev/ttyUSB0", R_OK) == 0)
344 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB0");
345 if (g_access ("/dev/ttyUSB1", R_OK) == 0)
346 gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB1");
347 if (g_access ("/dev/ttyS0", R_OK) == 0)
348 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS0");
349 if (g_access ("/dev/ttyS1", R_OK) == 0)
350 gtk_combo_box_append_text (w->ser_b, "/dev/ttyS1");
352 gtk_combo_box_append_text (w->ser_b, "usb:");
353 gtk_combo_box_set_active (w->ser_b, 0);
354 g_object_ref(w->ser_b);
356 w->off_request_l = gtk_label_new (_("Turn Off After Transfer\n(Garmin Only)"));
357 w->off_request_b = GTK_CHECK_BUTTON ( gtk_check_button_new () );
359 box = GTK_TABLE(gtk_table_new(2, 3, FALSE));
360 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
361 gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
362 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
363 gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
364 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_l), 0, 1, 2, 3);
365 gtk_table_attach_defaults(box, GTK_WIDGET(w->off_request_b), 1, 3, 2, 3);
366 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
368 gtk_widget_show_all ( dialog );
371 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
373 GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
375 gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
377 gpslabel = gtk_label_new (_("GPS device: N/A"));
378 verlabel = gtk_label_new ("");
379 idlabel = gtk_label_new ("");
380 wplabel = gtk_label_new ("");
381 trklabel = gtk_label_new ("");
383 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
384 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
385 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
387 gtk_widget_show_all ( dialog );
389 w_gps->gps_label = gpslabel;
390 w_gps->id_label = idlabel;
391 w_gps->ver_label = verlabel;
392 w_gps->progress_label = w_gps->wp_label = wplabel;
393 w_gps->trk_label = trklabel;
394 w_gps->total_count = -1;