]> git.street.me.uk Git - andy/viking.git/blame - src/vikroutingwebengine.c
Make simple GPSBabel filter options use the updated acquire framework options.
[andy/viking.git] / src / vikroutingwebengine.c
CommitLineData
b44a5ac5
GB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (c) 2013, Guilhem Bonnefille <guilhem.bonnefille@gmail.com>
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
22/**
23 * SECTION:vikroutingwebengine
24 * @short_description: A generic class for WEB based routing engine
25 *
26 * The #VikRoutingWebEngine class handles WEB based
27 * routing engine.
28 */
29
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include <string.h>
35
36#include <glib.h>
37#include <glib/gstdio.h>
38
bc048a9c
GB
39#include "babel.h"
40
b44a5ac5
GB
41#include "vikroutingwebengine.h"
42
43static void vik_routing_web_engine_finalize ( GObject *gob );
44
41e48655 45static gboolean vik_routing_web_engine_find ( VikRoutingEngine *self, VikTrwLayer *vtl, struct LatLon start, struct LatLon end );
09f04587 46static gchar *vik_routing_web_engine_get_url_from_directions(VikRoutingEngine *self, const gchar *start, const gchar *end);
7f95fd54 47static gboolean vik_routing_web_engine_supports_direction(VikRoutingEngine *self);
41e48655 48static gboolean vik_routing_web_engine_refine ( VikRoutingEngine *self, VikTrwLayer *vtl, VikTrack *vt );
1a3be6a8 49static gboolean vik_routing_web_engine_supports_refine ( VikRoutingEngine *self );
b44a5ac5
GB
50
51typedef struct _VikRoutingWebEnginePrivate VikRoutingWebEnginePrivate;
52struct _VikRoutingWebEnginePrivate
53{
54 gchar *url_base;
7f95fd54
GB
55
56 /* LatLon */
b44a5ac5
GB
57 gchar *url_start_ll_fmt;
58 gchar *url_stop_ll_fmt;
59 gchar *url_via_ll_fmt;
60
7f95fd54
GB
61 /* Directions */
62 gchar *url_start_dir_fmt;
63 gchar *url_stop_dir_fmt;
64
b44a5ac5
GB
65 DownloadMapOptions options;
66};
67
68#define VIK_ROUTING_WEB_ENGINE_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), VIK_ROUTING_WEB_ENGINE_TYPE, VikRoutingWebEnginePrivate))
69
70/* properties */
71enum
72{
73 PROP_0,
74
75 PROP_URL_BASE,
7f95fd54
GB
76
77 /* LatLon */
b44a5ac5
GB
78 PROP_URL_START_LL,
79 PROP_URL_STOP_LL,
80 PROP_URL_VIA_LL,
81
7f95fd54
GB
82 /* Direction */
83 PROP_URL_START_DIR,
84 PROP_URL_STOP_DIR,
85
b44a5ac5
GB
86 PROP_REFERER,
87 PROP_FOLLOW_LOCATION,
88};
89
90G_DEFINE_TYPE (VikRoutingWebEngine, vik_routing_web_engine, VIK_ROUTING_ENGINE_TYPE)
91
92static void
93vik_routing_web_engine_set_property (GObject *object,
94 guint property_id,
95 const GValue *value,
96 GParamSpec *pspec)
97{
98 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( object );
99
100 switch (property_id)
101 {
102 case PROP_URL_BASE:
103 g_free (priv->url_base);
104 priv->url_base = g_strdup(g_value_get_string (value));
105 break;
106
107 case PROP_URL_START_LL:
108 g_free (priv->url_start_ll_fmt);
109 priv->url_start_ll_fmt = g_strdup(g_value_get_string (value));
110 break;
111
112 case PROP_URL_STOP_LL:
113 g_free (priv->url_stop_ll_fmt);
114 priv->url_stop_ll_fmt = g_strdup(g_value_get_string (value));
115 break;
116
117 case PROP_URL_VIA_LL:
118 g_free (priv->url_via_ll_fmt);
119 priv->url_via_ll_fmt = g_strdup(g_value_get_string (value));
120 break;
121
7f95fd54
GB
122 case PROP_URL_START_DIR:
123 g_free (priv->url_start_dir_fmt);
124 priv->url_start_dir_fmt = g_strdup(g_value_get_string (value));
125 break;
126
127 case PROP_URL_STOP_DIR:
128 g_free (priv->url_stop_dir_fmt);
129 priv->url_stop_dir_fmt = g_strdup(g_value_get_string (value));
130 break;
131
b44a5ac5
GB
132 case PROP_REFERER:
133 g_free (priv->options.referer);
134 priv->options.referer = g_value_dup_string (value);
135 break;
136
137 case PROP_FOLLOW_LOCATION:
138 priv->options.follow_location = g_value_get_long (value);
139 break;
140
141 default:
142 /* We don't have any other property... */
143 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
144 break;
145 }
146}
147
148static void
149vik_routing_web_engine_get_property (GObject *object,
150 guint property_id,
151 GValue *value,
152 GParamSpec *pspec)
153{
154 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( object );
155
156 switch (property_id)
157 {
158 case PROP_URL_BASE:
159 g_value_set_string (value, priv->url_base);
160 break;
161
162 case PROP_URL_START_LL:
163 g_value_set_string (value, priv->url_start_ll_fmt);
164 break;
165
166 case PROP_URL_STOP_LL:
167 g_value_set_string (value, priv->url_stop_ll_fmt);
168 break;
169
170 case PROP_URL_VIA_LL:
171 g_value_set_string (value, priv->url_via_ll_fmt);
172 break;
173
7f95fd54
GB
174 case PROP_URL_START_DIR:
175 g_value_set_string (value, priv->url_start_dir_fmt);
176 break;
177
178 case PROP_URL_STOP_DIR:
179 g_value_set_string (value, priv->url_stop_dir_fmt);
180 break;
181
b44a5ac5
GB
182 case PROP_REFERER:
183 g_value_set_string (value, priv->options.referer);
184 break;
185
186 case PROP_FOLLOW_LOCATION:
187 g_value_set_long (value, priv->options.follow_location);
188 break;
189
190 default:
191 /* We don't have any other property... */
192 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
193 break;
194 }
195}
196
197static void vik_routing_web_engine_class_init ( VikRoutingWebEngineClass *klass )
198{
199 GObjectClass *object_class;
200 VikRoutingEngineClass *parent_class;
201 GParamSpec *pspec = NULL;
202
203 object_class = G_OBJECT_CLASS (klass);
204
205 object_class->set_property = vik_routing_web_engine_set_property;
206 object_class->get_property = vik_routing_web_engine_get_property;
207 object_class->finalize = vik_routing_web_engine_finalize;
208
209 parent_class = VIK_ROUTING_ENGINE_CLASS (klass);
210
bc048a9c 211 parent_class->find = vik_routing_web_engine_find;
7f95fd54 212 parent_class->supports_direction = vik_routing_web_engine_supports_direction;
09f04587 213 parent_class->get_url_from_directions = vik_routing_web_engine_get_url_from_directions;
1a3be6a8
GB
214 parent_class->refine = vik_routing_web_engine_refine;
215 parent_class->supports_refine = vik_routing_web_engine_supports_refine;
b44a5ac5
GB
216
217 /**
218 * VikRoutingWebEngine:url-base:
219 *
220 * The base URL of the routing engine.
221 */
222 pspec = g_param_spec_string ("url-base",
223 "URL's base",
224 "The base URL of the routing engine",
225 "<no-set>" /* default value */,
226 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
227 g_object_class_install_property (object_class, PROP_URL_BASE, pspec);
228
229
230 /**
231 * VikRoutingWebEngine:url-start-ll:
232 *
233 * The part of the request hosting the end point.
234 */
235 pspec = g_param_spec_string ("url-start-ll",
236 "Start part of the URL",
237 "The part of the request hosting the start point",
238 "<no-set>" /* default value */,
239 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
240 g_object_class_install_property (object_class, PROP_URL_START_LL, pspec);
241
242
243 /**
244 * VikRoutingWebEngine:url-stop-ll:
245 *
246 * The part of the request hosting the end point.
247 */
248 pspec = g_param_spec_string ("url-stop-ll",
249 "Stop part of the URL",
250 "The part of the request hosting the end point",
251 "<no-set>" /* default value */,
252 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
253 g_object_class_install_property (object_class, PROP_URL_STOP_LL, pspec);
254
255
256 /**
257 * VikRoutingWebEngine:url-via-ll:
258 *
259 * The param of the request for setting a via point.
260 */
261 pspec = g_param_spec_string ("url-via-ll",
262 "Via part of the URL",
263 "The param of the request for setting a via point",
264 NULL /* default value */,
265 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
266 g_object_class_install_property (object_class, PROP_URL_VIA_LL, pspec);
267
268
7f95fd54
GB
269 /**
270 * VikRoutingWebEngine:url-start-dir:
271 *
272 * The part of the request hosting the end point.
273 */
274 pspec = g_param_spec_string ("url-start-dir",
275 "Start part of the URL",
276 "The part of the request hosting the start point",
277 NULL /* default value */,
278 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
279 g_object_class_install_property (object_class, PROP_URL_START_DIR, pspec);
280
281
282 /**
283 * VikRoutingWebEngine:url-stop-dir:
284 *
285 * The part of the request hosting the end point.
286 */
287 pspec = g_param_spec_string ("url-stop-dir",
288 "Stop part of the URL",
289 "The part of the request hosting the end point",
290 NULL /* default value */,
291 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
292 g_object_class_install_property (object_class, PROP_URL_STOP_DIR, pspec);
293
294
b44a5ac5
GB
295 /**
296 * VikRoutingWebEngine:referer:
297 *
298 * The REFERER string to use in HTTP request.
299 */
300 pspec = g_param_spec_string ("referer",
301 "Referer",
302 "The REFERER string to use in HTTP request",
303 NULL /* default value */,
304 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
305 g_object_class_install_property (object_class, PROP_REFERER, pspec);
306
307
308 /**
309 * VikRoutingWebEngine:follow-location:
310 *
311 * Specifies the number of retries to follow a redirect while downloading a page.
312 */
313 pspec = g_param_spec_long ("follow-location",
314 "Follow location",
315 "Specifies the number of retries to follow a redirect while downloading a page",
316 0 /* minimum value */,
317 G_MAXLONG /* maximum value */,
ceb44359 318 2 /* default value */,
b44a5ac5
GB
319 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE);
320 g_object_class_install_property (object_class, PROP_FOLLOW_LOCATION, pspec);
321
322 g_type_class_add_private (klass, sizeof (VikRoutingWebEnginePrivate));
323}
324
325static void vik_routing_web_engine_init ( VikRoutingWebEngine *self )
326{
327 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
328
329 priv->url_base = NULL;
7f95fd54
GB
330
331 /* LatLon */
b44a5ac5
GB
332 priv->url_start_ll_fmt = NULL;
333 priv->url_stop_ll_fmt = NULL;
334 priv->url_via_ll_fmt = NULL;
335
7f95fd54
GB
336 /* Directions */
337 priv->url_start_dir_fmt = NULL;
338 priv->url_stop_dir_fmt = NULL;
339
b44a5ac5
GB
340 priv->options.referer = NULL;
341 priv->options.follow_location = 0;
342 priv->options.check_file = NULL;
343 priv->options.check_file_server_time = FALSE;
344 priv->options.use_etag = FALSE;
345}
346
347static void vik_routing_web_engine_finalize ( GObject *gob )
348{
349 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( gob );
350
351 g_free (priv->url_base);
352 priv->url_base = NULL;
7f95fd54
GB
353
354 /* LatLon */
b44a5ac5
GB
355 g_free (priv->url_start_ll_fmt);
356 priv->url_start_ll_fmt = NULL;
357 g_free (priv->url_stop_ll_fmt);
358 priv->url_stop_ll_fmt = NULL;
359 g_free (priv->url_via_ll_fmt);
360 priv->url_via_ll_fmt = NULL;
361
7f95fd54
GB
362 /* Directions */
363 g_free (priv->url_start_dir_fmt);
364 priv->url_start_dir_fmt = NULL;
365 g_free (priv->url_stop_dir_fmt);
366 priv->url_stop_dir_fmt = NULL;
367
b44a5ac5
GB
368 g_free (priv->options.referer);
369 priv->options.referer = NULL;
370
371 G_OBJECT_CLASS (vik_routing_web_engine_parent_class)->finalize(gob);
372}
373
374static DownloadMapOptions *
375vik_routing_web_engine_get_download_options ( VikRoutingEngine *self )
376{
377 g_return_val_if_fail (VIK_IS_ROUTING_WEB_ENGINE(self), NULL);
378
379 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE(self);
380
381 return &(priv->options);
382}
383
384static gchar *
385substitute_latlon ( const gchar *fmt, struct LatLon ll )
386{
387 gchar lat[G_ASCII_DTOSTR_BUF_SIZE], lon[G_ASCII_DTOSTR_BUF_SIZE];
388 gchar *substituted = g_strdup_printf(fmt,
389 g_ascii_dtostr (lat, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) ll.lat),
390 g_ascii_dtostr (lon, G_ASCII_DTOSTR_BUF_SIZE, (gdouble) ll.lon));
391 return substituted;
392}
393
394static gchar *
395vik_routing_web_engine_get_url_for_coords ( VikRoutingEngine *self, struct LatLon start, struct LatLon end )
396{
397 gchar *startURL;
398 gchar *endURL;
399 gchar *url;
7f95fd54 400
cfd559a5
GB
401 g_return_val_if_fail ( VIK_IS_ROUTING_WEB_ENGINE (self), NULL);
402
b44a5ac5
GB
403 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
404
405 g_return_val_if_fail ( priv->url_base != NULL, NULL);
406 g_return_val_if_fail ( priv->url_start_ll_fmt != NULL, NULL);
407 g_return_val_if_fail ( priv->url_stop_ll_fmt != NULL, NULL);
408
409 startURL = substitute_latlon ( priv->url_start_ll_fmt, start );
410 endURL = substitute_latlon ( priv->url_stop_ll_fmt, end );
411 url = g_strconcat ( priv->url_base, startURL, endURL, NULL );
a2f71570
GB
412
413 /* Free memory */
b44a5ac5
GB
414 g_free ( startURL );
415 g_free ( endURL );
a2f71570
GB
416
417 return url;
b44a5ac5 418}
bc048a9c 419
41e48655 420static gboolean
bc048a9c
GB
421vik_routing_web_engine_find ( VikRoutingEngine *self, VikTrwLayer *vtl, struct LatLon start, struct LatLon end )
422{
8b02f264 423 gchar *uri = vik_routing_web_engine_get_url_for_coords(self, start, end);
bc048a9c
GB
424
425 DownloadMapOptions *options = vik_routing_web_engine_get_download_options(self);
426
427 gchar *format = vik_routing_engine_get_format ( self );
17acdaec
RN
428 ProcessOptions po = { NULL, NULL, format, uri, NULL, NULL };
429 gboolean ret = a_babel_convert_from ( vtl, &po, NULL, NULL, options );
bc048a9c
GB
430
431 g_free(uri);
a2f71570 432
bc048a9c
GB
433 return ret;
434}
7f95fd54
GB
435
436static gchar *
09f04587 437vik_routing_web_engine_get_url_from_directions ( VikRoutingEngine *self, const gchar *start, const gchar *end )
7f95fd54
GB
438{
439 g_return_val_if_fail ( VIK_IS_ROUTING_WEB_ENGINE (self), NULL);
440
441 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
442
443 g_return_val_if_fail ( priv->url_base != NULL, NULL);
444 g_return_val_if_fail ( priv->url_start_dir_fmt != NULL, NULL);
445 g_return_val_if_fail ( priv->url_stop_dir_fmt != NULL, NULL);
446
447 gchar *from_quoted, *to_quoted;
448 gchar **from_split, **to_split;
449 from_quoted = g_shell_quote ( start );
450 to_quoted = g_shell_quote ( end );
451
452 from_split = g_strsplit( from_quoted, " ", 0);
453 to_split = g_strsplit( to_quoted, " ", 0);
454
455 from_quoted = g_strjoinv( "%20", from_split);
456 to_quoted = g_strjoinv( "%20", to_split);
457
458 gchar *url_fmt = g_strconcat ( priv->url_base, priv->url_start_dir_fmt, priv->url_stop_dir_fmt, NULL );
459 gchar *url = g_strdup_printf ( url_fmt, from_quoted, to_quoted );
460
461 g_free ( url_fmt );
462
463 g_free(from_quoted);
464 g_free(to_quoted);
465 g_strfreev(from_split);
466 g_strfreev(to_split);
467
468 return url;
469}
470
471static gboolean
472vik_routing_web_engine_supports_direction ( VikRoutingEngine *self )
473{
474 g_return_val_if_fail ( VIK_IS_ROUTING_WEB_ENGINE (self), FALSE);
475
476 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
477
478 return (priv->url_start_dir_fmt) != NULL;
479}
1a3be6a8
GB
480
481struct _append_ctx {
482 VikRoutingWebEnginePrivate *priv;
483 gchar **urlParts;
484 int nb;
485};
486
487static void
488_append_stringified_coords ( gpointer data, gpointer user_data )
489{
490 VikTrackpoint *vtp = (VikTrackpoint*)data;
491 struct _append_ctx *ctx = (struct _append_ctx*)user_data;
492
493 /* Stringify coordinate */
494 struct LatLon position;
495 vik_coord_to_latlon ( &(vtp->coord), &position );
496 gchar *string = substitute_latlon ( ctx->priv->url_via_ll_fmt, position );
497
498 /* Append */
499 ctx->urlParts[ctx->nb] = string;
500 ctx->nb++;
501}
502
503static gchar *
504vik_routing_web_engine_get_url_for_track ( VikRoutingEngine *self, VikTrack *vt )
505{
506 gchar **urlParts;
507 gchar *url;
508
509 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
510
511 g_return_val_if_fail ( priv->url_base != NULL, NULL );
512 g_return_val_if_fail ( priv->url_start_ll_fmt != NULL, NULL );
513 g_return_val_if_fail ( priv->url_stop_ll_fmt != NULL, NULL );
514 g_return_val_if_fail ( priv->url_via_ll_fmt != NULL, NULL );
515
516 /* Init temporary storage */
517 gsize len = 1 + g_list_length ( vt->trackpoints ) + 1; /* base + trackpoints + NULL */
518 urlParts = g_malloc ( sizeof(gchar*)*len );
519 urlParts[0] = g_strdup ( priv->url_base );
520 urlParts[len-1] = NULL;
521
522 struct _append_ctx ctx;
523 ctx.priv = priv;
524 ctx.urlParts = urlParts;
525 ctx.nb = 1; /* First cell available, previous used for base URL */
526
527 /* Append all trackpoints to URL */
528 g_list_foreach ( vt->trackpoints, _append_stringified_coords, &ctx );
529
530 /* Override first and last positions with associated formats */
531 struct LatLon position;
532 VikTrackpoint *vtp;
533 g_free ( urlParts[1] );
534 vtp = g_list_first ( vt->trackpoints )->data;
535 vik_coord_to_latlon ( &(vtp->coord ), &position );
536 urlParts[1] = substitute_latlon ( priv->url_start_ll_fmt, position );
537 g_free ( urlParts[len-2] );
538 vtp = g_list_last ( vt->trackpoints )->data;
539 vik_coord_to_latlon ( &(vtp->coord), &position );
540 urlParts[len-2] = substitute_latlon ( priv->url_stop_ll_fmt, position );
541
542 /* Concat */
543 url = g_strjoinv ( NULL, urlParts );
544 g_debug ( "%s: %s", __FUNCTION__, url );
545
546 /* Free */
547 g_strfreev ( urlParts );
548
549 return url;
550}
551
41e48655 552static gboolean
1a3be6a8
GB
553vik_routing_web_engine_refine ( VikRoutingEngine *self, VikTrwLayer *vtl, VikTrack *vt )
554{
1a3be6a8 555 /* Compute URL */
8b02f264 556 gchar *uri = vik_routing_web_engine_get_url_for_track ( self, vt );
1a3be6a8
GB
557
558 /* Download data */
559 DownloadMapOptions *options = vik_routing_web_engine_get_download_options ( self );
560
561 /* Convert and insert data in model */
562 gchar *format = vik_routing_engine_get_format ( self );
17acdaec
RN
563 ProcessOptions po = { NULL, NULL, format, uri, NULL, NULL };
564 gboolean ret = a_babel_convert_from ( vtl, &po, NULL, NULL, options );
1a3be6a8
GB
565
566 g_free(uri);
567
568 return ret;
569}
570
571static gboolean
572vik_routing_web_engine_supports_refine ( VikRoutingEngine *self )
573{
574 g_return_val_if_fail ( VIK_IS_ROUTING_WEB_ENGINE (self), FALSE);
575
576 VikRoutingWebEnginePrivate *priv = VIK_ROUTING_WEB_ENGINE_PRIVATE ( self );
577
578 return priv->url_via_ll_fmt != NULL;
579}