]> git.street.me.uk Git - andy/viking.git/blob - src/datasource_gps.c
Update from Launchpad
[andy/viking.git] / src / datasource_gps.c
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 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24 #include <string.h>
25
26 #include <glib/gprintf.h>
27 #include <glib/gi18n.h>
28
29 #include "viking.h"
30 #include "babel.h"
31 #include "gpx.h"
32 #include "acquire.h"
33
34 #if GTK_CHECK_VERSION(2,6,0)
35 #define USE_NEW_COMBO_BOX
36 #endif
37
38 static gboolean gps_acquire_in_progress = FALSE;
39
40 static gpointer datasource_gps_init_func ( );
41 static void datasource_gps_get_cmd_string ( gpointer add_widgets_data_not_used, gchar **babelargs, gchar **input_file );
42 static void datasource_gps_cleanup ( gpointer user_data );
43 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w );
44 static void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data );
45 static void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data );
46
47 VikDataSourceInterface vik_datasource_gps_interface = {
48   N_("Acquire from GPS"),
49   N_("Acquired from GPS"),
50   VIK_DATASOURCE_GPSBABEL_DIRECT,
51   VIK_DATASOURCE_CREATENEWLAYER,
52   VIK_DATASOURCE_INPUTTYPE_NONE,
53   TRUE,
54   (VikDataSourceInitFunc)               datasource_gps_init_func,
55   (VikDataSourceCheckExistenceFunc)     NULL,
56   (VikDataSourceAddSetupWidgetsFunc)    datasource_gps_add_setup_widgets,
57   (VikDataSourceGetCmdStringFunc)       datasource_gps_get_cmd_string,
58   (VikDataSourceProgressFunc)           datasource_gps_progress,
59   (VikDataSourceAddProgressWidgetsFunc) datasource_gps_add_progress_widgets,
60   (VikDataSourceCleanupFunc)            datasource_gps_cleanup
61 };
62
63 /*********************************************************
64  * Definitions and routines for acquiring data from GPS
65  *********************************************************/
66
67 /* widgets in setup dialog specific to GPS */
68 /* widgets in progress dialog specific to GPS */
69 /* also counts needed for progress */
70 typedef struct {
71   /* setup dialog */
72   GtkWidget *proto_l;
73   GtkComboBox *proto_b;
74   GtkWidget *ser_l;
75   GtkComboBox *ser_b;
76
77   /* progress dialog */
78   GtkWidget *gps_label;
79   GtkWidget *ver_label;
80   GtkWidget *id_label;
81   GtkWidget *wp_label;
82   GtkWidget *trk_label;
83   GtkWidget *progress_label;
84
85   /* state */
86   int total_count;
87   int count;
88 } gps_user_data_t;
89
90 static gpointer datasource_gps_init_func ()
91 {
92   return g_malloc (sizeof(gps_user_data_t));
93 }
94
95 static void datasource_gps_get_cmd_string ( gpointer user_data, gchar **babelargs, gchar **input_file )
96 {
97   char *proto = NULL;
98   char *ser = NULL;
99   char *device = NULL;
100 #ifndef USE_NEW_COMBO_BOX
101   GtkTreeIter iter;
102 #endif
103   gps_user_data_t *w = (gps_user_data_t *)user_data;
104
105   if (gps_acquire_in_progress) {
106     *babelargs = *input_file = NULL;
107   }
108   
109   gps_acquire_in_progress = TRUE;
110
111 #ifdef USE_NEW_COMBO_BOX
112   proto = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->proto_b));
113 #else
114   proto = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->proto_b),&iter);
115 #endif
116   if (!strcmp(proto, "Garmin")) {
117     device = "garmin";
118   } else {
119     device = "magellan";
120   }
121   *babelargs = g_strdup_printf("-D 9 -t -w -i %s", device);
122   /* device points to static content => no free */
123   device = NULL;
124   
125   /* Old stuff */
126 #ifdef USE_NEW_COMBO_BOX
127   ser = gtk_combo_box_get_active_text(GTK_COMBO_BOX(w->ser_b));
128 #else
129   ser = gtk_combo_box_get_active_iter(GTK_COMBO_BOX(w->ser_b),&iter);
130 #endif
131   *input_file = g_strdup(ser);
132
133   g_debug(_("using cmdline '%s' and file '%s'\n"), *babelargs, *input_file);
134 }
135
136 static void datasource_gps_cleanup ( gpointer user_data )
137 {
138   g_free ( user_data );
139   gps_acquire_in_progress = FALSE;
140 }
141
142 static void set_total_count(gint cnt, acq_dialog_widgets_t *w)
143 {
144   gchar *s = NULL;
145   gdk_threads_enter();
146   if (w->ok) {
147     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
148     const gchar *tmp_str;
149     if (gps_data->progress_label == gps_data->wp_label)
150       tmp_str = ngettext("Downloading %d waypoint...", "Downloading %d waypoints...", cnt);
151     else
152       tmp_str = ngettext("Downloading %d trackpoint...", "Downloading %d trackpoints...", cnt);
153     s = g_strdup_printf(tmp_str, cnt);
154     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
155     gtk_widget_show ( gps_data->progress_label );
156     gps_data->total_count = cnt;
157   }
158   g_free(s); s = NULL;
159   gdk_threads_leave();
160 }
161
162 static void set_current_count(gint cnt, acq_dialog_widgets_t *w)
163 {
164   gchar *s = NULL;
165   gdk_threads_enter();
166   if (w->ok) {
167     gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
168
169     if (cnt < gps_data->total_count) {
170       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");
171     } else {
172       s = g_strdup_printf(_("Downloaded %d %s."), cnt, (gps_data->progress_label == gps_data->wp_label) ? "waypoints" : "trackpoints");
173     }     
174     gtk_label_set_text ( GTK_LABEL(gps_data->progress_label), s );
175   }
176   g_free(s); s = NULL;
177   gdk_threads_leave();
178 }
179
180 static void set_gps_info(const gchar *info, acq_dialog_widgets_t *w)
181 {
182   gchar *s = NULL;
183   gdk_threads_enter();
184   if (w->ok) {
185     s = g_strdup_printf(_("GPS Device: %s"), info);
186     gtk_label_set_text ( GTK_LABEL(((gps_user_data_t *)w->user_data)->gps_label), s );
187   }
188   g_free(s); s = NULL;
189   gdk_threads_leave();
190 }
191
192 /* 
193  * This routine relies on gpsbabel's diagnostic output to display the progress information. 
194  * These outputs differ when different GPS devices are used, so we will need to test
195  * them on several and add the corresponding support.
196  */
197 static void datasource_gps_progress ( BabelProgressCode c, gpointer data, acq_dialog_widgets_t *w )
198 {
199   gchar *line;
200   gps_user_data_t *gps_data = (gps_user_data_t *)w->user_data;
201
202   switch(c) {
203   case BABEL_DIAG_OUTPUT:
204     line = (gchar *)data;
205
206     /* tells us how many items there will be */
207     if (strstr(line, "Xfer Wpt")) { 
208       gps_data->progress_label = gps_data->wp_label;
209     }
210     if (strstr(line, "Xfer Trk")) { 
211       gps_data->progress_label = gps_data->trk_label;
212     }
213     if (strstr(line, "PRDDAT")) {
214       gchar **tokens = g_strsplit(line, " ", 0);
215       gchar info[128];
216       int ilen = 0;
217       int i;
218       int n_tokens = 0;
219
220       while (tokens[n_tokens])
221         n_tokens++;
222
223       if (n_tokens > 8) {
224         for (i=8; tokens[i] && ilen < sizeof(info)-2 && strcmp(tokens[i], "00"); i++) {
225           guint ch;
226           sscanf(tokens[i], "%x", &ch);
227           info[ilen++] = ch;
228         }
229         info[ilen++] = 0;
230         set_gps_info(info, w);
231       }
232       g_strfreev(tokens);
233     }
234     if (strstr(line, "RECORD")) { 
235       int lsb, msb, cnt;
236
237       if (strlen(line) > 20) {
238        sscanf(line+17, "%x", &lsb); 
239        sscanf(line+20, "%x", &msb);
240        cnt = lsb + msb * 256;
241        set_total_count(cnt, w);
242        gps_data->count = 0;
243       }
244     }
245     if ( strstr(line, "WPTDAT") || strstr(line, "TRKHDR") || strstr(line, "TRKDAT") ) {
246       gps_data->count++;
247       set_current_count(gps_data->count, w);
248     }
249     break;
250   case BABEL_DONE:
251     break;
252   default:
253     break;
254   }
255 }
256
257 void datasource_gps_add_setup_widgets ( GtkWidget *dialog, VikViewport *vvp, gpointer user_data )
258 {
259   gps_user_data_t *w = (gps_user_data_t *)user_data;
260   GtkTable*  box;
261
262   w->proto_l = gtk_label_new (_("GPS Protocol:"));
263   w->proto_b = GTK_COMBO_BOX(gtk_combo_box_new_text ());
264   gtk_combo_box_append_text (w->proto_b, "Garmin");
265   gtk_combo_box_append_text (w->proto_b, "Magellan");
266   gtk_combo_box_set_active (w->proto_b, 0);
267   g_object_ref(w->proto_b);
268
269   w->ser_l = gtk_label_new (_("Serial Port:"));
270   w->ser_b = GTK_COMBO_BOX(gtk_combo_box_entry_new_text ());
271 #ifdef WINDOWS
272   gtk_combo_box_append_text (w->ser_b, "com1");
273 #else
274   gtk_combo_box_append_text (w->ser_b, "/dev/ttyS0");
275   gtk_combo_box_append_text (w->ser_b, "/dev/ttyS1");
276   gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB0");
277   gtk_combo_box_append_text (w->ser_b, "/dev/ttyUSB1");
278 #endif
279   gtk_combo_box_append_text (w->ser_b, "usb:");
280   gtk_combo_box_set_active (w->ser_b, 0);
281   g_object_ref(w->ser_b);
282
283   box = GTK_TABLE(gtk_table_new(2, 2, FALSE));
284   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_l), 0, 1, 0, 1);
285   gtk_table_attach_defaults(box, GTK_WIDGET(w->proto_b), 1, 2, 0, 1);
286   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_l), 0, 1, 1, 2);
287   gtk_table_attach_defaults(box, GTK_WIDGET(w->ser_b), 1, 2, 1, 2);
288   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), GTK_WIDGET(box), FALSE, FALSE, 5 );
289
290   gtk_widget_show_all ( dialog );
291 }
292
293 void datasource_gps_add_progress_widgets ( GtkWidget *dialog, gpointer user_data )
294 {
295   GtkWidget *gpslabel, *verlabel, *idlabel, *wplabel, *trklabel;
296
297   gps_user_data_t *w_gps = (gps_user_data_t *)user_data;
298
299   gpslabel = gtk_label_new (_("GPS device: N/A"));
300   verlabel = gtk_label_new ("");
301   idlabel = gtk_label_new ("");
302   wplabel = gtk_label_new ("");
303   trklabel = gtk_label_new ("");
304
305   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), gpslabel, FALSE, FALSE, 5 );
306   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), wplabel, FALSE, FALSE, 5 );
307   gtk_box_pack_start ( GTK_BOX(GTK_DIALOG(dialog)->vbox), trklabel, FALSE, FALSE, 5 );
308
309   gtk_widget_show_all ( dialog );
310
311   w_gps->gps_label = gpslabel;
312   w_gps->id_label = idlabel;
313   w_gps->ver_label = verlabel;
314   w_gps->progress_label = w_gps->wp_label = wplabel;
315   w_gps->trk_label = trklabel;
316   w_gps->total_count = -1;
317 }