/[zanavi_public1]/navit/navit/osd/core/osd_core.c
ZANavi

Contents of /navit/navit/osd/core/osd_core.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 41 - (show annotations) (download)
Tue Aug 11 18:50:37 2015 UTC (8 years, 7 months ago) by zoff99
File MIME type: text/plain
File size: 104255 byte(s)
many fixes, and new features
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 #include "config.h"
21 #ifdef _MSC_VER
22 #define _USE_MATH_DEFINES 1
23 #endif /* _MSC_VER */
24 #include <stdlib.h>
25 #include <math.h>
26 #include <stdio.h>
27 #include <glib.h>
28 #include <time.h>
29 #ifdef HAVE_SYS_TIME_H
30 #include <sys/time.h>
31 #endif
32 #include <string.h>
33 #include "item.h"
34 #include "point.h"
35 #include "coord.h"
36 #include "graphics.h"
37 #include "transform.h"
38 #include "route.h"
39 #include "navit.h"
40 #include "plugin.h"
41 #include "debug.h"
42 #include "callback.h"
43 #include "color.h"
44 #include "vehicle.h"
45 #include "navigation.h"
46 #include "track.h"
47 #include "map.h"
48 #include "file.h"
49 #include "attr.h"
50 #include "command.h"
51 #include "navit_nls.h"
52 #include "messages.h"
53 #include "vehicleprofile.h"
54 #include "roadprofile.h"
55 #include "osd.h"
56 #include "speech.h"
57 #include "event.h"
58 #include "mapset.h"
59 #include "util.h"
60
61 #ifdef HAVE_API_WIN32_CE
62 #include "libc.h"
63 #endif
64
65 #ifdef _MSC_VER
66 static double round(double x)
67 {
68 if (x >= 0.0)
69 return floor(x + 0.5);
70 else
71 return ceil(x - 0.5);
72 }
73 #endif /* MSC_VER */
74
75 struct odometer;
76
77
78
79
80 int osd_core_item_id_hi = 0;
81 int osd_core_item_id_lo = 0;
82 struct map *osd_core_item_id_map = NULL;
83 char *street_name_save = NULL;
84 char *street_name_systematic_save = NULL;
85
86
87 int osd_core_item_id_hi_t = 0;
88 int osd_core_item_id_lo_t = 0;
89 struct map *osd_core_item_id_map_t = NULL;
90 char *street_name_save_t = NULL;
91 char *street_name_systematic_save_t = NULL;
92
93 char *osd_destination_name = NULL;
94
95
96 static void osd_odometer_reset(struct odometer *this);
97 static void osd_cmd_odometer_reset(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid);
98 static void osd_odometer_draw(struct odometer *this, struct navit *nav, struct vehicle *v);
99 static struct osd_text_item * oti_new(struct osd_text_item * parent);
100
101 static int b_commandtable_added = 0;
102
103 struct compass {
104 struct osd_item osd_item;
105 int width;
106 struct graphics_gc *green;
107 };
108
109 static void
110 transform_rotate(struct point *center, int angle, struct point *p,
111 int count)
112 {
113 //// dbg(0,,"EEnter\n");
114
115 int i, x, y;
116 double dx, dy;
117 for (i = 0; i < count; i++) {
118 dx = sin(M_PI * angle / 180.0);
119 dy = cos(M_PI * angle / 180.0);
120 x = dy * p->x - dx * p->y;
121 y = dx * p->x + dy * p->y;
122
123 p->x = center->x + x;
124 p->y = center->y + y;
125 p++;
126 }
127 }
128
129 static void
130 handle(struct graphics *gr, struct graphics_gc *gc, struct point *p, int r,
131 int dir)
132 {
133 // dbg(0,,"EEnter\n");
134
135 struct point ph[3];
136 int l = r * 0.4;
137
138 ph[0].x = 0;
139 ph[0].y = r;
140 ph[1].x = 0;
141 ph[1].y = -r;
142 transform_rotate(p, dir, ph, 2);
143 graphics_draw_lines(gr, gc, ph, 2);
144 ph[0].x = -l;
145 ph[0].y = -r + l;
146 ph[1].x = 0;
147 ph[1].y = -r;
148 ph[2].x = l;
149 ph[2].y = -r + l;
150 transform_rotate(p, dir, ph, 3);
151 graphics_draw_lines(gr, gc, ph, 3);
152 }
153
154 /**
155 * * Format distance, choosing the unit (m or km) and precision depending on distance
156 * *
157 * * @param distance distance in meters
158 * * @param sep separator character to be inserted between distance value and unit
159 * * @returns a pointer to a string containing the formatted distance
160 * */
161 static char *
162 format_distance(double distance, char *sep, int imperial)
163 {
164 //// dbg(0,,"EEnter\n");
165
166 if (imperial){
167 distance *= FEET_PER_METER;
168 if(distance <= 1500){
169 return g_strdup_printf("%.0f%sft", round(distance / 10) * 10, sep);
170 } else {
171 return g_strdup_printf("%.1f%smi", distance / FEET_PER_MILE, sep);
172 }
173 } else {
174 if (distance >= 100000)
175 return g_strdup_printf("%.0f%skm", distance / 1000, sep);
176 else if (distance >= 10000)
177 return g_strdup_printf("%.1f%skm", distance / 1000, sep);
178 else if (distance >= 300)
179 return g_strdup_printf("%.0f%sm", round(distance / 25) * 25, sep);
180 else if (distance >= 50)
181 return g_strdup_printf("%.0f%sm", round(distance / 10) * 10, sep);
182 else if (distance >= 10)
183 return g_strdup_printf("%.0f%sm", distance, sep);
184 else
185 return g_strdup_printf("%.1f%sm", distance, sep);
186 }
187 }
188
189 /**
190 * * Format time (duration)
191 * *
192 * * @param tm pointer to a tm structure specifying the time
193 * * @param days days
194 * * @returns a pointer to a string containing the formatted time
195 * */
196 static char *
197 format_time(struct tm *tm, int days)
198 {
199 if (days)
200 return g_strdup_printf("%d+%02d:%02d", days, tm->tm_hour, tm->tm_min);
201 else
202 return g_strdup_printf("%02d:%02d", tm->tm_hour, tm->tm_min);
203 }
204
205 /**
206 * * Format speed in km/h
207 * *
208 * * @param speed speed in km/h
209 * * @param sep separator character to be inserted between speed value and unit
210 * * @returns a pointer to a string containing the formatted speed
211 * */
212 static char *
213 format_speed(double speed, char *sep, char *format, int imperial)
214 {
215 char *unit="km/h";
216 if (imperial) {
217 speed = speed*1000*FEET_PER_METER/FEET_PER_MILE;
218 unit="mph";
219 }
220 if (!format || !strcmp(format,"named"))
221 return g_strdup_printf("%.0f%s%s", speed, sep, unit);
222 else if (!strcmp(format,"value") || !strcmp(format,"unit")) {
223 if (!strcmp(format,"value"))
224 return g_strdup_printf("%.0f", speed);
225 else
226 return g_strdup(unit);
227 }
228 return g_strdup("");
229 }
230
231 /*static char *
232 format_float(double num)
233 {
234 return g_strdup_printf("%f", num);
235 }*/
236
237 static char *
238 format_float_0(double num)
239 {
240 return g_strdup_printf("%.0f", num);
241 }
242
243 /**
244 * sets an attribute (name value pair) of a map item specified by map name and item id
245 *
246 * @param navit The navit instance
247 * @param function unused (needed to match command function signiture)
248 * @param in input attribute in[0] - name of the osd ; in[1] - attr name ; in[2] - attr value
249 * @param out output attribute, 0 on error, 1 on success
250 * @param valid unused
251 * @returns nothing
252 */
253 static void
254 osd_cmd_osd_set_attr(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
255 {
256 //// dbg(0,,"EEnter\n");
257
258 struct attr **list;
259 struct attr*val = g_new0(struct attr,1);
260 val->type = attr_type_int_begin;
261 val->u.num = 0;
262 list = g_new0(struct attr *,2);
263 list[0] = val;
264
265 if (
266 in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str &&//osd name
267 in[1] && ATTR_IS_STRING(in[1]->type) && in[1]->u.str &&//attr_type str
268 in[2] && ATTR_IS_STRING(in[2]->type) && in[2]->u.str //attr_value str
269 ) {
270 struct attr attr_to_set;
271 struct osd* osd;
272
273 if(ATTR_IS_STRING(attr_from_name(in[1]->u.str))) {
274 attr_to_set.u.str = in[2]->u.str;
275 attr_to_set.type = attr_from_name(in[1]->u.str);
276 }
277 else if(ATTR_IS_INT(attr_from_name(in[1]->u.str))) {
278 attr_to_set.u.num = atoi(in[2]->u.str);
279 attr_to_set.type = attr_from_name(in[1]->u.str);
280 }
281 else if(ATTR_IS_DOUBLE(attr_from_name(in[1]->u.str))) {
282 double* val = g_new0(double,1);
283 *val = atof(in[2]->u.str);
284 attr_to_set.u.numd = val;
285 attr_to_set.type = attr_from_name(in[1]->u.str);
286 }
287 osd = osd_get_osd_by_name(in[0]->u.str);
288 if(osd) {
289 osd_set_attr(osd, &attr_to_set);
290 val->u.num = 1;
291 }
292 }
293 list[1] = NULL;
294 *out = list;
295 }
296
297
298
299 static int odometers_saved = 0;
300 static GList* odometer_list = NULL;
301
302 static struct command_table commands[] = {
303 {"odometer_reset",command_cast(osd_cmd_odometer_reset)},
304 {"osd_set_attr" ,command_cast(osd_cmd_osd_set_attr)},
305 };
306
307 struct odometer {
308 struct osd_item osd_item;
309 int width;
310 struct graphics_gc *orange;
311 struct graphics_gc *white;
312 struct callback *click_cb;
313 char *text; //text of label attribute for this osd
314 char *name; //unique name of the odometer (needed for handling multiple odometers persistently)
315 struct color idle_color; //text color when counter is idle
316
317 int bDisableReset;
318 int bAutoStart;
319 int bActive; //counting or not
320 int autosave_period; //autosave period in seconds
321 double sum_dist; //sum of distance ofprevious intervals in meters
322 double sum_time; //sum of time of previous intervals in seconds (needed for avg spd calculation)
323 double time_all;
324 double last_click_time; //time of last click (for double click handling)
325 double last_start_time; //time of last start of counting
326 double last_update_time; //time of last position update
327 struct coord last_coord;
328 double last_speed;
329 double acceleration;
330 };
331
332 static void
333 osd_cmd_odometer_reset(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
334 {
335 //// dbg(0,,"EEnter\n");
336
337 if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) {
338 GList* list = odometer_list;
339 while(list) {
340 if(!strcmp(((struct odometer*)(list->data))->name,in[0]->u.str)) {
341 osd_odometer_reset(list->data);
342 osd_odometer_draw(list->data,this,NULL);
343 }
344 list = g_list_next(list);
345 }
346 }
347 }
348
349 static char*
350 str_replace(char*output, char*input, char*pattern, char*replacement)
351 {
352 //// dbg(0,,"EEnter\n");
353
354 char *pos;
355 char *pos2;
356 if (!output || !input || !pattern || !replacement) {
357 return NULL;
358 }
359 if(!strcmp(pattern,"")) {
360 return input;
361 }
362
363 pos = &input[0];
364 pos2 = &input[0];
365 output[0] = 0;
366 while ( (pos2=strstr(pos,pattern)) ) {
367 strncat(output,pos,pos2-pos);
368 strcat(output,replacement);
369 pos = pos2 + strlen(pattern);
370 }
371 strcat(output,pos);
372 return NULL;
373 }
374
375 /*
376 * save current odometer state to string
377 */
378 static char *osd_odometer_to_string(struct odometer* this_)
379 {
380 return g_strdup_printf("odometer %s %lf %lf %d\n",this_->name,this_->sum_dist,this_->time_all,this_->bActive);
381 }
382
383 /*
384 * load current odometer state from string
385 */
386 static void osd_odometer_from_string(struct odometer* this_, char*str)
387 {
388 char* tok;
389 char* name_str;
390 char* sum_dist_str;
391 char* sum_time_str;
392 char* active_str;
393 tok = strtok(str, " ");
394 if( !tok || strcmp("odometer",tok)) {
395 return;
396 }
397 name_str = g_strdup(strtok(NULL, " "));
398 if(!name_str) {
399 return;
400 }
401 sum_dist_str = g_strdup(strtok(NULL, " "));
402 if(!sum_dist_str) {
403 g_free(name_str);
404 return;
405 }
406 sum_time_str = g_strdup(strtok(NULL, " "));
407 if(!sum_time_str) {
408 g_free(name_str);
409 g_free(sum_dist_str);
410 return;
411 }
412 active_str = g_strdup(strtok(NULL, " "));
413 if(!active_str) {
414 g_free(name_str);
415 g_free(sum_dist_str);
416 g_free(sum_time_str);
417 return;
418 }
419 this_->name = name_str;
420 this_->sum_dist = atof(sum_dist_str);
421 this_->sum_time = atof(sum_time_str);
422 this_->bActive = atoi(active_str);
423 this_->last_coord.x = -1;
424 g_free(active_str);
425 g_free(sum_dist_str);
426 g_free(sum_time_str);
427 }
428
429 static void osd_odometer_draw(struct odometer *this, struct navit *nav, struct vehicle *v)
430 {
431 struct coord curr_coord;
432 struct graphics_gc *curr_color;
433
434 char *dist_buffer=0;
435 char *spd_buffer=0;
436 char *time_buffer = 0;
437 char *acc_buffer = 0;
438 struct point p, bbox[4];
439 struct attr position_attr,vehicle_attr,imperial_attr,speed_attr;
440 enum projection pro;
441 struct vehicle* curr_vehicle = v;
442 double spd = 0;
443 double curr_spd = 0;
444
445 int remainder;
446 int days;
447 int hours;
448 int mins;
449 int secs;
450 int imperial=0;
451
452 char buffer [256+1]="";
453 char buffer2[256+1]="";
454
455 if(nav) {
456 navit_get_attr(nav, attr_vehicle, &vehicle_attr, NULL);
457 if (navit_get_attr(nav, attr_imperial, &imperial_attr, NULL))
458 imperial=imperial_attr.u.num;
459 }
460 if (vehicle_attr.u.vehicle) {
461 curr_vehicle = vehicle_attr.u.vehicle;
462 }
463
464 if(0==curr_vehicle)
465 return;
466
467 osd_std_draw(&this->osd_item);
468 if(this->bActive) {
469 if(!vehicle_get_attr(curr_vehicle, attr_position_coord_geo,&position_attr, NULL)) {
470 return;
471 }
472 pro = projection_mg;//position_attr.u.pcoord->pro;
473 transform_from_geo(pro, position_attr.u.coord_geo, &curr_coord);
474
475 if (this->last_coord.x != -1 ) {
476 const double cStepDistLimit = 10000;
477 struct timeval tv;
478 double curr_time;
479 double dt;
480 double dCurrDist = 0;
481
482 gettimeofday(&tv,NULL);
483 curr_time = (double)(tv.tv_usec)/1000000.0+tv.tv_sec;
484 //we have valid previous position
485 dt = curr_time-this->last_update_time;
486 dCurrDist = transform_distance(pro, &curr_coord, &this->last_coord);
487 if(dCurrDist<=cStepDistLimit) {
488 this->sum_dist += dCurrDist;
489 }
490 this->time_all = curr_time-this->last_click_time+this->sum_time;
491 spd = 3.6*(double)this->sum_dist/(double)this->time_all;
492 if(dt != 0) {
493 if (curr_coord.x!=this->last_coord.x || curr_coord.y!=this->last_coord.y) {
494 if(vehicle_get_attr(curr_vehicle, attr_position_speed,&speed_attr, NULL)) {
495 double dv;
496 curr_spd = *speed_attr.u.numd;
497 dv = (curr_spd-this->last_speed)/3.6; //speed difference in m/sec
498 this->acceleration = dv/dt;
499 this->last_speed = curr_spd;
500 this->last_update_time = curr_time;
501 }
502 }
503 }
504 }
505 this->last_coord = curr_coord;
506 }
507
508 dist_buffer = format_distance(this->sum_dist,"",imperial);
509 spd_buffer = format_speed(spd,"","value",imperial);
510 acc_buffer = g_strdup_printf("%.3f m/s2",this->acceleration);
511 remainder = (int)this->time_all;
512 days = remainder / (24*60*60);
513 remainder = remainder % (24*60*60);
514 hours = remainder / (60*60);
515 remainder = remainder % (60*60);
516 mins = remainder / (60);
517 remainder = remainder % (60);
518 secs = remainder;
519 if(0<days) {
520 time_buffer = g_strdup_printf("%02dd %02d:%02d:%02d",days,hours,mins,secs);
521 }
522 else {
523 time_buffer = g_strdup_printf("%02d:%02d:%02d",hours,mins,secs);
524 }
525
526 buffer [0] = 0;
527 buffer2[0] = 0;
528 if(this->text) {
529 str_replace(buffer2,this->text,"${avg_spd}",spd_buffer);
530 str_replace(buffer,buffer2,"${distance}",dist_buffer);
531 str_replace(buffer2,buffer,"${time}",time_buffer);
532 str_replace(buffer,buffer2,"${acceleration}",acc_buffer);
533 }
534 g_free(time_buffer);
535
536 graphics_get_text_bbox(this->osd_item.gr, this->osd_item.font, buffer, 0x10000, 0, bbox, 0);
537 p.x=(this->osd_item.w-bbox[2].x)/2;
538 p.y = this->osd_item.h-this->osd_item.h/10;
539 curr_color = this->bActive?this->white:this->orange;
540 graphics_draw_text(this->osd_item.gr, curr_color, NULL, this->osd_item.font, buffer, &p, 0x10000, 0);
541 g_free(dist_buffer);
542 g_free(spd_buffer);
543 g_free(acc_buffer);
544 graphics_draw_mode(this->osd_item.gr, draw_mode_end);
545 }
546
547
548 static void
549 osd_odometer_reset(struct odometer *this)
550 {
551 if(!this->bDisableReset) {
552 this->bActive = 0;
553 this->sum_dist = 0;
554 this->sum_time = 0;
555 this->last_start_time = 0;
556 this->last_coord.x = -1;
557 this->last_coord.y = -1;
558 }
559 }
560
561 static void
562 osd_odometer_click(struct odometer *this, struct navit *nav, int pressed, int button, struct point *p)
563 {
564 struct point bp = this->osd_item.p;
565 struct timeval tv;
566 double curr_time;
567 const double double_click_timewin = .5;
568 osd_wrap_point(&bp, nav);
569 if ((p->x < bp.x || p->y < bp.y || p->x > bp.x + this->osd_item.w || p->y > bp.y + this->osd_item.h || !this->osd_item.configured ) && !this->osd_item.pressed)
570 return;
571 if (button != 1)
572 return;
573 if (navit_ignore_button(nav))
574 return;
575 if (!!pressed == !!this->osd_item.pressed)
576 return;
577
578 gettimeofday(&tv,NULL);
579 curr_time = (double)(tv.tv_usec)/1000000.0+tv.tv_sec;
580
581 if (pressed) { //single click handling
582 if(this->bActive) { //being stopped
583 this->last_coord.x = -1;
584 this->last_coord.y = -1;
585 this->sum_time += curr_time-this->last_click_time;
586 }
587
588 this->bActive ^= 1; //toggle active flag
589
590 if (curr_time-double_click_timewin <= this->last_click_time) { //double click handling
591 osd_odometer_reset(this);
592 }
593
594 this->last_click_time = curr_time;
595
596 osd_odometer_draw(this, nav,NULL);
597 }
598 }
599
600
601 static int
602 osd_odometer_save(struct navit* nav)
603 {
604 //save odometers that are persistent(ie have name)
605 FILE*f;
606 GList* list = odometer_list;
607 char* fn = g_strdup_printf("%s/odometer.txt",navit_get_user_data_directory(TRUE));
608 f = fopen(fn,"w+");
609 g_free(fn);
610 if(!f) {
611 return TRUE;
612 }
613 while (list) {
614 if( ((struct odometer*)(list->data))->name) {
615 char*odo_str = osd_odometer_to_string(list->data);
616 fprintf(f,"%s",odo_str);
617 g_free(odo_str);
618
619 }
620 list = g_list_next(list);
621 }
622 fclose(f);
623 return TRUE;
624 }
625
626
627 static void
628 osd_odometer_init(struct odometer *this, struct navit *nav)
629 {
630 osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
631
632 this->orange = graphics_gc_new(this->osd_item.gr);
633 graphics_gc_set_foreground(this->orange, &this->idle_color);
634 graphics_gc_set_linewidth(this->orange, this->width);
635
636 this->white = graphics_gc_new(this->osd_item.gr);
637 graphics_gc_set_foreground(this->white, &this->osd_item.text_color);
638 graphics_gc_set_linewidth(this->white, this->width);
639
640 graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width);
641
642 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_odometer_draw), attr_position_coord_geo, this));
643
644 navit_add_callback(nav, this->click_cb = callback_new_attr_1(callback_cast (osd_odometer_click), attr_button, this));
645
646 if(this->autosave_period>0) {
647 event_add_timeout(this->autosave_period*1000, 1, callback_new_1(callback_cast(osd_odometer_save), NULL));
648 }
649
650 if(this->bAutoStart) {
651 this->bActive = 1;
652 }
653 osd_odometer_draw(this, nav, NULL);
654 }
655
656 static void
657 osd_odometer_destroy(struct navit* nav)
658 {
659 if(!odometers_saved) {
660 odometers_saved = 1;
661 osd_odometer_save(NULL);
662 }
663 }
664
665 struct osd_priv *
666 osd_odometer_new(struct navit *nav, struct osd_methods *meth,
667 struct attr **attrs)
668 {
669 FILE* f;
670 char* fn;
671
672 struct odometer *this = g_new0(struct odometer, 1);
673 struct attr *attr;
674 struct color orange_color={0xffff,0xa5a5,0x0000,0xffff};
675 this->osd_item.p.x = 120;
676 this->osd_item.p.y = 20;
677 this->osd_item.w = 60;
678 this->osd_item.h = 80;
679 this->osd_item.navit = nav;
680 this->osd_item.font_size = 200;
681 this->osd_item.meth.draw = osd_draw_cast(osd_odometer_draw);
682
683 this->bActive = 0; //do not count on init
684 this->sum_dist = 0;
685 this->last_click_time = time(0);
686 this->last_coord.x = -1;
687 this->last_coord.y = -1;
688
689 attr = attr_search(attrs, NULL, attr_label);
690 //FIXME find some way to free text!!!!
691 if (attr) {
692 this->text = g_strdup(attr->u.str);
693 }
694 else
695 this->text = NULL;
696
697 attr = attr_search(attrs, NULL, attr_name);
698 //FIXME find some way to free text!!!!
699 if (attr) {
700 this->name = g_strdup(attr->u.str);
701 }
702 else
703 this->name = NULL;
704
705 attr = attr_search(attrs, NULL, attr_disable_reset);
706 if (attr)
707 this->bDisableReset = attr->u.num;
708 else
709 this->bDisableReset = 0;
710
711 attr = attr_search(attrs, NULL, attr_autostart);
712 if (attr)
713 this->bAutoStart = attr->u.num;
714 else
715 this->bAutoStart = 0;
716 attr = attr_search(attrs, NULL, attr_autosave_period);
717 if (attr)
718 this->autosave_period = attr->u.num;
719 else
720 this->autosave_period = -1; //disabled by default
721
722 osd_set_std_attr(attrs, &this->osd_item, 2);
723 attr = attr_search(attrs, NULL, attr_width);
724 this->width=attr ? attr->u.num : 2;
725 attr = attr_search(attrs, NULL, attr_idle_color);
726 this->idle_color=attr ? *attr->u.color : orange_color; // text idle_color defaults to orange
727
728 this->last_coord.x = -1;
729 this->last_coord.y = -1;
730 this->sum_dist = 0.0;
731
732 //load state from file
733 fn = g_strdup_printf("%s/odometer.txt",navit_get_user_data_directory(FALSE));
734 f = fopen(fn,"r+");
735
736 if(f) {
737 g_free(fn);
738
739 while(!feof(f)) {
740 char str[128];
741 char *line;
742 if(fgets(str,128,f))
743 {
744 char *tok;
745 line = g_strdup(str);
746 tok = strtok(str," ");
747 if(!strcmp(tok,"odometer")) {
748 tok = strtok(NULL," ");
749 if(this->name && tok && !strcmp(this->name,tok)) {
750 osd_odometer_from_string(this,line);
751 }
752 }
753 g_free(line);
754 }
755 }
756 fclose(f);
757 }
758
759 if(b_commandtable_added == 0) {
760 navit_command_add_table(nav, commands, sizeof(commands)/sizeof(struct command_table));
761 b_commandtable_added = 1;
762 }
763 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_odometer_init), attr_graphics_ready, this));
764 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_odometer_destroy), attr_destroy, nav));
765 odometer_list = g_list_append(odometer_list, this);
766
767 return (struct osd_priv *) this;
768 }
769
770
771 struct cmd_interface {
772 struct osd_item osd_item;
773 int width;
774 struct graphics_gc *orange,*white;
775 int update_period; //in sec
776 char* text;
777 struct graphics_image *img;
778 char*img_filename;
779 char* command;
780 int bReserved;
781 };
782
783 static void
784 osd_cmd_interface_draw(struct cmd_interface *this, struct navit *nav,
785 struct vehicle *v)
786 {
787 // dbg(0,,"EEnter\n");
788
789 struct point p;
790 struct point bbox[4];
791 struct graphics_gc *curr_color;
792 struct attr navit;
793 p.x = 0;
794 p.y = 0;
795 navit.type=attr_navit;
796 navit.u.navit = this->osd_item.navit;
797
798 if(0==this->bReserved) {
799 this->bReserved = 1;
800 command_evaluate(&navit, this->command);
801 this->bReserved = 0;
802 }
803
804 osd_std_draw(&this->osd_item);
805
806 //display image
807 if(this->img) {
808 graphics_draw_image(this->osd_item.gr, this->osd_item.graphic_bg, &p, this->img);
809 }
810
811 //display text
812 graphics_get_text_bbox(this->osd_item.gr, this->osd_item.font, this->text, 0x10000, 0, bbox, 0);
813 p.x=(this->osd_item.w-bbox[2].x)/2;
814 p.y = this->osd_item.h-this->osd_item.h/10;
815 curr_color = this->white;
816 if(this->text)
817 graphics_draw_text(this->osd_item.gr, curr_color, NULL, this->osd_item.font, this->text, &p, 0x10000, 0);
818 graphics_draw_mode(this->osd_item.gr, draw_mode_end);
819 }
820
821
822
823 static void
824 osd_cmd_interface_init(struct cmd_interface *this, struct navit *nav)
825 {
826 // dbg(0,,"EEnter\n");
827
828 osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
829
830 this->white = graphics_gc_new(this->osd_item.gr);
831 graphics_gc_set_foreground(this->white, &this->osd_item.text_color);
832 graphics_gc_set_linewidth(this->white, this->width);
833
834
835 graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width);
836
837 if(this->update_period>0) {
838 event_add_timeout(this->update_period*1000, 1, callback_new_1(callback_cast(osd_cmd_interface_draw), this));
839 }
840
841 struct callback *cb;
842 cb = callback_new_attr_1(callback_cast (osd_std_click), attr_button, &this->osd_item);
843 callback_add_names(cb, "osd_cmd_interface_init", "osd_std_click");
844 navit_add_callback(nav, cb);
845
846 this->text = g_strdup("");
847 }
848
849 static int
850 osd_cmd_interface_set_attr(struct cmd_interface *this_, struct attr* attr)
851 {
852 //// dbg(0,,"EEnter\n");
853
854 struct navit* nav;
855 if(NULL==attr || NULL==this_) {
856 return 0;
857 }
858
859 nav = this_->osd_item.navit;
860
861 if(attr->type == attr_status_text) {
862 if(this_->text) {
863 g_free(this_->text);
864 }
865 if(attr->u.str) {
866 this_->text = g_strdup(attr->u.str);
867 }
868 return 1;
869 }
870 if(attr->type == attr_src) {
871 if(attr->u.str) {
872 if((!this_->img_filename) || strcmp(this_->img_filename, graphics_icon_path(attr->u.str))) {
873 struct graphics *gra = navit_get_graphics(nav);
874 //destroy old img, create new image
875 if(this_->img) {
876 graphics_image_free(this_->osd_item.gr, this_->img);
877 }
878 if(this_->img_filename) {
879 g_free(this_->img_filename);
880 }
881 this_->img_filename = graphics_icon_path(attr->u.str);
882 this_->img = graphics_image_new(this_->osd_item.gr, this_->img_filename);
883 }
884 }
885 return 1;
886 }
887 return 0;
888 }
889
890
891 struct osd_priv *
892 osd_cmd_interface_new(struct navit *nav, struct osd_methods *meth,
893 struct attr **attrs)
894 {
895 // dbg(0,,"EEnter\n");
896
897 struct cmd_interface *this = g_new0(struct cmd_interface, 1);
898 struct attr *attr;
899
900 this->osd_item.p.x = 120;
901 this->osd_item.p.y = 20;
902 this->osd_item.w = 60;
903 this->osd_item.h = 80;
904 this->osd_item.navit = nav;
905 this->osd_item.font_size = 200;
906 this->osd_item.meth.draw = osd_draw_cast(osd_cmd_interface_draw);
907
908 meth->set_attr = osd_cmd_interface_set_attr;
909
910 osd_set_std_attr(attrs, &this->osd_item, 2);
911
912 attr = attr_search(attrs, NULL, attr_width);
913 this->width=attr ? attr->u.num : 2;
914
915 attr = attr_search(attrs, NULL, attr_update_period);
916 this->update_period=attr ? attr->u.num : 5; //default update period is 5 seconds
917
918 attr = attr_search(attrs, NULL, attr_command);
919 this->command = attr ? g_strdup(attr->u.str) : g_strdup("");
920
921 if (b_commandtable_added == 0)
922 {
923 navit_command_add_table(nav, commands, sizeof(commands)/sizeof(struct command_table));
924 b_commandtable_added = 1;
925 }
926
927 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_cmd_interface_init), attr_graphics_ready, this));
928 return (struct osd_priv *) this;
929 }
930
931
932
933
934 struct stopwatch {
935 struct osd_item osd_item;
936 int width;
937 struct graphics_gc *orange,*white;
938 struct callback *click_cb;
939 struct color idle_color; //text color when counter is idle
940
941 int bDisableReset;
942 int bActive; //counting or not
943 time_t current_base_time; //base time of currently measured time interval
944 time_t sum_time; //sum of previous time intervals (except current intervals)
945 time_t last_click_time; //time of last click (for double click handling)
946 };
947
948 static void
949 osd_stopwatch_draw(struct stopwatch *this, struct navit *nav,
950 struct vehicle *v)
951 {
952 //// dbg(0,,"EEnter\n");
953
954 struct graphics_gc *curr_color;
955 char buffer[32]="00:00:00";
956 struct point p;
957 struct point bbox[4];
958 time_t total_sec,total_min,total_hours,total_days;
959 total_sec = this->sum_time;
960
961 osd_std_draw(&this->osd_item);
962
963 if(this->bActive) {
964 total_sec += time(0)-this->current_base_time;
965 }
966
967 total_min = total_sec/60;
968 total_hours = total_min/60;
969 total_days = total_hours/24;
970
971 if (total_days==0) {
972 g_snprintf(buffer,32,"%02d:%02d:%02d", (int)total_hours%24, (int)total_min%60, (int)total_sec%60);
973 } else {
974 g_snprintf(buffer,32,"%02dd %02d:%02d:%02d",
975 (int)total_days, (int)total_hours%24, (int)total_min%60, (int)total_sec%60);
976 }
977
978 graphics_get_text_bbox(this->osd_item.gr, this->osd_item.font, buffer, 0x10000, 0, bbox, 0);
979 p.x=(this->osd_item.w-bbox[2].x)/2;
980 p.y = this->osd_item.h-this->osd_item.h/10;
981
982 curr_color = this->bActive?this->white:this->orange;
983 graphics_draw_text(this->osd_item.gr, curr_color, NULL, this->osd_item.font, buffer, &p, 0x10000, 0);
984 graphics_draw_mode(this->osd_item.gr, draw_mode_end);
985 }
986
987
988 static void
989 osd_stopwatch_click(struct stopwatch *this, struct navit *nav, int pressed, int button, struct point *p)
990 {
991 struct point bp = this->osd_item.p;
992 osd_wrap_point(&bp, nav);
993 if ((p->x < bp.x || p->y < bp.y || p->x > bp.x + this->osd_item.w || p->y > bp.y + this->osd_item.h || !this->osd_item.configured ) && !this->osd_item.pressed)
994 return;
995 if (button != 1)
996 return;
997 if (navit_ignore_button(nav))
998 return;
999 if (!!pressed == !!this->osd_item.pressed)
1000 return;
1001
1002 if (pressed) { //single click handling
1003
1004 if(this->bActive) {
1005 this->sum_time += time(0)-this->current_base_time;
1006 this->current_base_time = 0;
1007 } else {
1008 this->current_base_time = time(0);
1009 }
1010
1011 this->bActive ^= 1; //toggle active flag
1012
1013 if (this->last_click_time == time(0) && !this->bDisableReset) { //double click handling
1014 this->bActive = 0;
1015 this->current_base_time = 0;
1016 this->sum_time = 0;
1017 }
1018
1019 this->last_click_time = time(0);
1020 }
1021
1022 osd_stopwatch_draw(this, nav,NULL);
1023 }
1024
1025
1026 static void
1027 osd_stopwatch_init(struct stopwatch *this, struct navit *nav)
1028 {
1029 osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
1030
1031 this->orange = graphics_gc_new(this->osd_item.gr);
1032 graphics_gc_set_foreground(this->orange, &this->idle_color);
1033 graphics_gc_set_linewidth(this->orange, this->width);
1034
1035 this->white = graphics_gc_new(this->osd_item.gr);
1036 graphics_gc_set_foreground(this->white, &this->osd_item.text_color);
1037 graphics_gc_set_linewidth(this->white, this->width);
1038
1039
1040 graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width);
1041
1042 event_add_timeout(500, 1, callback_new_1(callback_cast(osd_stopwatch_draw), this));
1043
1044 navit_add_callback(nav, this->click_cb = callback_new_attr_1(callback_cast (osd_stopwatch_click), attr_button, this));
1045
1046 osd_stopwatch_draw(this, nav, NULL);
1047 }
1048
1049 struct osd_priv *
1050 osd_stopwatch_new(struct navit *nav, struct osd_methods *meth,
1051 struct attr **attrs)
1052 {
1053 struct stopwatch *this = g_new0(struct stopwatch, 1);
1054 struct attr *attr;
1055 struct color orange_color={0xffff,0xa5a5,0x0000,0xffff};
1056
1057 this->osd_item.p.x = 120;
1058 this->osd_item.p.y = 20;
1059 this->osd_item.w = 60;
1060 this->osd_item.h = 80;
1061 this->osd_item.navit = nav;
1062 this->osd_item.font_size = 200;
1063 this->osd_item.meth.draw = osd_draw_cast(osd_stopwatch_draw);
1064
1065 this->bActive = 0; //do not count on init
1066 this->current_base_time = 0;
1067 this->sum_time = 0;
1068 this->last_click_time = 0;
1069
1070 osd_set_std_attr(attrs, &this->osd_item, 2);
1071 attr = attr_search(attrs, NULL, attr_width);
1072 this->width=attr ? attr->u.num : 2;
1073 attr = attr_search(attrs, NULL, attr_idle_color);
1074 this->idle_color=attr ? *attr->u.color : orange_color; // text idle_color defaults to orange
1075 attr = attr_search(attrs, NULL, attr_disable_reset);
1076 if (attr)
1077 this->bDisableReset = attr->u.num;
1078 else
1079 this->bDisableReset = 0;
1080
1081 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_stopwatch_init), attr_graphics_ready, this));
1082 return (struct osd_priv *) this;
1083 }
1084
1085
1086 static void
1087 osd_compass_draw(struct compass *this, struct navit *nav, struct vehicle *v)
1088 {
1089 // dbg(0,,"EEnter\n");
1090
1091 struct point p,bbox[4];
1092 struct attr attr_dir, destination_attr, position_attr, imperial_attr;
1093 double dir, vdir = 0;
1094 char *buffer;
1095 struct coord c1, c2;
1096 enum projection pro;
1097 int imperial=0;
1098
1099 if (navit_get_attr(nav, attr_imperial, &imperial_attr, NULL))
1100 {
1101 imperial = imperial_attr.u.num;
1102 }
1103
1104 //// dbg(0,,"CCC 1\n");
1105 // **DISABLE** osd_std_draw(&this->osd_item);
1106 // **DISABLE** p.x = this->osd_item.w/2;
1107 // **DISABLE** p.y = this->osd_item.w/2;
1108
1109 // graphics_send_osd_values(this->osd_item.gr,this->osd_item.graphic_fg_white,"compass","draw_circle","","",0,0,0,0,0.0,0.0,0.0);
1110
1111 // **DISABLE** graphics_draw_circle(this->osd_item.gr, this->osd_item.graphic_fg_white, &p, this->osd_item.w*5/6);
1112 //// dbg(0,,"CCC 2\n");
1113 if (v)
1114 {
1115 //// dbg(0,,"CCC 3\n");
1116 if (vehicle_get_attr(v, attr_position_direction, &attr_dir, NULL))
1117 {
1118 //// dbg(0,,"CCC 4\n");
1119 vdir = *attr_dir.u.numd;
1120
1121 #if 1
1122 if (nav->tracking)
1123 {
1124 // double dd;
1125 // dd = tracking_get_direction(nav->tracking);
1126 // dbg(0, "XYZ:vdir:%4.1f tracking:%4.1f\n", (float)vdir, (float)dd);
1127 vdir = tracking_get_direction(nav->tracking);
1128 }
1129 #endif
1130
1131 // **DISABLE** handle(this->osd_item.gr, this->osd_item.graphic_fg_white, &p, this->osd_item.w/3, -vdir);
1132 //char *buf_value;
1133 //g_snprintf(buf_value, 20, "%f", -vdir);
1134 //// dbg(0,,"CCC 5\n");
1135
1136 #ifdef HAVE_API_ANDROID
1137 send_osd_values("compass","direction","","",(int)-vdir,0,0,0,0,0,0);
1138 #endif
1139 //g_free(buf_value);
1140 //// dbg(0,,"CCC 6\n");
1141 }
1142
1143 //// dbg(0,,"CCC 7\n");
1144 if (navit_get_attr(nav, attr_destination, &destination_attr, NULL) && vehicle_get_attr(v, attr_position_coord_geo,&position_attr, NULL))
1145 {
1146 pro = destination_attr.u.pcoord->pro;
1147 transform_from_geo(pro, position_attr.u.coord_geo, &c1);
1148 c2.x = destination_attr.u.pcoord->x;
1149 c2.y = destination_attr.u.pcoord->y;
1150 dir = atan2(c2.x - c1.x, c2.y - c1.y) * 180.0 / M_PI;
1151 dir -= vdir;
1152 //// dbg(0,,"CCC 8\n");
1153 // **DISABLE** handle(this->osd_item.gr, this->green, &p, this->osd_item.w/3, dir);
1154 buffer=format_distance(transform_distance(pro, &c1, &c2),"",imperial);
1155 // **DISABLE** graphics_get_text_bbox(this->osd_item.gr, this->osd_item.font, buffer, 0x10000, 0, bbox, 0);
1156 // **DISABLE** p.x=(this->osd_item.w-bbox[2].x)/2;
1157 // **DISABLE** p.y = this->osd_item.h-this->osd_item.h/10;
1158
1159 // // dbg(0,,"dir:%f\n",dir);
1160 //char *buf_value;
1161 //g_snprintf(buf_value, 20, "%f", dir);
1162 //// dbg(0,,"CCC 8\n");
1163 #ifdef HAVE_API_ANDROID
1164 send_osd_values("compass","text_and_dst_angle",buffer,"",(int)dir,0,0,0,0,0,0);
1165 #endif
1166 //// dbg(0,,"CCC 10\n");
1167 //g_free(buf_value);
1168
1169 // **DISABLE** graphics_draw_text(this->osd_item.gr, this->green, NULL, this->osd_item.font, buffer, &p, 0x10000, 0);
1170 g_free(buffer);
1171 //// dbg(0,,"CCC 11\n");
1172 }
1173 }
1174
1175 //// dbg(0,,"CCC 12\n");
1176 // **DISABLE** graphics_draw_mode(this->osd_item.gr, draw_mode_end);
1177 //// dbg(0,,"CCC 13\n");
1178 }
1179
1180
1181
1182 static void
1183 osd_compass_init(struct compass *this, struct navit *nav)
1184 {
1185 //struct color c;
1186
1187 //// dbg(0,,"CCC 14\n");
1188
1189 //osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
1190
1191 //// dbg(0,,"CCC 15\n");
1192
1193 //this->green = graphics_gc_new(this->osd_item.gr);
1194 //c.r = 0;
1195 //c.g = 65535;
1196 //c.b = 0;
1197 //c.a = 65535;
1198
1199 // **DISABLE** graphics_gc_set_foreground(this->green, &c);
1200 // **DISABLE** graphics_gc_set_linewidth(this->green, this->width);
1201 // **DISABLE** graphics_gc_set_linewidth(this->osd_item.graphic_fg_white, this->width);
1202
1203 //// dbg(0,,"CCC 16\n");
1204 struct callback *cb;
1205 cb = callback_new_attr_1(callback_cast(osd_compass_draw), attr_position_coord_geo, this);
1206 callback_add_names(cb, "osd_compass_init", "osd_compass_draw");
1207 navit_add_callback(nav, cb);
1208
1209 //// dbg(0,,"CCC 17\n");
1210
1211 osd_compass_draw(this, nav, NULL);
1212
1213 //// dbg(0,,"CCC 18\n");
1214 }
1215
1216 struct osd_priv *
1217 osd_compass_new(struct navit *nav, struct osd_methods *meth,
1218 struct attr **attrs)
1219 {
1220 //// dbg(0,,"EEnter\n");
1221
1222 struct compass *this = g_new0(struct compass, 1);
1223 struct attr *attr;
1224 this->osd_item.p.x = 20;
1225 this->osd_item.p.y = 20;
1226 this->osd_item.w = 60;
1227 this->osd_item.h = 80;
1228 this->osd_item.navit = nav;
1229 this->osd_item.font_size = 200;
1230 this->osd_item.meth.draw = osd_draw_cast(osd_compass_draw);
1231 osd_set_std_attr(attrs, &this->osd_item, 2);
1232 attr = attr_search(attrs, NULL, attr_width);
1233 this->width=attr ? attr->u.num : 2;
1234
1235 struct callback *cb;
1236 cb = callback_new_attr_1(callback_cast(osd_compass_init), attr_graphics_ready, this);
1237 callback_add_names(cb, "osd_compass_new", "osd_compass_init");
1238 navit_add_callback(nav, cb);
1239
1240 // dbg(0,,"11111111111\n");
1241
1242 return (struct osd_priv *) this;
1243 }
1244
1245 struct osd_button {
1246 int use_overlay;
1247 struct osd_item item;
1248 struct callback *draw_cb,*navit_init_cb;
1249 struct graphics_image *img;
1250 char *src;
1251 };
1252
1253 static void
1254 osd_button_draw(struct osd_button *this, struct navit *nav)
1255 {
1256 // dbg(0,,"EEnter\n");
1257
1258 struct point bp = this->item.p;
1259 if (!this->item.configured)
1260 return;
1261 osd_wrap_point(&bp, nav);
1262 //graphics_draw_image(this->item.gr, this->item.graphic_bg, &bp, this->img);
1263 }
1264
1265 static void
1266 osd_button_init(struct osd_button *this, struct navit *nav)
1267 {
1268 // dbg(0,,"EEnter\n");
1269
1270 struct graphics *gra = navit_get_graphics(nav);
1271 //dbg(1, "enter\n");
1272 this->img = graphics_image_new(gra, this->src);
1273 if (!this->img) {
1274 //dbg(1, "failed to load '%s'\n", this->src);
1275 return;
1276 }
1277 if (!this->item.w)
1278 this->item.w=this->img->width;
1279 if (!this->item.h)
1280 this->item.h=this->img->height;
1281 if (this->use_overlay) {
1282 struct graphics_image *img;
1283 struct point p;
1284 osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
1285 img=graphics_image_new(this->item.gr, this->src);
1286 p.x=(this->item.w-this->img->width)/2;
1287 p.y=(this->item.h-this->img->height)/2;
1288 osd_std_draw(&this->item);
1289 graphics_draw_image(this->item.gr, this->item.graphic_bg, &p, img);
1290 graphics_draw_mode(this->item.gr, draw_mode_end);
1291 graphics_image_free(this->item.gr, img);
1292 } else {
1293 osd_set_std_config(nav, &this->item);
1294 this->item.gr=gra;
1295 this->item.graphic_bg=graphics_gc_new(this->item.gr);
1296 graphics_add_callback(gra, this->draw_cb=callback_new_attr_2(callback_cast(osd_button_draw), attr_postdraw, this, nav));
1297 }
1298 navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_std_click), attr_button, &this->item));
1299 osd_button_draw(this,nav);
1300 }
1301
1302 int
1303 osd_button_set_attr(struct osd_button *this_, struct attr* attr)
1304 {
1305 // dbg(0,,"EEnter\n");
1306
1307 if(NULL==attr || NULL==this_) {
1308 return 0;
1309 }
1310 if(attr->type == attr_src) {
1311 struct navit *nav;
1312 struct graphics *gra;
1313 if(this_->src) {
1314 g_free(this_->src);
1315 }
1316 if(attr->u.str) {
1317 this_->src = graphics_icon_path(attr->u.str);
1318 }
1319 nav = this_->item.navit;
1320 gra = navit_get_graphics(nav);
1321 this_->img = graphics_image_new(gra, this_->src);
1322 if (!this_->img)
1323 {
1324 //dbg(1, "failed to load '%s'\n", this_->src);
1325 return 0;
1326 }
1327 if (!this_->item.w)
1328 this_->item.w=this_->img->width;
1329 if (!this_->item.h)
1330 this_->item.h=this_->img->height;
1331
1332 if (this_->use_overlay) {
1333 struct graphics_image *img;
1334 struct point p;
1335 img=graphics_image_new(this_->item.gr, this_->src);
1336 p.x=(this_->item.w-this_->img->width)/2;
1337 p.y=(this_->item.h-this_->img->height)/2;
1338 osd_std_draw(&this_->item);
1339 graphics_draw_image(this_->item.gr, this_->item.graphic_bg, &p, img);
1340 graphics_image_free(this_->item.gr, img);
1341 }
1342 osd_button_draw(this_,nav);
1343 navit_draw(this_->item.navit);
1344 return 1;
1345 }
1346 return 0;
1347 }
1348
1349
1350
1351 struct osd_priv *
1352 osd_button_new(struct navit *nav, struct osd_methods *meth,
1353 struct attr **attrs)
1354 {
1355 // dbg(0,,"EEnter\n");
1356
1357 struct osd_button *this = g_new0(struct osd_button, 1);
1358 struct attr *attr;
1359
1360 this->item.navit = nav;
1361 this->item.meth.draw = osd_draw_cast(osd_button_draw);
1362
1363 meth->set_attr = osd_button_set_attr;
1364
1365 osd_set_std_attr(attrs, &this->item, 1|16);
1366
1367 attr=attr_search(attrs, NULL, attr_use_overlay);
1368 if (attr)
1369 this->use_overlay=attr->u.num;
1370 if (!this->item.command) {
1371 // dbg(0,, "no command\n");
1372 goto error;
1373 }
1374 attr = attr_search(attrs, NULL, attr_src);
1375 if (!attr) {
1376 // dbg(0,, "no src\n");
1377 goto error;
1378 }
1379
1380 this->src = graphics_icon_path(attr->u.str);
1381
1382 navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_button_init), attr_graphics_ready, this));
1383
1384 if(b_commandtable_added == 0) {
1385 navit_command_add_table(nav, commands, sizeof(commands)/sizeof(struct command_table));
1386 b_commandtable_added = 1;
1387 }
1388
1389 return (struct osd_priv *) this;
1390 error:
1391 g_free(this);
1392 return NULL;
1393 }
1394
1395 struct osd_image {
1396 int use_overlay;
1397 struct osd_item item;
1398 struct callback *draw_cb,*navit_init_cb;
1399 struct graphics_image *img;
1400 char *src;
1401 };
1402
1403 static void
1404 osd_image_draw(struct osd_image *this, struct navit *nav)
1405 {
1406 // dbg(0,,"EEnter\n");
1407
1408 struct point bp = this->item.p;
1409 osd_wrap_point(&bp, nav);
1410 graphics_draw_image(this->item.gr, this->item.graphic_bg, &bp, this->img);
1411 }
1412
1413 static void
1414 osd_image_init(struct osd_image *this, struct navit *nav)
1415 {
1416 // dbg(0,,"EEnter\n");
1417
1418 struct graphics *gra = navit_get_graphics(nav);
1419 //dbg(1, "enter\n");
1420 this->img = graphics_image_new(gra, this->src);
1421 if (!this->img)
1422 {
1423 //dbg(1, "failed to load '%s'\n", this->src);
1424 return;
1425 }
1426 if (!this->item.w)
1427 this->item.w=this->img->width;
1428 if (!this->item.h)
1429 this->item.h=this->img->height;
1430 if (this->use_overlay) {
1431 struct graphics_image *img;
1432 struct point p;
1433 osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
1434 img=graphics_image_new(this->item.gr, this->src);
1435 p.x=(this->item.w-this->img->width)/2;
1436 p.y=(this->item.h-this->img->height)/2;
1437 osd_std_draw(&this->item);
1438 graphics_draw_image(this->item.gr, this->item.graphic_bg, &p, img);
1439 graphics_draw_mode(this->item.gr, draw_mode_end);
1440 graphics_image_free(this->item.gr, img);
1441 } else {
1442 this->item.configured=1;
1443 this->item.gr=gra;
1444 this->item.graphic_bg=graphics_gc_new(this->item.gr);
1445 graphics_add_callback(gra, this->draw_cb=callback_new_attr_2(callback_cast(osd_button_draw), attr_postdraw, this, nav));
1446 }
1447 osd_image_draw(this,nav);
1448 }
1449
1450 struct osd_priv *
1451 osd_image_new(struct navit *nav, struct osd_methods *meth,
1452 struct attr **attrs)
1453 {
1454 // dbg(0,,"EEnter\n");
1455
1456 struct osd_image *this = g_new0(struct osd_image, 1);
1457 struct attr *attr;
1458
1459 this->item.navit = nav;
1460 this->item.meth.draw = osd_draw_cast(osd_image_draw);
1461
1462 osd_set_std_attr(attrs, &this->item, 1);
1463
1464 attr=attr_search(attrs, NULL, attr_use_overlay);
1465 if (attr)
1466 this->use_overlay=attr->u.num;
1467 attr = attr_search(attrs, NULL, attr_src);
1468 if (!attr) {
1469 // dbg(0,, "no src\n");
1470 goto error;
1471 }
1472
1473 this->src = graphics_icon_path(attr->u.str);
1474
1475 navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_image_init), attr_graphics_ready, this));
1476
1477 return (struct osd_priv *) this;
1478 error:
1479 g_free(this);
1480 return NULL;
1481 }
1482
1483 struct nav_next_turn {
1484 struct osd_item osd_item;
1485 char *test_text;
1486 char *icon_src;
1487 int icon_h, icon_w, active;
1488 char *last_name;
1489 int level;
1490 char *last_destination_name;
1491 };
1492
1493 static void
1494 osd_nav_next_turn_draw(struct nav_next_turn *this, struct navit *navit, struct vehicle *v)
1495 {
1496 struct point p;
1497 int do_draw = 0;
1498 struct navigation *nav = NULL;
1499 struct map *map = NULL;
1500 struct map_rect *mr = NULL;
1501 struct item *item = NULL;
1502 struct graphics_image *gr_image = NULL;
1503 char *image;
1504 char *name = "unknown";
1505 int level = this->level;
1506 char *street_destin_text = NULL;
1507
1508
1509 // -- WHO writes code in this style ??????
1510 // -- WHO writes code in this style ??????
1511 if (navit)
1512 nav = navit_get_navigation(navit);
1513 if (nav)
1514 map = navigation_get_map(nav);
1515 if (map)
1516 mr = map_rect_new(map, NULL);
1517 if (mr)
1518 while ((item = map_rect_get_item(mr))
1519 && (item->type == type_nav_position || item->type == type_nav_none || level-- > 0));
1520 // -- WHO writes code in this style ??????
1521 // -- WHO writes code in this style ??????
1522
1523
1524
1525 if (item)
1526 {
1527 name = item_to_name(item->type);
1528
1529 //if (street_destin_text)
1530 //{
1531 // g_free(street_destin_text);
1532 //}
1533
1534 struct attr attr_l;
1535 if (item_attr_get(item, attr_street_destination, &attr_l))
1536 {
1537 street_destin_text = g_strdup(attr_l.u.str);
1538 }
1539 else
1540 {
1541 street_destin_text = NULL;
1542 }
1543
1544 int dest_changed = 0;
1545 if ((street_destin_text == NULL) && (this->last_destination_name))
1546 {
1547 dest_changed = 1;
1548 }
1549 else if ((street_destin_text) && (this->last_destination_name == NULL))
1550 {
1551 dest_changed = 1;
1552 }
1553 else if ((street_destin_text) && (this->last_destination_name) && (strcmp(street_destin_text, this->last_destination_name) != 0) )
1554 {
1555 dest_changed = 1;
1556 }
1557
1558 if (dest_changed == 1)
1559 {
1560 if (osd_destination_name)
1561 {
1562 g_free(osd_destination_name);
1563 osd_destination_name = NULL;
1564 }
1565
1566 if (street_destin_text)
1567 {
1568 osd_destination_name = g_strdup(street_destin_text);
1569 }
1570 }
1571
1572 // dbg(0, "DST01:00X:1 sd=%s last=%s %d\n", street_destin_text, this->last_destination_name, dest_changed);
1573
1574 if (this->active != 1 || this->last_name != name || dest_changed)
1575 {
1576 this->active = 1;
1577 this->last_name = name;
1578 if (this->last_destination_name)
1579 {
1580 g_free(this->last_destination_name);
1581 this->last_destination_name = NULL;
1582 }
1583
1584 if (street_destin_text)
1585 {
1586 this->last_destination_name = g_strdup(street_destin_text);
1587 }
1588 else
1589 {
1590 this->last_destination_name = NULL;
1591 }
1592 do_draw = 1;
1593 }
1594 }
1595 else
1596 {
1597 if (this->active != 0)
1598 {
1599 this->active = 0;
1600 do_draw = 1;
1601 }
1602 }
1603
1604 if (do_draw)
1605 {
1606 //dbg(0, "DST01:000a\n");
1607
1608 if (this->active)
1609 {
1610 //dbg(0, "DST01:000b\n");
1611
1612 #ifdef HAVE_API_ANDROID
1613 android_send_generic_text(3, street_destin_text);
1614 #endif
1615
1616 image = g_strdup_printf(this->icon_src, name);
1617
1618 #ifdef HAVE_API_ANDROID
1619 send_osd_values("nav_next_turn","draw_image1",image,"",this->icon_w,this->icon_h,0,0,0.0,0.0,0.0);
1620 #endif
1621
1622 g_free(image);
1623 }
1624 }
1625
1626 if (street_destin_text)
1627 {
1628 g_free(street_destin_text);
1629 }
1630
1631 if (mr)
1632 {
1633 map_rect_destroy(mr);
1634 }
1635
1636 }
1637
1638 static void
1639 osd_nav_next_turn_init(struct nav_next_turn *this, struct navit *nav)
1640 {
1641 // dbg(0,,"EEnter\n");
1642
1643 //osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
1644 struct callback *cb;
1645 cb = callback_new_attr_1(callback_cast(osd_nav_next_turn_draw), attr_position_coord_geo, this);
1646 callback_add_names(cb, "osd_nav_next_turn_init", "osd_nav_next_turn_draw");
1647 navit_add_callback(nav, cb);
1648 //navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_std_click), attr_button, &this->osd_item));
1649 osd_nav_next_turn_draw(this, nav, NULL);
1650 }
1651
1652 struct osd_priv *
1653 osd_nav_next_turn_new(struct navit *nav, struct osd_methods *meth,
1654 struct attr **attrs)
1655 {
1656 // dbg(0,,"EEnter\n");
1657
1658 struct nav_next_turn *this = g_new0(struct nav_next_turn, 1);
1659 struct attr *attr;
1660
1661 this->osd_item.p.x = 20;
1662 this->osd_item.p.y = -80;
1663 this->osd_item.w = 70;
1664 this->osd_item.navit = nav;
1665 this->osd_item.h = 70;
1666 this->osd_item.font_size = 200;
1667 this->osd_item.meth.draw = osd_draw_cast(osd_nav_next_turn_draw);
1668 osd_set_std_attr(attrs, &this->osd_item, 0);
1669
1670 this->icon_w = -1;
1671 this->icon_h = -1;
1672 this->active = -1;
1673 this->level = 0;
1674
1675 attr = attr_search(attrs, NULL, attr_icon_w);
1676 if (attr)
1677 this->icon_w = attr->u.num;
1678
1679 attr = attr_search(attrs, NULL, attr_icon_h);
1680 if (attr)
1681 this->icon_h = attr->u.num;
1682
1683 attr = attr_search(attrs, NULL, attr_icon_src);
1684
1685
1686 if (attr)
1687 {
1688 /*
1689 struct file_wordexp *we;
1690 char **array;
1691 we = file_wordexp_new(attr->u.str);
1692 array = file_wordexp_get_array(we);
1693 this->icon_src = graphics_icon_path(array[0]);
1694 file_wordexp_destroy(we);
1695 */
1696
1697 this->icon_src = graphics_icon_path(attr->u.str);
1698 }
1699 else
1700 {
1701 this->icon_src = graphics_icon_path("%s_wh.svg");
1702 }
1703
1704
1705 attr = attr_search(attrs, NULL, attr_level);
1706 if (attr)
1707 {
1708 this->level=attr->u.num;
1709 }
1710
1711 struct callback *cb;
1712 cb = callback_new_attr_1(callback_cast(osd_nav_next_turn_init), attr_graphics_ready, this);
1713 callback_add_names(cb, "osd_nav_next_turn_new", "osd_nav_next_turn_init");
1714 navit_add_callback(nav, cb);
1715
1716 return (struct osd_priv *) this;
1717 }
1718
1719 struct nav_toggle_announcer
1720 {
1721 int w,h;
1722 struct callback *navit_init_cb;
1723 struct osd_item item;
1724 char *icon_src;
1725 int icon_h, icon_w, active, last_state;
1726 };
1727
1728 static void
1729 osd_nav_toggle_announcer_draw(struct nav_toggle_announcer *this, struct navit *navit, struct vehicle *v)
1730 {
1731 struct point p;
1732 int do_draw = 0;
1733 struct graphics_image *gr_image;
1734 char *path;
1735 char *gui_sound_off = "gui_sound_off";
1736 char *gui_sound_on = "gui_sound";
1737 struct attr attr, speechattr;
1738
1739 if (this->last_state == -1)
1740 {
1741 if (!navit_get_attr(navit, attr_speech, &speechattr, NULL))
1742 if (!speech_get_attr(speechattr.u.speech, attr_active, &attr, NULL))
1743 attr.u.num = 1;
1744 this->active = attr.u.num;
1745 } else
1746 this->active = !this->active;
1747
1748 if(this->active != this->last_state)
1749 {
1750 this->last_state = this->active;
1751 do_draw = 1;
1752 }
1753
1754 if (do_draw)
1755 {
1756 graphics_draw_mode(this->item.gr, draw_mode_begin);
1757 p.x = 0;
1758 p.y = 0;
1759 graphics_draw_rectangle(this->item.gr, this->item.graphic_bg, &p, this->item.w, this->item.h);
1760
1761 if (this->active)
1762 path = g_strdup_printf(this->icon_src, gui_sound_on);
1763 else
1764 path = g_strdup_printf(this->icon_src, gui_sound_off);
1765
1766 gr_image = graphics_image_new_scaled(this->item.gr, path, this->icon_w, this->icon_h);
1767 if (!gr_image)
1768 {
1769 g_free(path);
1770 path = graphics_icon_path("unknown.xpm");
1771 gr_image = graphics_image_new_scaled(this->item.gr, path, this->icon_w, this->icon_h);
1772 }
1773
1774 dbg(1, "gr_image=%p\n", gr_image);
1775
1776 if (gr_image)
1777 {
1778 p.x = (this->item.w - gr_image->width) / 2;
1779 p.y = (this->item.h - gr_image->height) / 2;
1780 graphics_draw_image(this->item.gr, this->item.graphic_fg_white, &p, gr_image);
1781 graphics_image_free(this->item.gr, gr_image);
1782 }
1783
1784 g_free(path);
1785 graphics_draw_mode(this->item.gr, draw_mode_end);
1786 }
1787 }
1788
1789 static void
1790 osd_nav_toggle_announcer_init(struct nav_toggle_announcer *this, struct navit *nav)
1791 {
1792 osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
1793 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_nav_toggle_announcer_draw), attr_speech, this));
1794 navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast(osd_std_click), attr_button, &this->item));
1795 osd_nav_toggle_announcer_draw(this, nav, NULL);
1796 }
1797
1798 struct osd_priv *
1799 osd_nav_toggle_announcer_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
1800 {
1801 struct nav_toggle_announcer *this = g_new0(struct nav_toggle_announcer, 1);
1802 struct attr *attr;
1803 char *command = "announcer_toggle()";
1804
1805 this->item.w = 48;
1806 this->item.h = 48;
1807 this->item.p.x = -64;
1808 this->item.navit = nav;
1809 this->item.p.y = 76;
1810 this->item.meth.draw = osd_draw_cast(osd_nav_toggle_announcer_draw);
1811
1812 osd_set_std_attr(attrs, &this->item, 0);
1813
1814 this->icon_w = -1;
1815 this->icon_h = -1;
1816 this->last_state = -1;
1817
1818 attr = attr_search(attrs, NULL, attr_icon_src);
1819
1820 /*
1821 if (attr) {
1822 struct file_wordexp *we;
1823 char **array;
1824 we = file_wordexp_new(attr->u.str);
1825 array = file_wordexp_get_array(we);
1826 this->icon_src = g_strdup(array[0]);
1827 file_wordexp_destroy(we);
1828 } else
1829 this->icon_src = graphics_icon_path("%s_32.xpm");
1830 */
1831
1832 this->item.command = g_strdup(command);
1833
1834 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_nav_toggle_announcer_init), attr_graphics_ready, this));
1835 return (struct osd_priv *) this;
1836 }
1837
1838 enum osd_speed_warner_eAnnounceState {eNoWarn=0,eWarningTold=1};
1839 enum camera_t {CAM_FIXED=1, CAM_TRAFFIC_LAMP, CAM_RED, CAM_SECTION, CAM_MOBILE, CAM_RAIL, CAM_TRAFFIPAX};
1840 char*camera_t_strs[] = {"None","Fix","Traffic lamp","Red detect","Section","Mobile","Rail","Traffipax(non persistent)"};
1841 char*camdir_t_strs[] = {"All dir.","UNI-dir","BI-dir"};
1842 enum cam_dir_t {CAMDIR_ALL=0, CAMDIR_ONE, CAMDIR_TWO};
1843
1844 struct osd_speed_cam_entry {
1845 double lon;
1846 double lat;
1847 enum camera_t cam_type;
1848 int speed_limit;
1849 enum cam_dir_t cam_dir;
1850 int direction;
1851 };
1852
1853 struct osd_speed_cam {
1854 struct osd_item item;
1855 int width;
1856 struct graphics_gc *white,*orange;
1857 struct graphics_gc *red;
1858 struct color idle_color;
1859
1860 int announce_on;
1861 enum osd_speed_warner_eAnnounceState announce_state;
1862 char *text; //text of label attribute for this osd
1863 };
1864
1865 static double
1866 angle_diff(int firstAngle,int secondAngle)
1867 {
1868 double difference = secondAngle - firstAngle;
1869 while (difference < -180) difference += 360;
1870 while (difference > 180) difference -= 360;
1871 return difference;
1872 }
1873
1874 static void
1875 osd_speed_cam_draw(struct osd_speed_cam *this_, struct navit *navit, struct vehicle *v)
1876 {
1877 struct attr position_attr,vehicle_attr,imperial_attr;
1878 struct point p, bbox[4];
1879 struct attr speed_attr;
1880 struct vehicle* curr_vehicle = v;
1881 struct coord curr_coord;
1882 struct coord cam_coord;
1883 struct mapset* ms;
1884
1885 double dCurrDist = -1;
1886 int dir_idx = -1;
1887 int dir = -1;
1888 int spd = -1;
1889 int idx = -1;
1890 double speed = -1;
1891 int bFound = 0;
1892
1893 int dst=2000;
1894 int dstsq=dst*dst;
1895 struct map_selection sel;
1896 struct map_rect *mr;
1897 struct mapset_handle *msh;
1898 struct map *map;
1899 struct item *item;
1900
1901 struct attr attr_dir;
1902 struct graphics_gc *curr_color;
1903 int ret_attr = 0;
1904 int imperial=0;
1905
1906 if (navit_get_attr(navit, attr_imperial, &imperial_attr, NULL))
1907 imperial=imperial_attr.u.num;
1908
1909
1910 if(navit) {
1911 navit_get_attr(navit, attr_vehicle, &vehicle_attr, NULL);
1912 }
1913 else {
1914 return;
1915 }
1916 if (vehicle_attr.u.vehicle) {
1917 curr_vehicle = vehicle_attr.u.vehicle;
1918 }
1919
1920 if(0==curr_vehicle)
1921 return;
1922
1923 if(!(ms=navit_get_mapset(navit))) {
1924 return;
1925 }
1926
1927 ret_attr = vehicle_get_attr(curr_vehicle, attr_position_coord_geo,&position_attr, NULL);
1928 if(0==ret_attr) {
1929 return;
1930 }
1931
1932 transform_from_geo(projection_mg, position_attr.u.coord_geo, &curr_coord);
1933
1934 sel.next=NULL;
1935 sel.order=18;
1936 sel.range.min=type_tec_common;
1937 sel.range.max=type_tec_common;
1938 sel.u.c_rect.lu.x=curr_coord.x-dst;
1939 sel.u.c_rect.lu.y=curr_coord.y+dst;
1940 sel.u.c_rect.rl.x=curr_coord.x+dst;
1941 sel.u.c_rect.rl.y=curr_coord.y-dst;
1942
1943 msh=mapset_open(ms);
1944 while ((map=mapset_next(msh, 1))) {
1945 struct attr attr;
1946 if(map_get_attr(map, attr_type, &attr, NULL)) {
1947 if( strcmp("csv", attr.u.str) && strcmp("binfile", attr.u.str)) {
1948 continue;
1949 }
1950 }
1951 else {
1952 continue;
1953 }
1954 mr=map_rect_new(map, &sel);
1955 if (!mr)
1956 continue;
1957 while ((item=map_rect_get_item(mr))) {
1958 struct coord cn;
1959 if (item->type == type_tec_common && item_coord_get(item, &cn, 1)) {
1960 int dist=transform_distance_sq(&cn, &curr_coord);
1961 if (dist < dstsq) {
1962 struct attr tec_attr;
1963 bFound = 1;
1964 dstsq=dist;
1965 dCurrDist = sqrt(dist);
1966 cam_coord = cn;
1967 idx = -1;
1968 if(item_attr_get(item,attr_tec_type,&tec_attr)) {
1969 idx = tec_attr.u.num;
1970 }
1971 dir_idx = -1;
1972 if(item_attr_get(item,attr_tec_dirtype,&tec_attr)) {
1973 dir_idx = tec_attr.u.num;
1974 }
1975 dir= 0;
1976 if(item_attr_get(item,attr_tec_direction,&tec_attr)) {
1977 dir = tec_attr.u.num;
1978 }
1979 spd= 0;
1980 if(item_attr_get(item,attr_maxspeed,&tec_attr)) {
1981 spd = tec_attr.u.num;
1982 }
1983 }
1984 }
1985 }
1986 map_rect_destroy(mr);
1987 }
1988 mapset_close(msh);
1989
1990 if(bFound) {
1991 dCurrDist = transform_distance(projection_mg, &curr_coord, &cam_coord);
1992 ret_attr = vehicle_get_attr(curr_vehicle,attr_position_speed,&speed_attr, NULL);
1993 if(0==ret_attr) {
1994 graphics_overlay_disable(this_->item.gr,1);
1995 return;
1996 }
1997 graphics_overlay_disable(this_->item.gr,0);
1998 speed = *speed_attr.u.numd;
1999 if(dCurrDist <= speed*750.0/130.0) { //at speed 130 distance limit is 750m
2000 if(this_->announce_state==eNoWarn && this_->announce_on) {
2001 this_->announce_state=eWarningTold; //warning told
2002 navit_say(navit, _("Look out! Camera!"));
2003 }
2004 }
2005 else {
2006 this_->announce_state=eNoWarn;
2007 }
2008
2009 if(this_->text) {
2010 char buffer [256]="";
2011 char buffer2[256]="";
2012 char dir_str[16];
2013 char spd_str[16];
2014 buffer [0] = 0;
2015 buffer2[0] = 0;
2016
2017 osd_std_draw(&this_->item);
2018
2019 str_replace(buffer,this_->text,"${distance}",format_distance(dCurrDist,"",imperial));
2020 str_replace(buffer2,buffer,"${camera_type}",(0<=idx && idx<=CAM_TRAFFIPAX)?camera_t_strs[idx]:"");
2021 str_replace(buffer,buffer2,"${camera_dir}",(0<=dir_idx && dir_idx<=CAMDIR_TWO)?camdir_t_strs[dir_idx]:"");
2022 sprintf(dir_str,"%d",dir);
2023 sprintf(spd_str,"%d",spd);
2024 str_replace(buffer2,buffer,"${direction}",dir_str);
2025 str_replace(buffer,buffer2,"${speed_limit}",spd_str);
2026
2027 graphics_get_text_bbox(this_->item.gr, this_->item.font, buffer, 0x10000, 0, bbox, 0);
2028 p.x=(this_->item.w-bbox[2].x)/2;
2029 p.y = this_->item.h-this_->item.h/10;
2030 curr_color = this_->orange;
2031 //tolerance is +-20 degrees
2032 if(
2033 dir_idx==CAMDIR_ONE &&
2034 dCurrDist <= speed*750.0/130.0 &&
2035 vehicle_get_attr(v, attr_position_direction, &attr_dir, NULL) &&
2036 fabs(angle_diff(dir,*attr_dir.u.numd))<=20 ) {
2037 curr_color = this_->red;
2038 }
2039 //tolerance is +-20 degrees in both directions
2040 else if(
2041 dir_idx==CAMDIR_TWO &&
2042 dCurrDist <= speed*750.0/130.0 &&
2043 vehicle_get_attr(v, attr_position_direction, &attr_dir, NULL) &&
2044 (fabs(angle_diff(dir,*attr_dir.u.numd))<=20 || fabs(angle_diff(dir+180,*attr_dir.u.numd))<=20 )) {
2045 curr_color = this_->red;
2046 }
2047 else if(dCurrDist <= speed*750.0/130.0) {
2048 curr_color = this_->red;
2049 }
2050 graphics_draw_text(this_->item.gr, curr_color, NULL, this_->item.font, buffer, &p, 0x10000, 0);
2051 graphics_draw_mode(this_->item.gr, draw_mode_end);
2052 }
2053 }
2054 else {
2055 graphics_overlay_disable(this_->item.gr,1);
2056 }
2057 }
2058
2059 static void
2060 osd_speed_cam_init(struct osd_speed_cam *this, struct navit *nav)
2061 {
2062 struct color red_color={0xffff,0x0000,0x0000,0xffff};
2063 osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
2064
2065 this->red = graphics_gc_new(this->item.gr);
2066 graphics_gc_set_foreground(this->red, &red_color);
2067 graphics_gc_set_linewidth(this->red, this->width);
2068
2069 this->orange = graphics_gc_new(this->item.gr);
2070 graphics_gc_set_foreground(this->orange, &this->idle_color);
2071 graphics_gc_set_linewidth(this->orange, this->width);
2072
2073 this->white = graphics_gc_new(this->item.gr);
2074 graphics_gc_set_foreground(this->white, &this->item.text_color);
2075 graphics_gc_set_linewidth(this->white, this->width);
2076
2077
2078 graphics_gc_set_linewidth(this->item.graphic_fg_white, this->width);
2079
2080 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_speed_cam_draw), attr_position_coord_geo, this));
2081
2082 }
2083
2084 struct osd_priv *
2085 osd_speed_cam_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
2086 {
2087
2088 struct color default_color={0xffff,0xa5a5,0x0000,0xffff};
2089
2090 struct osd_speed_cam *this = g_new0(struct osd_speed_cam, 1);
2091 struct attr *attr;
2092 this->item.p.x = 120;
2093 this->item.p.y = 20;
2094 this->item.w = 60;
2095 this->item.h = 80;
2096 this->item.navit = nav;
2097 this->item.font_size = 200;
2098 this->item.meth.draw = osd_draw_cast(osd_speed_cam_draw);
2099
2100 osd_set_std_attr(attrs, &this->item, 2);
2101 attr = attr_search(attrs, NULL, attr_width);
2102 this->width=attr ? attr->u.num : 2;
2103 attr = attr_search(attrs, NULL, attr_idle_color);
2104 this->idle_color=attr ? *attr->u.color : default_color; // text idle_color defaults to orange
2105
2106 attr = attr_search(attrs, NULL, attr_label);
2107 if (attr) {
2108 this->text = g_strdup(attr->u.str);
2109 }
2110 else
2111 this->text = NULL;
2112
2113 attr = attr_search(attrs, NULL, attr_announce_on);
2114 if (attr) {
2115 this->announce_on = attr->u.num;
2116 }
2117 else {
2118 this->announce_on = 1; //announce by default
2119 }
2120
2121 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_speed_cam_init), attr_graphics_ready, this));
2122 return (struct osd_priv *) this;
2123 }
2124
2125 struct osd_speed_warner {
2126 struct osd_item item;
2127 struct graphics_gc *red;
2128 struct graphics_gc *green;
2129 struct graphics_gc *grey;
2130 struct graphics_gc *black;
2131 struct graphics_gc *white;
2132 int width;
2133 int active;
2134 int d;
2135 double speed_exceed_limit_offset;
2136 double speed_exceed_limit_percent;
2137 int announce_on;
2138 enum osd_speed_warner_eAnnounceState announce_state;
2139 int bTextOnly;
2140 struct graphics_image *img_active,*img_passive,*img_off;
2141 char* label_str;
2142 };
2143
2144 static void
2145 osd_speed_warner_draw(struct osd_speed_warner *this, struct navit *navit, struct vehicle *v)
2146 {
2147 struct point p,bbox[4];
2148 char text[16]="";
2149
2150 struct tracking *tracking = NULL;
2151 struct graphics_gc *osd_color=this->grey;
2152 struct graphics_image *img = this->img_off;
2153
2154
2155 osd_std_draw(&this->item);
2156 p.x=this->item.w/2-this->d/4;
2157 p.y=this->item.h/2-this->d/4;
2158 p.x=this->item.w/2;
2159 p.y=this->item.h/2;
2160
2161 if (navit) {
2162 tracking = navit_get_tracking(navit);
2163 }
2164 if (tracking) {
2165
2166 struct attr maxspeed_attr,speed_attr,imperial_attr;
2167 int *flags;
2168 double routespeed = -1;
2169 double tracking_speed = -1;
2170 int osm_data = 0;
2171 struct item *item;
2172 int imperial=0;
2173
2174 item=tracking_get_current_item(tracking);
2175
2176 if(navit) {
2177 if (navit_get_attr(navit, attr_imperial, &imperial_attr, NULL))
2178 imperial=imperial_attr.u.num;
2179 }
2180
2181 flags=tracking_get_current_flags(tracking);
2182 if (flags && (*flags & NAVIT_AF_SPEED_LIMIT) && tracking_get_attr(tracking, attr_maxspeed, &maxspeed_attr, NULL)) {
2183 routespeed = maxspeed_attr.u.num;
2184 osm_data = 1;
2185 }
2186 if (routespeed == -1) {
2187 struct vehicleprofile *prof=navit_get_vehicleprofile(navit);
2188 struct roadprofile *rprof=NULL;
2189 if (prof && item)
2190 rprof=vehicleprofile_get_roadprofile(prof, item->type);
2191 if (rprof) {
2192 if(rprof->maxspeed!=0)
2193 routespeed=rprof->maxspeed;
2194 }
2195 }
2196 tracking_get_attr(tracking, attr_position_speed, &speed_attr, NULL);
2197 tracking_speed = *speed_attr.u.numd;
2198 if( -1 != tracking_speed && -1 != routespeed ) {
2199 char*routespeed_str = format_speed(routespeed,"","value",imperial);
2200 g_snprintf(text,16,"%s%s",osm_data ? "" : "~",routespeed_str);
2201 g_free(routespeed_str);
2202 if( this->speed_exceed_limit_offset+routespeed<tracking_speed &&
2203 (100.0+this->speed_exceed_limit_percent)/100.0*routespeed<tracking_speed ) {
2204 if(this->announce_state==eNoWarn && this->announce_on) {
2205 this->announce_state=eWarningTold; //warning told
2206 navit_say(navit,_("Please decrease your speed"));
2207 }
2208 }
2209 if( tracking_speed <= routespeed ) {
2210 this->announce_state=eNoWarn; //no warning
2211 osd_color = this->green;
2212 img = this->img_passive;
2213 }
2214 else {
2215 osd_color = this->red;
2216 img = this->img_active;
2217 }
2218 } else {
2219 osd_color = this->grey;
2220 img = this->img_off;
2221 this->announce_state = eNoWarn;
2222 }
2223 } else {
2224 //when tracking is not available display grey
2225 osd_color = this->grey;
2226 img = this->img_off;
2227 this->announce_state = eNoWarn;
2228 }
2229 if(this->img_active && this->img_passive && this->img_off) {
2230 struct point p;
2231 p.x=(this->item.w-img->width)/2;
2232 p.y=(this->item.h-img->height)/2;
2233 graphics_draw_image(this->item.gr, this->item.graphic_bg, &p, img);
2234 }
2235 else if(0==this->bTextOnly) {
2236 graphics_draw_circle(this->item.gr, osd_color, &p, this->d-this->width*2 );
2237 }
2238 graphics_get_text_bbox(this->item.gr, this->item.font, text, 0x10000, 0, bbox, 0);
2239 p.x=(this->item.w-bbox[2].x)/2;
2240 p.y=(this->item.h+bbox[2].y)/2-bbox[2].y;
2241 graphics_draw_text(this->item.gr, osd_color, NULL, this->item.font, text, &p, 0x10000, 0);
2242 graphics_draw_mode(this->item.gr, draw_mode_end);
2243 }
2244
2245 static void
2246 osd_speed_warner_init(struct osd_speed_warner *this, struct navit *nav)
2247 {
2248 struct color white_color={0xffff,0xffff,0xffff,0x0000};
2249 struct color red_color={0xffff,0,0,0xffff};
2250 struct color green_color={0,0xffff,0,0xffff};
2251 struct color grey_color={0x8888,0x8888,0x8888,0x8888};
2252 struct color black_color={0x1111,0x1111,0x1111,0x9999};
2253
2254 osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
2255 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_speed_warner_draw), attr_position_coord_geo, this));
2256
2257 if(this->label_str && !strncmp("images:",this->label_str,7)) {
2258 char *tok1=NULL, *tok2=NULL, *tok3=NULL;
2259 strtok(this->label_str,":");
2260 tok1 = strtok(NULL,":");
2261 if(tok1) {
2262 tok2 = strtok(NULL,":");
2263 }
2264 if(tok1 && tok2) {
2265 tok3 = strtok(NULL,":");
2266 }
2267 if(tok1 && tok2 && tok3) {
2268 tok1 = graphics_icon_path(tok1);
2269 tok2 = graphics_icon_path(tok2);
2270 tok3 = graphics_icon_path(tok3);
2271 this->img_active = graphics_image_new(this->item.gr, tok1);
2272 this->img_passive = graphics_image_new(this->item.gr, tok2);
2273 this->img_off = graphics_image_new(this->item.gr, tok3);
2274 g_free(tok1);
2275 g_free(tok2);
2276 g_free(tok3);
2277 }
2278 }
2279
2280 g_free(this->label_str);
2281 this->label_str = NULL;
2282
2283 this->white=graphics_gc_new(this->item.gr);
2284 graphics_gc_set_foreground(this->white, &white_color);
2285
2286 graphics_gc_set_linewidth(this->white, this->d/2-2 /*-this->width*/ );
2287
2288 this->red=graphics_gc_new(this->item.gr);
2289 graphics_gc_set_foreground(this->red, &red_color);
2290 graphics_gc_set_linewidth(this->red, this->width);
2291
2292 this->green=graphics_gc_new(this->item.gr);
2293 graphics_gc_set_foreground(this->green, &green_color);
2294 graphics_gc_set_linewidth(this->green, this->width-2);
2295
2296 this->grey=graphics_gc_new(this->item.gr);
2297 graphics_gc_set_foreground(this->grey, &grey_color);
2298 graphics_gc_set_linewidth(this->grey, this->width);
2299
2300 this->black=graphics_gc_new(this->item.gr);
2301 graphics_gc_set_foreground(this->black, &black_color);
2302 graphics_gc_set_linewidth(this->black, this->width);
2303
2304 osd_speed_warner_draw(this, nav, NULL);
2305 }
2306
2307 struct osd_priv *
2308 osd_speed_warner_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
2309 {
2310 struct osd_speed_warner *this=g_new0(struct osd_speed_warner, 1);
2311 struct attr *attr;
2312 this->item.p.x=-80;
2313 this->item.p.y=20;
2314 this->item.w=60;
2315 this->item.navit = nav;
2316 this->item.h=60;
2317 this->active=-1;
2318 this->item.meth.draw = osd_draw_cast(osd_speed_warner_draw);
2319
2320 attr = attr_search(attrs, NULL, attr_speed_exceed_limit_offset);
2321 if (attr) {
2322 this->speed_exceed_limit_offset = attr->u.num;
2323 } else
2324 this->speed_exceed_limit_offset = 15; //by default 15 km/h
2325
2326 attr = attr_search(attrs, NULL, attr_speed_exceed_limit_percent);
2327 if (attr) {
2328 this->speed_exceed_limit_percent = attr->u.num;
2329 } else
2330 this->speed_exceed_limit_percent = 10; //by default factor of 1.1
2331
2332 this->bTextOnly = 0; //by default display graphics also
2333 attr = attr_search(attrs, NULL, attr_label);
2334 if (attr) {
2335 this->label_str = g_strdup(attr->u.str);
2336 if (!strcmp("text_only",attr->u.str)) {
2337 this->bTextOnly = 1;
2338 }
2339 }
2340
2341 attr = attr_search(attrs, NULL, attr_announce_on);
2342 if (attr)
2343 this->announce_on = attr->u.num;
2344 else
2345 this->announce_on = 1; //announce by default
2346 osd_set_std_attr(attrs, &this->item, 2);
2347 this->d=this->item.w;
2348 if (this->item.h < this->d)
2349 this->d=this->item.h;
2350 this->width=this->d/10;
2351 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_speed_warner_init), attr_graphics_ready, this));
2352 return (struct osd_priv *) this;
2353 }
2354
2355 struct osd_text_item {
2356 int static_text;
2357 char *text;
2358 void *prev;
2359 void *next;
2360 enum attr_type section;
2361 enum attr_type attr_typ;
2362 void *root;
2363 int offset;
2364 char *format;
2365 };
2366
2367 struct osd_text {
2368 struct osd_item osd_item;
2369 int active;
2370 char *text;
2371 int align;
2372 char *last;
2373 struct osd_text_item *items;
2374 };
2375
2376
2377 /**
2378 * @brief Format a text attribute
2379 *
2380 * Returns the formatted current value of an attribute as a string
2381 *
2382 * @param attr Pointer to an attr structure specifying the attribute to be formatted
2383 * @param format Pointer to a string specifying how to format the attribute. Allowed format strings depend on the attribute; this member can be NULL.
2384 * @returns Pointer to a string containing the formatted value
2385 */
2386 static char *
2387 osd_text_format_attr(struct attr *attr, char *format, int imperial)
2388 {
2389 struct tm tm, text_tm, text_tm0;
2390 time_t textt;
2391 int days=0;
2392 char buffer[1024];
2393
2394 switch (attr->type)
2395 {
2396 case attr_position_speed:
2397 return format_speed(*attr->u.numd,"",format,imperial);
2398
2399 case attr_position_height:
2400 case attr_position_direction:
2401 return format_float_0(*attr->u.numd);
2402
2403 case attr_position_magnetic_direction:
2404 return g_strdup_printf("%d",attr->u.num);
2405
2406 case attr_position_coord_geo:
2407 if ((!format) || (!strcmp(format,"pos_degminsec")))
2408 {
2409 coord_format(attr->u.coord_geo->lat,attr->u.coord_geo->lng,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
2410 return g_strdup(buffer);
2411 }
2412 else if (!strcmp(format,"pos_degmin"))
2413 {
2414 coord_format(attr->u.coord_geo->lat,attr->u.coord_geo->lng,DEGREES_MINUTES,buffer,sizeof(buffer));
2415 return g_strdup(buffer);
2416 }
2417 else if (!strcmp(format,"pos_deg"))
2418 {
2419 coord_format(attr->u.coord_geo->lat,attr->u.coord_geo->lng,DEGREES_DECIMAL,buffer,sizeof(buffer));
2420 return g_strdup(buffer);
2421 }
2422 else if (!strcmp(format,"lat_degminsec"))
2423 {
2424 coord_format(attr->u.coord_geo->lat,360,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
2425 return g_strdup(buffer);
2426 }
2427 else if (!strcmp(format,"lat_degmin"))
2428 {
2429 coord_format(attr->u.coord_geo->lat,360,DEGREES_MINUTES,buffer,sizeof(buffer));
2430 return g_strdup(buffer);
2431 }
2432 else if (!strcmp(format,"lat_deg"))
2433 {
2434 coord_format(attr->u.coord_geo->lat,360,DEGREES_DECIMAL,buffer,sizeof(buffer));
2435 return g_strdup(buffer);
2436 }
2437 else if (!strcmp(format,"lng_degminsec"))
2438 {
2439 coord_format(360,attr->u.coord_geo->lng,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
2440 return g_strdup(buffer);
2441 }
2442 else if (!strcmp(format,"lng_degmin"))
2443 {
2444 coord_format(360,attr->u.coord_geo->lng,DEGREES_MINUTES,buffer,sizeof(buffer));
2445 return g_strdup(buffer);
2446 }
2447 else if (!strcmp(format,"lng_deg"))
2448 {
2449 coord_format(360,attr->u.coord_geo->lng,DEGREES_DECIMAL,buffer,sizeof(buffer));
2450 return g_strdup(buffer);
2451 }
2452 else
2453 { // fall back to pos_degminsec
2454 coord_format(attr->u.coord_geo->lat,attr->u.coord_geo->lng,DEGREES_MINUTES_SECONDS,buffer,sizeof(buffer));
2455 return g_strdup(buffer);
2456 }
2457
2458 case attr_destination_time:
2459 if (!format || (strcmp(format,"arrival") && strcmp(format,"remaining")))
2460 break;
2461
2462 textt = time(NULL);
2463 tm = *localtime(&textt);
2464
2465 if (!strcmp(format,"remaining"))
2466 {
2467 textt-=tm.tm_hour*3600+tm.tm_min*60+tm.tm_sec;
2468 tm = *localtime(&textt);
2469 }
2470
2471 textt += attr->u.num / 10;
2472 text_tm = *localtime(&textt);
2473
2474 if (tm.tm_year != text_tm.tm_year || tm.tm_mon != text_tm.tm_mon || tm.tm_mday != text_tm.tm_mday)
2475 {
2476 text_tm0 = text_tm;
2477 text_tm0.tm_sec = 0;
2478 text_tm0.tm_min = 0;
2479 text_tm0.tm_hour = 0;
2480 tm.tm_sec = 0;
2481 tm.tm_min = 0;
2482 tm.tm_hour = 0;
2483 days = (mktime(&text_tm0) - mktime(&tm) + 43200) / 86400;
2484 }
2485 return format_time(&text_tm, days);
2486
2487 case attr_length:
2488 case attr_destination_length:
2489 if (!format)
2490 break;
2491
2492 if (!strcmp(format,"named"))
2493 return format_distance(attr->u.num,"",imperial);
2494
2495 if (!strcmp(format,"value") || !strcmp(format,"unit"))
2496 {
2497 char *ret,*tmp=format_distance(attr->u.num," ",imperial);
2498 char *pos=strchr(tmp,' ');
2499 if (! pos)
2500 return tmp;
2501
2502 *pos++='\0';
2503 if (!strcmp(format,"value"))
2504 return tmp;
2505
2506 ret=g_strdup(pos);
2507 g_free(tmp);
2508
2509 return ret;
2510 }
2511 case attr_position_time_iso8601:
2512 if ((!format) || (!strcmp(format,"iso8601")))
2513 {
2514 break;
2515 }
2516 else
2517 {
2518 if (strstr(format, "local;") == format)
2519 {
2520 textt = iso8601_to_secs(attr->u.str);
2521 memcpy ((void *) &tm, (void *) localtime(&textt), sizeof(tm));
2522 strftime(buffer, sizeof(buffer), (char *)(format + 6), &tm);
2523 }
2524 else if ((sscanf(format, "%*c%2d:%2d;", &(text_tm.tm_hour), &(text_tm.tm_min)) == 2) && (strchr("+-", format[0])))
2525 {
2526 if (strchr("-", format[0]))
2527 {
2528 textt = iso8601_to_secs(attr->u.str) - text_tm.tm_hour * 3600 - text_tm.tm_min * 60;
2529 }
2530 else
2531 {
2532 textt = iso8601_to_secs(attr->u.str) + text_tm.tm_hour * 3600 + text_tm.tm_min * 60;
2533 }
2534 memcpy ((void *) &tm, (void *) gmtime(&textt), sizeof(tm));
2535 strftime(buffer, sizeof(buffer), &format[strcspn(format, ";") + 1], &tm);
2536 }
2537 else
2538 {
2539 sscanf(attr->u.str, "%4d-%2d-%2dT%2d:%2d:%2d", &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday), &(tm.tm_hour), &(tm.tm_min), &(tm.tm_sec));
2540 // the tm structure definition is kinda weird and needs some extra voodoo
2541 tm.tm_year-=1900; tm.tm_mon--;
2542 // get weekday and day of the year
2543 mktime(&tm);
2544 strftime(buffer, sizeof(buffer), format, &tm);
2545 }
2546 return g_strdup(buffer);
2547 }
2548 default:
2549 break;
2550 }
2551 return attr_to_text(attr, NULL, 1);
2552 }
2553
2554 /**
2555 * Parse a string of the form key.subkey or key[index].subkey into its components, where subkey can itself have its own index and further subkeys
2556 *
2557 * @param in String to parse (the part before subkey will be modified by the function); upon returning this pointer will point to a string containing key
2558 * @param index Pointer to an address that will receive a pointer to a string containing index or a null pointer if key does not have an index
2559 * @returns If the function succeeds, a pointer to a string containing subkey, i.e. everything following the first period, or a pointer to an empty string if there is nothing left to parse. If the function fails(index with missing closed bracket or passing a null pointer as index argument when an index was encountered), the return value is NULL
2560 */
2561 static char *
2562 osd_text_split(char *in, char **index)
2563 {
2564 char *pos;
2565 int len;
2566 if (index)
2567 *index=NULL;
2568 len=strcspn(in,"[.");
2569 in+=len;
2570 switch (in[0]) {
2571 case '\0':
2572 return in;
2573 case '.':
2574 *in++='\0';
2575 return in;
2576 case '[':
2577 if (!index)
2578 return NULL;
2579 *in++='\0';
2580 *index=in;
2581 pos=strchr(in,']');
2582 if (pos) {
2583 *pos++='\0';
2584 if (*pos == '.') {
2585 *pos++='\0';
2586 }
2587 return pos;
2588 }
2589 return NULL;
2590 }
2591 return NULL;
2592 }
2593
2594 static void
2595 osd_text_draw(struct osd_text *this, struct navit *navit, struct vehicle *v)
2596 {
2597
2598 struct point p, p2[4];
2599 char *str,*last,*next,*value,*absbegin;
2600 char *id_string=NULL;
2601 int do_draw = 0;
2602 struct attr attr, vehicle_attr, maxspeed_attr, imperial_attr;
2603 struct navigation *nav = NULL;
2604 struct tracking *tracking = NULL;
2605 struct route *route = NULL;
2606 struct map *nav_map = NULL;
2607 struct map_rect *nav_mr = NULL;
2608 struct item *item;
2609 struct osd_text_item *oti;
2610 int offset,lines;
2611 int height=this->osd_item.font_size*13/256;
2612 int yspacing=height/2;
2613 int xspacing=height/4;
2614 int imperial=0;
2615
2616 if (navit_get_attr(navit, attr_imperial, &imperial_attr, NULL))
2617 {
2618 imperial = imperial_attr.u.num;
2619 }
2620
2621 vehicle_attr.u.vehicle=NULL;
2622 oti=this->items;
2623 str=NULL;
2624
2625 while (oti)
2626 {
2627
2628 item=NULL;
2629 value=NULL;
2630 id_string=NULL;
2631
2632 if (oti->static_text)
2633 {
2634 value = g_strdup(oti->text);
2635 id_string = g_strdup("none:static_text:static_text");
2636 }
2637 else if (oti->section == attr_navigation)
2638 {
2639 if (navit && !nav)
2640 nav = navit_get_navigation(navit);
2641
2642 if (nav && !nav_map)
2643 nav_map = navigation_get_map(nav);
2644
2645 if (nav_map)
2646 nav_mr = map_rect_new(nav_map, NULL);
2647
2648 if (nav_mr)
2649 item = map_rect_get_item(nav_mr);
2650
2651 offset=oti->offset;
2652
2653 while (item)
2654 {
2655 if (item->type == type_nav_none)
2656 {
2657 item=map_rect_get_item(nav_mr);
2658 }
2659 else if (!offset)
2660 {
2661 break;
2662 }
2663 else
2664 {
2665 offset--;
2666 item=map_rect_get_item(nav_mr);
2667 }
2668 }
2669
2670
2671
2672
2673
2674 if (item)
2675 {
2676
2677
2678
2679
2680
2681
2682
2683
2684 if ((osd_core_item_id_hi == item->id_hi) && (osd_core_item_id_lo == item->id_lo) && (osd_core_item_id_map == item->map))
2685 {
2686 if ((oti->attr_typ == attr_street_name) && (street_name_save))
2687 {
2688 value = g_strdup(street_name_save);
2689 }
2690 else if ((oti->attr_typ == attr_street_name_systematic) && (street_name_systematic_save))
2691 {
2692 value = g_strdup(street_name_systematic_save);
2693 }
2694 else
2695 {
2696 if (item_attr_get(item, oti->attr_typ, &attr))
2697 {
2698 value = osd_text_format_attr(&attr, oti->format, imperial);
2699 }
2700 else
2701 {
2702 // send blank value
2703 value = g_strdup("");
2704 }
2705 }
2706 }
2707 else
2708 {
2709 if ((oti->attr_typ == attr_street_name) || (oti->attr_typ == attr_street_name_systematic))
2710 {
2711 if (item_attr_get(item, attr_street_name, &attr))
2712 {
2713 if (street_name_save)
2714 {
2715 g_free(street_name_save);
2716 }
2717 street_name_save = osd_text_format_attr(&attr, oti->format, imperial);
2718 }
2719 else
2720 {
2721 if (street_name_save)
2722 {
2723 g_free(street_name_save);
2724 }
2725 street_name_save = NULL;
2726 }
2727
2728 if (item_attr_get(item, attr_street_name_systematic, &attr))
2729 {
2730 if (street_name_systematic_save)
2731 {
2732 g_free(street_name_systematic_save);
2733 }
2734 street_name_systematic_save = osd_text_format_attr(&attr, oti->format, imperial);
2735 }
2736 else
2737 {
2738 if (street_name_systematic_save)
2739 {
2740 g_free(street_name_systematic_save);
2741 }
2742 street_name_systematic_save = NULL;
2743 }
2744
2745 osd_core_item_id_hi = item->id_hi;
2746 osd_core_item_id_lo = item->id_lo;
2747 osd_core_item_id_map = item->map;
2748
2749 }
2750
2751 if (item_attr_get(item, oti->attr_typ, &attr))
2752 {
2753 value = osd_text_format_attr(&attr, oti->format, imperial);
2754 }
2755 else
2756 {
2757 // send blank value
2758 value = g_strdup("");
2759 }
2760 }
2761
2762
2763 // -- for navigation use next destination if possible for OSD -----------
2764 if (oti->attr_typ == attr_street_name)
2765 {
2766 if (osd_destination_name)
2767 {
2768 if (value)
2769 {
2770 g_free(value);
2771 value = NULL;
2772 }
2773 value = g_strdup(osd_destination_name);
2774 }
2775 }
2776 else if (oti->attr_typ == attr_street_name_systematic)
2777 {
2778 #if 0
2779 if (osd_destination_name)
2780 {
2781 if (value)
2782 {
2783 g_free(value);
2784 value = NULL;
2785 }
2786 value = g_strdup("");
2787 }
2788 #endif
2789 }
2790 // -- for navigation use next destination if possible for OSD -----------
2791
2792 id_string = g_strdup_printf("navigation:%s:%s", item_to_name(item->type), attr_to_name(oti->attr_typ));
2793
2794
2795 #ifdef HAVE_API_ANDROID
2796 // -- now dirty hardcoded send time to target in seconds to JAVA --
2797 if (oti->attr_typ == attr_destination_time)
2798 {
2799 // ??? // if (!format || (strcmp(format,"arrival") && strcmp(format,"remaining")))
2800 char *value2 = g_strdup_printf("%d", (int)(attr.u.num / 10)); // time to target in [secs]
2801 send_osd_values("osd_text_draw","draw_text","navigation:nav_position:destination_secs_time",value2 ? value2 : "", 0,0,0,0, 0.0,0.0,0.0);
2802 g_free(value2);
2803 }
2804 #endif
2805
2806
2807 #if 0
2808
2809
2810 if ((osd_core_item_id_hi == item->id_hi) && (osd_core_item_id_lo == item->id_lo) && (osd_core_item_id_map == item->map))
2811 {
2812 if ((oti->attr_typ == attr_street_name) && (street_name_save))
2813 {
2814 value = g_strdup(street_name_save);
2815 }
2816 else if ((oti->attr_typ == attr_street_name_systematic) && (street_name_systematic_save))
2817 {
2818 value = g_strdup(street_name_systematic_save);
2819 }
2820 else
2821 {
2822 if (item_attr_get(item, oti->attr_typ, &attr))
2823 {
2824 value = osd_text_format_attr(&attr, oti->format, imperial);
2825 }
2826 }
2827 }
2828 else
2829 {
2830 if (item_attr_get(item, oti->attr_typ, &attr))
2831 {
2832 value = osd_text_format_attr(&attr, oti->format, imperial);
2833 }
2834 }
2835
2836 id_string = g_strdup_printf("navigation:%s:%s", item_to_name(item->type), attr_to_name(oti->attr_typ));
2837
2838
2839 if (oti->attr_typ == attr_street_name)
2840 {
2841 osd_core_item_id_hi = item->id_hi;
2842 osd_core_item_id_lo = item->id_lo;
2843 osd_core_item_id_map = item->map;
2844 if (street_name_save)
2845 {
2846 g_free(street_name_save);
2847 }
2848 street_name_save = g_strdup(value);
2849 }
2850 else if (oti->attr_typ == attr_street_name_systematic)
2851 {
2852 osd_core_item_id_hi = item->id_hi;
2853 osd_core_item_id_lo = item->id_lo;
2854 osd_core_item_id_map = item->map;
2855 if (street_name_systematic_save)
2856 {
2857 g_free(street_name_systematic_save);
2858 }
2859 street_name_systematic_save = g_strdup(value);
2860 }
2861
2862
2863 #endif
2864
2865
2866
2867 }
2868
2869
2870
2871
2872 if (nav_mr)
2873 {
2874 map_rect_destroy(nav_mr);
2875 }
2876 }
2877 else if (oti->section == attr_vehicle)
2878 {
2879 if (navit && !vehicle_attr.u.vehicle)
2880 {
2881 navit_get_attr(navit, attr_vehicle, &vehicle_attr, NULL);
2882 }
2883
2884 if (vehicle_attr.u.vehicle)
2885 {
2886 if (vehicle_get_attr(vehicle_attr.u.vehicle, oti->attr_typ, &attr, NULL))
2887 {
2888 value=osd_text_format_attr(&attr, oti->format, imperial);
2889 id_string=g_strdup_printf("vehicle:%s:", attr_to_name(oti->attr_typ));
2890 }
2891 }
2892 }
2893 else if (oti->section == attr_tracking)
2894 {
2895 if (navit)
2896 {
2897 tracking = navit_get_tracking(navit);
2898 route = navit_get_route(navit);
2899 }
2900
2901 if (tracking)
2902 {
2903 item = tracking_get_current_item(tracking);
2904
2905 if (item && (oti->attr_typ == attr_speed))
2906 {
2907 double routespeed = -1;
2908 int *flags=tracking_get_current_flags(tracking);
2909 if (flags && (*flags & NAVIT_AF_SPEED_LIMIT) && tracking_get_attr(tracking, attr_maxspeed, &maxspeed_attr, NULL))
2910 {
2911 routespeed = maxspeed_attr.u.num;
2912 }
2913
2914 if (routespeed == -1)
2915 {
2916 struct vehicleprofile *prof=navit_get_vehicleprofile(navit);
2917 struct roadprofile *rprof=NULL;
2918 if (prof)
2919 {
2920 rprof=vehicleprofile_get_roadprofile(prof, item->type);
2921 }
2922 if (rprof)
2923 {
2924 routespeed=rprof->speed;
2925 }
2926 }
2927 value = format_speed(routespeed,"", oti->format, imperial);
2928 id_string=g_strdup("tracking:speed:");
2929 }
2930 else if (item)
2931 {
2932
2933 if ((osd_core_item_id_hi_t == item->id_hi) && (osd_core_item_id_lo_t == item->id_lo) && (osd_core_item_id_map_t == item->map))
2934 {
2935 if ((oti->attr_typ == attr_street_name) && (street_name_save_t))
2936 {
2937 value = g_strdup(street_name_save_t);
2938 }
2939 else if ((oti->attr_typ == attr_street_name_systematic) && (street_name_systematic_save_t))
2940 {
2941 value = g_strdup(street_name_systematic_save_t);
2942 }
2943 else
2944 {
2945 if (tracking_get_attr(tracking, oti->attr_typ, &attr, NULL))
2946 {
2947 value = osd_text_format_attr(&attr, oti->format, imperial);
2948 }
2949 else
2950 {
2951 // send blank value
2952 value = g_strdup("");
2953 }
2954 }
2955 }
2956 else
2957 {
2958 if ((oti->attr_typ == attr_street_name) || (oti->attr_typ == attr_street_name_systematic))
2959 {
2960 if (tracking_get_attr(tracking, attr_street_name, &attr, NULL))
2961 {
2962 if (street_name_save_t)
2963 {
2964 g_free(street_name_save_t);
2965 }
2966 street_name_save_t = osd_text_format_attr(&attr, oti->format, imperial);
2967 }
2968 else
2969 {
2970 if (street_name_save_t)
2971 {
2972 g_free(street_name_save_t);
2973 }
2974 street_name_save_t = NULL;
2975 }
2976
2977 if (tracking_get_attr(tracking, attr_street_name_systematic, &attr, NULL))
2978 {
2979 if (street_name_systematic_save_t)
2980 {
2981 g_free(street_name_systematic_save_t);
2982 }
2983 street_name_systematic_save_t = osd_text_format_attr(&attr, oti->format, imperial);
2984 }
2985 else
2986 {
2987 if (street_name_systematic_save_t)
2988 {
2989 g_free(street_name_systematic_save_t);
2990 }
2991 street_name_systematic_save_t = NULL;
2992 }
2993
2994 osd_core_item_id_hi_t = item->id_hi;
2995 osd_core_item_id_lo_t = item->id_lo;
2996 osd_core_item_id_map_t = item->map;
2997
2998 }
2999
3000 if (tracking_get_attr(tracking, oti->attr_typ, &attr, NULL))
3001 {
3002 value=osd_text_format_attr(&attr, oti->format, imperial);
3003 }
3004 else
3005 {
3006 // send blank value
3007 value=g_strdup("");
3008 }
3009 }
3010
3011 id_string=g_strdup_printf("tracking:%s:", attr_to_name(oti->attr_typ));
3012 }
3013 }
3014 }
3015 else if (oti->section == attr_navit)
3016 {
3017 if (oti->attr_typ == attr_message)
3018 {
3019 struct message *msg;
3020 int len,offset;
3021 char *tmp;
3022
3023 msg = navit_get_messages(navit);
3024 len = 0;
3025
3026 while (msg)
3027 {
3028 len+= strlen(msg->text) + 2;
3029
3030 msg = msg->next;
3031 }
3032
3033 value = g_malloc(len +1);
3034
3035 msg = navit_get_messages(navit);
3036 offset = 0;
3037
3038 while (msg)
3039 {
3040 tmp = g_stpcpy((value+offset), msg->text);
3041 g_stpcpy(tmp, "\\n");
3042 offset += strlen(msg->text) + 2;
3043
3044 msg = msg->next;
3045 }
3046
3047 value[len] = '\0';
3048 }
3049 }
3050
3051 // id_string=g_strdup_printf("%s#+#%s:%s",id_string, str ? str:"",value ? value:" ");
3052
3053 #ifdef HAVE_API_ANDROID
3054 send_osd_values("osd_text_draw","draw_text",id_string,value ? value : "", 0,0,0,0, 0.0,0.0,0.0);
3055 #endif
3056 //// dbg(0,,"%s\n",id_string);
3057 if (id_string)
3058 {
3059 g_free(id_string);
3060 }
3061
3062 next=g_strdup_printf("%s%s",str ? str:"",value ? value:" ");
3063
3064 if (value)
3065 g_free(value);
3066
3067 if (str)
3068 g_free(str);
3069
3070 str=next;
3071 oti=oti->next;
3072 }
3073
3074 if ( this->last && str && !strcmp(this->last, str) )
3075 {
3076 do_draw=0;
3077 }
3078 else
3079 {
3080 do_draw=1;
3081
3082 if (this->last)
3083 g_free(this->last);
3084
3085 this->last = g_strdup(str);
3086 }
3087
3088 absbegin=str;
3089 if (do_draw)
3090 {
3091 // **DISABLE** osd_std_draw(&this->osd_item);
3092 }
3093 if (do_draw && str)
3094 {
3095 lines=0;
3096 next=str;
3097 last=str;
3098 while ((next=strstr(next, "\\n"))) {
3099 last = next;
3100 lines++;
3101 next++;
3102 }
3103
3104 while (*last) {
3105 if (! g_ascii_isspace(*last)) {
3106 lines++;
3107 break;
3108 }
3109 last++;
3110 }
3111
3112 // dbg(1,"this->align=%d\n", this->align);
3113 switch (this->align & 51)
3114 {
3115 case 1:
3116 p.y=0;
3117 break;
3118 case 2:
3119 p.y=(this->osd_item.h-lines*(height+yspacing)-yspacing);
3120 break;
3121 case 16: // Grow from top to bottom
3122 p.y = 0;
3123 if (lines != 0) {
3124 this->osd_item.h = (lines-1) * (height+yspacing) + height;
3125 } else {
3126 this->osd_item.h = 0;
3127 }
3128
3129 if (do_draw)
3130 {
3131 //osd_std_resize(&this->osd_item);
3132 }
3133 default:
3134 p.y=(this->osd_item.h-lines*(height+yspacing)-yspacing)/2;
3135 }
3136
3137 while (str)
3138 {
3139 next=strstr(str, "\\n");
3140 if (next)
3141 {
3142 *next='\0';
3143 next+=2;
3144 }
3145
3146 /*
3147 graphics_get_text_bbox(this->osd_item.gr,
3148 this->osd_item.font,
3149 str, 0x10000,
3150 0x0, p2, 0);
3151 */
3152
3153 /*
3154 switch (this->align & 12)
3155 {
3156 case 4:
3157 p.x=xspacing;
3158 break;
3159 case 8:
3160 p.x=this->osd_item.w-(p2[2].x-p2[0].x)-xspacing;
3161 break;
3162 default:
3163 p.x = ((p2[0].x - p2[2].x) / 2) + (this->osd_item.w / 2);
3164 }
3165 p.y += height+yspacing;
3166 */
3167
3168 // graphics_send_osd_values(this->osd_item.gr, this->osd_item.graphic_fg_text,"osd_text_draw","draw_text",str,"", 0,0,0,0, 0.0,0.0,0.0);
3169
3170 // **DISABLE**
3171 /*
3172 graphics_draw_text(this->osd_item.gr,
3173 this->osd_item.graphic_fg_text,
3174 NULL, this->osd_item.font,
3175 str, &p, 0x10000,
3176 0);
3177 */
3178 str=next;
3179 }
3180 }
3181
3182 if (do_draw)
3183 {
3184 // **DISABLE** graphics_draw_mode(this->osd_item.gr, draw_mode_end);
3185 }
3186 g_free(absbegin);
3187 }
3188
3189 /**
3190 * @brief Create a new osd_text_item and insert it into a linked list
3191 *
3192 * @param parent Pointer to the preceding osd_text_item structure in the list. If NULL, the new osd_text_item becomes the root element of a new list.
3193 * @returns A pointer to the new osd_text_item element.
3194 */
3195 static struct osd_text_item *
3196 oti_new(struct osd_text_item * parent)
3197 {
3198 // dbg(0,,"EEnter\n");
3199
3200 struct osd_text_item *this;
3201 this=g_new0(struct osd_text_item, 1);
3202 this->prev=parent;
3203
3204 if(!parent) {
3205 this->root=this;
3206 } else {
3207 parent->next=this;
3208 this->root=parent->root;
3209 }
3210
3211 return this;
3212 }
3213
3214 /**
3215 * @brief Prepare a text type OSD element
3216 *
3217 * Parses the label string (as specified in the XML file) for a text type OSD element into attributes and static text.
3218 *
3219 * @param this Pointer to an osd_text structure representing the OSD element. The items member of this structure will receive a pointer to a list of osd_text_item structures.
3220 * @param nav Pointer to a navit structure
3221 * @returns nothing
3222 */
3223 static void
3224 osd_text_prepare(struct osd_text *this, struct navit *nav)
3225 {
3226 // dbg(0,,"EEnter\n");
3227
3228 char *absbegin,*str,*start,*end,*key,*subkey,*index;
3229 struct osd_text_item *oti;
3230
3231 oti=NULL;
3232 str=g_strdup(this->text);
3233 absbegin=str;
3234
3235 while ((start=strstr(str, "${"))) {
3236
3237 *start='\0';
3238 start+=2;
3239
3240 // find plain text before
3241 if (start!=str) {
3242 oti = oti_new(oti);
3243 oti->static_text=1;
3244 oti->text=g_strdup(str);
3245
3246 }
3247
3248 end=strstr(start,"}");
3249 if (! end)
3250 break;
3251
3252 *end++='\0';
3253 key=start;
3254
3255 subkey=osd_text_split(key,NULL);
3256
3257 oti = oti_new(oti);
3258 oti->section=attr_from_name(key);
3259
3260 if (( oti->section == attr_navigation ||
3261 oti->section == attr_tracking) && subkey) {
3262 key=osd_text_split(subkey,&index);
3263
3264 if (index)
3265 oti->offset=atoi(index);
3266
3267 subkey=osd_text_split(key,&index);
3268
3269 if (!strcmp(key,"route_speed")) {
3270 oti->attr_typ=attr_speed;
3271 } else {
3272 oti->attr_typ=attr_from_name(key);
3273 }
3274 oti->format = g_strdup(index);
3275
3276 } else if ((oti->section == attr_vehicle || oti->section == attr_navit) && subkey) {
3277 key=osd_text_split(subkey,&index);
3278 if (!strcmp(subkey,"messages")) {
3279 oti->attr_typ=attr_message;
3280 } else {
3281 oti->attr_typ=attr_from_name(subkey);
3282 }
3283 oti->format = g_strdup(index);
3284 }
3285
3286 switch(oti->attr_typ)
3287 {
3288 struct callback *cb;
3289
3290 default:
3291 cb = callback_new_attr_1(callback_cast(osd_text_draw), attr_position_coord_geo, this);
3292 callback_add_names(cb, "osd_text_prepare", "osd_text_draw");
3293 navit_add_callback(nav, cb);
3294 break;
3295 }
3296
3297 str=(end);
3298 }
3299
3300 if(*str!='\0'){
3301 oti = oti_new(oti);
3302 oti->static_text=1;
3303 oti->text=g_strdup(str);
3304 }
3305
3306 if (oti)
3307 this->items=oti->root;
3308 else
3309 this->items=NULL;
3310
3311 g_free(absbegin);
3312
3313 }
3314
3315 static void
3316 osd_text_init(struct osd_text *this, struct navit *nav)
3317 {
3318 // dbg(0,,"EEnter\n");
3319
3320 //osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
3321
3322 struct callback *cb;
3323 cb = callback_new_attr_1(callback_cast(osd_std_click), attr_button, &this->osd_item);
3324 callback_add_names(cb, "osd_text_init", "osd_std_click");
3325 navit_add_callback(nav, cb);
3326
3327 osd_text_prepare(this,nav);
3328 osd_text_draw(this, nav, NULL);
3329 }
3330
3331 struct osd_priv *
3332 osd_text_new(struct navit *nav, struct osd_methods *meth,
3333 struct attr **attrs)
3334 {
3335 struct osd_text *this = g_new0(struct osd_text, 1);
3336 struct attr *attr;
3337
3338 this->osd_item.p.x = -80;
3339 this->osd_item.p.y = 20;
3340 this->osd_item.w = 60;
3341 this->osd_item.h = 20;
3342 this->osd_item.navit = nav;
3343 this->osd_item.font_size = 200;
3344 this->osd_item.meth.draw = osd_draw_cast(osd_text_draw);
3345 osd_set_std_attr(attrs, &this->osd_item, 2);
3346
3347 this->active = -1;
3348 this->last = NULL;
3349
3350 attr = attr_search(attrs, NULL, attr_label);
3351 if (attr)
3352 this->text = g_strdup(attr->u.str);
3353 else
3354 this->text = NULL;
3355
3356 attr = attr_search(attrs, NULL, attr_align);
3357
3358 if (attr)
3359 this->align=attr->u.num;
3360
3361 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_text_init), attr_graphics_ready, this));
3362
3363 return (struct osd_priv *) this;
3364 }
3365
3366 struct gps_status {
3367 struct osd_item osd_item;
3368 char *icon_src;
3369 int icon_h, icon_w, active;
3370 int strength;
3371 };
3372
3373 static void
3374 osd_gps_status_draw(struct gps_status *this, struct navit *navit,
3375 struct vehicle *v)
3376 {
3377 struct point p;
3378 int do_draw = 0;
3379 struct graphics_image *gr_image;
3380 char *image;
3381 struct attr attr, vehicle_attr;
3382 int strength=-1;
3383
3384 if (navit && navit_get_attr(navit, attr_vehicle, &vehicle_attr, NULL)) {
3385 if (vehicle_get_attr(vehicle_attr.u.vehicle, attr_position_fix_type, &attr, NULL)) {
3386 switch(attr.u.num) {
3387 case 1:
3388 case 2:
3389 strength=2;
3390 if (vehicle_get_attr(vehicle_attr.u.vehicle, attr_position_sats_used, &attr, NULL)) {
3391 dbg(1,"num=%d\n", attr.u.num);
3392 if (attr.u.num >= 3)
3393 strength=attr.u.num-1;
3394 if (strength > 5)
3395 strength=5;
3396 if (strength > 3) {
3397 if (vehicle_get_attr(vehicle_attr.u.vehicle, attr_position_hdop, &attr, NULL)) {
3398 if (*attr.u.numd > 2.0 && strength > 4)
3399 strength=4;
3400 if (*attr.u.numd > 4.0 && strength > 3)
3401 strength=3;
3402 }
3403 }
3404 }
3405 break;
3406 default:
3407 strength=1;
3408 }
3409 }
3410 }
3411 if (this->strength != strength) {
3412 this->strength=strength;
3413 do_draw=1;
3414 }
3415 if (do_draw) {
3416 osd_std_draw(&this->osd_item);
3417 if (this->active) {
3418 image = g_strdup_printf(this->icon_src, strength);
3419 gr_image = graphics_image_new_scaled(this->osd_item.gr, image, this->icon_w, this->icon_h);
3420 if (gr_image) {
3421 p.x = (this->osd_item.w - gr_image->width) / 2;
3422 p.y = (this->osd_item.h - gr_image->height) / 2;
3423 graphics_draw_image(this->osd_item.gr, this->osd_item. graphic_fg_white, &p, gr_image);
3424 graphics_image_free(this->osd_item.gr, gr_image);
3425 }
3426 g_free(image);
3427 }
3428 graphics_draw_mode(this->osd_item.gr, draw_mode_end);
3429 }
3430 }
3431
3432 static void
3433 osd_gps_status_init(struct gps_status *this, struct navit *nav)
3434 {
3435 osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
3436 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_gps_status_draw), attr_position_coord_geo, this));
3437 osd_gps_status_draw(this, nav, NULL);
3438 }
3439
3440 struct osd_priv *
3441 osd_gps_status_new(struct navit *nav, struct osd_methods *meth,
3442 struct attr **attrs)
3443 {
3444 struct gps_status *this = g_new0(struct gps_status, 1);
3445 struct attr *attr;
3446
3447 this->osd_item.p.x = 20;
3448 this->osd_item.p.y = -80;
3449 this->osd_item.w = 60;
3450 this->osd_item.navit = nav;
3451 this->osd_item.h = 40;
3452 this->osd_item.font_size = 200;
3453 this->osd_item.meth.draw = osd_draw_cast(osd_gps_status_draw);
3454 osd_set_std_attr(attrs, &this->osd_item, 0);
3455
3456 this->icon_w = -1;
3457 this->icon_h = -1;
3458 this->active = -1;
3459 this->strength = -2;
3460
3461 attr = attr_search(attrs, NULL, attr_icon_w);
3462 if (attr)
3463 this->icon_w = attr->u.num;
3464
3465 attr = attr_search(attrs, NULL, attr_icon_h);
3466 if (attr)
3467 this->icon_h = attr->u.num;
3468
3469 attr = attr_search(attrs, NULL, attr_icon_src);
3470 /*
3471 if (attr) {
3472 struct file_wordexp *we;
3473 char **array;
3474 we = file_wordexp_new(attr->u.str);
3475 array = file_wordexp_get_array(we);
3476 this->icon_src = g_strdup(array[0]);
3477 file_wordexp_destroy(we);
3478 } else
3479 this->icon_src = graphics_icon_path("gui_strength_%d_32_32.png");
3480 */
3481
3482 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_gps_status_init), attr_graphics_ready, this));
3483 return (struct osd_priv *) this;
3484 }
3485
3486
3487 struct volume {
3488 struct osd_item osd_item;
3489 char *icon_src;
3490 int icon_h, icon_w, active;
3491 int strength;
3492 struct callback *click_cb;
3493 };
3494
3495 static void
3496 osd_volume_draw(struct volume *this, struct navit *navit)
3497 {
3498 struct point p;
3499 struct graphics_image *gr_image;
3500 char *image;
3501
3502 osd_std_draw(&this->osd_item);
3503 if (this->active) {
3504 image = g_strdup_printf(this->icon_src, this->strength);
3505 gr_image = graphics_image_new_scaled(this->osd_item.gr, image, this->icon_w, this->icon_h);
3506 if (gr_image) {
3507 p.x = (this->osd_item.w - gr_image->width) / 2;
3508 p.y = (this->osd_item.h - gr_image->height) / 2;
3509 graphics_draw_image(this->osd_item.gr, this->osd_item. graphic_fg_white, &p, gr_image);
3510 graphics_image_free(this->osd_item.gr, gr_image);
3511 }
3512 g_free(image);
3513 }
3514 graphics_draw_mode(this->osd_item.gr, draw_mode_end);
3515 }
3516
3517 static void
3518 osd_volume_click(struct volume *this, struct navit *nav, int pressed, int button, struct point *p)
3519 {
3520 struct point bp = this->osd_item.p;
3521 osd_wrap_point(&bp, nav);
3522 if ((p->x < bp.x || p->y < bp.y || p->x > bp.x + this->osd_item.w || p->y > bp.y + this->osd_item.h) && !this->osd_item.pressed)
3523 return;
3524 navit_ignore_button(nav);
3525 if (pressed) {
3526 if (p->y - bp.y < this->osd_item.h/2)
3527 this->strength++;
3528 else
3529 this->strength--;
3530 if (this->strength < 0)
3531 this->strength=0;
3532 if (this->strength > 5)
3533 this->strength=5;
3534 osd_volume_draw(this, nav);
3535 }
3536 }
3537 static void
3538 osd_volume_init(struct volume *this, struct navit *nav)
3539 {
3540 osd_set_std_graphic(nav, &this->osd_item, (struct osd_priv *)this);
3541 navit_add_callback(nav, this->click_cb = callback_new_attr_1(callback_cast (osd_volume_click), attr_button, this));
3542 osd_volume_draw(this, nav);
3543 }
3544
3545 struct osd_priv *
3546 osd_volume_new(struct navit *nav, struct osd_methods *meth,
3547 struct attr **attrs)
3548 {
3549 struct volume *this = g_new0(struct volume, 1);
3550 struct attr *attr;
3551
3552 this->osd_item.p.x = 20;
3553 this->osd_item.p.y = -80;
3554 this->osd_item.w = 60;
3555 this->osd_item.navit = nav;
3556 this->osd_item.h = 40;
3557 this->osd_item.font_size = 200;
3558 this->osd_item.meth.draw = osd_draw_cast(osd_volume_draw);
3559 osd_set_std_attr(attrs, &this->osd_item, 0);
3560
3561 this->icon_w = -1;
3562 this->icon_h = -1;
3563 this->active = -1;
3564 this->strength = -1;
3565
3566 attr = attr_search(attrs, NULL, attr_icon_w);
3567 if (attr)
3568 this->icon_w = attr->u.num;
3569
3570 attr = attr_search(attrs, NULL, attr_icon_h);
3571 if (attr)
3572 this->icon_h = attr->u.num;
3573
3574 attr = attr_search(attrs, NULL, attr_icon_src);
3575
3576 /*
3577 if (attr) {
3578 struct file_wordexp *we;
3579 char **array;
3580 we = file_wordexp_new(attr->u.str);
3581 array = file_wordexp_get_array(we);
3582 this->icon_src = g_strdup(array[0]);
3583 file_wordexp_destroy(we);
3584 } else
3585 this->icon_src = graphics_icon_path("gui_strength_%d_32_32.png");
3586 */
3587
3588 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_volume_init), attr_graphics_ready, this));
3589 return (struct osd_priv *) this;
3590 }
3591
3592 struct osd_scale {
3593 int use_overlay;
3594 struct osd_item item;
3595 struct callback *draw_cb,*navit_init_cb;
3596 struct graphics_gc *black;
3597 };
3598
3599 static void
3600 osd_scale_draw(struct osd_scale *this, struct navit *nav)
3601 {
3602 // dbg(0,,"EEnter\n");
3603
3604 struct point bp,bp1,bp2;
3605 struct point p[10],bbox[4];
3606 struct coord c[2];
3607 struct attr transformation, imperial_attr;
3608 int len;
3609 double dist,exp,base,man;
3610 char *text;
3611 int w=this->item.w*9/10;
3612 int o=(this->item.w-w)/2;
3613 int imperial=0;
3614
3615 if (navit_get_attr(nav, attr_imperial, &imperial_attr, NULL))
3616 imperial=imperial_attr.u.num;
3617
3618 if (!navit_get_attr(nav, attr_transformation, &transformation, NULL))
3619 return;
3620 if (this->use_overlay)
3621 {
3622 // **DISABLE** graphics_draw_mode(this->item.gr, draw_mode_begin);
3623 bp.x=0;
3624 bp.y=0;
3625
3626 #ifdef HAVE_API_ANDROID
3627 send_osd_values("scale","draw_rectangle1","","",this->item.w, this->item.h,0,0,0.0,0.0,0.0);
3628 #endif
3629 // **DISABLE** graphics_draw_rectangle(this->item.gr, this->item.graphic_bg, &bp, this->item.w, this->item.h);
3630 } else {
3631 bp=this->item.p;
3632 osd_wrap_point(&bp, nav);
3633 }
3634 bp1=bp;
3635 bp1.y+=this->item.h/2;
3636 bp1.x+=o;
3637 bp2=bp1;
3638 bp2.x+=w;
3639 p[0]=bp1;
3640 p[1]=bp2;
3641 transform_reverse(transformation.u.transformation, &p[0], &c[0]);
3642 transform_reverse(transformation.u.transformation, &p[1], &c[1]);
3643 dist=transform_distance(transform_get_projection(transformation.u.transformation), &c[0], &c[1]);
3644 exp=floor(log10(dist));
3645 base=pow(10,exp);
3646 man=dist/base;
3647 if (man >= 5)
3648 man=5;
3649 else if (man >= 2)
3650 man=2;
3651 else
3652 man=1;
3653 len=this->item.w-man*base/dist*w;
3654 p[0].x+=len/2;
3655 p[1].x-=len/2;
3656 p[2]=p[0];
3657 p[3]=p[0];
3658 p[2].y-=this->item.h/10;
3659 p[3].y+=this->item.h/10;
3660 p[4]=p[1];
3661 p[5]=p[1];
3662 p[4].y-=this->item.h/10;
3663 p[5].y+=this->item.h/10;
3664 p[6]=p[2];
3665 p[6].x-=2;
3666 p[6].y-=2;
3667 p[7]=p[0];
3668 p[7].y-=2;
3669 p[8]=p[4];
3670 p[8].x-=2;
3671 p[8].y-=2;
3672
3673 #ifdef HAVE_API_ANDROID
3674 send_osd_values("scale","draw_rectangle2","","",len,this->item.h,0,0,0.0,0.0,0.0);
3675 #endif
3676
3677 // **DISABLE** graphics_draw_rectangle(this->item.gr, this->item.graphic_fg_white, p+6, 4,this->item.h/5+4);
3678 // **DISABLE** graphics_draw_rectangle(this->item.gr, this->item.graphic_fg_white, p+7, p[1].x-p[0].x, 4);
3679 // **DISABLE** graphics_draw_rectangle(this->item.gr, this->item.graphic_fg_white, p+8, 4,this->item.h/5+4);
3680 // **DISABLE** graphics_draw_lines(this->item.gr, this->black, p, 2);
3681 // **DISABLE** graphics_draw_lines(this->item.gr, this->black, p+2, 2);
3682 // **DISABLE** graphics_draw_lines(this->item.gr, this->black, p+4, 2);
3683 text=format_distance(man*base, "", imperial);
3684 graphics_get_text_bbox(this->item.gr, this->item.font, text, 0x10000, 0, bbox, 0);
3685 p[0].x=(this->item.w-bbox[2].x)/2+bp.x;
3686 p[0].y=bp.y+this->item.h-this->item.h/10;
3687
3688 #ifdef HAVE_API_ANDROID
3689 send_osd_values("scale","draw_text",text,"",0,0,0,0,0.0,0.0,0.0);
3690 #endif
3691
3692 // **DISABLE** graphics_draw_text(this->item.gr, this->black, this->item.graphic_fg_white, this->item.font, text, &p[0], 0x10000, 0);
3693 g_free(text);
3694 if (this->use_overlay)
3695 {
3696 // **DISABLE** graphics_draw_mode(this->item.gr, draw_mode_end);
3697 }
3698 }
3699
3700 static void
3701 osd_scale_init(struct osd_scale *this, struct navit *nav)
3702 {
3703 // dbg(0,,"EEnter\n");
3704
3705 /*
3706 struct color color_white={0xffff,0xffff,0xffff,0x0000};
3707 struct color color_black={0x0000,0x0000,0x0000,0x0000};
3708 struct graphics *gra = navit_get_graphics(nav);
3709 dbg(1, "enter\n");
3710 if (this->use_overlay) {
3711 osd_set_std_graphic(nav, &this->item, (struct osd_priv *)this);
3712 } else {
3713 this->item.configured=1;
3714 this->item.gr=gra;
3715 this->item.font = graphics_font_new(this->item.gr, this->item.font_size, 1);
3716 this->item.graphic_fg_white=graphics_gc_new(this->item.gr);
3717 this->item.color_white=color_white;
3718 graphics_gc_set_foreground(this->item.graphic_fg_white, &this->item.color_white);
3719 }
3720 this->black=graphics_gc_new(this->item.gr);
3721 graphics_gc_set_foreground(this->black, &color_black);
3722 graphics_add_callback(gra, this->draw_cb=callback_new_attr_2(callback_cast(osd_scale_draw), attr_postdraw, this, nav));
3723 if (navit_get_ready(nav) == 3)
3724 osd_scale_draw(this, nav);
3725
3726 */
3727 }
3728
3729 struct osd_priv *
3730 osd_scale_new(struct navit *nav, struct osd_methods *meth,
3731 struct attr **attrs)
3732 {
3733
3734 // dbg(0,,"EEnter\n");
3735
3736 struct osd_scale *this = g_new0(struct osd_scale, 1);
3737 struct attr *attr;
3738
3739 this->item.navit = nav;
3740 this->item.meth.draw = osd_draw_cast(osd_scale_draw);
3741
3742 osd_set_std_attr(attrs, &this->item, 3);
3743
3744 attr=attr_search(attrs, NULL, attr_use_overlay);
3745 if (attr)
3746 this->use_overlay=attr->u.num;
3747
3748 // navit_add_callback(nav, this->navit_init_cb = callback_new_attr_1(callback_cast (osd_scale_init), attr_graphics_ready, this));
3749
3750 return (struct osd_priv *) this;
3751 }
3752
3753 struct auxmap {
3754 struct osd_item osd_item;
3755 struct displaylist *displaylist;
3756 struct transformation *ntrans;
3757 struct transformation *trans;
3758 struct layout *layout;
3759 struct callback *postdraw_cb;
3760 struct graphics_gc *red;
3761 struct navit *nav;
3762 };
3763
3764 static void
3765 osd_auxmap_draw(struct auxmap *this)
3766 {
3767 int d=10;
3768 struct point p;
3769 struct attr mapset;
3770
3771 if (!this->osd_item.configured)
3772 return;
3773 if (!navit_get_attr(this->nav, attr_mapset, &mapset, NULL) || !mapset.u.mapset)
3774 return;
3775 p.x=this->osd_item.w/2;
3776 p.y=this->osd_item.h/2;
3777 transform_set_center(this->trans, transform_get_center(this->ntrans));
3778 transform_set_scale(this->trans, 64);
3779 transform_set_yaw(this->trans, transform_get_yaw(this->ntrans));
3780 transform_setup_source_rect(this->trans);
3781 transform_set_projection(this->trans, transform_get_projection(this->ntrans));
3782 #if 0
3783 graphics_displaylist_draw(this->osd_item.gr, this->displaylist, this->trans, this->layout, 4);
3784 #endif
3785 graphics_draw(this->osd_item.gr, this->displaylist, mapset.u.mapset, this->trans, this->layout, 0, NULL, 1);
3786 graphics_draw_circle(this->osd_item.gr, this->red, &p, d);
3787 graphics_draw_mode(this->osd_item.gr, draw_mode_end);
3788
3789 }
3790
3791 static void
3792 osd_auxmap_init(struct auxmap *this, struct navit *nav)
3793 {
3794 // dbg(0,,"EEnter\n");
3795
3796
3797 struct graphics *gra;
3798 struct attr attr;
3799 struct map_selection sel;
3800 struct color red={0xffff,0x0,0x0,0xffff};
3801
3802 this->nav=nav;
3803 if (! navit_get_attr(nav, attr_graphics, &attr, NULL))
3804 return;
3805 gra=attr.u.graphics;
3806 graphics_add_callback(gra, callback_new_attr_1(callback_cast(osd_auxmap_draw), attr_postdraw, this));
3807 if (! navit_get_attr(nav, attr_transformation, &attr, NULL))
3808 return;
3809 this->ntrans=attr.u.transformation;
3810 if (! navit_get_attr(nav, attr_displaylist, &attr, NULL))
3811 return;
3812 this->displaylist=attr.u.displaylist;
3813 if (! navit_get_attr(nav, attr_layout, &attr, NULL))
3814 return;
3815 this->layout=attr.u.layout;
3816 osd_set_std_graphic(nav, &this->osd_item, NULL);
3817 graphics_init(this->osd_item.gr);
3818 this->red=graphics_gc_new(gra);
3819 graphics_gc_set_foreground(this->red,&red);
3820 graphics_gc_set_linewidth(this->red,3);
3821 this->trans=transform_new();
3822 memset(&sel, 0, sizeof(sel));
3823 sel.u.p_rect.rl.x=this->osd_item.w;
3824 sel.u.p_rect.rl.y=this->osd_item.h;
3825 transform_set_screen_selection(this->trans, &sel);
3826 graphics_set_rect(this->osd_item.gr, &sel.u.p_rect);
3827 #if 0
3828 osd_auxmap_draw(this, nav);
3829 #endif
3830 }
3831
3832 struct osd_priv *
3833 osd_auxmap_new(struct navit *nav, struct osd_methods *meth, struct attr **attrs)
3834 {
3835 struct auxmap *this = g_new0(struct auxmap, 1);
3836
3837 this->osd_item.p.x = 20;
3838 this->osd_item.p.y = -80;
3839 this->osd_item.w = 60;
3840 this->osd_item.h = 40;
3841 this->osd_item.font_size = 200;
3842 osd_set_std_attr(attrs, &this->osd_item, 0);
3843
3844 navit_add_callback(nav, callback_new_attr_1(callback_cast(osd_auxmap_init), attr_navit, this));
3845 return (struct osd_priv *) this;
3846 }
3847
3848 #ifdef PLUGSSS
3849 void
3850 plugin_init(void)
3851 {
3852 //dbg(0,"osd plugin init\n");
3853 plugin_register_osd_type("compass", osd_compass_new);
3854 //dbg(0,"osd 1\n");
3855 plugin_register_osd_type("navigation_next_turn", osd_nav_next_turn_new);
3856 //dbg(0,"osd 2\n");
3857 plugin_register_osd_type("button", osd_button_new);
3858 //dbg(0,"osd 3\n");
3859 plugin_register_osd_type("toggle_announcer", osd_nav_toggle_announcer_new);
3860 //dbg(0,"osd 4\n");
3861 plugin_register_osd_type("speed_warner", osd_speed_warner_new);
3862 //dbg(0,"osd 5\n");
3863 plugin_register_osd_type("speed_cam", osd_speed_cam_new);
3864 //dbg(0,"osd 6\n");
3865 plugin_register_osd_type("text", osd_text_new);
3866 //dbg(0,"osd 7\n");
3867 plugin_register_osd_type("gps_status", osd_gps_status_new);
3868 //dbg(0,"osd 8\n");
3869 plugin_register_osd_type("volume", osd_volume_new);
3870 //dbg(0,"osd 10\n");
3871 plugin_register_osd_type("scale", osd_scale_new);
3872 //dbg(0,"osd 11\n");
3873 plugin_register_osd_type("image", osd_image_new);
3874 //dbg(0,"osd 12\n");
3875 plugin_register_osd_type("stopwatch", osd_stopwatch_new);
3876 //dbg(0,"osd 13\n");
3877 plugin_register_osd_type("odometer", osd_odometer_new);
3878 //dbg(0,"osd 14\n");
3879 plugin_register_osd_type("auxmap", osd_auxmap_new);
3880 //dbg(0,"osd 15\n");
3881 plugin_register_osd_type("cmd_interface", osd_cmd_interface_new);
3882 //dbg(0,"osd ready\n");
3883 }
3884 #endif
3885

   
Visit the ZANavi Wiki