1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <time.h>
6 #include <errno.h>
7 #include <math.h>
8 
9 #include <gtk/gtk.h>
10 #include <glib.h>
11 
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 
16 #include <libxml/parser.h>
17 #include <libxml/tree.h>
18 
19 #include <gps.h>
20 
21 
22 #include "globals.h"
23 #include "interface.h"
24 #include "support.h"
25 #include "converter.h"
26 #include "map_management.h"
27 #include "tile_management.h"
28 #include "tracks.h"
29 #include "util.h"
30 
31 GSList *loaded_track = NULL;
32 GtkWidget *window12;
33 static GtkWidget *dialog10;
34 
35 
36 
37 GtkWidget *	make_file_label(const char *file, char *full_file);
38 
39 bbox_t		get_track_bbox(GSList *track);
40 
41 GSList *	load_log_file_into_list(char *file);
42 GSList *	load_gpx_file_into_list(char *file);
43 GSList * load_ols_XML_file_into_list(char *file);
44 GSList * load_kml_XML_file_into_list(char *file);
45 GSList * parse_gpx_nodes(xmlNode *node);
46 GSList * parse_ols_XML_nodes(xmlNode *node);
47 GSList * parse_kml_XML_nodes(xmlNode *node);
48 
49 void * fetch_track_thread(void *ptr);
50 void * fetch_openrouteservice_track_thread(void *ptr);
51 
52 
53 void
reset_loaded_track()54 reset_loaded_track()
55 {
56 
57 	loaded_track = NULL;
58 }
59 
60 void
paint_track()61 paint_track()
62 {
63 	GList *list;
64 	int pixel_x, pixel_y, x,y, last_x = 0, last_y = 0;
65 	int counter = -1, modulo, j=0;
66 	float lat, lon;
67 	GdkColor color;
68 	GdkGC *gc;
69 	gboolean is_line = FALSE;
70 
71 	gc = gdk_gc_new(pixmap);
72 	color.green = 0;
73 	color.blue = 0;
74 	color.red = 60000;
75 	gdk_gc_set_rgb_fg_color(gc, &color);
76 	gdk_gc_set_line_attributes(gc,
77 		5, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
78 
79 	if (global_zoom < 16 && global_zoom > 10)
80 		modulo = exp2(16-global_zoom);
81 	else if (global_zoom <= 10)
82 		modulo = 32;
83 	else
84 		modulo = 1;
85 
86 	for(list = trackpoint_list->tail; list != NULL; list = list->prev)
87 	{
88 		counter++;
89 
90 		if (counter % modulo == 0)
91 		{
92 			j++;
93 			if (j > 300)
94 			{
95 				break;
96 			}
97 
98 			trackpoint_t *tp = list->data;
99 
100 			lat = tp->lat;
101 			lon = tp->lon;
102 
103 
104 
105 			pixel_x = lon2pixel(global_zoom, lon);
106 			pixel_y = lat2pixel(global_zoom, lat);
107 
108 			x = pixel_x - global_x;
109 			y = pixel_y - global_y;
110 
111 
112 			if(is_line)
113 			{
114 				gdk_draw_line (pixmap, gc, x, y, last_x, last_y);
115 				gtk_widget_queue_draw_area (
116 					map_drawable,
117 					x-4, y-4,
118 					8,8);
119 			}
120 
121 			last_x = x;
122 			last_y = y;
123 
124 			is_line = TRUE;
125 		}
126 	}
127 }
128 
129 
130 void
paint_loaded_track()131 paint_loaded_track()
132 {
133 
134 	GSList *list;
135 	int pixel_x, pixel_y, x,y, last_x = 0, last_y = 0;
136 	float lat, lon;
137 	GdkColor color;
138 	GdkGC *gc;
139 	gboolean is_line = FALSE;
140 
141 	gc = gdk_gc_new(pixmap);
142 	color.green = 50000;
143 	color.blue = 0;
144 	color.red = 0;
145 	gdk_gc_set_rgb_fg_color(gc, &color);
146 	gdk_gc_set_line_attributes(gc,
147 		5, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
148 
149 
150 	for(list = loaded_track; list != NULL; list = list->next)
151 	{
152 		trackpoint_t *tp = list->data;
153 
154 		lat = tp->lat;
155 		lon = tp->lon;
156 
157 
158 
159 
160 		pixel_x = lon2pixel(global_zoom, lon);
161 		pixel_y = lat2pixel(global_zoom, lat);
162 
163 		x = pixel_x - global_x;
164 		y = pixel_y - global_y;
165 
166 
167 		if(is_line)
168 		{
169 			gdk_draw_line (pixmap, gc, x, y, last_x, last_y);
170 			gtk_widget_queue_draw_area (
171 				map_drawable,
172 				x-4, y-4,
173 				8,8);
174 
175 		}
176 
177 		last_x = x;
178 		last_y = y;
179 
180 
181 		is_line = TRUE;
182 	}
183 }
184 
185 
186 FILE *fp = NULL;
187 
188 
189 
190 void
track_log()191 track_log()
192 {
193 	gchar buffer[256];
194 	const gchar *fixstr;
195 	time_t time_sec;
196 	struct tm *ts;
197 	int heartfreq = 42;
198 
199 
200 	if(gpsdata->valid)
201 	{
202 
203 		time_sec = (time_t)gpsdata->fix.time;
204 		ts = gmtime(&time_sec);
205 		strftime(buffer, sizeof(buffer), "%Y-%m-%dT%H:%M:%SZ", ts);
206 
207 		heartfreq = (hrmdata) ? hrmdata->freq : 0;
208 
209 		switch (gpsdata->fix.mode) {
210 		default:
211 		case MODE_NOT_SEEN:
212 		case MODE_NO_FIX:
213 			fixstr = "none";
214 			break;
215 		case MODE_2D:
216 			fixstr = "2d";
217 			break;
218 		case MODE_3D:
219 			fixstr = "3d";
220 			break;
221 		}
222 
223 		if (fp)
224 		{
225 			fprintf (fp, "\n"
226 			         "<trkpt lat=\"%f\" lon=\"%f\">\n"
227 			         "  <ele>%g</ele>\n"
228 			         "  <time>%s</time>\n"
229 			         "  <fix>%s</fix>\n"
230 			         "  <hdop>%g</hdop>\n"
231 			         "  <extensions>\n"
232 			         "    <gpxtpx:TrackPointExtension>\n",
233 			         gpsdata->fix.latitude,
234 			         gpsdata->fix.longitude,
235 			         gpsdata->fix.altitude,
236 			         buffer,
237 			         fixstr,
238 			         gpsdata->hdop);
239 
240 			if (heartfreq > 0)
241 			{
242 				/* The TrackPointExtension schema defines
243 				   the lower bound on heart-rate to be 1. */
244 
245 				fprintf (fp,
246 				 "      <gpxtpx:hr>%d</gpxtpx:hr>\n",
247 				         heartfreq);
248 			}
249 
250 			fprintf (fp,
251 			         "      <gpxtpx:speed>%g</gpxtpx:speed>\n"
252 			         "      <gpxtpx:course>%g</gpxtpx:course>\n"
253 			         "    </gpxtpx:TrackPointExtension>\n"
254 			         "  </extensions>\n"
255 			         "</trkpt>\n",
256 			         gpsdata->fix.speed,
257 			         gpsdata->fix.heading);
258 		}
259 	}
260 }
261 
262 void
track_log_open()263 track_log_open()
264 {
265 	time_t time_epoch_sec;
266 	struct tm  *tm_struct;
267 	gchar buffer[256];
268 	gchar *filename = NULL;
269 	GtkLabel *label76;
270 	gchar *labeltext;
271 
272 	label76 = GTK_LABEL(lookup_widget(window1, "label76"));
273 
274 
275 	time_epoch_sec = time(NULL);
276 	tm_struct = localtime(&time_epoch_sec);
277 
278 
279 
280 
281 	strftime (buffer, sizeof (buffer), "%Y%m%d_%H%M%S%z.gpx", tm_struct);
282 
283 
284 	filename = g_strconcat(global_track_dir, buffer,NULL);
285 
286 	if(fp==NULL && trip_logger_on)
287 	{
288 		fp = fopen(filename,"w");
289 		if(!fp)
290 		{
291 			printf (_("oops: %s\n"), strerror (errno));
292 			perror (_("Triplog open failed: "));
293 			gtk_label_set_label (label76,
294 			                     _("<span foreground='#ff0000'>"
295 			                       "Error opening logfile"
296 			                       "</span>"));
297 		}
298 		else
299 		{
300 			labeltext = g_strdup_printf (_("<b><span foreground='#0000ff'>Log: %s</span></b>"), buffer);
301 			gtk_label_set_label(label76,labeltext);
302 			g_free(labeltext);
303 
304 			fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
305 			            "<gpx version=\"1.1\"\n"
306 			            "     creator=\"" PACKAGE_NAME " " PACKAGE_VERSION "\"\n"
307 			            "     xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
308 			            "     xmlns:gpxtpx=\"http://www.garmin.com/xmlschemas/TrackPointExtension/v2\"\n"
309 			            "     xmlns=\"http://www.topografix.com/GPX/1/1\"\n"
310 			            "     xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1\n"
311 			            "                         http://www.topografix.com/GPX/1/1/gpx.xsd\n"
312 			            "                         http://www.garmin.com/xmlschemas/TrackPointExtension/v2\n"
313 			            "                         http://www8.garmin.com/xmlschemas/TrackPointExtensionv2.xsd\">\n"
314 			            "<trk>\n"
315 			            "<trkseg>\n");
316 		}
317 	}
318 
319 	g_free(filename);
320 }
321 
322 
323 void
track_log_close()324 track_log_close()
325 {
326 	int ret;
327 	GtkLabel *label76;
328 	label76 = GTK_LABEL(lookup_widget(window1, "label76"));
329 	gtk_label_set_label(label76,"");
330 
331 	if(fp) {
332 		fprintf (fp, "\n"
333 		         "</trkseg>\n"
334 		         "</trk>\n"
335 		         "</gpx>\n");
336 
337 		ret = fclose(fp);
338 		fp = NULL;
339 
340 		if(ret) printf("ERROR closing file\n");
341 	}
342 }
343 
344 
345 
346 
347 void
tracks_open_tracks_dialog()348 tracks_open_tracks_dialog()
349 {
350 	GDir *dir;
351 	GError *err = NULL;
352 	const char *file;
353 	gboolean isfile;
354 	GList *list = NULL;
355 
356 	GtkWidget *label, *vbox, *eventbox;
357 
358 
359 	dir = g_dir_open(global_track_dir, 0, &err);
360 
361 	if (err != NULL)
362 	{
363 		fprintf (stderr, _("Problem opening directory: %s\n"),
364 		         err->message);
365 		g_error_free (err);
366 		return;
367 	}
368 
369 
370 
371 	window12 = glade_xml_get_widget(gladexml, "window12");
372 	gtk_widget_show(window12);
373 
374 	vbox = lookup_widget(window12, "vbox39");
375 
376 
377 
378 	file = g_dir_read_name(dir);
379 
380 	while (file)
381 	{
382 		isfile = g_file_test(g_strconcat(global_track_dir,file,NULL), G_FILE_TEST_IS_REGULAR);
383 
384 		if(isfile)
385 			list = g_list_insert_sorted( list, g_strdup(file), (GCompareFunc) g_strcmp0 );
386 
387 		file = g_dir_read_name(dir);
388 	}
389 
390 	for(; list!=NULL; list=list->next)
391 	{
392 		char *file = list->data;
393 
394 		eventbox = gtk_event_box_new ();
395 		gtk_widget_set_events (eventbox, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_ENTER_NOTIFY_MASK);
396 		gtk_widget_show (eventbox);
397 
398 
399 		gtk_box_pack_start (GTK_BOX (vbox), eventbox, FALSE, FALSE, 0);
400 
401 		label = make_file_label(file, g_strconcat(global_track_dir,file,NULL));
402 		gtk_widget_show(label);
403 		gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
404 		gtk_misc_set_padding (GTK_MISC (label), 3, 2);
405 
406 		gtk_container_add (GTK_CONTAINER (eventbox), label);
407 
408 		g_signal_connect ((gpointer) eventbox, "button_release_event",
409 				G_CALLBACK (tracks_on_file_button_release_event),
410 				g_strconcat(global_track_dir,file,NULL));
411 	}
412 
413 	g_list_free(list);
414 	g_dir_close(dir);
415 }
416 
417 
418 GtkWidget *
make_file_label(const char * file,char * full_file)419 make_file_label(const char *file, char *full_file)
420 {
421 	GtkWidget *label;
422 
423 	label = gtk_label_new (g_strdup(file));
424 
425 	return label;
426 }
427 
428 void
show_bbox(bbox_t bbox)429 show_bbox (bbox_t bbox)
430 {
431 	GtkWidget *drawingarea, *range;
432 	int track_zoom, width, height;
433 
434 	drawingarea = lookup_widget (window1, "drawingarea1");
435 	width  = drawingarea->allocation.width;
436 	height = drawingarea->allocation.height;
437 
438 	track_zoom = get_zoom_covering (width, height,
439 	                                bbox.lat1, bbox.lon1,
440 	                                bbox.lat2, bbox.lon2);
441 	track_zoom = (track_zoom > 15) ? 15 : track_zoom;
442 
443 	set_mapcenter (rad2deg ((bbox.lat1+bbox.lat2)/2),
444 	               rad2deg ((bbox.lon1+bbox.lon2)/2),
445 	               track_zoom);
446 
447 	range = lookup_widget (window1, "vscale1");
448 	gtk_range_set_value (GTK_RANGE (range), (double) global_zoom);
449 }
450 
451 gboolean
tracks_on_file_button_release_event(GtkWidget * widget,GdkEventButton * event,gpointer user_data)452 tracks_on_file_button_release_event   (	GtkWidget       *widget,
453                                         GdkEventButton  *event,
454                                         gpointer         user_data)
455 {
456 	GtkWidget *widget_tmp;
457 	char *file;
458 	bbox_t bbox;
459 
460 	widget_tmp = lookup_widget(window1, "button79");
461 	gtk_widget_show(widget_tmp);
462 
463 	file = (char *) user_data;
464 
465 	if (widget && window12) {
466 		/* Note that this function is also called from
467 		   geo_photos_geocode_track_select_dialog(),
468 		   not just as a GTK+ callback!
469 
470 		   In this case, all arguments except for user_data
471 		   are NULL and we have not been called as a result of
472 		   anything actually involving window12, and we should
473 		   avoid messing with it. In fact, we *must* avoid it:
474 		   the window12 object may not even exist, since it's
475 		   created only on demand.
476 		*/
477 
478 		GtkWidget *vbox;
479 
480 		gtk_widget_hide(window12);
481 
482 		vbox = lookup_widget(window12, "vbox39");
483 		gtk_container_foreach (GTK_CONTAINER (vbox),
484 				       (GtkCallback) gtk_widget_destroy,
485 				       NULL);
486 	}
487 
488 	if(loaded_track)
489 	{
490 		g_slist_foreach (loaded_track, (GFunc) g_free, NULL);
491 		g_slist_free (loaded_track);
492 	}
493 	loaded_track = NULL;
494 
495 	if (g_strrstr(file,".gpx") ||
496 	    g_strrstr(file,".GPX") ||
497 	    g_strrstr(file,".Gpx") )
498 	{
499 		loaded_track = load_gpx_file_into_list(file);
500 	}
501 	else
502 		loaded_track = load_log_file_into_list(file);
503 
504 	if(loaded_track)
505 	{
506 		bbox = get_track_bbox (loaded_track);
507 		show_bbox (bbox);
508 	}
509 
510 	paint_loaded_track();
511 
512 	return FALSE;
513 }
514 
515 
516 
517 bbox_t
get_track_bbox(GSList * track)518 get_track_bbox(GSList *track)
519 {
520 	GSList *list;
521 	bbox_t bbox;
522 	double lat, lon;
523 
524 	bbox.lat1 =  -90;
525 	bbox.lon1 =  180;
526 	bbox.lat2 =   90;
527 	bbox.lon2 = -180;
528 
529 
530 	for(list = track; list != NULL; list = list->next)
531 	{
532 		trackpoint_t *tp = list->data;
533 
534 		lat = tp->lat;
535 		lon = tp->lon;
536 		bbox.lat1 = (lat > bbox.lat1) ? lat : bbox.lat1;
537 		bbox.lat2 = (lat < bbox.lat2) ? lat : bbox.lat2;
538 		bbox.lon1 = (lon < bbox.lon1) ? lon : bbox.lon1;
539 		bbox.lon2 = (lon > bbox.lon2) ? lon : bbox.lon2;
540 	}
541 
542 	return bbox;
543 }
544 
545 
546 GSList *
load_log_file_into_list(char * file)547 load_log_file_into_list(char *file)
548 {
549 	GSList *list = NULL;
550 	char line[121];
551 	FILE *fd;
552 
553 	fd = fopen(file, "r");
554 
555 	if (!fd) {
556 		return list;
557 	}
558 
559 	while(fgets(line,120, fd))
560 	{
561 		trackpoint_t *tp;
562 		char *latstr, *lonstr;
563 		char *parseptr;
564 
565 		latstr = strtok_r (line, ",", &parseptr);
566 		lonstr = strtok_r (NULL, ",", &parseptr);
567 
568 
569 		if (latstr == NULL || lonstr == NULL) continue;
570 
571 
572 		tp = g_new0 (trackpoint_t, 1);
573 		tp->lat = deg2rad (atof (latstr));
574 		tp->lon = deg2rad (atof (lonstr));
575 
576 		list = g_slist_append(list, tp);
577 	}
578 
579 	fclose (fd);
580 
581 	return list;
582 }
583 
584 
585 GSList *
load_gpx_file_into_list(char * file)586 load_gpx_file_into_list(char *file)
587 {
588 	GSList *list = NULL;
589 	xmlDoc *doc = NULL;
590 	xmlNode *root_element = NULL;
591 
592 
593 	LIBXML_TEST_VERSION
594 
595 	doc = xmlReadFile(file, NULL, 0);
596 
597 	if (doc == NULL) {
598 		printf("error: could not parse file %s\n", file);
599 	} else {
600 		root_element = xmlDocGetRootElement(doc);
601 		list = parse_gpx_nodes(root_element);
602 
603 		xmlFreeDoc(doc);
604 	}
605 
606 	return list;
607 }
608 
609 GSList *
load_gpx_string_into_list(char * gpx_string)610 load_gpx_string_into_list(char *gpx_string)
611 {
612 	GSList *list = NULL;
613 	xmlDoc *doc = NULL;
614 	xmlNode *root_element = NULL;
615 
616 	if(!gpx_string) return NULL;
617 
618 	LIBXML_TEST_VERSION
619 
620 	doc = xmlReadMemory(gpx_string, strlen(gpx_string), "noname.xml", NULL, 0);
621 
622 	if (doc == NULL) {
623 		fprintf (stderr, _("Failed to parse document\n"));
624 	} else {
625 		root_element = xmlDocGetRootElement(doc);
626 		list = parse_gpx_nodes(root_element);
627 
628 		xmlFreeDoc(doc);
629 	}
630 
631 	return list;
632 }
633 
634 GSList *
load_ols_XML_string_into_list(char * ols_string)635 load_ols_XML_string_into_list(char *ols_string)
636 {
637 	GSList *list = NULL;
638 	xmlDoc *doc = NULL;
639 	xmlNode *root_element = NULL;
640 
641 	if(!ols_string) return NULL;
642 
643 	LIBXML_TEST_VERSION
644 
645 	doc = xmlReadMemory(ols_string, strlen(ols_string), "noname.xml", NULL, 0);
646 
647 	if (doc == NULL) {
648 		fprintf (stderr, _("Failed to parse document\n"));
649 	} else {
650 		root_element = xmlDocGetRootElement(doc);
651 		list = parse_ols_XML_nodes(root_element);
652 		xmlFreeDoc(doc);
653 	}
654 
655 	return list;
656 }
657 
658 GSList *
load_kml_XML_string_into_list(char * kml_string)659 load_kml_XML_string_into_list(char *kml_string)
660 {
661 	GSList *list = NULL;
662 	xmlDoc *doc = NULL;
663 	xmlNode *root_element = NULL;
664 
665 	if(!kml_string) return NULL;
666 
667 	LIBXML_TEST_VERSION
668 
669 	doc = xmlReadMemory(kml_string, strlen(kml_string), "noname.xml", NULL, 0);
670 
671 	if (doc == NULL) {
672 		fprintf (stderr, _("Failed to parse document\n"));
673 	} else {
674 		root_element = xmlDocGetRootElement(doc);
675 		list = parse_kml_XML_nodes(root_element);
676 		xmlFreeDoc(doc);
677 	}
678 
679 	return list;
680 }
681 
682 GSList *
parse_gpx_nodes(xmlNode * node)683 parse_gpx_nodes(xmlNode *node)
684 {
685 	xmlNode *cur_node = NULL;
686 	GSList *list = NULL;
687 
688 
689 	for (cur_node = node; cur_node; cur_node = cur_node->next)
690 	{
691 		if (cur_node->type == XML_ELEMENT_NODE)
692 		{
693 			if (xmlStrEqual(cur_node->name, BAD_CAST "trkpt") ||
694 			    xmlStrEqual(cur_node->name, BAD_CAST "rtept"))
695 			{
696 				double lat, lon;
697 				trackpoint_t *tp = g_new0(trackpoint_t,1);
698 
699 				if (xmlHasProp(cur_node, BAD_CAST "junction") &&
700 				    strcmp(xmlGetProp(cur_node, BAD_CAST "junction"), "") == 0)
701 				{
702 					continue;
703 				}
704 
705 				lat = atof((char *)xmlGetProp(cur_node, BAD_CAST "lat"));
706 				lon = atof((char *)xmlGetProp(cur_node, BAD_CAST "lon"));
707 
708 				tp->lat = deg2rad(lat);
709 				tp->lon = deg2rad(lon);
710 
711 				list = g_slist_append(list, tp);
712 			}
713 		}
714 		list = g_slist_concat(list, parse_gpx_nodes(cur_node->children));
715 	}
716 
717 	return list;
718 }
719 
720 GSList *
parse_ols_XML_nodes(xmlNode * node)721 parse_ols_XML_nodes(xmlNode *node)
722 {
723 	xmlNode *cur_node = NULL;
724 	GSList *list = NULL;
725 
726 	for (cur_node = node; cur_node; cur_node = cur_node->next)
727 	{
728 		if (xmlStrEqual(cur_node->name, BAD_CAST "RouteGeometry"))
729 		{
730 			xmlNode *geometry_node = cur_node->children;
731 			while (geometry_node != NULL)
732 			{
733 				if (xmlStrEqual(geometry_node->name, BAD_CAST "LineString"))
734 				{
735 					xmlNode *inner_cur_node = geometry_node->children;
736 					while (inner_cur_node != NULL)
737 					{
738 						if (xmlStrEqual(inner_cur_node->name, BAD_CAST "pos"))
739 						{
740 							double lat, lon;
741 							char** lonlat;
742 
743 							trackpoint_t *tp = g_new0(trackpoint_t,1);
744 							fflush(stdout);
745 							lonlat = g_strsplit(xmlNodeGetContent(inner_cur_node), " ", 2);
746 							if (lonlat[0])
747 							{
748 								lon = atof(lonlat[0]);
749 								if (lonlat[1])
750 								{
751 									lat = atof(lonlat[1]);
752 									tp->lat = deg2rad(lat);
753 									tp->lon = deg2rad(lon);
754 									list = g_slist_append(list, tp);
755 								}
756 							}
757 							g_strfreev (lonlat);
758 						}
759 						inner_cur_node = inner_cur_node->next;
760 					}
761 				}
762 				geometry_node = geometry_node->next;
763 			}
764 		}
765 		list = g_slist_concat(list, parse_ols_XML_nodes(cur_node->children));
766 	}
767 
768 	return list;
769 }
770 
771 GSList *
parse_kml_XML_nodes(xmlNode * node)772 parse_kml_XML_nodes(xmlNode *node)
773 {
774 	xmlNode *cur_node = NULL;
775 	GSList *list = NULL;
776 
777 	for (cur_node = node; cur_node; cur_node = cur_node->next)
778 	{
779 		if (xmlStrEqual(cur_node->name, BAD_CAST "Placemark"))
780 		{
781 			xmlNode *geometry_node = cur_node->children;
782 			while (geometry_node != NULL)
783 			{
784 				if (xmlStrEqual(geometry_node->name, BAD_CAST "LineString"))
785 				{
786 					xmlNode *inner_cur_node = geometry_node->children;
787 					while (inner_cur_node != NULL)
788 					{
789 						if (xmlStrEqual(inner_cur_node->name, BAD_CAST "coordinates")) {
790 							char** lonlatlist;
791 							lonlatlist = g_strsplit(xmlNodeGetContent(inner_cur_node), "\n", -1);
792 							for(unsigned int i = 0; lonlatlist[i]; i++){
793 								g_strchug(lonlatlist[i]);
794 								g_strchomp(lonlatlist[i]);
795 								char** lonlat = g_strsplit(lonlatlist[i], ",", 2);
796 								if (lonlat[0])
797 								{
798 									double lat, lon;
799 									lon = atof(lonlat[0]);
800 									if (lonlat[1])
801 									{
802 										trackpoint_t *tp = g_new0(trackpoint_t,1);
803 										lat = atof(lonlat[1]);
804 										tp->lat = deg2rad(lat);
805 										tp->lon = deg2rad(lon);
806 										list = g_slist_append(list, tp);
807 									}
808 								}
809 								g_strfreev (lonlat);
810 							}
811 							g_strfreev (lonlatlist);
812 						}
813 						inner_cur_node = inner_cur_node->next;
814 					}
815 				}
816 				geometry_node = geometry_node->next;
817 			}
818 		}
819 		list = g_slist_concat(list, parse_kml_XML_nodes(cur_node->children));
820 	}
821 
822 	return list;
823 }
824 
825 
826 void
fetch_track(GtkWidget * widget,char * service,char * start,char * end)827 fetch_track(GtkWidget *widget, char *service, char *start, char *end)
828 {
829 	if (strcmp (service, "yournavigation.org") == 0)
830 		fetch_yournavigation_track(widget, start, end);
831 	else if (strcmp (service, "openrouteservice.org") == 0)
832 		fetch_openrouteservice_track(widget, start, end);
833 	else
834 	{
835 		char *err_msg = g_strdup_printf (_("<span color='#aa0000'><b>"
836 		                                   "Unknown service selected"
837 		                                   "</b></span>\n"
838 		                                   "This is a bug in %s!"),
839 		                                 _(PACKAGE_NAME));
840 		GtkWidget *tmpWidget;
841 
842 		tmpWidget = lookup_widget(dialog10, "label190");
843 		gtk_label_set_label(GTK_LABEL(tmpWidget), err_msg);
844 
845 		tmpWidget = lookup_widget(dialog10, "okbutton11");
846 		gtk_widget_set_sensitive(tmpWidget, TRUE);
847 
848 		g_warning("###unknown route service (%s) selected\n", service);
849 	}
850 }
851 
fetch_yournavigation_track(GtkWidget * widget,char * start,char * end)852 void fetch_yournavigation_track(GtkWidget *widget, char *start, char *end)
853 {
854 	char *url;
855 	char *startlatstr;
856 	char *startlonstr;
857 	char *endlatstr;
858 	char *endlonstr;
859 	char *parseptr;
860 	startlatstr = strtok_r (start, ",", &parseptr);
861 	startlonstr = strtok_r (NULL, ",", &parseptr);
862 	endlatstr = strtok_r (end, ",", &parseptr);
863 	endlonstr = strtok_r (NULL, ",", &parseptr);
864 	dialog10 = widget;
865 
866 	url = g_strdup_printf("http://www.yournavigation.org/api/1.0/gosmore.php?format=kml&flat=%s&flon=%s&tlat=%s&tlon=%s&v=motorcar&fast=1&layer=mapnik",startlatstr, startlonstr, endlatstr, endlonstr);
867 #if GLIB_CHECK_VERSION(2,34,0)
868 	if (!g_thread_new("fetch track thread", &fetch_track_thread, (void *)url) != 0)
869 #else
870 	if (!g_thread_create(&fetch_track_thread, (void *)url, FALSE, NULL) != 0)
871 #endif
872 		g_warning("### can't create route thread\n");
873 }
874 
fetch_openrouteservice_track(GtkWidget * widget,char * start,char * end)875 void fetch_openrouteservice_track(GtkWidget *widget, char *start, char *end)
876 {
877 	char *url;
878 	dialog10 = widget;
879 	char *startlatstr;
880 	char *startlonstr;
881 	char *endlatstr;
882 	char *endlonstr;
883 	char *parseptr;
884 	startlatstr = strtok_r (start, ",", &parseptr);
885 	startlonstr = strtok_r (NULL, ",", &parseptr);
886 	endlatstr = strtok_r (end, ",", &parseptr);
887 	endlonstr = strtok_r (NULL, ",", &parseptr);
888 	char *request;
889 
890 	request = g_strdup_printf("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
891 	                          "<xls:XLS xmlns:xls=\"http://www.opengis.net/xls\" xmlns:sch=\"http://www.ascc.net/xml/schematron\" "
892 	                          "xmlns:gml=\"http://www.opengis.net/gml\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
893 	                          "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
894 	                          "xsi:schemaLocation=\"http://www.opengis.net/xls "
895 	                          "http://schemas.opengis.net/ols/1.1.0/RouteService.xsd\" version=\"1.1\" xls:lang=\"en\">\n"
896 	                          "<xls:RequestHeader/>\n"
897 	                          "<xls:Request methodName=\"RouteRequest\" requestID=\"999\" version=\"1.1\">\n"
898 	                          "<xls:DetermineRouteRequest distanceUnit=\"KM\">\n"
899 	                          "<xls:RoutePlan>\n"
900 	                          "<xls:RoutePreference>Fastest</xls:RoutePreference>"
901 	                          "<xls:WayPointList>\n"
902 	                          "<xls:StartPoint>\n"
903 	                          "<xls:Position>\n"
904 	                          "<gml:Point srsName=\"EPSG:4326\">\n"
905 	                          "<gml:pos>%s %s</gml:pos>\n"
906 	                          "</gml:Point>\n"
907 	                          "</xls:Position>\n"
908 	                          "</xls:StartPoint>\n"
909 	                          "<xls:EndPoint>\n"
910 	                          "<xls:Position>\n"
911 	                          "<gml:Point srsName=\"EPSG:4326\">\n"
912 	                          "<gml:pos>%s %s</gml:pos>\n"
913 	                          "</gml:Point>\n"
914 	                          "</xls:Position>\n"
915 	                          "</xls:EndPoint>\n"
916 	                          "</xls:WayPointList>\n"
917 	                          "</xls:RoutePlan>\n"
918 	                          "<xls:RouteInstructionsRequest provideGeometry=\"true\"/>\n"
919 	                          "<xls:RouteGeometryRequest/>\n"
920 	                          "</xls:DetermineRouteRequest>"
921 	                          "</xls:Request>\n"
922 	                          "</xls:XLS>\n",
923 	                          startlonstr,
924 	                          startlatstr,
925 	                          endlonstr,
926 	                          endlatstr
927 	);
928 
929 	url = g_strdup_printf("http://openls.geog.uni-heidelberg.de/osm/eu/routing");
930 
931 	char **urlAndRequest = g_malloc(2 * sizeof(char*));
932 	urlAndRequest[0] = url;
933 	urlAndRequest[1] = request;
934 
935 #if GLIB_CHECK_VERSION(2,34,0)
936 	if (!g_thread_new("fetch open route thread", &fetch_openrouteservice_track_thread, (void *)urlAndRequest) != 0)
937 #else
938 	if (!g_thread_create(&fetch_openrouteservice_track_thread, (void *)urlAndRequest, FALSE, NULL) != 0)
939 #endif
940 		g_warning("### can't create route thread\n");
941 }
942 
process_fetched_track(postreply_t * reply,bool save_gpx)943 void process_fetched_track(postreply_t *reply, bool save_gpx)
944 {
945 	bbox_t bbox;
946 
947 	if(loaded_track)
948 	{
949 		if (save_gpx)
950 		{
951 			FILE *fp = NULL;
952 			time_t time_epoch_sec;
953 			struct tm  *tm_struct;
954 			gchar buffer[256];
955 			gchar *filename = NULL;
956 
957 			time_epoch_sec = time(NULL);
958 			tm_struct = localtime(&time_epoch_sec);
959 			strftime(buffer, sizeof(buffer), "nav%Y%m%d_%H%M%S%z.gpx", tm_struct);
960 
961 			filename = g_strconcat(global_track_dir, buffer,NULL);
962 
963 			fp = fopen(filename,"w");
964 			if(!fp)
965 			{
966 				printf("oops: %s \n",strerror(errno));
967 				perror("navtrack open failed: ");
968 			}
969 			else
970 			{
971 				fprintf(fp,"%s", reply->data);
972 				fclose(fp);
973 			}
974 
975 			g_free(filename);
976 		}
977 
978 		gdk_threads_enter();
979 		{
980 			if(loaded_track)
981 			{
982 				bbox = get_track_bbox (loaded_track);
983 				show_bbox (bbox);
984 			}
985 
986 			paint_loaded_track();
987 			gtk_widget_hide(dialog10);
988 		}
989 		gdk_threads_leave();
990 	}
991 	else
992 	{
993 		const char *err_msg;
994 
995 
996 
997 		if(reply->status_code == 200)
998 			err_msg = g_strdup (_("<span color='#aa0000'><b>"
999 			                      "Oops! No Route found"
1000 			                      "</b></span>\n"
1001 			                      "Try with another Start/End"));
1002 
1003 
1004 		else if(reply->status_code == 203)
1005 			err_msg = g_strdup(reply->data);
1006 
1007 
1008 		else if (reply->status_code)
1009 			err_msg = g_strdup (_("<span color='#aa0000'><b>"
1010 			                      "Duh! A Server Error"
1011 			                      "</b></span>\n"
1012 			                      "Maybe try later again..."));
1013 
1014 
1015 		else
1016 			err_msg = g_strdup (_("<span color='#aa0000'><b>"
1017 			                      "Oh! A Network Error"
1018 			                      "</b></span>\n"
1019 			                      "Check the internet!"));
1020 
1021 		gdk_threads_enter();
1022 		{
1023 			GtkWidget *widget;
1024 
1025 			widget = lookup_widget(dialog10, "label190");
1026 			gtk_label_set_label(GTK_LABEL(widget), err_msg);
1027 
1028 			widget = lookup_widget(dialog10, "okbutton11");
1029 			gtk_widget_set_sensitive(widget, TRUE);
1030 		}
1031 		gdk_threads_leave();
1032 
1033 	}
1034 
1035 }
1036 
1037 void *
fetch_openrouteservice_track_thread(void * ptr)1038 fetch_openrouteservice_track_thread(void *ptr)
1039 {
1040 	postreply_t *reply = NULL;
1041 	char *url;
1042 	char *request;
1043 
1044 	url = ((char**)ptr)[0];
1045 	request = ((char**)ptr)[1];
1046 
1047 
1048 	reply = mycurl__do_http_post_XML(url, request, NULL);
1049 
1050 	loaded_track = load_ols_XML_string_into_list(reply->data);
1051 	process_fetched_track(reply, false);
1052 
1053 	g_free(url);
1054 	g_free(request);
1055 	g_free((char**)ptr);
1056 	return NULL;
1057 }
1058 
1059 void *
fetch_track_thread(void * ptr)1060 fetch_track_thread(void *ptr)
1061 {
1062 	postreply_t *reply = NULL;
1063 	char *url;
1064 	GtkWidget *range, *drawingarea;
1065 	int track_zoom, width, height;
1066 	bbox_t bbox;
1067 
1068 	drawingarea = lookup_widget(window1, "drawingarea1");
1069 	width  = drawingarea->allocation.width;
1070 	height = drawingarea->allocation.height;
1071 
1072 	url = ptr;
1073 
1074 	reply = mycurl__do_http_get(url, NULL);
1075 
1076 	loaded_track = load_kml_XML_string_into_list(reply->data);
1077 	process_fetched_track(reply, true);
1078 
1079 	return NULL;
1080 }
1081