1 
2 
3 #ifdef HAVE_CONFIG_H
4 #  include <config.h>
5 #endif
6 
7 #include <glib.h>
8 #include <glib/gprintf.h>
9 
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <time.h>
14 #include <string.h>
15 #include <math.h>
16 
17 #include <gps.h>
18 
19 #include "gps_functions.h"
20 #include "globals.h"
21 #include "support.h"
22 #include "tile_management.h"
23 #include "map_management.h"
24 #include "converter.h"
25 #include "wp.h"
26 #include "tracks.h"
27 #include "hrm_functions.h"
28 
29 #if GPSD_API_MAJOR_VERSION < 5
30 #define gps_read gps_poll
31 #define gps_open gps_open_r
32 #endif
33 
34 #define BUFSIZE 512
35 char * distance2scale(float distance, float *factor);
36 static void * get_gps_thread(void *ptr);
37 
38 
39 static GIOChannel *gpsd_io_channel =NULL;
40 static struct gps_data_t libgps_gpsdata;
41 static gboolean libgps_initialized = FALSE;
42 
43 gboolean reconnect_gpsd = TRUE;
44 
45 static guint sid1 = 0;
46 static guint sid3 = 0;
47 static guint watchdog = 0;
48 static guint gps_timer = 0;
49 
50 gboolean
cb_gps_timer()51 cb_gps_timer()
52 {
53 
54 
55 	int pixel_x, pixel_y, x, y, last_x, last_y;
56 	static float lat, lon, lat_tmp=0, lon_tmp=0;
57 	float trip_delta=0;
58 
59 	static double trip_time_accumulated = 0;
60 	static gboolean trip_counter_got_stopped = FALSE;
61 
62 	GdkColor color;
63 	static GdkGC *gc=NULL, *gc_2=NULL, *gc_3=NULL, *gc_4=NULL, *gc_5=NULL;
64 
65 	if(gc == NULL)
66 	{
67 		gc   = gdk_gc_new(pixmap);
68 		gc_2 = gdk_gc_new(pixmap);
69 		gc_3 = gdk_gc_new(pixmap);
70 		gc_4 = gdk_gc_new(pixmap);
71 		gc_5 = gdk_gc_new(pixmap);
72 
73 
74 		color.red = 60000;
75 		color.green = 0;
76 		color.blue = 0;
77 		gdk_gc_set_rgb_fg_color(gc, &color);
78 		gdk_gc_set_line_attributes(gc,
79 				5, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
80 
81 
82 		color.red = 5000;
83 		color.green = 5000;
84 		color.blue = 55000;
85 		gdk_gc_set_rgb_fg_color(gc_2, &color);
86 		gdk_gc_set_line_attributes(gc_2,
87 				6, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
88 
89 
90 		color.red = 25500;
91 		color.green = 35000;
92 		color.blue = 65500;
93 		gdk_gc_set_rgb_fg_color(gc_3, &color);
94 		gdk_gc_set_line_attributes(gc_3,
95 				7, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
96 
97 
98 		color.red = 35500;
99 		color.green = 5000;
100 		color.blue = 500;
101 		gdk_gc_set_rgb_fg_color(gc_4, &color);
102 		gdk_gc_set_line_attributes(gc_4,
103 				7, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
104 
105 
106 		color.red = 65500;
107 		color.green = 65500;
108 		color.blue = 65500;
109 		gdk_gc_set_rgb_fg_color(gc_5, &color);
110 		gdk_gc_set_line_attributes(gc_5,
111 				11, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
112 
113 	}
114 
115 
116 	if(!gpsdata  || reconnect_gpsd)
117 		get_gps();
118 
119 
120 	if(gpsdata)
121 	{
122 		trackpoint_t *tp = g_new0(trackpoint_t,1);
123 
124 		lat = deg2rad(gpsdata->fix.latitude);
125 		lon = deg2rad(gpsdata->fix.longitude);
126 
127 
128 		pixel_x = lon2pixel(global_zoom, lon);
129 		pixel_y = lat2pixel(global_zoom, lat);
130 
131 		x = pixel_x - global_x;
132 		y = pixel_y - global_y;
133 
134 
135 		pixel_x = lon2pixel(global_zoom, lon_tmp);
136 		pixel_y = lat2pixel(global_zoom, lat_tmp);
137 
138 		last_x = pixel_x - global_x;
139 		last_y = pixel_y - global_y;
140 
141 
142 
143 		if(gpsdata->seen_valid)
144 		{
145 			int hand_x, hand_y, hand_wp_x, hand_wp_y;
146 			double heading_rad, bearing;
147 
148 			heading_rad = (gpsdata->fix.heading * (1.0 / 180.0)) * M_PI;
149 
150 			if(gpsdata->fix.speed>0.3)
151 			{
152 				hand_x =  25 * sinf(heading_rad);
153 				hand_y = -25 * cosf(heading_rad);
154 			}
155 			else
156 			{
157 				hand_x = 0;
158 				hand_y = 0;
159 			}
160 
161 
162 
163 			gdk_draw_drawable (
164 				map_drawable->window,
165 				map_drawable->style->fg_gc[GTK_WIDGET_STATE (map_drawable)],
166 				pixmap,
167 				last_x-29, last_y-29,
168 				last_x-29 + mouse_dx, last_y-29 + mouse_dy,
169 				58,58);
170 
171 
172 			if (lat_tmp && lon_tmp)
173 				gdk_draw_line(pixmap, gc, last_x, last_y, x, y);
174 
175 
176 			gdk_window_process_all_updates();
177 
178 
179 			if(mouse_dx == 0 && mouse_dy == 0)
180 			{
181 
182 				gdk_draw_arc (
183 					map_drawable->window,
184 					gc_2,
185 					FALSE,
186 					x-15 + mouse_dx,
187 					y-15 + mouse_dy,
188 					30,30,
189 					0, 360*64);
190 
191 
192 				if(global_wp_on && gpsdata->valid)
193 				{
194 
195 					bearing = get_bearing(lat, lon, global_wp.lat, global_wp.lon);
196 					gpsdata->fix.bearing = bearing;
197 
198 					hand_wp_x =  25 * sinf(bearing);
199 					hand_wp_y = -25 * cosf(bearing);
200 
201 					gdk_draw_line(map_drawable->window,
202 							gc_5,
203 							x + mouse_dx,
204 							y + mouse_dy,
205 							x + mouse_dx + hand_wp_x,
206 							y + mouse_dy + hand_wp_y);
207 
208 					gdk_draw_line(map_drawable->window,
209 							gc_4,
210 							x + mouse_dx,
211 							y + mouse_dy,
212 							x + mouse_dx + hand_wp_x,
213 							y + mouse_dy + hand_wp_y);
214 
215 					osd_wp();
216 
217 				}
218 
219 
220 				gdk_draw_line(map_drawable->window,
221 						gc_5,
222 						x + mouse_dx,
223 						y + mouse_dy,
224 						x + mouse_dx + hand_x,
225 						y + mouse_dy + hand_y);
226 
227 				gdk_draw_line(map_drawable->window,
228 						gc_3,
229 						x + mouse_dx,
230 						y + mouse_dy,
231 						x + mouse_dx + hand_x,
232 						y + mouse_dy + hand_y);
233 			}
234 		}
235 
236 
237 		if(global_autocenter)
238 		{
239 			if(    (x < (global_drawingarea_width /2 - global_drawingarea_width /8) ||
240 				x > (global_drawingarea_width /2 + global_drawingarea_width /8) ||
241 				y < (global_drawingarea_height /2 - global_drawingarea_height /8) ||
242 				y > (global_drawingarea_height /2 + global_drawingarea_height /8) ) &&
243 
244 
245 				isnan(gpsdata->fix.latitude) ==0 &&
246 				isnan(gpsdata->fix.longitude)==0 &&
247 				gpsdata->fix.latitude  !=0 &&
248 				gpsdata->fix.longitude !=0
249 				)
250 			{
251 				set_mapcenter(gpsdata->fix.latitude, gpsdata->fix.longitude, global_zoom);
252 			}
253 		}
254 
255 
256 
257 
258 
259 		if( gpsdata->valid && lat_tmp!=0 && lon_tmp!=0)
260 		{
261 			trip_delta = 6371.0 *  acos(sin(lat) * sin(lat_tmp) +
262 				     cos(lat) * cos(lat_tmp) * cos(lon_tmp-lon) );
263 
264 			if(isnan(trip_delta))
265 			{
266 
267 				trip_delta = 0;
268 			}
269 
270 			if(trip_delta > TRIP_DELTA_MIN)
271 			{
272 					tp->time    = gpsdata->fix.time;
273 					tp->lat     = lat;
274 					tp->lon     = lon;
275 					tp->lat_deg = gpsdata->fix.latitude;
276 					tp->lon_deg = gpsdata->fix.longitude;
277 					tp->alt     = gpsdata->fix.altitude;
278 					tp->speed   = gpsdata->fix.speed;
279 					tp->head    = gpsdata->fix.heading;
280 					tp->hdop    = gpsdata->hdop;
281 					tp->heart   = 0;
282 
283 					if (trip_delta > SEGMENT_DISTANCE)
284 						tp->hdop = 999;
285 
286 
287 					if (trackpoint_list->length > TRACKPOINT_LIST_MAX_LENGTH)
288 						g_free(g_queue_pop_head(trackpoint_list));
289 
290 					g_queue_push_tail(trackpoint_list, tp);
291 			}
292 		}
293 
294 		if(trip_counter_on)
295 		{
296 			trip_distance += trip_delta;
297 
298 
299 			if(gpsdata->valid && gpsdata->fix.speed > trip_maxspeed)
300 				trip_maxspeed = gpsdata->fix.speed;
301 
302 
303 
304 
305 			if(trip_time == 0)
306 				trip_time_accumulated = 0;
307 
308 			if(trip_counter_got_stopped)
309 			{
310 				trip_counter_got_stopped = FALSE;
311 				trip_time_accumulated = trip_time;
312 				trip_starttime = 0;
313 			}
314 
315 
316 			if(trip_starttime == 0 && gpsdata->seen_valid)
317 			{
318 				trip_starttime = gpsdata->fix.time;
319 			}
320 
321 
322 			if(trip_starttime > 0 && gpsdata->seen_valid)
323 			{
324 				trip_time = gpsdata->fix.time - trip_starttime + trip_time_accumulated;
325 			}
326 
327 			if(trip_time < 0)
328 			{
329 				trip_time = 0;
330 				trip_starttime = 0;
331 				trip_distance = 0;
332 				trip_maxspeed = 0;
333 			}
334 
335 		}
336 
337 		else
338 		{
339 			trip_counter_got_stopped = TRUE;
340 			lat_tmp = lon_tmp = 0;
341 		}
342 
343 
344 		if (global_new_msg)
345 			set_label_newmsg ();
346 		else
347 			set_label ();
348 
349 		if(trip_logger_on && gpsdata->valid)
350 			track_log();
351 
352 		if(gpsdata->valid)
353 		{
354 			lat_tmp = lat;
355 			lon_tmp = lon;
356 		}
357 	}
358 	else
359 	{
360 		if (global_new_msg)
361 			set_label_newmsg ();
362 		else
363 			set_label_nogps();
364 	}
365 
366 	if(hrm_on && (!hrmdata  || global_reconnect_hrm))
367 		get_hrm_data();
368 	else if(hrm_on && hrmdata) {
369 		osd_hrm(FALSE);
370 		if(global_infopane_visible)
371 			set_hrm_labels();
372 	}
373 
374 	return TRUE;
375 }
376 
377 gboolean
reset_gpsd_io()378 reset_gpsd_io()
379 {
380 	reconnect_gpsd = TRUE;
381 
382 	return FALSE;
383 }
384 
385 
386 void
osd_speed(gboolean force_redraw)387 osd_speed(gboolean force_redraw)
388 {
389 
390 	PangoContext		*context = NULL;
391 	PangoLayout		*layout  = NULL;
392 	PangoFontDescription	*desc    = NULL;
393 
394 	GdkColor color;
395 	GdkGC *gc;
396 
397 	gchar *buffer;
398 	static int x = 10, y = 10;
399 	static int width = 0, height = 0;
400 
401 	static double speed_tmp = 0;
402 
403 	double unit_conv = 1;
404 
405 	if(gpsdata && mouse_dx == 0 && mouse_dy == 0)
406 	{
407 		switch (global_speed_unit)
408 		{
409 			case 0:
410 				unit_conv = 1.0;
411 				break;
412 			case 1 :
413 				unit_conv = 1.0/1.609344;
414 				break;
415 			case 2 :
416 				unit_conv = 1.0 / 1.852;
417 				break;
418 		}
419 
420 
421 
422 		buffer = g_strdup_printf("%.0f", gpsdata->fix.speed*3.6*unit_conv);
423 
424 
425 		context = gtk_widget_get_pango_context (map_drawable);
426 		layout  = pango_layout_new (context);
427 		desc    = pango_font_description_new();
428 
429 		pango_font_description_set_absolute_size (desc, 80 * PANGO_SCALE);
430 		pango_layout_set_font_description (layout, desc);
431 		pango_layout_set_text (layout, buffer, strlen(buffer));
432 
433 
434 		gc = gdk_gc_new (map_drawable->window);
435 
436 		color.red = (gpsdata->fix.speed*3.6*unit_conv > 50) ? 0xffff : 0;
437 		color.green = 0;
438 		color.blue = 0;
439 
440 		gdk_gc_set_rgb_fg_color (gc, &color);
441 
442 
443 
444 		if(speed_tmp != floor(gpsdata->fix.speed*3.6*unit_conv) || force_redraw)
445 		{
446 
447 			gdk_draw_drawable (
448 				map_drawable->window,
449 				map_drawable->style->fg_gc[GTK_WIDGET_STATE (map_drawable)],
450 				pixmap,
451 				0,0,
452 				0, 0,
453 				width+10,height+10);
454 
455 
456 			if(gpsdata->fix.speed>0.01 && gpsdata->valid)
457 				gdk_draw_layout(map_drawable->window,
458 						gc,
459 						x, y,
460 						layout);
461 
462 
463 			pango_layout_get_pixel_size(layout, &width, &height);
464 		}
465 
466 		speed_tmp = floor(gpsdata->fix.speed*3.6*unit_conv);
467 
468 		g_free(buffer);
469 		pango_font_description_free (desc);
470 		g_object_unref (layout);
471 		g_object_unref (gc);
472 	}
473 }
474 
475 void
set_label_newmsg()476 set_label_newmsg()
477 {
478 	static GtkLabel *label = NULL;
479 
480 	if (label == NULL)
481 	{
482 		label = GTK_LABEL(lookup_widget(window1, "label4"));
483 	}
484 
485 	gtk_label_set_label (label,
486 	                     _("<span foreground='#ff0000'><b>"
487 	                       "New Message arrived. Click here."
488 	                       "</b></span>"));
489 }
490 
491 void
set_label_nogps()492 set_label_nogps()
493 {
494 	static GtkLabel *label=NULL;
495 	static gchar buffer[BUFSIZE];
496 	int num_dl_threads = 0;
497 
498 	if(label == NULL)
499 		label   = GTK_LABEL(lookup_widget(window1, "label4"));
500 
501 	num_dl_threads = update_thread_number(0);
502 	if(num_dl_threads && !global_tiles_in_dl_queue)
503 	{
504 		g_snprintf (buffer, BUFSIZE,
505 		            _("<b>no GPSD found</b>"
506 		              " - "
507 		              "<span foreground='#0000ff'><b>D%d</b></span>"),
508 			num_dl_threads);
509 	}
510 	else if (num_dl_threads && global_tiles_in_dl_queue)
511 		g_snprintf (buffer, BUFSIZE,
512 		            _("<b>no GPSD found</b>"
513 		              " - "
514 		              "<span foreground='#0000ff'><b>D%d</b></span>"
515 		              " - "
516 		              "<b>[%d]</b>"),
517 			num_dl_threads, global_tiles_in_dl_queue);
518 	else
519 		g_snprintf (buffer, BUFSIZE, _("<b>no GPSD found</b>"));
520 
521 	gtk_label_set_label(label, buffer);
522 
523 }
524 void
set_label()525 set_label()
526 {
527 	static GtkLabel *label=NULL,   *label31, *label38, *label39;
528 	static GtkLabel *label41, *label42, *label43, *label45;
529 	static GtkLabel *label66, *label68, *label70;
530 	static gchar buffer[BUFSIZE];
531 	static gchar numdl_buf[64], dl_buf[64], ff_buf[64], tr_buf[64];
532 	static gchar speedunit[5], distunit[3], altunit[3];
533 	int trip_hours, trip_minutes, trip_seconds;
534 	int num_dl_threads = 0;
535 	time_t time_sec;
536 	struct tm  *ts;
537 	double unit_conv = 1, unit_conv_alt = 1;
538 
539 	osd_speed(FALSE);
540 
541 	if(global_speed_unit==1)
542 	{
543 		unit_conv = 1.0/1.609344;
544 		g_sprintf(speedunit, "%s","mph");
545 		g_sprintf(distunit, "%s", "m");
546 	}
547 	else if(global_speed_unit==2)
548 	{
549 		unit_conv = 1.0/1.852;
550 		g_sprintf(speedunit, "%s","kn");
551 		g_sprintf(distunit, "%s", "NM");
552 	}
553 	else
554 	{
555 		g_sprintf(speedunit, "%s","km/h");
556 		g_sprintf(distunit, "%s", "km");
557 	}
558 
559 
560 	if(global_alt_unit==1)
561 	{
562 		unit_conv_alt = 1.0/0.3048;
563 		g_sprintf(altunit, "%s", "ft");
564 	}
565 	else
566 		g_sprintf(altunit, "%s", "m");
567 
568 	if(global_auto_download)
569 		g_sprintf(dl_buf, "%s", "");
570 	else
571 		g_sprintf(dl_buf, "%s", "<span foreground='#ff0000'><b>!</b></span>");
572 
573 	if (global_fftimer_running)
574 		g_sprintf(ff_buf, "%s", "<span foreground='#00e000'><b>f</b></span>");
575 	else
576 		g_sprintf(ff_buf, "%s", "");
577 
578 	if (trip_logger_on)
579 		g_sprintf(tr_buf, "%s", "<span foreground='#00e000'><b>t</b></span>");
580 	else
581 		g_sprintf(tr_buf, "%s", "");
582 
583 	if(label == NULL)
584 	{
585 		label   = GTK_LABEL(lookup_widget(window1, "label4"));
586 		label45 = GTK_LABEL(lookup_widget(window1, "label45"));
587 		label41 = GTK_LABEL(lookup_widget(window1, "label41"));
588 		label31 = GTK_LABEL(lookup_widget(window1, "label31"));
589 		label38 = GTK_LABEL(lookup_widget(window1, "label38"));
590 		label39 = GTK_LABEL(lookup_widget(window1, "label39"));
591 		label42 = GTK_LABEL(lookup_widget(window1, "label42"));
592 		label43 = GTK_LABEL(lookup_widget(window1, "label43"));
593 		label66 = GTK_LABEL(lookup_widget(window1, "label66"));
594 		label68 = GTK_LABEL(lookup_widget(window1, "label68"));
595 		label70 = GTK_LABEL(lookup_widget(window1, "label70"));
596 	}
597 
598 
599 
600 
601 
602 	num_dl_threads = update_thread_number(0);
603 
604 	if(num_dl_threads && !global_tiles_in_dl_queue)
605 		g_sprintf(numdl_buf, "<span foreground='#0000ff'><b>D%d</b></span> ",
606 			  num_dl_threads);
607 	else if (num_dl_threads && global_tiles_in_dl_queue)
608 		g_sprintf(numdl_buf, "<span foreground='#0000ff'><b>D%d</b></span>-%d ",
609 			  num_dl_threads, global_tiles_in_dl_queue);
610 	else
611 		g_sprintf(numdl_buf, "%s", "");
612 
613 
614 	g_snprintf(buffer, BUFSIZE,
615 	           _("%s%s%s%s<b>%4.1f</b>%s "
616 	             "<small>trp </small><b>%.2f</b>%s "
617 	             "<small>alt </small><b>%.0f</b>%s "
618 	             "<small>hdg </small><b>%.0f</b>° "
619 	             "<small></small>%d/%.1f"),
620 	             numdl_buf, dl_buf, tr_buf, ff_buf,
621 	             gpsdata->fix.speed * 3.6 * unit_conv, speedunit,
622 	             trip_distance * unit_conv, distunit,
623 	             gpsdata->fix.altitude * unit_conv_alt, altunit,
624 	             gpsdata->fix.heading,
625 	             gpsdata->satellites_used,
626 	             gpsdata->hdop);
627 
628 	gtk_label_set_label(label, buffer);
629 
630 
631 	if(global_infopane_visible)
632 	{
633 
634 
635 
636 
637 
638 		time_sec = (time_t)gpsdata->fix.time;
639 		ts = localtime(&time_sec);
640 
641 
642 		strftime(buffer, sizeof(buffer), "<big><b>%a %Y-%m-%d %H:%M:%S</b></big>", ts);
643 		gtk_label_set_label(label41,buffer);
644 
645 
646 		switch (global_latlon_unit)
647 		{
648 			case 0:
649 				g_snprintf(buffer, BUFSIZE, "<big><b>%f - %f</b></big>", gpsdata->fix.latitude, gpsdata->fix.longitude);
650 				break;
651 			case 1:
652 				g_snprintf(buffer, BUFSIZE, "<big><b>%s   %s</b></big>",
653 					  latdeg2latmin(gpsdata->fix.latitude),
654 					  londeg2lonmin(gpsdata->fix.longitude));
655 				break;
656 			case 2:
657 				g_snprintf(buffer, BUFSIZE, "<big><b>%s   %s</b></big>",
658 					  latdeg2latsec(gpsdata->fix.latitude),
659 					  londeg2lonsec(gpsdata->fix.longitude));
660 		}
661 		gtk_label_set_label(label31,buffer);
662 
663 
664 		g_snprintf(buffer, BUFSIZE,
665 			"<b><span foreground='#0000ff'><span font_desc='50'>%.1f</span></span></b> %s",
666 			gpsdata->fix.speed*3.6*unit_conv, speedunit);
667 		gtk_label_set_label(label38,buffer);
668 
669 
670 		g_snprintf(buffer, BUFSIZE, "<big><b>%.1f %s</b></big>", gpsdata->fix.altitude * unit_conv_alt, altunit);
671 		gtk_label_set_label(label39,buffer);
672 
673 
674 		g_snprintf(buffer, BUFSIZE, "<big><b>%.1f°</b></big> ", gpsdata->fix.heading);
675 		gtk_label_set_label(label42,buffer);
676 
677 
678 		g_snprintf (buffer, BUFSIZE, _("<big><b>%d</b>  <small>HDOP</small><b> %.1f</b></big>"),
679 				gpsdata->satellites_used, gpsdata->hdop);
680 		gtk_label_set_label(label43,buffer);
681 
682 
683 
684 
685 
686 
687 		g_snprintf(buffer, BUFSIZE, "<big><b>%.3f</b></big> <small>%s</small>", trip_distance*unit_conv,distunit);
688 		gtk_label_set_label(label45,buffer);
689 
690 
691 
692 		trip_hours   = trip_time / 3600;
693 		trip_minutes = ((int)trip_time%3600)/60;
694 		trip_seconds = (int)trip_time % 60;
695 
696 		if (trip_seconds < 10 && trip_minutes < 10)
697 		{
698 			g_sprintf(buffer, "<big><b>%d:0%d:0%d</b></big>",trip_hours,trip_minutes,trip_seconds);
699 		}
700 		else if (trip_seconds < 10)
701 			g_sprintf(buffer, "<big><b>%d:%d:0%d</b></big>",trip_hours,trip_minutes,trip_seconds);
702 		else if (trip_minutes < 10)
703 			g_sprintf(buffer, "<big><b>%d:0%d:%d</b></big>",trip_hours,trip_minutes,trip_seconds);
704 		else
705 			g_sprintf(buffer, "<big><b>%d:%d:%d</b></big>",trip_hours,trip_minutes,trip_seconds);
706 
707 		gtk_label_set_label(label66,buffer);
708 
709 
710 		g_sprintf(buffer, "<big><b>%.1f</b></big><small> %s</small>", trip_distance*3600*unit_conv/(trip_time+2.0), speedunit);
711 		gtk_label_set_label(label68,buffer);
712 
713 
714 		g_sprintf(buffer, "<big><b>%.1f</b></big><small> %s</small>", trip_maxspeed*3.6*unit_conv, speedunit);
715 		gtk_label_set_label(label70,buffer);
716 	}
717 }
718 
719 
720 
721 
722 
723 static gboolean
cb_gpsd_io_error(GIOChannel * src,GIOCondition condition,gpointer data)724 cb_gpsd_io_error(GIOChannel *src, GIOCondition condition, gpointer data)
725 {
726 	reset_gpsd_io();
727 
728 	return FALSE;
729 }
730 
731 
732 static double
timespec_to_double(struct timespec ts)733 timespec_to_double(struct timespec ts)
734 {
735 	return ((double)(ts.tv_sec) + ((double)(ts.tv_nsec) / 1e9));
736 }
737 
738 static gboolean
cb_gpsd_data(GIOChannel * src,GIOCondition condition,gpointer data)739 cb_gpsd_data(GIOChannel *src, GIOCondition condition, gpointer data)
740 {
741 	int ret;
742 
743 	if (!libgps_initialized)
744 		return FALSE;
745 
746 #if GPSD_API_MAJOR_VERSION >= 7 /* API change. gpsd version 3.18 and subsequent. */
747 	ret = gps_read(&libgps_gpsdata, NULL, 0);
748 #else
749 	ret = gps_read(&libgps_gpsdata);
750 #endif
751 	/* Note that gps_read() will never actually return 0
752 	   (zero-length reads are converted internally to a -1 return,
753 	    since they mean that the connection to the daemon has closed),
754 	   and gps_poll() will never return >0, but both will return
755 	   <0 to indicate failure; hence the following ">= 0" check:
756 	*/
757 	if (ret >= 0)
758 	{
759 		gpsdata->satellites_used = libgps_gpsdata.satellites_used;
760 		gpsdata->hdop = libgps_gpsdata.dop.hdop;
761 		gpsdata->fix.time = timespec_to_double(libgps_gpsdata.fix.time);
762 		if (isnan(gpsdata->fix.time))
763 		{
764 			gpsdata->fix.time = (time_t) 0;
765 		}
766 		gpsdata->valid = (libgps_gpsdata.status != STATUS_NO_FIX);
767 		if (gpsdata->valid)
768 		{
769 			gpsdata->seen_valid = TRUE;
770 			gpsdata->fix.mode = libgps_gpsdata.fix.mode;
771 			gpsdata->fix.latitude = libgps_gpsdata.fix.latitude;
772 			gpsdata->fix.longitude = libgps_gpsdata.fix.longitude;
773 			gpsdata->fix.speed = libgps_gpsdata.fix.speed;
774 			gpsdata->fix.heading = libgps_gpsdata.fix.track;
775 			gpsdata->fix.altitude = libgps_gpsdata.fix.altitude;
776 		}
777 
778 		g_source_remove(watchdog);
779 		watchdog = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT_IDLE,60,reset_gpsd_io,NULL,NULL);
780 	}
781 	else
782 	{
783 		fprintf (stderr, _("connection to gpsd LOST\n"));
784 		return cb_gpsd_io_error(src, condition, data);
785 	}
786 	return TRUE;
787 }
788 
789 
790 void
get_gps()791 get_gps()
792 {
793 	/* Set this flag to FALSE *immediately* so that a slow gps_open()
794 	   doesn't cause successive cb_gps_timer() callbacks to call
795 	   us *again* before we've even finished *this* invocation--
796 	   which would create multiple, simultaneous get_gps_thread()
797 	   threads and all sorts of associated problems:
798 	*/
799 	reconnect_gpsd = FALSE;
800 
801 	if (gps_timer) {
802 		/* Disable the regularly scheduled callback to cb_gps_timer()
803 		   until after get_gps_thread() has returned, to guard against
804 		   the situation described above when reconnect_gpsd
805 		   is re-set by something else (e.g.: the user bouncing
806 		   on the `Change GPSD' button):
807 		*/
808 		g_source_remove (gps_timer);
809 		gps_timer = 0;
810 	}
811 
812 	if (watchdog) {
813 		g_source_remove(watchdog);
814 	}
815 
816 	if (sid1) {
817 		g_source_remove(sid1);
818 		sid1 = 0;
819 	}
820 
821 	if (sid3) {
822 		g_source_remove(sid3);
823 		sid3 = 0;
824 	}
825 
826 	if (gpsd_io_channel) {
827 		g_io_channel_unref (gpsd_io_channel);
828 		gpsd_io_channel = NULL;
829 	}
830 
831 	/* Note that we're *not* free'ing the internal gpsdata structure,
832 	   ever. We'd only immediately reallocate it, so it's not a net win
833 	   in terms of memory-footprint; and it doesn't contain references
834 	   to any file-descriptors or other ephemeral resources, so
835 	   the only thing we'd be doing by re-initialising it would be
836 	   throwing away our last known fix, etc.
837 	*/
838 
839 	if (libgps_initialized) {
840 		gps_close(&libgps_gpsdata);
841 		libgps_initialized = FALSE;
842 	}
843 
844 #if GLIB_CHECK_VERSION(2,34,0)
845 	g_thread_new("gps thread", &get_gps_thread, (gpointer)NULL);
846 #else
847 	g_thread_create(&get_gps_thread, NULL, FALSE, NULL);
848 #endif
849 }
850 
851 static void *
get_gps_thread(void * ptr)852 get_gps_thread(void *ptr)
853 {
854 	if (gps_open(global_server, global_port, &libgps_gpsdata) == 0)
855 	{
856 		fprintf (stderr, _("connection to gpsd SUCCEEDED \n"));
857 
858 		libgps_initialized = TRUE;
859 
860 		/* Unless someone has re-set reconnect_gpsd
861 		   between when get_gps() set it and now,
862 		   then it should still be FALSE; if someone else
863 		   *did* re-set it, then they did it for a reason.
864 
865 		   Either way, we're better off leaving it alone,
866 		   here.
867 		*/
868 
869 		if(!gpsdata)
870 		{
871 			gpsdata = g_new0(tangogps_gps_data_t,1);
872 		}
873 
874 
875 		gps_stream(&libgps_gpsdata, WATCH_ENABLE, NULL);
876 
877 		watchdog = g_timeout_add_seconds_full(G_PRIORITY_DEFAULT_IDLE,60,reset_gpsd_io,NULL,NULL);
878 
879 
880 		gpsd_io_channel = g_io_channel_unix_new(libgps_gpsdata.gps_fd);
881 		g_io_channel_set_flags(gpsd_io_channel, G_IO_FLAG_NONBLOCK, NULL);
882 
883 
884 		sid1 = g_io_add_watch_full(gpsd_io_channel, G_PRIORITY_HIGH_IDLE+200, G_IO_ERR | G_IO_HUP, cb_gpsd_io_error, NULL, NULL);
885 
886 
887 		sid3 = g_io_add_watch_full(gpsd_io_channel, G_PRIORITY_HIGH_IDLE+200, G_IO_IN | G_IO_PRI, cb_gpsd_data, NULL, NULL);
888 
889 	} else {
890 		/* Failure. Maybe it's transient--try again
891 		   on the next cycle: */
892 		reconnect_gpsd = TRUE;
893 	}
894 
895 	gps_timer = g_timeout_add (1000, cb_gps_timer, NULL);
896 
897 	return NULL;
898 }
899 
900 void
map_scale_indicator()901 map_scale_indicator()
902 {
903 	int y, width, height, max_bar_length=250;
904 	float distance, factor, lat, lon1, lon2;
905 	char *buffer=NULL;
906 	GdkColor color;
907 	static GdkGC *gc=NULL, *gc1=NULL;
908 
909 	PangoContext		*context = NULL;
910 	PangoLayout		*layout  = NULL;
911 	PangoFontDescription	*desc    = NULL;
912 
913 	y = map_drawable->allocation.height - 8;
914 
915 	if(gc == NULL)
916 	{
917 		gc   = gdk_gc_new(pixmap);
918 		gc1  = gdk_gc_new(pixmap);
919 	}
920 	color.red   = 0;
921 	color.green = 0;
922 	color.blue  = 0;
923 
924 	gdk_gc_set_rgb_fg_color(gc, &color);
925 	gdk_gc_set_line_attributes(gc,
926 	                           5, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);
927 
928 	color.red   = 65000;
929 	color.green = 65000;
930 	color.blue  = 65000;
931 
932 	gdk_gc_set_rgb_fg_color(gc1, &color);
933 	gdk_gc_set_line_attributes(gc1,
934 	                           3, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);
935 
936 
937 
938 	lat   = pixel2lat(global_zoom, global_y+y);
939 	lon1  = pixel2lon(global_zoom, 0);
940 	lon2  = pixel2lon(global_zoom, max_bar_length);
941 
942 	distance = get_distance(lat, lon1, lat, lon2);
943 
944 	buffer = distance2scale(distance, &factor);
945 	max_bar_length *= factor;
946 
947 	gdk_draw_line(map_drawable->window, gc, 4, y, max_bar_length+6, y);
948 	gdk_draw_line(map_drawable->window, gc1,5, y, max_bar_length+5, y);
949 
950 
951 	context = gtk_widget_get_pango_context (map_drawable);
952 	layout  = pango_layout_new (context);
953 	desc    = pango_font_description_new();
954 
955 	pango_font_description_set_absolute_size (desc, 12 * PANGO_SCALE);
956 	pango_layout_set_font_description (layout, desc);
957 	pango_layout_set_text (layout, buffer, strlen(buffer));
958 
959 
960 
961 	pango_layout_get_pixel_size(layout, &width, &height);
962 
963 
964 
965 	gdk_gc_set_line_attributes(gc,
966 	                           height+2, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);
967 
968 	gdk_gc_set_line_attributes(gc1,
969 	                           height, GDK_LINE_SOLID, GDK_CAP_BUTT, GDK_JOIN_ROUND);
970 
971 	gdk_draw_line(map_drawable->window, gc1, 22, y-height/2+6, 20+width+6, y-height/2+6);
972 
973 
974 
975 	gdk_draw_layout(map_drawable->window,
976 	                gc,
977 	                25, y-height+7,
978 	                layout);
979 
980 
981 
982 	g_free(buffer);
983 	pango_font_description_free (desc);
984 	g_object_unref (layout);
985 
986 
987 
988 }
989 
990 char *
distance2scale(float distance,float * factor)991 distance2scale(float distance, float *factor)
992 {
993 	float unit_conv=1;
994 	char *buf = NULL;
995 	char unit[5];
996 
997 	switch (global_speed_unit)
998 	{
999 		case METRICAL:
1000 			unit_conv = 1.0;
1001 			strncpy(unit, "km", 3);
1002 			break;
1003 		case IMPERIAL :
1004 			unit_conv = 1.0/1.609344;
1005 			strncpy(unit, "m", 2);
1006 			break;
1007 		case NAUTICAL :
1008 			unit_conv = 1.0 / 1.852;
1009 			strncpy(unit, "NM", 3);
1010 			break;
1011 	}
1012 
1013 	distance *= unit_conv;
1014 	if (distance >= 5000) {
1015 		buf = g_strconcat("5000", unit, NULL);
1016 		*factor = 5000/distance;
1017 	}
1018 	else if (distance < 5000 && distance >= 2000) {
1019 		buf = g_strconcat("2000", unit, NULL);
1020 		*factor = 2000/distance;
1021 	}
1022 	else if (distance < 2000 && distance >= 1000) {
1023 		buf = g_strconcat("1000", unit, NULL);
1024 		*factor = 1000/distance;
1025 	}
1026 	else if (distance < 1000 && distance >= 500) {
1027 		buf = g_strconcat("500", unit, NULL);
1028 		*factor = 500/distance;
1029 	}
1030 	else if (distance < 500 && distance >= 200) {
1031 		buf = g_strconcat("200", unit, NULL);
1032 		*factor = 200/distance;
1033 	}
1034 	else if (distance < 200 && distance >= 100) {
1035 		buf = g_strconcat("100", unit, NULL);
1036 		*factor = 100/distance;
1037 	}
1038 	else if (distance < 100 && distance >= 50) {
1039 		buf = g_strconcat("50", unit, NULL);
1040 		*factor = 50/distance;
1041 	}
1042 	else if (distance < 50 && distance >= 20) {
1043 		buf = g_strconcat("20", unit, NULL);
1044 		*factor = 20/distance;
1045 	}
1046 	else if (distance < 20 && distance >= 10) {
1047 		buf = g_strconcat("10", unit, NULL);
1048 		*factor = 10/distance;
1049 	}
1050 	else if (distance < 10 && distance >= 5) {
1051 		buf = g_strconcat("5", unit, NULL);
1052 		*factor = 5/distance;
1053 	}
1054 	else if (distance < 5 && distance >= 2) {
1055 		buf = g_strconcat("2", unit, NULL);
1056 		*factor = 2/distance;
1057 	}
1058 	else if (distance < 2 && distance >= 1) {
1059 		buf = g_strconcat("1", unit, NULL);
1060 		*factor = 1/distance;
1061 	}
1062 	else if(global_speed_unit == METRICAL)
1063 	{
1064 		if (distance < 1 && distance >= 0.5) {
1065 			buf = g_strdup("500m");
1066 			*factor = 0.5/distance;
1067 		}
1068 		else if (distance < 0.5 && distance >= 0.2) {
1069 			buf = g_strdup("200m");
1070 			*factor = 0.2/distance;
1071 		}
1072 		else if (distance < 0.2 && distance >= 0.1) {
1073 			buf = g_strdup("100m");
1074 			*factor = 0.1/distance;
1075 		}
1076 		else if (distance < 0.1 && distance >= 0.05) {
1077 			buf = g_strdup("50m");
1078 			*factor = 0.05/distance;
1079 		}
1080 		else if (distance < 0.05 && distance >= 0.02) {
1081 			buf = g_strdup("20m");
1082 			*factor = 0.02/distance;
1083 		}
1084 		else {
1085 			buf = g_strdup("10m");
1086 			*factor = 0.01/distance;
1087 		}
1088 	}
1089 	else if(global_speed_unit == IMPERIAL)
1090 	{
1091 		distance *= 5280;
1092 		if (distance >= 5000) {
1093 			buf = g_strdup("5000ft");
1094 			*factor = 5000/distance;
1095 		}
1096 		else if (distance < 5000 && distance >= 2000) {
1097 			buf = g_strdup("2000ft");
1098 			*factor = 2000/distance;
1099 		}
1100 		else if (distance < 2000 && distance >= 1000) {
1101 			buf = g_strdup("1000ft");
1102 			*factor = 1000/distance;
1103 		}
1104 		else if (distance < 1000 && distance >= 500) {
1105 			buf = g_strdup("500ft");
1106 			*factor = 500/distance;
1107 		}
1108 		else if (distance < 500 && distance >= 200) {
1109 			buf = g_strdup("200ft");
1110 			*factor = 200/distance;
1111 		}
1112 		else {
1113 			buf = g_strdup("100ft");
1114 			*factor = 100/distance;
1115 		}
1116 	}
1117 	else if(global_speed_unit == NAUTICAL)
1118 	{
1119 		if (distance < 1 && distance >= 0.5) {
1120 			buf = g_strdup("0.5NM");
1121 			*factor = 0.5/distance;
1122 		}
1123 		else if (distance < 0.5 && distance >= 0.2) {
1124 			buf = g_strdup("0.2NM");
1125 			*factor = 0.2/distance;
1126 		}
1127 		else if (distance < 0.2 && distance >= 0.1) {
1128 			buf = g_strdup("0.1NM");
1129 			*factor = 0.1/distance;
1130 		}
1131 		else if (distance < 0.1 && distance >= 0.05) {
1132 			buf = g_strdup("0.05NM");
1133 			*factor = 0.05/distance;
1134 		}
1135 		else if (distance < 0.05 && distance >= 0.02) {
1136 			buf = g_strdup("0.02NM");
1137 			*factor = 0.02/distance;
1138 		}
1139 		else {
1140 			buf = g_strdup("0.01NM");
1141 			*factor = 0.01/distance;
1142 		}
1143 	}
1144 
1145 	if(!buf)
1146 		buf=g_strdup("bingo");
1147 
1148 	return buf;
1149 }
1150