]> git.street.me.uk Git - andy/viking.git/blame - src/datasource_gps.c
Improve grammar/usage for conversion macro function to convert meters into feet....
[andy/viking.git] / src / datasource_gps.c
CommitLineData
7b3479e3
EB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5 *
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.
10 *
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.
15 *
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
19 *
20 */
8aad4ca3
GB
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
7b3479e3 24#include <string.h>
99163c34
RN
25#ifdef HAVE_UNISTD_H
26#include <unistd.h>
27#endif
4c77d5e0 28
99163c34 29#include <glib/gstdio.h>
7b3479e3 30#include <glib/gprintf.h>
4c77d5e0 31#include <glib/gi18n.h>
7b3479e3
EB
32
33#include "viking.h"
34#include "babel.h"
35#include "gpx.h"
36#include "acquire.h"
37
1a8437ab
AF
38#if GTK_CHECK_VERSION(2,6,0)
39#define USE_NEW_COMBO_BOX
40#endif
41
7b3479e3
EB
42static gboolean gps_acquire_in_progress = FALSE;
43
65f0ccab 44static gpointer datasource_gps_init_func ( );
7b3479e3 45static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
65f0ccab 46static void datasource_gps_cleanup ( gpointer user_data );
7b3479e3 47static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
65f0ccab
AF
48static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
49static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
2b756ea0 50static void datasource_gps_off ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
7b3479e3
EB
51
52VikDataSourceInterface vik_datasource_gps_interface = {
4c77d5e0
GB
53 N_("Acquire from GPS"),
54 N_("Acquired from GPS"),
7b3479e3 55 VIK_DATASOURCE_GPSBABEL_DIRECT,
805d282e 56 VIK_DATASOURCE_CREATENEWLAYER,
28c82d8b
EB
57 VIK_DATASOURCE_INPUTTYPE_NONE,
58 TRUE,
65f0ccab 59 (VikDataSourceInitFunc) datasource_gps_init_func,
92255687 60 (VikDataSourceCheckExistenceFunc) NULL,
65f0ccab 61 (VikDataSourceAddSetupWidgetsFunc) datasource_gps_add_setup_widgets,
7b3479e3 62 (VikDataSourceGetCmdStringFunc) datasource_gps_get_cmd_string,
7b3479e3
EB
63 (VikDataSourceProgressFunc) datasource_gps_progress,
64 (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
2b756ea0
RN
65 (VikDataSourceCleanupFunc) datasource_gps_cleanup,
66 (VikDataSourceOffFunc) datasource_gps_off
7b3479e3
EB
67};
68
69/*********************************************************
70 * Definitions and routines for acquiring data from GPS
71 *********************************************************/
72
65f0ccab 73/* widgets in setup dialog specific to GPS */
7b3479e3
EB
74/* widgets in progress dialog specific to GPS */
75/* also counts needed for progress */
76typedef struct {
65f0ccab
AF
77 /* setup dialog */
78 GtkWidget *proto_l;
79 GtkComboBox *proto_b;
80 GtkWidget *ser_l;
81 GtkComboBox *ser_b;
2b756ea0
RN
82 GtkWidget *off_request_l;
83 GtkCheckButton *off_request_b;
65f0ccab
AF
84
85 /* progress dialog */
7b3479e3
EB
86 GtkWidget *gps_label;
87 GtkWidget *ver_label;
88 GtkWidget *id_label;
89 GtkWidget *wp_label;
90 GtkWidget *trk_label;
91 GtkWidget *progress_label;
65f0ccab
AF
92
93 /* state */
7b3479e3
EB
94 int total_count;
95 int count;
65f0ccab
AF
96} gps_user_data_t;
97
98static gpointer datasource_gps_init_func ()
99{
100 return g_malloc (sizeof(gps_user_data_t));
101}
7b3479e3 102
65f0ccab 103static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file )
7b3479e3 104{
cf7fdc15
GB
105 char *proto = NULL;
106 char *ser = NULL;
107 char *device = NULL;
1a8437ab 108#ifndef USE_NEW_COMBO_BOX
f3f1fa6c 109 GtkTreeIter iter;
1a8437ab 110#endif
65f0ccab
AF
111 gps_user_data_t *w = (gps_user_data_t *)user_data;
112
7b3479e3
EB
113 if (gps_acquire_in_progress) {
114 *babelargs = *input_file = NULL;
115 }
65f0ccab
AF
116
117 gps_acquire_in_progress = TRUE;
118
1a8437ab 119#ifdef USE_NEW_COMBO_BOX
cf7fdc15 120 proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
1a8437ab 121#else
cf7fdc15 122 proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
1a8437ab 123#endif
cf7fdc15
GB
124 if (!strcmp(proto, "Garmin")) {
125 device = "garmin";
65f0ccab 126 } else {
cf7fdc15 127 device = "magellan";
65f0ccab 128 }
2b756ea0 129
cf7fdc15
GB
130 *babelargs = g_strdup_printf("-D 9 -t -w -i %s", device);
131 /* device points to static content => no free */
132 device = NULL;
f3f1fa6c
AF
133
134 /* Old stuff */
1a8437ab 135#ifdef USE_NEW_COMBO_BOX
cf7fdc15 136 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
1a8437ab 137#else
cf7fdc15 138 ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
1a8437ab 139#endif
cf7fdc15 140 *input_file = g_strdup(ser);
7b3479e3 141
4c77d5e0 142 g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
7b3479e3
EB
143}
144
2b756ea0
RN
145
146static void datasource_gps_off ( gpointer user_data, gchar **babelargs, gchar **input_file )
147{
148 char *proto = NULL;
149 char *ser = NULL;
150 char *device = NULL;
151#ifndef USE_NEW_COMBO_BOX
152 GtkTreeIter iter;
153#endif
154 gps_user_data_t *w = (gps_user_data_t *)user_data;
155
156 if (gps_acquire_in_progress) {
157 *babelargs = *input_file = NULL;
158 }
159
160 /* See if we should turn off the device */
161 if (!gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w->off_request_b))) {
162 return;
163 }
164
165#ifdef USE_NEW_COMBO_BOX
166 proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
167#else
168 proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
169#endif
170 if (!strcmp(proto, "Garmin")) {
171 device = "garmin,power_off";
172 } else {
173 return;
174 }
175
176 *babelargs = g_strdup_printf("-i %s", device);
177 /* device points to static content => no free */
178 device = NULL;
179
180 /* Old stuff */
181#ifdef USE_NEW_COMBO_BOX
182 ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
183#else
184 ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
185#endif
186 *input_file = g_strdup(ser);
187}
188
189
65f0ccab 190static void datasource_gps_cleanup ( gpointer user_data )
7b3479e3 191{
65f0ccab 192 g_free ( user_data );
7b3479e3
EB
193 gps_acquire_in_progress = FALSE;
194}
195
196static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
197{
cf7fdc15 198 gchar *s = NULL;
7b3479e3
EB
199 gdk_threads_enter();
200 if (w->ok) {
65f0ccab 201 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
97634600
GB
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);
205 else
206 tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt);
207 s = g_strdup_printf(tmp_str, cnt);
7b3479e3
EB
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;
211 }
cf7fdc15 212 g_free(s); s = NULL;
7b3479e3
EB
213 gdk_threads_leave();
214}
215
216static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
217{
cf7fdc15 218 gchar *s = NULL;
7b3479e3
EB
219 gdk_threads_enter();
220 if (w->ok) {
65f0ccab 221 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
7b3479e3
EB
222
223 if (cnt < gps_data->total_count) {
4c77d5e0 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");
7b3479e3 225 } else {
4c77d5e0 226 s = g_strdup_printf(_("Downloaded %d %s."), cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
7b3479e3
EB
227 }
228 gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
229 }
cf7fdc15 230 g_free(s); s = NULL;
7b3479e3
EB
231 gdk_threads_leave();
232}
233
234static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
235{
cf7fdc15 236 gchar *s = NULL;
7b3479e3
EB
237 gdk_threads_enter();
238 if (w->ok) {
4c77d5e0 239 s = g_strdup_printf(_("GPS Device: %s"), info);
65f0ccab 240 gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
7b3479e3 241 }
cf7fdc15 242 g_free(s); s = NULL;
7b3479e3
EB
243 gdk_threads_leave();
244}
245
246/*
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.
250 */
251static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
252{
253 gchar *line;
65f0ccab 254 gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
7b3479e3 255
7b3479e3
EB
256 switch(c) {
257 case BABEL_DIAG_OUTPUT:
258 line = (gchar *)data;
259
260 /* tells us how many items there will be */
261 if (strstr(line, "Xfer Wpt")) {
262 gps_data->progress_label = gps_data->wp_label;
263 }
264 if (strstr(line, "Xfer Trk")) {
265 gps_data->progress_label = gps_data->trk_label;
266 }
267 if (strstr(line, "PRDDAT")) {
268 gchar **tokens = g_strsplit(line, " ", 0);
269 gchar info[128];
270 int ilen = 0;
271 int i;
c83b5ad9
QT
272 int n_tokens = 0;
273
274 while (tokens[n_tokens])
275 n_tokens++;
276
277 if (n_tokens > 8) {
278 for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
279 guint ch;
280 sscanf(tokens[i], "%x", &ch);
281 info[ilen++] = ch;
282 }
283 info[ilen++] = 0;
284 set_gps_info(info, w);
7b3479e3 285 }
c83b5ad9 286 g_strfreev(tokens);
7b3479e3 287 }
0a3f9142
RN
288 /* eg: "Unit:\teTrex Legend HCx Software Version 2.90\n" */
289 if (strstr(line, "Unit:")) {
290 gchar **tokens = g_strsplit(line, "\t", 0);
291 int n_tokens = 0;
292 while (tokens[n_tokens])
293 n_tokens++;
294
295 if (n_tokens > 1) {
296 set_gps_info(tokens[1], w);
297 }
298 g_strfreev(tokens);
299 }
7b3479e3
EB
300 if (strstr(line, "RECORD")) {
301 int lsb, msb, cnt;
302
c83b5ad9
QT
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);
308 gps_data->count = 0;
309 }
7b3479e3
EB
310 }
311 if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
312 gps_data->count++;
313 set_current_count(gps_data->count, w);
314 }
315 break;
316 case BABEL_DONE:
317 break;
318 default:
319 break;
320 }
321}
322
65f0ccab
AF
323void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
324{
325 gps_user_data_t *w = (gps_user_data_t *)user_data;
326 GtkTable* box;
327
4c77d5e0 328 w->proto_l = gtk_label_new (_("GPS Protocol:"));
65f0ccab
AF
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);
334
4c77d5e0 335 w->ser_l = gtk_label_new (_("Serial Port:"));
65f0ccab 336 w->ser_b = GTK_COMBO_BOX(gtk_combo_box_entry_new_text ());
8d70f073
MA
337#ifdef WINDOWS
338 gtk_combo_box_append_text (w->ser_b, "com1");
339#else
99163c34
RN
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");
8d70f073 351#endif
7963d365 352 gtk_combo_box_append_text (w->ser_b, "usb:");
65f0ccab
AF
353 gtk_combo_box_set_active (w->ser_b, 0);
354 g_object_ref(w->ser_b);
355
2b756ea0
RN
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 () );
358
359 box = GTK_TABLE(gtk_table_new(2, 3, FALSE));
65f0ccab
AF
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);
2b756ea0
RN
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);
65f0ccab
AF
366 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
367
368 gtk_widget_show_all ( dialog );
369}
370
371void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
7b3479e3
EB
372{
373 GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
374
65f0ccab 375 gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
7b3479e3 376
4c77d5e0 377 gpslabel = gtk_label_new (_("GPS device: N/A"));
7b3479e3
EB
378 verlabel = gtk_label_new ("");
379 idlabel = gtk_label_new ("");
380 wplabel = gtk_label_new ("");
381 trklabel = gtk_label_new ("");
382
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 );
386
7b3479e3
EB
387 gtk_widget_show_all ( dialog );
388
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;
7b3479e3 395}