/* * clock - clock resource for zavai * * Copyright (C) 2009 Enrico Zini * * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ using GLib; namespace zavai { namespace clock { public enum SourceType { SYSTEM, GPS } public class Alarm : Object { public signal void trigger(); public time_t deadline; public string label; public Alarm(time_t deadline, string label) { this.deadline = deadline; this.label = label; } } private int alarm_compare(void* a, void* b) { return (int)(((Alarm*)a)->deadline - ((Alarm*)b)->deadline); } public class Clock: zavai.Service { protected time_t last_gps_time; protected time_t last_gps_time_system_time; protected time_t last_system_time; protected dynamic DBus.Object gps_time; protected uint system_time_timeout; protected time_t last_minute; protected time_t chosen_time; protected SourceType chosen_type; protected dynamic DBus.Object otimed_alarm; protected dynamic DBus.Object notification; protected SList alarms; // Ticks once a minute public signal void minute_changed(long time, SourceType source); public Clock() { name = "clock"; alarms = null; last_minute = 0; last_gps_time = 0; last_gps_time_system_time = 0; last_system_time = time_t(); chosen_time = last_system_time; gps_time = zavai.registry.sbus.get_object( "org.freesmartphone.ogpsd", "/org/freedesktop/Gypsy", "org.freedesktop.Gypsy.Time"); // FSO alarm system otimed_alarm = zavai.registry.sbus.get_object( "org.freesmartphone.otimed", "/org/freesmartphone/Time/Alarm", "org.freesmartphone.Time.Alarm"); notification = zavai.registry.sbus.get_object( "org.freesmartphone", "org/freesmartphone/Notification", "org.freesmartphone.Notification"); notification.Alarm += on_alarm; } public void schedule(Alarm a) { alarms.insert_sorted(a, alarm_compare); zavai.log.info("Next alarm: " + alarms.data.label + " at " + Time.local(alarms.data.deadline).to_string()); otimed_reschedule(); } private void otimed_reschedule() { if (alarms != null) { try { otimed_alarm.ClearAlarm(zavai.registry.bus_name); otimed_alarm.SetAlarm(zavai.registry.bus_name, alarms.data.deadline); } catch (Error e) { zavai.log.error("Cannot reschedule alarms: " + e.message); } } } private void on_alarm() { check_alarms(); } public void check_alarms() { last_system_time = time_t(); update_time(); while (alarms != null && alarms.data.deadline <= chosen_time) { Alarm a = alarms.data; alarms.remove(a); zavai.log.info("Triggering " + a.label); a.trigger(); } otimed_reschedule(); } private void on_gps_time(dynamic DBus.Object pos, int t) { if (t == 0) { last_gps_time_system_time = 0; update_time(); } else { last_gps_time = (time_t)t; last_gps_time_system_time = time_t(); update_time(); } } private bool on_system_time() { last_system_time = time_t(); update_time(); return true; } private void update_time() { if (last_gps_time_system_time + 10 > last_system_time) { chosen_time = last_gps_time; chosen_type = SourceType.GPS; } else { chosen_time = last_system_time; chosen_type = SourceType.SYSTEM; } if (chosen_time / 60 != last_minute) { last_minute = chosen_time / 60; minute_changed(chosen_time, chosen_type); } } /// Request GPS resource public override void start() { if (started) return; system_time_timeout = Timeout.add(5000, on_system_time); gps_time.TimeChanged += on_gps_time; last_system_time = time_t(); update_time(); base.start(); } public override void stop() { if (!started) return; Source.remove(system_time_timeout); gps_time.TimeChanged -= on_gps_time; base.stop(); } } public Clock clock = null; public void init() { clock = new Clock(); zavai.registry.register_service(clock); } } }