/** * ZANavi, Zoff Android Navigation system. * Copyright (C) 2011-2012 Zoff * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ /** * Navit, a modular navigation system. * Copyright (C) 2005-2009 Navit Team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #define _USE_MATH_DEFINES 1 #include "config.h" #ifdef HAVE_UNISTD_H #include #endif #include #include #include #include #include #include #include #include #include "debug.h" #include "navit.h" #include "callback.h" #include "gui.h" #include "item.h" #include "projection.h" #include "map.h" #include "mapset.h" #include "main.h" #include "coord.h" #include "point.h" #include "transform.h" #include "param.h" #include "menu.h" #include "graphics.h" #include "popup.h" #include "data_window.h" #include "route.h" #include "navigation.h" #include "speech.h" #include "track.h" #include "vehicle.h" #include "layout.h" #include "log.h" #include "attr.h" #include "event.h" #include "file.h" #include "profile.h" #include "command.h" #include "navit_nls.h" #include "map.h" #include "util.h" #include "messages.h" #include "vehicleprofile.h" #include "sunriset.h" #include "bookmarks.h" #include "map.h" #ifdef HAVE_API_WIN32_BASE #include #include "util.h" #endif #ifdef HAVE_API_WIN32_CE #include "libc.h" #endif /** * @defgroup navit the navit core instance. navit is the object containing nearly everything: A set of maps, one or more vehicle, a graphics object for rendering the map, a gui object for displaying the user interface, a route object, a navigation object and so on. Be warned that it is theoretically possible to have more than one navit object * @{ */ struct gui *main_loop_gui; struct attr_iter { union { GList *list; struct mapset_handle *mapset_handle; } u; }; static void navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv); static void navit_vehicle_draw(struct navit *this_, struct navit_vehicle *nv, struct point *pnt); static int navit_set_attr_do(struct navit *this_, struct attr *attr, int init); static int navit_get_cursor_pnt(struct navit *this_, struct point *p, int keep_orientation, int *dir); static void navit_cmd_zoom_to_route(struct navit *this); static void navit_cmd_set_center_cursor(struct navit *this_); static void navit_cmd_announcer_toggle(struct navit *this_); static void navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv); int allow_gui_internal = 0; int routing_mode = 0; int MYSTERY_SPEED = 2; int offline_search_filter_duplicates = 0; int offline_search_break_searching = 0; char *navit_maps_dir; int cancel_drawing_global = 0; int global_speak_streetnames = 1; int allow_large_mapfiles = 1; // allow the use of large (>2GB) mapfiles // -> value unused for now int cache_size_file = 1024 * 1024 * 10; // default value was: 20971520 (~20 MB) int draw_polylines_fast = 0; // default: 0 int limit_order_corrected = 4; // remain at this order level for drawing streets etc. int global_search_street_size_factor = 1; // make search radius for streets bigger void navit_add_mapset(struct navit *this_, struct mapset *ms) { ////DBG dbg(0,"EEnter\n"); this_->mapsets = g_list_append(this_->mapsets, ms); } struct mapset * navit_get_mapset(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); if (this_->mapsets) { return this_->mapsets->data; } else { //DBG dbg(0,"No mapsets enabled! Is it on purpose? Navit can't draw a map. Please check your navit.xml\n"); } return NULL; } struct tracking * navit_get_tracking(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); return this_->tracking; } /** * @brief Get the user data directory. * @param[in] create - create the directory if it does not exist * * @return char * to the data directory string. * * returns the directory used to store user data files (center.txt, * destination.txt, bookmark.txt, ...) * */ char* navit_get_user_data_directory(int create) { ////DBG dbg(0,"EEnter\n"); char *dir; dir = getenv("NAVIT_USER_DATADIR"); if (create && !file_exists(dir)) { //DBG dbg(0, "creating dir %s\n", dir); if (file_mkdir(dir, 0)) { //DBG dbg(0, "failed creating dir %s\n", dir); return NULL; } } return dir; } /* end: navit_get_user_data_directory(gboolean create) */ void navit_draw_async(struct navit *this_, int async) { //DBG dbg(0,"EEnter this_->blocked=%d\n",this_->blocked); if (this_->blocked) { this_->blocked |= 2; ////DBG dbg(0,"set this_->blocked=%d\n",this_->blocked); return; } transform_setup_source_rect(this_->trans); graphics_draw(this_->gra, this_->displaylist, this_->mapsets->data, this_->trans, this_->layout_current, async, NULL, this_->graphics_flags | 1); } void navit_draw(struct navit *this_) { ////DBG dbg(0,"EEnter this_->ready=%d\n",this_->ready); if (this_->ready == 3) { ////DBG dbg(0,"navit_draw_async_001\n"); navit_draw_async(this_, 0); } } int navit_get_ready(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); return this_->ready; } void navit_draw_displaylist(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); if (this_->ready == 3) { // //DBG dbg(0,"call graphics_displaylist_draw 2") graphics_displaylist_draw(this_->gra, this_->displaylist, this_->trans, this_->layout_current, this_->graphics_flags | 1); } } static void navit_map_progress(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); struct map *map; struct mapset *ms; struct mapset_handle *msh; struct attr attr; struct point p; if (this_->ready != 3) return; p.x = 10; p.y = 32; ms = this_->mapsets->data; msh = mapset_open(ms); while (msh && (map = mapset_next(msh, 0))) { if (map_get_attr(map, attr_progress, &attr, NULL)) { char *str = g_strdup_printf("%s ", attr.u.str); graphics_draw_mode(this_->gra, draw_mode_begin); graphics_draw_text_std(this_->gra, 16, str, &p); g_free(str); p.y += 32; graphics_draw_mode(this_->gra, draw_mode_end); } } mapset_close(msh); } static void navit_redraw_route(struct navit *this_, struct route *route, struct attr *attr) { ////DBG dbg(0,"EEnter\n"); int updated; if ((this_->route) && (this_->route->route_status_was_updated == 1)) { this_->route->route_status_was_updated = 0; // send route_status to java #ifdef HAVE_API_ANDROID android_return_generic_int(1, this_->route->route_status); #endif } if (attr->type != attr_route_status) { ////DBG dbg(0,"ret 1\n"); return; } updated = attr->u.num; ////DBG dbg(0,"updated=%d\n", updated); if (this_->ready != 3) { ////DBG dbg(0,"ret 2\n"); return; } if (updated != route_status_path_done_new) { ////DBG dbg(0,"ret 3\n"); return; } if (this_->vehicle) { if (this_->vehicle->follow_curr == 1) { ////DBG dbg(0,"ret 4\n"); ////DBG dbg(0,"disabled -> we want redraw!!\n"); // return; } if (this_->vehicle->follow_curr <= this_->vehicle->follow) { this_->vehicle->follow_curr = this_->vehicle->follow; } } ////DBG dbg(0,"draw s*\n"); navit_draw(this_); ////DBG dbg(0,"draw e*\n"); } void navit_handle_resize(struct navit *this_, int w, int h) { //DBG dbg(0,"EEnter\n"); struct map_selection sel; int callback = (this_->ready == 1); ////DBG dbg(0,"pre this_->ready=%d\n",this_->ready); this_->ready |= 2; ////DBG dbg(0,"set this_->ready=%d\n",this_->ready); memset(&sel, 0, sizeof(sel)); this_->w = w; this_->h = h; sel.u.p_rect.rl.x = w; sel.u.p_rect.rl.y = h; transform_set_screen_selection(this_->trans, &sel); graphics_init(this_->gra); graphics_set_rect(this_->gra, &sel.u.p_rect); if (callback) { //DBG dbg(0,"callback do\n"); callback_list_call_attr_1(this_->attr_cbl, attr_graphics_ready, this_); } if (this_->ready == 3) { //DBG dbg(0,"navit_draw_async_002\n"); navit_draw_async(this_, 1); } } void navit_resize(void *data, int w, int h) { //DBG dbg(0,"EEnter %p\n", data); struct navit *this = data; if (!this->ignore_graphics_events) { //DBG dbg(0,"11\n"); navit_handle_resize(this, w, h); } } int navit_get_width(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); return this_->w; } int navit_get_height(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); return this_->h; } static void navit_popup(void *data) { ////DBG dbg(0,"EEnter\n"); struct navit *this_ = data; popup(this_, 1, &this_->pressed); this_->button_timeout = NULL; this_->popped = 1; } int navit_ignore_button(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); if (this_->ignore_button) return 1; this_->ignore_button = 1; return 0; } void navit_ignore_graphics_events(struct navit *this_, int ignore) { ////DBG dbg(0,"EEnter\n"); this_->ignore_graphics_events = ignore; } static void update_transformation(struct transformation *tr, struct point *old, struct point *new, struct point *rot) { ////DBG dbg(0,"EEnter\n"); struct coord co, cn; struct coord c, *cp; int yaw; double angleo, anglen; if (!transform_reverse(tr, old, &co)) return; if (rot) { angleo = atan2(old->y - rot->y, old->x - rot->x) * 180 / M_PI; anglen = atan2(new->y - rot->y, new->x - rot->x) * 180 / M_PI; yaw = transform_get_yaw(tr) + angleo - anglen; transform_set_yaw(tr, yaw % 360); } if (!transform_reverse(tr, new, &cn)) return; cp = transform_get_center(tr); c.x = cp->x + co.x - cn.x; c.y = cp->y + co.y - cn.y; // dbg(1, "from 0x%x,0x%x to 0x%x,0x%x\n", cp->x, cp->y, c.x, c.y); transform_set_center(tr, &c); } void navit_set_timeout(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); struct attr follow; follow.type = attr_follow; follow.u.num = this_->center_timeout; navit_set_attr(this_, &follow); } int navit_handle_button(struct navit *this_, int pressed, int button, struct point *p, struct callback *popup_callback) { ////DBG dbg(0,"EEnter\n"); int border = 16; // dbg(1, "enter %d %d (ignore %d)\n", pressed, button, this_->ignore_button); callback_list_call_attr_4(this_->attr_cbl, attr_button, this_, GINT_TO_POINTER(pressed), GINT_TO_POINTER(button), p); if (this_->ignore_button) { this_->ignore_button = 0; return 0; } if (pressed) { this_->pressed = *p; this_->last = *p; this_->zoomed = 0; if (button == 1) { this_->button_pressed = 1; this_->moved = 0; this_->popped = 0; if (popup_callback) this_->button_timeout = event_add_timeout(500, 0, popup_callback); } if (button == 2) navit_set_center_screen(this_, p, 1); if (button == 3) popup(this_, button, p); if (button == 4 && this_->use_mousewheel) { this_->zoomed = 1; navit_zoom_in(this_, 2, p); } if (button == 5 && this_->use_mousewheel) { this_->zoomed = 1; navit_zoom_out(this_, 2, p); } } else { this_->button_pressed = 0; if (this_->button_timeout) { event_remove_timeout(this_->button_timeout); this_->button_timeout = NULL; if (!this_->moved && !transform_within_border(this_->trans, p, border)) { navit_set_center_screen(this_, p, !this_->zoomed); } } if (this_->motion_timeout) { event_remove_timeout(this_->motion_timeout); this_->motion_timeout = NULL; } if (this_->moved) { struct point pr; pr.x = this_->w / 2; pr.y = this_->h; #if 0 update_transformation(this_->trans, &this_->pressed, p, &pr); #else update_transformation(this_->trans, &this_->pressed, p, NULL); #endif graphics_draw_drag(this_->gra, NULL); transform_copy(this_->trans, this_->trans_cursor); graphics_overlay_disable(this_->gra, 0); if (!this_->zoomed) navit_set_timeout(this_); navit_draw(this_); } else return 1; } return 0; } static void navit_button(void *data, int pressed, int button, struct point *p) { ////DBG dbg(0,"EEnter\n"); struct navit *this = data; // dbg(1, "enter %d %d ignore %d\n", pressed, button, this->ignore_graphics_events); if (!this->ignore_graphics_events) { if (!this->popup_callback) this->popup_callback = callback_new_1(callback_cast(navit_popup), this); navit_handle_button(this, pressed, button, p, this->popup_callback); } } static void navit_motion_timeout(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); int dx, dy; if (this_->drag_bitmap) { struct point point; point.x = (this_->current.x - this_->pressed.x); point.y = (this_->current.y - this_->pressed.y); if (graphics_draw_drag(this_->gra, &point)) { graphics_overlay_disable(this_->gra, 1); graphics_draw_mode(this_->gra, draw_mode_end); this_->moved = 1; this_->motion_timeout = NULL; return; } } dx = (this_->current.x - this_->last.x); dy = (this_->current.y - this_->last.y); if (dx || dy) { struct transformation *tr; struct point pr; this_->last = this_->current; graphics_overlay_disable(this_->gra, 1); tr = transform_dup(this_->trans); pr.x = this_->w / 2; pr.y = this_->h; #if 0 update_transformation(tr, &this_->pressed, &this_->current, &pr); #else update_transformation(tr, &this_->pressed, &this_->current, NULL); #endif #if 0 graphics_displaylist_move(this_->displaylist, dx, dy); #endif graphics_draw_cancel(this_->gra, this_->displaylist); // //DBG dbg(0,"call graphics_displaylist_draw 1") graphics_displaylist_draw(this_->gra, this_->displaylist, tr, this_->layout_current, this_->graphics_flags); transform_destroy(tr); this_->moved = 1; } this_->motion_timeout = NULL; return; } void navit_handle_motion(struct navit *this_, struct point *p) { ////DBG dbg(0,"EEnter\n"); int dx, dy; if (this_->button_pressed && !this_->popped) { dx = (p->x - this_->pressed.x); dy = (p->y - this_->pressed.y); if (dx < -8 || dx > 8 || dy < -8 || dy > 8) { this_->moved = 1; if (this_->button_timeout) { event_remove_timeout(this_->button_timeout); this_->button_timeout = NULL; } this_->current = *p; if (!this_->motion_timeout_callback) this_->motion_timeout_callback = callback_new_1(callback_cast(navit_motion_timeout), this_); if (!this_->motion_timeout) this_->motion_timeout = event_add_timeout(100, 0, this_->motion_timeout_callback); } } } static void navit_motion(void *data, struct point *p) { ////DBG dbg(0,"EEnter\n"); struct navit *this = data; if (!this->ignore_graphics_events) navit_handle_motion(this, p); } static void navit_predraw(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); GList *l; struct navit_vehicle *nv; transform_copy(this_->trans, this_->trans_cursor); l = this_->vehicles; while (l) { nv = l->data; ////DBG dbg(0,"* here *\n"); ////DBG dbg(0,"vehicle_draw_004\n"); navit_vehicle_draw(this_, nv, NULL); l = g_list_next(l); } } static void navit_scale(struct navit *this_, long scale, struct point *p, int draw) { //DBG dbg(0,"EEnter\n"); struct coord c1, c2, *center; if (scale < this_->zoom_min) { scale = this_->zoom_min; } if (scale > this_->zoom_max) { scale = this_->zoom_max; } // return scale value to android #ifdef HAVE_API_ANDROID android_return_generic_int(3, (int)scale); #endif if (p) { transform_reverse(this_->trans, p, &c1); } transform_set_scale(this_->trans, scale); if (p) { transform_reverse(this_->trans, p, &c2); center = transform_center(this_->trans); center->x += c1.x - c2.x; center->y += c1.y - c2.y; } //DBG dbg(0,"aa331\n"); if (draw) { navit_draw(this_); } //DBG dbg(0,"leave\n"); } /** * @brief Automatically adjusts zoom level * * This function automatically adjusts the current * zoom level according to the current speed. * * @param this_ The navit struct * @param center The "immovable" point - i.e. the vehicles position if we're centering on the vehicle * @param speed The vehicles speed in meters per second * @param dir The direction into which the vehicle moves */ static void navit_autozoom(struct navit *this_, struct coord *center, int speed, int draw) { struct point pc; int distance, w, h; double new_scale; long scale; if (!this_->autozoom_active) { return; } distance = speed * this_->autozoom_secs; transform_get_size(this_->trans, &w, &h); transform(this_->trans, transform_get_projection(this_->trans), center, &pc, 1, 0, 0, NULL); scale = transform_get_scale(this_->trans); /* We make sure that the point we want to see is within a certain range * around the vehicle. The radius of this circle is the size of the * screen. This doesn't necessarily mean the point is visible because of * perspective etc. Quite rough, but should be enough. */ if (w > h) { new_scale = (double) distance / h * 16; } else { new_scale = (double) distance / w * 16; } if (abs(new_scale - scale) < 2) { return; // Smoothing } if (new_scale >= this_->autozoom_min) { navit_scale(this_, (long) new_scale, &pc, 0); } else { if (scale != this_->autozoom_min) { navit_scale(this_, this_->autozoom_min, &pc, 0); } } } /** * Change the current zoom level, zooming closer to the ground * * @param navit The navit instance * @param factor The zoom factor, usually 2 * @param p The invariant point (if set to NULL, default to center) * @returns nothing */ void navit_zoom_in(struct navit *this_, int factor, struct point *p) { ////DBG dbg(0,"EEnter\n"); long scale = transform_get_scale(this_->trans) / factor; if (scale < 1) scale = 1; ////DBG dbg(0,"zoom in -> scale=%d",scale); navit_scale(this_, scale, p, 1); } /** * Change the current zoom level * * @param navit The navit instance * @param factor The zoom factor, usually 2 * @param p The invariant point (if set to NULL, default to center) * @returns nothing */ void navit_zoom_out(struct navit *this_, int factor, struct point *p) { ////DBG dbg(0,"EEnter\n"); long scale = transform_get_scale(this_->trans) * factor; ////DBG dbg(0,"zoom out -> scale=%d",scale); navit_scale(this_, scale, p, 1); } int navit_get_cur_pnt(struct navit *this_, struct point *p) { ////DBG dbg(0,"EEnter\n"); return navit_get_cursor_pnt(this_, p, 0, NULL); } void navit_zoom_in_cursor(struct navit *this_, int factor) { ////DBG dbg(0,"EEnter\n"); struct point p; if (this_->vehicle && this_->vehicle->follow_curr <= 1 && navit_get_cursor_pnt(this_, &p, 0, NULL)) { navit_zoom_in(this_, factor, &p); this_->vehicle->follow_curr = this_->vehicle->follow; } else navit_zoom_in(this_, factor, NULL); } void navit_zoom_to_scale(struct navit *this_, int new_scale) { //DBG dbg(0,"EEnter\n"); long scale = transform_get_scale(this_->trans); long new_scale_long = new_scale; //DBG dbg(0,"zoom to scale -> old scale=%d",scale); //DBG dbg(0,"zoom to scale -> want scale=%d",new_scale_long); // only do something if scale changed! if (scale != new_scale_long) { navit_scale(this_, new_scale_long, NULL, 1); } } void navit_zoom_out_cursor(struct navit *this_, int factor) { ////DBG dbg(0,"EEnter\n"); struct point p; if (this_->vehicle && this_->vehicle->follow_curr <= 1 && navit_get_cursor_pnt(this_, &p, 0, NULL)) { navit_zoom_out(this_, 2, &p); this_->vehicle->follow_curr = this_->vehicle->follow; } else navit_zoom_out(this_, 2, NULL); } static int navit_cmd_zoom_in(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); navit_zoom_in_cursor(this_, 2); return 0; } static int navit_cmd_zoom_out(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); navit_zoom_out_cursor(this_, 2); return 0; } static void navit_cmd_say(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) { navit_say(this, in[0]->u.str); } } static GHashTable *cmd_int_var_hash = NULL; static GHashTable *cmd_attr_var_hash = NULL; /** * Store key value pair for the command system (for int typed values) * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attributes in[0] is the key string, in[1] is the integer value to store * @param out output attributes, unused * @param valid unused * @returns nothing */ static void navit_cmd_set_int_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); char*key; struct attr*val; if (!cmd_int_var_hash) { cmd_int_var_hash = g_hash_table_new(g_str_hash, g_str_equal); } if ((in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) && (in && in[1] && ATTR_IS_NUMERIC(in[1]->type))) { val = g_new(struct attr,1); attr_dup_content(in[1], val); key = g_strdup(in[0]->u.str); g_hash_table_insert(cmd_int_var_hash, key, val); } } /** * Store key value pair for the command system (for attr typed values, can be used as opaque handles) * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attributes in[0] is the key string, in[1] is the attr* value to store * @param out output attributes, unused * @param valid unused * @returns nothing */ //TODO free stored attributes on navit_destroy static void navit_cmd_set_attr_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); char*key; struct attr*val; if (!cmd_attr_var_hash) { cmd_attr_var_hash = g_hash_table_new(g_str_hash, g_str_equal); } if ((in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) && (in && in[1])) { val = attr_dup(in[1]); //val = in[1]; key = g_strdup(in[0]->u.str); g_hash_table_insert(cmd_attr_var_hash, key, val); } } /** * command to toggle the active state of a named layer of the current layout * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attribute in[0] is the name of the layer * @param out output unused * @param valid unused * @returns nothing */ static void navit_cmd_toggle_layer(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) { if (this->layout_current && this->layout_current->layers) { GList* layers = this->layout_current->layers; while (layers) { struct layer*l = layers->data; if (l && !strcmp(l->name, in[0]->u.str)) { l->active ^= 1; navit_draw(this); return; } layers = g_list_next(layers); } } } } /** * adds an item with the current coordinate of the vehicle to a named map * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attribute in[0] is the name of the map * @param out output attribute, 0 on error or the id of the created item on success * @param valid unused * @returns nothing */ static void navit_cmd_map_add_curr_pos(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); struct attr **list = g_new0(struct attr *,2); struct attr*val = g_new0(struct attr,1); struct mapset* ms; struct map_selection sel; const int selection_range = 10; enum item_type item_type; struct item *it; struct map* curr_map = NULL; struct coord curr_coord; struct map_rect *mr; val->type = attr_type_item_begin; val->u.item = NULL; //return invalid item on error list[0] = val; list[1] = NULL; *out = list; if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str && //map name in[1] && ATTR_IS_STRING(in[1]->type) && in[1]->u.str //item type ) { if (!(ms = navit_get_mapset(this))) { return; } if ((item_type = item_from_name(in[1]->u.str)) == type_none) { return; } curr_map = mapset_get_map_by_name(ms, in[0]->u.str); //no map with the given name found if (!curr_map) { return; } if (this->vehicle && this->vehicle->vehicle) { struct attr pos_attr; if (vehicle_get_attr(this->vehicle->vehicle, attr_position_coord_geo, &pos_attr, NULL)) { transform_from_geo(projection_mg, pos_attr.u.coord_geo, &curr_coord); } else { return; } } else { return; } sel.next = NULL; sel.order = 18; sel.range.min = type_none; sel.range.max = type_tec_common; sel.u.c_rect.lu.x = curr_coord.x - selection_range; sel.u.c_rect.lu.y = curr_coord.y + selection_range; sel.u.c_rect.rl.x = curr_coord.x + selection_range; sel.u.c_rect.rl.y = curr_coord.y - selection_range; mr = map_rect_new(curr_map, &sel); if (mr) { it = map_rect_create_item(mr, item_type); item_coord_set(it, &curr_coord, 1, change_mode_modify); val->u.item = it; } map_rect_destroy(mr); } } /** * sets an attribute (name value pair) of a map item specified by map name and item id * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attribute in[0] - name of the map ; in[1] - item ; in[2] - attr name ; in[3] - attr value * @param out output attribute, 0 on error, 1 on success * @param valid unused * @returns nothing */ static void navit_cmd_map_item_set_attr(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str && //map name in[1] && ATTR_IS_ITEM(in[1]->type) && //item in[2] && ATTR_IS_STRING(in[2]->type) && in[2]->u.str && //attr_type str in[3] && ATTR_IS_STRING(in[3]->type) && in[3]->u.str //attr_value str ) { struct attr attr_to_set; struct map* curr_map = NULL; struct mapset *ms; struct map_selection sel; const int selection_range = 500; struct coord curr_coord; struct item *it; if (ATTR_IS_STRING(attr_from_name(in[2]->u.str))) { attr_to_set.u.str = in[3]->u.str; attr_to_set.type = attr_from_name(in[2]->u.str); } else if (ATTR_IS_INT(attr_from_name(in[2]->u.str))) { attr_to_set.u.num = atoi(in[3]->u.str); attr_to_set.type = attr_from_name(in[2]->u.str); } else if (ATTR_IS_DOUBLE(attr_from_name(in[2]->u.str))) { double* val = g_new0(double,1); *val = atof(in[3]->u.str); attr_to_set.u.numd = val; attr_to_set.type = attr_from_name(in[2]->u.str); } ms = navit_get_mapset(this); curr_map = mapset_get_map_by_name(ms, in[0]->u.str); if (!curr_map) { return; } sel.next = NULL; sel.order = 18; sel.range.min = type_none; sel.range.max = type_tec_common; sel.u.c_rect.lu.x = curr_coord.x - selection_range; sel.u.c_rect.lu.y = curr_coord.y + selection_range; sel.u.c_rect.rl.x = curr_coord.x + selection_range; sel.u.c_rect.rl.y = curr_coord.y - selection_range; it = in[1]->u.item; if (it) { item_attr_set(it, &attr_to_set, change_mode_modify); } } } /** * Get attr variable given a key string for the command system (for opaque usage) * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attribute in[0] is the key string * @param out output attribute, the attr for the given key string if exists or NULL * @param valid unused * @returns nothing */ static void navit_cmd_get_attr_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); struct attr **list = g_new0(struct attr *,2); if (!cmd_int_var_hash) { struct attr*val = g_new0(struct attr,1); val->type = attr_type_item_begin; val->u.item = NULL; list[0] = val; } if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) { struct attr*ret = g_hash_table_lookup(cmd_attr_var_hash, in[0]->u.str); if (ret) { list[0] = attr_dup(ret); } else { struct attr*val = g_new0(struct attr,1); val->type = attr_type_int_begin; val->u.item = NULL; list[0] = val; } } list[1] = NULL; *out = list; } /** * Get value given a key string for the command system * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attribute in[0] is the key string * @param out output attribute, the value for the given key string if exists or 0 * @param valid unused * @returns nothing */ static void navit_cmd_get_int_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); struct attr **list = g_new0(struct attr *,2); if (!cmd_int_var_hash) { struct attr*val = g_new0(struct attr,1); val->type = attr_type_int_begin; val->u.num = 0; list[0] = val; } if (in && in[0] && ATTR_IS_STRING(in[0]->type) && in[0]->u.str) { struct attr*ret = g_hash_table_lookup(cmd_int_var_hash, in[0]->u.str); if (ret) { list[0] = ret; } else { struct attr*val = g_new0(struct attr,1); val->type = attr_type_int_begin; val->u.num = 0; list[0] = val; } } list[1] = NULL; *out = list; } GList *cmd_int_var_stack = NULL; /** * Push an integer to the stack for the command system * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attribute in[0] is the integer attibute to push * @param out output attributes, unused * @param valid unused * @returns nothing */ static void navit_cmd_push_int(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); if (in && in[0] && ATTR_IS_NUMERIC(in[0]->type)) { struct attr*val = g_new(struct attr,1); attr_dup_content(in[0], val); cmd_int_var_stack = g_list_prepend(cmd_int_var_stack, val); } } /** * Pop an integer from the command system's integer stack * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attributes unused * @param out output attribute, the value popped if stack isn't empty or 0 * @param valid unused * @returns nothing */ static void navit_cmd_pop_int(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); struct attr **list = g_new0(struct attr *,2); if (!cmd_int_var_stack) { struct attr*val = g_new0(struct attr,1); val->type = attr_type_int_begin; val->u.num = 0; list[0] = val; } else { list[0] = cmd_int_var_stack->data; cmd_int_var_stack = g_list_remove_link(cmd_int_var_stack, cmd_int_var_stack); } list[1] = NULL; *out = list; } /** * Get current size of command system's integer stack * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attributes unused * @param out output attribute, the size of stack * @param valid unused * @returns nothing */ static void navit_cmd_int_stack_size(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); struct attr **list; struct attr *attr = g_new0(struct attr ,1); attr->type = attr_type_int_begin; if (!cmd_int_var_stack) { attr->u.num = 0; } else { attr->u.num = g_list_length(cmd_int_var_stack); }list = g_new0(struct attr *,2); list[0] = attr; list[1] = NULL; *out = list; cmd_int_var_stack = g_list_remove_link(cmd_int_var_stack, cmd_int_var_stack); } static void navit_cmd_set_destination(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); struct pcoord pc; char *description = NULL; if (!in) return; if (!in[0]) return; pc.pro = transform_get_projection(this->trans); if (ATTR_IS_COORD(in[0]->type)) { pc.x = in[0]->u.coord->x; pc.y = in[0]->u.coord->y; in++; } else if (ATTR_IS_PCOORD(in[0]->type)) { pc = *in[0]->u.pcoord; in++; } else if (in[1] && in[2] && ATTR_IS_INT(in[0]->type) && ATTR_IS_INT(in[1]->type) && ATTR_IS_INT(in[2]->type)) { pc.pro = in[0]->u.num; pc.x = in[1]->u.num; pc.y = in[2]->u.num; in += 3; } else if (in[1] && ATTR_IS_INT(in[0]->type) && ATTR_IS_INT(in[1]->type)) { pc.x = in[0]->u.num; pc.y = in[1]->u.num; in += 2; } else { return; } if (in[0] && ATTR_IS_STRING(in[0]->type)) { description = in[0]->u.str; } navit_set_destination(this, &pc, description, 1); } static void navit_cmd_fmt_coordinates(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); struct attr attr; attr.type = attr_type_string_begin; attr.u.str = "Fix me"; if (out) { *out = attr_generic_add_attr(*out, &attr); } } /** * Join several string attributes into one * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attributes in[0] - separator, in[1..] - attributes to join * @param out output attribute joined attribute as string * @param valid unused * @returns nothing */ static void navit_cmd_strjoin(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); struct attr attr; gchar *ret, *sep; int i; attr.type = attr_type_string_begin; attr.u.str = NULL; if (in[0] && in[1]) { sep = attr_to_text(in[0], NULL, 1); ret = attr_to_text(in[1], NULL, 1); for (i = 2; in[i]; i++) { gchar *in_i = attr_to_text(in[i], NULL, 1); gchar *r = g_strjoin(sep, ret, in_i, NULL); g_free(in_i); g_free(ret); ret = r; } g_free(sep); attr.u.str = ret; if (out) { *out = attr_generic_add_attr(*out, &attr); } g_free(ret); } } /** * Call external program * * @param navit The navit instance * @param function unused (needed to match command function signiture) * @param in input attributes in[0] - name of executable, in[1..] - parameters * @param out output attribute unused * @param valid unused * @returns nothing */ static void navit_cmd_spawn(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid) { ////DBG dbg(0,"EEnter\n"); int i, j, nparms, nvalid; const char ** argv = NULL; struct spawn_process_info *pi; nparms = 0; nvalid = 0; if (in) { while (in[nparms]) { if (in[nparms]->type != attr_none) nvalid++; nparms++; } } if (nvalid > 0) { argv=g_new(char*,nvalid+1); for (i = 0, j = 0; in[i]; i++) { if (in[i]->type != attr_none) { argv[j++] = attr_to_text(in[i], NULL, 1); } else { //DBG dbg(0, "Parameter #%i is attr_none - skipping\n", i); } } argv[j] = NULL; pi = spawn_process(argv); // spawn_process() testing suite - uncomment following code to test. //sleep(3); // example of non-blocking wait //int st=spawn_process_check_status(pi,0);//DBG dbg(0,"status %i\n",st); // example of blocking wait //st=spawn_process_check_status(pi,1);//DBG dbg(0,"status %i\n",st); // example of wait after process is finished and status is // already tested //st=spawn_process_check_status(pi,1);//DBG dbg(0,"status %i\n",st); // example of wait after process is finished and status is // already tested - unblocked //st=spawn_process_check_status(pi,0);//DBG dbg(0,"status %i\n",st); // End testing suite spawn_process_info_free(pi); for (i = 0; argv[i]; i++) g_free(argv[i]); g_free(argv); } } static struct command_table commands[] = { { "zoom_in", command_cast(navit_cmd_zoom_in) }, { "zoom_out", command_cast(navit_cmd_zoom_out) }, { "zoom_to_route", command_cast(navit_cmd_zoom_to_route) }, { "say", command_cast(navit_cmd_say) }, { "set_center_cursor", command_cast(navit_cmd_set_center_cursor) }, { "set_destination", command_cast(navit_cmd_set_destination) }, { "announcer_toggle", command_cast(navit_cmd_announcer_toggle) }, { "fmt_coordinates", command_cast(navit_cmd_fmt_coordinates) }, { "set_int_var", command_cast(navit_cmd_set_int_var) }, { "get_int_var", command_cast(navit_cmd_get_int_var) }, { "push_int", command_cast(navit_cmd_push_int) }, { "pop_int", command_cast(navit_cmd_pop_int) }, { "int_stack_size", command_cast(navit_cmd_int_stack_size) }, { "toggle_layer", command_cast(navit_cmd_toggle_layer) }, { "strjoin", command_cast(navit_cmd_strjoin) }, { "spawn", command_cast(navit_cmd_spawn) }, { "map_add_curr_pos", command_cast(navit_cmd_map_add_curr_pos) }, { "map_item_set_attr", command_cast(navit_cmd_map_item_set_attr) }, { "set_attr_var", command_cast(navit_cmd_set_attr_var) }, { "get_attr_var", command_cast(navit_cmd_get_attr_var) }, }; void navit_command_add_table(struct navit*this_, struct command_table *commands, int count) { ////DBG dbg(0,"EEnter\n"); command_add_table(this_->attr_cbl, commands, count, this_); } struct navit * navit_new(struct attr *parent, struct attr **attrs) { ////DBG dbg(0,"EEnter\n"); struct navit *this_=g_new0(struct navit, 1); struct pcoord center; struct coord co; struct coord_geo g; enum projection pro = projection_mg; int zoom = 256; g.lat = 53.13; g.lng = 11.70; this_->self.type = attr_navit; this_->self.u.navit = this_; this_->attr_cbl = callback_list_new(); this_->orientation = -1; this_->tracking_flag = 1; this_->recentdest_count = 10; this_->osd_configuration = -1; // changed default to 1 this_->center_timeout = 1; this_->use_mousewheel = 1; this_->autozoom_secs = 10; this_->autozoom_min = 7; this_->autozoom_active = 0; this_->zoom_min = 1; this_->zoom_max = 1048576; //-> order=-2 // 2097152 -> order=-3; this_->follow_cursor = 1; this_->radius = 30; this_->border = 16; this_->trans = transform_new(); this_->trans_cursor = transform_new(); transform_from_geo(pro, &g, &co); center.x = co.x; center.y = co.y; center.pro = pro; //DBG dbg(0, "setting center from xmlfile [hardcoded]\n"); transform_setup(this_->trans, ¢er, zoom, (this_->orientation != -1) ? this_->orientation : 0); // initialze trans_cursor here transform_copy(this_->trans, this_->trans_cursor); // initialze trans_cursor here this_->bookmarks = bookmarks_new(&this_->self, NULL, this_->trans); this_->prevTs = 0; for (; *attrs; attrs++) { navit_set_attr_do(this_, *attrs, 1); } this_->displaylist = graphics_displaylist_new(); command_add_table(this_->attr_cbl, commands, sizeof(commands) / sizeof(struct command_table), this_); // this_->messages = messagelist_new(attrs); ////DBG dbg(0,"111111\n"); return this_; } static int navit_set_gui(struct navit *this_, struct gui *gui) { ////DBG dbg(0,"EEnter\n"); if (this_->gui) return 0; this_->gui = gui; if (gui_has_main_loop(this_->gui)) { if (!main_loop_gui) { main_loop_gui = this_->gui; } else { //DBG dbg(0, "gui with main loop already active, ignoring this instance"); return 0; } } return 1; } void navit_add_message(struct navit *this_, char *message) { ////DBG dbg(0,"EEnter\n"); // message_new(this_->messages, message); } struct message *navit_get_messages(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); // return message_get(this_->messages); } static int navit_set_graphics(struct navit *this_, struct graphics *gra) { ////DBG dbg(0,"EEnter\n"); if (this_->gra) return 0; this_->gra = gra; this_->resize_callback = callback_new_attr_1(callback_cast(navit_resize), attr_resize, this_); graphics_add_callback(gra, this_->resize_callback); this_->button_callback = callback_new_attr_1(callback_cast(navit_button), attr_button, this_); graphics_add_callback(gra, this_->button_callback); this_->motion_callback = callback_new_attr_1(callback_cast(navit_motion), attr_motion, this_); graphics_add_callback(gra, this_->motion_callback); this_->predraw_callback = callback_new_attr_1(callback_cast(navit_predraw), attr_predraw, this_); graphics_add_callback(gra, this_->predraw_callback); ////DBG dbg(0,"111111111\n"); return 1; } struct graphics * navit_get_graphics(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); return this_->gra; } struct vehicleprofile * navit_get_vehicleprofile(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); return this_->vehicleprofile; } GList * navit_get_vehicleprofiles(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); return this_->vehicleprofiles; } static void navit_projection_set(struct navit *this_, enum projection pro, int draw) { ////DBG dbg(0,"EEnter\n"); struct coord_geo g; struct coord *c; c = transform_center(this_->trans); transform_to_geo(transform_get_projection(this_->trans), c, &g); transform_set_projection(this_->trans, pro); transform_from_geo(pro, &g, c); if (draw) navit_draw(this_); } /** * Start the route computing to a given set of coordinates * * @param navit The navit instance * @param c The coordinate to start routing to * @param description A label which allows the user to later identify this destination in the former destinations selection * @returns nothing */ void navit_set_destination(struct navit *this_, struct pcoord *c, const char *description, int async) { ////DBG dbg(0,"EEnter\n"); char *destination_file; if (c) { this_->destination = *c; this_->destination_valid = 1; //dbg(0, "navit->navit_set_destination %i\n", c->x); //dbg(0, "navit->navit_set_destination %i\n", c->y); } else { this_->destination_valid = 0; } //destination_file = bookmarks_get_destination_file(TRUE); //bookmarks_append_coord(this_->bookmarks, destination_file, c, 1, "former_destination", description, NULL, this_->recentdest_count); //g_free(destination_file); callback_list_call_attr_0(this_->attr_cbl, attr_destination); if (this_->route) { //dbg(0, "navit->navit_set_destination 2: %i %i\n", c->x, c->y); route_set_destination(this_->route, c, async); if (this_->ready == 3) { navit_draw(this_); } } } /** * add a waypoint to an active route * * @param navit The navit instance * @param c The coordinate of the waypoint * @param description A dummy string * @returns nothing */ void navit_add_waypoint_to_route(struct navit *this_, struct pcoord *c, const char *description, int async) { if (this_->destination_valid == 1) { //int count = 0; //count = g_list_length(this_->route->destinations); //DBG dbg(0, "count=%d\n", count); //dbg(0, "navit->navit_add_waypoint_to_route 1: %i %i\n", c->x, c->y); route_add_destination(this_->route, c, async); this_->destination = *c; this_->destination_valid = 1; } else { //dbg(0, "navit->navit_add_waypoint_to_route 2: %i %i\n", c->x, c->y); navit_set_destination(this_, c, description, async); } } /** * Start the route computing to a given set of coordinates including waypoints * * @param navit The navit instance * @param c The coordinate to start routing to * @param description A label which allows the user to later identify this destination in the former destinations selection * @returns nothing */ void navit_set_destinations(struct navit *this_, struct pcoord *c, int count, const char *description, int async) { ////DBG dbg(0,"EEnter\n"); char *destination_file; if (c && count) { this_->destination = c[count - 1]; this_->destination_valid = 1; //dbg(0, "navit->navit_set_destinations 1: %i %i\n", c[count-1].x, c[count-1].y); } else { this_->destination_valid = 0; } //destination_file = bookmarks_get_destination_file(TRUE); //bookmarks_append_coord(this_->bookmarks, destination_file, c, count, "former_itinerary", description, NULL, this_->recentdest_count); //g_free(destination_file); callback_list_call_attr_0(this_->attr_cbl, attr_destination); if (this_->route) { route_set_destinations(this_->route, c, count, async); if (this_->ready == 3) { navit_draw(this_); } } } /** * @brief Checks if a route is calculated * * This function checks if a route is calculated. * * @param this_ The navit struct whose route should be checked. * @return True if the route is set, false otherwise. */ int navit_check_route(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); if (this_->route) { return route_get_path_set(this_->route); } return 0; } static int navit_former_destinations_active(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); return 0; // disable this function!! char *destination_file = bookmarks_get_destination_file(FALSE); FILE *f; int active = 0; char buffer[3]; f = fopen(destination_file, "r"); if (f) { if (!fseek(f, -2, SEEK_END) && fread(buffer, 2, 1, f) == 1 && (buffer[0] != '\n' || buffer[1] != '\n')) { active = 1; } fclose(f); } g_free(destination_file); return active; } static void navit_add_former_destinations_from_file(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); char *destination_file = bookmarks_get_destination_file(FALSE); struct attr *attrs[4]; struct map_rect *mr; struct item *item; int i, valid = 0, count = 0; struct coord c[16]; struct pcoord pc[16]; struct attr parent; struct attr type; struct attr data; struct attr flags; parent.type = attr_navit; parent.u.navit = this_; type.type = attr_type; type.u.str = "textfile"; data.type = attr_data; data.u.str = destination_file; flags.type = attr_flags; flags.u.num = 1; attrs[0] = &type; attrs[1] = &data; attrs[2] = &flags; attrs[3] = NULL; this_->former_destination = map_new(&parent, attrs); g_free(destination_file); if (!this_->route || !navit_former_destinations_active(this_)) return; mr = map_rect_new(this_->former_destination, NULL); while ((item = map_rect_get_item(mr))) { if ((item->type == type_former_destination || item->type == type_former_itinerary || item->type == type_former_itinerary_part) && (count = item_coord_get(item, c, 16))) valid = 1; } map_rect_destroy(mr); if (valid && count > 0) { for (i = 0; i < count; i++) { pc[i].pro = map_projection(this_->former_destination); pc[i].x = c[i].x; pc[i].y = c[i].y; } if (count == 1) { route_set_destination(this_->route, &pc[0], 1); } else { route_set_destinations(this_->route, pc, count, 1); } this_->destination = pc[count - 1]; this_->destination_valid = 1; } } void navit_textfile_debug_log(struct navit *this_, const char *fmt, ...) { ////DBG dbg(0,"EEnter\n"); va_list ap; char *str1, *str2; va_start(ap, fmt); if (this_->textfile_debug_log && this_->vehicle) { str1 = g_strdup_vprintf(fmt, ap); str2 = g_strdup_printf("0x%x 0x%x%s%s\n", this_->vehicle->coord.x, this_->vehicle->coord.y, strlen(str1) ? " " : "", str1); log_write(this_->textfile_debug_log, str2, strlen(str2), 0); g_free(str2); g_free(str1); } va_end(ap); } void navit_textfile_debug_log_at(struct navit *this_, struct pcoord *pc, const char *fmt, ...) { ////DBG dbg(0,"EEnter\n"); va_list ap; char *str1, *str2; va_start(ap, fmt); if (this_->textfile_debug_log && this_->vehicle) { str1 = g_strdup_vprintf(fmt, ap); str2 = g_strdup_printf("0x%x 0x%x%s%s\n", pc->x, pc->y, strlen(str1) ? " " : "", str1); log_write(this_->textfile_debug_log, str2, strlen(str2), 0); g_free(str2); g_free(str1); } va_end(ap); } void navit_say(struct navit *this_, char *text) { ////DBG dbg(0,"EEnter\n"); if (this_->speech) { speech_say(this_->speech, text); } } /** * @brief Toggles the navigation announcer for navit * @param this_ The navit object */ static void navit_cmd_announcer_toggle(struct navit *this_) { struct attr attr, speechattr; // search for the speech attribute if (!navit_get_attr(this_, attr_speech, &speechattr, NULL)) return; // find out if the corresponding attribute attr_active has been set if (speech_get_attr(speechattr.u.speech, attr_active, &attr, NULL)) { // flip it then... attr.u.num = !attr.u.num; } else { // otherwise disable it because voice is enabled by default attr.type = attr_active; attr.u.num = 0; } // apply the new state if (!speech_set_attr(speechattr.u.speech, &attr)) return; // announce that the speech attribute has changed callback_list_call_attr_0(this_->attr_cbl, attr_speech); } void navit_cmd_announcer_on(struct navit *this_) { struct attr attr, speechattr; // search for the speech attribute if (!navit_get_attr(this_, attr_speech, &speechattr, NULL)) return; attr.type = attr_active; attr.u.num = 1; // apply the new state if (!speech_set_attr(speechattr.u.speech, &attr)) return; // announce that the speech attribute has changed callback_list_call_attr_0(this_->attr_cbl, attr_speech); } void navit_cmd_announcer_off(struct navit *this_) { struct attr attr, speechattr; // search for the speech attribute if (!navit_get_attr(this_, attr_speech, &speechattr, NULL)) return; attr.type = attr_active; attr.u.num = 0; // apply the new state if (!speech_set_attr(speechattr.u.speech, &attr)) return; // announce that the speech attribute has changed callback_list_call_attr_0(this_->attr_cbl, attr_speech); } void navit_speak(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); struct navigation *nav = this_->navigation; struct map *map = NULL; struct map_rect *mr = NULL; struct item *item; struct attr attr; if (!speech_get_attr(this_->speech, attr_active, &attr, NULL)) attr.u.num = 1; // dbg(1, "this_.speech->active %i\n", attr.u.num); if (!attr.u.num) return; if (nav) map = navigation_get_map(nav); if (map) mr = map_rect_new(map, NULL); if (mr) { while ((item = map_rect_get_item(mr)) && (item->type == type_nav_position || item->type == type_nav_none)) ; if (item && item_attr_get(item, attr_navigation_speech, &attr)) { speech_say(this_->speech, attr.u.str); //navit_add_message(this_, attr.u.str); navit_textfile_debug_log(this_, "type=announcement label=\"%s\"", attr.u.str); } map_rect_destroy(mr); } } static void navit_window_roadbook_update(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); struct navigation *nav = this_->navigation; struct map *map = NULL; struct map_rect *mr = NULL; struct item *item; struct attr attr; struct param_list param[5]; int secs; // dbg(1, "enter\n"); datawindow_mode(this_->roadbook_window, 1); if (nav) map = navigation_get_map(nav); if (map) mr = map_rect_new(map, NULL); ////DBG dbg(0,"nav=%p map=%p mr=%p\n", nav, map, mr); if (mr) { ////DBG dbg(0,"while loop\n"); while ((item = map_rect_get_item(mr))) { ////DBG dbg(0,"item=%p\n", item); attr.u.str = NULL; if (item->type != type_nav_position) { item_attr_get(item, attr_navigation_long, &attr); if (attr.u.str == NULL) { continue; } dbg(2, "Command='%s'\n", attr.u.str); param[0].value = g_strdup(attr.u.str); } else param[0].value = _("Position"); param[0].name = _("Command"); item_attr_get(item, attr_length, &attr); dbg(2, "Length=%d\n", attr.u.num); param[1].name = _("Length"); if (attr.u.num >= 2000) { param[1].value = g_strdup_printf("%5.1f %s", (float) attr.u.num / 1000, _("km")); } else { param[1].value = g_strdup_printf("%7d %s", attr.u.num, _("m")); } item_attr_get(item, attr_time, &attr); dbg(2, "Time=%d\n", attr.u.num); secs = attr.u.num / 10; param[2].name = _("Time"); if (secs >= 3600) { param[2].value = g_strdup_printf("%d:%02d:%02d", secs / 60, (secs / 60) % 60, secs % 60); } else { param[2].value = g_strdup_printf("%d:%02d", secs / 60, secs % 60); } item_attr_get(item, attr_destination_length, &attr); dbg(2, "Destlength=%d\n", attr.u.num); param[3].name = _("Destination Length"); if (attr.u.num >= 2000) { param[3].value = g_strdup_printf("%5.1f %s", (float) attr.u.num / 1000, _("km")); } else { param[3].value = g_strdup_printf("%d %s", attr.u.num, _("m")); } item_attr_get(item, attr_destination_time, &attr); dbg(2, "Desttime=%d\n", attr.u.num); secs = attr.u.num / 10; param[4].name = _("Destination Time"); if (secs >= 3600) { param[4].value = g_strdup_printf("%d:%02d:%02d", secs / 3600, (secs / 60) % 60, secs % 60); } else { param[4].value = g_strdup_printf("%d:%02d", secs / 60, secs % 60); } datawindow_add(this_->roadbook_window, param, 5); } map_rect_destroy(mr); } datawindow_mode(this_->roadbook_window, 0); } void navit_window_roadbook_destroy(struct navit *this_) { ////DBG dbg(0, "enter\n"); navigation_unregister_callback(this_->navigation, attr_navigation_long, this_->roadbook_callback); this_->roadbook_window = NULL; this_->roadbook_callback = NULL; } void navit_window_roadbook_new(struct navit *this_) { if (!this_->gui || this_->roadbook_callback || this_->roadbook_window) { return; } this_->roadbook_callback = callback_new_1(callback_cast(navit_window_roadbook_update), this_); navigation_register_callback(this_->navigation, attr_navigation_long, this_->roadbook_callback); this_->roadbook_window = gui_datawindow_new(this_->gui, _("Roadbook"), NULL, callback_new_1(callback_cast(navit_window_roadbook_destroy), this_)); navit_window_roadbook_update(this_); } void navit_remove_all_maps(struct navit *this_) { struct mapset *ms; struct map *map3; // first: stop navigation! //if (global_navit->destination_valid != 0) //{ navit_set_destination(global_navit, NULL, NULL, 0); //} if (this_->route) { struct attr callback; // this_->route_cb=callback_new_attr_1(callback_cast(navit_redraw_route), attr_route_status, this_); callback.type=attr_callback; callback.u.callback=this_->route_cb; route_remove_attr(this_->route, &callback); this_->route->ms = NULL; // route_set_mapset(this_->route, ms); // route_set_projection(this_->route, transform_get_projection(this_->trans)); //*********route_destroy(this_->route); //route_path_destroy(this_->route->path2,1); //this_->route->path2 = NULL; //route_graph_destroy(this_->route->graph); //this_->route->graph=NULL; } /* map_rect_destroy(displaylist->mr); if (!route_selection) map_selection_destroy(displaylist->sel); mapset_close(displaylist->msh); displaylist->mr=NULL; displaylist->sel=NULL; displaylist->m=NULL; displaylist->msh=NULL; profile(1,"callback\n"); callback_call_1(displaylist->cb, cancel); */ struct displaylist *dl = navit_get_displaylist(this_); dl->m = NULL; dl->msh = NULL; if (this_->mapsets) { struct mapset_handle *msh; ms = this_->mapsets->data; msh = mapset_open(ms); ////DBG dbg(0,"removing map bb0\n"); while (msh && (map3 = mapset_next(msh, 0))) { ////DBG dbg(0,"removing map bb1\n"); struct attr map_name_attr; if (map_get_attr(map3, attr_name, &map_name_attr, NULL)) { //DBG dbg(0, "map name=%s", map_name_attr.u.str); if (strncmp("_ms_sdcard_map:", map_name_attr.u.str, 15) == 0) { //DBG dbg(0, "removing map a0\n"); struct attr active; active.type = attr_active; active.u.num = 0; //map_set_attr(map3, &active); //DBG dbg(0, "removing map a1\n"); struct attr map_attr; map_attr.u.map = map3; map_attr.type = attr_map; mapset_remove_attr(ms, &map_attr); //DBG dbg(0, "removing map a2\n"); map3->refcount = 1; map_destroy(map3); //DBG dbg(0, "removing map a3\n"); map3 = NULL; } } } mapset_close(msh); //DBG dbg(0, "removing map bb4\n"); } dl->ms = this_->mapsets->data; // int async = 0; // transform_setup_source_rect(this_->trans); // graphics_draw(this_->gra, this_->displaylist, this_->mapsets->data, this_->trans, this_->layout_current, async, NULL, this_->graphics_flags|1); //this_->displaylist->ms=this_->mapsets->data; } void navit_add_all_maps(struct navit *this_) { struct map *map3; if (this_->mapsets) { //DBG dbg(0, "xADDx all maps - start\n"); struct mapset *ms; ms = this_->mapsets->data; struct attr type; struct attr parent; struct attr data; struct attr flags; struct map *map2; struct attr map2_attr; struct attr *attrs[4]; char *map_file; parent.type = attr_navit; parent.u.navit = this_; type.type = attr_type; type.u.str = "binfile"; data.type = attr_data; map_file = g_strdup_printf("%sborders.bin", navit_maps_dir); data.u.str = map_file; ////DBG dbg(0,"map name=%s",map_file); flags.type = attr_flags; flags.u.num = 0; attrs[0] = &type; attrs[1] = &data; attrs[2] = &flags; attrs[3] = NULL; map2 = map_new(&parent, attrs); if (map2) { map2_attr.u.data = map2; map2_attr.type = attr_map; // mapset_add_attr_name(ms, &map2_attr); mapset_add_attr_name_str(ms, &map2_attr, "/sdcard/zanavi/maps/borders.bin"); struct attr active; active.type = attr_active; active.u.num = 0; //map_set_attr(map2, &active); } g_free(map_file); parent.type = attr_navit; parent.u.navit = this_; type.type = attr_type; type.u.str = "binfile"; data.type = attr_data; map_file = g_strdup_printf("%scoastline.bin", navit_maps_dir); data.u.str = map_file; ////DBG dbg(0,"map name=%s",map_file); flags.type = attr_flags; flags.u.num = 0; attrs[0] = &type; attrs[1] = &data; attrs[2] = &flags; attrs[3] = NULL; map2 = map_new(&parent, attrs); if (map2) { map2_attr.u.data = map2; map2_attr.type = attr_map; // mapset_add_attr_name(ms, &map2_attr); mapset_add_attr_name_str(ms, &map2_attr, "/sdcard/zanavi/maps/coastline.bin"); struct attr active; active.type = attr_active; active.u.num = 0; //map_set_attr(map2, &active); } g_free(map_file); int i = 1; for (i = 1; i < 10; i++) { struct map *map22; struct attr map22_attr; parent.type = attr_navit; parent.u.navit = this_; type.type = attr_type; type.u.str = "binfile"; data.type = attr_data; map_file = g_strdup_printf("%snavitmap_00%d.bin", navit_maps_dir, i); data.u.str = map_file; flags.type = attr_flags; flags.u.num = 0; attrs[0] = &type; attrs[1] = &data; attrs[2] = &flags; attrs[3] = NULL; map22 = map_new(&parent, attrs); if (map22) { //DBG dbg(0, "*add* map name=%s\n", map_file); map22_attr.u.data = map22; map22_attr.type = attr_map; // mapset_add_attr_name(ms, &map22_attr); char *map_name_str; map_name_str = g_strdup_printf("/sdcard/zanavi/maps/navitmap_00%d.bin", i); mapset_add_attr_name_str(ms, &map22_attr, map_name_str); struct attr active; active.type = attr_active; active.u.num = 0; //map_set_attr(map22, &active); g_free(map_name_str); } g_free(map_file); } i = 10; for (i = 10; i < 21; i++) { parent.type = attr_navit; parent.u.navit = this_; type.type = attr_type; type.u.str = "binfile"; data.type = attr_data; map_file = g_strdup_printf("%snavitmap_0%d.bin", navit_maps_dir, i); data.u.str = map_file; ////DBG dbg(0,"map name=%s",map_file); flags.type = attr_flags; flags.u.num = 0; attrs[0] = &type; attrs[1] = &data; attrs[2] = &flags; attrs[3] = NULL; map2 = map_new(&parent, attrs); if (map2) { map2_attr.u.data = map2; map2_attr.type = attr_map; // mapset_add_attr_name(ms, &map2_attr); char *map_name_str; map_name_str = g_strdup_printf("/sdcard/zanavi/maps/navitmap_0%d.bin", i); mapset_add_attr_name_str(ms, &map2_attr, map_name_str); struct attr active; active.type = attr_active; active.u.num = 0; //map_set_attr(map2, &active); g_free(map_name_str); } g_free(map_file); } } /* if (this_->mapsets) { struct mapset_handle *msh; struct map *map; struct mapset *ms; //DBG dbg(0,"xx ms callbacks xx\n"); ms=this_->mapsets->data; this_->progress_cb=callback_new_attr_1(callback_cast(navit_map_progress), attr_progress, this_); msh=mapset_open(ms); while (msh && (map=mapset_next(msh, 0))) { //pass new callback instance for each map in the mapset to make map callback list destruction work correctly struct callback *pcb = callback_new_attr_1(callback_cast(navit_map_progress), attr_progress, this_); map_add_callback(map, pcb); } mapset_close(msh); } */ struct attr parent; parent.type = attr_navit; parent.u.navit = global_navit; struct attr *attrs_r[2]; attrs_r[0] = NULL; attrs_r[1] = NULL; //***this_->route = route_new(&parent, attrs_r); //int async = 0; //transform_setup_source_rect(this_->trans); //graphics_draw(this_->gra, this_->displaylist, this_->mapsets->data, this_->trans, this_->layout_current, async, NULL, this_->graphics_flags|1); struct displaylist *dl = navit_get_displaylist(this_); dl->ms = this_->mapsets->data; dl->m = NULL; dl->msh = NULL; if (this_->route) { struct mapset *ms; ms = this_->mapsets->data; route_set_mapset(this_->route, ms); struct attr callback; this_->route_cb=callback_new_attr_1(callback_cast(navit_redraw_route), attr_route_status, this_); callback.type=attr_callback; callback.u.callback=this_->route_cb; route_add_attr(this_->route, &callback); // ***** route_set_projection(this_->route, transform_get_projection(this_->trans)); } if (this_->tracking) { struct mapset *ms; ms = this_->mapsets->data; tracking_set_mapset(this_->tracking, ms); if (this_->route) { tracking_set_route(this_->tracking, this_->route); } } } void navit_reload_maps(struct navit *this_) { navit_remove_all_maps(this_); navit_add_all_maps(this_); } void navit_init(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); struct mapset *ms; struct map *map; int callback; char *center_file; // default value navit_maps_dir = "/sdcard/zanavi/maps/"; global_img_waypoint = NULL; //DBG dbg(0, "enter gui %p graphics %p\n", this_->gui, this_->gra); if (!this_->gui && !(this_->flags & 2)) { dbg(0, "no gui\n"); navit_destroy(this_); return; } if (!this_->gra && !(this_->flags & 1)) { dbg(0, "no graphics\n"); navit_destroy(this_); return; } //DBG dbg(0, "Connecting gui to graphics\n"); if (this_->gui && this_->gra && gui_set_graphics(this_->gui, this_->gra)) { struct attr attr_type_gui, attr_type_graphics; gui_get_attr(this_->gui, attr_type, &attr_type_gui, NULL); graphics_get_attr(this_->gra, attr_type, &attr_type_graphics, NULL); //DBG dbg(0, "failed to connect graphics '%s' to gui '%s'\n", attr_type_graphics.u.str, attr_type_gui.u.str); // //DBG dbg(0," Please see http://wiki.navit-project.org/index.php/Failed_to_connect_graphics_to_gui\n"); // //DBG dbg(0," for explanations and solutions\n"); dbg(0,"failed to connect to graphics\n"); navit_destroy(this_); return; } if (this_->speech && this_->navigation) { struct attr speech; speech.type = attr_speech; speech.u.speech = this_->speech; navigation_set_attr(this_->navigation, &speech); } //DBG dbg(0, "Initializing graphics\n"); //DBG dbg(0, "Setting Vehicle\n"); navit_set_vehicle(this_, this_->vehicle); //DBG dbg(0, "Adding dynamic maps to mapset %p\n", this_->mapsets); if (this_->mapsets) { struct mapset_handle *msh; ms = this_->mapsets->data; // **D** // this_->progress_cb=callback_new_attr_1(callback_cast(navit_map_progress), attr_progress, this_); msh = mapset_open(ms); while (msh && (map = mapset_next(msh, 0))) { //pass new callback instance for each map in the mapset to make map callback list destruction work correctly // **D** // struct callback *pcb = callback_new_attr_1(callback_cast(navit_map_progress), attr_progress, this_); // **D** // map_add_callback(map, pcb); } mapset_close(msh); if (this_->route) { if ((map = route_get_map(this_->route))) { struct attr map_a, map_name; map_a.type = attr_map; map_a.u.map = map; map_name.type = attr_name; map_name.u.str = "_ms_route"; map_set_attr(map_a.u.map, &map_name); mapset_add_attr(ms, &map_a); } if ((map = route_get_graph_map(this_->route))) { struct attr map_a, active, map_name; map_a.type = attr_map; map_a.u.map = map; active.type = attr_active; active.u.num = 0; map_name.type = attr_name; map_name.u.str = "_ms_route_graph"; map_set_attr(map_a.u.map, &map_name); mapset_add_attr(ms, &map_a); map_set_attr(map, &active); } route_set_mapset(this_->route, ms); route_set_projection(this_->route, transform_get_projection(this_->trans)); } if (this_->tracking) { tracking_set_mapset(this_->tracking, ms); if (this_->route) { tracking_set_route(this_->tracking, this_->route); } } if (this_->navigation) { if ((map = navigation_get_map(this_->navigation))) { struct attr map_a, active, map_name; map_a.type = attr_map; map_a.u.map = map; active.type = attr_active; active.u.num = 0; map_name.type = attr_name; map_name.u.str = "_ms_navigation"; map_set_attr(map_a.u.map, &map_name); mapset_add_attr(ms, &map_a); map_set_attr(map, &active); } } if (this_->tracking) { if ((map = tracking_get_map(this_->tracking))) { struct attr map_a, active, map_name; map_a.type = attr_map; map_a.u.map = map; active.type = attr_active; active.u.num = 0; map_name.type = attr_name; map_name.u.str = "_ms_tracking"; map_set_attr(map_a.u.map, &map_name); mapset_add_attr(ms, &map_a); map_set_attr(map, &active); } } // *DISABLED* navit_add_former_destinations_from_file(this_); } if (this_->route) { struct attr callback; this_->route_cb = callback_new_attr_1(callback_cast(navit_redraw_route), attr_route_status, this_); callback.type = attr_callback; callback.u.callback = this_->route_cb; route_add_attr(this_->route, &callback); } if (this_->navigation) { if (this_->speech) { this_->nav_speech_cb = callback_new_1(callback_cast(navit_speak), this_); navigation_register_callback(this_->navigation, attr_navigation_speech, this_->nav_speech_cb); } if (this_->route) { navigation_set_route(this_->navigation, this_->route); } } dbg(0, "Setting Center\n"); center_file = bookmarks_get_center_file(FALSE); //dbg(0, "g0\n"); bookmarks_set_center_from_file(this_->bookmarks, center_file); g_free(center_file); #if 0 if (this_->menubar) { men=menu_add(this_->menubar, "Data", menu_type_submenu, NULL); if (men) { navit_add_menu_windows_items(this_, men); } } #endif global_navit = this_; #if 0 navit_window_roadbook_new(this_); navit_window_items_new(this_); #endif //dbg(0, "g1\n"); //messagelist_init(this_->messages); //dbg(0, "g2\n"); navit_set_cursors(this_); callback_list_call_attr_1(this_->attr_cbl, attr_navit, this_); callback = (this_->ready == 2); //DBG dbg(0, "pre this_->ready=%d\n", this_->ready); this_->ready |= 1; //DBG dbg(0, "set this_->ready=%d\n", this_->ready); ////DBG dbg(0,"ready=%d\n",this_->ready); if (this_->ready == 3) { ////DBG dbg(0,"navit_draw_async_003\n"); navit_draw_async(this_, 1); } if (callback) { callback_list_call_attr_1(this_->attr_cbl, attr_graphics_ready, this_); } #if 0 routech_test(this_); #endif //dbg(0, "1111111111\n"); } void navit_zoom_to_rect(struct navit *this_, struct coord_rect *r) { ////DBG dbg(0,"EEnter\n"); struct coord c; int scale = 16; c.x = (r->rl.x + r->lu.x) / 2; c.y = (r->rl.y + r->lu.y) / 2; transform_set_center(this_->trans, &c); // dbg(1, "%x,%x-%x,%x\n", r->rl.x, r->rl.y, r->lu.x, r->lu.y); while (scale < 1 << 20) { struct point p1, p2; transform_set_scale(this_->trans, scale); transform_setup_source_rect(this_->trans); transform(this_->trans, transform_get_projection(this_->trans), &r->lu, &p1, 1, 0, 0, NULL); transform(this_->trans, transform_get_projection(this_->trans), &r->rl, &p2, 1, 0, 0, NULL); // dbg(1, "%d,%d-%d,%d\n", p1.x, p1.y, p2.x, p2.y); if (p1.x < 0 || p2.x < 0 || p1.x > this_->w || p2.x > this_->w || p1.y < 0 || p2.y < 0 || p1.y > this_->h || p2.y > this_->h) scale *= 2; else break; } if (this_->ready == 3) { ////DBG dbg(0,"navit_draw_async_004\n"); navit_draw_async(this_, 0); } } void navit_zoom_to_route(struct navit *this_, int orientation) { ////DBG dbg(0,"EEnter\n"); struct map *map; struct map_rect *mr = NULL; struct item *item; struct coord c; struct coord_rect r; int count = 0; if (!this_->route) return; // dbg(1, "enter\n"); map = route_get_map(this_->route); // dbg(1, "map=%p\n", map); if (map) mr = map_rect_new(map, NULL); // dbg(1, "mr=%p\n", mr); if (mr) { while ((item = map_rect_get_item(mr))) { // dbg(1, "item=%s\n", item_to_name(item->type)); while (item_coord_get(item, &c, 1)) { // dbg(1, "coord\n"); if (!count) r.lu = r.rl = c; else coord_rect_extend(&r, &c); count++; } } map_rect_destroy(mr); } if (!count) return; if (orientation != -1) transform_set_yaw(this_->trans, orientation); navit_zoom_to_rect(this_, &r); } static void navit_cmd_zoom_to_route(struct navit *this) { ////DBG dbg(0,"EEnter\n"); navit_zoom_to_route(this, 0); } /** * show point on map * * @param navit The navit instance * @param center The point where to center the map, including its projection * @returns nothing */ void navit_set_center(struct navit *this_, struct pcoord *center, int set_timeout) { ////DBG dbg(0,"EEnter\n"); struct coord *c = transform_center(this_->trans); struct coord c1, c2; enum projection pro = transform_get_projection(this_->trans); if (pro != center->pro) { c1.x = center->x; c1.y = center->y; transform_from_to(&c1, center->pro, &c2, pro); } else { c2.x = center->x; c2.y = center->y; } *c = c2; if (set_timeout) { navit_set_timeout(this_); } if (this_->ready == 3) { navit_draw(this_); } } static void navit_set_center_coord_screen(struct navit *this_, struct coord *c, struct point *p, int set_timeout) { ////DBG dbg(0,"EEnter\n"); int width, height; struct point po; transform_set_center(this_->trans, c); transform_get_size(this_->trans, &width, &height); po.x = width / 2; po.y = height / 2; update_transformation(this_->trans, &po, p, NULL); if (set_timeout) { navit_set_timeout(this_); } } /** * Links all vehicles to a cursor depending on the current profile. * * @param this_ A navit instance * @author Ralph Sennhauser (10/2009) */ void navit_set_cursors(struct navit *this_) { struct attr name; struct navit_vehicle *nv; struct cursor *c; GList *v; //dbg(0, "Enter\n"); v = g_list_first(this_->vehicles); // GList of navit_vehicles while (v) { dbg(0, "* found vehicle *\n"); nv = v->data; if (vehicle_get_attr(nv->vehicle, attr_cursorname, &name, NULL)) { if (!strcmp(name.u.str, "none")) { c = NULL; } else { c = layout_get_cursor(this_->layout_current, name.u.str); } } else { c = layout_get_cursor(this_->layout_current, "default"); } vehicle_set_cursor(nv->vehicle, c, 0); v = g_list_next(v); } return; } void navit_remove_cursors(struct navit *this_) { struct attr name; struct navit_vehicle *nv; struct cursor *c; GList *v; //dbg(0, "Enter\n"); name.type = attr_cursor; v = g_list_first(this_->vehicles); // GList of navit_vehicles while (v) { dbg(0, "* found vehicle *\n"); nv = v->data; vehicle_remove_attr(nv->vehicle, &name); v = g_list_next(v); } return; } static int navit_get_cursor_pnt(struct navit *this_, struct point *p, int keep_orientation, int *dir) { ////DBG dbg(0,"EEnter\n"); int width, height; struct navit_vehicle *nv = this_->vehicle; float offset = this_->radius; // Cursor offset from the center of the screen (percent). #if 0 /* Better improve track.c to get that issue resolved or make it configurable with being off the default, the jumping back to the center is a bit annoying */ float min_offset = 0.; // Percent offset at min_offset_speed. float max_offset = 30.; // Percent offset at max_offset_speed. int min_offset_speed = 2; // Speed in km/h int max_offset_speed = 50; // Speed ini km/h // Calculate cursor offset from the center of the screen, upon speed. if (nv->speed <= min_offset_speed) { offset = min_offset; } else if (nv->speed > max_offset_speed) { offset = max_offset; } else { offset = (max_offset - min_offset) / (max_offset_speed - min_offset_speed) * (nv->speed - min_offset_speed); } #endif transform_get_size(this_->trans, &width, &height); if (this_->orientation == -1 || keep_orientation) { p->x = 50 * width / 100; p->y = (50 + offset) * height / 100; if (dir) *dir = keep_orientation ? this_->orientation : nv->dir; } else { int mdir; if (this_->tracking && this_->tracking_flag) { mdir = tracking_get_angle(this_->tracking) - this_->orientation; } else { mdir = nv->dir - this_->orientation; } p->x = (50 - offset * sin(M_PI * mdir / 180.)) * width / 100; p->y = (50 + offset * cos(M_PI * mdir / 180.)) * height / 100; if (dir) *dir = this_->orientation; } return 1; } void navit_set_center_cursor(struct navit *this_, int autozoom, int keep_orientation) { ////DBG dbg(0,"EEnter\n"); int dir; struct point pn; struct navit_vehicle *nv = this_->vehicle; navit_get_cursor_pnt(this_, &pn, keep_orientation, &dir); transform_set_yaw(this_->trans, dir); navit_set_center_coord_screen(this_, &nv->coord, &pn, 0); if (autozoom) navit_autozoom(this_, &nv->coord, nv->speed, 0); } static void navit_set_center_cursor_draw(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); navit_set_center_cursor(this_, 1, 0); if (this_->ready == 3) { ////DBG dbg(0,"navit_draw_async_005\n"); navit_draw_async(this_, 1); } } static void navit_cmd_set_center_cursor(struct navit *this_) { ////DBG dbg(0,"EEnter\n"); navit_set_center_cursor_draw(this_); } void navit_set_center_screen(struct navit *this_, struct point *p, int set_timeout) { ////DBG dbg(0,"EEnter\n"); struct coord c; struct pcoord pc; transform_reverse(this_->trans, p, &c); pc.x = c.x; pc.y = c.y; pc.pro = transform_get_projection(this_->trans); navit_set_center(this_, &pc, set_timeout); } #if 0 switch((*attrs)->type) { case attr_zoom: zoom=(*attrs)->u.num; break; case attr_center: g=*((*attrs)->u.coord_geo); break; #endif static int navit_set_attr_do(struct navit *this_, struct attr *attr, int init) { ////DBG dbg(0,"EEnter\n"); int dir = 0, orient_old = 0, attr_updated = 0; struct coord co; long zoom; GList *l; struct navit_vehicle *nv; struct layout *lay; struct attr active; active.type = attr_active; active.u.num = 0; switch (attr->type) { case attr_autozoom: attr_updated = (this_->autozoom_secs != attr->u.num); this_->autozoom_secs = attr->u.num; break; case attr_autozoom_active: attr_updated = (this_->autozoom_active != attr->u.num); this_->autozoom_active = attr->u.num; break; case attr_center: transform_from_geo(transform_get_projection(this_->trans), attr->u.coord_geo, &co); // dbg(1, "0x%x,0x%x\n", co.x, co.y); transform_set_center(this_->trans, &co); break; case attr_drag_bitmap: attr_updated = (this_->drag_bitmap != !!attr->u.num); this_->drag_bitmap = !!attr->u.num; break; case attr_flags: attr_updated = (this_->flags != attr->u.num); this_->flags = attr->u.num; break; case attr_flags_graphics: attr_updated = (this_->graphics_flags != attr->u.num); this_->graphics_flags = attr->u.num; break; case attr_follow: if (!this_->vehicle) return 0; attr_updated = (this_->vehicle->follow_curr != attr->u.num); this_->vehicle->follow_curr = attr->u.num; break; case attr_layout: if (this_->layout_current != attr->u.layout) { this_->layout_current = attr->u.layout; graphics_font_destroy_all(this_->gra); navit_set_cursors(this_); if (this_->ready == 3) navit_draw(this_); attr_updated = 1; } break; case attr_layout_name: l = this_->layouts; while (l) { lay = l->data; if (!strcmp(lay->name, attr->u.str)) { struct attr attr; attr.type = attr_layout; attr.u.layout = lay; return navit_set_attr_do(this_, &attr, init); } l = g_list_next(l); } return 0; case attr_map_border: if (this_->border != attr->u.num) { this_->border = attr->u.num; attr_updated = 1; } break; case attr_orientation: orient_old = this_->orientation; this_->orientation = attr->u.num; if (!init) { if (this_->orientation != -1) { dir = this_->orientation; } else { if (this_->vehicle) { dir = this_->vehicle->dir; } } transform_set_yaw(this_->trans, dir); if (orient_old != this_->orientation) { #if 0 if (this_->ready == 3) navit_draw(this_); #endif attr_updated = 1; } } break; case attr_osd_configuration: //DBG dbg(0, "setting osd_configuration to %d (was %d)\n", attr->u.num, this_->osd_configuration); attr_updated = (this_->osd_configuration != attr->u.num); this_->osd_configuration = attr->u.num; break; case attr_pitch: attr_updated = (this_->pitch != attr->u.num); this_->pitch = attr->u.num; transform_set_pitch(this_->trans, this_->pitch); if (!init && attr_updated && this_->ready == 3) navit_draw(this_); break; case attr_projection: if (this_->trans && transform_get_projection(this_->trans) != attr->u.projection) { navit_projection_set(this_, attr->u.projection, !init); attr_updated = 1; } break; case attr_radius: attr_updated = (this_->radius != attr->u.num); this_->radius = attr->u.num; break; case attr_recent_dest: attr_updated = (this_->recentdest_count != attr->u.num); this_->recentdest_count = attr->u.num; break; case attr_speech: if (this_->speech && this_->speech != attr->u.speech) { attr_updated = 1; this_->speech = attr->u.speech; } break; case attr_timeout: attr_updated = (this_->center_timeout != attr->u.num); this_->center_timeout = attr->u.num; break; case attr_tracking: attr_updated = (this_->tracking_flag != !!attr->u.num); this_->tracking_flag = !!attr->u.num; break; case attr_transformation: this_->trans = attr->u.transformation; break; case attr_use_mousewheel: attr_updated = (this_->use_mousewheel != !!attr->u.num); this_->use_mousewheel = !!attr->u.num; break; case attr_vehicle: l = this_->vehicles; while (l) { nv = l->data; if (nv->vehicle == attr->u.vehicle) { if (!this_->vehicle || this_->vehicle->vehicle != attr->u.vehicle) { if (this_->vehicle) vehicle_set_attr(this_->vehicle->vehicle, &active); active.u.num = 1; vehicle_set_attr(nv->vehicle, &active); attr_updated = 1; } navit_set_vehicle(this_, nv); } l = g_list_next(l); } break; case attr_zoom: zoom = transform_get_scale(this_->trans); attr_updated = (zoom != attr->u.num); transform_set_scale(this_->trans, attr->u.num); if (attr_updated && !init) navit_draw(this_); break; case attr_zoom_min: attr_updated = (attr->u.num != this_->zoom_min); this_->zoom_min = attr->u.num; break; case attr_zoom_max: attr_updated = (attr->u.num != this_->zoom_max); this_->zoom_max = attr->u.num; break; case attr_message: //navit_add_message(this_, attr->u.str); break; case attr_follow_cursor: attr_updated = (this_->follow_cursor != !!attr->u.num); this_->follow_cursor = !!attr->u.num; break; case attr_imperial: attr_updated = (this_->imperial != attr->u.num); this_->imperial = attr->u.num; break; default: return 0; } if (attr_updated && !init) { callback_list_call_attr_2(this_->attr_cbl, attr->type, this_, attr); if (attr->type == attr_osd_configuration) graphics_draw_mode(this_->gra, draw_mode_end); } return 1; } int navit_set_attr(struct navit *this_, struct attr *attr) { ////DBG dbg(0,"EEnter\n"); return navit_set_attr_do(this_, attr, 0); } int navit_get_attr(struct navit *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter) { ////DBG dbg(0,"EEnter\n"); struct message *msg; int len, offset; int ret = 1; switch (type) { case attr_message: return 0; /* msg = navit_get_messages(this_); if (!msg) { return 0; } len = 0; while (msg) { len += strlen(msg->text) + 1; msg = msg->next; } attr->u.str = g_malloc(len + 1); msg = navit_get_messages(this_); offset = 0; while (msg) { g_stpcpy((attr->u.str + offset), msg->text); offset += strlen(msg->text); attr->u.str[offset] = '\n'; offset++; msg = msg->next; } attr->u.str[len] = '\0'; */ break; case attr_imperial: attr->u.num = this_->imperial; break; case attr_bookmark_map: attr->u.map = bookmarks_get_map(this_->bookmarks); break; case attr_bookmarks: attr->u.bookmarks = this_->bookmarks; break; case attr_callback_list: attr->u.callback_list = this_->attr_cbl; break; case attr_destination: if (!this_->destination_valid) return 0; attr->u.pcoord = &this_->destination; break; case attr_displaylist: attr->u.displaylist = this_->displaylist; return (attr->u.displaylist != NULL); case attr_follow: if (!this_->vehicle) return 0; attr->u.num = this_->vehicle->follow_curr; break; case attr_former_destination_map: attr->u.map = this_->former_destination; break; case attr_graphics: attr->u.graphics = this_->gra; ret = (attr->u.graphics != NULL); break; case attr_gui: attr->u.gui = this_->gui; ret = (attr->u.gui != NULL); break; case attr_layout: if (iter) { if (iter->u.list) { iter->u.list = g_list_next(iter->u.list); } else { iter->u.list = this_->layouts; } if (!iter->u.list) { return 0; } attr->u.layout = (struct layout *) iter->u.list->data; } else { attr->u.layout = this_->layout_current; } break; case attr_map: if (iter && this_->mapsets) { if (!iter->u.mapset_handle) { iter->u.mapset_handle = mapset_open((struct mapset *) this_->mapsets->data); } attr->u.map = mapset_next(iter->u.mapset_handle, 0); if (!attr->u.map) { mapset_close(iter->u.mapset_handle); return 0; } } else { return 0; } break; case attr_mapset: attr->u.mapset = this_->mapsets->data; ret = (attr->u.mapset != NULL); break; case attr_navigation: attr->u.navigation = this_->navigation; break; case attr_orientation: attr->u.num = this_->orientation; break; case attr_osd_configuration: attr->u.num = this_->osd_configuration; break; case attr_pitch: attr->u.num = transform_get_pitch(this_->trans); break; case attr_projection: if (this_->trans) { attr->u.num = transform_get_projection(this_->trans); } else { return 0; } break; case attr_route: attr->u.route = this_->route; break; case attr_speech: attr->u.speech = this_->speech; break; case attr_tracking: attr->u.num = this_->tracking_flag; break; case attr_trackingo: attr->u.tracking = this_->tracking; break; case attr_transformation: attr->u.transformation = this_->trans; break; case attr_vehicle: if (iter) { if (iter->u.list) { iter->u.list = g_list_next(iter->u.list); } else { iter->u.list = this_->vehicles; } if (!iter->u.list) return 0; attr->u.vehicle = ((struct navit_vehicle*) iter->u.list->data)->vehicle; } else { if (this_->vehicle) { attr->u.vehicle = this_->vehicle->vehicle; } else { return 0; } } break; case attr_vehicleprofile: attr->u.vehicleprofile = this_->vehicleprofile; break; case attr_zoom: attr->u.num = transform_get_scale(this_->trans); break; case attr_autozoom_active: attr->u.num = this_->autozoom_active; break; case attr_follow_cursor: attr->u.num = this_->follow_cursor; break; default: return 0; } attr->type = type; return ret; } static int navit_add_log(struct navit *this_, struct log *log) { struct attr type_attr; if (!log_get_attr(log, attr_type, &type_attr, NULL)) return 0; if (!strcmp(type_attr.u.str, "textfile_debug")) { char *header = "type=track_tracked\n"; if (this_->textfile_debug_log) return 0; log_set_header(log, header, strlen(header)); this_->textfile_debug_log = log; return 1; } return 0; } static int navit_add_layout(struct navit *this_, struct layout *layout) { ////DBG dbg(0,"EEnter\n"); struct attr active; this_->layouts = g_list_append(this_->layouts, layout); layout_get_attr(layout, attr_active, &active, NULL); if (active.u.num || !this_->layout_current) { this_->layout_current = layout; return 1; } return 0; } int navit_add_attr(struct navit *this_, struct attr *attr) { ////DBG dbg(0,"EEnter\n"); int ret = 1; switch (attr->type) { case attr_callback: navit_add_callback(this_, attr->u.callback); break; case attr_log: ret = navit_add_log(this_, attr->u.log); break; case attr_gui: ret = navit_set_gui(this_, attr->u.gui); break; case attr_graphics: ret = navit_set_graphics(this_, attr->u.graphics); break; case attr_layout: ret = navit_add_layout(this_, attr->u.layout); break; case attr_route: this_->route = attr->u.route; break; case attr_mapset: this_->mapsets = g_list_append(this_->mapsets, attr->u.mapset); break; case attr_navigation: this_->navigation = attr->u.navigation; break; case attr_recent_dest: this_->recentdest_count = attr->u.num; break; case attr_speech: this_->speech = attr->u.speech; break; case attr_tracking: this_->tracking = attr->u.tracking; break; case attr_vehicle: ret = navit_add_vehicle(this_, attr->u.vehicle); break; case attr_vehicleprofile: this_->vehicleprofiles = g_list_prepend(this_->vehicleprofiles, attr->u.vehicleprofile); break; case attr_autozoom_min: this_->autozoom_min = attr->u.num; break; default: return 0; } callback_list_call_attr_2(this_->attr_cbl, attr->type, this_, attr); return ret; } int navit_remove_attr(struct navit *this_, struct attr *attr) { int ret = 1; switch (attr->type) { case attr_callback: navit_remove_callback(this_, attr->u.callback); break; default: return 0; } return ret; } struct attr_iter * navit_attr_iter_new(void) { return g_new0(struct attr_iter, 1); } void navit_attr_iter_destroy(struct attr_iter *iter) { g_free(iter); } void navit_add_callback(struct navit *this_, struct callback *cb) { ////DBG dbg(0,"EEnter\n"); callback_list_add(this_->attr_cbl, cb); } void navit_remove_callback(struct navit *this_, struct callback *cb) { ////DBG dbg(0,"EEnter\n"); callback_list_remove(this_->attr_cbl, cb); } /** * Toggle the cursor update : refresh the map each time the cursor has moved (instead of only when it reaches a border) * * @param navit The navit instance * @returns nothing */ static void navit_vehicle_draw(struct navit *this_, struct navit_vehicle *nv, struct point *pnt) { ////DBG dbg(0,"EEnter\n"); struct point cursor_pnt; enum projection pro; if (this_->blocked) return; if (pnt) { cursor_pnt = *pnt; } else { pro = transform_get_projection(this_->trans_cursor); if (!pro) return; transform(this_->trans_cursor, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL); } ////DBG dbg(0,"xx=%d\n",cursor_pnt.x); ////DBG dbg(0,"yy=%d\n",cursor_pnt.y); global_vehicle_pos_onscreen.x = cursor_pnt.x; global_vehicle_pos_onscreen.y = cursor_pnt.y; ////DBG dbg(0,"xx=%d\n",pnt->x); ////DBG dbg(0,"yy=%d\n",pnt->y); ////DBG dbg(0,"vehicle_draw_001\n"); vehicle_draw(nv->vehicle, this_->gra, &cursor_pnt, pnt ? 0 : 1, nv->dir - transform_get_yaw(this_->trans_cursor), nv->speed); #if 0 if (pnt) pnt2=*pnt; else { pro=transform_get_projection(this_->trans); transform(this_->trans, pro, &nv->coord, &pnt2, 1); } #if 1 cursor_draw(nv->cursor, &pnt2, nv->dir-transform_get_angle(this_->trans, 0), nv->speed > 2, pnt == NULL); #else cursor_draw(nv->cursor, &pnt2, nv->dir-transform_get_angle(this_->trans, 0), nv->speed > 2, 1); #endif #endif } static void navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv) { //DBG dbg(0,"EEnter\n"); struct attr attr_valid, attr_dir, attr_speed, attr_pos; struct pcoord cursor_pc; struct point cursor_pnt, *pnt = &cursor_pnt; struct tracking *tracking = NULL; struct pcoord pc[16]; enum projection pro = transform_get_projection(this_->trans_cursor); int count; int (*get_attr)(void *, enum attr_type, struct attr *, struct attr_iter *); void *attr_object; char *destination_file; // //DBG dbg(0,"navit_vehicle_update_001 %d\n",pro); //profile(0,NULL); if (this_->ready != 3) { //profile(0,"return 1\n"); return; } navit_layout_switch(this_); if (this_->vehicle == nv && this_->tracking_flag) tracking = this_->tracking; if (tracking) { tracking_update(tracking, nv->vehicle, this_->vehicleprofile, pro); attr_object = tracking; get_attr = (int(*)(void *, enum attr_type, struct attr *, struct attr_iter *)) tracking_get_attr; } else { attr_object = nv->vehicle; get_attr = (int(*)(void *, enum attr_type, struct attr *, struct attr_iter *)) vehicle_get_attr; } if (get_attr(attr_object, attr_position_valid, &attr_valid, NULL)) if (!attr_valid.u.num != attr_position_valid_invalid) return; if (!get_attr(attr_object, attr_position_direction, &attr_dir, NULL) || !get_attr(attr_object, attr_position_speed, &attr_speed, NULL) || !get_attr(attr_object, attr_position_coord_geo, &attr_pos, NULL)) { // profile(0,"return 2\n"); return; } nv->dir = *attr_dir.u.numd; nv->speed = *attr_speed.u.numd; transform_from_geo(pro, attr_pos.u.coord_geo, &nv->coord); if (nv != this_->vehicle) { ////DBG dbg(0,"---> 2 x=%d\n", nv->coord.x); ////DBG dbg(0,"---> 2 y=%d\n", nv->coord.y); // //DBG dbg(0,"vehicle_draw_002\n"); navit_vehicle_draw(this_, nv, NULL); // profile(0,"return 3\n"); return; } cursor_pc.x = nv->coord.x; cursor_pc.y = nv->coord.y; cursor_pc.pro = pro; if (this_->route) { if (tracking) route_set_position_from_tracking(this_->route, tracking, pro); else route_set_position(this_->route, &cursor_pc); } callback_list_call_attr_0(this_->attr_cbl, attr_position); // navit_textfile_debug_log(this_, "type=trackpoint_tracked"); if (this_->gui && nv->speed > MYSTERY_SPEED) navit_disable_suspend(); transform(this_->trans_cursor, pro, &nv->coord, &cursor_pnt, 1, 0, 0, NULL); if (this_->button_pressed != 1 && this_->follow_cursor && nv->follow_curr <= nv->follow && (nv->follow_curr == 1 || !transform_within_border(this_->trans_cursor, &cursor_pnt, this_->border))) { navit_set_center_cursor_draw(this_); ////DBG dbg(0,"---> xxCENTER\n"); ////DBG dbg(0,"---> 3 x=%d\n", nv->coord.x); ////DBG dbg(0,"---> 3 y=%d\n", nv->coord.y); ////DBG dbg(0,"---> 4 x=%d\n", cursor_pnt.x); ////DBG dbg(0,"---> 4 y=%d\n", cursor_pnt.y); //global_vehicle_pos_onscreen.x=cursor_pnt.x; //global_vehicle_pos_onscreen.y=cursor_pnt.y; } else { ////DBG dbg(0,"vehicle_draw_003\n"); navit_vehicle_draw(this_, nv, pnt); //global_vehicle_pos_onscreen.x=pnt->x; //global_vehicle_pos_onscreen.y=pnt->y; ////DBG dbg(0,"---> x=%d\n", pnt->x); ////DBG dbg(0,"---> y=%d\n", pnt->y); } if (nv->follow_curr > 1) nv->follow_curr--; else nv->follow_curr = nv->follow; callback_list_call_attr_2(this_->attr_cbl, attr_position_coord_geo, this_, nv->vehicle); /* Finally, if we reached our destination, stop navigation. */ if (this_->route) { switch (route_destination_reached(this_->route)) { case 1: route_remove_waypoint(this_->route); count = route_get_destinations(this_->route, pc, 16); // destination_file = bookmarks_get_destination_file(TRUE); // bookmarks_append_coord(this_->bookmarks, destination_file, pc, count, "former_itinerary_part", NULL, NULL, this_->recentdest_count); #ifdef HAVE_API_ANDROID // waypoint reached android_return_generic_int(5, 1); android_send_generic_text(1,"+*#O:Waypoint reached\n"); // say it navit_say(this_, _("Waypoint reached")); #endif break; case 2: navit_set_destination(this_, NULL, NULL, 0); // ** inform java that we reached our destination ** #ifdef HAVE_API_ANDROID android_return_generic_int(4, 1); android_send_generic_text(1,"+*#O:You have reached your destination\n"); // say it navit_say(this_, _("You have reached your destination")); #endif break; } } //profile(0,"return 5\n"); // //DBG dbg(0,"navit_vehicle_update_999\n"); } /** * Set the position of the vehicle * * @param navit The navit instance * @param c The coordinate to set as position * @returns nothing */ void navit_set_position(struct navit *this_, struct pcoord *c) { //DBG dbg(0,"EEnter\n"); if (this_->route) { route_set_position(this_->route, c); callback_list_call_attr_0(this_->attr_cbl, attr_position); } if (this_->ready == 3) navit_draw(this_); } static int navit_set_vehicleprofile(struct navit *this_, char *name) { ////DBG dbg(0,"EEnter\n"); struct attr attr; GList *l; l = this_->vehicleprofiles; while (l) { if (vehicleprofile_get_attr(l->data, attr_name, &attr, NULL)) { if (!strcmp(attr.u.str, name)) { this_->vehicleprofile = l->data; if (this_->route) route_set_profile(this_->route, this_->vehicleprofile); return 1; } } l = g_list_next(l); } return 0; } static void navit_set_vehicle(struct navit *this_, struct navit_vehicle *nv) { ////DBG dbg(0,"EEnter\n"); struct attr attr; this_->vehicle = nv; if (nv && vehicle_get_attr(nv->vehicle, attr_profilename, &attr, NULL)) { if (navit_set_vehicleprofile(this_, attr.u.str)) { return; } } if (!navit_set_vehicleprofile(this_, "car")) { /* We do not have a fallback "car" profile * so lets set any profile */ GList *l; l = this_->vehicleprofiles; if (l) { this_->vehicleprofile = l->data; if (this_->route) { route_set_profile(this_->route, this_->vehicleprofile); } } } } /** * Register a new vehicle * * @param navit The navit instance * @param v The vehicle instance * @returns 1 for success */ int navit_add_vehicle(struct navit *this_, struct vehicle *v) { ////DBG dbg(0,"EEnter\n"); struct navit_vehicle *nv=g_new0(struct navit_vehicle, 1); struct attr follow, active, animate; nv->vehicle = v; nv->follow = 0; nv->last.x = 0; nv->last.y = 0; nv->animate_cursor = 0; if ((vehicle_get_attr(v, attr_follow, &follow, NULL))) nv->follow = follow.u.num; nv->follow_curr = nv->follow; this_->vehicles = g_list_append(this_->vehicles, nv); if ((vehicle_get_attr(v, attr_active, &active, NULL)) && active.u.num) navit_set_vehicle(this_, nv); if ((vehicle_get_attr(v, attr_animate, &animate, NULL))) nv->animate_cursor = animate.u.num; nv->callback.type = attr_callback; nv->callback.u.callback = callback_new_attr_2(callback_cast(navit_vehicle_update), attr_position_coord_geo, this_, nv); vehicle_add_attr(nv->vehicle, &nv->callback); vehicle_set_attr(nv->vehicle, &this_->self); return 1; } struct gui * navit_get_gui(struct navit *this_) { return this_->gui; } struct transformation * navit_get_trans(struct navit *this_) { return this_->trans; } struct route * navit_get_route(struct navit *this_) { return this_->route; } struct navigation * navit_get_navigation(struct navit *this_) { return this_->navigation; } struct displaylist * navit_get_displaylist(struct navit *this_) { return this_->displaylist; } void navit_layout_switch(struct navit *n) { ////DBG dbg(0,"EEnter\n"); int currTs = 0; struct attr iso8601_attr, geo_attr, valid_attr, layout_attr; double trise, tset, trise_actual; struct layout *l; int year, month, day; if (navit_get_attr(n, attr_layout, &layout_attr, NULL) != 1) { return; //No layout - nothing to switch } if (!n->vehicle) return; l = layout_attr.u.layout; if (l->dayname || l->nightname) { //Ok, we know that we have profile to switch //Check that we aren't calculating too fast if (vehicle_get_attr(n->vehicle->vehicle, attr_position_time_iso8601, &iso8601_attr, NULL) == 1) { currTs = iso8601_to_secs(iso8601_attr.u.str); // dbg(1, "currTs: %u:%u\n", currTs % 86400 / 3600, ((currTs % 86400) % 3600) / 60); } if (currTs - (n->prevTs) < 60) { //We've have to wait a little return; } if (sscanf(iso8601_attr.u.str, "%d-%02d-%02dT", &year, &month, &day) != 3) return; if (vehicle_get_attr(n->vehicle->vehicle, attr_position_valid, &valid_attr, NULL) && valid_attr.u.num == attr_position_valid_invalid) { return; //No valid fix yet } if (vehicle_get_attr(n->vehicle->vehicle, attr_position_coord_geo, &geo_attr, NULL) != 1) { //No position - no sun return; } //We calculate sunrise anyway, cause it is needed both for day and for night if (__sunriset__(year, month, day, geo_attr.u.coord_geo->lng, geo_attr.u.coord_geo->lat, -5, 1, &trise, &tset) != 0) { //near the pole sun never rises/sets, so we should never switch profiles // dbg(1, "trise: %u:%u, sun never visible, never switch profile\n", HOURS(trise), MINUTES(trise)); n->prevTs = currTs; return; } trise_actual = trise; // dbg(1, "trise: %u:%u\n", HOURS(trise), MINUTES(trise)); if (l->dayname) { if ((HOURS(trise) * 60 + MINUTES(trise) == (currTs % 86400) / 60) || (n->prevTs == 0 && ((HOURS(trise) * 60 + MINUTES(trise) < (currTs % 86400) / 60)))) { //The sun is rising now! if (strcmp(l->name, l->dayname)) { navit_set_layout_by_name(n, l->dayname); } } } if (l->nightname) { if (__sunriset__(year, month, day, geo_attr.u.coord_geo->lng, geo_attr.u.coord_geo->lat, -5, 1, &trise, &tset) != 0) { //near the pole sun never rises/sets, so we should never switch profiles // dbg(1,"tset: %u:%u, sun always visible, never switch profile\n",HOURS(tset), MINUTES(tset)); n->prevTs = currTs; return; } // dbg(1, "tset: %u:%u\n", HOURS(tset), MINUTES(tset)); if (HOURS(tset) * 60 + MINUTES(tset) == ((currTs % 86400) / 60) || (n->prevTs == 0 && (((HOURS(tset) * 60 + MINUTES(tset) < (currTs % 86400) / 60)) || ((HOURS(trise_actual) * 60 + MINUTES(trise_actual) > (currTs % 86400) / 60))))) { //Time to sleep if (strcmp(l->name, l->nightname)) { navit_set_layout_by_name(n, l->nightname); } } } n->prevTs = currTs; } } int navit_set_vehicle_by_name(struct navit *n, const char *name) { ////DBG dbg(0,"EEnter\n"); struct vehicle *v; struct attr_iter *iter; struct attr vehicle_attr, name_attr; iter = navit_attr_iter_new(); while (navit_get_attr(n, attr_vehicle, &vehicle_attr, iter)) { v = vehicle_attr.u.vehicle; vehicle_get_attr(v, attr_name, &name_attr, NULL); if (name_attr.type == attr_name) { if (!strcmp(name, name_attr.u.str)) { navit_set_attr(n, &vehicle_attr); navit_attr_iter_destroy(iter); return 1; } } } navit_attr_iter_destroy(iter); return 0; } int navit_set_layout_by_name(struct navit *n, const char *name) { ////DBG dbg(0,"EEnter\n"); struct layout *l; struct attr_iter iter; struct attr layout_attr; iter.u.list = 0x00; if (navit_get_attr(n, attr_layout, &layout_attr, &iter) != 1) { return 0; //No layouts - nothing to do } if (iter.u.list == NULL) { return 0; } iter.u.list = g_list_first(iter.u.list); while (iter.u.list) { l = (struct layout*) iter.u.list->data; if (!strcmp(name, l->name)) { layout_attr.u.layout = l; layout_attr.type = attr_layout; navit_set_attr(n, &layout_attr); iter.u.list = g_list_first(iter.u.list); return 1; } iter.u.list = g_list_next(iter.u.list); } iter.u.list = g_list_first(iter.u.list); return 0; } void navit_disable_suspend() { ////DBG dbg(0,"EEnter\n"); gui_disable_suspend(global_navit->gui); callback_list_call_attr_0(global_navit->attr_cbl, attr_unsuspend); } int navit_block(struct navit *this_, int block) { ////DBG dbg(0,"EEnter\n"); if (block > 0) { this_->blocked |= 1; if (graphics_draw_cancel(this_->gra, this_->displaylist)) this_->blocked |= 2; return 0; } if ((this_->blocked & 2) || block < 0) { this_->blocked = 0; navit_draw(this_); return 1; } this_->blocked = 0; return 0; } void navit_destroy(struct navit *this_) { dbg(0,"EEnter\n"); struct mapset*ms; callback_list_call_attr_1(this_->attr_cbl, attr_destroy, this_); // //DBG dbg(0,"enter"); /* TODO: destroy objects contained in this_ */ if (this_->vehicle) vehicle_destroy(this_->vehicle->vehicle); if (this_->bookmarks) { dbg(0, "save position to file\n"); char *center_file = bookmarks_get_center_file(TRUE); bookmarks_write_center_to_file(this_->bookmarks, center_file); g_free(center_file); bookmarks_destroy(this_->bookmarks); dbg(0, "save position to file -> ready\n"); } dbg(0,"ex 001\n"); callback_destroy(this_->nav_speech_cb); dbg(0,"ex 002\n"); callback_destroy(this_->roadbook_callback); dbg(0,"ex 003\n"); callback_destroy(this_->popup_callback); dbg(0,"ex 004\n"); callback_destroy(this_->motion_timeout_callback); dbg(0,"ex 005\n"); callback_destroy(this_->progress_cb); dbg(0,"ex 006\n"); if (this_->gra) graphics_remove_callback(this_->gra, this_->resize_callback); callback_destroy(this_->resize_callback); dbg(0,"ex 007\n"); if (this_->gra) graphics_remove_callback(this_->gra, this_->button_callback); callback_destroy(this_->button_callback); dbg(0,"ex 008\n"); if (this_->gra) graphics_remove_callback(this_->gra, this_->motion_callback); callback_destroy(this_->motion_callback); dbg(0,"ex 009\n"); if (this_->gra) graphics_remove_callback(this_->gra, this_->predraw_callback); callback_destroy(this_->predraw_callback); dbg(0,"ex 010\n"); route_destroy(this_->route); dbg(0,"ex 011\n"); ms = navit_get_mapset(this_); dbg(0,"ex 012\n"); if (ms) mapset_destroy(ms); dbg(0,"ex 013\n"); graphics_free(this_->gra); dbg(0,"ex 014\n"); g_free(this_); dbg(0,"ex 015\n"); } /** @} */