]> git.street.me.uk Git - andy/viking.git/blame - src/vikgpsdlayer.c
Add realtime tracking to GPS layer.
[andy/viking.git] / src / vikgpsdlayer.c
CommitLineData
1b236385
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 <math.h>
22#include <gps.h>
23
50a54941
EB
24#include "globals.h"
25#include "dialog.h"
1b236385
EB
26#include "vikgpsdlayer.h"
27#include "viklayer.h"
28#include "vikgpsdlayer_pixmap.h"
29
30static void gpsd_layer_marshall( VikGpsdLayer *vgl, guint8 **data, gint *len );
31static VikGpsdLayer *gpsd_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp );
32static gboolean gpsd_layer_set_param ( VikGpsdLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp );
33static VikLayerParamData gpsd_layer_get_param ( VikGpsdLayer *vgl, guint16 id );
34static VikGpsdLayer *vik_gpsd_layer_new ( VikViewport *vp );
35static void vik_gpsd_layer_free ( VikGpsdLayer *vgl );
36static void vik_gpsd_layer_draw ( VikGpsdLayer *vgl, gpointer data );
37
38
39static VikLayerParam gpsd_layer_params[] = {
40};
41
42
43enum { NUM_PARAMS=0 };
44
45VikLayerInterface vik_gpsd_layer_interface = {
46 "Gpsd",
47 &gpsdlayer_pixbuf,
48
49 NULL,
50 0,
51
52// gpsd_layer_params,
53 NULL,
54 NUM_PARAMS,
55 NULL,
56 0,
57
58 VIK_MENU_ITEM_ALL,
59
60 (VikLayerFuncCreate) vik_gpsd_layer_new,
61 (VikLayerFuncRealize) NULL,
62 NULL,
63 (VikLayerFuncFree) vik_gpsd_layer_free,
64
65 (VikLayerFuncProperties) NULL,
66 (VikLayerFuncDraw) vik_gpsd_layer_draw,
67 (VikLayerFuncChangeCoordMode) NULL,
68
69 (VikLayerFuncSetMenuItemsSelection) NULL,
70 (VikLayerFuncGetMenuItemsSelection) NULL,
71
72 (VikLayerFuncAddMenuItems) NULL,
73 (VikLayerFuncSublayerAddMenuItems) NULL,
74
75 (VikLayerFuncSublayerRenameRequest) NULL,
76 (VikLayerFuncSublayerToggleVisible) NULL,
77
78 (VikLayerFuncMarshall) gpsd_layer_marshall,
79 (VikLayerFuncUnmarshall) gpsd_layer_unmarshall,
80
81 (VikLayerFuncSetParam) gpsd_layer_set_param,
82 (VikLayerFuncGetParam) gpsd_layer_get_param,
83
84 (VikLayerFuncReadFileData) NULL,
85 (VikLayerFuncWriteFileData) NULL,
86
87 (VikLayerFuncDeleteItem) NULL,
88 (VikLayerFuncCopyItem) NULL,
89 (VikLayerFuncPasteItem) NULL,
90 (VikLayerFuncFreeCopiedItem) NULL,
91 (VikLayerFuncDragDropRequest) NULL,
92};
93
94typedef struct {
95 struct gps_data_t data;
96 VikGpsdLayer *vgl;
97} FakeGpsData;
98
99struct _VikGpsdLayer {
100 VikLayer vl;
415302f4 101 GdkGC *gc, *pt_gc;
1b236385
EB
102 struct LatLon ll;
103 gdouble course;
50a54941 104 FakeGpsData *fgd;
1b236385
EB
105 gint timeout;
106};
107
108GType vik_gpsd_layer_get_type ()
109{
110 static GType vgl_type = 0;
111
112 if (!vgl_type)
113 {
114 static const GTypeInfo vgl_info =
115 {
116 sizeof (VikGpsdLayerClass),
117 NULL, /* base_init */
118 NULL, /* base_finalize */
119 NULL, /* class init */
120 NULL, /* class_finalize */
121 NULL, /* class_data */
122 sizeof (VikGpsdLayer),
123 0,
124 NULL /* instance init */
125 };
126 vgl_type = g_type_register_static ( VIK_LAYER_TYPE, "VikGpsdLayer", &vgl_info, 0 );
127 }
128
129 return vgl_type;
130}
131
132static void gpsd_layer_marshall( VikGpsdLayer *vgl, guint8 **data, gint *len )
133{
134 vik_layer_marshall_params ( VIK_LAYER(vgl), data, len );
135}
136
137static VikGpsdLayer *gpsd_layer_unmarshall( guint8 *data, gint len, VikViewport *vvp )
138{
139 VikGpsdLayer *rv = vik_gpsd_layer_new ( vvp );
140 vik_layer_unmarshall_params ( VIK_LAYER(rv), data, len, vvp );
141 return rv;
142}
143
144gboolean gpsd_layer_set_param ( VikGpsdLayer *vgl, guint16 id, VikLayerParamData data, VikViewport *vp )
145{
146 switch ( id )
147 {
148
149 }
150 return TRUE;
151}
152
153static VikLayerParamData gpsd_layer_get_param ( VikGpsdLayer *vgl, guint16 id )
154{
155 VikLayerParamData rv;
156 switch ( id )
157 {
158// case PARAM_COLOR: rv.s = vgl->color ? vgl->color : ""; break;
159 }
160 return rv;
161}
162
163static void vik_gpsd_layer_draw ( VikGpsdLayer *vgl, gpointer data )
164{
165 VikViewport *vp = (VikViewport *) data;
166 VikCoord nw, se;
167 struct LatLon lnw, lse;
168 vik_viewport_screen_to_coord ( vp, -20, -20, &nw );
169 vik_viewport_screen_to_coord ( vp, vik_viewport_get_width(vp)+20, vik_viewport_get_width(vp)+20, &se );
170 vik_coord_to_latlon ( &nw, &lnw );
171 vik_coord_to_latlon ( &se, &lse );
172 if ( vgl->ll.lat > lse.lat &&
173 vgl->ll.lat < lnw.lat &&
174 vgl->ll.lon > lnw.lon &&
175 vgl->ll.lon < lse.lon ) {
176 VikCoord gps;
177 gint x, y;
415302f4 178 gint half_back_x, half_back_y;
1b236385 179 gint pt_x, pt_y;
415302f4 180 gint side1_x, side1_y, side2_x, side2_y;
1b236385
EB
181
182 vik_coord_load_from_latlon ( &gps, vik_viewport_get_coord_mode(vp), &(vgl->ll) );
183 vik_viewport_coord_to_screen ( vp, &gps, &x, &y );
1b236385 184
415302f4
EB
185 half_back_y = y+8*cos(M_PI/180*vgl->course);
186 half_back_x = x-8*sin(M_PI/180*vgl->course);
187
188 pt_y = half_back_y-24*cos(M_PI/180*vgl->course);
189 pt_x = half_back_x+24*sin(M_PI/180*vgl->course);
190
191 side1_y = half_back_y+9*sin(M_PI/180*vgl->course);
192 side1_x = half_back_x+9*cos(M_PI/180*vgl->course);
193
194 side2_y = half_back_y-9*sin(M_PI/180*vgl->course);
195 side2_x = half_back_x-9*cos(M_PI/180*vgl->course);
196
197 GdkPoint trian[3] = { { pt_x, pt_y }, {side1_x, side1_y}, {side2_x, side2_y} };
1b236385
EB
198
199 g_print("%d %d %d %d\n", x, y, pt_x, pt_y);
415302f4
EB
200 vik_viewport_draw_polygon ( vp, vgl->gc, TRUE, trian, 3 );
201 vik_viewport_draw_rectangle ( vp, vgl->pt_gc, TRUE, x-2, y-2, 4, 4 );
1b236385
EB
202 }
203}
204
205static void vik_gpsd_layer_free ( VikGpsdLayer *vgl )
206{
50a54941
EB
207 /* we already free'd the original gps_data,
208 * and the current one lives in the VikGpsdLayer and would be freed twice.
209 * so we malloc one, copy the data, and close/free it.
210 */
211 if ( vgl->fgd ) {
212 gps_close ( (struct gps_data_t *) vgl->fgd );
213 gtk_timeout_remove ( vgl->timeout );
214 }
215
1b236385
EB
216 if ( vgl->gc != NULL )
217 g_object_unref ( G_OBJECT(vgl->gc) );
415302f4
EB
218 if ( vgl->pt_gc != NULL )
219 g_object_unref ( G_OBJECT(vgl->pt_gc) );
1b236385
EB
220}
221
415302f4 222void gpsd_hook(struct gps_data_t *gps_data, char *data)
1b236385 223{
415302f4 224 FakeGpsData *fgd = (FakeGpsData *) gps_data;
1b236385
EB
225 gdouble lat, lon, alt, herror, verror, course, speed;
226 /* skip thru three spaces */
227 while (*data && *data != ' ') data++; if (*data) data++;
228 while (*data && *data != ' ') data++; if (*data) data++;
229 while (*data && *data != ' ') data++; if (*data) data++;
230 if ( sscanf(data, "%lf %lf %lf %lf %lf %lf %lf", &lat, &lon,
231 &alt, &herror, &verror, &course, &speed) ) {
232 VikGpsdLayer *vgl = fgd->vgl;
233 vgl->ll.lat = lat;
234 vgl->ll.lon = lon;
235 vgl->course = course;
236 /* could/should emit update here. */
237 }
238}
239
240static gboolean gpsd_timeout(VikGpsdLayer *vgl)
241{
50a54941
EB
242 if ( vgl->fgd ) {
243 gps_query( (struct gps_data_t *) vgl->fgd, "o");
244 vik_layer_emit_update ( VIK_LAYER(vgl) );
245 }
1b236385
EB
246 return TRUE;
247}
248
249static VikGpsdLayer *vik_gpsd_layer_new ( VikViewport *vp )
250{
251 VikGpsdLayer *vgl = VIK_GPSD_LAYER ( g_object_new ( VIK_GPSD_LAYER_TYPE, NULL ) );
252
253 vik_layer_init ( VIK_LAYER(vgl), VIK_LAYER_GPSD );
254
255 struct gps_data_t *orig_data = gps_open ("localhost", DEFAULT_GPSD_PORT);
50a54941
EB
256 if ( orig_data ) {
257 vgl->fgd = g_realloc ( orig_data, sizeof(FakeGpsData) );
258 vgl->fgd->vgl = vgl;
259
260 gps_set_raw_hook( (struct gps_data_t *) vgl->fgd, gpsd_hook ); /* pass along vgl in fgd */
261
262 vgl->timeout = gtk_timeout_add ( 1000, (GtkFunction)gpsd_timeout, vgl);
263 } else {
264 a_dialog_warning_msg(VIK_GTK_WINDOW_FROM_WIDGET(vp), "No Gpsd found! Right-click layer and click 'Enable GPSD' (not yet implemented) once daemon is started.");
265 }
1b236385 266
415302f4
EB
267 vgl->gc = vik_viewport_new_gc ( vp, "#203070", 2 );
268 vgl->pt_gc = vik_viewport_new_gc ( vp, "red", 2 );
1b236385
EB
269 vgl->ll.lat = vgl->ll.lon = vgl->course = 0;
270
1b236385
EB
271 return vgl;
272}
273