Add:Core:Made log items of gpx log configurable
[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 "util.h"
33
34 struct vehicle {
35         struct vehicle_priv *priv;
36         struct vehicle_methods meth;
37         struct callback_list *cbl;
38         struct log *nmea_log, *gpx_log;
39         struct attr **attrs;
40 };
41
42 static void
43 vehicle_log_nmea(struct vehicle *this_, struct log *log)
44 {
45         struct attr pos_attr;
46         if (!this_->meth.position_attr_get)
47                 return;
48         if (!this_->meth.position_attr_get(this_->priv, attr_position_nmea, &pos_attr))
49                 return;
50         log_write(log, pos_attr.u.str, strlen(pos_attr.u.str));
51 }
52
53 static void
54 vehicle_log_gpx(struct vehicle *this_, struct log *log)
55 {
56         struct attr attr,*attrp;
57         enum attr_type *attr_types;
58         char *logstr;
59         char *extensions="\t<extensions>\n";
60
61         if (!this_->meth.position_attr_get)
62                 return;
63         if (log_get_attr(log, attr_attr_types, &attr, NULL))
64                 attr_types=attr.u.attr_types;
65         else
66                 attr_types=NULL;
67         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &attr))
68                 return;
69         logstr=g_strdup_printf("<trkpt lat=\"%f\" lon=\"%f\">\n",attr.u.coord_geo->lat,attr.u.coord_geo->lng);
70         if (attr_types && attr_types_contains_default(attr_types, attr_position_time_iso8601, 0)) {
71                 if (this_->meth.position_attr_get(this_->priv, attr_position_time_iso8601, &attr)) {
72                         logstr=g_strconcat_printf(logstr,"\t<time>%s</time>\n",attr.u.str);
73                 } else {
74                         char *timep = current_to_iso8601();
75                         logstr=g_strconcat_printf(logstr,"\t<time>%s</time>\n",timep);
76                         g_free(timep);
77                 }
78         }
79         if (attr_types_contains_default(attr_types, attr_position_direction,0) && this_->meth.position_attr_get(this_->priv, attr_position_direction, &attr))
80                 logstr=g_strconcat_printf(logstr,"\t<course>%.1f</course>\n",*attr.u.numd);
81         if (attr_types_contains_default(attr_types, attr_position_speed, 0) && this_->meth.position_attr_get(this_->priv, attr_position_speed, &attr))
82                 logstr=g_strconcat_printf(logstr,"\t<speed>%.2f</speed>\n",*attr.u.numd);
83         if (attr_types_contains_default(attr_types, attr_profilename, 0) && (attrp=attr_search(this_->attrs, NULL, attr_profilename))) {
84                 logstr=g_strconcat_printf(logstr,"%s\t\t<navit:profilename>%s</navit:profilename>\n",extensions,attrp->u.str);
85                 extensions="";
86         }
87         if (attr_types_contains_default(attr_types, attr_position_radius, 0) && this_->meth.position_attr_get(this_->priv, attr_position_radius, &attr)) {
88                 logstr=g_strconcat_printf(logstr,"%s\t\t<navit:radius>%.2f</navit:radius>\n",extensions,*attr.u.numd);
89                 extensions="";
90         }
91         if (!strcmp(extensions,"")) {
92                 logstr=g_strconcat_printf(logstr,"\t</extensions>\n");
93                 
94         }
95         logstr=g_strconcat_printf(logstr,"</trkpt>\n");
96         log_printf(log,"%s",logstr);
97         g_free(logstr);
98 }
99
100 static void
101 vehicle_log_textfile(struct vehicle *this_, struct log *log)
102 {
103         struct attr pos_attr;
104         char buffer[256];
105         if (!this_->meth.position_attr_get)
106                 return;
107         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
108                 return;
109         sprintf(buffer,"%f %f type=trackpoint\n", pos_attr.u.coord_geo->lng, pos_attr.u.coord_geo->lat);
110         log_write(log, buffer, strlen(buffer));
111 }
112
113 static int
114 vehicle_add_log(struct vehicle *this_, struct log *log)
115 {
116         struct callback *cb;
117         struct attr type_attr;
118         if (!log_get_attr(log, attr_type, &type_attr, NULL))
119                 return 1;
120
121         if (!strcmp(type_attr.u.str, "nmea")) {
122                 cb=callback_new_2(callback_cast(vehicle_log_nmea), this_, log);
123         } else if (!strcmp(type_attr.u.str, "gpx")) {
124                 char *header = "<?xml version='1.0' encoding='UTF-8'?>\n"
125                         "<gpx version='1.1' creator='Navit http://navit.sourceforge.net'\n"
126                         "     xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n"
127                         "     xmlns:navit='http://www.navit-project.org/schema/navit'\n"
128                         "     xmlns='http://www.topografix.com/GPX/1/1'\n"
129                         "     xsi:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd'>\n"
130                         "<trk>\n"
131                         "<trkseg>\n";
132                 char *trailer = "</trkseg>\n</trk>\n</gpx>\n";
133                 log_set_header(log, header, strlen(header));
134                 log_set_trailer(log, trailer, strlen(trailer));
135                 cb=callback_new_2(callback_cast(vehicle_log_gpx), this_, log);
136         } else if (!strcmp(type_attr.u.str, "textfile")) {
137                 char *header = "type=track\n";
138                 log_set_header(log, header, strlen(header));
139                 cb=callback_new_2(callback_cast(vehicle_log_textfile), this_, log);
140         } else
141                 return 1;
142         callback_list_add(this_->cbl, cb);
143         return 0;
144 }
145
146 struct vehicle *
147 vehicle_new(struct attr *parent, struct attr **attrs)
148 {
149         struct vehicle *this_;
150         struct attr *source;
151         struct vehicle_priv *(*vehicletype_new) (struct vehicle_methods *
152                                                  meth,
153                                                  struct callback_list *
154                                                  cbl,
155                                                  struct attr ** attrs);
156         char *type, *colon;
157
158         dbg(1, "enter\n");
159         source = attr_search(attrs, NULL, attr_source);
160         if (!source) {
161                 dbg(0, "no source\n");
162                 return NULL;
163         }
164
165         type = g_strdup(source->u.str);
166         colon = strchr(type, ':');
167         if (colon)
168                 *colon = '\0';
169         dbg(1, "source='%s' type='%s'\n", source->u.str, type);
170
171         vehicletype_new = plugin_get_vehicle_type(type);
172         if (!vehicletype_new) {
173                 dbg(0, "invalid type '%s'\n", type);
174                 return NULL;
175         }
176         this_ = g_new0(struct vehicle, 1);
177         this_->cbl = callback_list_new();
178         this_->priv = vehicletype_new(&this_->meth, this_->cbl, attrs);
179         if (!this_->priv) {
180                 dbg(0, "vehicletype_new failed\n");
181                 callback_list_destroy(this_->cbl);
182                 g_free(this_);
183                 return NULL;
184         }
185         this_->attrs=attr_list_dup(attrs);
186         dbg(1, "leave\n");
187
188         return this_;
189 }
190
191 int
192 vehicle_get_attr(struct vehicle *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
193 {
194         int ret;
195         if (this_->meth.position_attr_get) {
196                 ret=this_->meth.position_attr_get(this_->priv, type, attr);
197                 if (ret)
198                         return ret;
199         }
200         return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
201 }
202
203 int
204 vehicle_set_attr(struct vehicle *this_, struct attr *attr,
205                  struct attr **attrs)
206 {
207         int ret=1;
208         if (this_->meth.set_attr)
209                 ret=this_->meth.set_attr(this_->priv, attr, attrs);
210         if (ret == 1 && attr->type != attr_navit)
211                 this_->attrs=attr_generic_set_attr(this_->attrs, attr);
212         return ret != 0;
213 }
214
215 int
216 vehicle_add_attr(struct vehicle *this_, struct attr *attr)
217 {
218         int ret=1;
219         switch (attr->type) {
220         case attr_callback:
221                 callback_list_add(this_->cbl, attr->u.callback);
222                 break;
223         case attr_log:
224                 ret=vehicle_add_log(this_, attr->u.log);
225                 break;
226         default:
227                 break;
228         }
229         if (ret)
230                 this_->attrs=attr_generic_add_attr(this_->attrs, attr);
231         return ret;
232 }
233
234 int
235 vehicle_remove_attr(struct vehicle *this_, struct attr *attr)
236 {
237         switch (attr->type) {
238         case attr_callback:
239                 callback_list_remove(this_->cbl, attr->u.callback);
240                 break;
241         default:
242                 return 0;
243         }
244         return 1;
245 }
246
247 void
248 vehicle_destroy(struct vehicle *this_)
249 {
250         this_->meth.destroy(this_->priv);
251         callback_list_destroy(this_->cbl);
252         attr_list_free(this_->attrs);
253         g_free(this_);
254 }