Fix:Core:Renamed src to navit for cleanup of includes
[navit-package] / navit / osd / core / osd_core.c
1 #include <math.h>
2 #include <stdio.h>
3 #include <glib.h>
4 #include <time.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include "config.h"
8 #include "item.h"
9 #include "point.h"
10 #include "coord.h"
11 #include "graphics.h"
12 #include "transform.h"
13 #include "route.h"
14 #include "navit.h"
15 #include "plugin.h"
16 #include "debug.h"
17 #include "callback.h"
18 #include "color.h"
19 #include "vehicle.h"
20 #include "navigation.h"
21 #include "track.h"
22 #include "map.h"
23
24 struct compass {
25         struct point p;
26         int w,h;
27         struct graphics *gr;
28         struct graphics_gc *bg;
29         struct graphics_gc *white;
30         struct graphics_gc *green;
31         struct graphics_font *font;
32 };
33
34
35 static void
36 transform_rotate(struct point *center, int angle, struct point *p, int count)
37 {
38         int i,x,y;
39         double dx,dy;
40         for (i = 0 ; i < count ; i++)
41         {
42                 dx=sin(M_PI*angle/180.0);
43                 dy=cos(M_PI*angle/180.0);
44                 x=dy*p->x-dx*p->y;      
45                 y=dx*p->x+dy*p->y;
46                         
47                 p->x=center->x+x;
48                 p->y=center->y+y;
49                 p++;
50         }
51 }
52
53 static void
54 handle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r, int dir)
55 {
56         struct point ph[3];
57         int l=r*0.4;
58
59         ph[0].x=0;
60         ph[0].y=r;
61         ph[1].x=0;
62         ph[1].y=-r;
63         transform_rotate(p, dir, ph, 2);
64         graphics_draw_lines(gr, gc, ph, 2);
65         ph[0].x=-l;
66         ph[0].y=-r+l;
67         ph[1].x=0;
68         ph[1].y=-r;
69         ph[2].x=l;
70         ph[2].y=-r+l;
71         transform_rotate(p, dir, ph, 3);
72         graphics_draw_lines(gr, gc, ph, 3);
73 }
74
75 static void
76 format_distance(char *buffer, double distance)
77 {
78         if (distance >= 100000)
79                 sprintf(buffer,"%.0f km", distance/1000);
80         else if (distance >= 10000)
81                 sprintf(buffer,"%.1f km", distance/1000);
82         else if (distance >= 300)
83                 sprintf(buffer,"%.0f m", round(distance/25)*25);
84         else if (distance >= 50) 
85                 sprintf(buffer,"%.0f m", round(distance/10)*10);
86         else if (distance >= 10) 
87                 sprintf(buffer,"%.0f m", distance);
88         else
89                 sprintf(buffer,"%.1f m", distance);
90 }
91
92 static void
93 osd_compass_draw(struct compass *this, struct navit *nav, struct vehicle *v)
94 {
95         struct point p;
96         struct attr attr_dir, destination_attr, position_attr;
97         double dir,vdir=0;
98         char buffer[16];
99         struct coord c1, c2;
100         enum projection pro;
101
102         graphics_draw_mode(this->gr, draw_mode_begin);
103         p.x=0;
104         p.y=0;
105         graphics_draw_rectangle(this->gr, this->bg, &p, this->w, this->h);
106         p.x=30;
107         p.y=30;
108         graphics_draw_circle(this->gr, this->white, &p, 50);
109         if (v && vehicle_get_attr(v, attr_position_direction, &attr_dir)) {
110                 vdir=*attr_dir.u.numd;
111                 handle(this->gr, this->white, &p, 20, -vdir);
112         }
113         if (navit_get_attr(nav, attr_destination, &destination_attr, NULL) && v && vehicle_get_attr(v, attr_position_coord_geo, &position_attr)) {
114                 pro=destination_attr.u.pcoord->pro;
115                 transform_from_geo(pro, position_attr.u.coord_geo, &c1);
116                 c2.x=destination_attr.u.pcoord->x;
117                 c2.y=destination_attr.u.pcoord->y;
118                 dir=atan2(c2.x-c1.x,c2.y-c1.y)*180.0/M_PI;
119                 dir-=vdir;
120                 handle(this->gr, this->green, &p, 20, dir);
121                 format_distance(buffer, transform_distance(pro, &c1, &c2));
122                 p.x=8;
123                 p.y=72;
124                 graphics_draw_text(this->gr, this->green, NULL, this->font, buffer, &p, 0x10000, 0);
125         }
126         graphics_draw_mode(this->gr, draw_mode_end);
127 }
128
129 static void
130 osd_compass_init(struct compass *this, struct navit *nav)
131 {
132         struct graphics *navit_gr;
133         struct color c;
134         navit_gr=navit_get_graphics(nav);
135         this->gr=graphics_overlay_new(navit_gr, &this->p, this->w, this->h);
136
137         this->bg=graphics_gc_new(this->gr);
138         c.r=0; c.g=0; c.b=0;
139         graphics_gc_set_foreground(this->bg, &c);
140
141         this->white=graphics_gc_new(this->gr);
142         c.r=65535; c.g=65535; c.b=65535;
143         graphics_gc_set_foreground(this->white, &c);
144         graphics_gc_set_linewidth(this->white, 2);
145
146         this->green=graphics_gc_new(this->gr);
147         c.r=0; c.g=65535; c.b=0;
148         graphics_gc_set_foreground(this->green, &c);
149         graphics_gc_set_linewidth(this->green, 2);
150
151         this->font=graphics_font_new(this->gr, 200, 1);
152         navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_compass_draw), attr_position_coord_geo, this));
153
154         osd_compass_draw(this, nav, NULL);
155 }
156
157 static struct osd_priv *
158 osd_compass_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
159 {
160         struct compass *this=g_new0(struct compass, 1);
161         struct attr *attr;
162         this->p.x=20;
163         this->p.y=20;
164         this->w=60;
165         this->h=80;
166         attr=attr_search(attrs, NULL, attr_x);
167         if (attr)
168                 this->p.x=attr->u.num;
169         attr=attr_search(attrs, NULL, attr_y);
170         if (attr)
171                 this->p.y=attr->u.num;
172         navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_compass_init), attr_navit, this));
173         return (struct osd_priv *) this;
174 }
175
176 struct eta {
177         struct point p;
178         int w,h;
179         struct graphics *gr;
180         struct graphics_gc *bg;
181         struct graphics_gc *white;
182         struct graphics_font *font;
183         struct graphics_image *flag;
184         int active;
185         char last_eta[16];
186         char last_distance[16];
187 };
188
189 static void
190 osd_eta_draw(struct eta *this, struct navit *navit, struct vehicle *v)
191 {
192         struct point p;
193         char eta[16];
194         char distance[16];
195         int days=0,do_draw=0;
196         time_t etat;
197         struct tm tm,eta_tm,eta_tm0;
198         struct attr attr;
199         struct navigation *nav=NULL;
200         struct map *map=NULL;
201         struct map_rect *mr=NULL;
202         struct item *item=NULL;
203
204
205         eta[0]='\0';
206         distance[0]='\0';
207
208         if (navit)
209                 nav=navit_get_navigation(navit);
210         if (nav)
211                 map=navigation_get_map(nav);
212         if (map)
213                 mr=map_rect_new(map, NULL);
214         if (mr)
215                 item=map_rect_get_item(mr);
216         if (item) {
217                 if (item_attr_get(item, attr_destination_length, &attr)) {
218                         format_distance(distance, attr.u.num);
219                 }
220                 if (item_attr_get(item, attr_destination_time, &attr)) {
221                         etat=time(NULL);
222                         tm=*localtime(&etat);
223                         etat+=attr.u.num/10;
224                         eta_tm=*localtime(&etat);
225                         if (tm.tm_year != eta_tm.tm_year || tm.tm_mon != eta_tm.tm_mon || tm.tm_mday != eta_tm.tm_mday) {
226                                 eta_tm0=eta_tm;
227                                 eta_tm0.tm_sec=0;
228                                 eta_tm0.tm_min=0;
229                                 eta_tm0.tm_hour=0;
230                                 tm.tm_sec=0;
231                                 tm.tm_min=0;
232                                 tm.tm_hour=0;
233                                 days=(mktime(&eta_tm0)-mktime(&tm)+43200)/86400;
234                         }
235                         if (days) 
236                                 sprintf(eta, "%d+%02d:%02d", days, eta_tm.tm_hour, eta_tm.tm_min);
237                         else
238                                 sprintf(eta, "  %02d:%02d", eta_tm.tm_hour, eta_tm.tm_min);
239                 }
240                 if (this->active != 1 || strcmp(this->last_distance, distance) || strcmp(this->last_eta, eta)) {
241                         this->active=1;
242                         strcpy(this->last_distance, distance);
243                         strcpy(this->last_eta, eta);
244                         do_draw=1;
245                 }
246         } else {
247                 if (this->active != 0) {
248                         this->active=0;
249                         do_draw=1;
250                 }
251         }
252         if (mr)
253                 map_rect_destroy(mr);
254
255         if (do_draw) {
256                 graphics_draw_mode(this->gr, draw_mode_begin);
257                 p.x=0;
258                 p.y=0;
259                 graphics_draw_rectangle(this->gr, this->bg, &p, this->w, this->h);
260                 p.x=6;
261                 p.y=6;
262                 if (this->flag)
263                         graphics_draw_image(this->gr, this->white, &p, this->flag);
264                 if (eta[0]) {
265                         p.x=28;
266                         p.y=28;
267                         graphics_draw_text(this->gr, this->white, NULL, this->font, "ETA", &p, 0x10000, 0);
268                         p.x=6;
269                         p.y=42;
270                         graphics_draw_text(this->gr, this->white, NULL, this->font, eta, &p, 0x10000, 0);
271                 }
272                 if (distance[0]) {
273                         p.x=6;
274                         p.y=56;
275                         graphics_draw_text(this->gr, this->white, NULL, this->font, distance, &p, 0x10000, 0);
276                 }
277                 graphics_draw_mode(this->gr, draw_mode_end);
278         }       
279 }
280
281 static void
282 osd_eta_init(struct eta *this, struct navit *nav)
283 {
284         struct graphics *navit_gr;
285         struct color c;
286         char *flag=g_strjoin(NULL,getenv("NAVIT_SHAREDIR"), "/xpm/flag_wh_bk.xpm", NULL);
287         navit_gr=navit_get_graphics(nav);
288         this->gr=graphics_overlay_new(navit_gr, &this->p, this->w, this->h);
289
290         this->bg=graphics_gc_new(this->gr);
291         c.r=0; c.g=0; c.b=0;
292         graphics_gc_set_foreground(this->bg, &c);
293
294         this->white=graphics_gc_new(this->gr);
295         c.r=65535; c.g=65535; c.b=65535;
296         graphics_gc_set_foreground(this->white, &c);
297         graphics_gc_set_linewidth(this->white, 2);
298
299         this->font=graphics_font_new(this->gr, 200, 1);
300         this->flag=graphics_image_new(this->gr, flag);
301         navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_eta_draw), attr_position_coord_geo, this));
302
303         osd_eta_draw(this, nav, NULL);
304         g_free(flag);
305 }
306
307 static struct osd_priv *
308 osd_eta_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
309 {
310         struct eta *this=g_new0(struct eta, 1);
311         struct attr *attr;
312         this->p.x=-80;
313         this->p.y=20;
314         this->w=60;
315         this->h=60;
316         this->active=-1;
317         attr=attr_search(attrs, NULL, attr_x);
318         if (attr)
319                 this->p.x=attr->u.num;
320         attr=attr_search(attrs, NULL, attr_y);
321         if (attr)
322                 this->p.y=attr->u.num;
323         navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_eta_init), attr_navit, this));
324         return (struct osd_priv *) this;
325 }
326
327 struct osd_navigation {
328         struct point p;
329         int w,h;
330         struct graphics *gr;
331         struct graphics_gc *bg;
332         struct graphics_gc *white;
333         struct graphics_font *font;
334         int active;
335         char last_distance[16];
336         char *last_name;
337 };
338
339 static void
340 osd_navigation_draw(struct osd_navigation *this, struct navit *navit, struct vehicle *v)
341 {
342         struct point p;
343         char distance[16];
344         int do_draw=0;
345         struct attr attr;
346         struct navigation *nav=NULL;
347         struct map *map=NULL;
348         struct map_rect *mr=NULL;
349         struct item *item=NULL;
350         struct graphics_image *gr_image;
351         char *image;
352         char *name="unknown";
353
354         distance[0]='\0';
355
356         if (navit)
357                 nav=navit_get_navigation(navit);
358         if (nav)
359                 map=navigation_get_map(nav);
360         if (map)
361                 mr=map_rect_new(map, NULL);
362         if (mr)
363                 item=map_rect_get_item(mr);
364         if (item) {
365                 name=item_to_name(item->type);
366                 dbg(1,"name=%s\n", name);
367                 if (item_attr_get(item, attr_length, &attr)) {
368                         format_distance(distance, attr.u.num);
369                 }
370                 if (this->active != 1 || strcmp(this->last_distance, distance) || this->last_name != name) {
371                         this->active=1;
372                         strcpy(this->last_distance, distance);
373                         this->last_name=name;
374                         do_draw=1;
375                 }
376         } else {
377                 if (this->active != 0) {
378                         this->active=0;
379                         do_draw=1;
380                 }
381         }
382         if (mr)
383                 map_rect_destroy(mr);
384
385         if (do_draw) {
386                 graphics_draw_mode(this->gr, draw_mode_begin);
387                 p.x=0;
388                 p.y=0;
389                 graphics_draw_rectangle(this->gr, this->bg, &p, this->w, this->h);
390                 if (this->active) {
391                         image=g_strjoin(NULL,getenv("NAVIT_SHAREDIR"), "/xpm/", name, "_32.xpm", NULL);
392                         gr_image=graphics_image_new(this->gr, image);
393                         if (! gr_image) {
394                                 g_free(image);
395                                 image=g_strjoin(NULL,getenv("NAVIT_SHAREDIR"), "/xpm/unknown.xpm", NULL);
396                                 gr_image=graphics_image_new(this->gr, image);
397                         }
398                         dbg(1,"gr_image=%p\n", gr_image);
399                         if (gr_image) {
400                                 p.x=(this->w-gr_image->width)/2;
401                                 p.y=(46-gr_image->height)/2;
402                                 graphics_draw_image(this->gr, this->white, &p, gr_image);
403                                 graphics_image_free(this->gr, gr_image);
404                         }
405                         p.x=12;
406                         p.y=56;
407                         graphics_draw_text(this->gr, this->white, NULL, this->font, distance, &p, 0x10000, 0);
408                 }
409                 graphics_draw_mode(this->gr, draw_mode_end);
410         }
411 }
412
413 static void
414 osd_navigation_init(struct osd_navigation *this, struct navit *nav)
415 {
416         struct graphics *navit_gr;
417         struct color c;
418         navit_gr=navit_get_graphics(nav);
419         this->gr=graphics_overlay_new(navit_gr, &this->p, this->w, this->h);
420
421         this->bg=graphics_gc_new(this->gr);
422         c.r=0; c.g=0; c.b=0;
423         graphics_gc_set_foreground(this->bg, &c);
424
425         this->white=graphics_gc_new(this->gr);
426         c.r=65535; c.g=65535; c.b=65535;
427         graphics_gc_set_foreground(this->white, &c);
428         graphics_gc_set_linewidth(this->white, 2);
429
430         this->font=graphics_font_new(this->gr, 200, 1);
431         navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_navigation_draw), attr_position_coord_geo, this));
432
433         osd_navigation_draw(this, nav, NULL);
434 }
435
436 static struct osd_priv *
437 osd_navigation_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
438 {
439         struct osd_navigation *this=g_new0(struct osd_navigation, 1);
440         struct attr *attr;
441         this->p.x=20;
442         this->p.y=-80;
443         this->w=60;
444         this->h=60;
445         this->active=-1;
446         attr=attr_search(attrs, NULL, attr_x);
447         if (attr)
448                 this->p.x=attr->u.num;
449         attr=attr_search(attrs, NULL, attr_y);
450         if (attr)
451                 this->p.y=attr->u.num;
452         navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_navigation_init), attr_navit, this));
453         return (struct osd_priv *) this;
454 }
455
456 struct osd_street_name {
457         struct point p;
458         int w,h;
459         struct graphics *gr;
460         struct graphics_gc *bg;
461         struct graphics_gc *white;
462         struct graphics_font *font;
463         int active;
464         struct item item;
465 };
466
467 static void
468 osd_street_name_draw(struct osd_street_name *this, struct navit *navit, struct vehicle *v)
469 {
470         struct point p;
471         char distance[16];
472         int do_draw=0;
473         struct attr attr_name1, attr_name2;
474         char *name1=NULL,*name2=NULL;
475         struct tracking *tr=NULL;
476         struct map_rect *mr=NULL;
477         struct item *item=NULL;
478         char *name=NULL;
479
480         distance[0]='\0';
481         if (navit) 
482                 tr=navit_get_tracking(navit);
483         if (tr)
484                 item=tracking_get_current_item(tr);
485         dbg(1,"navit=%p tr=%p item=%p\n", navit, tr, item);
486         if (item) {
487                 if (!item_is_equal(*item, this->item)) {
488                         do_draw=1;
489                         this->item=*item;
490                         mr=map_rect_new(item->map,NULL);
491                         item=map_rect_get_item_byid(mr, item->id_hi, item->id_lo);
492                         if (item_attr_get(item, attr_street_name, &attr_name1))
493                                 name1=map_convert_string(item->map, attr_name1.u.str);
494                         if (item_attr_get(item, attr_street_name_systematic, &attr_name2))
495                                 name2=map_convert_string(item->map, attr_name2.u.str);
496                         printf("name1=%s name2=%s\n", name1, name2);
497                         map_rect_destroy(mr);
498                         if (name1 && name2)
499                                 name=g_strdup_printf("%s/%s", name2,name1);
500                         else
501                                 name=g_strdup(name1?name1:name2);
502                         map_convert_free(name1);
503                         map_convert_free(name2);
504                         this->active=1;
505                 }
506         } else {
507                 if (this->item.map || this->active)
508                         do_draw=1;
509                 this->active=0;
510                 memset(&this->item, 0, sizeof(this->item));
511                 name=NULL;
512         }
513         if (do_draw) {
514                 dbg(1,"name=%s\n", name);
515                 graphics_draw_mode(this->gr, draw_mode_begin);
516                 p.x=0;
517                 p.y=0;
518                 graphics_draw_rectangle(this->gr, this->bg, &p, 32767, 32767);
519                 if (name) {
520                         p.x=2;
521                         p.y=12;
522                         graphics_draw_text(this->gr, this->white, NULL, this->font, name, &p, 0x10000, 0);
523                 }
524                 graphics_draw_mode(this->gr, draw_mode_end);
525         }
526 }
527
528 static void
529 osd_street_name_init(struct osd_street_name *this, struct navit *nav)
530 {
531         struct graphics *navit_gr;
532         struct color c;
533         navit_gr=navit_get_graphics(nav);
534         this->active=-1;
535         this->gr=graphics_overlay_new(navit_gr, &this->p, this->w, this->h);
536
537         this->bg=graphics_gc_new(this->gr);
538         c.r=0; c.g=0; c.b=0;
539         graphics_gc_set_foreground(this->bg, &c);
540
541         this->white=graphics_gc_new(this->gr);
542         c.r=65535; c.g=65535; c.b=65535;
543         graphics_gc_set_foreground(this->white, &c);
544
545         this->font=graphics_font_new(this->gr, 200, 1);
546         navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_street_name_draw), attr_position_coord_geo, this));
547
548         osd_street_name_draw(this, nav, NULL);
549 }
550
551 static struct osd_priv *
552 osd_street_name_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
553 {
554         struct osd_street_name *this=g_new0(struct osd_street_name, 1);
555         struct attr *attr;
556         this->p.x=90;
557         this->p.y=-36;
558         this->w=150;
559         this->h=16;
560         attr=attr_search(attrs, NULL, attr_x);
561         if (attr)
562                 this->p.x=attr->u.num;
563         attr=attr_search(attrs, NULL, attr_y);
564         if (attr)
565                 this->p.y=attr->u.num;
566         navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_street_name_init), attr_navit, this));
567         return (struct osd_priv *) this;
568 }
569
570 void
571 plugin_init(void)
572 {
573         plugin_register_osd_type("compass", osd_compass_new);
574         plugin_register_osd_type("eta", osd_eta_new);
575         plugin_register_osd_type("navigation", osd_navigation_new);
576         plugin_register_osd_type("street_name", osd_street_name_new);
577 }
578