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