2 * log - logging functions
4 * Copyright (C) 2009--2010 Enrico Zini <enrico@enricozini.org>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 public class Waypoint : Object
34 if (gps.gps.fix_status() != libgps.STATUS_NO_FIX)
36 lat = gps.gps.info().fix.latitude;
37 lon = gps.gps.info().fix.longitude;
38 ts = (time_t)gps.gps.info().fix.time;
40 // Use 1000 as missing values
47 public void writeInside(FileStream outfd)
50 outfd.printf(" <time>%s</time>\n", t.format("%Y-%m-%dT%H:%M:%SZ"));
55 public class LogEntry : Waypoint
64 public void write(FileStream outfd)
66 outfd.printf(" <wpt lat=\"%f\" lon=\"%f\">\n", lat, lon);
68 outfd.printf(" <name>%s</name>\n", Markup.escape_text(msg));
69 outfd.puts(" </wpt>\n");
73 public class TrackEntry : Waypoint
80 public void write(FileStream outfd)
82 outfd.printf(" <trkpt lat=\"%f\" lon=\"%f\">\n", lat, lon);
84 outfd.puts(" </trkpt>\n");
89 public class Log : Object
93 public List<LogEntry> entries;
94 public List<TrackEntry> track;
96 public Log(string tag, string title)
104 public void add(string msg)
106 var entry = new LogEntry();
108 entries.append(entry);
111 public void add_trackpoint()
113 track.append(new TrackEntry());
118 if (entries == null) return;
120 // Directory where we save the log
121 string dir = config.homedir + "/log-" + tag;
122 DirUtils.create(dir, 0777);
124 // First try with a plain name
125 var t = Time.local(entries.data.ts);
126 string basename = dir + "/" + t.format("%Y%m%d-%H%M%S");
128 string pathname = basename + ".gpx";
130 // Find a pathname that does not exist already
131 for (int i = 1; FileUtils.test(pathname, FileTest.EXISTS); ++i)
132 pathname = "%s-%d.gpx".printf(basename, i);
135 var outfd = FileStream.open(pathname, "w");
138 zavai.log.error("opening " + pathname + ": " + strerror(errno));
146 protected void writeTrack(FileStream outfd)
148 outfd.puts(" <trk>\n");
149 outfd.puts(" <trkseg>\n");
150 for (weak List<TrackEntry> i = track; i != null; i = i.next)
152 outfd.puts(" </trkseg>\n");
153 outfd.puts(" </trk>\n");
156 protected void writeEntries(FileStream outfd)
158 outfd.puts(" <wpt>\n");
159 for (weak List<LogEntry> i = entries; i != null; i = i.next)
161 outfd.puts(" </wpt>\n");
164 protected void write(FileStream outfd)
166 outfd.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
167 outfd.puts("<gpx version=\"1.0\"\n");
168 outfd.printf(" creator=\"zavai %s\"\n", zavai.config.version);
169 outfd.puts(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
170 outfd.puts(" xmlns=\"http://www.topografix.com/GPX/1/0\"\n");
171 outfd.puts(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">\n");
172 outfd.puts(" <metadata>\n");
173 outfd.printf(" <name>%s</name>\n", Markup.escape_text(title));
174 outfd.puts(" </metadata>\n");
175 if (track != null) writeTrack(outfd);
176 if (entries != null) writeEntries(outfd);
177 outfd.puts(" </gpx>\n");
181 enum LogParserState {
188 class LogParser: Object
190 const MarkupParser parser = { // It's a structure, not an object
191 start,// when an element opens
192 end, // when an element closes
193 text, // when text is found
194 null, // when comments are found
195 null // when errors occur
198 MarkupParseContext context = null;
199 public Log result = null;
200 LogParserState state = LogParserState.NONE;
201 string cur_text = "";
205 context = new MarkupParseContext(
206 parser, // the structure with the callbacks
207 0, // MarkupParseFlags
208 this, // extra argument for the callbacks, methods in this case
209 destroy // when the parsing ends
218 public bool parse(string content, ssize_t len = -1) throws MarkupError
220 return context.parse(content, len);
225 outfd.puts(" <metadata>\n");
226 outfd.printf(" <name>%s</name>\n", Markup.escape_text(title));
227 outfd.puts(" </metadata>\n");
228 if (track != null) writeTrack(outfd);
229 if (entries != null) writeEntries(outfd);
230 outfd.puts(" </gpx>\n");
234 void start (MarkupParseContext context, string name,
235 string[] attr_names, string[] attr_values) throws MarkupError
239 state = LogParserState.NONE;
240 result = new Log("TODO:TAG", "TODO:TITLE");
241 } else if (name == "metadata") {
242 state = LogParserState.METADATA;
243 } else if (name == "wpt") {
244 state = LogParserState.WPT;
245 } else if (name == "trkseg") {
246 state = LogParserState.TRACK;
251 void end (MarkupParseContext context, string name) throws MarkupError
254 if (state == LogParserState.METADATA)
255 result.title = cur_text;
258 void text (MarkupParseContext context,
259 string text, size_t text_len) throws MarkupError
265 public class Logger : Resource, Object
267 protected List<Log> logs;
272 zavai.registry.register(this);
275 protected void start_trace()
277 gps.gps.pos_changed += on_pos_changed;
280 protected void end_trace()
282 gps.gps.pos_changed -= on_pos_changed;
285 protected void on_pos_changed()
287 for (weak List<Log> i = logs; i != null; i = i.next)
288 i.data.add_trackpoint();
291 protected void pop(Log log)
293 for (weak List<Log> i = logs; i != null; i = i.next)
298 public Log start(string tag, string title)
300 bool was_empty = (logs == null);
301 Log res = new Log(tag, title);
303 if (was_empty) start_trace();
307 public void end(Log log)
311 if (logs == null) end_trace();
314 public Log load(string fname)
318 FileUtils.get_contents(fname, out contents, out length);
319 LogParser parser = new LogParser();
320 parser.parse(contents, (ssize_t)length);
321 return parser.result;
324 public void instant(string tag, string msg)
326 var log = new Log(tag, msg);
331 public void shutdown()
333 bool had_logs = (logs != null);
337 logs.delete_link(logs);
339 if (had_logs) end_trace();
343 public void error(string s)
345 stderr.printf("%s\n", s);
347 public void warning(string s)
349 stderr.printf("%s\n", s);
351 public void info(string s)
353 stderr.printf("%s\n", s);
355 public void debug(string s)
357 stderr.printf("%s\n", s);