/[zanavi_public1]/navit/navit/navigation.c
ZANavi

Contents of /navit/navit/navigation.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 30 - (hide annotations) (download)
Wed Aug 22 17:01:27 2012 UTC (11 years, 7 months ago) by zoff99
File MIME type: text/plain
File size: 81473 byte(s)
ZANavi 2.0, lots of changes, everything in its own thread, more performance
1 zoff99 2 /**
2 zoff99 27 * ZANavi, Zoff Android Navigation system.
3     * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
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     /**
21 zoff99 2 * Navit, a modular navigation system.
22     * Copyright (C) 2005-2008 Navit Team
23     *
24     * This program is free software; you can redistribute it and/or
25     * modify it under the terms of the GNU General Public License
26     * version 2 as published by the Free Software Foundation.
27     *
28     * This program is distributed in the hope that it will be useful,
29     * but WITHOUT ANY WARRANTY; without even the implied warranty of
30     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31     * GNU General Public License for more details.
32     *
33     * You should have received a copy of the GNU General Public License
34     * along with this program; if not, write to the
35     * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36     * Boston, MA 02110-1301, USA.
37     */
38    
39     #include <stdio.h>
40     #include <stdlib.h>
41     #include <string.h>
42     #include <math.h>
43     #include <ctype.h>
44     #include <glib.h>
45     #include "debug.h"
46     #include "profile.h"
47     #include "navigation.h"
48     #include "coord.h"
49     #include "item.h"
50     #include "route.h"
51     #include "transform.h"
52     #include "mapset.h"
53     #include "projection.h"
54     #include "map.h"
55     #include "navit.h"
56     #include "callback.h"
57     #include "speech.h"
58     #include "vehicleprofile.h"
59     #include "plugin.h"
60     #include "navit_nls.h"
61    
62     /* #define DEBUG */
63    
64 zoff99 27 static int roundabout_extra_length = 50;
65 zoff99 2
66 zoff99 27 struct suffix
67     {
68 zoff99 2 char *fullname;
69     char *abbrev;
70     int sex;
71 zoff99 30 } suffixes[] = { { "weg", NULL, 1 }, { "platz", "pl.", 1 }, { "ring", NULL, 1 }, { "allee", NULL, 2 }, { "gasse", NULL, 2 }, { "straße", "str.", 2 }, { "strasse", NULL, 2 }, };
72 zoff99 2
73 zoff99 27 struct navigation
74     {
75 zoff99 2 struct route *route;
76     struct map *map;
77     struct item_hash *hash;
78     struct vehicleprofile *vehicleprofile;
79     struct navigation_itm *first;
80     struct navigation_itm *last;
81     struct navigation_command *cmd_first;
82     struct navigation_command *cmd_last;
83     struct callback_list *callback_speech;
84     struct callback_list *callback;
85     struct navit *navit;
86     struct speech *speech;
87     int level_last;
88     struct item item_last;
89     int turn_around;
90     int turn_around_limit;
91     int distance_turn;
92     struct callback *route_cb;
93 zoff99 27 int announce[route_item_last - route_item_first + 1][3];
94 zoff99 2 int tell_street_name;
95     int delay;
96     int curr_delay;
97     };
98    
99 zoff99 30 int distances[] = { 1, 2, 3, 4, 5, 10, 25, 50, 75, 100, 150, 200, 250, 300, 400, 500, 750, -1 };
100 zoff99 2
101 zoff99 27 struct navigation_command
102     {
103 zoff99 2 struct navigation_itm *itm;
104     struct navigation_command *next;
105     struct navigation_command *prev;
106     int delta;
107     int roundabout_delta;
108     int length;
109     };
110    
111     static void navigation_flush(struct navigation *this_);
112    
113     /**
114     * @brief Calculates the delta between two angles
115     * @param angle1 The first angle
116     * @param angle2 The second angle
117     * @return The difference between the angles: -179..-1=angle2 is left of angle1,0=same,1..179=angle2 is right of angle1,180=angle1 is opposite of angle2
118 zoff99 27 */
119 zoff99 2
120 zoff99 27 static int angle_delta(int angle1, int angle2)
121 zoff99 2 {
122 zoff99 27 int delta = angle2 - angle1;
123 zoff99 2 if (delta <= -180)
124 zoff99 27 delta += 360;
125 zoff99 2 if (delta > 180)
126 zoff99 27 delta -= 360;
127 zoff99 2 return delta;
128     }
129    
130 zoff99 27 static int angle_median(int angle1, int angle2)
131 zoff99 2 {
132 zoff99 27 int delta = angle_delta(angle1, angle2);
133     int ret = angle1 + delta / 2;
134 zoff99 2 if (ret < 0)
135 zoff99 27 ret += 360;
136 zoff99 2 if (ret > 360)
137 zoff99 27 ret -= 360;
138 zoff99 2 return ret;
139     }
140    
141 zoff99 27 static int angle_opposite(int angle)
142 zoff99 2 {
143 zoff99 27 return ((angle + 180) % 360);
144 zoff99 2 }
145    
146 zoff99 30 int navigation_get_attr(struct navigation *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
147 zoff99 2 {
148     struct map_rect *mr;
149     struct item *item;
150 zoff99 27 dbg(1, "enter %s\n", attr_to_name(type));
151     switch (type)
152     {
153     case attr_map:
154     attr->u.map = this_->map;
155     break;
156     case attr_item_type:
157     case attr_length:
158     case attr_navigation_speech:
159     mr = map_rect_new(this_->map, NULL);
160     while ((item = map_rect_get_item(mr)))
161     {
162 zoff99 30 if (item->type != type_nav_none && item->type != type_nav_position)
163 zoff99 27 {
164     if (type == attr_item_type)
165     attr->u.item_type = item->type;
166     else
167     {
168     if (!item_attr_get(item, type, attr))
169     item = NULL;
170     }
171     break;
172 zoff99 2 }
173     }
174 zoff99 27 map_rect_destroy(mr);
175     if (!item)
176     return 0;
177     break;
178     default:
179 zoff99 2 return 0;
180     }
181 zoff99 27 attr->type = type;
182 zoff99 2 return 1;
183     }
184    
185 zoff99 27 int navigation_set_attr(struct navigation *this_, struct attr *attr)
186 zoff99 2 {
187 zoff99 27 switch (attr->type)
188     {
189     case attr_speech:
190     this_->speech = attr->u.speech;
191     return 1;
192     default:
193     return 0;
194 zoff99 2 }
195     }
196    
197     struct navigation *
198     navigation_new(struct attr *parent, struct attr **attrs)
199     {
200 zoff99 27 int i, j;
201 zoff99 2 struct attr * attr;
202     struct navigation *ret=g_new0(struct navigation, 1);
203 zoff99 27 ret->hash = item_hash_new();
204     ret->callback = callback_list_new();
205     ret->callback_speech = callback_list_new();
206     ret->level_last = -2;
207     ret->distance_turn = 50;
208     ret->turn_around_limit = 3;
209     ret->navit = parent->u.navit;
210     ret->tell_street_name = 1;
211 zoff99 2
212 zoff99 27 for (j = 0; j <= route_item_last - route_item_first; j++)
213     {
214     for (i = 0; i < 3; i++)
215     {
216     ret->announce[j][i] = -1;
217 zoff99 2 }
218     }
219    
220 zoff99 27 if ((attr = attr_search(attrs, NULL, attr_tell_street_name)))
221     {
222 zoff99 2 ret->tell_street_name = attr->u.num;
223     }
224 zoff99 27 if ((attr = attr_search(attrs, NULL, attr_delay)))
225     {
226 zoff99 2 ret->delay = attr->u.num;
227     }
228    
229 zoff99 27 return ret;
230 zoff99 2 }
231    
232 zoff99 30 int navigation_set_announce(struct navigation *this_, enum item_type type, int *level)
233 zoff99 2 {
234     int i;
235 zoff99 27 if (type < route_item_first || type > route_item_last)
236     {
237 zoff99 30 dbg(0, "street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
238 zoff99 2 return 0;
239     }
240 zoff99 27 for (i = 0; i < 3; i++)
241     this_->announce[type - route_item_first][i] = level[i];
242 zoff99 2 return 1;
243     }
244    
245 zoff99 30 static int navigation_get_announce_level(struct navigation *this_, enum item_type type, int dist)
246 zoff99 2 {
247     int i;
248    
249     if (type < route_item_first || type > route_item_last)
250     return -1;
251 zoff99 27 for (i = 0; i < 3; i++)
252     {
253     if (dist <= this_->announce[type - route_item_first][i])
254 zoff99 2 return i;
255     }
256     return i;
257     }
258    
259     /**
260     * @brief Holds a way that one could possibly drive from a navigation item
261     */
262 zoff99 27 struct navigation_way
263     {
264     struct navigation_way *next; /**< Pointer to a linked-list of all navigation_ways from this navigation item */
265     short dir; /**< The direction -1 or 1 of the way */
266     short angle2; /**< The angle one has to steer to drive from the old item to this street */
267     int flags; /**< The flags of the way */
268     struct item item; /**< The item of the way */
269 zoff99 2 char *name1;
270     char *name2;
271     };
272    
273 zoff99 27 struct navigation_itm
274     {
275 zoff99 2 struct navigation_way way;
276     int angle_end;
277 zoff99 27 struct coord start, end;
278 zoff99 2 int time;
279     int length;
280     int speed;
281     int dest_time;
282     int dest_length;
283 zoff99 27 int told; /**< Indicates if this item's announcement has been told earlier and should not be told again*/
284     int streetname_told; /**< Indicates if this item's streetname has been told in speech navigation*/
285 zoff99 2 int dest_count;
286     struct navigation_itm *next;
287     struct navigation_itm *prev;
288     };
289    
290 zoff99 30 static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode);
291 zoff99 2
292 zoff99 30 static int navigation_get_announce_level_cmd(struct navigation *this_, struct navigation_itm *itm, struct navigation_command *cmd, int distance)
293 zoff99 2 {
294 zoff99 30 int level2, level = navigation_get_announce_level(this_, itm->way.item.type, distance);
295 zoff99 27 if (this_->cmd_first->itm->prev)
296     {
297 zoff99 30 level2 = navigation_get_announce_level(this_, cmd->itm->prev->way.item.type, distance);
298 zoff99 2 if (level2 > level)
299 zoff99 27 level = level2;
300 zoff99 2 }
301     return level;
302     }
303    
304     /* 0=N,90=E */
305 zoff99 27 static int road_angle(struct coord *c1, struct coord *c2, int dir)
306 zoff99 2 {
307 zoff99 27 int ret = transform_get_angle_delta(c1, c2, dir);
308     // dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret);
309 zoff99 2 return ret;
310     }
311    
312 zoff99 27 static char *get_count_str(int n)
313 zoff99 2 {
314 zoff99 27 switch (n)
315     {
316     case 0:
317     #ifdef HAVE_API_ANDROID
318 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
319 zoff99 27 android_send_generic_text(1,"+*#O:zeroth\n");
320     #endif
321 zoff99 28 #endif
322 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the zeroth street)
323     return _("zeroth"); // Not sure if this exists, neither if it will ever be needed
324     case 1:
325     #ifdef HAVE_API_ANDROID
326 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
327 zoff99 27 android_send_generic_text(1,"+*#O:first\n");
328     #endif
329 zoff99 28 #endif
330 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the first street)
331     return _("first");
332     case 2:
333     #ifdef HAVE_API_ANDROID
334 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
335 zoff99 27 android_send_generic_text(1,"+*#O:second\n");
336     #endif
337 zoff99 28 #endif
338 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the second street)
339     return _("second");
340     case 3:
341     #ifdef HAVE_API_ANDROID
342 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
343 zoff99 27 android_send_generic_text(1,"+*#O:third\n");
344     #endif
345 zoff99 28 #endif
346 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the third street)
347     return _("third");
348     case 4:
349     #ifdef HAVE_API_ANDROID
350 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
351 zoff99 27 android_send_generic_text(1,"+*#O:fourth\n");
352     #endif
353 zoff99 28 #endif
354 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the fourth street)
355     return _("fourth");
356     case 5:
357     #ifdef HAVE_API_ANDROID
358 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
359 zoff99 27 android_send_generic_text(1,"+*#O:fifth\n");
360     #endif
361 zoff99 28 #endif
362 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the fifth street)
363     return _("fifth");
364     case 6:
365     #ifdef HAVE_API_ANDROID
366 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
367 zoff99 27 android_send_generic_text(1,"+*#O:sixth\n");
368     #endif
369 zoff99 28 #endif
370 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the sixth street)
371     return _("sixth");
372     case 7:
373     #ifdef HAVE_API_ANDROID
374 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
375 zoff99 27 android_send_generic_text(1,"+*#O:seventh\n");
376     #endif
377 zoff99 28 #endif
378 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the seventh street)
379     return _("seventh");
380     case 8:
381     #ifdef HAVE_API_ANDROID
382 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
383 zoff99 27 android_send_generic_text(1,"+*#O:eighth\n");
384     #endif
385 zoff99 28 #endif
386 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the eighth street)
387     return _("eighth");
388     case 9:
389     #ifdef HAVE_API_ANDROID
390 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
391 zoff99 27 android_send_generic_text(1,"+*#O:ninth\n");
392     #endif
393 zoff99 28 #endif
394 zoff99 27 // TRANSLATORS: the following counts refer to streets (example: turn right after the ninth street)
395     return _("ninth");
396     default:
397     return NULL;
398 zoff99 2 }
399     }
400    
401 zoff99 27 static char *get_exit_count_str(int n)
402 zoff99 2 {
403 zoff99 27 switch (n)
404     {
405     case 0:
406     #ifdef HAVE_API_ANDROID
407 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
408 zoff99 27 android_send_generic_text(1,"+*#O:zeroth exit\n");
409     #endif
410 zoff99 28 #endif
411 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the zeroth exit)
412     return _("zeroth exit"); // Not sure if this exists, neither if it will ever be needed
413     case 1:
414     #ifdef HAVE_API_ANDROID
415 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
416 zoff99 27 android_send_generic_text(1,"+*#O:first exit\n");
417     #endif
418 zoff99 28 #endif
419 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the first exit)
420     return _("first exit");
421     case 2:
422     #ifdef HAVE_API_ANDROID
423 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
424 zoff99 27 android_send_generic_text(1,"+*#O:second exit\n");
425     #endif
426 zoff99 28 #endif
427 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the second exit)
428     return _("second exit");
429     case 3:
430     #ifdef HAVE_API_ANDROID
431 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
432 zoff99 27 android_send_generic_text(1,"+*#O:third exit\n");
433     #endif
434 zoff99 28 #endif
435 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the third exit)
436     return _("third exit");
437     case 4:
438     #ifdef HAVE_API_ANDROID
439 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
440 zoff99 27 android_send_generic_text(1,"+*#O:fourth exit\n");
441     #endif
442 zoff99 28 #endif
443 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the fourth exit)
444     return _("fourth exit");
445     case 5:
446     #ifdef HAVE_API_ANDROID
447 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
448 zoff99 27 android_send_generic_text(1,"+*#O:fifth exit\n");
449     #endif
450 zoff99 28 #endif
451 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the fifth exit)
452     return _("fifth exit");
453     case 6:
454     #ifdef HAVE_API_ANDROID
455 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
456 zoff99 27 android_send_generic_text(1,"+*#O:sixth exit\n");
457     #endif
458 zoff99 28 #endif
459 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the sixth exit)
460     return _("sixth exit");
461     case 7:
462     #ifdef HAVE_API_ANDROID
463 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
464 zoff99 27 android_send_generic_text(1,"+*#O:seventh exit\n");
465     #endif
466 zoff99 28 #endif
467 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the seventh exit)
468     return _("seventh exit");
469     case 8:
470     #ifdef HAVE_API_ANDROID
471 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
472 zoff99 27 android_send_generic_text(1,"+*#O:eighth exit\n");
473     #endif
474 zoff99 28 #endif
475 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the eighth exit)
476     return _("eighth exit");
477     case 9:
478     #ifdef HAVE_API_ANDROID
479 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
480 zoff99 27 android_send_generic_text(1,"+*#O:ninth exit\n");
481     #endif
482 zoff99 28 #endif
483 zoff99 27 // TRANSLATORS: the following counts refer to roundabout exits (example: leave the roundabout at the ninth exit)
484     return _("ninth exit");
485     default:
486     return NULL;
487 zoff99 2 }
488     }
489 zoff99 27 static int round_distance(int dist)
490 zoff99 2 {
491 zoff99 27 if (dist < 100)
492     {
493     dist = (dist + 5) / 10;
494     return dist * 10;
495 zoff99 2 }
496 zoff99 27 if (dist < 250)
497     {
498     dist = (dist + 13) / 25;
499     return dist * 25;
500 zoff99 2 }
501 zoff99 27 if (dist < 500)
502     {
503     dist = (dist + 25) / 50;
504     return dist * 50;
505 zoff99 2 }
506 zoff99 27 if (dist < 1000)
507     {
508     dist = (dist + 50) / 100;
509     return dist * 100;
510 zoff99 2 }
511 zoff99 27 if (dist < 5000)
512     {
513     dist = (dist + 50) / 100;
514     return dist * 100;
515 zoff99 2 }
516 zoff99 27 if (dist < 100000)
517     {
518     dist = (dist + 500) / 1000;
519     return dist * 1000;
520 zoff99 2 }
521 zoff99 27 dist = (dist + 5000) / 10000;
522     return dist * 10000;
523 zoff99 2 }
524    
525 zoff99 27 static int round_for_vocabulary(int vocabulary, int dist, int factor)
526 zoff99 2 {
527 zoff99 27 if (!(vocabulary & 256))
528     {
529     if (factor != 1)
530     dist = (dist + factor / 2) / factor;
531     }
532     else
533     factor = 1;
534     if (!(vocabulary & 255))
535     {
536     int i = 0, d = 0, m = 0;
537     while (distances[i] > 0)
538     {
539     if (!i || abs(distances[i] - dist) <= d)
540     {
541     d = abs(distances[i] - dist);
542     m = i;
543 zoff99 2 }
544     if (distances[i] > dist)
545     break;
546     i++;
547     }
548 zoff99 27 // dbg(0, "converted %d to %d with factor %d\n", dist, distances[m], factor);
549     dist = distances[m];
550 zoff99 2 }
551 zoff99 27 return dist * factor;
552 zoff99 2 }
553    
554 zoff99 27 static int vocabulary_last(int vocabulary)
555 zoff99 2 {
556 zoff99 27 int i = 0;
557 zoff99 2 if (vocabulary == 65535)
558     return 1000;
559 zoff99 27 while (distances[i] > 0)
560 zoff99 2 i++;
561 zoff99 27 return distances[i - 1];
562 zoff99 2 }
563    
564     static char *
565 zoff99 30 get_distance(struct navigation *nav, int dist, enum attr_type type, int is_length)
566 zoff99 2 {
567 zoff99 27 int imperial = 0, vocabulary = 65535;
568 zoff99 2 struct attr attr;
569 zoff99 27
570     if (type == attr_navigation_long)
571     {
572 zoff99 2 if (is_length)
573 zoff99 27 {
574     #ifdef HAVE_API_ANDROID
575 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
576 zoff99 27 android_send_generic_text(1,"+*#O:%d m\n");
577     #endif
578 zoff99 28 #endif
579 zoff99 2 return g_strdup_printf(_("%d m"), dist);
580 zoff99 27 }
581 zoff99 2 else
582 zoff99 27 {
583     #ifdef HAVE_API_ANDROID
584 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
585 zoff99 27 android_send_generic_text(1,"+*#O:in %d m\n");
586     #endif
587 zoff99 28 #endif
588 zoff99 2 return g_strdup_printf(_("in %d m"), dist);
589 zoff99 27 }
590 zoff99 2 }
591     if (navit_get_attr(nav->navit, attr_imperial, &attr, NULL))
592 zoff99 27 imperial = attr.u.num;
593 zoff99 30 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_distances, &attr, NULL))
594 zoff99 27 vocabulary = attr.u.num;
595     if (imperial)
596     {
597     if (dist * FEET_PER_METER < vocabulary_last(vocabulary))
598     {
599     dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER, 1);
600 zoff99 2 if (is_length)
601 zoff99 27 {
602     #ifdef HAVE_API_ANDROID
603 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
604 zoff99 27 android_send_generic_text(1,"+*#O:%d feet\n");
605     #endif
606 zoff99 28 #endif
607 zoff99 2 return g_strdup_printf(_("%d feet"), dist);
608 zoff99 27 }
609 zoff99 2 else
610 zoff99 27 {
611     #ifdef HAVE_API_ANDROID
612 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
613 zoff99 27 android_send_generic_text(1,"+*#O:in %d feet\n");
614     #endif
615 zoff99 28 #endif
616 zoff99 2 return g_strdup_printf(_("in %d feet"), dist);
617 zoff99 27 }
618 zoff99 2 }
619 zoff99 27 }
620     else
621     {
622     if (dist < vocabulary_last(vocabulary))
623     {
624     dist = round_for_vocabulary(vocabulary, dist, 1);
625 zoff99 2 if (is_length)
626 zoff99 27 {
627     #ifdef HAVE_API_ANDROID
628 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
629 zoff99 27 android_send_generic_text(1,"+*#O:%d meters\n");
630     gchar* xy=g_strdup_printf("+*#1:%d\n", dist);
631     android_send_generic_text(1,xy);
632     g_free(xy);
633     #endif
634 zoff99 28 #endif
635 zoff99 2 return g_strdup_printf(_("%d meters"), dist);
636 zoff99 27 }
637 zoff99 2 else
638 zoff99 27 {
639     #ifdef HAVE_API_ANDROID
640 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
641 zoff99 27 android_send_generic_text(1,"+*#O:in %d meters\n");
642     gchar* xy=g_strdup_printf("+*#1:%d\n", dist);
643     android_send_generic_text(1,xy);
644     g_free(xy);
645     #endif
646 zoff99 28 #endif
647 zoff99 2 return g_strdup_printf(_("in %d meters"), dist);
648 zoff99 27 }
649 zoff99 2 }
650     }
651     if (imperial)
652 zoff99 27 {
653 zoff99 30 dist = round_for_vocabulary(vocabulary, dist * FEET_PER_METER * 1000 / FEET_PER_MILE, 1000);
654 zoff99 27 }
655 zoff99 2 else
656 zoff99 27 {
657     dist = round_for_vocabulary(vocabulary, dist, 1000);
658     }
659    
660     if (dist < 5000)
661     {
662     int rem = (dist / 100) % 10;
663     if (rem)
664     {
665     if (imperial)
666     {
667 zoff99 2 if (is_length)
668 zoff99 27 {
669     #ifdef HAVE_API_ANDROID
670 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
671 zoff99 27 android_send_generic_text(1,"+*#O:%d.%d miles\n");
672     #endif
673 zoff99 28 #endif
674 zoff99 27 return g_strdup_printf(_("%d.%d miles"), dist / 1000, rem);
675     }
676 zoff99 2 else
677 zoff99 27 {
678     #ifdef HAVE_API_ANDROID
679 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
680 zoff99 27 android_send_generic_text(1,"+*#O:in %d.%d miles\n");
681     #endif
682 zoff99 28 #endif
683 zoff99 30 return g_strdup_printf(_("in %d.%d miles"), dist / 1000, rem);
684 zoff99 27 }
685     }
686     else
687     {
688 zoff99 2 if (is_length)
689 zoff99 27 {
690     #ifdef HAVE_API_ANDROID
691 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
692 zoff99 27 android_send_generic_text(1,"+*#O:%d.%d kilometers\n");
693     #endif
694 zoff99 28 #endif
695 zoff99 30 return g_strdup_printf(_("%d.%d kilometers"), dist / 1000, rem);
696 zoff99 27 }
697 zoff99 2 else
698 zoff99 27 {
699     #ifdef HAVE_API_ANDROID
700 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
701 zoff99 27 android_send_generic_text(1,"+*#O:in %d.%d kilometers\n");
702     #endif
703 zoff99 28 #endif
704 zoff99 30 return g_strdup_printf(_("in %d.%d kilometers"), dist / 1000, rem);
705 zoff99 27 }
706 zoff99 2 }
707     }
708     }
709 zoff99 27 if (imperial)
710     {
711     if (is_length)
712 zoff99 30 return g_strdup_printf(ngettext("one mile", "%d miles", dist / 1000), dist / 1000);
713 zoff99 2 else
714 zoff99 30 return g_strdup_printf(ngettext("in one mile", "in %d miles", dist / 1000), dist / 1000);
715 zoff99 27 }
716     else
717     {
718     if (is_length)
719     {
720     #ifdef HAVE_API_ANDROID
721 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
722 zoff99 27 android_send_generic_text(1,"+*#O:one kilometer|%d kilometers\n");
723     #endif
724 zoff99 28 #endif
725 zoff99 30 return g_strdup_printf(ngettext("one kilometer", "%d kilometers", dist / 1000), dist / 1000);
726 zoff99 27 }
727 zoff99 2 else
728 zoff99 27 {
729     #ifdef HAVE_API_ANDROID
730 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
731 zoff99 27 android_send_generic_text(1,"+*#O:in one kilometer|in %d kilometers\n");
732     #endif
733 zoff99 28 #endif
734 zoff99 30 return g_strdup_printf(ngettext("in one kilometer", "in %d kilometers", dist / 1000), dist / 1000);
735 zoff99 27 }
736 zoff99 2 }
737     }
738    
739     /**
740     * @brief This calculates the angle with which an item starts or ends
741     *
742     * This function can be used to get the angle an item (from a route graph map)
743     * starts or ends with. Note that the angle will point towards the inner of
744     * the item.
745     *
746     * This is meant to be used with items from a route graph map
747     * With other items this will probably not be optimal...
748     *
749     * @param w The way which should be calculated
750 zoff99 27 */
751     static void calculate_angle(struct navigation_way *w)
752 zoff99 2 {
753     struct coord cbuf[2];
754     struct item *ritem; // the "real" item
755     struct coord c;
756     struct map_rect *mr;
757     struct attr attr;
758    
759 zoff99 27 w->angle2 = 361;
760 zoff99 2 mr = map_rect_new(w->item.map, NULL);
761     if (!mr)
762     return;
763    
764     ritem = map_rect_get_item_byid(mr, w->item.id_hi, w->item.id_lo);
765 zoff99 27 if (!ritem)
766     {
767     dbg(1, "Item from segment not found on map!\n");
768 zoff99 2 map_rect_destroy(mr);
769     return;
770     }
771    
772 zoff99 27 if (ritem->type < type_line || ritem->type >= type_area)
773     {
774 zoff99 2 map_rect_destroy(mr);
775     return;
776     }
777     if (item_attr_get(ritem, attr_flags, &attr))
778 zoff99 27 w->flags = attr.u.num;
779 zoff99 2 else
780 zoff99 27 w->flags = 0;
781 zoff99 2 if (item_attr_get(ritem, attr_street_name, &attr))
782 zoff99 27 w->name1 = map_convert_string(ritem->map, attr.u.str);
783 zoff99 2 else
784 zoff99 27 w->name1 = NULL;
785 zoff99 2 if (item_attr_get(ritem, attr_street_name_systematic, &attr))
786 zoff99 27 w->name2 = map_convert_string(ritem->map, attr.u.str);
787 zoff99 2 else
788 zoff99 27 w->name2 = NULL;
789    
790     if (w->dir < 0)
791     {
792     if (item_coord_get(ritem, cbuf, 2) != 2)
793     {
794 zoff99 30 dbg(1, "Using calculate_angle() with a less-than-two-coords-item?\n");
795 zoff99 2 map_rect_destroy(mr);
796     return;
797     }
798 zoff99 27
799     while (item_coord_get(ritem, &c, 1))
800     {
801 zoff99 2 cbuf[0] = cbuf[1];
802     cbuf[1] = c;
803     }
804 zoff99 27
805     }
806     else
807     {
808     if (item_coord_get(ritem, cbuf, 2) != 2)
809     {
810 zoff99 30 dbg(1, "Using calculate_angle() with a less-than-two-coords-item?\n");
811 zoff99 2 map_rect_destroy(mr);
812     return;
813     }
814     c = cbuf[0];
815     cbuf[0] = cbuf[1];
816     cbuf[1] = c;
817     }
818    
819     map_rect_destroy(mr);
820    
821 zoff99 27 w->angle2 = road_angle(&cbuf[1], &cbuf[0], 0);
822 zoff99 2 }
823    
824     /**
825     * @brief Returns the time (in seconds) one will drive between two navigation items
826     *
827     * This function returns the time needed to drive between two items, including both of them,
828     * in seconds.
829     *
830     * @param from The first item
831     * @param to The last item
832     * @return The travel time in seconds, or -1 on error
833     */
834 zoff99 30 static int navigation_time(struct navigation_itm *from, struct navigation_itm *to)
835 zoff99 2 {
836     struct navigation_itm *cur;
837     int time;
838    
839     time = 0;
840     cur = from;
841 zoff99 27 while (cur)
842     {
843 zoff99 2 time += cur->time;
844    
845 zoff99 27 if (cur == to)
846     {
847 zoff99 2 break;
848     }
849     cur = cur->next;
850     }
851    
852 zoff99 27 if (!cur)
853     {
854 zoff99 2 return -1;
855     }
856    
857     return time;
858     }
859    
860     /**
861     * @brief Clears the ways one can drive from itm
862     *
863     * @param itm The item that should have its ways cleared
864     */
865 zoff99 27 static void navigation_itm_ways_clear(struct navigation_itm *itm)
866 zoff99 2 {
867 zoff99 27 struct navigation_way *c, *n;
868 zoff99 2
869     c = itm->way.next;
870 zoff99 27 while (c)
871     {
872 zoff99 2 n = c->next;
873     map_convert_free(c->name1);
874     map_convert_free(c->name2);
875     g_free(c);
876     c = n;
877     }
878    
879     itm->way.next = NULL;
880     }
881    
882     /**
883     * @brief Updates the ways one can drive from itm
884     *
885     * This updates the list of possible ways to drive to from itm. The item "itm" is on
886     * and the next navigation item are excluded.
887     *
888     * @param itm The item that should be updated
889     * @param graph_map The route graph's map that these items are on
890     */
891 zoff99 30 static void navigation_itm_ways_update(struct navigation_itm *itm, struct map *graph_map)
892 zoff99 2 {
893     struct map_selection coord_sel;
894     struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
895 zoff99 27 struct item *i, *sitem;
896     struct attr sitem_attr, direction_attr;
897     struct navigation_way *w, *l;
898 zoff99 2
899     navigation_itm_ways_clear(itm);
900    
901     // These values cause the code in route.c to get us only the route graph point and connected segments
902     coord_sel.next = NULL;
903     coord_sel.u.c_rect.lu = itm->start;
904     coord_sel.u.c_rect.rl = itm->start;
905     // the selection's order is ignored
906 zoff99 27
907 zoff99 2 g_rect = map_rect_new(graph_map, &coord_sel);
908 zoff99 27
909 zoff99 2 i = map_rect_get_item(g_rect);
910 zoff99 27 if (!i || i->type != type_rg_point)
911     { // probably offroad?
912     return;
913 zoff99 2 }
914    
915     w = NULL;
916 zoff99 27
917     while (1)
918     {
919 zoff99 2 i = map_rect_get_item(g_rect);
920    
921 zoff99 27 if (!i)
922     {
923 zoff99 2 break;
924     }
925 zoff99 27
926     if (i->type != type_rg_segment)
927     {
928 zoff99 2 continue;
929     }
930 zoff99 27
931     if (!item_attr_get(i, attr_street_item, &sitem_attr))
932     {
933 zoff99 30 dbg(1, "Got no street item for route graph item in entering_straight()\n");
934 zoff99 2 continue;
935 zoff99 27 }
936 zoff99 2
937 zoff99 27 if (!item_attr_get(i, attr_direction, &direction_attr))
938     {
939 zoff99 2 continue;
940     }
941    
942     sitem = sitem_attr.u.item;
943 zoff99 30 if (sitem->type == type_street_turn_restriction_no || sitem->type == type_street_turn_restriction_only)
944 zoff99 2 continue;
945    
946 zoff99 30 if (item_is_equal(itm->way.item, *sitem) || ((itm->prev) && item_is_equal(itm->prev->way.item, *sitem)))
947 zoff99 27 {
948 zoff99 2 continue;
949     }
950    
951     l = w;
952     w = g_new(struct navigation_way, 1);
953     w->dir = direction_attr.u.num;
954     w->item = *sitem;
955     w->next = l;
956     calculate_angle(w);
957     }
958    
959     map_rect_destroy(g_rect);
960 zoff99 27
961 zoff99 2 itm->way.next = w;
962     }
963    
964 zoff99 30 static void navigation_destroy_itms_cmds(struct navigation *this_, struct navigation_itm *end)
965 zoff99 2 {
966     struct navigation_itm *itm;
967     struct navigation_command *cmd;
968 zoff99 27 // dbg(2, "enter this_=%p this_->first=%p this_->cmd_first=%p end=%p\n", this_, this_->first, this_->cmd_first, end);
969 zoff99 2 if (this_->cmd_first)
970 zoff99 27 {
971     // dbg(2, "this_->cmd_first->itm=%p\n", this_->cmd_first->itm);
972     }
973     while (this_->first && this_->first != end)
974     {
975     itm = this_->first;
976     // dbg(3, "destroying %p\n", itm);
977 zoff99 2 item_hash_remove(this_->hash, &itm->way.item);
978 zoff99 27 this_->first = itm->next;
979 zoff99 2 if (this_->first)
980 zoff99 27 this_->first->prev = NULL;
981     if (this_->cmd_first && this_->cmd_first->itm == itm->next)
982     {
983     cmd = this_->cmd_first;
984     this_->cmd_first = cmd->next;
985     if (cmd->next)
986     {
987 zoff99 2 cmd->next->prev = NULL;
988     }
989     g_free(cmd);
990     }
991     map_convert_free(itm->way.name1);
992     map_convert_free(itm->way.name2);
993     navigation_itm_ways_clear(itm);
994     g_free(itm);
995     }
996 zoff99 27 if (!this_->first)
997     this_->last = NULL;
998     if (!this_->first && end)
999     {
1000     // dbg(0, "end wrong\n");
1001     }
1002     // dbg(2, "ret this_->first=%p this_->cmd_first=%p\n", this_->first, this_->cmd_first);
1003 zoff99 2 }
1004    
1005 zoff99 30 static void navigation_itm_update(struct navigation_itm *itm, struct item *ritem)
1006 zoff99 2 {
1007     struct attr length, time, speed;
1008    
1009 zoff99 27 if (!item_attr_get(ritem, attr_length, &length))
1010     {
1011     // dbg(0, "no length\n");
1012 zoff99 2 return;
1013     }
1014 zoff99 27 if (!item_attr_get(ritem, attr_time, &time))
1015     {
1016     // dbg(0, "no time\n");
1017 zoff99 2 return;
1018     }
1019 zoff99 27 if (!item_attr_get(ritem, attr_speed, &speed))
1020     {
1021     // dbg(0, "no time\n");
1022 zoff99 2 return;
1023     }
1024    
1025 zoff99 27 // dbg(1, "length=%d time=%d speed=%d\n", length.u.num, time.u.num, speed.u.num);
1026     itm->length = length.u.num;
1027     itm->time = time.u.num;
1028     itm->speed = speed.u.num;
1029 zoff99 2 }
1030    
1031     /**
1032     * @brief This check if an item is part of a roundabout
1033     *
1034     * @param itm The item to be checked
1035     * @return True if the item is part of a roundabout
1036 zoff99 27 */
1037     static int check_roundabout(struct navigation_itm *itm, struct map *graph_map)
1038 zoff99 2 {
1039     struct map_selection coord_sel;
1040     struct map_rect *g_rect; // Contains a map rectangle from the route graph's map
1041 zoff99 27 struct item *i, *sitem;
1042     struct attr sitem_attr, flags_attr;
1043 zoff99 2
1044     // These values cause the code in route.c to get us only the route graph point and connected segments
1045     coord_sel.next = NULL;
1046     coord_sel.u.c_rect.lu = itm->start;
1047     coord_sel.u.c_rect.rl = itm->start;
1048     // the selection's order is ignored
1049 zoff99 27
1050 zoff99 2 g_rect = map_rect_new(graph_map, &coord_sel);
1051 zoff99 27
1052 zoff99 2 i = map_rect_get_item(g_rect);
1053 zoff99 27 if (!i || i->type != type_rg_point)
1054     { // probably offroad?
1055 zoff99 2 map_rect_destroy(g_rect);
1056     return 0;
1057     }
1058    
1059 zoff99 27 while (1)
1060     {
1061 zoff99 2 i = map_rect_get_item(g_rect);
1062    
1063 zoff99 27 if (!i)
1064     {
1065 zoff99 2 break;
1066     }
1067 zoff99 27
1068     if (i->type != type_rg_segment)
1069     {
1070 zoff99 2 continue;
1071     }
1072 zoff99 27
1073     if (!item_attr_get(i, attr_street_item, &sitem_attr))
1074     {
1075 zoff99 2 continue;
1076 zoff99 27 }
1077 zoff99 2
1078     sitem = sitem_attr.u.item;
1079 zoff99 27 if (item_is_equal(itm->way.item, *sitem))
1080     {
1081 zoff99 30 if (item_attr_get(i, attr_flags, &flags_attr) && (flags_attr.u.num & AF_ROUNDABOUT))
1082 zoff99 27 {
1083 zoff99 2 map_rect_destroy(g_rect);
1084     return 1;
1085     }
1086     }
1087     }
1088    
1089     map_rect_destroy(g_rect);
1090     return 0;
1091     }
1092    
1093     static struct navigation_itm *
1094     navigation_itm_new(struct navigation *this_, struct item *ritem)
1095     {
1096     struct navigation_itm *ret=g_new0(struct navigation_itm, 1);
1097 zoff99 27 int i = 0;
1098 zoff99 2 struct item *sitem;
1099     struct map *graph_map = NULL;
1100 zoff99 27 struct attr street_item, direction, route_attr;
1101 zoff99 2 struct map_rect *mr;
1102     struct attr attr;
1103     struct coord c[5];
1104    
1105 zoff99 27 if (ritem)
1106     {
1107     ret->streetname_told = 0;
1108     if (!item_attr_get(ritem, attr_street_item, &street_item))
1109     {
1110     //dbg(1, "no street item\n");
1111 zoff99 2 g_free(ret);
1112     ret = NULL;
1113     return ret;
1114     }
1115     if (item_attr_get(ritem, attr_direction, &direction))
1116 zoff99 27 ret->way.dir = direction.u.num;
1117 zoff99 2 else
1118 zoff99 27 ret->way.dir = 0;
1119 zoff99 2
1120 zoff99 27 sitem = street_item.u.item;
1121     ret->way.item = *sitem;
1122 zoff99 2 item_hash_insert(this_->hash, sitem, ret);
1123 zoff99 27 mr = map_rect_new(sitem->map, NULL);
1124     if (!(sitem = map_rect_get_item_byid(mr, sitem->id_hi, sitem->id_lo)))
1125 zoff99 2 return NULL;
1126     if (item_attr_get(sitem, attr_street_name, &attr))
1127 zoff99 27 ret->way.name1 = map_convert_string(sitem->map, attr.u.str);
1128 zoff99 2 if (item_attr_get(sitem, attr_street_name_systematic, &attr))
1129 zoff99 27 ret->way.name2 = map_convert_string(sitem->map, attr.u.str);
1130 zoff99 2 navigation_itm_update(ret, ritem);
1131    
1132 zoff99 27 while (item_coord_get(ritem, &c[i], 1))
1133     {
1134     //dbg(1, "coord %d 0x%x 0x%x\n", i, c[i].x, c[i].y);
1135 zoff99 2
1136 zoff99 27 if (i < 4)
1137 zoff99 2 i++;
1138 zoff99 27 else
1139     {
1140     c[2] = c[3];
1141     c[3] = c[4];
1142 zoff99 2 }
1143     }
1144 zoff99 27 //dbg(1, "count=%d\n", i);
1145 zoff99 2 i--;
1146    
1147 zoff99 27 ret->way.angle2 = road_angle(&c[0], &c[1], 0);
1148     ret->angle_end = road_angle(&c[i - 1], &c[i], 0);
1149 zoff99 2
1150 zoff99 27 ret->start = c[0];
1151     ret->end = c[i];
1152 zoff99 2
1153     item_attr_get(ritem, attr_route, &route_attr);
1154     graph_map = route_get_graph_map(route_attr.u.route);
1155 zoff99 27 if (check_roundabout(ret, graph_map))
1156     {
1157 zoff99 2 ret->way.flags |= AF_ROUNDABOUT;
1158     }
1159    
1160 zoff99 27 // dbg(1, "i=%d start %d end %d '%s' '%s'\n", i, ret->way.angle2, ret->angle_end, ret->way.name1, ret->way.name2);
1161 zoff99 2 map_rect_destroy(mr);
1162 zoff99 27 }
1163     else
1164     {
1165 zoff99 2 if (this_->last)
1166 zoff99 27 ret->start = ret->end = this_->last->end;
1167 zoff99 2 }
1168 zoff99 27 if (!this_->first)
1169     this_->first = ret;
1170     if (this_->last)
1171     {
1172     this_->last->next = ret;
1173     ret->prev = this_->last;
1174     if (graph_map)
1175     {
1176     navigation_itm_ways_update(ret, graph_map);
1177 zoff99 2 }
1178     }
1179 zoff99 27 //dbg(1, "ret=%p\n", ret);
1180     this_->last = ret;
1181 zoff99 2 return ret;
1182     }
1183    
1184     /**
1185     * @brief Counts how many times a driver could turn right/left
1186     *
1187     * This function counts how many times the driver theoretically could
1188     * turn right/left between two navigation items, not counting the final
1189     * turn itself.
1190     *
1191     * @param from The navigation item which should form the start
1192     * @param to The navigation item which should form the end
1193     * @param direction Set to < 0 to count turns to the left >= 0 for turns to the right
1194     * @return The number of possibilities to turn or -1 on error
1195     */
1196 zoff99 30 static int count_possible_turns(struct navigation *nav, struct navigation_itm *from, struct navigation_itm *to, int direction)
1197 zoff99 2 {
1198     int count;
1199     struct navigation_itm *curr;
1200     struct navigation_way *w;
1201    
1202     count = 0;
1203     curr = from->next;
1204 zoff99 27 while (curr && (curr != to))
1205     {
1206 zoff99 2 w = curr->way.next;
1207    
1208 zoff99 27 while (w)
1209     {
1210     if (is_way_allowed(nav, w, 4))
1211     {
1212     if (direction < 0)
1213     {
1214     if (angle_delta(curr->prev->angle_end, w->angle2) < 0)
1215     {
1216 zoff99 2 count++;
1217     break;
1218     }
1219 zoff99 27 }
1220     else
1221     {
1222     if (angle_delta(curr->prev->angle_end, w->angle2) > 0)
1223     {
1224 zoff99 2 count++;
1225     break;
1226 zoff99 27 }
1227 zoff99 2 }
1228     }
1229     w = w->next;
1230     }
1231     curr = curr->next;
1232     }
1233    
1234 zoff99 27 if (!curr)
1235     { // from does not lead to to?
1236 zoff99 2 return -1;
1237     }
1238    
1239     return count;
1240     }
1241    
1242     /**
1243     * @brief Calculates distance and time to the destination
1244     *
1245     * This function calculates the distance and the time to the destination of a
1246     * navigation. If incr is set, this is only calculated for the first navigation
1247     * item, which is a lot faster than re-calculation the whole destination, but works
1248     * only if the rest of the navigation already has been calculated.
1249     *
1250     * @param this_ The navigation whose destination / time should be calculated
1251     * @param incr Set this to true to only calculate the first item. See description.
1252     */
1253 zoff99 27 static void calculate_dest_distance(struct navigation *this_, int incr)
1254 zoff99 2 {
1255 zoff99 27 int len = 0, time = 0, count = 0;
1256     struct navigation_itm *next, *itm = this_->last;
1257     //dbg(1, "enter this_=%p, incr=%d\n", this_, incr);
1258     if (incr)
1259     {
1260     if (itm)
1261     {
1262     //dbg(2, "old values: (%p) time=%d lenght=%d\n", itm,
1263     // itm->dest_length, itm->dest_time);
1264 zoff99 2 }
1265 zoff99 27 else
1266     {
1267     //dbg(2, "old values: itm is null\n");
1268     }
1269     itm = this_->first;
1270     next = itm->next;
1271     //dbg(2, "itm values: time=%d lenght=%d\n", itm->length, itm->time);
1272     //dbg(2, "next values: (%p) time=%d lenght=%d\n", next, next->dest_length, next->dest_time);
1273     itm->dest_length = next->dest_length + itm->length;
1274     itm->dest_count = next->dest_count + 1;
1275     itm->dest_time = next->dest_time + itm->time;
1276     //dbg(2, "new values: time=%d lenght=%d\n", itm->dest_length, itm->dest_time);
1277 zoff99 2 return;
1278     }
1279 zoff99 27 while (itm)
1280     {
1281     len += itm->length;
1282     time += itm->time;
1283     itm->dest_length = len;
1284     itm->dest_time = time;
1285     itm->dest_count = count++;
1286     itm = itm->prev;
1287 zoff99 2 }
1288 zoff99 27 //dbg(1, "len %d time %d\n", len, time);
1289 zoff99 2 }
1290    
1291     /**
1292     * @brief Checks if two navigation items are on the same street
1293     *
1294     * This function checks if two navigation items are on the same street. It returns
1295     * true if either their name or their "systematic name" (e.g. "A6" or "B256") are the
1296     * same.
1297     *
1298     * @param old The first item to be checked
1299     * @param new The second item to be checked
1300     * @return True if both old and new are on the same street
1301     */
1302 zoff99 30 static int is_same_street2(char *old_name1, char *old_name2, char *new_name1, char *new_name2)
1303 zoff99 2 {
1304 zoff99 27 if (old_name1 && new_name1 && !strcmp(old_name1, new_name1))
1305     {
1306     // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (1.)\n", old_name2, new_name2, old_name1, new_name1);
1307 zoff99 2 return 1;
1308     }
1309 zoff99 27 if (old_name2 && new_name2 && !strcmp(old_name2, new_name2))
1310     {
1311     // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' yes (2.)\n", old_name2, new_name2, old_name1, new_name1);
1312 zoff99 2 return 1;
1313     }
1314 zoff99 27 // dbg(1, "is_same_street: '%s' '%s' vs '%s' '%s' no\n", old_name2, new_name2, old_name1, new_name1);
1315 zoff99 2 return 0;
1316     }
1317    
1318     #if 0
1319     /**
1320     * @brief Checks if two navigation items are on the same street
1321     *
1322     * This function checks if two navigation items are on the same street. It returns
1323     * true if the first part of their "systematic name" is equal. If the "systematic name" is
1324     * for example "A352/E3" (a german highway which at the same time is part of the international
1325     * E-road network), it would only search for "A352" in the second item's systematic name.
1326     *
1327     * @param old The first item to be checked
1328     * @param new The second item to be checked
1329     * @return True if the "systematic name" of both items matches. See description.
1330     */
1331     static int
1332     is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new)
1333     {
1334     int slashold,slashnew;
1335     if (!old->name2 || !new->name2)
1336 zoff99 27 return 1;
1337 zoff99 2 slashold=strcspn(old->name2, "/");
1338     slashnew=strcspn(new->name2, "/");
1339     if (slashold != slashnew || strncmp(old->name2, new->name2, slashold))
1340 zoff99 27 return 0;
1341 zoff99 2 return 1;
1342     }
1343    
1344     /**
1345     * @brief Check if there are multiple possibilities to drive from old
1346     *
1347     * This function checks, if there are multiple streets connected to the exit of "old".
1348     * Sometimes it happens that an item on a map is just segmented, without any other streets
1349     * being connected there, and it is not useful if navit creates a maneuver there.
1350     *
1351     * @param new The navigation item we're driving to
1352     * @return True if there are multiple streets
1353     */
1354 zoff99 27 static int
1355 zoff99 2 maneuver_multiple_streets(struct navigation_itm *new)
1356     {
1357 zoff99 27 if (new->way.next)
1358     {
1359 zoff99 2 return 1;
1360 zoff99 27 }
1361     else
1362     {
1363 zoff99 2 return 0;
1364     }
1365     }
1366    
1367     /**
1368     * @brief Check if the new item is entered "straight"
1369     *
1370     * This function checks if the new item is entered "straight" from the old item, i.e. if there
1371     * is no other street one could take from the old item on with less steering.
1372     *
1373     * @param new The navigation item we're driving to
1374     * @param diff The absolute angle one needs to steer to drive to this item
1375     * @return True if the new item is entered "straight"
1376     */
1377 zoff99 27 static int
1378 zoff99 2 maneuver_straight(struct navigation_itm *new, int diff)
1379     {
1380     int curr_diff;
1381     struct navigation_way *w;
1382    
1383     w = new->way.next;
1384     dbg(1,"diff=%d\n", diff);
1385 zoff99 27 while (w)
1386     {
1387 zoff99 2 curr_diff=abs(angle_delta(new->prev->angle_end, w->angle2));
1388     dbg(1,"curr_diff=%d\n", curr_diff);
1389 zoff99 27 if (curr_diff < diff)
1390     {
1391 zoff99 2 return 0;
1392     }
1393     w = w->next;
1394     }
1395     return 1;
1396     }
1397     #endif
1398    
1399     static int maneuver_category(enum item_type type)
1400     {
1401 zoff99 27 switch (type)
1402     {
1403     case type_street_0:
1404     return 1;
1405     case type_street_1_city:
1406     return 2;
1407     case type_street_2_city:
1408     return 3;
1409     case type_street_3_city:
1410     return 4;
1411     case type_street_4_city:
1412     return 5;
1413     case type_highway_city:
1414     return 7;
1415     case type_street_1_land:
1416     return 2;
1417     case type_street_2_land:
1418     return 3;
1419     case type_street_3_land:
1420     return 4;
1421     case type_street_4_land:
1422     return 5;
1423     case type_street_n_lanes:
1424     return 6;
1425     case type_highway_land:
1426     return 7;
1427     case type_ramp:
1428     return 0;
1429     case type_roundabout:
1430     return 0;
1431     case type_ferry:
1432     return 0;
1433     default:
1434     return 0;
1435 zoff99 2 }
1436 zoff99 27
1437 zoff99 2 }
1438    
1439 zoff99 30 static int is_way_allowed(struct navigation *nav, struct navigation_way *way, int mode)
1440 zoff99 2 {
1441     if (!nav->vehicleprofile)
1442 zoff99 27 {
1443 zoff99 2 return 1;
1444 zoff99 27 }
1445 zoff99 30 return !way->flags || ((way->flags & (way->dir >= 0 ? nav->vehicleprofile->flags_forward_mask : nav->vehicleprofile->flags_reverse_mask)) == nav->vehicleprofile->flags);
1446 zoff99 2 }
1447    
1448     /**
1449     * @brief Checks if navit has to create a maneuver to drive from old to new
1450     *
1451     * This function checks if it has to create a "maneuver" - i.e. guide the user - to drive
1452     * from "old" to "new".
1453     *
1454     * @param old The old navigation item, where we're coming from
1455     * @param new The new navigation item, where we're going to
1456     * @param delta The angle the user has to steer to navigate from old to new
1457     * @param reason A text string explaining how the return value resulted
1458     * @return True if navit should guide the user, false otherwise
1459     */
1460 zoff99 30 static int maneuver_required2(struct navigation *nav, struct navigation_itm *old, struct navigation_itm *new, int *delta, char **reason)
1461 zoff99 2 {
1462 zoff99 27 int ret = 0, d, dw, dlim;
1463     char *r = NULL;
1464 zoff99 2 struct navigation_way *w;
1465 zoff99 30 int cat, ncat, wcat, maxcat, left = -180, right = 180, is_unambigous = 0, is_same_street;
1466 zoff99 2
1467 zoff99 27 //dbg(1, "enter %p %p %p\n", old, new, delta);
1468     d = angle_delta(old->angle_end, new->way.angle2);
1469     if (!new->way.next)
1470     {
1471 zoff99 2 /* No announcement necessary */
1472 zoff99 27 r = "no: Only one possibility";
1473     }
1474 zoff99 30 else if (!new->way.next->next && new->way.next->item.type == type_ramp && !is_way_allowed(nav, new->way.next, 1))
1475 zoff99 27 {
1476 zoff99 2 /* If the other way is only a ramp and it is one-way in the wrong direction, no announcement necessary */
1477 zoff99 27 r = "no: Only ramp";
1478 zoff99 2 }
1479 zoff99 27 if (!r)
1480     {
1481 zoff99 30 if ((old->way.flags & AF_ROUNDABOUT) && !(new->way.flags & AF_ROUNDABOUT))
1482 zoff99 27 {
1483     r = "yes: leaving roundabout";
1484     ret = 1;
1485     }
1486 zoff99 30 else if (!(old->way.flags & AF_ROUNDABOUT) && (new->way.flags & AF_ROUNDABOUT))
1487 zoff99 27 {
1488     r = "no: entering roundabout";
1489     }
1490 zoff99 30 else if ((old->way.flags & AF_ROUNDABOUT) && (new->way.flags & AF_ROUNDABOUT))
1491 zoff99 27 r = "no: staying in roundabout";
1492 zoff99 2 }
1493 zoff99 27 if (!r && abs(d) > 75)
1494     {
1495 zoff99 2 /* always make an announcement if you have to make a sharp turn */
1496 zoff99 27 r = "yes: delta over 75";
1497     ret = 1;
1498 zoff99 2 }
1499 zoff99 27 cat = maneuver_category(old->way.item.type);
1500     ncat = maneuver_category(new->way.item.type);
1501     if (!r)
1502     {
1503 zoff99 2 /* Check whether the street keeps its name */
1504 zoff99 30 is_same_street = is_same_street2(old->way.name1, old->way.name2, new->way.name1, new->way.name2);
1505 zoff99 2 w = new->way.next;
1506 zoff99 27 maxcat = -1;
1507     while (w)
1508     {
1509     dw = angle_delta(old->angle_end, w->angle2);
1510     if (dw < 0)
1511     {
1512 zoff99 2 if (dw > left)
1513 zoff99 27 left = dw;
1514     }
1515     else
1516     {
1517 zoff99 2 if (dw < right)
1518 zoff99 27 right = dw;
1519 zoff99 2 }
1520 zoff99 27 wcat = maneuver_category(w->item.type);
1521 zoff99 2 /* If any other street has the same name but isn't a highway (a highway might split up temporarily), then
1522 zoff99 27 we can't use the same name criterium */
1523 zoff99 30 if (is_same_street && is_same_street2(old->way.name1, old->way.name2, w->name1, w->name2) && (cat != 7 || wcat != 7) && is_way_allowed(nav, w, 2))
1524 zoff99 27 is_same_street = 0;
1525 zoff99 2 /* Even if the ramp has the same name, announce it */
1526 zoff99 30 if (new->way.item.type == type_ramp && old->way.item.type != type_ramp)
1527 zoff99 27 is_same_street = 0;
1528 zoff99 2 /* Mark if the street has a higher or the same category */
1529     if (wcat > maxcat)
1530 zoff99 27 maxcat = wcat;
1531 zoff99 2 w = w->next;
1532     }
1533     /* get the delta limit for checking for other streets. It is lower if the street has no other
1534 zoff99 27 streets of the same or higher category */
1535 zoff99 2 if (ncat < cat)
1536 zoff99 27 dlim = 80;
1537 zoff99 2 else
1538 zoff99 27 dlim = 120;
1539 zoff99 2 /* if the street is really straight, the others might be closer to straight */
1540     if (abs(d) < 20)
1541 zoff99 27 dlim /= 2;
1542     if ((maxcat == ncat && maxcat == cat) || (ncat == 0 && cat == 0))
1543     dlim = abs(d) * 620 / 256;
1544 zoff99 2 else if (maxcat < ncat && maxcat < cat)
1545 zoff99 27 dlim = abs(d) * 128 / 256;
1546     if (left < -dlim && right > dlim)
1547     is_unambigous = 1;
1548     if (!is_same_street && is_unambigous < 1)
1549     {
1550     ret = 1;
1551     r = "yes: not same street or ambigous";
1552     }
1553     else
1554     r = "no: same street and unambigous";
1555 zoff99 2 #ifdef DEBUG
1556 zoff99 27 // r=g_strdup_printf("yes: d %d left %d right %d dlim=%d cat old:%d new:%d max:%d unambigous=%d same_street=%d", d, left, right, dlim, cat, ncat, maxcat, is_unambigous, is_same_street);
1557 zoff99 2 #endif
1558     }
1559 zoff99 27 *delta = d;
1560 zoff99 2 if (reason)
1561 zoff99 27 {
1562     *reason = r;
1563     }
1564 zoff99 2 return ret;
1565    
1566     #if 0
1567 zoff99 27 if (new->item.type == old->item.type || (new->item.type != type_ramp && old->item.type != type_ramp))
1568     {
1569     if (is_same_street2(old, new))
1570     {
1571     if (! entering_straight(new, abs(*delta)))
1572     {
1573 zoff99 2 dbg(1, "maneuver_required: Not driving straight: yes\n");
1574     if (reason)
1575 zoff99 27 *reason="yes: Not driving straight";
1576 zoff99 2 return 1;
1577     }
1578    
1579 zoff99 27 if (check_multiple_streets(new))
1580     {
1581     if (entering_straight(new,abs(*delta)*2))
1582     {
1583 zoff99 2 if (reason)
1584 zoff99 27 *reason="no: delta < ext_limit for same name";
1585 zoff99 2 return 0;
1586     }
1587 zoff99 27 if (reason)
1588     *reason="yes: delta > ext_limit for same name";
1589 zoff99 2 return 1;
1590 zoff99 27 }
1591     else
1592     {
1593 zoff99 2 dbg(1, "maneuver_required: Staying on the same street: no\n");
1594     if (reason)
1595 zoff99 27 *reason="no: Staying on same street";
1596 zoff99 2 return 0;
1597     }
1598     }
1599 zoff99 27 }
1600     else
1601     dbg(1, "maneuver_required: old or new is ramp\n");
1602 zoff99 2 #if 0
1603 zoff99 27 if (old->item.type == type_ramp && (new->item.type == type_highway_city || new->item.type == type_highway_land))
1604     {
1605 zoff99 2 dbg(1, "no_maneuver_required: old is ramp new is highway\n");
1606     if (reason)
1607 zoff99 27 *reason="no: old is ramp new is highway";
1608 zoff99 2 return 0;
1609     }
1610     #endif
1611     #if 0
1612 zoff99 27 if (old->crossings_end == 2)
1613     {
1614 zoff99 2 dbg(1, "maneuver_required: only 2 connections: no\n");
1615     return 0;
1616     }
1617     #endif
1618     dbg(1,"delta=%d-%d=%d\n", new->way.angle2, old->angle_end, *delta);
1619 zoff99 27 if ((new->item.type == type_highway_land || new->item.type == type_highway_city || old->item.type == type_highway_land || old->item.type == type_highway_city) && (!is_same_street_systematic(old, new) || (old->name2 != NULL && new->name2 == NULL)))
1620     {
1621 zoff99 2 dbg(1, "maneuver_required: highway changed name\n");
1622     if (reason)
1623 zoff99 27 *reason="yes: highway changed name";
1624 zoff99 2 return 1;
1625     }
1626 zoff99 27 if (abs(*delta) < straight_limit)
1627     {
1628     if (! entering_straight(new,abs(*delta)))
1629     {
1630 zoff99 2 if (reason)
1631 zoff99 27 *reason="yes: not straight";
1632 zoff99 2 dbg(1, "maneuver_required: not driving straight: yes\n");
1633     return 1;
1634     }
1635    
1636     dbg(1, "maneuver_required: delta(%d) < %d: no\n", *delta, straight_limit);
1637     if (reason)
1638 zoff99 27 *reason="no: delta < limit";
1639 zoff99 2 return 0;
1640     }
1641 zoff99 27 if (abs(*delta) < ext_straight_limit)
1642     {
1643     if (entering_straight(new,abs(*delta)*2))
1644     {
1645 zoff99 2 if (reason)
1646 zoff99 27 *reason="no: delta < ext_limit";
1647 zoff99 2 return 0;
1648     }
1649     }
1650    
1651 zoff99 27 if (! check_multiple_streets(new))
1652     {
1653 zoff99 2 dbg(1, "maneuver_required: only one possibility: no\n");
1654     if (reason)
1655 zoff99 27 *reason="no: only one possibility";
1656 zoff99 2 return 0;
1657     }
1658    
1659     dbg(1, "maneuver_required: delta=%d: yes\n", *delta);
1660     if (reason)
1661 zoff99 27 *reason="yes: delta >= limit";
1662 zoff99 2 return 1;
1663     #endif
1664     }
1665    
1666     static struct navigation_command *
1667     command_new(struct navigation *this_, struct navigation_itm *itm, int delta)
1668     {
1669     struct navigation_command *ret=g_new0(struct navigation_command, 1);
1670 zoff99 27 //dbg(1, "enter this_=%p itm=%p delta=%d\n", this_, itm, delta);
1671     ret->delta = delta;
1672     ret->itm = itm;
1673 zoff99 30 if (itm && itm->prev && itm->way.next && itm->prev->way.next && !(itm->way.flags & AF_ROUNDABOUT) && (itm->prev->way.flags & AF_ROUNDABOUT))
1674 zoff99 27 {
1675     int len = 0;
1676     int angle = 0;
1677 zoff99 2 int entry_angle;
1678 zoff99 27 struct navigation_itm *itm2 = itm->prev;
1679 zoff99 30 int exit_angle = angle_median(itm->prev->angle_end, itm->way.next->angle2);
1680 zoff99 27 //dbg(1, "exit %d median from %d,%d\n", exit_angle, itm->prev->angle_end, itm->way.next->angle2);
1681     while (itm2 && (itm2->way.flags & AF_ROUNDABOUT))
1682     {
1683     len += itm2->length;
1684     angle = itm2->angle_end;
1685     itm2 = itm2->prev;
1686 zoff99 2 }
1687 zoff99 27 if (itm2 && itm2->next && itm2->next->way.next)
1688     {
1689     itm2 = itm2->next;
1690 zoff99 30 entry_angle = angle_median(angle_opposite(itm2->way.angle2), itm2->way.next->angle2);
1691 zoff99 27 // dbg(1, "entry %d median from %d(%d),%d\n", entry_angle, angle_opposite(itm2->way.angle2), itm2->way.angle2, itm2->way.next->angle2);
1692 zoff99 2 }
1693 zoff99 27 else
1694     {
1695     entry_angle = angle_opposite(angle);
1696     }
1697     //dbg(0, "entry %d exit %d\n", entry_angle, exit_angle);
1698     ret->roundabout_delta = angle_delta(entry_angle, exit_angle);
1699     ret->length = len + roundabout_extra_length;
1700 zoff99 2 }
1701 zoff99 27 if (this_->cmd_last)
1702     {
1703     this_->cmd_last->next = ret;
1704 zoff99 2 ret->prev = this_->cmd_last;
1705     }
1706 zoff99 27 this_->cmd_last = ret;
1707 zoff99 2
1708     if (!this_->cmd_first)
1709 zoff99 27 this_->cmd_first = ret;
1710 zoff99 2 return ret;
1711     }
1712    
1713 zoff99 27 static void make_maneuvers(struct navigation *this_, struct route *route)
1714 zoff99 2 {
1715 zoff99 27 struct navigation_itm *itm, *last = NULL, *last_itm = NULL;
1716 zoff99 2 int delta;
1717 zoff99 27 itm = this_->first;
1718     this_->cmd_last = NULL;
1719     this_->cmd_first = NULL;
1720     while (itm)
1721     {
1722     if (last)
1723     {
1724     if (maneuver_required2(this_, last_itm, itm, &delta, NULL))
1725     {
1726 zoff99 2 command_new(this_, itm, delta);
1727     }
1728 zoff99 27 }
1729     else
1730     last = itm;
1731     last_itm = itm;
1732     itm = itm->next;
1733 zoff99 2 }
1734     command_new(this_, last_itm, 0);
1735     }
1736    
1737 zoff99 27 static int contains_suffix(char *name, char *suffix)
1738 zoff99 2 {
1739     if (!suffix)
1740     return 0;
1741     if (strlen(name) < strlen(suffix))
1742     return 0;
1743 zoff99 27 return !g_strcasecmp(name + strlen(name) - strlen(suffix), suffix);
1744 zoff99 2 }
1745    
1746     static char *
1747     replace_suffix(char *name, char *search, char *replace)
1748     {
1749 zoff99 27 int len = strlen(name) - strlen(search);
1750     char *ret = g_malloc(len + strlen(replace) + 1);
1751 zoff99 2 strncpy(ret, name, len);
1752 zoff99 27 strcpy(ret + len, replace);
1753     if (isupper(name[len]))
1754     {
1755     ret[len] = toupper(ret[len]);
1756 zoff99 2 }
1757    
1758     return ret;
1759     }
1760    
1761     static char *
1762 zoff99 30 navigation_item_destination(struct navigation *nav, struct navigation_itm *itm, struct navigation_itm *next, char *prefix)
1763 zoff99 2 {
1764 zoff99 27 char *ret = NULL, *name1, *sep, *name2;
1765     char *n1, *n2;
1766     int i, sex;
1767     int vocabulary1 = 65535;
1768     int vocabulary2 = 65535;
1769 zoff99 2 struct attr attr;
1770    
1771 zoff99 27 if (!prefix)
1772     prefix = "";
1773 zoff99 30 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name, &attr, NULL))
1774 zoff99 27 vocabulary1 = attr.u.num;
1775 zoff99 30 if (nav->speech && speech_get_attr(nav->speech, attr_vocabulary_name_systematic, &attr, NULL))
1776 zoff99 27 vocabulary2 = attr.u.num;
1777     n1 = itm->way.name1;
1778     n2 = itm->way.name2;
1779 zoff99 2 if (!vocabulary1)
1780 zoff99 27 n1 = NULL;
1781 zoff99 2 if (!vocabulary2)
1782 zoff99 27 n2 = NULL;
1783     if (!n1 && !n2 && itm->way.item.type == type_ramp && vocabulary2)
1784     {
1785     //dbg(1,">> Next is ramp %lx current is %lx \n", itm->way.item.type, next->way.item.type);
1786    
1787     if (next->way.item.type == type_ramp)
1788 zoff99 2 return NULL;
1789 zoff99 30 if (itm->way.item.type == type_highway_city || itm->way.item.type == type_highway_land)
1790 zoff99 27 {
1791     #ifdef HAVE_API_ANDROID
1792 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
1793 zoff99 27 android_send_generic_text(1,"+*#O:exit\n");
1794     gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
1795     android_send_generic_text(1,xy);
1796     g_free(xy);
1797     #endif
1798 zoff99 28 #endif
1799 zoff99 27 return g_strdup_printf("%s%s", prefix, _("exit")); /* %FIXME Can this even be reached? and "exit" is the wrong text anyway ! */
1800     }
1801 zoff99 2 else
1802 zoff99 27 {
1803     #ifdef HAVE_API_ANDROID
1804 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
1805 zoff99 27 android_send_generic_text(1,"+*#O:into the ramp\n");
1806     gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
1807     android_send_generic_text(1,xy);
1808     g_free(xy);
1809     #endif
1810 zoff99 28 #endif
1811 zoff99 27 return g_strdup_printf("%s%s", prefix, _("into the ramp"));
1812     }
1813    
1814 zoff99 2 }
1815 zoff99 27
1816 zoff99 2 if (!n1 && !n2)
1817 zoff99 27 {
1818 zoff99 2 return NULL;
1819 zoff99 27 }
1820    
1821     if (n1)
1822     {
1823     sex = -1;
1824     name1 = NULL;
1825     for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); i++)
1826     {
1827     if (contains_suffix(n1, suffixes[i].fullname))
1828     {
1829     sex = suffixes[i].sex;
1830     name1 = g_strdup(n1);
1831 zoff99 2 break;
1832     }
1833 zoff99 27 if (contains_suffix(n1, suffixes[i].abbrev))
1834     {
1835     sex = suffixes[i].sex;
1836 zoff99 30 name1 = replace_suffix(n1, suffixes[i].abbrev, suffixes[i].fullname);
1837 zoff99 2 break;
1838     }
1839     }
1840 zoff99 27
1841     if (n2)
1842     {
1843     name2 = n2;
1844     sep = " ";
1845 zoff99 2 }
1846 zoff99 27 else
1847     {
1848     name2 = "";
1849     sep = "";
1850 zoff99 2 }
1851 zoff99 27
1852     gchar* xy;
1853     switch (sex)
1854     {
1855     case -1:
1856     #ifdef HAVE_API_ANDROID
1857 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
1858 zoff99 27 android_send_generic_text(1,"+*#O:%sinto the street %s%s%s\n");
1859     xy=g_strdup_printf("+*#1:%s\n", prefix);
1860     android_send_generic_text(1,xy);
1861     g_free(xy);
1862     xy=g_strdup_printf("+*#1:%s\n", n1);
1863     android_send_generic_text(1,xy);
1864     g_free(xy);
1865     xy=g_strdup_printf("+*#1:%s\n", sep);
1866     android_send_generic_text(1,xy);
1867     g_free(xy);
1868     xy=g_strdup_printf("+*#1:%s\n", name2);
1869     android_send_generic_text(1,xy);
1870     g_free(xy);
1871     #endif
1872 zoff99 28 #endif
1873 zoff99 27 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name
1874 zoff99 30 ret = g_strdup_printf(_("%sinto the street %s%s%s"), prefix, n1, sep, name2);
1875 zoff99 27 break;
1876     case 1:
1877     #ifdef HAVE_API_ANDROID
1878 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
1879 zoff99 27 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|male form\n");
1880     xy=g_strdup_printf("+*#1:%s\n", prefix);
1881     android_send_generic_text(1,xy);
1882     g_free(xy);
1883     xy=g_strdup_printf("+*#1:%s\n", name1);
1884     android_send_generic_text(1,xy);
1885     g_free(xy);
1886     xy=g_strdup_printf("+*#1:%s\n", sep);
1887     android_send_generic_text(1,xy);
1888     g_free(xy);
1889     xy=g_strdup_printf("+*#1:%s\n", name2);
1890     android_send_generic_text(1,xy);
1891     g_free(xy);
1892     #endif
1893 zoff99 28 #endif
1894 zoff99 27 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Male form. The stuff after | doesn't have to be included
1895 zoff99 30 ret = g_strdup_printf(_("%sinto the %s%s%s|male form"), prefix, name1, sep, name2);
1896 zoff99 27 break;
1897     case 2:
1898     #ifdef HAVE_API_ANDROID
1899 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
1900 zoff99 27 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|female form\n");
1901     xy=g_strdup_printf("+*#1:%s\n", prefix);
1902     android_send_generic_text(1,xy);
1903     g_free(xy);
1904     xy=g_strdup_printf("+*#1:%s\n", name1);
1905     android_send_generic_text(1,xy);
1906     g_free(xy);
1907     xy=g_strdup_printf("+*#1:%s\n", sep);
1908     android_send_generic_text(1,xy);
1909     g_free(xy);
1910     xy=g_strdup_printf("+*#1:%s\n", name2);
1911     android_send_generic_text(1,xy);
1912     g_free(xy);
1913     #endif
1914 zoff99 28 #endif
1915 zoff99 27 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Female form. The stuff after | doesn't have to be included
1916 zoff99 30 ret = g_strdup_printf(_("%sinto the %s%s%s|female form"), prefix, name1, sep, name2);
1917 zoff99 27 break;
1918     case 3:
1919     #ifdef HAVE_API_ANDROID
1920 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
1921 zoff99 27 android_send_generic_text(1,"+*#O:%sinto the %s%s%s|neutral form\n");
1922     xy=g_strdup_printf("+*#1:%s\n", prefix);
1923     android_send_generic_text(1,xy);
1924     g_free(xy);
1925     xy=g_strdup_printf("+*#1:%s\n", name1);
1926     android_send_generic_text(1,xy);
1927     g_free(xy);
1928     xy=g_strdup_printf("+*#1:%s\n", sep);
1929     android_send_generic_text(1,xy);
1930     g_free(xy);
1931     xy=g_strdup_printf("+*#1:%s\n", name2);
1932     android_send_generic_text(1,xy);
1933     g_free(xy);
1934     #endif
1935 zoff99 28 #endif
1936 zoff99 27 // TRANSLATORS: Arguments: 1: Prefix (Space if required) 2: Street Name 3: Separator (Space if required), 4: Systematic Street Name. Neutral form. The stuff after | doesn't have to be included
1937 zoff99 30 ret = g_strdup_printf(_("%sinto the %s%s%s|neutral form"), prefix, name1, sep, name2);
1938 zoff99 27 break;
1939     }
1940 zoff99 2 g_free(name1);
1941 zoff99 27
1942     }
1943     else
1944     {
1945     #ifdef HAVE_API_ANDROID
1946 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
1947 zoff99 27 android_send_generic_text(1,"+*#O:sinto the %s\n");
1948     gchar* xy=g_strdup_printf("+*#1:%s\n", prefix);
1949     android_send_generic_text(1,xy);
1950     g_free(xy);
1951     xy=g_strdup_printf("+*#1:%s\n", n2);
1952     android_send_generic_text(1,xy);
1953     g_free(xy);
1954     #endif
1955 zoff99 28 #endif
1956 zoff99 27 // TRANSLATORS: gives the name of the next road to turn into (into the E17)
1957     ret = g_strdup_printf(_("%sinto the %s"), prefix, n2);
1958     }
1959    
1960     name1 = ret;
1961    
1962     while (name1 && *name1)
1963     {
1964     switch (*name1)
1965     {
1966     case '|':
1967     *name1 = '\0';
1968     break;
1969     case '/':
1970     *name1++ = ' ';
1971     break;
1972     default:
1973     name1++;
1974 zoff99 2 }
1975     }
1976 zoff99 27
1977 zoff99 2 return ret;
1978     }
1979    
1980     static char *
1981 zoff99 30 show_maneuver(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type, int connect)
1982 zoff99 2 {
1983 zoff99 27 // TRANSLATORS: right, as in 'Turn right'
1984     char *dir = _("right");
1985     char *strength = "";
1986     int distance = itm->dest_length - cmd->itm->dest_length;
1987     char *d, *ret = NULL;
1988     int delta = cmd->delta;
1989 zoff99 2 int level;
1990     int strength_needed;
1991     int skip_roads;
1992     int count_roundabout;
1993     struct navigation_itm *cur;
1994     struct navigation_way *w;
1995 zoff99 27
1996     if (connect)
1997     {
1998 zoff99 2 level = -2; // level = -2 means "connect to another maneuver via 'then ...'"
1999     }
2000 zoff99 27 else
2001     {
2002     level = 1;
2003     }
2004 zoff99 2
2005     w = itm->next->way.next;
2006     strength_needed = 0;
2007 zoff99 27
2008     if (angle_delta(itm->next->way.angle2, itm->angle_end) < 0)
2009     {
2010     while (w)
2011     {
2012     if (angle_delta(w->angle2, itm->angle_end) < 0)
2013     {
2014 zoff99 2 strength_needed = 1;
2015     break;
2016     }
2017     w = w->next;
2018     }
2019 zoff99 27 }
2020     else
2021     {
2022     while (w)
2023     {
2024     if (angle_delta(w->angle2, itm->angle_end) > 0)
2025     {
2026 zoff99 2 strength_needed = 1;
2027     break;
2028     }
2029     w = w->next;
2030     }
2031     }
2032    
2033 zoff99 27 if (delta < 0)
2034     {
2035     #ifdef HAVE_API_ANDROID
2036 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2037 zoff99 27 android_send_generic_text(1,"+*#O:left\n");
2038     #endif
2039 zoff99 28 #endif
2040 zoff99 27 // TRANSLATORS: left, as in 'Turn left'
2041     dir = _("left");
2042     delta = -delta;
2043 zoff99 2 }
2044 zoff99 27 else
2045     {
2046     // dir = right
2047     #ifdef HAVE_API_ANDROID
2048 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2049 zoff99 27 android_send_generic_text(1,"+*#O:right\n");
2050     #endif
2051 zoff99 28 #endif
2052 zoff99 27 }
2053 zoff99 2
2054 zoff99 27 if (strength_needed)
2055     {
2056     if (delta < 45)
2057     {
2058     #ifdef HAVE_API_ANDROID
2059 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2060 zoff99 27 android_send_generic_text(1,"+*#O:slight \n");
2061     #endif
2062 zoff99 28 #endif
2063 zoff99 27 // TRANSLATORS: Don't forget the ending space
2064     // TRANSLATORS: EXAMPLE: turn slight right
2065     strength = _("slight ");
2066 zoff99 2 }
2067 zoff99 27 else if (delta < 105)
2068     {
2069     strength = "";
2070     }
2071     else if (delta < 165)
2072     {
2073     #ifdef HAVE_API_ANDROID
2074 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2075 zoff99 27 android_send_generic_text(1,"+*#O:hard \n");
2076     #endif
2077 zoff99 28 #endif
2078 zoff99 27 // TRANSLATORS: Don't forget the ending space
2079     // TRANSLATORS: EXAMPLE: turn hard right
2080     strength = _("hard ");
2081     }
2082     else if (delta < 180)
2083     {
2084     #ifdef HAVE_API_ANDROID
2085 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2086 zoff99 27 android_send_generic_text(1,"+*#O:really hard \n");
2087     #endif
2088 zoff99 28 #endif
2089 zoff99 27 // TRANSLATORS: Don't forget the ending space
2090     // TRANSLATORS: EXAMPLE: turn really hard right
2091     strength = _("really hard ");
2092     }
2093     else
2094     {
2095     // dbg(1,"delta=%d\n", delta);
2096     // TRANSLATORS: Don't forget the ending space
2097     //strength=_("unknown ");
2098     strength = "";
2099     }
2100 zoff99 2 }
2101 zoff99 27
2102     if (type != attr_navigation_long_exact)
2103     {
2104     distance = round_distance(distance);
2105     }
2106    
2107     if (type == attr_navigation_speech)
2108     {
2109     if (nav->turn_around && nav->turn_around == nav->turn_around_limit)
2110     {
2111     #ifdef HAVE_API_ANDROID
2112 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2113 zoff99 27 android_send_generic_text(1,"+*#O:When possible, please turn around\n");
2114     #endif
2115 zoff99 28 #endif
2116 zoff99 2 return g_strdup(_("When possible, please turn around"));
2117     }
2118 zoff99 27
2119     if (!connect)
2120     {
2121 zoff99 30 level = navigation_get_announce_level_cmd(nav, itm, cmd, distance - cmd->length);
2122 zoff99 27 }
2123     // dbg(1,"distance=%d level=%d type=0x%x\n", distance, level, itm->way.item.type);
2124 zoff99 2 }
2125    
2126 zoff99 27 if (cmd->itm->prev->way.flags & AF_ROUNDABOUT)
2127     {
2128 zoff99 2 cur = cmd->itm->prev;
2129     count_roundabout = 0;
2130 zoff99 27 while (cur && (cur->way.flags & AF_ROUNDABOUT))
2131     {
2132     // If the next segment has no exit or the exit isn't allowed, don't count it
2133 zoff99 30 if (cur->next->way.next && is_way_allowed(nav, cur->next->way.next, 3))
2134 zoff99 27 {
2135 zoff99 2 count_roundabout++;
2136     }
2137     cur = cur->prev;
2138     }
2139 zoff99 27
2140     gchar* xy;
2141    
2142     switch (level)
2143     {
2144     case 2:
2145     #ifdef HAVE_API_ANDROID
2146 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2147 zoff99 27 android_send_generic_text(1,"+*#O:Enter the roundabout soon\n");
2148     #endif
2149 zoff99 28 #endif
2150 zoff99 27 return g_strdup(_("Enter the roundabout soon"));
2151     case 1:
2152     d = get_distance(nav, distance, type, 1);
2153    
2154     #ifdef HAVE_API_ANDROID
2155 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2156 zoff99 27 android_send_generic_text(1,"+*#O:In %s, enter the roundabout\n");
2157     xy=g_strdup_printf("+*#1:%s\n", d);
2158     android_send_generic_text(1,xy);
2159     g_free(xy);
2160     #endif
2161 zoff99 28 #endif
2162 zoff99 27 // TRANSLATORS: %s is the distance to the roundabout
2163     // TRANSLATORS: EXAMPLE: In 300m, enter the roundabout
2164     ret = g_strdup_printf(_("In %s, enter the roundabout"), d);
2165     g_free(d);
2166     return ret;
2167     case -2:
2168     #ifdef HAVE_API_ANDROID
2169 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2170 zoff99 27 android_send_generic_text(1,"+*#O:then leave the roundabout at the %s\n");
2171     xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
2172     android_send_generic_text(1,xy);
2173     g_free(xy);
2174     #endif
2175 zoff99 28 #endif
2176 zoff99 27 // TRANSLATORS: EXAMPLE: ... then leave the roundabout at the second exit
2177 zoff99 30 return g_strdup_printf(_("then leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
2178 zoff99 27 case 0:
2179     #ifdef HAVE_API_ANDROID
2180 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2181 zoff99 27 android_send_generic_text(1,"+*#O:Leave the roundabout at the %s\n");
2182     xy=g_strdup_printf("+*#1:%s\n", get_exit_count_str(count_roundabout));
2183     android_send_generic_text(1,xy);
2184     g_free(xy);
2185     #endif
2186 zoff99 28 #endif
2187 zoff99 27 // TRANSLATORS: EXAMPLE: Leave the roundabout at the second exit
2188 zoff99 30 return g_strdup_printf(_("Leave the roundabout at the %s"), get_exit_count_str(count_roundabout));
2189 zoff99 27 }
2190     }
2191    
2192     switch (level)
2193     {
2194     case 3:
2195     d = get_distance(nav, distance, type, 1);
2196    
2197     #ifdef HAVE_API_ANDROID
2198 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2199 zoff99 27 android_send_generic_text(1,"+*#O:Follow the road for the next %s\n");
2200     gchar* xy=g_strdup_printf("+*#1:%s\n", d);
2201     android_send_generic_text(1,xy);
2202     g_free(xy);
2203     #endif
2204 zoff99 28 #endif
2205 zoff99 27 // TRANSLATORS: EXAMPLE: Follow the road for the next 300 meters
2206     ret = g_strdup_printf(_("Follow the road for the next %s"), d);
2207     g_free(d);
2208     return ret;
2209 zoff99 2 case 2:
2210 zoff99 27 #ifdef HAVE_API_ANDROID
2211 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2212 zoff99 27 android_send_generic_text(1,"+*#O:soon\n");
2213     #endif
2214 zoff99 28 #endif
2215 zoff99 27 d = g_strdup(_("soon"));
2216     break;
2217 zoff99 2 case 1:
2218 zoff99 27 d = get_distance(nav, distance, attr_navigation_short, 0);
2219     break;
2220     case 0:
2221 zoff99 30 skip_roads = count_possible_turns(nav, cmd->prev ? cmd->prev->itm : nav->first, cmd->itm, cmd->delta);
2222 zoff99 27 if (skip_roads > 0)
2223     {
2224     if (get_count_str(skip_roads + 1))
2225     {
2226     #ifdef HAVE_API_ANDROID
2227 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2228 zoff99 27 android_send_generic_text(1,"+*#O:Take the %1$s road to the %2$s\n");
2229     gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
2230     android_send_generic_text(1,xy);
2231     g_free(xy);
2232     xy=g_strdup_printf("+*#1:%s\n", dir);
2233     android_send_generic_text(1,xy);
2234     g_free(xy);
2235     #endif
2236 zoff99 28 #endif
2237 zoff99 27 // TRANSLATORS: First argument is the how manieth street to take, second the direction
2238 zoff99 30 ret = g_strdup_printf(_("Take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
2239 zoff99 27 return ret;
2240     }
2241     else
2242     {
2243     #ifdef HAVE_API_ANDROID
2244 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2245 zoff99 27 android_send_generic_text(1,"+*#O:after %i roads\n");
2246     gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
2247     android_send_generic_text(1,xy);
2248     g_free(xy);
2249     #endif
2250 zoff99 28 #endif
2251 zoff99 27 d = g_strdup_printf(_("after %i roads"), skip_roads);
2252     }
2253     }
2254     else
2255     {
2256     #ifdef HAVE_API_ANDROID
2257 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2258 zoff99 27 android_send_generic_text(1,"+*#O:now\n");
2259     #endif
2260 zoff99 28 #endif
2261 zoff99 27 d = g_strdup(_("now"));
2262     }
2263     break;
2264 zoff99 2 case -2:
2265 zoff99 30 skip_roads = count_possible_turns(nav, cmd->prev->itm, cmd->itm, cmd->delta);
2266 zoff99 27 if (skip_roads > 0)
2267     {
2268     // TRANSLATORS: First argument is the how manieth street to take, second the direction
2269     // TRANSLATORS: EXAMPLE: ... then take the second road to the right
2270     if (get_count_str(skip_roads + 1))
2271     {
2272     #ifdef HAVE_API_ANDROID
2273 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2274 zoff99 27 android_send_generic_text(1,"+*#O:then take the %1$s road to the %2$s\n");
2275     gchar* xy=g_strdup_printf("+*#1:%s\n", get_count_str(skip_roads + 1));
2276     android_send_generic_text(1,xy);
2277     g_free(xy);
2278     xy=g_strdup_printf("+*#1:%s\n", dir);
2279     android_send_generic_text(1,xy);
2280     g_free(xy);
2281     #endif
2282 zoff99 28 #endif
2283 zoff99 30 ret = g_strdup_printf(_("then take the %1$s road to the %2$s"), get_count_str(skip_roads + 1), dir);
2284 zoff99 27 return ret;
2285     }
2286     else
2287     {
2288     #ifdef HAVE_API_ANDROID
2289 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2290 zoff99 27 android_send_generic_text(1,"+*#O:after %i roads\n");
2291     gchar* xy=g_strdup_printf("+*#1:%i\n", skip_roads);
2292     android_send_generic_text(1,xy);
2293     g_free(xy);
2294     #endif
2295 zoff99 28 #endif
2296 zoff99 27 d = g_strdup_printf(_("after %i roads"), skip_roads);
2297     }
2298 zoff99 2
2299     }
2300 zoff99 27 else
2301     {
2302     d = g_strdup("");
2303 zoff99 2 }
2304 zoff99 27 break;
2305     default:
2306     #ifdef HAVE_API_ANDROID
2307 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2308 zoff99 27 android_send_generic_text(1,"+*#O:error\n");
2309     #endif
2310 zoff99 28 #endif
2311 zoff99 27 d = g_strdup(_("error"));
2312     }
2313 zoff99 2
2314 zoff99 27 if (cmd->itm->next)
2315     {
2316 zoff99 2 int tellstreetname = 0;
2317     char *destination = NULL;
2318 zoff99 27
2319     if (type == attr_navigation_speech)
2320     { // In voice mode
2321 zoff99 2 // In Voice Mode only tell the street name in level 1 or in level 0 if level 1
2322     // was skipped
2323    
2324 zoff99 27 if (level == 1)
2325     { // we are close to the intersection
2326 zoff99 2 cmd->itm->streetname_told = 1; // remeber to be checked when we turn
2327     tellstreetname = 1; // Ok so we tell the name of the street
2328     }
2329    
2330 zoff99 27 if (level == 0)
2331     {
2332     if (cmd->itm->streetname_told == 0) // we are right at the intersection
2333     {
2334     tellstreetname = 1;
2335     }
2336 zoff99 2 else
2337 zoff99 27 {
2338     cmd->itm->streetname_told = 0; // reset just in case we come to the same street again
2339     }
2340 zoff99 2 }
2341    
2342     }
2343     else
2344 zoff99 27 {
2345     tellstreetname = 1;
2346     }
2347 zoff99 2
2348 zoff99 27 if (global_speak_streetnames == 0)
2349     {
2350     // never speak streetnames (user config option)
2351     tellstreetname = 0;
2352     }
2353 zoff99 2
2354 zoff99 27 if (nav->tell_street_name && tellstreetname)
2355     {
2356     destination = navigation_item_destination(nav, cmd->itm, itm, " ");
2357 zoff99 2 }
2358 zoff99 27
2359     if (level != -2)
2360     {
2361     #ifdef HAVE_API_ANDROID
2362 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2363 zoff99 27 android_send_generic_text(1,"+*#O:Turn %1$s%2$s %3$s%4$s\n");
2364     gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
2365     android_send_generic_text(1,xy);
2366     g_free(xy);
2367     xy=g_strdup_printf("+*#1:%s\n", dir);
2368     android_send_generic_text(1,xy);
2369     g_free(xy);
2370     xy=g_strdup_printf("+*#1:%s\n", d);
2371     android_send_generic_text(1,xy);
2372     g_free(xy);
2373     xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
2374     android_send_generic_text(1,xy);
2375     g_free(xy);
2376     #endif
2377 zoff99 28 #endif
2378 zoff99 27 // TRANSLATORS: The first argument is strength, the second direction, the third distance and the fourth destination Example: 'Turn 'slightly' 'left' in '100 m' 'onto baker street'
2379 zoff99 30 ret = g_strdup_printf(_("Turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
2380 zoff99 27 }
2381     else
2382     {
2383     #ifdef HAVE_API_ANDROID
2384 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2385 zoff99 27 android_send_generic_text(1,"+*#O:then turn %1$s%2$s %3$s%4$s\n");
2386     gchar* xy=g_strdup_printf("+*#1:%s\n", strength);
2387     android_send_generic_text(1,xy);
2388     g_free(xy);
2389     xy=g_strdup_printf("+*#1:%s\n", dir);
2390     android_send_generic_text(1,xy);
2391     g_free(xy);
2392     xy=g_strdup_printf("+*#1:%s\n", d);
2393     android_send_generic_text(1,xy);
2394     g_free(xy);
2395     xy=g_strdup_printf("+*#1:%s\n", destination ? destination : "");
2396     android_send_generic_text(1,xy);
2397     g_free(xy);
2398     #endif
2399 zoff99 28 #endif
2400 zoff99 27 // TRANSLATORS: First argument is strength, second direction, third how many roads to skip, fourth destination
2401 zoff99 30 ret = g_strdup_printf(_("then turn %1$s%2$s %3$s%4$s"), strength, dir, d, destination ? destination : "");
2402 zoff99 27 }
2403 zoff99 2 g_free(destination);
2404 zoff99 27 }
2405     else
2406     {
2407     if (!connect)
2408     {
2409     #ifdef HAVE_API_ANDROID
2410 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2411 zoff99 27 android_send_generic_text(1,"+*#O:You have reached your destination %s\n");
2412     gchar* xy=g_strdup_printf("+*#1:%s\n", d);
2413     android_send_generic_text(1,xy);
2414     g_free(xy);
2415     #endif
2416 zoff99 28 #endif
2417 zoff99 27 // TRANSLATORS: EXAMPLE: You have reached your destination in 300 meters
2418     ret = g_strdup_printf(_("You have reached your destination %s"), d);
2419 zoff99 2 }
2420 zoff99 27 else
2421     {
2422     #ifdef HAVE_API_ANDROID
2423 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2424 zoff99 27 android_send_generic_text(1,"+*#O:then you have reached your destination.\n");
2425     #endif
2426 zoff99 28 #endif
2427 zoff99 27 ret = g_strdup_printf(_("then you have reached your destination."));
2428     }
2429 zoff99 2 }
2430     g_free(d);
2431     return ret;
2432     }
2433    
2434     /**
2435     * @brief Creates announcements for maneuvers, plus maneuvers immediately following the next maneuver
2436     *
2437     * This function does create an announcement for the current maneuver and for maneuvers
2438     * immediately following that maneuver, if these are too close and we're in speech navigation.
2439     *
2440     * @return An announcement that should be made
2441     */
2442     static char *
2443 zoff99 30 show_next_maneuvers(struct navigation *nav, struct navigation_itm *itm, struct navigation_command *cmd, enum attr_type type)
2444 zoff99 2 {
2445 zoff99 27 struct navigation_command *cur, *prev;
2446     int distance = itm->dest_length - cmd->itm->dest_length;
2447 zoff99 2 int level, dist, i, time;
2448 zoff99 27 int speech_time, time2nav;
2449     char *ret, *old, *buf, *next;
2450 zoff99 2
2451 zoff99 27 if (type != attr_navigation_speech)
2452     {
2453 zoff99 2 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only in speech navigation
2454     }
2455    
2456 zoff99 30 level = navigation_get_announce_level(nav, itm->way.item.type, distance - cmd->length);
2457 zoff99 2
2458 zoff99 27 if (level > 1)
2459     {
2460 zoff99 2 return show_maneuver(nav, itm, cmd, type, 0); // We accumulate maneuvers only if they are close
2461     }
2462    
2463 zoff99 27 if (cmd->itm->told)
2464     {
2465     #ifdef HAVE_API_ANDROID
2466 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2467 zoff99 27 android_send_generic_text(1,"+*#C1:*CANCEL*\n");
2468     #endif
2469 zoff99 28 #endif
2470 zoff99 2 return g_strdup("");
2471     }
2472    
2473     ret = show_maneuver(nav, itm, cmd, type, 0);
2474 zoff99 27 time2nav = navigation_time(itm, cmd->itm->prev);
2475 zoff99 2 old = NULL;
2476    
2477     cur = cmd->next;
2478     prev = cmd;
2479     i = 0;
2480 zoff99 27 while (cur && cur->itm)
2481     {
2482 zoff99 2 // We don't merge more than 3 announcements...
2483 zoff99 27 if (i > 1)
2484     { // if you change this, please also change the value below, that is used to terminate the loop
2485 zoff99 2 break;
2486     }
2487 zoff99 27
2488     next = show_maneuver(nav, prev->itm, cur, type, 0);
2489 zoff99 2 if (nav->speech)
2490 zoff99 27 {
2491     speech_time = speech_estimate_duration(nav->speech, next);
2492     }
2493 zoff99 2 else
2494 zoff99 27 {
2495 zoff99 2 speech_time = -1;
2496 zoff99 27 }
2497 zoff99 2 g_free(next);
2498    
2499 zoff99 27 if (speech_time == -1)
2500     { // user didn't set cps
2501 zoff99 2 speech_time = 30; // assume 3 seconds
2502     }
2503    
2504     dist = prev->itm->dest_length - cur->itm->dest_length;
2505 zoff99 27 time = navigation_time(prev->itm, cur->itm->prev);
2506 zoff99 2
2507 zoff99 27 if (time >= (speech_time + 30))
2508     { // 3 seconds for understanding what has been said
2509 zoff99 2 break;
2510     }
2511    
2512     old = ret;
2513     buf = show_maneuver(nav, prev->itm, cur, type, 1);
2514     ret = g_strdup_printf("%s, %s", old, buf);
2515     g_free(buf);
2516 zoff99 27
2517 zoff99 30 if (nav->speech && speech_estimate_duration(nav->speech, ret) > time2nav)
2518 zoff99 27 {
2519 zoff99 2 g_free(ret);
2520     ret = old;
2521     i = 2; // This will terminate the loop
2522 zoff99 27 }
2523     else
2524     {
2525 zoff99 2 g_free(old);
2526     }
2527    
2528     // If the two maneuvers are *really* close, we shouldn't tell the second one again, because TTS won't be fast enough
2529 zoff99 27 if (time <= speech_time)
2530     {
2531     #ifdef HAVE_API_ANDROID
2532 zoff99 28 #ifdef NAVIT_SAY_DEBUG_PRINT
2533 zoff99 27 android_send_generic_text(1,"+*#C2:*CANCEL*\n");
2534     #endif
2535 zoff99 28 #endif
2536 zoff99 2 cur->itm->told = 1;
2537     }
2538    
2539     prev = cur;
2540     cur = cur->next;
2541     i++;
2542     }
2543    
2544     return ret;
2545     }
2546    
2547 zoff99 30 static void navigation_call_callbacks(struct navigation *this_, int force_speech)
2548 zoff99 2 {
2549     int distance, level = 0;
2550 zoff99 27 void *p = this_;
2551 zoff99 30
2552 zoff99 2 if (!this_->cmd_first)
2553 zoff99 30 {
2554 zoff99 2 return;
2555 zoff99 30 }
2556    
2557 zoff99 2 callback_list_call(this_->callback, 1, &p);
2558 zoff99 27 //dbg(1,"force_speech=%d turn_around=%d turn_around_limit=%d\n", force_speech, this_->turn_around, this_->turn_around_limit);
2559 zoff99 30 distance = round_distance(this_->first->dest_length - this_->cmd_first->itm->dest_length);
2560     if (this_->turn_around_limit && this_->turn_around == this_->turn_around_limit)
2561 zoff99 27 {
2562     //dbg(1,"distance=%d distance_turn=%d\n", distance, this_->distance_turn);
2563     while (distance > this_->distance_turn)
2564     {
2565     this_->level_last = 4;
2566     level = 4;
2567     force_speech = 2;
2568 zoff99 2 if (this_->distance_turn >= 500)
2569 zoff99 27 this_->distance_turn *= 2;
2570 zoff99 2 else
2571 zoff99 27 this_->distance_turn = 500;
2572 zoff99 2 }
2573 zoff99 27 }
2574 zoff99 30 else if (!this_->turn_around_limit || this_->turn_around == -this_->turn_around_limit + 1)
2575 zoff99 27 {
2576     this_->distance_turn = 50;
2577     distance -= this_->cmd_first->length;
2578 zoff99 30 level = navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance);
2579 zoff99 27 if (level < this_->level_last)
2580     {
2581 zoff99 2 /* only tell if the level is valid for more than 3 seconds */
2582 zoff99 27 int speed_distance = this_->first->speed * 30 / 36;
2583 zoff99 30 if (distance < speed_distance || navigation_get_announce_level_cmd(this_, this_->first, this_->cmd_first, distance - speed_distance) == level)
2584 zoff99 27 {
2585 zoff99 30 dbg(1, "distance %d speed_distance %d\n", distance, speed_distance);
2586 zoff99 27 dbg(1, "level %d < %d\n", level, this_->level_last);
2587     this_->level_last = level;
2588     force_speech = 3;
2589 zoff99 2 }
2590     }
2591 zoff99 27
2592     if (!item_is_equal(this_->cmd_first->itm->way.item, this_->item_last))
2593     {
2594     this_->item_last = this_->cmd_first->itm->way.item;
2595 zoff99 2 if (this_->delay)
2596 zoff99 27 this_->curr_delay = this_->delay;
2597 zoff99 2 else
2598 zoff99 27 force_speech = 5;
2599     }
2600     else
2601     {
2602     if (this_->curr_delay)
2603     {
2604 zoff99 2 this_->curr_delay--;
2605     if (!this_->curr_delay)
2606 zoff99 27 force_speech = 4;
2607 zoff99 2 }
2608     }
2609     }
2610 zoff99 27
2611     if (force_speech)
2612     {
2613     this_->level_last = level;
2614     this_->curr_delay = 0;
2615 zoff99 30 dbg(1, "force_speech=%d distance=%d level=%d type=0x%x\n", force_speech, distance, level, this_->first->way.item.type);
2616 zoff99 2 callback_list_call(this_->callback_speech, 1, &p);
2617     }
2618     }
2619    
2620 zoff99 30 static void navigation_update(struct navigation *this_, struct route *route, struct attr *attr)
2621 zoff99 2 {
2622     struct map *map;
2623     struct map_rect *mr;
2624 zoff99 27 struct item *ritem; /* Holds an item from the route map */
2625     struct item *sitem; /* Holds the corresponding item from the actual map */
2626     struct attr street_item, street_direction;
2627 zoff99 2 struct navigation_itm *itm;
2628     struct attr vehicleprofile;
2629 zoff99 27 int mode = 0, incr = 0, first = 1;
2630 zoff99 2 if (attr->type != attr_route_status)
2631     return;
2632    
2633 zoff99 27 dbg(1, "enter %d\n", mode);
2634 zoff99 30 if (attr->u.num == route_status_no_destination || attr->u.num == route_status_not_found || attr->u.num == route_status_path_done_new)
2635 zoff99 2 navigation_flush(this_);
2636 zoff99 30 if (attr->u.num != route_status_path_done_new && attr->u.num != route_status_path_done_incremental)
2637 zoff99 2 return;
2638 zoff99 27
2639     if (!this_->route)
2640 zoff99 2 return;
2641 zoff99 27 map = route_get_map(this_->route);
2642     if (!map)
2643 zoff99 2 return;
2644 zoff99 27 mr = map_rect_new(map, NULL);
2645     if (!mr)
2646 zoff99 2 return;
2647     if (route_get_attr(route, attr_vehicleprofile, &vehicleprofile, NULL))
2648 zoff99 27 this_->vehicleprofile = vehicleprofile.u.vehicleprofile;
2649 zoff99 2 else
2650 zoff99 27 this_->vehicleprofile = NULL;
2651     //dbg(1,"enter\n");
2652    
2653     while ((ritem = map_rect_get_item(mr)))
2654     {
2655 zoff99 30 if (ritem->type == type_route_start && this_->turn_around > -this_->turn_around_limit + 1)
2656 zoff99 2 this_->turn_around--;
2657 zoff99 30 if (ritem->type == type_route_start_reverse && this_->turn_around < this_->turn_around_limit)
2658 zoff99 2 this_->turn_around++;
2659     if (ritem->type != type_street_route)
2660     continue;
2661 zoff99 27
2662     if (first && item_attr_get(ritem, attr_street_item, &street_item))
2663     {
2664     first = 0;
2665 zoff99 2 if (!item_attr_get(ritem, attr_direction, &street_direction))
2666 zoff99 27 street_direction.u.num = 0;
2667     sitem = street_item.u.item;
2668     //dbg(1,"sitem=%p\n", sitem);
2669     itm = item_hash_lookup(this_->hash, sitem);
2670     //dbg(2,"itm for item with id (0x%x,0x%x) is %p\n", sitem->id_hi, sitem->id_lo, itm);
2671    
2672     if (itm && itm->way.dir != street_direction.u.num)
2673     {
2674     //dbg(2,"wrong direction\n");
2675     itm = NULL;
2676 zoff99 2 }
2677     navigation_destroy_itms_cmds(this_, itm);
2678 zoff99 27 if (itm)
2679     {
2680 zoff99 2 navigation_itm_update(itm, ritem);
2681     break;
2682     }
2683 zoff99 27 //dbg(1,"not on track\n");
2684 zoff99 2 }
2685     navigation_itm_new(this_, ritem);
2686     }
2687 zoff99 27 dbg(2, "turn_around=%d\n", this_->turn_around);
2688     if (first)
2689 zoff99 2 navigation_destroy_itms_cmds(this_, NULL);
2690 zoff99 27 else
2691     {
2692     if (!ritem)
2693     {
2694 zoff99 2 navigation_itm_new(this_, NULL);
2695 zoff99 27 make_maneuvers(this_, this_->route);
2696 zoff99 2 }
2697     calculate_dest_distance(this_, incr);
2698 zoff99 27 //profile(0,"end");
2699 zoff99 2 navigation_call_callbacks(this_, FALSE);
2700     }
2701     map_rect_destroy(mr);
2702     }
2703    
2704 zoff99 27 static void navigation_flush(struct navigation *this_)
2705 zoff99 2 {
2706     navigation_destroy_itms_cmds(this_, NULL);
2707     }
2708    
2709 zoff99 27 void navigation_destroy(struct navigation *this_)
2710 zoff99 2 {
2711     navigation_flush(this_);
2712     item_hash_destroy(this_->hash);
2713     callback_list_destroy(this_->callback);
2714     callback_list_destroy(this_->callback_speech);
2715     g_free(this_);
2716     }
2717    
2718 zoff99 30 int navigation_register_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
2719 zoff99 2 {
2720     if (type == attr_navigation_speech)
2721     callback_list_add(this_->callback_speech, cb);
2722     else
2723     callback_list_add(this_->callback, cb);
2724     return 1;
2725     }
2726    
2727 zoff99 30 void navigation_unregister_callback(struct navigation *this_, enum attr_type type, struct callback *cb)
2728 zoff99 2 {
2729     if (type == attr_navigation_speech)
2730     callback_list_remove_destroy(this_->callback_speech, cb);
2731     else
2732     callback_list_remove_destroy(this_->callback, cb);
2733     }
2734    
2735     struct map *
2736     navigation_get_map(struct navigation *this_)
2737     {
2738     struct attr *attrs[5];
2739 zoff99 27 struct attr type, navigation, data, description;
2740     type.type = attr_type;
2741     type.u.str = "navigation";
2742     navigation.type = attr_navigation;
2743     navigation.u.navigation = this_;
2744     data.type = attr_data;
2745     data.u.str = "";
2746     description.type = attr_description;
2747     description.u.str = "Navigation";
2748    
2749     attrs[0] = &type;
2750     attrs[1] = &navigation;
2751     attrs[2] = &data;
2752     attrs[3] = &description;
2753     attrs[4] = NULL;
2754     if (!this_->map)
2755     this_->map = map_new(NULL, attrs);
2756     return this_->map;
2757 zoff99 2 }
2758    
2759 zoff99 27 struct map_priv
2760     {
2761 zoff99 2 struct navigation *navigation;
2762     };
2763    
2764 zoff99 27 struct map_rect_priv
2765     {
2766 zoff99 2 struct navigation *nav;
2767     struct navigation_command *cmd;
2768     struct navigation_command *cmd_next;
2769     struct navigation_itm *itm;
2770     struct navigation_itm *itm_next;
2771     struct navigation_itm *cmd_itm;
2772     struct navigation_itm *cmd_itm_next;
2773     struct item item;
2774     enum attr_type attr_next;
2775     int ccount;
2776     int debug_idx;
2777     struct navigation_way *ways;
2778     int show_all;
2779     char *str;
2780     };
2781    
2782 zoff99 30 static int navigation_map_item_coord_get(void *priv_data, struct coord *c, int count)
2783 zoff99 2 {
2784 zoff99 27 struct map_rect_priv *this = priv_data;
2785     if (this->ccount || !count)
2786 zoff99 2 return 0;
2787 zoff99 27 *c = this->itm->start;
2788     this->ccount = 1;
2789 zoff99 2 return 1;
2790     }
2791    
2792 zoff99 30 static int navigation_map_item_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2793 zoff99 2 {
2794 zoff99 27 struct map_rect_priv *this_ = priv_data;
2795     struct navigation_command *cmd = this_->cmd;
2796     struct navigation_itm *itm = this_->itm;
2797     struct navigation_itm *prev = itm->prev;
2798     attr->type = attr_type;
2799 zoff99 2
2800 zoff99 27 if (this_->str)
2801     {
2802 zoff99 2 g_free(this_->str);
2803 zoff99 27 this_->str = NULL;
2804 zoff99 2 }
2805    
2806 zoff99 27 if (cmd)
2807     {
2808 zoff99 2 if (cmd->itm != itm)
2809 zoff99 27 cmd = NULL;
2810 zoff99 2 }
2811 zoff99 27 switch (attr_type)
2812     {
2813     case attr_navigation_short:
2814     this_->attr_next = attr_navigation_long;
2815     if (cmd)
2816     {
2817 zoff99 30 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2818 zoff99 2 return 1;
2819     }
2820 zoff99 27 return 0;
2821     case attr_navigation_long:
2822     this_->attr_next = attr_navigation_long_exact;
2823     if (cmd)
2824     {
2825 zoff99 30 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2826 zoff99 2 return 1;
2827     }
2828 zoff99 27 return 0;
2829     case attr_navigation_long_exact:
2830     this_->attr_next = attr_navigation_speech;
2831     if (cmd)
2832     {
2833 zoff99 30 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, cmd, attr_type);
2834 zoff99 2 return 1;
2835     }
2836 zoff99 27 return 0;
2837     case attr_navigation_speech:
2838     this_->attr_next = attr_length;
2839     if (cmd)
2840     {
2841 zoff99 30 this_->str = attr->u.str = show_next_maneuvers(this_->nav, this_->cmd_itm, this_->cmd, attr_type);
2842 zoff99 2 return 1;
2843     }
2844 zoff99 27 return 0;
2845     case attr_length:
2846     this_->attr_next = attr_time;
2847     if (cmd)
2848     {
2849 zoff99 30 attr->u.num = this_->cmd_itm->dest_length - cmd->itm->dest_length;
2850 zoff99 2 return 1;
2851     }
2852 zoff99 27 return 0;
2853     case attr_time:
2854     this_->attr_next = attr_destination_length;
2855     if (cmd)
2856     {
2857     attr->u.num = this_->cmd_itm->dest_time - cmd->itm->dest_time;
2858 zoff99 2 return 1;
2859     }
2860 zoff99 27 return 0;
2861     case attr_destination_length:
2862     attr->u.num = itm->dest_length;
2863     this_->attr_next = attr_destination_time;
2864     return 1;
2865     case attr_destination_time:
2866     attr->u.num = itm->dest_time;
2867     this_->attr_next = attr_street_name;
2868     return 1;
2869     case attr_street_name:
2870     attr->u.str = itm->way.name1;
2871     this_->attr_next = attr_street_name_systematic;
2872     if (attr->u.str)
2873 zoff99 2 return 1;
2874 zoff99 27 return 0;
2875     case attr_street_name_systematic:
2876     attr->u.str = itm->way.name2;
2877     this_->attr_next = attr_debug;
2878     if (attr->u.str)
2879     return 1;
2880     return 0;
2881     case attr_debug:
2882     switch (this_->debug_idx)
2883     {
2884     case 0:
2885     this_->debug_idx++;
2886 zoff99 30 this_->str = attr->u.str = g_strdup_printf("angle:%d (- %d)", itm->way.angle2, itm->angle_end);
2887 zoff99 27 return 1;
2888     case 1:
2889     this_->debug_idx++;
2890 zoff99 30 this_->str = attr->u.str = g_strdup_printf("item type:%s", item_to_name(itm->way.item.type));
2891 zoff99 27 return 1;
2892     case 2:
2893     this_->debug_idx++;
2894     if (cmd)
2895     {
2896 zoff99 30 this_->str = attr->u.str = g_strdup_printf("delta:%d", cmd->delta);
2897 zoff99 27 return 1;
2898     }
2899     case 3:
2900     this_->debug_idx++;
2901     if (prev)
2902     {
2903 zoff99 30 this_->str = attr->u.str = g_strdup_printf("prev street_name:%s", prev->way.name1);
2904 zoff99 27 return 1;
2905     }
2906     case 4:
2907     this_->debug_idx++;
2908     if (prev)
2909     {
2910 zoff99 30 this_->str = attr->u.str = g_strdup_printf("prev street_name_systematic:%s", prev->way.name2);
2911 zoff99 27 return 1;
2912     }
2913     case 5:
2914     this_->debug_idx++;
2915     if (prev)
2916     {
2917 zoff99 30 this_->str = attr->u.str = g_strdup_printf("prev angle:(%d -) %d", prev->way.angle2, prev->angle_end);
2918 zoff99 27 return 1;
2919     }
2920     case 6:
2921     this_->debug_idx++;
2922     this_->ways = itm->way.next;
2923     if (prev)
2924     {
2925 zoff99 30 this_->str = attr->u.str = g_strdup_printf("prev item type:%s", item_to_name(prev->way.item.type));
2926 zoff99 27 return 1;
2927     }
2928     case 7:
2929     if (this_->ways && prev)
2930     {
2931 zoff99 30 this_->str = attr->u.str = g_strdup_printf("other item angle:%d delta:%d flags:%d dir:%d type:%s id:(0x%x,0x%x)", this_->ways->angle2, angle_delta(prev->angle_end, this_->ways->angle2), this_->ways->flags, this_->ways->dir, item_to_name(this_->ways->item.type), this_->ways->item.id_hi, this_->ways->item.id_lo);
2932 zoff99 27 this_->ways = this_->ways->next;
2933     return 1;
2934     }
2935     this_->debug_idx++;
2936     case 8:
2937     this_->debug_idx++;
2938     if (prev)
2939     {
2940     int delta = 0;
2941     char *reason = NULL;
2942 zoff99 30 maneuver_required2(this_->nav, prev, itm, &delta, &reason);
2943     this_->str = attr->u.str = g_strdup_printf("reason:%s", reason);
2944 zoff99 27 return 1;
2945     }
2946    
2947     default:
2948     this_->attr_next = attr_none;
2949     return 0;
2950 zoff99 2 }
2951 zoff99 27 case attr_any:
2952     while (this_->attr_next != attr_none)
2953     {
2954 zoff99 30 if (navigation_map_item_attr_get(priv_data, this_->attr_next, attr))
2955 zoff99 27 return 1;
2956     }
2957     return 0;
2958 zoff99 2 default:
2959 zoff99 27 attr->type = attr_none;
2960 zoff99 2 return 0;
2961     }
2962     }
2963    
2964 zoff99 30 static struct item_methods navigation_map_item_methods = { NULL, navigation_map_item_coord_get, NULL, navigation_map_item_attr_get, };
2965 zoff99 2
2966 zoff99 27 static void navigation_map_destroy(struct map_priv *priv)
2967 zoff99 2 {
2968     g_free(priv);
2969     }
2970    
2971 zoff99 27 static void navigation_map_rect_init(struct map_rect_priv *priv)
2972 zoff99 2 {
2973 zoff99 27 priv->cmd_next = priv->nav->cmd_first;
2974     priv->cmd_itm_next = priv->itm_next = priv->nav->first;
2975 zoff99 2 }
2976    
2977     static struct map_rect_priv *
2978     navigation_map_rect_new(struct map_priv *priv, struct map_selection *sel)
2979     {
2980 zoff99 27 struct navigation *nav = priv->navigation;
2981 zoff99 2 struct map_rect_priv *ret=g_new0(struct map_rect_priv, 1);
2982 zoff99 27 ret->nav = nav;
2983 zoff99 2 navigation_map_rect_init(ret);
2984 zoff99 27 ret->item.meth = &navigation_map_item_methods;
2985     ret->item.priv_data = ret;
2986 zoff99 2 #ifdef DEBUG
2987     ret->show_all=1;
2988     #endif
2989     return ret;
2990     }
2991    
2992 zoff99 27 static void navigation_map_rect_destroy(struct map_rect_priv *priv)
2993 zoff99 2 {
2994     g_free(priv);
2995     }
2996    
2997     static struct item *
2998     navigation_map_get_item(struct map_rect_priv *priv)
2999     {
3000 zoff99 27 struct item *ret = &priv->item;
3001 zoff99 2 int delta;
3002     if (!priv->itm_next)
3003     return NULL;
3004 zoff99 27 priv->itm = priv->itm_next;
3005     priv->cmd = priv->cmd_next;
3006     priv->cmd_itm = priv->cmd_itm_next;
3007 zoff99 2 if (!priv->cmd)
3008     return NULL;
3009 zoff99 27 if (!priv->show_all && priv->itm->prev != NULL)
3010     priv->itm = priv->cmd->itm;
3011     priv->itm_next = priv->itm->next;
3012 zoff99 2 if (priv->itm->prev)
3013 zoff99 27 ret->type = type_nav_none;
3014 zoff99 2 else
3015 zoff99 27 ret->type = type_nav_position;
3016     if (priv->cmd->itm == priv->itm)
3017     {
3018     priv->cmd_itm_next = priv->cmd->itm;
3019     priv->cmd_next = priv->cmd->next;
3020 zoff99 2 if (priv->cmd_itm_next && !priv->cmd_itm_next->next)
3021 zoff99 27 ret->type = type_nav_destination;
3022     else
3023     {
3024 zoff99 30 if (priv->itm && priv->itm->prev && !(priv->itm->way.flags & AF_ROUNDABOUT) && (priv->itm->prev->way.flags & AF_ROUNDABOUT))
3025 zoff99 27 {
3026     enum item_type r = type_none, l = type_none;
3027     switch (((180 + 22) - priv->cmd->roundabout_delta) / 45)
3028     {
3029     case 0:
3030     case 1:
3031     r = type_nav_roundabout_r1;
3032     l = type_nav_roundabout_l7;
3033     break;
3034     case 2:
3035     r = type_nav_roundabout_r2;
3036     l = type_nav_roundabout_l6;
3037     break;
3038     case 3:
3039     r = type_nav_roundabout_r3;
3040     l = type_nav_roundabout_l5;
3041     break;
3042     case 4:
3043     r = type_nav_roundabout_r4;
3044     l = type_nav_roundabout_l4;
3045     break;
3046     case 5:
3047     r = type_nav_roundabout_r5;
3048     l = type_nav_roundabout_l3;
3049     break;
3050     case 6:
3051     r = type_nav_roundabout_r6;
3052     l = type_nav_roundabout_l2;
3053     break;
3054     case 7:
3055     r = type_nav_roundabout_r7;
3056     l = type_nav_roundabout_l1;
3057     break;
3058     case 8:
3059     r = type_nav_roundabout_r8;
3060     l = type_nav_roundabout_l8;
3061     break;
3062 zoff99 2 }
3063 zoff99 27 dbg(1, "delta %d\n", priv->cmd->delta);
3064 zoff99 2 if (priv->cmd->delta < 0)
3065 zoff99 27 ret->type = l;
3066 zoff99 2 else
3067 zoff99 27 ret->type = r;
3068     }
3069     else
3070     {
3071     delta = priv->cmd->delta;
3072     if (delta < 0)
3073     {
3074     delta = -delta;
3075 zoff99 2 if (delta < 45)
3076 zoff99 27 ret->type = type_nav_left_1;
3077 zoff99 2 else if (delta < 105)
3078 zoff99 27 ret->type = type_nav_left_2;
3079     else if (delta < 165)
3080     ret->type = type_nav_left_3;
3081 zoff99 2 else
3082 zoff99 27 ret->type = type_none;
3083     }
3084     else
3085     {
3086 zoff99 2 if (delta < 45)
3087 zoff99 27 ret->type = type_nav_right_1;
3088 zoff99 2 else if (delta < 105)
3089 zoff99 27 ret->type = type_nav_right_2;
3090     else if (delta < 165)
3091     ret->type = type_nav_right_3;
3092 zoff99 2 else
3093 zoff99 27 ret->type = type_none;
3094 zoff99 2 }
3095     }
3096     }
3097     }
3098 zoff99 27 priv->ccount = 0;
3099     priv->debug_idx = 0;
3100     priv->attr_next = attr_navigation_short;
3101 zoff99 2
3102 zoff99 27 ret->id_lo = priv->itm->dest_count;
3103     dbg(1, "type=%d\n", ret->type);
3104 zoff99 2 return ret;
3105     }
3106    
3107     static struct item *
3108     navigation_map_get_item_byid(struct map_rect_priv *priv, int id_hi, int id_lo)
3109     {
3110     struct item *ret;
3111     navigation_map_rect_init(priv);
3112 zoff99 27 while ((ret = navigation_map_get_item(priv)))
3113     {
3114     if (ret->id_hi == id_hi && ret->id_lo == id_lo)
3115 zoff99 2 return ret;
3116     }
3117     return NULL;
3118     }
3119    
3120 zoff99 30 static struct map_methods navigation_map_meth = { projection_mg, "utf-8", navigation_map_destroy, navigation_map_rect_new, navigation_map_rect_destroy, navigation_map_get_item, navigation_map_get_item_byid, NULL, NULL, NULL, };
3121 zoff99 2
3122     static struct map_priv *
3123 zoff99 30 navigation_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
3124 zoff99 2 {
3125     struct map_priv *ret;
3126     struct attr *navigation_attr;
3127    
3128 zoff99 27 navigation_attr = attr_search(attrs, NULL, attr_navigation);
3129     if (!navigation_attr)
3130     return NULL;ret=g_new0(struct map_priv, 1);
3131     *meth = navigation_map_meth;
3132     ret->navigation = navigation_attr->u.navigation;
3133 zoff99 2
3134     return ret;
3135     }
3136    
3137 zoff99 27 void navigation_set_route(struct navigation *this_, struct route *route)
3138 zoff99 2 {
3139     struct attr callback;
3140 zoff99 27 this_->route = route;
3141 zoff99 30 this_->route_cb = callback_new_attr_1(callback_cast(navigation_update), attr_route_status, this_);
3142     callback_add_names(this_->route_cb, "navigation_set_route", "navigation_update");
3143 zoff99 27 callback.type = attr_callback;
3144     callback.u.callback = this_->route_cb;
3145 zoff99 2 route_add_attr(route, &callback);
3146     }
3147    
3148 zoff99 27 void navigation_init(void)
3149 zoff99 2 {
3150     plugin_register_map_type("navigation", navigation_map_new);
3151     }

   
Visit the ZANavi Wiki