Fix:vehicle_demo:Give back a reasonable timestamp
[navit-package] / navit / vehicle.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 Navit Team
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * version 2 as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA  02110-1301, USA.
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <glib.h>
23 #include <time.h>
24 #include "config.h"
25 #include "debug.h"
26 #include "coord.h"
27 #include "item.h"
28 #include "log.h"
29 #include "callback.h"
30 #include "plugin.h"
31 #include "vehicle.h"
32
33 struct vehicle {
34         struct vehicle_priv *priv;
35         struct vehicle_methods meth;
36         struct callback_list *cbl;
37         struct log *nmea_log, *gpx_log;
38         struct attr **attrs;
39 };
40
41 static void
42 vehicle_log_nmea(struct vehicle *this_, struct log *log)
43 {
44         struct attr pos_attr;
45         if (!this_->meth.position_attr_get)
46                 return;
47         if (!this_->meth.position_attr_get(this_->priv, attr_position_nmea, &pos_attr))
48                 return;
49         log_write(log, pos_attr.u.str, strlen(pos_attr.u.str));
50 }
51
52 static void
53 vehicle_log_gpx(struct vehicle *this_, struct log *log)
54 {
55         struct attr pos_attr;
56         struct attr time_attr;
57         char buffer[256];
58         char tbuf[256];
59         char *timep;
60         int free=0;
61
62         if (!this_->meth.position_attr_get)
63                 return;
64         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
65                 return;
66         if (!this_->meth.position_attr_get(this_->priv, attr_position_time_iso8601, &time_attr)) {
67                 timep = current_to_iso8601();
68                 free=1;
69         } else {
70                 timep = time_attr.u.str;
71         }
72         sprintf(buffer,"<trkpt lat=\"%f\" lon=\"%f\">\n\t<time>%s</time>\n</trkpt>\n",
73                 pos_attr.u.coord_geo->lat, pos_attr.u.coord_geo->lng, timep);
74         log_write(log, buffer, strlen(buffer));
75         if (free)
76                 g_free(timep);
77 }
78
79 static void
80 vehicle_log_textfile(struct vehicle *this_, struct log *log)
81 {
82         struct attr pos_attr;
83         char buffer[256];
84         if (!this_->meth.position_attr_get)
85                 return;
86         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
87                 return;
88         sprintf(buffer,"%f %f type=trackpoint\n", pos_attr.u.coord_geo->lng, pos_attr.u.coord_geo->lat);
89         log_write(log, buffer, strlen(buffer));
90 }
91
92 static int
93 vehicle_add_log(struct vehicle *this_, struct log *log)
94 {
95         struct callback *cb;
96         struct attr type_attr;
97         if (!log_get_attr(log, attr_type, &type_attr, NULL))
98                 return 1;
99
100         if (!strcmp(type_attr.u.str, "nmea")) {
101                 cb=callback_new_2(callback_cast(vehicle_log_nmea), this_, log);
102         } else if (!strcmp(type_attr.u.str, "gpx")) {
103                 char *header =
104                     "<?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";
105                 char *trailer = "</trkseg>\n</trk>\n</gpx>\n";
106                 log_set_header(log, header, strlen(header));
107                 log_set_trailer(log, trailer, strlen(trailer));
108                 cb=callback_new_2(callback_cast(vehicle_log_gpx), this_, log);
109         } else if (!strcmp(type_attr.u.str, "textfile")) {
110                 char *header = "type=track\n";
111                 log_set_header(log, header, strlen(header));
112                 cb=callback_new_2(callback_cast(vehicle_log_textfile), this_, log);
113         } else
114                 return 1;
115         callback_list_add(this_->cbl, cb);
116         return 0;
117 }
118
119 struct vehicle *
120 vehicle_new(struct attr *parent, struct attr **attrs)
121 {
122         struct vehicle *this_;
123         struct attr *source;
124         struct vehicle_priv *(*vehicletype_new) (struct vehicle_methods *
125                                                  meth,
126                                                  struct callback_list *
127                                                  cbl,
128                                                  struct attr ** attrs);
129         char *type, *colon;
130
131         dbg(1, "enter\n");
132         source = attr_search(attrs, NULL, attr_source);
133         if (!source) {
134                 dbg(0, "no source\n");
135                 return NULL;
136         }
137
138         type = g_strdup(source->u.str);
139         colon = strchr(type, ':');
140         if (colon)
141                 *colon = '\0';
142         dbg(1, "source='%s' type='%s'\n", source->u.str, type);
143
144         vehicletype_new = plugin_get_vehicle_type(type);
145         if (!vehicletype_new) {
146                 dbg(0, "invalid type '%s'\n", type);
147                 return NULL;
148         }
149         this_ = g_new0(struct vehicle, 1);
150         this_->cbl = callback_list_new();
151         this_->priv = vehicletype_new(&this_->meth, this_->cbl, attrs);
152         if (!this_->priv) {
153                 dbg(0, "vehicletype_new failed\n");
154                 callback_list_destroy(this_->cbl);
155                 g_free(this_);
156                 return NULL;
157         }
158         this_->attrs=attr_list_dup(attrs);
159         dbg(1, "leave\n");
160
161         return this_;
162 }
163
164 int
165 vehicle_get_attr(struct vehicle *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
166 {
167         int ret;
168         if (this_->meth.position_attr_get) {
169                 ret=this_->meth.position_attr_get(this_->priv, type, attr);
170                 if (ret)
171                         return ret;
172         }
173         return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
174 }
175
176 int
177 vehicle_set_attr(struct vehicle *this_, struct attr *attr,
178                  struct attr **attrs)
179 {
180         if (this_->meth.set_attr)
181                 return this_->meth.set_attr(this_->priv, attr, attrs);
182         return 0;
183 }
184
185 int
186 vehicle_add_attr(struct vehicle *this_, struct attr *attr)
187 {
188         int ret=1;
189         switch (attr->type) {
190         case attr_callback:
191                 callback_list_add(this_->cbl, attr->u.callback);
192                 break;
193         case attr_log:
194                 ret=vehicle_add_log(this_, attr->u.log);
195                 break;
196         default:
197                 break;
198         }
199         if (ret)
200                 this_->attrs=attr_generic_add_attr(this_->attrs, attr);
201         return ret;
202 }
203
204 int
205 vehicle_remove_attr(struct vehicle *this_, struct attr *attr)
206 {
207         switch (attr->type) {
208         case attr_callback:
209                 callback_list_remove(this_->cbl, attr->u.callback);
210                 break;
211         default:
212                 return 0;
213         }
214         return 1;
215 }
216
217 void
218 vehicle_destroy(struct vehicle *this_)
219 {
220         this_->meth.destroy(this_->priv);
221         callback_list_destroy(this_->cbl);
222         attr_list_free(this_->attrs);
223         g_free(this_);
224 }