#include "vehicleprofile.h"
#include "sunriset.h"
#include "bookmarks.h"
+#ifdef HAVE_API_WIN32_BASE
+#include <windows.h>
+#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
/* 2=No gui ok */
int border;
int imperial;
+ struct attr **attr_list;
};
struct gui *main_loop_gui;
struct attr_iter {
+ void *iter;
union {
GList *list;
struct mapset_handle *mapset_handle;
}
static GHashTable *cmd_int_var_hash = NULL;
+static GHashTable *cmd_attr_var_hash = NULL;
/**
- * Store key value pair for the command system
+ * 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)
static void
navit_cmd_set_int_var(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
{
+ 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))) {
- char*key;
- struct attr*val = g_new(struct attr,1);
+ 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)
+{
+ 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
*
}
}
+/**
+ * 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)
+{
+ 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;
+
+ //return invalid item on error
+ val->type = attr_none;
+ val->u.item = NULL;
+ 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);
+ if (it) {
+ val->type = attr_type_item_begin;
+ 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)
+{
+ 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)
+{
+ struct attr **list = g_new0(struct attr *,2);
+ if(!cmd_int_var_hash) {
+ struct attr*val = g_new0(struct attr,1);
+ cmd_attr_var_hash = g_hash_table_new(g_str_hash, g_str_equal);
+ 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
struct attr **list = g_new0(struct attr *,2);
if(!cmd_int_var_hash) {
struct attr*val = g_new0(struct attr,1);
+ cmd_int_var_hash = g_hash_table_new(g_str_hash, g_str_equal);
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;
+ list[0] = attr_dup(ret);
}
else {
struct attr*val = g_new0(struct attr,1);
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)
+static struct attr **
+navit_get_coord(struct navit *this, struct attr **in, struct pcoord *pc)
{
- struct pcoord pc;
- char *description=NULL;
if (!in)
- return;
+ return NULL;
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;
+ return NULL;
+ pc->pro = transform_get_projection(this->trans);
+ if (ATTR_IS_STRING(in[0]->type)) {
+ struct coord c;
+ coord_parse(in[0]->u.str, pc->pro, &c);
+ pc->x=c.x;
+ pc->y=c.y;
+ in++;
+ } else 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;
+ *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;
+ 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;
+ pc->x=in[0]->u.num;
+ pc->y=in[1]->u.num;
in+=2;
} else
+ return NULL;
+ return in;
+}
+
+static void
+navit_cmd_set_destination(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+ struct pcoord pc;
+ char *description=NULL;
+ in=navit_get_coord(this, in, &pc);
+ if (!in)
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_set_center(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
+{
+ struct pcoord pc;
+ in=navit_get_coord(this, in, &pc);
+ if (!in)
+ return;
+ navit_set_center(this, &pc, 0);
+}
+
static void
navit_cmd_fmt_coordinates(struct navit *this, char *function, struct attr **in, struct attr ***out, int *valid)
{
}
}
+/**
+ * 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)
+{
+ 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)
+{
+ 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(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(0,"status %i\n",st);
+ // example of blocking wait
+ //st=spawn_process_check_status(pi,1);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(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(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",command_cast(navit_cmd_set_center)},
{"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)},
{"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
this_->destination=*c;
this_->destination_valid=1;
- dbg(1, "navit->navit_set_destination %i\n", c->x);
- dbg(1, "navit->navit_set_destination %i\n", c->y);
-
+ dbg(1, "c=(%i,%i)\n", c->x,c->y);
+ destination_file = bookmarks_get_destination_file(TRUE);
+ bookmarks_append_coord(this_->former_destination, destination_file, c, type_former_destination, description, this_->recentdest_count);
+ g_free(destination_file);
} 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) {
route_set_destination(this_->route, c, async);
if (c && count) {
this_->destination=c[count-1];
this_->destination_valid=1;
+
+ destination_file = bookmarks_get_destination_file(TRUE);
+ bookmarks_append_coord(this_->former_destination, destination_file, c, type_former_itinerary, description, this_->recentdest_count);
+ g_free(destination_file);
} 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);
return active;
}
-static void
-navit_add_former_destinations_from_file(struct navit *this_)
-{
+struct map* read_former_destinations_from_file(){
+ struct attr type, data, flags, *attrs[4];
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_;
+ struct map *m;
type.type=attr_type;
type.u.str="textfile";
attrs[0]=&type; attrs[1]=&data; attrs[2]=&flags; attrs[3]=NULL;
- this_->former_destination=map_new(&parent, attrs);
+ m=map_new(NULL, attrs);
g_free(destination_file);
+ return m;
+}
+
+static void
+navit_add_former_destinations_from_file(struct navit *this_)
+{
+ struct item *item;
+ int i,valid=0,count=0;
+ struct coord c[16];
+ struct pcoord pc[16];
+ struct map_rect *mr;
+
+ this_->former_destination=read_former_destinations_from_file();
if (!this_->route || !navit_former_destinations_active(this_))
return;
mr=map_rect_new(this_->former_destination, NULL);
void
navit_say(struct navit *this_, char *text)
{
+ struct attr attr;
if(this_->speech) {
- speech_say(this_->speech, text);
+ 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)
+ speech_say(this_->speech, text);
}
}
{
dbg(0, "enter\n");
navigation_unregister_callback(this_->navigation, attr_navigation_long, this_->roadbook_callback);
+ callback_destroy(this_->roadbook_callback);
this_->roadbook_window=NULL;
this_->roadbook_callback=NULL;
}
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))) {
- map_add_callback(map, this_->progress_cb);
+ //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);
count++;
}
}
+ map_rect_destroy(mr);
}
if (! count)
return;
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)
{
case attr_orientation:
attr->u.num=this_->orientation;
break;
+ case attr_osd:
+ ret=attr_generic_get_attr(this_->attr_list, NULL, type, attr, iter?(struct attr_iter *)&iter->iter:NULL);
+ break;
case attr_osd_configuration:
attr->u.num=this_->osd_configuration;
break;
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)
+ if(active.u.num || !this_->layout_current) {
this_->layout_current=layout;
- return 1;
+ return 1;
+ }
+ return 0;
}
int
case attr_navigation:
this_->navigation=attr->u.navigation;
break;
+ case attr_osd:
+ this_->attr_list=attr_generic_add_attr(this_->attr_list, attr);
+ break;
case attr_recent_dest:
this_->recentdest_count = attr->u.num;
break;
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);
+ bookmarks_append_coord(this_->former_destination, destination_file, pc, type_former_itinerary_part, NULL, this_->recentdest_count);
break;
case 2:
navit_set_destination(this_, NULL, NULL, 0);
void
navit_destroy(struct navit *this_)
{
+ struct mapset*ms;
callback_list_call_attr_1(this_->attr_cbl, attr_destroy, this_);
/* TODO: destroy objects contained in this_ */
callback_destroy(this_->roadbook_callback);
callback_destroy(this_->popup_callback);
callback_destroy(this_->motion_timeout_callback);
+ callback_destroy(this_->progress_cb);
if(this_->gra)
graphics_remove_callback(this_->gra, this_->resize_callback);
callback_destroy(this_->resize_callback);
graphics_remove_callback(this_->gra, this_->predraw_callback);
callback_destroy(this_->predraw_callback);
route_destroy(this_->route);
+ ms = navit_get_mapset(this_);
+ if(ms)
+ mapset_destroy(ms);
graphics_free(this_->gra);
g_free(this_);
}