Fix:core:More descriptive error messages
[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 "config.h"
24 #include "debug.h"
25 #include "coord.h"
26 #include "item.h"
27 #include "log.h"
28 #include "callback.h"
29 #include "plugin.h"
30 #include "vehicle.h"
31
32 struct vehicle {
33         char *name;
34         struct vehicle_priv *priv;
35         struct vehicle_methods meth;
36         struct callback_list *cbl;
37         struct log *nmea_log, *gpx_log;
38 };
39
40 static void
41 vehicle_log_nmea(struct vehicle *this_, struct log *log)
42 {
43         struct attr pos_attr;
44         if (!this_->meth.position_attr_get)
45                 return;
46         if (!this_->meth.position_attr_get(this_->priv, attr_position_nmea, &pos_attr))
47                 return;
48         log_write(log, pos_attr.u.str, strlen(pos_attr.u.str));
49 }
50
51 static void
52 vehicle_log_gpx(struct vehicle *this_, struct log *log)
53 {
54         struct attr pos_attr;
55         char buffer[256];
56         if (!this_->meth.position_attr_get)
57                 return;
58         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
59                 return;
60         sprintf(buffer,"<trkpt lat=\"%f\" lon=\"%f\" />\n", pos_attr.u.coord_geo->lat, pos_attr.u.coord_geo->lng);
61         log_write(log, buffer, strlen(buffer));
62 }
63
64
65 static void
66 vehicle_log_textfile(struct vehicle *this_, struct log *log)
67 {
68         struct attr pos_attr;
69         char buffer[256];
70         if (!this_->meth.position_attr_get)
71                 return;
72         if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
73                 return;
74         sprintf(buffer,"%f %f type=trackpoint\n", pos_attr.u.coord_geo->lng, pos_attr.u.coord_geo->lat);
75         log_write(log, buffer, strlen(buffer));
76 }
77
78 static int
79 vehicle_add_log(struct vehicle *this_, struct log *log)
80 {
81         struct callback *cb;
82         struct attr type_attr;
83         if (!log_get_attr(log, attr_type, &type_attr, NULL))
84                 return 1;
85
86         if (!strcmp(type_attr.u.str, "nmea")) {
87                 cb=callback_new_2(callback_cast(vehicle_log_nmea), this_, log);
88         } else if (!strcmp(type_attr.u.str, "gpx")) {
89                 char *header =
90                     "<?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";
91                 char *trailer = "</trkseg>\n</trk>\n</gpx>\n";
92                 log_set_header(log, header, strlen(header));
93                 log_set_trailer(log, trailer, strlen(trailer));
94                 cb=callback_new_2(callback_cast(vehicle_log_gpx), this_, log);
95         } else if (!strcmp(type_attr.u.str, "textfile")) {
96                 char *header = "type=track\n";
97                 log_set_header(log, header, strlen(header));
98                 cb=callback_new_2(callback_cast(vehicle_log_textfile), this_, log);
99         } else
100                 return 1;
101         callback_list_add(this_->cbl, cb);
102         return 0;
103 }
104
105 struct vehicle *
106 vehicle_new(struct attr **attrs)
107 {
108         struct vehicle *this_;
109         struct attr *source;
110         struct vehicle_priv *(*vehicletype_new) (struct vehicle_methods *
111                                                  meth,
112                                                  struct callback_list *
113                                                  cbl,
114                                                  struct attr ** attrs);
115         char *type, *colon;
116         struct attr *name;
117
118         dbg(1, "enter\n");
119         source = attr_search(attrs, NULL, attr_source);
120         if (!source) {
121                 dbg(0, "no source\n");
122                 return NULL;
123         }
124
125         type = g_strdup(source->u.str);
126         colon = index(type, ':');
127         if (colon)
128                 *colon = '\0';
129         dbg(1, "source='%s' type='%s'\n", source->u.str, type);
130
131         vehicletype_new = plugin_get_vehicle_type(type);
132         if (!vehicletype_new) {
133                 dbg(0, "invalid type '%s'\n", type);
134                 return NULL;
135         }
136         this_ = g_new0(struct vehicle, 1);
137         this_->cbl = callback_list_new();
138         this_->priv = vehicletype_new(&this_->meth, this_->cbl, attrs);
139         if (!this_->priv) {
140                 dbg(0, "vehicletype_new failed\n");
141                 callback_list_destroy(this_->cbl);
142                 g_free(this_);
143                 return NULL;
144         }
145         dbg(1, "leave\n");
146
147         if ((name=attr_search(attrs, NULL, attr_name))) {
148                 this_->name=g_strdup(name->u.str);
149         } else {
150                 this_->name=g_strdup("Noname");
151         }
152         return this_;
153 }
154
155 int
156 vehicle_get_attr(struct vehicle *this_, enum attr_type type, struct attr *attr)
157 {
158         switch (type) {
159         case attr_name:
160                 attr->u.str=this_->name;
161                 break;
162         default:
163                 if (this_->meth.position_attr_get) {
164                         return this_->meth.position_attr_get(this_->priv, type, attr);
165                 } else {
166                         return 0;
167                 }
168         }
169         attr->type=type;
170         return 1;
171 }
172
173 int
174 vehicle_set_attr(struct vehicle *this_, struct attr *attr,
175                  struct attr **attrs)
176 {
177         if (this_->meth.set_attr)
178                 return this_->meth.set_attr(this_->priv, attr, attrs);
179         return 0;
180 }
181
182 int
183 vehicle_add_attr(struct vehicle *this_, struct attr *attr)
184 {
185         switch (attr->type) {
186         case attr_callback:
187                 callback_list_add(this_->cbl, attr->u.callback);
188                 break;
189         case attr_log:
190                 return vehicle_add_log(this_, attr->u.log);
191         default:
192                 return 0;
193         }
194         return 1;
195 }
196
197 int
198 vehicle_remove_attr(struct vehicle *this_, struct attr *attr)
199 {
200         switch (attr->type) {
201         case attr_callback:
202                 callback_list_remove(this_->cbl, attr->u.callback);
203                 break;
204         default:
205                 return 0;
206         }
207         return 1;
208 }
209
210 void
211 vehicle_destroy(struct vehicle *this_)
212 {
213         callback_list_destroy(this_->cbl);
214         if(this_->name) g_free(this_->name);
215         g_free(this_);
216 }