Fix:core:Fixed various compiler warnings
[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 #include "transform.h"
33 #include "util.h"
34
35 struct vehicle {
36         struct vehicle_priv *priv;
37         struct vehicle_methods meth;
38         struct callback_list *cbl;
39         struct log *nmea_log, *gpx_log;
40         struct attr **attrs;
41 };
42
43 static void
44 vehicle_log_nmea(struct vehicle *this_, struct log *log)
45 {
46         struct attr pos_attr;
47         if (!this_->meth.position_attr_get)
48                 return;
49         if (!this_->meth.position_attr_get(this_->priv, attr_position_nmea, &pos_attr))
50                 return;
51         log_write(log, pos_attr.u.str, strlen(pos_attr.u.str), 0);
52 }
53
54 static void
55 vehicle_log_gpx(struct vehicle *this_, struct log *log)
56 {
57         struct attr attr,*attrp;
58         enum attr_type *attr_types;
59         char *logstr;
60         char *extensions="\t<extensions>\n";
61
62         if (!this_->meth.position_attr_get)
63                 return;
64         if (log_get_attr(log, attr_attr_types, &attr, NULL))
65                 attr_types=attr.u.attr_types;
66         else
67                 attr_types=NULL;
68         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &attr))
69                 return;
70         logstr=g_strdup_printf("<trkpt lat=\"%f\" lon=\"%f\">\n",attr.u.coord_geo->lat,attr.u.coord_geo->lng);
71         if (attr_types && attr_types_contains_default(attr_types, attr_position_time_iso8601, 0)) {
72                 if (this_->meth.position_attr_get(this_->priv, attr_position_time_iso8601, &attr)) {
73                         logstr=g_strconcat_printf(logstr,"\t<time>%s</time>\n",attr.u.str);
74                 } else {
75                         char *timep = current_to_iso8601();
76                         logstr=g_strconcat_printf(logstr,"\t<time>%s</time>\n",timep);
77                         g_free(timep);
78                 }
79         }
80         if (attr_types_contains_default(attr_types, attr_position_direction,0) && this_->meth.position_attr_get(this_->priv, attr_position_direction, &attr))
81                 logstr=g_strconcat_printf(logstr,"\t<course>%.1f</course>\n",*attr.u.numd);
82         if (attr_types_contains_default(attr_types, attr_position_speed, 0) && this_->meth.position_attr_get(this_->priv, attr_position_speed, &attr))
83                 logstr=g_strconcat_printf(logstr,"\t<speed>%.2f</speed>\n",*attr.u.numd);
84         if (attr_types_contains_default(attr_types, attr_profilename, 0) && (attrp=attr_search(this_->attrs, NULL, attr_profilename))) {
85                 logstr=g_strconcat_printf(logstr,"%s\t\t<navit:profilename>%s</navit:profilename>\n",extensions,attrp->u.str);
86                 extensions="";
87         }
88         if (attr_types_contains_default(attr_types, attr_position_radius, 0) && this_->meth.position_attr_get(this_->priv, attr_position_radius, &attr)) {
89                 logstr=g_strconcat_printf(logstr,"%s\t\t<navit:radius>%.2f</navit:radius>\n",extensions,*attr.u.numd);
90                 extensions="";
91         }
92         if (!strcmp(extensions,"")) {
93                 logstr=g_strconcat_printf(logstr,"\t</extensions>\n");
94         }
95         logstr=g_strconcat_printf(logstr,"</trkpt>\n");
96         callback_list_call_attr_1(this_->cbl, attr_log_gpx, &logstr);
97         log_write(log, logstr, strlen(logstr), 0);
98         g_free(logstr);
99 }
100
101 static void
102 vehicle_log_textfile(struct vehicle *this_, struct log *log)
103 {
104         struct attr pos_attr;
105         char *logstr;
106         if (!this_->meth.position_attr_get)
107                 return;
108         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
109                 return;
110         logstr=g_strdup_printf("%f %f type=trackpoint\n", pos_attr.u.coord_geo->lng, pos_attr.u.coord_geo->lat);
111         callback_list_call_attr_1(this_->cbl, attr_log_textfile, &logstr);
112         log_write(log, logstr, strlen(logstr), 0);
113 }
114
115 static void
116 vehicle_log_binfile(struct vehicle *this_, struct log *log)
117 {
118         struct attr pos_attr;
119         int *buffer;
120         int *buffer_new;
121         int len,limit=1024,done=0,radius=25;
122         struct coord c;
123         enum log_flags flags;
124
125         if (!this_->meth.position_attr_get)
126                 return;
127         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
128                 return;
129         transform_from_geo(projection_mg, pos_attr.u.coord_geo, &c);
130         if (!c.x || !c.y)
131                 return;
132         while (!done) {
133                 buffer=log_get_buffer(log, &len);
134                 if (! buffer || !len) {
135                         buffer_new=g_malloc(5*sizeof(int));
136                         buffer_new[0]=2;
137                         buffer_new[1]=type_track;
138                         buffer_new[2]=0;
139                 } else {
140                         buffer_new=g_malloc((buffer[0]+3)*sizeof(int));
141                         memcpy(buffer_new, buffer, (buffer[0]+1)*sizeof(int));
142                 }
143                 dbg(1,"c=0x%x,0x%x\n",c.x,c.y);
144                 buffer_new[buffer_new[0]+1]=c.x;
145                 buffer_new[buffer_new[0]+2]=c.y;
146                 buffer_new[0]+=2;
147                 buffer_new[2]+=2;
148                 if (buffer_new[2] > limit) {
149                         int count=buffer_new[2]/2;
150                         struct coord out[count];
151                         struct coord *in=(struct coord *)(buffer_new+3);
152                         int count_out=transform_douglas_peucker(in, count, radius, out);
153                         memcpy(in, out, count_out*2*sizeof(int));
154                         buffer_new[0]+=(count_out-count)*2;     
155                         buffer_new[2]+=(count_out-count)*2;     
156                         flags=log_flag_replace_buffer|log_flag_force_flush|log_flag_truncate;
157                 } else {
158                         flags=log_flag_replace_buffer|log_flag_keep_pointer|log_flag_keep_buffer|log_flag_force_flush;
159                         done=1;
160                 }
161                 log_write(log, (char *)buffer_new, (buffer_new[0]+1)*sizeof(int), flags);
162         }
163 }
164
165 static int
166 vehicle_add_log(struct vehicle *this_, struct log *log)
167 {
168         struct callback *cb;
169         struct attr type_attr;
170         if (!log_get_attr(log, attr_type, &type_attr, NULL))
171                 return 1;
172
173         if (!strcmp(type_attr.u.str, "nmea")) {
174                 cb=callback_new_attr_2(callback_cast(vehicle_log_nmea), attr_position_coord_geo, this_, log);
175         } else if (!strcmp(type_attr.u.str, "gpx")) {
176                 char *header = "<?xml version='1.0' encoding='UTF-8'?>\n"
177                         "<gpx version='1.1' creator='Navit http://navit.sourceforge.net'\n"
178                         "     xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n"
179                         "     xmlns:navit='http://www.navit-project.org/schema/navit'\n"
180                         "     xmlns='http://www.topografix.com/GPX/1/1'\n"
181                         "     xsi:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd'>\n"
182                         "<trk>\n"
183                         "<trkseg>\n";
184                 char *trailer = "</trkseg>\n</trk>\n</gpx>\n";
185                 log_set_header(log, header, strlen(header));
186                 log_set_trailer(log, trailer, strlen(trailer));
187                 cb=callback_new_attr_2(callback_cast(vehicle_log_gpx), attr_position_coord_geo, this_, log);
188         } else if (!strcmp(type_attr.u.str, "textfile")) {
189                 char *header = "type=track\n";
190                 log_set_header(log, header, strlen(header));
191                 cb=callback_new_attr_2(callback_cast(vehicle_log_textfile), attr_position_coord_geo, this_, log);
192         } else if (!strcmp(type_attr.u.str, "binfile")) {
193                 cb=callback_new_attr_2(callback_cast(vehicle_log_binfile), attr_position_coord_geo, this_, log);
194         } else
195                 return 1;
196         callback_list_add(this_->cbl, cb);
197         return 0;
198 }
199
200 struct vehicle *
201 vehicle_new(struct attr *parent, struct attr **attrs)
202 {
203         struct vehicle *this_;
204         struct attr *source;
205         struct vehicle_priv *(*vehicletype_new) (struct vehicle_methods *
206                                                  meth,
207                                                  struct callback_list *
208                                                  cbl,
209                                                  struct attr ** attrs);
210         char *type, *colon;
211
212         dbg(1, "enter\n");
213         source = attr_search(attrs, NULL, attr_source);
214         if (!source) {
215                 dbg(0, "no source\n");
216                 return NULL;
217         }
218
219         type = g_strdup(source->u.str);
220         colon = strchr(type, ':');
221         if (colon)
222                 *colon = '\0';
223         dbg(1, "source='%s' type='%s'\n", source->u.str, type);
224
225         vehicletype_new = plugin_get_vehicle_type(type);
226         if (!vehicletype_new) {
227                 dbg(0, "invalid type '%s'\n", type);
228                 return NULL;
229         }
230         this_ = g_new0(struct vehicle, 1);
231         this_->cbl = callback_list_new();
232         this_->priv = vehicletype_new(&this_->meth, this_->cbl, attrs);
233         if (!this_->priv) {
234                 dbg(0, "vehicletype_new failed\n");
235                 callback_list_destroy(this_->cbl);
236                 g_free(this_);
237                 return NULL;
238         }
239         this_->attrs=attr_list_dup(attrs);
240         dbg(1, "leave\n");
241
242         return this_;
243 }
244
245 struct attr_iter *
246 vehicle_attr_iter_new(void)
247 {
248         return g_new0(struct attr_iter,1);
249 }
250
251 void
252 vehicle_attr_iter_destroy(struct attr_iter *iter)
253 {
254         g_free(iter);
255 }
256
257
258 int
259 vehicle_get_attr(struct vehicle *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
260 {
261         int ret;
262         if (this_->meth.position_attr_get) {
263                 ret=this_->meth.position_attr_get(this_->priv, type, attr);
264                 if (ret)
265                         return ret;
266         }
267         return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
268 }
269
270 int
271 vehicle_set_attr(struct vehicle *this_, struct attr *attr,
272                  struct attr **attrs)
273 {
274         int ret=1;
275         if (this_->meth.set_attr)
276                 ret=this_->meth.set_attr(this_->priv, attr, attrs);
277         if (ret == 1 && attr->type != attr_navit)
278                 this_->attrs=attr_generic_set_attr(this_->attrs, attr);
279         return ret != 0;
280 }
281
282 int
283 vehicle_add_attr(struct vehicle *this_, struct attr *attr)
284 {
285         int ret=1;
286         switch (attr->type) {
287         case attr_callback:
288                 callback_list_add(this_->cbl, attr->u.callback);
289                 break;
290         case attr_log:
291                 ret=vehicle_add_log(this_, attr->u.log);
292                 break;
293         default:
294                 break;
295         }
296         if (ret)
297                 this_->attrs=attr_generic_add_attr(this_->attrs, attr);
298         return ret;
299 }
300
301 int
302 vehicle_remove_attr(struct vehicle *this_, struct attr *attr)
303 {
304         switch (attr->type) {
305         case attr_callback:
306                 callback_list_remove(this_->cbl, attr->u.callback);
307                 break;
308         default:
309                 return 0;
310         }
311         return 1;
312 }
313
314 void
315 vehicle_destroy(struct vehicle *this_)
316 {
317         this_->meth.destroy(this_->priv);
318         callback_list_destroy(this_->cbl);
319         attr_list_free(this_->attrs);
320         g_free(this_);
321 }