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

   
Visit the ZANavi Wiki