added more modules
[navit-package] / src / navit.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <glib.h>
6 #include "debug.h"
7 #include "navit.h"
8 #include "gui.h"
9 #include "map.h"
10 #include "mapset.h"
11 #include "coord.h"
12 #include "point.h"
13 #include "transform.h"
14 #include "projection.h"
15 #include "menu.h"
16 #include "graphics.h"
17 #include "cursor.h"
18 #include "popup.h"
19 #include "route.h"
20 #include "navigation.h"
21 #include "track.h"
22
23 struct navit {
24         GList *mapsets;
25         GList *layouts;
26         struct gui *gui;
27         struct layout *layout_current;
28         struct graphics *gra;
29         struct action *action;
30         struct transformation *trans;
31         struct compass *compass;
32         struct map_data *map_data;
33         struct menu *menu;
34         struct menu *toolbar;
35         struct statusbar *statusbar;
36         struct menu *menubar;
37         struct route *route;
38         struct navigation *navigation;
39         struct cursor *cursor;
40         struct speech *speech;
41         struct vehicle *vehicle;
42         struct track *track;
43         struct map_flags *flags;
44         int ready;
45         struct window *win;
46         struct displaylist *displaylist;
47         int cursor_flag;
48         int update;
49         int follow;
50         int update_curr;
51         int follow_curr;
52 };
53
54 struct gui *
55 main_loop_gui;
56
57
58 void
59 navit_add_mapset(struct navit *this_, struct mapset *ms)
60 {
61         this_->mapsets = g_list_append(this_->mapsets, ms);
62 }
63
64 struct mapset *
65 navit_get_mapset(struct navit *this_)
66 {
67         return this_->mapsets->data;
68 }
69
70 void
71 navit_add_layout(struct navit *this_, struct layout *lay)
72 {
73         this_->layouts = g_list_append(this_->layouts, lay);
74 }
75
76 void
77 navit_draw(struct navit *this_)
78 {
79         transform_setup_source_rect(this_->trans);
80         graphics_draw(this_->gra, this_->displaylist, this_->mapsets, this_->trans, this_->layouts, this_->route);
81         this_->ready=1;
82 }
83
84 void
85 navit_draw_displaylist(struct navit *this_)
86 {
87         if (this_->ready) {
88                 graphics_displaylist_draw(this_->gra, this_->displaylist, this_->trans, this_->layouts, this_->route);
89         }
90 }
91
92 static void
93 navit_resize(void *data, int w, int h)
94 {
95         struct navit *this_=data;
96         transform_set_size(this_->trans, w, h);
97         navit_draw(this_);
98 }
99
100 static void
101 navit_button(void *data, int pressed, int button, struct point *p)
102 {
103         struct navit *this_=data;
104         if (pressed && button == 1) {
105                 int border=16;
106                 if (! transform_within_border(this_->trans, p, border)) {
107                         navit_set_center_screen(this_, p);
108                 } else
109                         popup(this_, button, p);
110         }
111         if (pressed && button == 2)
112                 navit_set_center_screen(this_, p);
113         if (pressed && button == 3)
114                 popup(this_, button, p);
115         if (pressed && button == 4)
116                 navit_zoom_in(this_, 2);
117         if (pressed && button == 5)
118                 navit_zoom_out(this_, 2);
119 }
120
121 void
122 navit_zoom_in(struct navit *this_, int factor)
123 {
124         long scale=transform_get_scale(this_->trans)/factor;
125         if (scale < 1)
126                 scale=1;
127         transform_set_scale(this_->trans, scale);
128         navit_draw(this_);
129 }
130
131 void
132 navit_zoom_out(struct navit *this_, int factor)
133 {
134         long scale=transform_get_scale(this_->trans)*factor;
135         transform_set_scale(this_->trans,scale);
136         navit_draw(this_);
137 }
138
139 struct navit *
140 navit_new(const char *ui, const char *graphics, struct coord *center, enum projection pro, int zoom)
141 {
142         struct navit *this_=g_new0(struct navit, 1);
143
144         this_->cursor_flag=1;
145         this_->trans=transform_new();
146         transform_set_projection(this_->trans, pro);
147
148         transform_setup(this_->trans, center, zoom, 0);
149         /* this_->flags=g_new0(struct map_flags, 1); */
150         this_->displaylist=graphics_displaylist_new();
151         this_->gui=gui_new(this_, ui, 792, 547);
152         if (! this_->gui) {
153                 g_warning("failed to create gui '%s'", ui);
154                 navit_destroy(this_);
155                 return NULL;
156         }
157         if (gui_has_main_loop(this_->gui)) {
158                 if (! main_loop_gui) {
159                         main_loop_gui=this_->gui;
160                 } else {
161                         g_warning("gui with main loop already active, ignoring this instance");
162                         navit_destroy(this_);
163                         return NULL;
164                 }
165         }
166         this_->menubar=gui_menubar_new(this_->gui);
167         this_->toolbar=gui_toolbar_new(this_->gui);
168         this_->statusbar=gui_statusbar_new(this_->gui);
169         this_->gra=graphics_new(graphics);
170         if (! this_->gra) {
171                 g_warning("failed to create graphics '%s'", graphics);
172                 navit_destroy(this_);
173                 return NULL;
174         }
175         graphics_register_resize_callback(this_->gra, navit_resize, this_);
176         graphics_register_button_callback(this_->gra, navit_button, this_);
177         if (gui_set_graphics(this_->gui, this_->gra)) {
178                 g_warning("failed to connect graphics '%s' to gui '%s'\n", graphics, ui);
179                 navit_destroy(this_);
180                 return NULL;
181         }
182         graphics_init(this_->gra);
183         return this_;
184 }
185
186 static void
187 navit_map_toggle(struct menu *menu, void *this__p, void *map_p)
188 {
189         if ((menu_get_toggle(menu) != 0) != (map_get_active(map_p) != 0)) {
190                 map_set_active(map_p, (menu_get_toggle(menu) != 0));
191                 navit_draw(this__p);
192         }
193 }
194
195 static void
196 navit_projection_set(struct menu *menu, void *this__p, void *pro_p)
197 {
198         struct navit *this_=this__p;
199         enum projection pro=(enum projection) pro_p;
200         struct coord_geo g;
201         struct coord *c;
202
203         c=transform_center(this_->trans);
204         transform_to_geo(transform_get_projection(this_->trans), c, &g);
205         transform_set_projection(this_->trans, pro);
206         transform_from_geo(pro, &g, c);
207         navit_draw(this_);
208 }
209
210 static void
211 navit_set_destination_menu(struct menu *menu, void *this__p, void *c_p)
212 {
213         struct navit *this_=this__p;
214         struct coord *c=c_p;
215         if (this_->route) {
216                 route_set_destination(this_->route, c);
217                 navit_draw(this_);
218         }
219
220 }
221
222 void
223 navit_set_destination(struct navit *this_, struct coord *c, char *description)
224 {
225         int fd;
226         char *buffer;
227         buffer=g_strdup_printf("0x%x 0x%x %s\n", c->x, c->y, description);
228         fd=open("destination.txt", O_RDWR|O_CREAT|O_APPEND, 0644);
229         if (fd != -1)
230                 write(fd, buffer, strlen(buffer));
231         close(fd);
232         g_free(buffer);
233         if (this_->route) {
234                 route_set_destination(this_->route, c);
235                 navit_draw(this_);
236         }
237 }
238
239 struct navit *global_navit;
240
241 static void
242 navit_debug(struct navit *this_)
243 {
244 #if 0
245 #include "attr.h"
246 #include "item.h"
247 #include "search.h"
248         struct attr attr;
249         struct search_list *sl;
250         struct search_list_result *res;
251
252         debug_level_set("data_mg:town_search_get_item",1);
253         debug_level_set("data_mg:town_search_compare",1);
254         debug_level_set("data_mg:tree_search_next",1);
255         sl=search_list_new(this_->mapsets->data);
256         attr.type=attr_country_all;
257         attr.u.str="Deu";
258         search_list_search(sl, &attr, 1);
259         while (res=search_list_get_result(sl)) {
260                 printf("country result\n");
261         }
262         attr.type=attr_town_name;
263         attr.u.str="U";
264         search_list_search(sl, &attr, 1);
265         while (res=search_list_get_result(sl)) {
266                 printf("town result\n");
267         }
268         search_list_destroy(sl);
269 #endif
270 }
271
272 static void
273 navit_show_roadbook(struct navigation *nav, void *data)
274 {
275         struct navigation_list *list;
276         char *str;
277         
278         list=navigation_list_new(nav);
279         while ((str=navigation_list_get(list, navigation_mode_long))) {
280                 printf("%s\n", str);
281         }
282         navigation_list_destroy(list);
283 }
284
285 void
286 navit_init(struct navit *this_)
287 {
288         struct menu *mapmen,*men,*men2;
289         struct map *map;
290         struct mapset_handle *handle;
291         struct mapset *ms=this_->mapsets->data;
292
293         if (this_->menubar) {
294                 mapmen=menu_add(this_->menubar, "Map", menu_type_submenu, NULL, NULL, NULL);
295                 // menu_add(map, "Test", menu_type_menu, NULL, NULL);
296                 men=menu_add(mapmen, "Layout", menu_type_submenu, NULL, NULL, NULL);
297                 menu_add(men, "Test", menu_type_menu, NULL, NULL, NULL);
298                 men=menu_add(mapmen, "Projection", menu_type_submenu, NULL, NULL, NULL);
299                 menu_add(men, "M&G", menu_type_menu, navit_projection_set, this_, (void *)projection_mg);
300                 menu_add(men, "Garmin", menu_type_menu, navit_projection_set, this_, (void *)projection_garmin);
301                 handle=mapset_open(ms);
302                 while ((map=mapset_next(handle,0))) {
303                         char *s=g_strdup_printf("%s:%s", map_get_type(map), map_get_filename(map));
304                         men2=menu_add(mapmen, s, menu_type_toggle, navit_map_toggle, this_, map);
305                         menu_set_toggle(men2, map_get_active(map));
306                         g_free(s);
307                 }
308                 mapset_close(handle);
309         }
310         {
311                 struct mapset *ms=this_->mapsets->data;
312                 struct coord c;
313                 int pos,flag=0;
314                 FILE *f;
315
316                 char buffer[2048];
317                 this_->route=route_new(ms);
318                 this_->navigation=navigation_new(ms);
319                 dbg(0,"navigation_register_callback(%p, ... %p)\n", this_->navigation, this_);
320                 navigation_register_callback(this_->navigation, navigation_mode_long, navit_show_roadbook, this_);
321 #if 1
322                 this_->track=track_new(ms);
323 #endif
324                 men=NULL;
325                 if (this_->menubar) {
326                         men=menu_add(this_->menubar, "Route", menu_type_submenu, NULL, NULL, NULL);
327                         men=menu_add(men, "Former Destinations", menu_type_submenu, NULL, NULL, NULL);
328                 }
329                 f=fopen("destination.txt", "r");
330                 if (f) {
331                         while (! feof(f) && fgets(buffer, 2048, f)) {
332                                 if ((pos=coord_parse(buffer, projection_mg, &c))) {
333                                         if (buffer[pos] && buffer[pos] != '\n' ) {
334                                                 struct coord *cn=g_new(struct coord, 1);
335                                                 *cn=c;
336                                                 buffer[strlen(buffer)-1]='\0';
337                                                 if (men)
338                                                         menu_add(men, buffer+pos+1, menu_type_menu, navit_set_destination_menu, this_, cn);
339                                         }
340                                         flag=1;
341                                 }
342                         }
343                         fclose(f);
344                         if (flag)
345                                 route_set_destination(this_->route, &c);
346                 }
347         }
348         global_navit=this_;
349         navit_debug(this_);
350 }
351
352 void
353 navit_set_center(struct navit *this_, struct coord *center)
354 {
355         struct coord *c=transform_center(this_->trans);
356         *c=*center;
357         if (this_->ready)
358                 navit_draw(this_);
359 }
360
361 static void
362 navit_set_center_cursor(struct navit *this_, struct coord *cursor, int dir, int xpercent, int ypercent)
363 {
364         struct coord *c=transform_center(this_->trans);
365         int width, height;
366         struct point p;
367         struct coord cnew;
368
369         transform_get_size(this_->trans, &width, &height);
370         *c=*cursor;
371         transform_set_angle(this_->trans, dir);
372         p.x=(100-xpercent)*width/100;
373         p.y=(100-ypercent)*height/100;
374         transform_reverse(this_->trans, &p, &cnew);
375         *c=cnew;
376         if (this_->ready)
377                 navit_draw(this_);
378                 
379 }
380
381
382 void
383 navit_set_center_screen(struct navit *this_, struct point *p)
384 {
385         struct coord c;
386         transform_reverse(this_->trans, p, &c);
387         navit_set_center(this_, &c);
388 }
389
390 void
391 navit_toggle_cursor(struct navit *this_)
392 {
393         this_->cursor_flag=1-this_->cursor_flag;
394 }
395
396 static void
397 navit_cursor_offscreen(struct cursor *cursor, void *this__p)
398 {
399         struct navit *this_=this__p;
400
401         if (this_->cursor_flag)
402                 navit_set_center(this_, cursor_pos_get(cursor));
403 }
404
405 static void
406 navit_cursor_update(struct cursor *cursor, void *this__p)
407 {
408         struct navit *this_=this__p;
409         struct coord *cursor_c=cursor_pos_get(cursor);
410         int dir=cursor_get_dir(cursor);
411
412         if (this_->track) {
413                 struct coord c=*cursor_c;
414                 if (track_update(this_->track, &c, dir)) {
415                         cursor_c=&c;
416                         cursor_pos_set(cursor, cursor_c);
417                         if (this_->route && this_->update_curr == 1)
418                                 route_set_position_from_track(this_->route, this_->track);
419                 }
420         } else {
421                 if (this_->route && this_->update_curr == 1)
422                         route_set_position(this_->route, cursor_c);
423         }
424         if (this_->route && this_->update_curr == 1)
425                 navigation_update(this_->navigation, this_->route);
426         if (this_->cursor_flag) {
427                 if (this_->follow_curr == 1)
428                         navit_set_center_cursor(this_, cursor_c, dir, 50, 80);
429         }
430         if (this_->follow_curr > 1)
431                 this_->follow_curr--;
432         else
433                 this_->follow_curr=this_->follow;
434         if (this_->update_curr > 1)
435                 this_->update_curr--;
436         else
437                 this_->update_curr=this_->update;
438 }
439
440 void
441 navit_set_position(struct navit *this_, struct coord *c)
442 {
443         if (this_->route) {
444                 route_set_position(this_->route, c);
445                 if (this_->navigation) {
446                         navigation_update(this_->navigation, this_->route);
447                 }
448         }
449         navit_draw(this_);
450 }
451
452 void
453 navit_vehicle_add(struct navit *this_, struct vehicle *v, struct color *c, int update, int follow)
454 {
455         this_->vehicle=v;
456         this_->update_curr=this_->update=update;
457         this_->follow_curr=this_->follow=follow;
458         this_->cursor=cursor_new(this_->gra, v, c, this_->trans);
459         cursor_register_offscreen_callback(this_->cursor, navit_cursor_offscreen, this_);
460         cursor_register_update_callback(this_->cursor, navit_cursor_update, this_);
461 }
462
463
464 struct gui *
465 navit_get_gui(struct navit *this_)
466 {
467         return this_->gui;
468 }
469
470 struct transformation *
471 navit_get_trans(struct navit *this_)
472 {
473         return this_->trans;
474 }
475
476 struct route *
477 navit_get_route(struct navit *this_)
478 {
479         return this_->route;
480 }
481
482 struct navigation *
483 navit_get_navigation(struct navit *this_)
484 {
485         return this_->navigation;
486 }
487
488 struct displaylist *
489 navit_get_displaylist(struct navit *this_)
490 {
491         return this_->displaylist;
492 }
493
494 void
495 navit_destroy(struct navit *this_)
496 {
497         g_free(this_);
498 }
499