Fix:vehicle_gpsd:Auto-Start gpsd on maemo
[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
61         if (!this_->meth.position_attr_get)
62                 return;
63         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
64                 return;
65         if (!this_->meth.position_attr_get(this_->priv, attr_position_time_iso8601, &time_attr)) {
66 #ifdef HAVE_GLIB
67                 GTimeVal time; 
68                 g_get_current_time(&time); 
69                 timep = g_time_val_to_iso8601(&time);
70                 sprintf(tbuf, "%s", timep);
71                 g_free(timep);
72                 timep = tbuf;
73 #else
74                 time_t tnow;
75                 struct tm *tm;
76                 tnow = time(0);
77                 tm = gmtime(&tnow);
78                 if (tm) {
79                         strftime(tbuf, sizeof(tbuf),
80                                 "%Y-%m-%dT%TZ", tm);
81                 }
82                 timep = tbuf;
83 #endif
84         } else {
85                 timep = time_attr.u.str;
86         }
87         sprintf(buffer,"<trkpt lat=\"%f\" lon=\"%f\">\n\t<time>%s</time>\n</trkpt>\n",
88                 pos_attr.u.coord_geo->lat, pos_attr.u.coord_geo->lng, timep);
89         log_write(log, buffer, strlen(buffer));
90 }
91
92 static void
93 vehicle_log_textfile(struct vehicle *this_, struct log *log)
94 {
95         struct attr pos_attr;
96         char buffer[256];
97         if (!this_->meth.position_attr_get)
98                 return;
99         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
100                 return;
101         sprintf(buffer,"%f %f type=trackpoint\n", pos_attr.u.coord_geo->lng, pos_attr.u.coord_geo->lat);
102         log_write(log, buffer, strlen(buffer));
103 }
104
105 static int
106 vehicle_add_log(struct vehicle *this_, struct log *log)
107 {
108         struct callback *cb;
109         struct attr type_attr;
110         if (!log_get_attr(log, attr_type, &type_attr, NULL))
111                 return 1;
112
113         if (!strcmp(type_attr.u.str, "nmea")) {
114                 cb=callback_new_2(callback_cast(vehicle_log_nmea), this_, log);
115         } else if (!strcmp(type_attr.u.str, "gpx")) {
116                 char *header =
117                     "<?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";
118                 char *trailer = "</trkseg>\n</trk>\n</gpx>\n";
119                 log_set_header(log, header, strlen(header));
120                 log_set_trailer(log, trailer, strlen(trailer));
121                 cb=callback_new_2(callback_cast(vehicle_log_gpx), this_, log);
122         } else if (!strcmp(type_attr.u.str, "textfile")) {
123                 char *header = "type=track\n";
124                 log_set_header(log, header, strlen(header));
125                 cb=callback_new_2(callback_cast(vehicle_log_textfile), this_, log);
126         } else
127                 return 1;
128         callback_list_add(this_->cbl, cb);
129         return 0;
130 }
131
132 struct vehicle *
133 vehicle_new(struct attr *parent, struct attr **attrs)
134 {
135         struct vehicle *this_;
136         struct attr *source;
137         struct vehicle_priv *(*vehicletype_new) (struct vehicle_methods *
138                                                  meth,
139                                                  struct callback_list *
140                                                  cbl,
141                                                  struct attr ** attrs);
142         char *type, *colon;
143
144         dbg(1, "enter\n");
145         source = attr_search(attrs, NULL, attr_source);
146         if (!source) {
147                 dbg(0, "no source\n");
148                 return NULL;
149         }
150
151         type = g_strdup(source->u.str);
152         colon = strchr(type, ':');
153         if (colon)
154                 *colon = '\0';
155         dbg(1, "source='%s' type='%s'\n", source->u.str, type);
156
157         vehicletype_new = plugin_get_vehicle_type(type);
158         if (!vehicletype_new) {
159                 dbg(0, "invalid type '%s'\n", type);
160                 return NULL;
161         }
162         this_ = g_new0(struct vehicle, 1);
163         this_->cbl = callback_list_new();
164         this_->priv = vehicletype_new(&this_->meth, this_->cbl, attrs);
165         if (!this_->priv) {
166                 dbg(0, "vehicletype_new failed\n");
167                 callback_list_destroy(this_->cbl);
168                 g_free(this_);
169                 return NULL;
170         }
171         this_->attrs=attr_list_dup(attrs);
172         dbg(1, "leave\n");
173
174         return this_;
175 }
176
177 int
178 vehicle_get_attr(struct vehicle *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
179 {
180         int ret;
181         if (this_->meth.position_attr_get) {
182                 ret=this_->meth.position_attr_get(this_->priv, type, attr);
183                 if (ret)
184                         return ret;
185         }
186         return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
187 }
188
189 int
190 vehicle_set_attr(struct vehicle *this_, struct attr *attr,
191                  struct attr **attrs)
192 {
193         if (this_->meth.set_attr)
194                 return this_->meth.set_attr(this_->priv, attr, attrs);
195         return 0;
196 }
197
198 int
199 vehicle_add_attr(struct vehicle *this_, struct attr *attr)
200 {
201         int ret=1;
202         switch (attr->type) {
203         case attr_callback:
204                 callback_list_add(this_->cbl, attr->u.callback);
205                 break;
206         case attr_log:
207                 ret=vehicle_add_log(this_, attr->u.log);
208                 break;
209         default:
210                 break;
211         }
212         if (ret)
213                 this_->attrs=attr_generic_add_attr(this_->attrs, attr);
214         return ret;
215 }
216
217 int
218 vehicle_remove_attr(struct vehicle *this_, struct attr *attr)
219 {
220         switch (attr->type) {
221         case attr_callback:
222                 callback_list_remove(this_->cbl, attr->u.callback);
223                 break;
224         default:
225                 return 0;
226         }
227         return 1;
228 }
229
230 void
231 vehicle_destroy(struct vehicle *this_)
232 {
233         this_->meth.destroy(this_->priv);
234         callback_list_destroy(this_->cbl);
235         attr_list_free(this_->attrs);
236         g_free(this_);
237 }