]>
Commit | Line | Data |
---|---|---|
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 */ | |
33 | typedef 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 | ||
48 | acq_dialog_widgets_t *w = NULL; | |
49 | int total_count = -1; | |
50 | int count; | |
51 | ||
52 | static 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 | ||
65 | static 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 | ||
80 | static 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 | */ | |
96 | static 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 */ | |
147 | static 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 | ||
187 | void 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 | } |