/* * 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(Alarm a); 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); } [DBus (name = "org.freesmartphone.Notification")] public class AlarmNotification : Object { public void Alarm () { clock.check_alarms(); } } 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 AlarmNotification listener; protected dynamic DBus.Object otimed_alarm; protected dynamic DBus.Object rtc; protected SList alarms; // Ticks once a minute public signal void minute_changed(long time, SourceType source); public signal void schedule_changed(); public Clock() { name = "clock"; alarms = null; listener = new AlarmNotification(); 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"); rtc = zavai.registry.sbus.get_object( "org.freesmartphone.odeviced", "/org/freesmartphone/Device/RTC/0", "org.freesmartphone.Device.RealTimeClock"); zavai.registry.sbus.register_object("/", listener); } public Alarm? next_alarm() { if (alarms == null) return null; return alarms.data; } public void schedule(Alarm a) { alarms.insert_sorted(a, alarm_compare); otimed_reschedule(); } private void otimed_reschedule() { if (alarms != null) { zavai.log.info("Scheduling next alarm: " + alarms.data.label + " at " + Time.local(alarms.data.deadline).to_string()); zavai.log.info("Scheduling at abs " + "%d".printf((int)alarms.data.deadline)); try { otimed_alarm.ClearAlarm(zavai.registry.bus_name); } catch (Error e) { zavai.log.error("Cannot clear alarms: " + e.message); } try { otimed_alarm.SetAlarm(zavai.registry.bus_name, (int)alarms.data.deadline); } catch (Error e) { zavai.log.error("Cannot reschedule alarms: " + e.message); } string t = rtc.GetCurrentTime(); stderr.printf("Current time: %d, RTC time: %s\n", (int)time_t(), t); t = rtc.GetWakeupTime(); stderr.printf("Scheduled alarm: %d, RTC wakeup time: %s\n", (int)alarms.data.deadline, t); } else zavai.log.info("No alarms left to reschedule"); schedule_changed(); } 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(a); } 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); } } }