]> ToastFreeware Gitweb - gregoa/zavai.git/blob - src/clock.vala
It works now, python-rtc was missing
[gregoa/zavai.git] / src / clock.vala
1 /*
2  * clock - clock resource for zavai
3  *
4  * Copyright (C) 2009  Enrico Zini <enrico@enricozini.org>
5  *
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.
10  *
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.
15  *
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
19  */
20
21 using GLib;
22
23 namespace zavai {
24 namespace clock {
25
26 public enum SourceType
27 {
28     SYSTEM,
29     GPS
30 }
31
32 public class Alarm : Object
33 {
34     public signal void trigger(Alarm a);
35
36     public time_t deadline;
37     public string label;
38
39     public Alarm(time_t deadline, string label)
40     {
41         this.deadline = deadline;
42         this.label = label;
43     }
44 }
45
46 private int alarm_compare(void* a, void* b)
47 {
48     return (int)(((Alarm*)a)->deadline - ((Alarm*)b)->deadline);
49 }
50
51 [DBus (name = "org.freesmartphone.Notification")]
52 public class AlarmNotification : Object {
53     public void Alarm () {
54         clock.check_alarms();
55     }
56 }
57
58 public class Clock: zavai.Service
59 {
60     protected time_t last_gps_time;
61     protected time_t last_gps_time_system_time;
62     protected time_t last_system_time;
63         protected dynamic DBus.Object gps_time;
64     protected uint system_time_timeout;
65     protected time_t last_minute;
66     protected time_t chosen_time;
67     protected SourceType chosen_type;
68     protected AlarmNotification listener;
69
70         protected dynamic DBus.Object otimed_alarm;
71         protected dynamic DBus.Object rtc;
72     protected SList<Alarm> alarms;
73
74     // Ticks once a minute
75     public signal void minute_changed(long time, SourceType source);
76     public signal void schedule_changed();
77
78         public Clock()
79         {
80                 name = "clock";
81         alarms = null;
82         listener = new AlarmNotification();
83         last_minute = 0;
84         last_gps_time = 0;
85         last_gps_time_system_time = 0;
86         last_system_time = time_t();
87         chosen_time = last_system_time;
88         
89                 gps_time = zavai.registry.sbus.get_object(
90                         "org.freesmartphone.ogpsd",
91                         "/org/freedesktop/Gypsy",
92                         "org.freedesktop.Gypsy.Time");
93
94         // FSO alarm system
95             otimed_alarm = zavai.registry.sbus.get_object(
96                         "org.freesmartphone.otimed",
97                         "/org/freesmartphone/Time/Alarm",
98                         "org.freesmartphone.Time.Alarm");
99
100                 rtc = zavai.registry.sbus.get_object(
101                         "org.freesmartphone.odeviced",
102                         "/org/freesmartphone/Device/RealTimeClock/0",
103                         "org.freesmartphone.Device.RealTimeClock");
104
105         zavai.registry.sbus.register_object("/", listener);
106
107         }
108
109     public Alarm? next_alarm()
110     {
111         if (alarms == null)
112             return null;
113         return alarms.data;
114     }
115
116     public void schedule(Alarm a)
117     {
118         alarms.insert_sorted(a, alarm_compare);
119         otimed_reschedule();
120     }
121
122     private void otimed_reschedule()
123     {
124         if (alarms != null)
125         {
126             zavai.log.info("Scheduling next alarm: " + alarms.data.label + " at " + Time.local(alarms.data.deadline).to_string());
127             
128             try {
129                 otimed_alarm.ClearAlarm(zavai.registry.bus_name);
130             } catch (Error e) {
131                 zavai.log.error("Cannot clear alarms: " + e.message);
132             }
133             try {
134                 otimed_alarm.SetAlarm(zavai.registry.bus_name, (int)alarms.data.deadline);
135             } catch (Error e) {
136                 zavai.log.error("Cannot reschedule alarms: " + e.message);
137             }
138
139 //string t = rtc.GetCurrentTime();
140 //stderr.printf("Current time: %d, RTC time: %s\n", (int)time_t(), t);
141 //t = rtc.GetWakeupTime();
142 //stderr.printf("Scheduled alarm: %d, RTC wakeup time: %s\n", (int)alarms.data.deadline, t);
143         } else
144             zavai.log.info("No alarms left to reschedule");
145         schedule_changed();
146     }
147
148     public void check_alarms()
149     {
150         last_system_time = time_t();
151         update_time();
152         while (alarms != null && alarms.data.deadline <= chosen_time)
153         {
154             Alarm a = alarms.data;
155             alarms.remove(a);
156             zavai.log.info("Triggering " + a.label);
157             a.trigger(a);
158         }
159
160         otimed_reschedule();
161     }
162
163         private void on_gps_time(dynamic DBus.Object pos, int t)
164         {
165         if (t == 0)
166         {
167             last_gps_time_system_time = 0;
168             update_time();
169         } else {
170             last_gps_time = (time_t)t;
171             last_gps_time_system_time = time_t();
172             update_time();
173         }
174         }
175
176     private bool on_system_time()
177     {
178         last_system_time = time_t();
179         update_time();
180         return true;
181     }
182
183     private void update_time()
184     {
185         if (last_gps_time_system_time + 10 > last_system_time)
186         {
187             chosen_time = last_gps_time;
188             chosen_type = SourceType.GPS;
189         }
190         else
191         {
192             chosen_time = last_system_time;
193             chosen_type = SourceType.SYSTEM;
194         }
195         if (chosen_time / 60 != last_minute)
196         {
197             last_minute = chosen_time / 60;
198             minute_changed(chosen_time, chosen_type);
199         }
200     }
201
202         /// Request GPS resource
203         public override void start()
204         {
205                 if (started) return;
206
207         system_time_timeout = Timeout.add(5000, on_system_time);
208                 gps_time.TimeChanged += on_gps_time;
209         last_system_time = time_t();
210         update_time();
211
212                 base.start();
213         }
214
215         public override void stop()
216         {
217                 if (!started) return;
218
219         Source.remove(system_time_timeout);
220                 gps_time.TimeChanged -= on_gps_time;
221
222                 base.stop();
223         }
224 }
225
226 public Clock clock = null;
227
228 public void init()
229 {
230     clock = new Clock();
231
232         zavai.registry.register_service(clock);
233 }
234
235 }
236 }