Show next deadline
[gregoa/zavai.git] / src / clock.vala
index 166d5373af8b4e2098d3aa8d167bd47db954b514..394ff29e08e5622fe55859e394a526b52be3d138 100644 (file)
@@ -29,6 +29,32 @@ public enum SourceType
     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);
+}
+
+[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;
@@ -37,25 +63,100 @@ public class Clock: zavai.Service
        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 notification;
+    protected SList<Alarm> 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");
+        if (otimed_alarm == null)
+            zavai.log.error("ALARM IS NULL");
+
+        zavai.registry.sbus.register_object("/", listener);
+
+        //notification = zavai.registry.sbus.get_object(
+        //    "org.freesmartphone",
+        //    "org/freesmartphone/Notification",
+        //    "org.freesmartphone.Notification");
+        //notification.Alarm += on_alarm;
        }
 
+    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()
+    {
+        zavai.log.info("No alarms left to reschedule");
+        if (alarms != null)
+        {
+            zavai.log.info("Scheduling next alarm: " + alarms.data.label + " at " + Time.local(alarms.data.deadline).to_string());
+            
+            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);
+            }
+        }
+        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();
+        }
+
+        otimed_reschedule();
+    }
+
        private void on_gps_time(dynamic DBus.Object pos, int t)
        {
         if (t == 0)
@@ -78,22 +179,20 @@ public class Clock: zavai.Service
 
     private void update_time()
     {
-        time_t chosen;
-        SourceType type;
         if (last_gps_time_system_time + 10 > last_system_time)
         {
-            chosen = last_gps_time;
-            type = SourceType.GPS;
+            chosen_time = last_gps_time;
+            chosen_type = SourceType.GPS;
         }
         else
         {
-            chosen = last_system_time;
-            type = SourceType.SYSTEM;
+            chosen_time = last_system_time;
+            chosen_type = SourceType.SYSTEM;
         }
-        if (chosen / 60 != last_minute)
+        if (chosen_time / 60 != last_minute)
         {
-            last_minute = chosen / 60;
-            minute_changed(chosentype);
+            last_minute = chosen_time / 60;
+            minute_changed(chosen_time, chosen_type);
         }
     }