]> git.street.me.uk Git - andy/viking.git/blame - src/acquire.c
Alex's GPSBabel acquire code
[andy/viking.git] / src / acquire.c
CommitLineData
1d1bc3c1
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 */
21#include <string.h>
22#include <glib/gprintf.h>
23
24#include "viking.h"
25#include "babel.h"
26#include "gpx.h"
27
28/*********************************************************
29 * Definitions and routines for acquiring data from GPS
30 *********************************************************/
31
32/* global data structure used to expose the progress dialog to the worker thread */
33typedef struct {
34 VikWindow *vw;
35 VikLayersPanel *vlp;
36 VikViewport *vvp;
37 GtkWidget *dialog;
38 GtkWidget *status;
39 GtkWidget *gps_label;
40 GtkWidget *ver_label;
41 GtkWidget *id_label;
42 GtkWidget *wp_label;
43 GtkWidget *trk_label;
44 GtkWidget *progress_label;
45 gboolean ok;
46} acq_dialog_widgets_t;
47
48acq_dialog_widgets_t *w = NULL;
49int total_count = -1;
50int count;
51
52static void set_total_count(gint cnt)
53{
54 gchar s[128];
55 gdk_threads_enter();
56 if (w->ok) {
57 g_sprintf(s, "Downloading %d %s...", cnt, (w->progress_label == w->wp_label) ? "waypoints" : "trackpoints");
58 gtk_label_set_text ( GTK_LABEL(w->progress_label), s );
59 gtk_widget_show ( w->progress_label );
60 total_count = cnt;
61 }
62 gdk_threads_leave();
63}
64
65static void set_current_count(gint cnt)
66{
67 gchar s[128];
68 gdk_threads_enter();
69 if (w->ok) {
70 if (cnt < total_count) {
71 g_sprintf(s, "Downloaded %d out of %d %s...", cnt, total_count, (w->progress_label == w->wp_label) ? "waypoints" : "trackpoints");
72 } else {
73 g_sprintf(s, "Downloaded %d %s.", cnt, (w->progress_label == w->wp_label) ? "waypoints" : "trackpoints");
74 }
75 gtk_label_set_text ( GTK_LABEL(w->progress_label), s );
76 }
77 gdk_threads_leave();
78}
79
80static void set_gps_info(const gchar *info)
81{
82 gchar s[256];
83 gdk_threads_enter();
84 if (w->ok) {
85 g_sprintf(s, "GPS Device: %s", info);
86 gtk_label_set_text ( GTK_LABEL(w->gps_label), s );
87 }
88 gdk_threads_leave();
89}
90
91/*
92 * This routine relies on gpsbabel's diagnostic output to display the progress information.
93 * These outputs differ when different GPS devices are used, so we will need to test
94 * them on several and add the corresponding support.
95 */
96static void progress_func ( BabelProgressCode c, gpointer data )
97{
98 gchar *line;
99
100 switch(c) {
101 case BABEL_DIAG_OUTPUT:
102 line = (gchar *)data;
103
104 /* tells us how many items there will be */
105 if (strstr(line, "Xfer Wpt")) {
106 w->progress_label = w->wp_label;
107 }
108 if (strstr(line, "Xfer Trk")) {
109 w->progress_label = w->trk_label;
110 }
111 if (strstr(line, "PRDDAT")) {
112 gchar **tokens = g_strsplit(line, " ", 0);
113 gchar info[128];
114 int ilen = 0;
115 int i;
116
117 for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
118 guint ch;
119 sscanf(tokens[i], "%x", &ch);
120 info[ilen++] = ch;
121 }
122 info[ilen++] = 0;
123 set_gps_info(info);
124 }
125 if (strstr(line, "RECORD")) {
126 int lsb, msb, cnt;
127
128 sscanf(line+17, "%x", &lsb);
129 sscanf(line+20, "%x", &msb);
130 cnt = lsb + msb * 256;
131 set_total_count(cnt);
132 count = 0;
133 }
134 if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
135 count++;
136 set_current_count(count);
137 }
138 break;
139 case BABEL_DONE:
140 break;
141 default:
142 break;
143 }
144}
145
146/* this routine is the worker thread. there is only one simultaneous download allowed */
147static void get_from_gps ( gpointer data )
148{
149 VikTrwLayer *vtl;
150
151 if ( w ) {
152 /* simultaneous downloads are not allowed, so we return. */
153 g_free(data);
154 g_thread_exit ( NULL );
155 return;
156 }
157
158 w = data;
159
160 gdk_threads_enter();
161 vtl = VIK_TRW_LAYER ( vik_layer_create ( VIK_LAYER_TRW, w->vvp, NULL, FALSE ) );
162 vik_layer_rename ( VIK_LAYER ( vtl ), "Acquired from GPS" );
163 gtk_label_set_text ( GTK_LABEL(w->status), "Working..." );
164 gdk_threads_leave();
165
166 if (!a_babel_convert_from (vtl, "-D 9 -t -w -i garmin", progress_func, "/dev/ttyS0")) {
167 gdk_threads_enter();
168 gtk_label_set_text ( GTK_LABEL(w->status), "Error: couldn't find gpsbabel." );
169 gdk_threads_leave();
170 }
171
172 gdk_threads_enter();
173 if (w->ok) {
174 gtk_label_set_text ( GTK_LABEL(w->status), "Done." );
175 vik_aggregate_layer_add_layer( vik_layers_panel_get_top_layer(w->vlp), VIK_LAYER(vtl));
176 gtk_dialog_set_response_sensitive ( GTK_DIALOG(w->dialog), GTK_RESPONSE_ACCEPT, TRUE );
177 gtk_dialog_set_response_sensitive ( GTK_DIALOG(w->dialog), GTK_RESPONSE_REJECT, FALSE );
178 } else {
179 g_object_unref(vtl);
180 }
181 g_free ( w );
182 w = NULL;
183 gdk_threads_leave();
184 g_thread_exit ( NULL );
185}
186
187void a_acquire_from_gps ( VikWindow *vw, VikLayersPanel *vlp, VikViewport *vvp )
188{
189 GtkWidget *status, *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
190 GtkWidget *dialog = NULL;
191 acq_dialog_widgets_t *w = g_malloc(sizeof(*w));
192
193 dialog = gtk_dialog_new_with_buttons ( "", NULL, 0, GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, NULL );
194 gtk_dialog_set_response_sensitive ( GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT, FALSE );
195
196 status = gtk_label_new ("Status: detecting gpsbabel");
197 gpslabel = gtk_label_new ("GPS device: N/A");
198 verlabel = gtk_label_new ("Version: N/A");
199 idlabel = gtk_label_new ("ID: N/A");
200 wplabel = gtk_label_new ("WP");
201 trklabel = gtk_label_new ("TRK");
202
203 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), status, FALSE, FALSE, 5 );
204 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
205 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
206 gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
207
208 gtk_window_set_title ( GTK_WINDOW(dialog), "Acquire data from GPS" );
209
210 gtk_widget_show ( status );
211 gtk_widget_show ( gpslabel );
212 gtk_widget_show ( dialog );
213
214 w->dialog = dialog;
215 w->status = status;
216 w->gps_label = gpslabel;
217 w->id_label = idlabel;
218 w->ver_label = verlabel;
219 w->progress_label = w->wp_label = wplabel;
220 w->trk_label = trklabel;
221 w->vw = vw;
222 w->vlp = vlp;
223 w->vvp = vvp;
224 w->ok = TRUE;
225 g_thread_create((GThreadFunc)get_from_gps, w, FALSE, NULL );
226
227 gtk_dialog_run ( GTK_DIALOG(dialog) );
228 w->ok = FALSE;
229 gtk_widget_destroy ( dialog );
230}