Modularized vehicle
authormartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Tue, 18 Dec 2007 19:40:39 +0000 (19:40 +0000)
committermartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Tue, 18 Dec 2007 19:40:39 +0000 (19:40 +0000)
git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk/navit@650 ffa7fe5e-494d-0410-b361-a75ebd5db220

23 files changed:
configure.in
src/Makefile.am
src/attr.c
src/attr.h
src/attr_def.h
src/cursor.c
src/cursor.h
src/graphics.c
src/graphics.h
src/gui/gtk/gui_gtk_action.c
src/gui/sdl/gui_sdl_window.cpp
src/navit.c
src/navit.h
src/plugin_def.h
src/vehicle.c
src/vehicle.h
src/vehicle/Makefile.am
src/vehicle/demo/Makefile.am [new file with mode: 0644]
src/vehicle/demo/vehicle_demo.c [new file with mode: 0644]
src/vehicle/file/vehicle_file.c
src/vehicle/gpsd/Makefile.am
src/vehicle/gpsd/vehicle_gpsd.c
src/xmlconfig.c

index f28139c..b7ecaf5 100644 (file)
@@ -397,6 +397,7 @@ src/speech/speech_dispatcher/Makefile
 src/vehicle/Makefile
 src/vehicle/file/Makefile
 src/vehicle/gpsd/Makefile
+src/vehicle/demo/Makefile
 src/xpm/Makefile
 src/maps/Makefile
 intl/Makefile
index f09a337..a437b31 100644 (file)
@@ -26,6 +26,6 @@ navit_SOURCES = attr.c callback.c compass.c coord.c country.c cursor.c data_wind
 
 osm2navit_SOURCES = osm2navit.c item.c debug.c zipfile.h
 
-navit_LDADD = @NAVIT_LIBS@ @GPSD_LIBS@ @ZLIB_LIBS@ -Lfib-1.1 -lfib
+navit_LDADD = @NAVIT_LIBS@ @ZLIB_LIBS@ -Lfib-1.1 -lfib
 
 osm2navit_LDADD = @NAVIT_LIBS@  @ZLIB_LIBS@
index 9668b55..8feecd7 100644 (file)
@@ -1,8 +1,10 @@
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 #include <glib.h>
 #include "debug.h"
 #include "item.h"
+#include "color.h"
 #include "attr.h"
 
 struct attr_name {
@@ -59,13 +61,34 @@ attr_new_from_text(const char *name, const char *value)
                break;
        default:
                if (attr >= attr_type_string_begin && attr <= attr_type_string_end) {
-                       ret->u.str=value;
+                       ret->u.str=(char *)value;
                        break;
                }
                if (attr >= attr_type_int_begin && attr <= attr_type_int_end) {
                        ret->u.num=atoi(value);
                        break;
                }
+               if (attr >= attr_type_color_begin && attr <= attr_type_color_end) {
+                       struct color *color=g_new0(struct color, 1);
+                       int r,g,b,a;
+                       ret->u.color=color;
+                       if(strlen(value)==7){
+                               sscanf(value,"#%02x%02x%02x", &r, &g, &b);
+                               color->r = (r << 8) | r;
+                               color->g = (g << 8) | g;
+                               color->b = (b << 8) | b;
+                               color->a = (65535);
+                       } else if(strlen(value)==9){
+                               sscanf(value,"#%02x%02x%02x%02x", &r, &g, &b, &a);
+                               color->r = (r << 8) | r;
+                               color->g = (g << 8) | g;
+                               color->b = (b << 8) | b;
+                               color->a = (a << 8) | a;
+                       } else {
+                               dbg(0,"color %s has unknown format\n",value);
+                       }
+                       break;
+               }
                dbg(1,"default\n");
                g_free(ret);
                ret=NULL;
@@ -125,5 +148,7 @@ attr_data_set(struct attr *attr, void *data)
 void
 attr_free(struct attr *attr)
 {
+       if (attr->type >= attr_type_color_begin && attr->type <= attr_type_color_end) 
+               g_free(attr->u.color);
        g_free(attr);
 }
index 0d0b7df..13b935c 100644 (file)
@@ -31,6 +31,12 @@ struct attr {
                int num;
                struct item *item;
                enum item_type item_type;
+               double * numd;
+               struct color *color;
+               struct coord_geo *coord_geo;
+               struct navit *navit;
+               struct callback *callback;
+               struct log *log;
        } u;
 };
 
index 07efff5..b8221ed 100644 (file)
@@ -24,8 +24,14 @@ ATTR(flush_size)
 ATTR(flush_time)
 ATTR(zipfile_ref)
 ATTR(country_id)
+ATTR(position_sats)
+ATTR(position_sats_used)
+ATTR(update)
+ATTR(follow)
+ATTR2(0x00028000,type_boolean_begin)
 /* boolean */
 ATTR(overwrite)
+ATTR(active)
 ATTR2(0x0002ffff,type_int_end)
 ATTR2(0x00030000,type_string_begin)
 ATTR(type)
@@ -63,5 +69,23 @@ ATTR(navigation_short)
 ATTR(navigation_long)
 ATTR(navigation_long_exact)
 ATTR(navigation_speech)
+ATTR(name)
+ATTR(source)
 ATTR2(0x0003ffff,type_string_end)
 ATTR(order_limit)
+ATTR2(0x00050000,type_double_start)
+ATTR(position_height)
+ATTR(position_speed)
+ATTR(position_direction)
+ATTR2(0x0005ffff,type_double_end)
+ATTR2(0x00060000,type_coord_geo_start)
+ATTR(position_coord_geo)
+ATTR2(0x0006ffff,type_coord_geo_end)
+ATTR2(0x00070000,type_color_begin)
+ATTR(color)
+ATTR2(0x0007ffff,type_color_end)
+ATTR2(0x00080000,type_object_begin)
+ATTR(navit)
+ATTR(log)
+ATTR(callback)
+ATTR2(0x0008ffff,type_object_end)
index ba7051a..109315e 100644 (file)
 struct cursor {
        struct graphics *gra;
        struct graphics_gc *cursor_gc;
-       struct transformation *trans;
        struct point cursor_pnt;
-       struct callback_list *update_cbl;
-       struct vehicle *v;
-       struct callback *vehicle_cb;
-       int dir;
-       int speed;
-       struct coord pos;
-       enum projection pro;
 };
 
-struct coord *
-cursor_pos_get(struct cursor *this)
-{
-       return &this->pos;
-#if 0
-       return vehicle_pos_get(this->v);
-#endif
-}
-
 
 void
-cursor_pos_set(struct cursor *this, struct coord *pos)
+cursor_draw(struct cursor *this_, struct point *pnt, int dir, int draw_dir, int force)
 {
-       this->pos=*pos;
-#if 0
-       return vehicle_pos_get(this->v);
-#endif
-}
-
-
-static void
-cursor_draw(struct cursor *this, struct point *pnt, int dir, int draw_dir)
-{
-       int x=this->cursor_pnt.x;
-       int y=this->cursor_pnt.y;
+       int x=this_->cursor_pnt.x;
+       int y=this_->cursor_pnt.y;
        int r=12,lw=2;
        double dx,dy;
        double fac1,fac2;
        struct point cpnt[3];
-       struct graphics *gra=this->gra;
+       struct graphics *gra=this_->gra;
 
-       if (pnt && x == pnt->x && y == pnt->y)
+       if (pnt && x == pnt->x && y == pnt->y && !force)
                return;
        if (!graphics_ready(gra))
                return;
-       cpnt[0]=this->cursor_pnt;
+       cpnt[0]=this_->cursor_pnt;
        cpnt[0].x-=r+lw;
        cpnt[0].y-=r+lw;
        graphics_draw_restore(gra, &cpnt[0], (r+lw)*2, (r+lw)*2);
        if (pnt) {
                graphics_draw_mode(gra, draw_mode_cursor);
-               this->cursor_pnt=*pnt;
+               this_->cursor_pnt=*pnt;
                x=pnt->x;
                y=pnt->y;
                cpnt[0].x=x;
                cpnt[0].y=y;
-               graphics_draw_circle(gra, this->cursor_gc, &cpnt[0], r*2);
+               graphics_draw_circle(gra, this_->cursor_gc, &cpnt[0], r*2);
                if (draw_dir) {
                        dx=sin(M_PI*dir/180.0);
                        dy=-cos(M_PI*dir/180.0);
@@ -96,162 +69,31 @@ cursor_draw(struct cursor *this, struct point *pnt, int dir, int draw_dir)
                        cpnt[1].y=y+dy*r;
                        cpnt[2].x=x-dx*fac1-dy*fac2;
                        cpnt[2].y=y-dy*fac1+dx*fac2;
-                       graphics_draw_lines(gra, this->cursor_gc, cpnt, 3);
+                       graphics_draw_lines(gra, this_->cursor_gc, cpnt, 3);
                } else {
                        cpnt[1]=cpnt[0];
-                       graphics_draw_lines(gra, this->cursor_gc, cpnt, 2);
+                       graphics_draw_lines(gra, this_->cursor_gc, cpnt, 2);
                }
                graphics_draw_mode(gra, draw_mode_end);
        }
 }
 
-void
-cursor_redraw(struct cursor *this)
-{
-       struct point pnt;
-       transform(this->trans, this->pro, &this->pos, &pnt);
-       cursor_draw(this, &pnt, this->dir-transform_get_angle(this->trans, 0), this->speed > 2.5);
-}
-
-#if 0
-static void
-cursor_map_reposition_screen(struct cursor *this, struct coord *c, double *dir, int x_new, int y_new)
-{
-       struct coord c_new;
-       struct transformation tr;
-       struct point pnt;
-       unsigned long scale;
-       long x,y;
-       int dir_i;
-       struct container *co=this->co;
-
-       if (dir)
-               dir_i=*dir;
-       else
-               dir_i=0;
-
-       pnt.x=co->trans->width-x_new;
-       pnt.y=co->trans->height-y_new;
-       graphics_get_view(co, &x, &y, &scale);
-       tr=*this->co->trans;
-       transform_setup(&tr, c->x, c->y, scale, dir_i);
-       transform_reverse(&tr, &pnt, &c_new);
-       printf("%lx %lx vs %lx %lx\n", c->x, c->y, c_new.x, c_new.y);
-       x=c_new.x;
-       y=c_new.y;
-       transform_set_angle(co->trans,dir_i);
-       graphics_set_view(co, &x, &y, &scale);
-}
-
-static void
-cursor_map_reposition(struct cursor *this, struct coord *c, double *dir)
-{
-       if (this->co->flags->orient_north) {
-               graphics_set_view(this->co, &c->x, &c->y, NULL);
-       } else {
-               cursor_map_reposition_screen(this, c, dir, this->co->trans->width/2, this->co->trans->height*0.8);
-       }
-}
-
-static int
-cursor_map_reposition_boundary(struct cursor *this, struct coord *c, double *dir, struct point *pnt)
-{
-       struct point pnt_new;
-       struct transformation *t=this->co->trans;
-
-       pnt_new.x=-1;
-       pnt_new.y=-1;
-       if (pnt->x < 0.1*t->width) {
-               pnt_new.x=0.8*t->width;
-               pnt_new.y=t->height/2;
-       }
-       if (pnt->x > 0.9*t->width) {
-               pnt_new.x=0.2*t->width;
-               pnt_new.y=t->height/2;
-       }
-       if (pnt->y < (this->co->flags->orient_north ? 0.1 : 0.5)*t->height) {
-               pnt_new.x=t->width/2;
-               pnt_new.y=0.8*t->height;
-       }
-       if (pnt->y > 0.9*t->height) {
-               pnt_new.x=t->width/2;
-               pnt_new.y=0.2*t->height;
-       }
-       if (pnt_new.x != -1) {
-               if (this->co->flags->orient_north) {
-                       cursor_map_reposition_screen(this, c, NULL, pnt_new.x, pnt_new.y);
-               } else {
-                       cursor_map_reposition(this, c, dir);
-               }
-               return 1;
-       }
-       return 0;
-}
-
-#endif
-
-int
-cursor_get_dir(struct  cursor *this)
-{
-       return this->dir;
-}
-
-int
-cursor_get_speed(struct cursor *this)
-{
-       return this->speed;
-}
-
-static void
-cursor_update(struct cursor *this, struct vehicle *v)
-{
-       struct point pnt;
-       struct coord *pos;
-       double *dir;
-       double *speed;
-       enum projection pro;
-
-       if (v) {
-               pos=vehicle_pos_get(v); 
-               dir=vehicle_dir_get(v);
-               speed=vehicle_speed_get(v);
-               pro=vehicle_projection(v);
-               this->dir=*dir;
-               this->speed=*speed;
-               this->pos=*pos;
-               this->pro=pro;
-               callback_list_call_1(this->update_cbl, this);
-               transform(this->trans, pro, &this->pos, &pnt);
-               cursor_draw(this, &pnt, *dir-transform_get_angle(this->trans, 0), *speed > 2.5);
-       }
-#if 0
-       compass_draw(this->co->compass, this->co);
-#endif
-}
-
 struct cursor *
-cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t)
+cursor_new(struct graphics *gra, struct color *c)
 {
-       dbg(2,"enter gra=%p v=%p c=%p t=%p\n", gra, v, c, t);
+       dbg(2,"enter gra=%p c=%p\n", gra, c);
        struct cursor *this=g_new(struct cursor,1);
-#if 0
-       this->offscreen_cbl=callback_list_new();
-#endif
-       this->update_cbl=callback_list_new();
        this->gra=gra;
-       this->trans=t;
        this->cursor_gc=graphics_gc_new(gra);
-       this->v=v;
        graphics_gc_set_foreground(this->cursor_gc, c);
        graphics_gc_set_linewidth(this->cursor_gc, 2);
-       this->vehicle_cb=callback_new_1(callback_cast(cursor_update), this);
-       vehicle_callback_add(v, this->vehicle_cb);
        dbg(2,"ret=%p\n", this);
        return this;
 }
 
 void
-cursor_add_callback(struct cursor *this, struct callback *cb)
+cursor_destroy(struct cursor *this_)
 {
-       callback_list_add(this->update_cbl, cb);
+       graphics_gc_destroy(this_->cursor_gc);
+       g_free(this_);
 }
index ee64d8f..7e7ec5e 100644 (file)
@@ -2,20 +2,13 @@
 #define NAVIT_CURSOR_H
 
 /* prototypes */
-struct callback;
 struct color;
-struct coord;
 struct cursor;
 struct graphics;
-struct transformation;
-struct vehicle;
-struct coord *cursor_pos_get(struct cursor *this);
-void cursor_pos_set(struct cursor *this, struct coord *pos);
-void cursor_redraw(struct cursor *this);
-int cursor_get_dir(struct cursor *this);
-int cursor_get_speed(struct cursor *this);
-struct cursor *cursor_new(struct graphics *gra, struct vehicle *v, struct color *c, struct transformation *t);
-void cursor_add_callback(struct cursor *this, struct callback *cb);
+struct point;
+void cursor_draw(struct cursor *this_, struct point *pnt, int dir, int draw_dir, int force);
+struct cursor *cursor_new(struct graphics *gra, struct color *c);
+void cursor_destroy(struct cursor *this_);
 /* end of prototypes */
 
 #endif
index 87ac508..5904c4e 100644 (file)
@@ -115,6 +115,12 @@ graphics_gc_new(struct graphics *gra)
 }
 
 void
+graphics_gc_destroy(struct graphics_gc *gc)
+{
+       gc->meth.gc_destroy(gc->priv);
+}
+
+void
 graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c)
 {
        gc->meth.gc_set_foreground(gc->priv, c);
index a657e61..33ccd18 100644 (file)
@@ -96,8 +96,6 @@ struct graphics_gc;
 struct graphics_image;
 struct item;
 struct point;
-struct route;
-struct transformation;
 struct graphics *graphics_new(const char *type, struct attr **attrs);
 struct graphics *graphics_overlay_new(struct graphics *parent, struct point *p, int w, int h);
 void graphics_init(struct graphics *this_);
@@ -107,6 +105,7 @@ void graphics_register_button_callback(struct graphics *this_, void (*callback)(
 void graphics_register_motion_callback(struct graphics *this_, void (*callback)(void *data, struct point *p), void *data);
 struct graphics_font *graphics_font_new(struct graphics *gra, int size);
 struct graphics_gc *graphics_gc_new(struct graphics *gra);
+void graphics_gc_destroy(struct graphics_gc *gc);
 void graphics_gc_set_foreground(struct graphics_gc *gc, struct color *c);
 void graphics_gc_set_background(struct graphics_gc *gc, struct color *c);
 void graphics_gc_set_linewidth(struct graphics_gc *gc, int width);
@@ -118,9 +117,7 @@ void graphics_draw_circle(struct graphics *this_, struct graphics_gc *gc, struct
 void graphics_draw_rectangle(struct graphics *this_, struct graphics_gc *gc, struct point *p, int w, int h);
 void display_add(struct displaylist *displaylist, struct item *item, int count, struct point *pnt, char *label);
 int graphics_ready(struct graphics *this_);
-void graphics_displaylist_draw(struct graphics *gra, struct displaylist *displaylist, struct transformation *trans, GList *layouts, struct route *route);
 void graphics_displaylist_move(struct displaylist *displaylist, int dx, int dy);
-void graphics_draw(struct graphics *gra, struct displaylist *displaylist, GList *mapsets, struct transformation *trans, GList *layouts, struct route *route);
 struct displaylist_handle *graphics_displaylist_open(struct displaylist *displaylist);
 struct displayitem *graphics_displaylist_next(struct displaylist_handle *dlh);
 void graphics_displaylist_close(struct displaylist_handle *dlh);
index 647e9b9..2a7540a 100644 (file)
@@ -222,7 +222,7 @@ static GtkActionEntry debug_entries[] =
        { "VisiblePolysAction", NULL, _n("VisiblePolys"), NULL, NULL, G_CALLBACK(visible_polys_action) },
        { "VisibleStreetsAction", NULL, _n("VisibleStreets"), NULL, NULL, G_CALLBACK(visible_streets_action) },
        { "VisiblePointsAction", NULL, _n("VisiblePoints"), NULL, NULL, G_CALLBACK(visible_points_action) },
-       { "VisiblePointsAction", NULL, _n("RouteGraph"), NULL, NULL, G_CALLBACK(visible_routegraph_action) }
+       { "VisibleRouteGraphAction", NULL, _n("RouteGraph"), NULL, NULL, G_CALLBACK(visible_routegraph_action) }
 };
 
 static guint n_debug_entries = G_N_ELEMENTS (debug_entries);
@@ -371,6 +371,7 @@ static char layout[] =
                                <menuitem name=\"Visible Polys\" action=\"VisiblePolysAction\" />\
                                <menuitem name=\"Visible Streets\" action=\"VisibleStreetsAction\" />\
                                <menuitem name=\"Visible Points\" action=\"VisiblePointsAction\" />\
+                               <menuitem name=\"Visible Routegraph\" action=\"VisibleRouteGraphAction\" />\
                                <placeholder name=\"DataMenuAdditions\" />\
                        </menu>\
                        <menu name=\"Route\" action=\"RouteMenuAction\">\
index 143c1d0..19f82a9 100644 (file)
@@ -712,16 +712,25 @@ static void init_sdlgui(char * skin_layout,int fullscreen,int tilt)
 
 static void vehicle_callback_handler( struct navit *nav, struct vehicle *v){
        char buffer [50];
-       double  speed=*vehicle_speed_get(v);
-       sprintf (buffer, "%02.02f km/h", speed);
+       struct attr attr;
+       int sats=0, sats_used=0;
+
+       if (vehicle_position_attr_get(v, attr_position_speed, &attr))
+               sprintf (buffer, "%02.02f km/h", *attr.u.numd);
+       else
+               strcpy (buffer, "N/A");
        CEGUI::WindowManager::getSingleton().getWindow("OSD/SpeedoMeter")->setText(buffer);
 
-       double  height=*vehicle_height_get(v);
-       sprintf (buffer, "%.0f m", height);
+       if (vehicle_position_attr_get(v, attr_position_speed, &attr))
+               sprintf (buffer, ".0f m", *attr.u.numd);
+       else
+               strcpy (buffer, "N/A");
        CEGUI::WindowManager::getSingleton().getWindow("OSD/Altimeter")->setText(buffer);
 
-       int sats=*vehicle_sats_get(v);
-       int sats_used=*vehicle_sats_used_get(v);
+       if (vehicle_position_attr_get(v, attr_position_sats, &attr))
+               sats=attr.u.num;
+       if (vehicle_position_attr_get(v, attr_position_sats_used, &attr))
+               sats_used=attr.u.num;
 //     printf(" sats : %i, used %i: \n",sats,sats_used);
        // Sat image hardcoded for now. may break the TaharezSkin
        // setProperty("Image", CEGUI::PropertyHelper::imageToString( yourImageSet->getImage( "yourImageName" ) ) );
index 711804a..d1a01aa 100644 (file)
@@ -44,14 +44,18 @@ struct navit_vehicle {
        int update_curr;
        int follow;
        int follow_curr;
+       struct coord coord;
+       int dir;
+       int speed;
        struct color c;
        struct menu *menu;
        struct cursor *cursor;
        struct vehicle *vehicle;
-       struct callback *update_cb;
+       struct attr callback;
 };
 
 struct navit {
+       struct attr self;
        GList *mapsets;
        GList *layouts;
        struct gui *gui;
@@ -95,7 +99,8 @@ struct navit {
 
 struct gui *main_loop_gui;
 
-static void navit_cursor_update(struct navit *this_, struct cursor *cursor);
+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);
 
 void
 navit_add_mapset(struct navit *this_, struct mapset *ms)
@@ -132,7 +137,7 @@ navit_draw(struct navit *this_)
        l=this_->vehicles;
        while (l) {
                nv=l->data;
-               cursor_redraw(nv->cursor);
+               navit_vehicle_draw(this_, nv, NULL);
                l=g_list_next(l);
        }
        this_->ready=1;
@@ -307,6 +312,8 @@ navit_new(struct pcoord *center, int zoom)
        FILE *f;
 
        main_add_navit(this_);
+       this_->self.type=attr_navit;
+       this_->self.u.navit=this_;
        this_->vehicle_cbl=callback_list_new();
        this_->init_cbl=callback_list_new();
 
@@ -977,12 +984,13 @@ navit_init(struct navit *this_)
        graphics_init(this_->gra);
        l=this_->vehicles;
        while (l) {
-               dbg(0,"parsed one vehicle\n");
+               dbg(1,"parsed one vehicle\n");
                nv=l->data;
-               nv->cursor=cursor_new(this_->gra, nv->vehicle, &nv->c, this_->trans);
-               nv->update_cb=callback_new_1(callback_cast(navit_cursor_update), this_);
-               cursor_add_callback(nv->cursor, nv->update_cb);
-               vehicle_set_navit(nv->vehicle, this_);
+               nv->cursor=cursor_new(this_->gra, &nv->c);
+               nv->callback.type=attr_callback;
+               nv->callback.u.callback=callback_new_2(callback_cast(navit_vehicle_update), this_, nv);
+               vehicle_add_attr(nv->vehicle, &nv->callback, NULL);
+               vehicle_set_attr(nv->vehicle, &this_->self, NULL);
                l=g_list_next(l);
        }
        if (this_->mapsets) {
@@ -1106,68 +1114,90 @@ navit_toggle_orient_north(struct navit *this_)
  */
 
 static void
-navit_cursor_update(struct navit *this_, struct cursor *cursor)
+navit_vehicle_draw(struct navit *this_, struct navit_vehicle *nv, struct point *pnt)
 {
-       struct point pnt;
-       struct coord *cursor_c=cursor_pos_get(cursor);
-       struct pcoord pc;
-       int dir=cursor_get_dir(cursor);
-       int speed=cursor_get_speed(cursor);
+       struct point pnt2;
        enum projection pro;
-       int border=30;
-
-       if (!this_->vehicle || this_->vehicle->cursor != cursor)
-               return;
+       if (pnt) 
+               pnt2=*pnt;
+       else {
+               pro=transform_get_projection(this_->trans);
+               transform(this_->trans, pro, &nv->coord, &pnt2);
+       }
+#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
+}
 
-       cursor_c=cursor_pos_get(cursor);
-       dir=cursor_get_dir(cursor);
-       speed=cursor_get_speed(cursor);
-       pro=vehicle_projection(this_->vehicle->vehicle);
+static void
+navit_vehicle_update(struct navit *this_, struct navit_vehicle *nv)
+{
+       struct attr attr_dir, attr_speed, attr_pos;
+       struct pcoord cursor_pc;
+       struct point cursor_pnt, *pnt=&cursor_pnt;
+       enum projection pro;
+       int border=16;
 
-       /* This transform is useless cursor and vehicle are in the same projection */
-       if (!transform(this_->trans, pro, cursor_c, &pnt) || !transform_within_border(this_->trans, &pnt, border)) {
-               if (!this_->cursor_flag)
-                       return;
-               if (this_->orient_north_flag)
-                       navit_set_center_cursor(this_, cursor_c, 0, 50 - 30.*sin(M_PI*dir/180.), 50 + 30.*cos(M_PI*dir/180.));
-               else
-                       navit_set_center_cursor(this_, cursor_c, dir, 50, 80);
-               transform(this_->trans, pro, cursor_c, &pnt);
+       if (! vehicle_position_attr_get(nv->vehicle, attr_position_direction, &attr_dir) ||
+           ! vehicle_position_attr_get(nv->vehicle, attr_position_speed, &attr_speed) ||
+           ! vehicle_position_attr_get(nv->vehicle, attr_position_coord_geo, &attr_pos))
+               return;
+       nv->dir=*attr_dir.u.numd;
+       nv->speed=*attr_speed.u.numd;
+       pro=transform_get_projection(this_->trans);
+       transform_from_geo(pro, attr_pos.u.coord_geo, &nv->coord);
+       if (nv != this_->vehicle) {
+               navit_vehicle_draw(this_, nv, NULL);
+               return;
        }
 
-       if (this_->pid && speed > 2)
-               kill(this_->pid, SIGWINCH);
        if (this_->tracking && this_->tracking_flag) {
-               struct coord c=*cursor_c;
-               if (tracking_update(this_->tracking, &c, dir)) {
-                       cursor_c=&c;
-                       cursor_pos_set(cursor, cursor_c);
-                       if (this_->route && this_->vehicle->update_curr == 1) 
+               if (tracking_update(this_->tracking, &nv->coord, nv->dir)) {
+                       if (this_->route && nv->update_curr == 1) 
                                route_set_position_from_tracking(this_->route, this_->tracking);
                }
        } else {
-               if (this_->route && this_->vehicle->update_curr == 1) {
-                       pc.pro = pro;
-                       pc.x = cursor_c->x;
-                       pc.y = cursor_c->y;
-                       route_set_position(this_->route, &pc);
+               if (this_->route && nv->update_curr == 1) {
+                       cursor_pc.pro = pro;
+                       cursor_pc.x = nv->coord.x;
+                       cursor_pc.y = nv->coord.y;
+                       route_set_position(this_->route, &cursor_pc);
+               }
+       }
+
+       if ((!transform(this_->trans, pro, &nv->coord, &cursor_pnt) || !transform_within_border(this_->trans, &cursor_pnt, border))) {
+               if (!this_->cursor_flag)
+                       return;
+               if (nv->follow_curr != 1) {
+                       if (this_->orient_north_flag)
+                               navit_set_center_cursor(this_, &nv->coord, 0, 50 - 30.*sin(M_PI*nv->dir/180.), 50 + 30.*cos(M_PI*nv->dir/180.));
+                       else
+                               navit_set_center_cursor(this_, &nv->coord, nv->dir, 50, 80);
+                       pnt=NULL;
                }
        }
-       if (this_->route && this_->vehicle->update_curr == 1)
+
+       if (this_->pid && nv->speed > 2)
+               kill(this_->pid, SIGWINCH);
+       if (this_->route && nv->update_curr == 1)
                navigation_update(this_->navigation, this_->route);
-       if (this_->cursor_flag) {
-               if (this_->vehicle->follow_curr == 1)
-                       navit_set_center_cursor(this_, cursor_c, dir, 50, 80);
+       if (this_->cursor_flag && nv->follow_curr == 1) {
+               navit_set_center_cursor(this_, &nv->coord, nv->dir, 50, 80);
+               pnt=NULL;
        }
-       if (this_->vehicle->follow_curr > 1)
-               this_->vehicle->follow_curr--;
+       if (nv->follow_curr > 1)
+               nv->follow_curr--;
        else
-               this_->vehicle->follow_curr=this_->vehicle->follow;
-       if (this_->vehicle->update_curr > 1)
-               this_->vehicle->update_curr--;
+               nv->follow_curr=nv->follow;
+       if (nv->update_curr > 1)
+               nv->update_curr--;
        else
-               this_->vehicle->update_curr=this_->vehicle->update;
-       callback_list_call_2(this_->vehicle_cbl, this_, this_->vehicle->vehicle);
+               nv->update_curr=nv->update;
+       callback_list_call_2(this_->vehicle_cbl, this_, nv->vehicle);
+       if (pnt) 
+               navit_vehicle_draw(this_, nv, pnt);
 }
 
 /**
@@ -1202,16 +1232,24 @@ navit_set_position(struct navit *this_, struct pcoord *c)
  * @returns a vehicle instance
  */
 struct navit_vehicle *
-navit_add_vehicle(struct navit *this_, struct vehicle *v, const char *name, struct color *c, int update, int follow)
+navit_add_vehicle(struct navit *this_, struct vehicle *v, struct attr **attrs)
 {
        struct navit_vehicle *nv=g_new0(struct navit_vehicle, 1);
+       struct attr *name,*update,*follow,*color,*active;
        nv->vehicle=v;
-       nv->name=g_strdup(name);
-       nv->update_curr=nv->update=update;
-       nv->follow_curr=nv->follow=follow;
-       nv->c=*c;
-
+       if ((name=attr_search(attrs, NULL, attr_name)))
+               nv->name=g_strdup(name->u.str);
+       if ((update=attr_search(attrs, NULL, attr_update)))
+               nv->update_curr=nv->update=update->u.num;
+       if ((follow=attr_search(attrs, NULL, attr_follow)))
+               nv->follow_curr=nv->follow=follow->u.num;
+       if ((color=attr_search(attrs, NULL, attr_color))) {
+               nv->c=*(color->u.color);
+       }
        this_->vehicles=g_list_append(this_->vehicles, nv);
+       if ((active=attr_search(attrs, NULL, attr_active)) && active->u.num) 
+               navit_set_vehicle(this_, nv);
+
        return nv;
 }
 
index ed7cdaf..812d73d 100644 (file)
@@ -7,11 +7,9 @@ extern "C" {
 extern struct gui *main_loop_gui;
 /* prototypes */
 enum item_type;
-enum projection;
+struct attr;
 struct callback;
-struct color;
 struct coord;
-struct pcoord;
 struct displaylist;
 struct graphics;
 struct gui;
@@ -22,6 +20,7 @@ struct navigation;
 struct navit;
 struct navit_vehicle;
 struct navit_window_items;
+struct pcoord;
 struct point;
 struct route;
 struct speech;
@@ -65,7 +64,7 @@ void navit_toggle_cursor(struct navit *this_);
 void navit_toggle_tracking(struct navit *this_);
 void navit_toggle_orient_north(struct navit *this_);
 void navit_set_position(struct navit *this_, struct pcoord *c);
-struct navit_vehicle *navit_add_vehicle(struct navit *this_, struct vehicle *v, const char *name, struct color *c, int update, int follow);
+struct navit_vehicle *navit_add_vehicle(struct navit *this_, struct vehicle *v, struct attr **attrs);
 void navit_add_vehicle_cb(struct navit *this_, struct callback *cb);
 void navit_remove_vehicle_cb(struct navit *this_, struct callback *cb);
 void navit_add_init_cb(struct navit *this_, struct callback *cb);
@@ -82,7 +81,6 @@ struct navigation *navit_get_navigation(struct navit *this_);
 struct displaylist *navit_get_displaylist(struct navit *this_);
 void navit_destroy(struct navit *this_);
 void navit_toggle_routegraph_display(struct navit *nav);
-
 /* end of prototypes */
 #ifdef __cplusplus
 }
index 831dfc9..aadf732 100644 (file)
@@ -1,11 +1,12 @@
 enum projection;
 struct attr;
+struct navit;
+struct callback_list;
 PLUGIN_FUNC1(draw, struct container *, co)
 PLUGIN_FUNC3(popup, struct container *, map, struct popup *, p, struct popup_item **, list)
-struct navit;
 PLUGIN_TYPE(graphics, (struct graphics_methods *meth, struct attr **attrs)) 
 PLUGIN_TYPE(gui, (struct navit *nav, struct gui_methods *meth, struct attr **attrs)) 
 PLUGIN_TYPE(map, (struct map_methods *meth, struct attr **attrs)) 
 PLUGIN_TYPE(osd, (struct navit *nav, struct osd_methods *meth, struct attr **attrs))
 PLUGIN_TYPE(speech, (char *data, struct speech_methods *meth)) 
-PLUGIN_TYPE(vehicle, (struct vehicle_methods *meth)) 
+PLUGIN_TYPE(vehicle, (struct vehicle_methods *meth, struct callback_list *cbl, struct attr **attrs)) 
index 7467ad2..8d656e1 100644 (file)
-#include "config.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <termios.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <math.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 #include <glib.h>
-#ifdef HAVE_LIBGPS
-#include <gps.h>
-#endif
+#include <string.h>
+#include "config.h"
 #include "debug.h"
 #include "coord.h"
-#include "callback.h"
-#include "transform.h"
-#include "projection.h"
-#include "statusbar.h"
-#include "navit.h"
 #include "item.h"
 #include "log.h"
+#include "callback.h"
+#include "plugin.h"
 #include "vehicle.h"
-#include "item.h"
-#include "route.h"
-
-static void disable_watch(struct vehicle *this_);
-static void enable_watch(struct vehicle *this_);
-
- /* #define INTERPOLATION_TIME 50 */
-
-struct callback {
-       void (*func)(struct vehicle *, void *data);
-       void *data;
-};
 
 struct vehicle {
-       char *url;
-       GIOChannel *iochan;
-       guint watch;
-       int is_file;
-       int is_pipe;
-       int timer_count;
-       int status; // Do we have a fix? 0=no 1=yes, without DGPS 2=yes, with DGPS
-       int sats,sats_used;
-       struct coord_geo geo;
-       double height;
-       double dir,speed;
-       double time;
-       double pdop;
-       struct coord current_pos;
-       struct coord_d curr;
-       struct coord_d delta;
-
-       double speed_last;
-       int fd;
-       FILE *file;
-#ifdef HAVE_LIBGPS
-       struct gps_data_t *gps;
-#endif
-#define BUFFER_SIZE 256
-       char buffer[BUFFER_SIZE];
-       int buffer_pos;
-
+       struct vehicle_priv *priv;
+       struct vehicle_methods meth;
        struct callback_list *cbl;
-       struct vehicle *child;
-       struct callback *child_cb;
-
-       int magic;
-       int is_udp;
-       int interval;
-       struct sockaddr_in rem;
        struct log *nmea_log, *gpx_log, *textfile_log;
-
-       struct navit *navit;
 };
 
-// FIXME : this_ is an ugly hack (dixit cp15 ;) )
-struct vehicle *vehicle_last;
-
-#if INTERPOLATION_TIME
-static int
-vehicle_timer(gpointer t)
-{
-       struct vehicle *this_=t;        
-/*     if (this_->timer_count++ < 1000/INTERPOLATION_TIME) { */
-               if (this_->delta.x || this_->delta.y) {
-                       this_->curr.x+=this_->delta.x;
-                       this_->curr.y+=this_->delta.y;  
-                       this_->current_pos.x=this_->curr.x;
-                       this_->current_pos.y=this_->curr.y;
-                       if (this_->callback_func)
-                               (*this_->callback_func)(this_, this_->callback_data);
-               }
-/*     } */
-       return TRUE; 
-}
-#endif
-
-enum projection
-vehicle_projection(struct vehicle *this_)
-{
-       return projection_mg;
-}
-
-struct coord *
-vehicle_pos_get(struct vehicle *this_)
-{
-       return &this_->current_pos;
-}
-
-double *
-vehicle_speed_get(struct vehicle *this_)
-{
-       return &this_->speed;
-}
-
-double *
-vehicle_height_get(struct vehicle *this_)
-{
-       return &this_->height;
-}
-double *
-vehicle_dir_get(struct vehicle *this_)
-{
-       return &this_->dir;
-}
-
-int *
-vehicle_status_get(struct vehicle *this_)
-{
-       return &this_->status;
-}
-
-int *
-vehicle_sats_get(struct vehicle *this_)
-{
-       return &this_->sats;
-}
-
-int *
-vehicle_sats_used_get(struct vehicle *this_)
-{
-       return &this_->sats_used;
-}
-
-double *
-vehicle_pdop_get(struct vehicle *this_)
-{
-       return &this_->pdop;
-}
-
-void
-vehicle_set_position(struct vehicle *this_, struct coord *pos)
-{
-       this_->current_pos=*pos;
-       this_->curr.x=this_->current_pos.x;
-       this_->curr.y=this_->current_pos.y;
-       this_->delta.x=0;
-       this_->delta.y=0;
-       callback_list_call_1(this_->cbl, this_);
-}
-
 static int
-enable_watch_timer(gpointer t)
-{
-       struct vehicle *this_=t;
-       enable_watch(this_);
-       
-       return FALSE;
-}
-
-// FIXME Should this_ function be static ?
-void
-vehicle_set_navit(struct vehicle *this_,struct navit *nav) {
-       dbg(0,"vehicle_set_navit called\n");
-       this_->navit=nav;
-}
-
-static void
-vehicle_parse_gps(struct vehicle *this_, char *buffer)
-{
-       char *p,*item[16];
-       double lat,lng,scale,speed;
-       int i,bcsum;
-       int len=strlen(buffer);
-       unsigned char csum=0;
-
-       dbg(1, "buffer='%s' ", buffer);
-       if (this_->nmea_log) {
-               log_write(this_->nmea_log, buffer, len);
-               log_write(this_->nmea_log, "\n", 1);
-       }
-       for (;;) {
-               if (len < 4) {
-                       dbg(0, "too short\n");
-                       return;
-               }
-               if (buffer[len-1] == '\r' || buffer[len-1] == '\n')
-                       buffer[--len]='\0';
-               else
-                       break;
-       }
-       if (buffer[0] != '$') {
-               dbg(0, "no leading $\n");
-               return;
-       }
-       if (buffer[len-3] != '*') {
-               dbg(0, "no *XX\n");
-               return;
-       }
-       for (i = 1 ; i < len-3 ; i++) {
-               csum ^= (unsigned char)(buffer[i]);
-       }
-       if (!sscanf(buffer+len-2, "%x", &bcsum)) {
-               dbg(0, "no checksum\n");
-               return;
-       }
-       if (bcsum != csum) {
-               dbg(0, "wrong checksum\n");
-               return;
-       }
-
-       if (!strncmp(buffer,"$GPGGA",6)) {
-               /* $GPGGA,184424.505,4924.2811,N,01107.8846,E,1,05,2.5,408.6,M,,,,0000*0C
-                       UTC of Fix,Latitude,N/S,Longitude,E/W,Quality,Satelites,HDOP,Altitude,"M"
-               */
-               i=0;
-               p=buffer;
-               while (i < 16) {
-                       item[i++]=p;
-                       while (*p && *p != ',') 
-                               p++;    
-                       if (! *p) break;
-                       *p++='\0';
-               }
-
-               sscanf(item[2],"%lf",&lat);
-               this_->geo.lat=floor(lat/100);
-               lat-=this_->geo.lat*100;
-               this_->geo.lat+=lat/60;
-
-               sscanf(item[4],"%lf",&lng);
-               this_->geo.lng=floor(lng/100);
-               lng-=this_->geo.lng*100;
-               this_->geo.lng+=lng/60;
-
-               sscanf(item[6],"%d",&this_->status);
-               sscanf(item[7],"%d",&this_->sats);
-               sscanf(item[9],"%lf",&this_->height);
-       
-               if (this_->gpx_log) {
-                       char buffer[256];
-                       sprintf(buffer,"<trkpt lat=\"%f\" lon=\"%f\" />\n",this_->geo.lat,this_->geo.lng);
-                       log_write(this_->gpx_log, buffer, strlen(buffer));
-                       
-               }
-               if (this_->textfile_log) {
-                       char buffer[256];
-                       sprintf(buffer,"%f %f type=trackpoint\n",this_->geo.lng,this_->geo.lat);
-                       log_write(this_->textfile_log, buffer, strlen(buffer));
-               }
-               transform_from_geo(projection_mg, &this_->geo, &this_->current_pos);
-                       
-               this_->curr.x=this_->current_pos.x;
-               this_->curr.y=this_->current_pos.y;
-               this_->timer_count=0;
-               callback_list_call_1(this_->cbl, this_);
-               if (this_->is_file) {
-                       disable_watch(this_);
-                       g_timeout_add(1000, enable_watch_timer, this_);
-               }
-       }
-       if (!strncmp(buffer,"$GPVTG",6)) {
-               /* $GPVTG,143.58,T,,M,0.26,N,0.5,K*6A 
-                         Course Over Ground Degrees True,"T",Course Over Ground Degrees Magnetic,"M",
-                         Speed in Knots,"N","Speed in KM/H","K",*CHECKSUM */
-               
-               i=0;
-               p=buffer;
-               while (i < 16) {
-                       item[i++]=p;
-                       while (*p && *p != ',') 
-                               p++;    
-                       if (! *p) break;
-                               *p++='\0';
-               }
-               sscanf(item[1],"%lf",&this_->dir);
-               sscanf(item[7],"%lf",&this_->speed);
-
-               scale=transform_scale(this_->current_pos.y);
-               speed=this_->speed+(this_->speed-this_->speed_last)/2;
-#ifdef INTERPOLATION_TIME
-               this_->delta.x=sin(M_PI*this_->dir/180)*speed*scale/3600*INTERPOLATION_TIME;
-               this_->delta.y=cos(M_PI*this_->dir/180)*speed*scale/3600*INTERPOLATION_TIME;
-#endif
-               this_->speed_last=this_->speed;
-       }
-       if (!strncmp(buffer,"$GPRMC",6)) {
-               /* $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A */
-               /* Time,Active/Void,lat,N/S,long,W/E,speed in knots,track angle,date,magnetic variation */
-               i=0;
-               p=buffer;
-               while (i < 16) {
-                       item[i++]=p;
-                       while (*p && *p != ',') 
-                               p++;    
-                       if (! *p) break;
-                       *p++='\0';
-               }
-               sscanf(item[8],"%lf",&this_->dir);
-               sscanf(item[7],"%lf",&this_->speed);
-               this_->speed *= 1.852;
-               scale=transform_scale(this_->current_pos.y);
-               speed=this_->speed+(this_->speed-this_->speed_last)/2;
-#ifdef INTERPOLATION_TIME
-               this_->delta.x=sin(M_PI*this_->dir/180)*speed*scale/3600*INTERPOLATION_TIME;
-               this_->delta.y=cos(M_PI*this_->dir/180)*speed*scale/3600*INTERPOLATION_TIME;
-#endif
-               this_->speed_last=this_->speed;
-       }
-}
-
-#ifdef HAVE_LIBGPS
-static void
-vehicle_gps_callback(struct gps_data_t *data, char *buf, size_t len, int level)
-{
-       // If data->fix.speed is NAN, then the drawing gets jumpy. 
-       if(isnan(data->fix.speed)){
-               return;
-       }
-
-       struct vehicle *this_=vehicle_last;
-       double scale,speed;
-#if INTERPOLATION_TIME
-       if (! (data->set & TIME_SET)) {
-               return;
-       }
-       data->set &= ~TIME_SET;
-       if (this_->time == data->fix.time)
-               return;
-       this_->time=data->fix.time;
-#endif
-       if (data->set & SPEED_SET) {
-               this_->speed_last=this_->speed;
-               this_->speed=data->fix.speed*3.6;
-               data->set &= ~SPEED_SET;
-       }
-       if (data->set & TRACK_SET) {
-               speed=this_->speed+(this_->speed-this_->speed_last)/2;
-               this_->dir=data->fix.track;
-               scale=transform_scale(this_->current_pos.y);
-#ifdef INTERPOLATION_TIME
-               this_->delta.x=sin(M_PI*this_->dir/180)*speed*scale/3600*INTERPOLATION_TIME;
-               this_->delta.y=cos(M_PI*this_->dir/180)*speed*scale/3600*INTERPOLATION_TIME;
-#endif
-               data->set &= ~TRACK_SET;
-       }
-       if (data->set & LATLON_SET) {
-               this_->geo.lat=data->fix.latitude;
-               this_->geo.lng=data->fix.longitude;
-               transform_from_geo(projection_mg, &this_->geo, &this_->current_pos);
-               this_->curr.x=this_->current_pos.x;
-               this_->curr.y=this_->current_pos.y;
-               this_->timer_count=0;
-               callback_list_call_1(this_->cbl, this_);
-               data->set &= ~LATLON_SET;
-       }
-       if (data->set & ALTITUDE_SET) {
-               this_->height=data->fix.altitude;
-               data->set &= ~ALTITUDE_SET;
-       }
-       if (data->set & SATELLITE_SET) {
-               this_->sats=data->satellites;
-               data->set &= ~SATELLITE_SET;
-               /* FIXME : the USED_SET check does not work yet. */
-               this_->sats_used=data->satellites_used;
-       }
-       if (data->set & STATUS_SET) {
-               this_->status=data->status;
-               data->set &= ~STATUS_SET;
-       }
-       if(data->set & PDOP_SET){
-               printf("pdop : %g\n",data->pdop);
-       }
-}
-#endif
-
-
-static void
-vehicle_close(struct vehicle *this_)
+vehicle_add_log(struct vehicle *this_, struct log *log,
+               struct attr **attrs)
 {
-       GError *error=NULL;
-
-
-       g_io_channel_shutdown(this_->iochan,0,&error);
-#ifdef HAVE_LIBGPS
-       if (this_->gps)
-               gps_close(this_->gps);
-#endif
-       if (this_->file)
-               pclose(this_->file);
-       if (this_->fd != -1)
-               close(this_->fd);
+       struct attr *type;
+       type = attr_search(attrs, NULL, attr_type);
+       if (!type)
+               return 1;
+       if (!strcmp(type->u.str, "nmea")) {
+               this_->nmea_log = log;
+       } else if (!strcmp(type->u.str, "gpx")) {
+               char *header =
+                   "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpx version=\"1.0\" creator=\"Navit http://navit.sourceforge.net\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n<trk>\n<trkseg>\n";
+               char *trailer = "</trkseg>\n</trk>\n</gpx>\n";
+               this_->gpx_log = log;
+               log_set_header(log, header, strlen(header));
+               log_set_trailer(log, trailer, strlen(trailer));
+       } else if (!strcmp(type->u.str, "textfile")) {
+               char *header = "type=track\n";
+               this_->textfile_log = log;
+               log_set_header(log, header, strlen(header));
+       } else
+               return 1;
+       return 0;
 }
 
-struct packet {
-       int magic __attribute__ ((packed));
-       unsigned char type;
-       union {
-               struct {
-                       int x __attribute__ ((packed));
-                       int y __attribute__ ((packed));
-                       unsigned char speed;
-                       unsigned char dir;
-               } pos;
-       } u;
-} __attribute__ ((packed)) ;
-
-static void
-vehicle_udp_recv(struct vehicle *this_)
+struct vehicle *
+vehicle_new(struct attr **attrs)
 {
-       struct packet pkt;
-       int size;
-
-       dbg(2,"enter this_=%p\n",this_);
-       size=recv(this_->fd, &pkt, 15, 0);
-       if (pkt.magic == this_->magic) {
-               dbg(3,"magic 0x%x size=%d\n", pkt.magic, size);
-               this_->current_pos.x=pkt.u.pos.x;
-               this_->current_pos.y=pkt.u.pos.y;
-               this_->speed=pkt.u.pos.speed;
-               this_->dir=pkt.u.pos.dir*2;
-               callback_list_call_1(this_->cbl, this_);
-       }
-}
+       struct vehicle *this_;
+       struct attr *source;
+       struct vehicle_priv *(*vehicletype_new) (struct vehicle_methods *
+                                                meth,
+                                                struct callback_list *
+                                                cbl,
+                                                struct attr ** attrs);
+       char *type, *colon;
+
+       dbg(0, "enter\n");
+       source = attr_search(attrs, NULL, attr_source);
+       if (!source) {
+               dbg(0, "no source\n");
+               return NULL;
+       }
+
+       type = g_strdup(source->u.str);
+       colon = index(type, ':');
+       if (colon)
+               *colon = '\0';
+       dbg(0, "source='%s' type='%s'\n", source->u.str, type);
+
+       vehicletype_new = plugin_get_vehicle_type(type);
+       if (!vehicletype_new) {
+               dbg(0, "invalid type\n");
+               return NULL;
+       }
+       this_ = g_new0(struct vehicle, 1);
+       this_->cbl = callback_list_new();
+       this_->priv = vehicletype_new(&this_->meth, this_->cbl, attrs);
+       if (!this_->priv) {
+               dbg(0, "vehicletype_new failed\n");
+               callback_list_destroy(this_->cbl);
+               g_free(this_);
+               return NULL;
+       }
+       dbg(0, "leave\n");
 
-static void
-vehicle_udp_update(struct vehicle *this_, struct vehicle *child)
-{
-       struct coord *pos=&child->current_pos;
-       struct packet pkt;
-       int speed=child->speed;
-       int dir=child->dir/2;
-       if (speed > 255)
-               speed=255;
-       pkt.magic=this_->magic;
-       pkt.type=1;
-       pkt.u.pos.x=pos->x;
-       pkt.u.pos.y=pos->y;
-       pkt.u.pos.speed=speed;
-       pkt.u.pos.dir=dir;
-       sendto(this_->fd, &pkt, 15, 0, (struct sockaddr *)&this_->rem, sizeof(this_->rem));
-       this_->current_pos=child->current_pos;
-       this_->speed=child->speed;
-       this_->dir=child->dir;
-       callback_list_call_1(this_->cbl, this_);
+       return this_;
 }
 
-static int
-vehicle_udp_query(void *data)
+int
+vehicle_position_attr_get(struct vehicle *this_, enum attr_type type,
+                         struct attr *attr)
 {
-       struct vehicle *this_=(struct vehicle *)data;
-       struct packet pkt;
-       dbg(2,"enter this_=%p\n", this_);
-       pkt.magic=this_->magic;
-       pkt.type=2;
-       sendto(this_->fd, &pkt, 5, 0, (struct sockaddr *)&this_->rem, sizeof(this_->rem));
-       dbg(2,"ret=TRUE\n");
-       return TRUE;
+       if (this_->meth.position_attr_get)
+               return this_->meth.position_attr_get(this_->priv, type,
+                                                    attr);
+       return 0;
 }
 
-static int
-vehicle_udp_open(struct vehicle *this_)
+int
+vehicle_set_attr(struct vehicle *this_, struct attr *attr,
+                struct attr **attrs)
 {
-       char *host,*child,*url,*colon;
-       int port;
-       url=g_strdup(this_->url);
-       colon=index(url+6,':');
-       struct sockaddr_in lcl;
-
-       if (! colon || sscanf(colon+1,"%d/%i/%d", &port, &this_->magic, &this_->interval) != 3) {
-               g_warning("Wrong syntax in %s\n", this_->url);
-               return 0;
-       }
-       host=url+6;
-       *colon='\0';
-       this_->fd=socket(PF_INET, SOCK_DGRAM, 0);
-       this_->is_udp=1;
-       memset(&lcl, 0, sizeof(lcl));
-       lcl.sin_family = AF_INET;
-
-       this_->rem.sin_family = AF_INET;
-       inet_aton(host, &this_->rem.sin_addr);
-       this_->rem.sin_port=htons(port);
-
-       bind(this_->fd, (struct sockaddr *)&lcl, sizeof(lcl));
-       child=index(colon+1,' ');
-       if (child) {
-               child++;
-               if (!this_->child) {
-                       dbg(3,"child=%s\n", child);
-                       this_->child=vehicle_new(child);
-                       this_->child_cb=callback_new_1(callback_cast(vehicle_udp_update), this_);
-                       vehicle_callback_add(this_->child, this_->child_cb);
-               }
-       } else {
-               vehicle_udp_query(this_);
-               g_timeout_add(this_->interval*1000, vehicle_udp_query, this_);
-       }
-       g_free(url);
        return 0;
 }
 
-static int
-vehicle_demo_timer (struct vehicle *this)
-{
-       struct route_path_coord_handle *h;
-       struct coord *c;
-       dbg(1,"###### Entering simulation loop\n");
-       if(!this->navit){
-               dbg(1,"vehicle->navit is not set. Can't simulate\n");
-               return 1;
-       }
-
-       // <cp15> Then check whether the route is set, if not return TRUE
-       struct route * vehicle_route=navit_get_route(this->navit);
-       if(!vehicle_route){
-               dbg(1,"navit_get_route NOK\n");
-               return 1;
-       }
-
-       h=route_path_coord_open(vehicle_route);
-       if (!h) {
-               dbg(1,"navit_path_coord_open NOK\n");
-               return 1;
-       }
-       c=route_path_coord_get(h);
-       dbg(1,"current pos=%p\n", c);
-       if (c) 
-               dbg(1,"current pos=0x%x,0x%x\n", c->x, c->y);
-       c=route_path_coord_get(h);
-       dbg(1,"next pos=%p\n", c);
-       if (c) {
-               dbg(1,"next pos=0x%x,0x%x\n", c->x, c->y);
-               vehicle_set_position(this,c);
+int
+vehicle_add_attr(struct vehicle *this_, struct attr *attr,
+                struct attr **attrs)
+{
+       switch (attr->type) {
+       case attr_callback:
+               callback_list_add(this_->cbl, attr->u.callback);
+               break;
+       case attr_log:
+               return vehicle_add_log(this_, attr->u.log, attrs);
+       default:
+               return 0;
        }
        return 1;
 }
 
-static int
-vehicle_open(struct vehicle *this_)
+int
+vehicle_remove_attr(struct vehicle *this_, struct attr *attr)
 {
-       struct termios tio;
-       struct stat st;
-       int fd=0;
-
-#ifdef HAVE_LIBGPS
-       struct gps_data_t *gps=NULL;
-       char *url_,*colon;
-#endif
-       if (! strncmp(this_->url,"file:",5)) {
-               fd=open(this_->url+5,O_RDONLY|O_NDELAY);
-               if (fd < 0) {
-                       g_warning("Failed to open %s", this_->url);
-                       return 0;
-               }
-               stat(this_->url+5, &st);
-               if (S_ISREG (st.st_mode)) {
-                       this_->is_file=1;
-               } else {
-                       tcgetattr(fd, &tio);
-                       cfmakeraw(&tio);
-                       cfsetispeed(&tio, B4800);
-                       cfsetospeed(&tio, B4800);
-                       tio.c_cc[VMIN]=16;
-                       tio.c_cc[VTIME]=1;
-                       tcsetattr(fd, TCSANOW, &tio);
-               }
-               this_->fd=fd;
-       } else if (! strncmp(this_->url,"pipe:",5)) {
-               this_->file=popen(this_->url+5, "r");
-               this_->is_pipe=1;
-               if (! this_->file) {
-                       g_warning("Failed to open %s", this_->url);
-                       return 0;
-               }
-               fd=fileno(this_->file);
-       } else if (! strncmp(this_->url,"gpsd://",7)) {
-#ifdef HAVE_LIBGPS
-               url_=g_strdup(this_->url);
-               colon=index(url_+7,':');
-               if (colon) {
-                       *colon=0;
-                       gps=gps_open(url_+7,colon+1);
-               } else
-                       gps=gps_open(this_->url+7,NULL);
-               g_free(url_);
-               if (! gps) {
-                       g_warning("Failed to connect to %s", this_->url);
-                       return 0;
-               }
-               gps_query(gps, "w+x\n");
-               gps_set_raw_hook(gps, vehicle_gps_callback);
-               fd=gps->gps_fd;
-               this_->gps=gps;
-#else
-               g_warning("No support for gpsd compiled in\n");
+       switch (attr->type) {
+       case attr_callback:
+               callback_list_remove(this_->cbl, attr->u.callback);
+               break;
+       default:
                return 0;
-#endif
-       } else if (! strncmp(this_->url,"udp://",6)) {
-               vehicle_udp_open(this_);
-               fd=this_->fd;
-       } else if (! strncmp(this_->url,"demo://",7)) {
-               dbg(0,"Creating a demo vehicle\n");
-               g_timeout_add(1000, (GSourceFunc) vehicle_demo_timer, this_);
        }
-       this_->iochan=g_io_channel_unix_new(fd);
-       enable_watch(this_);
        return 1;
 }
 
-
-static gboolean
-vehicle_track(GIOChannel *iochan, GIOCondition condition, gpointer t)
-{
-       struct vehicle *this_=t;
-       char *str,*tok;
-       gsize size;
-
-       dbg(1,"enter condition=%d\n", condition);
-       if (condition == G_IO_IN) {
-#ifdef HAVE_LIBGPS
-               if (this_->gps) {
-                       vehicle_last=this_;
-                       gps_poll(this_->gps);
-               } else {
-#else
-               {
-#endif
-                       if (this_->is_udp) {
-                               vehicle_udp_recv(this_);
-                               return TRUE;
-                       }
-                       size=read(g_io_channel_unix_get_fd(iochan), this_->buffer+this_->buffer_pos, BUFFER_SIZE-this_->buffer_pos-1);
-                       if (size <= 0) {
-                               vehicle_close(this_);
-                               vehicle_open(this_);
-                               return TRUE;
-                       }
-                       this_->buffer_pos+=size;
-                       this_->buffer[this_->buffer_pos]='\0';
-                       dbg(1,"size=%d pos=%d buffer='%s'\n", size, this_->buffer_pos, this_->buffer);
-                       str=this_->buffer;
-                       while ((tok=index(str, '\n'))) {
-                               *tok++='\0';
-                               dbg(1,"line='%s'\n", str);
-                               vehicle_parse_gps(this_, str);
-                               str=tok;
-                       }
-                       if (str != this_->buffer) {
-                               size=this_->buffer+this_->buffer_pos-str;
-                               memmove(this_->buffer, str, size+1);
-                               this_->buffer_pos=size;
-                               dbg(1,"now pos=%d buffer='%s'\n", this_->buffer_pos, this_->buffer);
-                       } else if (this_->buffer_pos == BUFFER_SIZE-1) {
-                               dbg(0,"overflow\n");
-                               this_->buffer_pos=0;
-                       }
-                       
-               }
-
-               return TRUE;
-       } 
-       return FALSE;
-}
-
-static void
-enable_watch(struct vehicle *this_)
-{
-       this_->watch=g_io_add_watch(this_->iochan, G_IO_IN|G_IO_ERR|G_IO_HUP, vehicle_track, this_);
-}
-
-static void
-disable_watch(struct vehicle *this_)
-{
-       g_source_remove(this_->watch);
-}
-
-struct vehicle *
-vehicle_new(const char *url)
-{
-       struct vehicle *this_;
-       this_=g_new0(struct vehicle,1);
-
-       this_->cbl=callback_list_new();
-       this_->url=g_strdup(url);
-       this_->fd=-1;
-
-       vehicle_open(this_);
-       this_->current_pos.x=0x130000;
-       this_->current_pos.y=0x600000;
-       this_->curr.x=this_->current_pos.x;
-       this_->curr.y=this_->current_pos.y;
-       this_->delta.x=0;
-       this_->delta.y=0;
-#if INTERPOLATION_TIME
-       g_timeout_add(INTERPOLATION_TIME, vehicle_timer, this_);
-#endif
-       
-       return this_;
-}
-
-void
-vehicle_callback_add(struct vehicle *this_, struct callback *cb)
-{
-       callback_list_add(this_->cbl, cb);
-}
-
-void
-vehicle_callback_remove(struct vehicle *this_, struct callback *cb)
-{
-       callback_list_remove(this_->cbl, cb);
-}
-
-
-int
-vehicle_add_log(struct vehicle *this_, struct log *log, struct attr **attrs)
-{
-       struct attr *type;
-       type=attr_search(attrs, NULL, attr_type);
-       if (! type) 
-               return 1;
-       if (!strcmp(type->u.str,"nmea")) {
-               this_->nmea_log=log;
-               if (this_->child) 
-                       this_->child->nmea_log=log;
-               
-       } else if (!strcmp(type->u.str,"gpx")) {
-               char *header="<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<gpx version=\"1.0\" creator=\"Navit http://navit.sourceforge.net\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns=\"http://www.topografix.com/GPX/1/0\" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n<trk>\n<trkseg>\n";
-               char *trailer="</trkseg>\n</trk>\n</gpx>\n";
-               this_->gpx_log=log;
-               if (this_->child)
-                       this_->child->gpx_log=log;
-               log_set_header(log,header,strlen(header));
-               log_set_trailer(log,trailer,strlen(trailer));
-       } else if (!strcmp(type->u.str,"textfile")) {
-               char *header="type=track\n";
-               this_->textfile_log=log;
-               if (this_->child)
-                       this_->child->textfile_log=log;
-               log_set_header(log,header,strlen(header));
-       } else
-               return 1;
-       return 0;
-}
-
 void
 vehicle_destroy(struct vehicle *this_)
 {
-       vehicle_close(this_);
        callback_list_destroy(this_->cbl);
-       g_free(this_->url);
        g_free(this_);
 }
index 557b927..7c4e5f4 100644 (file)
@@ -4,29 +4,22 @@
 #ifdef __cplusplus
 extern "C" {
 #endif
+struct vehicle_priv;
+
+struct vehicle_methods {
+       void (*destroy)(struct vehicle_priv *priv);
+       int (*position_attr_get)(struct vehicle_priv *priv, enum attr_type type, struct attr *attr);
+};
+
 /* prototypes */
-enum projection;
+enum attr_type;
 struct attr;
-struct callback;
-struct coord;
-struct log;
-struct navit;
 struct vehicle;
-enum projection vehicle_projection(struct vehicle *this_);
-struct coord *vehicle_pos_get(struct vehicle *this_);
-double *vehicle_speed_get(struct vehicle *this_);
-double *vehicle_height_get(struct vehicle *this_);
-double *vehicle_dir_get(struct vehicle *this_);
-int *vehicle_status_get(struct vehicle *this_);
-int *vehicle_sats_get(struct vehicle *this_);
-int *vehicle_sats_used_get(struct vehicle *this_);
-double *vehicle_pdop_get(struct vehicle *this_);
-void vehicle_set_position(struct vehicle *this_, struct coord *pos);
-void vehicle_set_navit(struct vehicle *this_, struct navit *nav);
-struct vehicle *vehicle_new(const char *url);
-void vehicle_callback_add(struct vehicle *this_, struct callback *cb);
-void vehicle_callback_remove(struct vehicle *this_, struct callback *cb);
-int vehicle_add_log(struct vehicle *this_, struct log *log, struct attr **attrs);
+struct vehicle *vehicle_new(struct attr **attrs);
+int vehicle_position_attr_get(struct vehicle *this_, enum attr_type type, struct attr *attr);
+int vehicle_set_attr(struct vehicle *this_, struct attr *attr, struct attr **attrs);
+int vehicle_add_attr(struct vehicle *this_, struct attr *attr, struct attr **attrs);
+int vehicle_remove_attr(struct vehicle *this_, struct attr *attr);
 void vehicle_destroy(struct vehicle *this_);
 /* end of prototypes */
 #ifdef __cplusplus
index d65d693..8901833 100644 (file)
@@ -1,4 +1,4 @@
-SUBDIRS=file
+SUBDIRS=demo file
 if VEHICLE_GPSD
   SUBDIRS += gpsd
 endif
diff --git a/src/vehicle/demo/Makefile.am b/src/vehicle/demo/Makefile.am
new file mode 100644 (file)
index 0000000..1d66f32
--- /dev/null
@@ -0,0 +1,4 @@
+include $(top_srcdir)/Makefile.inc
+AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -DMODULE=\"vehicle_demo\"
+modulevehicle_LTLIBRARIES = libvehicle_demo.la
+libvehicle_demo_la_SOURCES = vehicle_demo.c
diff --git a/src/vehicle/demo/vehicle_demo.c b/src/vehicle/demo/vehicle_demo.c
new file mode 100644 (file)
index 0000000..632b9f4
--- /dev/null
@@ -0,0 +1,7 @@
+#include "debug.h"
+
+void
+plugin_init(void)
+{
+       dbg(0,"enter\n");
+}
index 32be387..ce9d41f 100644 (file)
@@ -1,6 +1,345 @@
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <glib.h>
+#include <sys/stat.h>
+#include <termios.h>
+#include <math.h>
+#include "debug.h"
+#include "callback.h"
 #include "plugin.h"
+#include "coord.h"
+#include "item.h"
+#include "vehicle.h"
+
+static void vehicle_file_disable_watch(struct vehicle_priv *priv);
+static void vehicle_file_enable_watch(struct vehicle_priv *priv);
+
+enum file_type {
+       file_type_pipe = 1, file_type_device, file_type_file
+};
+
+static int buffer_size = 256;
+
+struct vehicle_priv {
+       char *source;
+       enum file_type file_type;
+       struct callback_list *cbl;
+       int fd;
+       FILE *file;
+       guint watch;
+       GIOChannel *iochan;
+       char *buffer;
+       int buffer_pos;
+
+       struct coord_geo geo;
+       double speed;
+       double direction;
+       double height;
+       int status;
+       int sats_used;
+};
+
+static int
+vehicle_file_open(struct vehicle_priv *priv)
+{
+       char *name;
+       struct stat st;
+       struct termios tio;
+
+       name = priv->source + 5;
+       if (!strncmp(priv->source, "file:", 5)) {
+               priv->fd = open(name, O_RDONLY | O_NDELAY);
+               if (priv->fd < 0)
+                       return 0;
+               stat(name, &st);
+               if (S_ISREG(st.st_mode)) {
+                       priv->file_type = file_type_file;
+               } else {
+                       tcgetattr(priv->fd, &tio);
+                       cfmakeraw(&tio);
+                       cfsetispeed(&tio, B4800);
+                       cfsetospeed(&tio, B4800);
+                       tio.c_cc[VMIN] = 16;
+                       tio.c_cc[VTIME] = 1;
+                       tcsetattr(priv->fd, TCSANOW, &tio);
+                       priv->file_type = file_type_device;
+               }
+       } else {
+               priv->file = popen(name, "r");
+               if (!priv->file)
+                       return 0;
+               priv->fd = fileno(priv->file);
+               priv->file_type = file_type_pipe;
+       }
+       priv->iochan = g_io_channel_unix_new(priv->fd);
+       return 1;
+}
+
+static void
+vehicle_file_close(struct vehicle_priv *priv)
+{
+       GError *error = NULL;
+       if (priv->iochan) {
+               g_io_channel_shutdown(priv->iochan, 0, &error);
+               priv->iochan = NULL;
+       }
+       if (priv->file)
+               pclose(priv->file);
+       else if (priv->fd >= 0)
+               close(priv->fd);
+       priv->file = NULL;
+       priv->fd = -1;
+}
+
+static int
+vehicle_file_enable_watch_timer(gpointer t)
+{
+       struct vehicle_priv *priv = t;
+       vehicle_file_enable_watch(priv);
+       dbg(1, "enter\n");
+
+       return FALSE;
+}
+
+
+static void
+vehicle_file_parse(struct vehicle_priv *priv, char *buffer)
+{
+       char *p, *item[16];
+       double lat, lng;
+       int i, bcsum;
+       int len = strlen(buffer);
+       unsigned char csum = 0;
+
+       dbg(1, "buffer='%s'\n", buffer);
+       for (;;) {
+               if (len < 4) {
+                       dbg(0, "too short\n");
+                       return;
+               }
+               if (buffer[len - 1] == '\r' || buffer[len - 1] == '\n')
+                       buffer[--len] = '\0';
+               else
+                       break;
+       }
+       if (buffer[0] != '$') {
+               dbg(0, "no leading $\n");
+               return;
+       }
+       if (buffer[len - 3] != '*') {
+               dbg(0, "no *XX\n");
+               return;
+       }
+       for (i = 1; i < len - 3; i++) {
+               csum ^= (unsigned char) (buffer[i]);
+       }
+       if (!sscanf(buffer + len - 2, "%x", &bcsum)) {
+               dbg(0, "no checksum\n");
+               return;
+       }
+       if (bcsum != csum) {
+               dbg(0, "wrong checksum\n");
+               return;
+       }
+
+       i = 0;
+       p = buffer;
+       while (i < 16) {
+               item[i++] = p;
+               while (*p && *p != ',')
+                       p++;
+               if (!*p)
+                       break;
+               *p++ = '\0';
+       }
+
+       if (!strncmp(buffer, "$GPGGA", 6)) {
+               /*                                                           1 1111
+                  0      1          2         3 4          5 6 7  8   9     0 1234
+                  $GPGGA,184424.505,4924.2811,N,01107.8846,E,1,05,2.5,408.6,M,,,,0000*0C
+                  UTC of Fix[1],Latitude[2],N/S[3],Longitude[4],E/W[5],Quality(0=inv,1=gps,2=dgps)[6],Satelites used[7],
+                  HDOP[8],Altitude[9],"M"[10],height of geoid[11], "M"[12], time since dgps update[13], dgps ref station [14] 
+                */
+               sscanf(item[2], "%lf", &lat);
+               priv->geo.lat = floor(lat / 100);
+               lat -= priv->geo.lat * 100;
+               priv->geo.lat += lat / 60;
+
+               sscanf(item[4], "%lf", &lng);
+               priv->geo.lng = floor(lng / 100);
+               lng -= priv->geo.lng * 100;
+               priv->geo.lng += lng / 60;
+
+               sscanf(item[6], "%d", &priv->status);
+               sscanf(item[7], "%d", &priv->sats_used);
+               sscanf(item[9], "%lf", &priv->height);
+
+               callback_list_call_0(priv->cbl);
+               if (priv->file_type == file_type_file) {
+                       vehicle_file_disable_watch(priv);
+                       g_timeout_add(1000,
+                                     vehicle_file_enable_watch_timer,
+                                     priv);
+               }
+       }
+       if (!strncmp(buffer, "$GPVTG", 6)) {
+               /* 0      1      2 34 5    6 7   8 
+                  $GPVTG,143.58,T,,M,0.26,N,0.5,K*6A 
+                  Course Over Ground Degrees True[1],"T"[2],Course Over Ground Degrees Magnetic[3],"M"[4],
+                  Speed in Knots[5],"N"[6],"Speed in KM/H"[7],"K"[8]
+                */
+               sscanf(item[1], "%lf", &priv->direction);
+               sscanf(item[7], "%lf", &priv->speed);
+       }
+       if (!strncmp(buffer, "$GPRMC", 6)) {
+               /*                                                           1     1
+                  0      1      2 3        4 5         6 7     8     9      0     1
+                  $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A 
+                  Time[1],Active/Void[2],lat[3],N/S[4],long[5],W/E[6],speed in knots[7],track angle[8],date[9],
+                  magnetic variation[10],magnetic variation direction[11]
+                */
+               sscanf(item[8], "%lf", &priv->direction);
+               sscanf(item[7], "%lf", &priv->speed);
+               priv->speed *= 1.852;
+       }
+}
+
+static gboolean
+vehicle_file_io(GIOChannel * iochan, GIOCondition condition, gpointer t)
+{
+       struct vehicle_priv *priv = t;
+       int size;
+       char *str, *tok;
+
+       dbg(1, "enter condition=%d\n", condition);
+       if (condition == G_IO_IN) {
+               size =
+                   read(g_io_channel_unix_get_fd(iochan),
+                        priv->buffer + priv->buffer_pos,
+                        buffer_size - priv->buffer_pos - 1);
+               if (size <= 0) {
+                       vehicle_file_close(priv);
+                       vehicle_file_open(priv);
+                       return TRUE;
+               }
+               priv->buffer_pos += size;
+               priv->buffer[priv->buffer_pos] = '\0';
+               dbg(1, "size=%d pos=%d buffer='%s'\n", size,
+                   priv->buffer_pos, priv->buffer);
+               str = priv->buffer;
+               while ((tok = index(str, '\n'))) {
+                       *tok++ = '\0';
+                       dbg(1, "line='%s'\n", str);
+                       vehicle_file_parse(priv, str);
+                       str = tok;
+               }
+               if (str != priv->buffer) {
+                       size = priv->buffer + priv->buffer_pos - str;
+                       memmove(priv->buffer, str, size + 1);
+                       priv->buffer_pos = size;
+                       dbg(1, "now pos=%d buffer='%s'\n",
+                           priv->buffer_pos, priv->buffer);
+               } else if (priv->buffer_pos == buffer_size - 1) {
+                       dbg(0,
+                           "Overflow. Most likely wrong baud rate or no nmea protocol\n");
+                       priv->buffer_pos = 0;
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static void
+vehicle_file_enable_watch(struct vehicle_priv *priv)
+{
+       priv->watch =
+           g_io_add_watch(priv->iochan, G_IO_IN | G_IO_ERR | G_IO_HUP,
+                          vehicle_file_io, priv);
+}
+
+static void
+vehicle_file_disable_watch(struct vehicle_priv *priv)
+{
+       if (priv->watch)
+               g_source_remove(priv->watch);
+       priv->watch = 0;
+}
+
+
+static void
+vehicle_file_destroy(struct vehicle_priv *priv)
+{
+       vehicle_file_close(priv);
+       if (priv->source)
+               g_free(priv->source);
+       if (priv->buffer)
+               g_free(priv->buffer);
+       g_free(priv);
+}
+
+static int
+vehicle_file_position_attr_get(struct vehicle_priv *priv,
+                              enum attr_type type, struct attr *attr)
+{
+       switch (type) {
+       case attr_position_height:
+               attr->u.numd = &priv->height;
+               break;
+       case attr_position_speed:
+               attr->u.numd = &priv->speed;
+               break;
+       case attr_position_direction:
+               attr->u.numd = &priv->direction;
+               break;
+       case attr_position_sats_used:
+               attr->u.num = priv->sats_used;
+               break;
+       case attr_position_coord_geo:
+               attr->u.coord_geo = &priv->geo;
+               break;
+       default:
+               return 0;
+       }
+       attr->type = type;
+       return 1;
+}
+
+struct vehicle_methods vehicle_file_methods = {
+       vehicle_file_destroy,
+       vehicle_file_position_attr_get,
+};
+
+static struct vehicle_priv *
+vehicle_file_new_file(struct vehicle_methods
+                     *meth, struct callback_list
+                     *cbl, struct attr **attrs)
+{
+       struct vehicle_priv *ret;
+       struct attr *source;
+
+       dbg(1, "enter\n");
+       source = attr_search(attrs, NULL, attr_source);
+       ret = g_new0(struct vehicle_priv, 1);
+       ret->fd = -1;
+       ret->cbl = cbl;
+       ret->source = g_strdup(source->u.str);
+       ret->buffer = g_malloc(buffer_size);
+       *meth = vehicle_file_methods;
+       if (vehicle_file_open(ret)) {
+               vehicle_file_enable_watch(ret);
+               return ret;
+       }
+       dbg(0, "Failed to open '%s'\n", ret->source);
+       vehicle_file_destroy(ret);
+       return NULL;
+}
 
 void
 plugin_init(void)
 {
+       dbg(1, "enter\n");
+       plugin_register_vehicle_type("file", vehicle_file_new_file);
+       plugin_register_vehicle_type("pipe", vehicle_file_new_file);
 }
index 50ec71a..c4222e3 100644 (file)
@@ -2,3 +2,4 @@ include $(top_srcdir)/Makefile.inc
 AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -DMODULE=\"vehicle_gpsd\"
 modulevehicle_LTLIBRARIES = libvehicle_gpsd.la
 libvehicle_gpsd_la_SOURCES = vehicle_gpsd.c
+libvehicle_gpsd_la_LIBADD = @GPSD_LIBS@
index 32be387..569b0e9 100644 (file)
@@ -1,6 +1,202 @@
+#include <gps.h>
+#include <string.h>
+#include <glib.h>
+#include <math.h>
+#include "debug.h"
+#include "callback.h"
 #include "plugin.h"
+#include "coord.h"
+#include "item.h"
+#include "vehicle.h"
+
+static struct vehicle_priv {
+       char *source;
+       struct callback_list *cbl;
+       GIOChannel *iochan;
+       guint watch;
+       struct gps_data_t *gps;
+       struct coord_geo geo;
+       double speed;
+       double direction;
+       double height;
+       int status;
+       int sats;
+       int sats_used;
+} *vehicle_last;
+
+static gboolean vehicle_gpsd_io(GIOChannel * iochan,
+                               GIOCondition condition, gpointer t);
+
+
+
+static void
+vehicle_gpsd_callback(struct gps_data_t *data, char *buf, size_t len,
+                     int level)
+{
+       struct vehicle_priv *priv = vehicle_last;
+       // If data->fix.speed is NAN, then the drawing gets jumpy. 
+       if (isnan(data->fix.speed)) {
+               return;
+       }
+
+       if (data->set & SPEED_SET) {
+               priv->speed = data->fix.speed * 3.6;
+               data->set &= ~SPEED_SET;
+       }
+       if (data->set & TRACK_SET) {
+               priv->direction = data->fix.track;
+               data->set &= ~TRACK_SET;
+       }
+       if (data->set & ALTITUDE_SET) {
+               priv->height = data->fix.altitude;
+               data->set &= ~ALTITUDE_SET;
+       }
+       if (data->set & SATELLITE_SET) {
+               priv->sats_used = data->satellites_used;
+               priv->sats = data->satellites;
+               data->set &= ~SATELLITE_SET;
+       }
+       if (data->set & STATUS_SET) {
+               priv->status = data->status;
+               data->set &= ~STATUS_SET;
+       }
+       if (data->set & PDOP_SET) {
+               dbg(0, "pdop : %g\n", data->pdop);
+               data->set &= ~PDOP_SET;
+       }
+       if (data->set & LATLON_SET) {
+               priv->geo.lat = data->fix.latitude;
+               priv->geo.lng = data->fix.longitude;
+               callback_list_call_0(priv->cbl);
+               data->set &= ~LATLON_SET;
+       }
+}
+
+static int
+vehicle_gpsd_open(struct vehicle_priv *priv)
+{
+       char *source = g_strdup(priv->source);
+       char *colon = index(source + 7, ':');
+       if (colon) {
+               *colon = '\0';
+               priv->gps = gps_open(source + 7, colon + 1);
+       } else
+               priv->gps = gps_open(source + 7, NULL);
+       g_free(source);
+       if (!priv->gps)
+               return 0;
+       gps_query(priv->gps, "w+x\n");
+       gps_set_raw_hook(priv->gps, vehicle_gpsd_callback);
+       priv->iochan = g_io_channel_unix_new(priv->gps->gps_fd);
+       priv->watch =
+           g_io_add_watch(priv->iochan, G_IO_IN | G_IO_ERR | G_IO_HUP,
+                          vehicle_gpsd_io, priv);
+       return 1;
+}
+
+static void
+vehicle_gpsd_close(struct vehicle_priv *priv)
+{
+       GError *error = NULL;
+
+       if (priv->watch) {
+               g_source_remove(priv->watch);
+               priv->watch = 0;
+       }
+       if (priv->iochan) {
+               g_io_channel_shutdown(priv->iochan, 0, &error);
+               priv->iochan = NULL;
+       }
+       if (priv->gps) {
+               gps_close(priv->gps);
+               priv->gps = NULL;
+       }
+}
+
+static gboolean
+vehicle_gpsd_io(GIOChannel * iochan, GIOCondition condition, gpointer t)
+{
+       struct vehicle_priv *priv = t;
+
+       dbg(1, "enter condition=%d\n", condition);
+       if (condition == G_IO_IN) {
+               if (priv->gps) {
+                       vehicle_last = priv;
+                       gps_poll(priv->gps);
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+static void
+vehicle_gpsd_destroy(struct vehicle_priv *priv)
+{
+       vehicle_gpsd_close(priv);
+       if (priv->source)
+               g_free(priv->source);
+       g_free(priv);
+}
+
+static int
+vehicle_gpsd_position_attr_get(struct vehicle_priv *priv,
+                              enum attr_type type, struct attr *attr)
+{
+       switch (type) {
+       case attr_position_height:
+               attr->u.numd = &priv->height;
+               break;
+       case attr_position_speed:
+               attr->u.numd = &priv->speed;
+               break;
+       case attr_position_direction:
+               attr->u.numd = &priv->direction;
+               break;
+       case attr_position_sats:
+               attr->u.num = priv->sats;
+               break;
+       case attr_position_sats_used:
+               attr->u.num = priv->sats_used;
+               break;
+       case attr_position_coord_geo:
+               attr->u.coord_geo = &priv->geo;
+               break;
+       default:
+               return 0;
+       }
+       attr->type = type;
+       return 1;
+}
+
+struct vehicle_methods vehicle_gpsd_methods = {
+       vehicle_gpsd_destroy,
+       vehicle_gpsd_position_attr_get,
+};
+
+static struct vehicle_priv *
+vehicle_gpsd_new_gpsd(struct vehicle_methods
+                     *meth, struct callback_list
+                     *cbl, struct attr **attrs)
+{
+       struct vehicle_priv *ret;
+       struct attr *source;
+
+       dbg(1, "enter\n");
+       source = attr_search(attrs, NULL, attr_source);
+       ret = g_new0(struct vehicle_priv, 1);
+       ret->source = g_strdup(source->u.str);
+       ret->cbl = cbl;
+       *meth = vehicle_gpsd_methods;
+       if (vehicle_gpsd_open(ret))
+               return ret;
+       dbg(0, "Failed to open '%s'\n", ret->source);
+       vehicle_gpsd_destroy(ret);
+       return NULL;
+}
 
 void
 plugin_init(void)
 {
+       dbg(1, "enter\n");
+       plugin_register_vehicle_type("gpsd", vehicle_gpsd_new_gpsd);
 }
index 50784fc..d1ebd8e 100644 (file)
@@ -259,40 +259,28 @@ xmlconfig_gui(struct xmlstate *state)
 static int
 xmlconfig_vehicle(struct xmlstate *state)
 {
-       const char *s=find_attribute(state, "source", 1);
-       const char *value,*name;
-       struct color color;
-       int update=1, follow=0, active;
-       struct navit_vehicle *nv;
+       struct attr **attrs;
+       attrs=convert_to_attrs(state);
 
-       if (! s)
-               return 0;
-       if (! find_color(state, 1, &color))
-               return 0;
-       state->element_object = vehicle_new(s);
+       state->element_object = vehicle_new(attrs);
        if (! state->element_object)
                return 0;
-       if ((value=find_attribute(state, "update", 0)))
-               update=convert_number(value);
-       if ((value=find_attribute(state, "follow", 0)))
-               follow=convert_number(value);
-       active=find_boolean(state, "active", 1, 0);
-       name=find_attribute(state, "name", 0);
-       nv=navit_add_vehicle(state->parent->element_object, state->element_object, name, &color, update, follow);
-       if (active)
-               navit_set_vehicle(state->parent->element_object, nv);
+       navit_add_vehicle(state->parent->element_object, state->element_object, attrs);
        return 1;
 }
 
 static int
 xmlconfig_log(struct xmlstate *state)
 {
+       struct attr attr;
        struct attr **attrs;
        attrs=convert_to_attrs(state);
        state->element_object = log_new(attrs);
        if (! state->element_object)
                return 0;
-       if (vehicle_add_log(state->parent->element_object, state->element_object, attrs))
+       attr.type=attr_log;
+       attr.u.log=state->element_object;
+       if (vehicle_add_attr(state->parent->element_object, &attr, attrs))
                return 0;
        return 1;
 }
@@ -658,6 +646,7 @@ start_element (GMarkupParseContext *context,
        struct xmlstate *new=NULL, **parent = user_data;
        struct element_func *e=elements,*func=NULL;
        const char *parent_name=NULL;
+       dbg(2,"name='%s'\n", element_name);
        while (e->name) {
                if (!g_ascii_strcasecmp(element_name, e->name)) {
                        func=e;
@@ -725,6 +714,7 @@ end_element (GMarkupParseContext *context,
 {
        struct xmlstate *curr, **state = user_data;
 
+       dbg(2,"name='%s'\n", element_name);
        curr=*state;
        if(!g_ascii_strcasecmp("plugins", element_name) && curr->element_object) 
                plugins_init(curr->element_object);