/*
* log - logging functions
*
- * Copyright (C) 2009 Enrico Zini <enrico@enricozini.org>
+ * Copyright (C) 2009--2010 Enrico Zini <enrico@enricozini.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+using GLib;
+
namespace zavai {
namespace log {
+public class Waypoint : Object
+{
+ public time_t ts;
+ public double lat;
+ public double lon;
+
+ public Waypoint()
+ {
+ if (gps.gps.fix_status() != libgps.STATUS_NO_FIX)
+ {
+ lat = gps.gps.info().fix.latitude;
+ lon = gps.gps.info().fix.longitude;
+ ts = (time_t)gps.gps.info().fix.time;
+ } else {
+ // Use 1000 as missing values
+ lat = 1000;
+ lon = 1000;
+ ts = time_t();
+ }
+ }
+
+ public void writeInside(FileStream outfd)
+ {
+ var t = Time.gm(ts);
+ outfd.printf(" <time>%s</time>", t.format("%Y-%m-%dT%H:%M:%SZ"));
+ }
+}
+
+
+public class LogEntry : Waypoint
+{
+ public string msg;
+
+ public LogEntry()
+ {
+ Object();
+ }
+
+ public void write(FileStream outfd)
+ {
+ outfd.printf(" <wpt lat=\"%f\" lon=\"%f\">", lat, lon);
+ writeInside(outfd);
+ outfd.puts(" </wpt>");
+ }
+}
+
+public class TrackEntry : Waypoint
+{
+ public TrackEntry()
+ {
+ Object();
+ }
+
+ public void write(FileStream outfd)
+ {
+ outfd.printf(" <trkpt lat=\"%f\" lon=\"%f\">", lat, lon);
+ writeInside(outfd);
+ outfd.puts(" </trkpt>");
+ }
+}
+
+
+public class Log : Object
+{
+ public uint id;
+ public string tag;
+ public List<LogEntry> entries;
+ public List<TrackEntry> track;
+
+ public Log(uint id, string tag)
+ {
+ this.id = id;
+ this.tag = tag;
+ entries = null;
+ track = null;
+ }
+
+ public void add(string msg)
+ {
+ var entry = new LogEntry();
+ entry.msg = msg;
+ entries.append(entry);
+ }
+
+ public void save()
+ {
+ if (entries == null) return;
+
+ // Directory where we save the log
+ string dir = config.homedir + "/log-" + tag;
+
+ // First try with a plain name
+ var t = Time.local(entries.data.ts);
+ string basename = t.format("%Y%m%d-%H%M%S");
+
+ string name = basename + ".gpx";
+
+ // Find a pathname that does not exist already
+ string pathname = dir + "/" + name;
+ for (int i = 1; FileUtils.test(dir + "/" + name, FileTest.EXISTS); ++i)
+ name = "%s-%d.gpx".printf(basename, i);
+
+ // Write out
+ var outfd = FileStream.open(pathname, "w");
+ write(outfd);
+ outfd.flush();
+ }
+
+ protected void writeTrack(FileStream outfd)
+ {
+ outfd.puts(" <trk>");
+ outfd.puts(" <trkseg>");
+ for (weak List<TrackEntry> i = track; i != null; i = i.next)
+ i.data.write(outfd);
+ outfd.puts(" </trkseg>");
+ outfd.puts(" </trk>");
+ }
+
+ protected void writeEntries(FileStream outfd)
+ {
+ outfd.puts(" <wpt>");
+ for (weak List<LogEntry> i = entries; i != null; i = i.next)
+ i.data.write(outfd);
+ outfd.puts(" </wpt>");
+ }
+
+ protected void write(FileStream outfd)
+ {
+ outfd.puts("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+ outfd.puts(" <gpx");
+ outfd.puts(" version=\"1.0\"");
+ outfd.printf(" creator=\"zavai %s\"\n", zavai.config.version);
+ outfd.puts(" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
+ outfd.puts(" xmlns=\"http://www.topografix.com/GPX/1/0\"");
+ outfd.puts(" xsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
+ if (track != null) writeTrack(outfd);
+ if (entries != null) writeEntries(outfd);
+ outfd.puts(" </gpx>");
+ }
+}
+
+public class Logger : Resource, Object
+{
+ protected List<Log> logs;
+ protected uint seq;
+
+ public Logger()
+ {
+ logs = null;
+ seq = 0;
+
+ zavai.registry.register(this);
+ }
+
+ protected uint gen_seq()
+ {
+ // Increase avoiding 0 on rollover
+ while (true)
+ {
+ if (++seq == 0) ++seq;
+ bool found = false;
+ for (weak List<Log> i = logs; i != null; i = i.next)
+ {
+ if (i.data.id == seq)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found) break;
+ }
+ return seq;
+ }
+
+ protected weak Log? find(uint id)
+ {
+ for (weak List<Log> i = logs; i != null; i = i.next)
+ if (i.data.id == id)
+ return i.data;
+ return null;
+ }
+
+ protected Log? pop(uint id)
+ {
+ for (weak List<Log> i = logs; i != null; i = i.next)
+ if (i.data.id == id)
+ {
+ Log res = i.data;
+ logs.delete_link(i);
+ return res;
+ }
+ return null;
+ }
+
+ public uint start(string tag)
+ {
+ uint id = gen_seq();
+ logs.append(new Log(id, tag));
+ return id;
+ }
+
+ public void add(uint id, string msg)
+ {
+ Log log = find(id);
+ if (log == null) return;
+ log.add(msg);
+ }
+
+ public void end(uint id)
+ {
+ Log log = pop(id);
+ log.save();
+ }
+
+ public void instant(string tag, string msg)
+ {
+ var log = new Log(0, tag);
+ log.add(msg);
+ log.save();
+ }
+
+ public void shutdown()
+ {
+ while (logs != null)
+ {
+ var log = pop(logs.data.id);
+ log.save();
+ }
+ }
+}
+
public void error(string s)
{
stderr.printf("%s\n", s);
stderr.printf("%s\n", s);
}
+Logger log = null;
+
+public void init()
+{
+ log = new Logger();
+}
+
}
}