Merge lp:~charlesk/indicator-datetime/hw-alarms-api into lp:indicator-datetime/13.10

Proposed by Ted Gould
Status: Merged
Approved by: Ted Gould
Approved revision: 353
Merged at revision: 344
Proposed branch: lp:~charlesk/indicator-datetime/hw-alarms-api
Merge into: lp:indicator-datetime/13.10
Diff against target: 1364 lines (+882/-141)
20 files modified
CMakeLists.txt (+7/-0)
MERGE-REVIEW (+30/-5)
debian/control (+2/-0)
include/datetime/alarm-queue-simple.h (+63/-0)
include/datetime/alarm-queue.h (+12/-28)
include/datetime/date-time.h (+3/-0)
include/datetime/planner-range.h (+1/-1)
include/datetime/wakeup-timer-mainloop.h (+62/-0)
include/datetime/wakeup-timer-uha.h (+64/-0)
include/datetime/wakeup-timer.h (+55/-0)
src/CMakeLists.txt (+31/-24)
src/alarm-queue-simple.cpp (+116/-38)
src/date-time.cpp (+5/-0)
src/engine-eds.cpp (+10/-2)
src/main.cpp (+88/-27)
src/planner-range.cpp (+1/-1)
src/wakeup-timer-mainloop.cpp (+138/-0)
src/wakeup-timer-uha.cpp (+175/-0)
tests/CMakeLists.txt (+1/-1)
tests/test-alarm-queue.cpp (+18/-14)
To merge this branch: bzr merge lp:~charlesk/indicator-datetime/hw-alarms-api
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Ted Gould (community) Approve
Review via email: mp+222716@code.launchpad.net

This proposal supersedes a proposal from 2014-04-25.

Commit message

Prefer to use ubuntu-platform-hardware-api for wakeups when possible s.t. user-defined alarms/appointments can wake up the phone from sleep to give a snap decision.

Description of the change

Jenkins isn't going to like this branch as-is.

Prerequisite: lp:~thomas-voss/platform-api/hw-alarms-api

TODO: (1) still some issues in the platform-api branch that I've mailed tvoss about. Once that's cleared I'll be able to give this branch more testing on (2) the phablet hybris impl and (3) the Desktop's fallback mode (ie, use a different implementation when u_hardware_alarm_create() fails on Desktop).

To post a comment you must log in.
Revision history for this message
Ted Gould (ted) wrote : Posted in a previous version of this proposal

 + std::vector<Appointment> find_current_alarms() const;
Doesn't that mean that the Appointment object will get copied when put in the vector?

 + bool is_set() const { return m_dt.get() != nullptr; }
 I think that you don't need the "get()" here, the "!=" is overridden so you can just do "!= nullptr"

In SimpleAlarmQueue it'd be nice to not have m_time and m_timer, easy to get them confused (I did)

824 + const auto difference_usec = g_date_time_difference(m_wakeup_time.get(), now.get());
825 + const guint interval_msec = (guint)difference_usec / 1000u;

Seems like we shouldn't just cast this to make it unsigned. abs? Or check the negative case?

Not sure how I feel about UhaWakeupTimer, it seems like you're basically creating a new GSource. But out of band. I'm not sure that it wouldn't be better to actually create a new GSource, thoughts?

Revision history for this message
Ted Gould (ted) wrote :

Resubmitted for 14.10

353. By Charles Kerr

in debian/control, remove 'Depends: libubuntu-platform-hardware-api1' as per ted's suggestion

Revision history for this message
Ted Gould (ted) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
354. By Charles Kerr

Don't build the hw-alarms pieces if ubuntu/hardware/alarm.h can't be found. Don't require libplatform-hardware-api-* unless the arch is armhf, i386, or amd64.

355. By Charles Kerr

remove a pair of #warning tracers

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-03-23 14:45:38 +0000
3+++ CMakeLists.txt 2014-06-11 04:07:06 +0000
4@@ -29,6 +29,7 @@
5 ##
6
7 find_package (PkgConfig REQUIRED)
8+include (CheckIncludeFile)
9 include (FindPkgConfig)
10
11 pkg_check_modules (SERVICE_DEPS REQUIRED
12@@ -43,6 +44,12 @@
13 properties-cpp>=0.0.1)
14 include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})
15
16+CHECK_INCLUDE_FILE(ubuntu/hardware/alarm.h HAVE_UBUNTU_HW_ALARM_H)
17+if (HAVE_UBUNTU_HW_ALARM_H)
18+ set (SERVICE_DEPS_LIBRARIES -lubuntu_platform_hardware_api ${SERVICE_DEPS_LIBRARIES})
19+ add_definitions(-DHAVE_UBUNTU_HW_ALARM_H)
20+endif ()
21+
22 ##
23 ## custom targets
24 ##
25
26=== modified file 'MERGE-REVIEW'
27--- MERGE-REVIEW 2014-01-31 20:17:55 +0000
28+++ MERGE-REVIEW 2014-06-11 04:07:06 +0000
29@@ -6,14 +6,39 @@
30
31 * Ensure the project compiles and the test suite executes without error
32 * Ensure that non-obvious code has comments explaining it
33- * If the change works on specific profiles, please include those in the merge description.
34+ * If the change affects specific features, please reference the appropriate
35+ tags in the merge description so reviewers can test appropriately:
36+ [phone profile], [desktop profile], [alarms]
37
38 == Reviewer Responsibilities ==
39
40 * Did the Jenkins build compile? Pass? Run unit tests successfully?
41 * Are there appropriate tests to cover any new functionality?
42- * If the description says this effects the phone profile:
43- * Run tests indicator-datetime/unity8*
44- * If the description says this effects the desktop profile:
45- * Run tests indicator-datetime/unity7*
46+ * Do the tag-specific tests pass?
47+
48+== Phone Profile Tests ==
49+
50+ * Run tests indicator-datetime/unity8*
51+
52+== Desktop Profile Tests ==
53+
54+ * Run tests indicator-datetime/unity7*
55+
56+== Alarm Tests ==
57+
58+ * Hardware wakeups for new alarms:
59+ 1. Create and save an upcoming alarm in ubuntu-clock-app.
60+ 2. Unplug the phone from any USB connection and put it to sleep.
61+ 3. Confirm that the alarm sounds on time even if the phone is asleep.
62+ (Note: if in doubt about sleep you can see in the syslog whether the
63+ device actually suspended or whether the suspend was aborted)
64+
65+ * Hardware wakeups for edited alarms:
66+ 1. Edit an alarm that's already passed. (see previous test)
67+ 2. Unplug the phone from any USB connection and put it to sleep.
68+ 3. Confirm that the alarm sounds on time even if the phone is asleep.
69+ (Note: if in doubt about sleep you can see in the syslog whether the
70+ device actually suspended or whether the suspend was aborted.)
71+
72+
73
74
75=== modified file 'debian/control'
76--- debian/control 2014-03-23 20:11:06 +0000
77+++ debian/control 2014-06-11 04:07:06 +0000
78@@ -19,6 +19,8 @@
79 libedataserver1.2-dev (>= 3.5),
80 liburl-dispatcher1-dev,
81 libproperties-cpp-dev,
82+ libplatform-hardware-api-headers [armhf i386 amd64],
83+ libplatform-hardware-api1-dev [armhf i386 amd64],
84 libdbustest1-dev,
85 locales,
86 Standards-Version: 3.9.3
87
88=== added file 'include/datetime/alarm-queue-simple.h'
89--- include/datetime/alarm-queue-simple.h 1970-01-01 00:00:00 +0000
90+++ include/datetime/alarm-queue-simple.h 2014-06-11 04:07:06 +0000
91@@ -0,0 +1,63 @@
92+/*
93+ * Copyright 2014 Canonical Ltd.
94+ *
95+ * This program is free software: you can redistribute it and/or modify it
96+ * under the terms of the GNU General Public License version 3, as published
97+ * by the Free Software Foundation.
98+ *
99+ * This program is distributed in the hope that it will be useful, but
100+ * WITHOUT ANY WARRANTY; without even the implied warranties of
101+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
102+ * PURPOSE. See the GNU General Public License for more details.
103+ *
104+ * You should have received a copy of the GNU General Public License along
105+ * with this program. If not, see <http://www.gnu.org/licenses/>.
106+ *
107+ * Authors:
108+ * Charles Kerr <charles.kerr@canonical.com>
109+ */
110+
111+#ifndef INDICATOR_DATETIME_ALARM_QUEUE_SIMPLE_H
112+#define INDICATOR_DATETIME_ALARM_QUEUE_SIMPLE_H
113+
114+#include <datetime/alarm-queue.h>
115+#include <datetime/clock.h>
116+#include <datetime/planner.h>
117+#include <datetime/wakeup-timer.h>
118+
119+namespace unity {
120+namespace indicator {
121+namespace datetime {
122+
123+/**
124+ * \brief A #AlarmQueue implementation
125+ */
126+class SimpleAlarmQueue: public AlarmQueue
127+{
128+public:
129+ SimpleAlarmQueue(const std::shared_ptr<Clock>& clock,
130+ const std::shared_ptr<Planner>& upcoming_planner,
131+ const std::shared_ptr<WakeupTimer>& timer);
132+ ~SimpleAlarmQueue();
133+ core::Signal<const Appointment&>& alarm_reached();
134+
135+private:
136+ void requeue();
137+ bool find_next_alarm(Appointment& setme) const;
138+ std::vector<Appointment> find_current_alarms() const;
139+ void check_alarms();
140+
141+ std::set<std::pair<std::string,DateTime>> m_triggered;
142+ const std::shared_ptr<Clock> m_clock;
143+ const std::shared_ptr<Planner> m_planner;
144+ const std::shared_ptr<WakeupTimer> m_timer;
145+ core::Signal<const Appointment&> m_alarm_reached;
146+ DateTime m_datetime;
147+};
148+
149+
150+} // namespace datetime
151+} // namespace indicator
152+} // namespace unity
153+
154+#endif // INDICATOR_DATETIME_ALARM_QUEUE_H
155
156=== renamed file 'include/datetime/clock-watcher.h' => 'include/datetime/alarm-queue.h'
157--- include/datetime/clock-watcher.h 2014-03-10 02:08:47 +0000
158+++ include/datetime/alarm-queue.h 2014-06-11 04:07:06 +0000
159@@ -17,12 +17,10 @@
160 * Charles Kerr <charles.kerr@canonical.com>
161 */
162
163-#ifndef INDICATOR_DATETIME_CLOCK_WATCHER_H
164-#define INDICATOR_DATETIME_CLOCK_WATCHER_H
165+#ifndef INDICATOR_DATETIME_ALARM_QUEUE_H
166+#define INDICATOR_DATETIME_ALARM_QUEUE_H
167
168 #include <datetime/appointment.h>
169-#include <datetime/clock.h>
170-#include <datetime/planner-upcoming.h>
171
172 #include <core/signal.h>
173
174@@ -34,42 +32,28 @@
175 namespace indicator {
176 namespace datetime {
177
178+/***
179+****
180+***/
181
182 /**
183 * \brief Watches the clock and appointments to notify when an
184 * appointment's time is reached.
185 */
186-class ClockWatcher
187+class AlarmQueue
188 {
189 public:
190- ClockWatcher() =default;
191- virtual ~ClockWatcher() =default;
192+ AlarmQueue() =default;
193+ virtual ~AlarmQueue() =default;
194 virtual core::Signal<const Appointment&>& alarm_reached() = 0;
195 };
196
197-
198-/**
199- * \brief A #ClockWatcher implementation
200- */
201-class ClockWatcherImpl: public ClockWatcher
202-{
203-public:
204- ClockWatcherImpl(const std::shared_ptr<Clock>& clock,
205- const std::shared_ptr<UpcomingPlanner>& upcoming_planner);
206- ~ClockWatcherImpl() =default;
207- core::Signal<const Appointment&>& alarm_reached();
208-
209-private:
210- void pulse();
211- std::set<std::string> m_triggered;
212- const std::shared_ptr<Clock> m_clock;
213- const std::shared_ptr<UpcomingPlanner> m_upcoming_planner;
214- core::Signal<const Appointment&> m_alarm_reached;
215-};
216-
217+/***
218+****
219+***/
220
221 } // namespace datetime
222 } // namespace indicator
223 } // namespace unity
224
225-#endif // INDICATOR_DATETIME_CLOCK_WATCHER_H
226+#endif // INDICATOR_DATETIME_ALARM_QUEUE_H
227
228=== modified file 'include/datetime/date-time.h'
229--- include/datetime/date-time.h 2014-03-10 02:08:47 +0000
230+++ include/datetime/date-time.h 2014-06-11 04:07:06 +0000
231@@ -61,10 +61,13 @@
232 bool operator<=(const DateTime& that) const;
233 bool operator!=(const DateTime& that) const;
234 bool operator==(const DateTime& that) const;
235+ int64_t operator- (const DateTime& that) const;
236
237 static bool is_same_day(const DateTime& a, const DateTime& b);
238 static bool is_same_minute(const DateTime& a, const DateTime& b);
239
240+ bool is_set() const { return m_dt != nullptr; }
241+
242 private:
243 std::shared_ptr<GDateTime> m_dt;
244 };
245
246=== modified file 'include/datetime/planner-range.h'
247--- include/datetime/planner-range.h 2014-03-10 03:26:26 +0000
248+++ include/datetime/planner-range.h 2014-06-11 04:07:06 +0000
249@@ -53,7 +53,7 @@
250 {
251 public:
252 SimpleRangePlanner(const std::shared_ptr<Engine>& engine,
253- const std::shared_ptr<Timezone>& timezone);
254+ const std::shared_ptr<Timezone>& timezone);
255 virtual ~SimpleRangePlanner();
256
257 core::Property<std::vector<Appointment>>& appointments();
258
259=== added file 'include/datetime/wakeup-timer-mainloop.h'
260--- include/datetime/wakeup-timer-mainloop.h 1970-01-01 00:00:00 +0000
261+++ include/datetime/wakeup-timer-mainloop.h 2014-06-11 04:07:06 +0000
262@@ -0,0 +1,62 @@
263+/*
264+ * Copyright 2014 Canonical Ltd.
265+ *
266+ * This program is free software: you can redistribute it and/or modify it
267+ * under the terms of the GNU General Public License version 3, as published
268+ * by the Free Software Foundation.
269+ *
270+ * This program is distributed in the hope that it will be useful, but
271+ * WITHOUT ANY WARRANTY; without even the implied warranties of
272+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
273+ * PURPOSE. See the GNU General Public License for more details.
274+ *
275+ * You should have received a copy of the GNU General Public License along
276+ * with this program. If not, see <http://www.gnu.org/licenses/>.
277+ *
278+ * Authors:
279+ * Charles Kerr <charles.kerr@canonical.com>
280+ */
281+
282+#ifndef INDICATOR_DATETIME_WAKEUP_TIMER_MAINLOOP_H
283+#define INDICATOR_DATETIME_WAKEUP_TIMER_MAINLOOP_H
284+
285+#include <datetime/clock.h>
286+#include <datetime/wakeup-timer.h>
287+
288+#include <memory> // std::unique_ptr, std::shared_ptr
289+
290+namespace unity {
291+namespace indicator {
292+namespace datetime {
293+
294+/***
295+****
296+***/
297+
298+/**
299+ * \brief a WakeupTimer implemented with g_timeout_add()
300+ */
301+class MainloopWakeupTimer: public WakeupTimer
302+{
303+public:
304+ MainloopWakeupTimer(const std::shared_ptr<Clock>&);
305+ ~MainloopWakeupTimer();
306+ void set_wakeup_time (const DateTime&);
307+ core::Signal<>& timeout();
308+
309+private:
310+ MainloopWakeupTimer(const MainloopWakeupTimer&) =delete;
311+ MainloopWakeupTimer& operator= (const MainloopWakeupTimer&) =delete;
312+ class Impl;
313+ std::unique_ptr<Impl> p;
314+};
315+
316+/***
317+****
318+***/
319+
320+} // namespace datetime
321+} // namespace indicator
322+} // namespace unity
323+
324+#endif // INDICATOR_DATETIME_WAKEUP_TIMER_MAINLOOP_H
325
326=== added file 'include/datetime/wakeup-timer-uha.h'
327--- include/datetime/wakeup-timer-uha.h 1970-01-01 00:00:00 +0000
328+++ include/datetime/wakeup-timer-uha.h 2014-06-11 04:07:06 +0000
329@@ -0,0 +1,64 @@
330+/*
331+ * Copyright 2014 Canonical Ltd.
332+ *
333+ * This program is free software: you can redistribute it and/or modify it
334+ * under the terms of the GNU General Public License version 3, as published
335+ * by the Free Software Foundation.
336+ *
337+ * This program is distributed in the hope that it will be useful, but
338+ * WITHOUT ANY WARRANTY; without even the implied warranties of
339+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
340+ * PURPOSE. See the GNU General Public License for more details.
341+ *
342+ * You should have received a copy of the GNU General Public License along
343+ * with this program. If not, see <http://www.gnu.org/licenses/>.
344+ *
345+ * Authors:
346+ * Charles Kerr <charles.kerr@canonical.com>
347+ */
348+
349+#ifndef INDICATOR_DATETIME_WAKEUP_TIMER_UHA_H
350+#define INDICATOR_DATETIME_WAKEUP_TIMER_UHA_H
351+
352+#include <datetime/clock.h>
353+#include <datetime/wakeup-timer.h>
354+
355+#include <memory> // std::unique_ptr, std::shared_ptr
356+
357+namespace unity {
358+namespace indicator {
359+namespace datetime {
360+
361+/***
362+****
363+***/
364+
365+/**
366+ * \brief a WakeupTimer implemented the UbuntuHardwareAlarm API
367+ */
368+class UhaWakeupTimer: public WakeupTimer
369+{
370+public:
371+ UhaWakeupTimer(const std::shared_ptr<Clock>&);
372+ ~UhaWakeupTimer();
373+ void set_wakeup_time (const DateTime&);
374+ core::Signal<>& timeout();
375+
376+ static bool is_supported();
377+
378+private:
379+ UhaWakeupTimer(const UhaWakeupTimer&) =delete;
380+ UhaWakeupTimer& operator= (const UhaWakeupTimer&) =delete;
381+ class Impl;
382+ std::unique_ptr<Impl> p;
383+};
384+
385+/***
386+****
387+***/
388+
389+} // namespace datetime
390+} // namespace indicator
391+} // namespace unity
392+
393+#endif // INDICATOR_DATETIME_WAKEUP_TIMER_UHA_H
394
395=== added file 'include/datetime/wakeup-timer.h'
396--- include/datetime/wakeup-timer.h 1970-01-01 00:00:00 +0000
397+++ include/datetime/wakeup-timer.h 2014-06-11 04:07:06 +0000
398@@ -0,0 +1,55 @@
399+/*
400+ * Copyright 2014 Canonical Ltd.
401+ *
402+ * This program is free software: you can redistribute it and/or modify it
403+ * under the terms of the GNU General Public License version 3, as published
404+ * by the Free Software Foundation.
405+ *
406+ * This program is distributed in the hope that it will be useful, but
407+ * WITHOUT ANY WARRANTY; without even the implied warranties of
408+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
409+ * PURPOSE. See the GNU General Public License for more details.
410+ *
411+ * You should have received a copy of the GNU General Public License along
412+ * with this program. If not, see <http://www.gnu.org/licenses/>.
413+ *
414+ * Authors:
415+ * Charles Kerr <charles.kerr@canonical.com>
416+ */
417+
418+#ifndef INDICATOR_DATETIME_WAKEUP_TIMER_H
419+#define INDICATOR_DATETIME_WAKEUP_TIMER_H
420+
421+#include <datetime/date-time.h>
422+
423+#include <core/signal.h>
424+
425+namespace unity {
426+namespace indicator {
427+namespace datetime {
428+
429+/***
430+****
431+***/
432+
433+/**
434+ * \brief A one-shot timer that emits a signal when its timeout is reached.
435+ */
436+class WakeupTimer
437+{
438+public:
439+ WakeupTimer() =default;
440+ virtual ~WakeupTimer() =default;
441+ virtual void set_wakeup_time (const DateTime&) =0;
442+ virtual core::Signal<>& timeout() = 0;
443+};
444+
445+/***
446+****
447+***/
448+
449+} // namespace datetime
450+} // namespace indicator
451+} // namespace unity
452+
453+#endif // INDICATOR_DATETIME_WAKEUP_TIMER_H
454
455=== modified file 'src/CMakeLists.txt'
456--- src/CMakeLists.txt 2014-03-10 03:26:26 +0000
457+++ src/CMakeLists.txt 2014-06-11 04:07:06 +0000
458@@ -7,30 +7,37 @@
459 add_definitions (-DTIMEZONE_FILE="/etc/timezone"
460 -DG_LOG_DOMAIN="Indicator-Datetime")
461
462-add_library (${SERVICE_LIB} STATIC
463- actions.cpp
464- actions-live.cpp
465- appointment.cpp
466- clock.cpp
467- clock-live.cpp
468- clock-watcher.cpp
469- date-time.cpp
470- engine-eds.cpp
471- exporter.cpp
472- formatter.cpp
473- formatter-desktop.cpp
474- locations.cpp
475- locations-settings.cpp
476- menu.cpp
477- planner-month.cpp
478- planner-range.cpp
479- planner-upcoming.cpp
480- settings-live.cpp
481- snap.cpp
482- timezone-file.cpp
483- timezone-geoclue.cpp
484- timezones-live.cpp
485- utils.c)
486+set (SERVICE_SOURCES
487+ actions.cpp
488+ actions-live.cpp
489+ alarm-queue-simple.cpp
490+ appointment.cpp
491+ clock.cpp
492+ clock-live.cpp
493+ date-time.cpp
494+ engine-eds.cpp
495+ exporter.cpp
496+ formatter.cpp
497+ formatter-desktop.cpp
498+ locations.cpp
499+ locations-settings.cpp
500+ menu.cpp
501+ planner-month.cpp
502+ planner-range.cpp
503+ planner-upcoming.cpp
504+ settings-live.cpp
505+ snap.cpp
506+ timezone-file.cpp
507+ timezone-geoclue.cpp
508+ timezones-live.cpp
509+ utils.c
510+ wakeup-timer-mainloop.cpp)
511+
512+if (HAVE_UBUNTU_HW_ALARM_H)
513+ set (SERVICE_SOURCES ${SERVICE_SOURCES} wakeup-timer-uha.cpp)
514+endif ()
515+
516+add_library (${SERVICE_LIB} STATIC ${SERVICE_SOURCES})
517 include_directories (${CMAKE_SOURCE_DIR})
518 link_directories (${SERVICE_DEPS_LIBRARY_DIRS})
519
520
521=== renamed file 'src/clock-watcher.cpp' => 'src/alarm-queue-simple.cpp'
522--- src/clock-watcher.cpp 2014-03-10 02:08:47 +0000
523+++ src/alarm-queue-simple.cpp 2014-06-11 04:07:06 +0000
524@@ -17,59 +17,137 @@
525 * Charles Kerr <charles.kerr@canonical.com>
526 */
527
528-#include <datetime/clock-watcher.h>
529+#include <datetime/alarm-queue-simple.h>
530+
531+#include <cmath>
532
533 namespace unity {
534 namespace indicator {
535 namespace datetime {
536
537 /***
538-****
539+**** Public API
540 ***/
541
542-ClockWatcherImpl::ClockWatcherImpl(const std::shared_ptr<Clock>& clock,
543- const std::shared_ptr<UpcomingPlanner>& upcoming_planner):
544+SimpleAlarmQueue::SimpleAlarmQueue(const std::shared_ptr<Clock>& clock,
545+ const std::shared_ptr<Planner>& planner,
546+ const std::shared_ptr<WakeupTimer>& timer):
547 m_clock(clock),
548- m_upcoming_planner(upcoming_planner)
549+ m_planner(planner),
550+ m_timer(timer),
551+ m_datetime(clock->localtime())
552 {
553- m_clock->date_changed.connect([this](){
554+ m_planner->appointments().changed().connect([this](const std::vector<Appointment>&){
555+ g_debug("AlarmQueue %p calling requeue() due to appointments changed", this);
556+ requeue();
557+ });
558+
559+ m_clock->minute_changed.connect([=]{
560 const auto now = m_clock->localtime();
561- g_debug("ClockWatcher %p refretching appointments due to date change: %s", this, now.format("%F %T").c_str());
562- m_upcoming_planner->date().set(now);
563- });
564-
565- m_clock->minute_changed.connect([this](){
566- g_debug("ClockWatcher %p calling pulse() due to clock minute_changed", this);
567- pulse();
568- });
569-
570- m_upcoming_planner->appointments().changed().connect([this](const std::vector<Appointment>&){
571- g_debug("ClockWatcher %p calling pulse() due to appointments changed", this);
572- pulse();
573- });
574-
575- pulse();
576-}
577-
578-core::Signal<const Appointment&>& ClockWatcherImpl::alarm_reached()
579+ constexpr auto skew_threshold_usec = int64_t{90} * G_USEC_PER_SEC;
580+ const bool clock_jumped = std::abs(now - m_datetime) > skew_threshold_usec;
581+ m_datetime = now;
582+ if (clock_jumped) {
583+ g_debug("AlarmQueue %p calling requeue() due to clock skew", this);
584+ requeue();
585+ }
586+ });
587+
588+ m_timer->timeout().connect([this](){
589+ g_debug("AlarmQueue %p calling requeue() due to timeout", this);
590+ requeue();
591+ });
592+
593+ requeue();
594+}
595+
596+SimpleAlarmQueue::~SimpleAlarmQueue()
597+{
598+}
599+
600+core::Signal<const Appointment&>& SimpleAlarmQueue::alarm_reached()
601 {
602 return m_alarm_reached;
603 }
604
605-void ClockWatcherImpl::pulse()
606-{
607- const auto now = m_clock->localtime();
608-
609- for(const auto& appointment : m_upcoming_planner->appointments().get())
610- {
611- if (m_triggered.count(appointment.uid))
612- continue;
613- if (!DateTime::is_same_minute(now, appointment.begin))
614- continue;
615-
616- m_triggered.insert(appointment.uid);
617- m_alarm_reached(appointment);
618- }
619+/***
620+****
621+***/
622+
623+void SimpleAlarmQueue::requeue()
624+{
625+ // kick any current alarms
626+ for (auto current : find_current_alarms())
627+ {
628+ const std::pair<std::string,DateTime> trig {current.uid, current.begin};
629+ m_triggered.insert(trig);
630+ m_alarm_reached(current);
631+ }
632+
633+ // idle until the next alarm
634+ Appointment next;
635+ if (find_next_alarm(next))
636+ {
637+ g_debug ("setting timer to wake up for next appointment '%s' at %s",
638+ next.summary.c_str(),
639+ next.begin.format("%F %T").c_str());
640+
641+ m_timer->set_wakeup_time(next.begin);
642+ }
643+}
644+
645+// find the next alarm that will kick now or in the future
646+bool SimpleAlarmQueue::find_next_alarm(Appointment& setme) const
647+{
648+ bool found = false;
649+ Appointment tmp;
650+ const auto now = m_clock->localtime();
651+ const auto beginning_of_minute = now.add_full (0, 0, 0, 0, 0, -now.seconds());
652+
653+ const auto appointments = m_planner->appointments().get();
654+ g_debug ("planner has %zu appointments in it", (size_t)appointments.size());
655+
656+ for(const auto& walk : appointments)
657+ {
658+ const std::pair<std::string,DateTime> trig {walk.uid, walk.begin};
659+ if (m_triggered.count(trig))
660+ continue;
661+
662+ if (walk.begin < beginning_of_minute) // has this one already passed?
663+ continue;
664+
665+ if (found && (tmp.begin < walk.begin)) // do we already have a better match?
666+ continue;
667+
668+ tmp = walk;
669+ found = true;
670+ }
671+
672+ if (found)
673+ setme = tmp;
674+
675+ return found;
676+}
677+
678+// find the alarm(s) that should kick right now
679+std::vector<Appointment> SimpleAlarmQueue::find_current_alarms() const
680+{
681+ std::vector<Appointment> appointments;
682+
683+ const auto now = m_clock->localtime();
684+
685+ for(const auto& walk : m_planner->appointments().get())
686+ {
687+ const std::pair<std::string,DateTime> trig {walk.uid, walk.begin};
688+ if (m_triggered.count(trig)) // did we already use this one?
689+ continue;
690+ if (!DateTime::is_same_minute(now, walk.begin))
691+ continue;
692+
693+ appointments.push_back(walk);
694+ }
695+
696+ return appointments;
697 }
698
699 /***
700
701=== modified file 'src/date-time.cpp'
702--- src/date-time.cpp 2014-03-10 02:08:47 +0000
703+++ src/date-time.cpp 2014-06-11 04:07:06 +0000
704@@ -174,6 +174,11 @@
705 return g_date_time_compare(get(), that.get()) == 0;
706 }
707
708+int64_t DateTime::operator- (const DateTime& that) const
709+{
710+ return g_date_time_difference(get(), that.get());
711+}
712+
713 bool DateTime::is_same_day(const DateTime& a, const DateTime& b)
714 {
715 // it's meaningless to compare uninitialized dates
716
717=== modified file 'src/engine-eds.cpp'
718--- src/engine-eds.cpp 2014-04-15 16:11:34 +0000
719+++ src/engine-eds.cpp 2014-06-11 04:07:06 +0000
720@@ -418,6 +418,14 @@
721 auto status = ICAL_STATUS_NONE;
722 e_cal_component_get_status(component, &status);
723
724+ const auto begin_dt = DateTime(begin);
725+ const auto end_dt = DateTime(end);
726+ g_debug ("got appointment from %s to %s, uid %s status %d",
727+ begin_dt.format("%F %T").c_str(),
728+ end_dt.format("%F %T").c_str(),
729+ uid,
730+ (int)status);
731+
732 if ((uid != nullptr) &&
733 (status != ICAL_STATUS_COMPLETED) &&
734 (status != ICAL_STATUS_CANCELLED))
735@@ -430,8 +438,8 @@
736 if (text.value)
737 appointment.summary = text.value;
738
739- appointment.begin = DateTime(begin);
740- appointment.end = DateTime(end);
741+ appointment.begin = begin_dt;
742+ appointment.end = end_dt;
743 appointment.color = subtask->color;
744 appointment.uid = uid;
745
746
747=== modified file 'src/main.cpp'
748--- src/main.cpp 2014-03-10 03:26:26 +0000
749+++ src/main.cpp 2014-06-11 04:07:06 +0000
750@@ -18,8 +18,8 @@
751 */
752
753 #include <datetime/actions-live.h>
754+#include <datetime/alarm-queue-simple.h>
755 #include <datetime/clock.h>
756-#include <datetime/clock-watcher.h>
757 #include <datetime/engine-mock.h>
758 #include <datetime/engine-eds.h>
759 #include <datetime/exporter.h>
760@@ -31,6 +31,11 @@
761 #include <datetime/state.h>
762 #include <datetime/timezone-file.h>
763 #include <datetime/timezones-live.h>
764+#include <datetime/wakeup-timer-mainloop.h>
765+
766+#ifdef HAVE_UBUNTU_HW_ALARM_H
767+ #include <datetime/wakeup-timer-uha.h>
768+#endif
769
770 #include <glib/gi18n.h> // bindtextdomain()
771 #include <gio/gio.h>
772@@ -42,6 +47,81 @@
773
774 using namespace unity::indicator::datetime;
775
776+namespace
777+{
778+ std::shared_ptr<Engine> create_engine()
779+ {
780+ std::shared_ptr<Engine> engine;
781+
782+ // we don't show appointments in the greeter,
783+ // so no need to connect to EDS there...
784+ if (!g_strcmp0("lightdm", g_get_user_name()))
785+ engine.reset(new MockEngine);
786+ else
787+ engine.reset(new EdsEngine);
788+
789+ return engine;
790+ }
791+
792+ std::shared_ptr<WakeupTimer> create_wakeup_timer(const std::shared_ptr<Clock>& clock)
793+ {
794+ std::shared_ptr<WakeupTimer> wakeup_timer;
795+
796+#ifdef HAVE_UBUNTU_HW_ALARM_H
797+ if (UhaWakeupTimer::is_supported()) // prefer to use the platform API
798+ wakeup_timer = std::make_shared<UhaWakeupTimer>(clock);
799+ else
800+#endif
801+ wakeup_timer = std::make_shared<MainloopWakeupTimer>(clock);
802+
803+ return wakeup_timer;
804+ }
805+
806+ std::shared_ptr<State> create_state(const std::shared_ptr<Engine>& engine,
807+ const std::shared_ptr<Timezone>& tz)
808+ {
809+ // create the live objects
810+ auto live_settings = std::make_shared<LiveSettings>();
811+ auto live_timezones = std::make_shared<LiveTimezones>(live_settings, TIMEZONE_FILE);
812+ auto live_clock = std::make_shared<LiveClock>(live_timezones);
813+
814+ // create a full-month planner currently pointing to the current month
815+ const auto now = live_clock->localtime();
816+ auto range_planner = std::make_shared<SimpleRangePlanner>(engine, tz);
817+ auto calendar_month = std::make_shared<MonthPlanner>(range_planner, now);
818+
819+ // create an upcoming-events planner currently pointing to the current date
820+ range_planner = std::make_shared<SimpleRangePlanner>(engine, tz);
821+ auto calendar_upcoming = std::make_shared<UpcomingPlanner>(range_planner, now);
822+
823+ // create the state
824+ auto state = std::make_shared<State>();
825+ state->settings = live_settings;
826+ state->clock = live_clock;
827+ state->locations = std::make_shared<SettingsLocations>(live_settings, live_timezones);
828+ state->calendar_month = calendar_month;
829+ state->calendar_upcoming = calendar_upcoming;
830+ return state;
831+ }
832+
833+ std::shared_ptr<AlarmQueue> create_simple_alarm_queue(const std::shared_ptr<Clock>& clock,
834+ const std::shared_ptr<Engine>& engine,
835+ const std::shared_ptr<Timezone>& tz)
836+ {
837+ // create an upcoming-events planner that =always= tracks the clock's date
838+ auto range_planner = std::make_shared<SimpleRangePlanner>(engine, tz);
839+ auto upcoming_planner = std::make_shared<UpcomingPlanner>(range_planner, clock->localtime());
840+ clock->date_changed.connect([clock,upcoming_planner](){
841+ const auto now = clock->localtime();
842+ g_debug("refretching appointments due to date change: %s", now.format("%F %T").c_str());
843+ upcoming_planner->date().set(now);
844+ });
845+
846+ auto wakeup_timer = create_wakeup_timer(clock);
847+ return std::make_shared<SimpleAlarmQueue>(clock, upcoming_planner, wakeup_timer);
848+ }
849+}
850+
851 int
852 main(int /*argc*/, char** /*argv*/)
853 {
854@@ -54,35 +134,16 @@
855 bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR);
856 textdomain(GETTEXT_PACKAGE);
857
858- // we don't show appointments in the greeter,
859- // so no need to connect to EDS there...
860- std::shared_ptr<Engine> engine;
861- if (!g_strcmp0("lightdm", g_get_user_name()))
862- engine.reset(new MockEngine);
863- else
864- engine.reset(new EdsEngine);
865-
866- // build the state, actions, and menufactory
867- std::shared_ptr<State> state(new State);
868- std::shared_ptr<Settings> live_settings(new LiveSettings);
869- std::shared_ptr<Timezones> live_timezones(new LiveTimezones(live_settings, TIMEZONE_FILE));
870- std::shared_ptr<Clock> live_clock(new LiveClock(live_timezones));
871- std::shared_ptr<Timezone> file_timezone(new FileTimezone(TIMEZONE_FILE));
872- const auto now = live_clock->localtime();
873- state->settings = live_settings;
874- state->clock = live_clock;
875- state->locations.reset(new SettingsLocations(live_settings, live_timezones));
876- auto calendar_month = new MonthPlanner(std::shared_ptr<RangePlanner>(new SimpleRangePlanner(engine, file_timezone)), now);
877- state->calendar_month.reset(calendar_month);
878- state->calendar_upcoming.reset(new UpcomingPlanner(std::shared_ptr<RangePlanner>(new SimpleRangePlanner(engine, file_timezone)), now));
879- std::shared_ptr<Actions> actions(new LiveActions(state));
880+ auto engine = create_engine();
881+ auto timezone = std::make_shared<FileTimezone>(TIMEZONE_FILE);
882+ auto state = create_state(engine, timezone);
883+ auto actions = std::make_shared<LiveActions>(state);
884 MenuFactory factory(actions, state);
885
886- // snap decisions
887- std::shared_ptr<UpcomingPlanner> upcoming_planner(new UpcomingPlanner(std::shared_ptr<RangePlanner>(new SimpleRangePlanner(engine, file_timezone)), now));
888- ClockWatcherImpl clock_watcher(live_clock, upcoming_planner);
889+ // set up the snap decisions
890 Snap snap;
891- clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){
892+ auto alarm_queue = create_simple_alarm_queue(state->clock, engine, timezone);
893+ alarm_queue->alarm_reached().connect([&snap](const Appointment& appt){
894 auto snap_show = [](const Appointment& a){
895 const char* url;
896 if(!a.url.empty())
897
898=== modified file 'src/planner-range.cpp'
899--- src/planner-range.cpp 2014-03-10 03:26:26 +0000
900+++ src/planner-range.cpp 2014-06-11 04:07:06 +0000
901@@ -34,7 +34,7 @@
902 m_range(std::pair<DateTime,DateTime>(DateTime::NowLocal(), DateTime::NowLocal()))
903 {
904 engine->changed().connect([this](){
905- g_debug("RangePlanner %p rebuilding soon because Engine %p emitted 'changed' signal%p", this, m_engine.get());
906+ g_debug("RangePlanner %p rebuilding soon because Engine %p emitted 'changed' signal", this, m_engine.get());
907 rebuild_soon();
908 });
909
910
911=== added file 'src/wakeup-timer-mainloop.cpp'
912--- src/wakeup-timer-mainloop.cpp 1970-01-01 00:00:00 +0000
913+++ src/wakeup-timer-mainloop.cpp 2014-06-11 04:07:06 +0000
914@@ -0,0 +1,138 @@
915+/*
916+ * Copyright 2014 Canonical Ltd.
917+ *
918+ * This program is free software: you can redistribute it and/or modify it
919+ * under the terms of the GNU General Public License version 3, as published
920+ * by the Free Software Foundation.
921+ *
922+ * This program is distributed in the hope that it will be useful, but
923+ * WITHOUT ANY WARRANTY; without even the implied warranties of
924+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
925+ * PURPOSE. See the GNU General Public License for more details.
926+ *
927+ * You should have received a copy of the GNU General Public License along
928+ * with this program. If not, see <http://www.gnu.org/licenses/>.
929+ *
930+ * Authors:
931+ * Charles Kerr <charles.kerr@canonical.com>
932+ */
933+
934+#include <datetime/wakeup-timer-mainloop.h>
935+
936+#include <glib.h>
937+
938+#include <cstdlib> // abs()
939+
940+namespace unity {
941+namespace indicator {
942+namespace datetime {
943+
944+/***
945+****
946+***/
947+
948+class MainloopWakeupTimer::Impl
949+{
950+
951+public:
952+
953+ Impl(const std::shared_ptr<Clock>& clock):
954+ m_clock(clock)
955+ {
956+ }
957+
958+ ~Impl()
959+ {
960+ cancel_timer();
961+ }
962+
963+ void set_wakeup_time(const DateTime& d)
964+ {
965+ m_wakeup_time = d;
966+
967+ rebuild_timer();
968+ }
969+
970+ core::Signal<>& timeout() { return m_timeout; }
971+
972+private:
973+
974+ void rebuild_timer()
975+ {
976+ cancel_timer();
977+
978+ g_return_if_fail(m_wakeup_time.is_set());
979+
980+ const auto now = m_clock->localtime();
981+ const auto difference_usec = g_date_time_difference(m_wakeup_time.get(), now.get());
982+ const guint interval_msec = std::abs(difference_usec) / 1000u;
983+ g_debug("%s setting wakeup timer to kick at %s, which is in %zu seconds",
984+ G_STRFUNC,
985+ m_wakeup_time.format("%F %T").c_str(),
986+ size_t{interval_msec/1000});
987+
988+ m_timeout_tag = g_timeout_add_full(G_PRIORITY_HIGH,
989+ interval_msec,
990+ on_timeout,
991+ this,
992+ nullptr);
993+ }
994+
995+ static gboolean on_timeout(gpointer gself)
996+ {
997+ g_debug("%s %s", G_STRLOC, G_STRFUNC);
998+ static_cast<Impl*>(gself)->on_timeout();
999+ return G_SOURCE_REMOVE;
1000+ }
1001+
1002+ void on_timeout()
1003+ {
1004+ cancel_timer();
1005+ m_timeout();
1006+ }
1007+
1008+ void cancel_timer()
1009+ {
1010+ if (m_timeout_tag != 0)
1011+ {
1012+ g_source_remove(m_timeout_tag);
1013+ m_timeout_tag = 0;
1014+ }
1015+ }
1016+
1017+ core::Signal<> m_timeout;
1018+ const std::shared_ptr<Clock>& m_clock;
1019+ guint m_timeout_tag = 0;
1020+ DateTime m_wakeup_time;
1021+};
1022+
1023+/***
1024+****
1025+***/
1026+
1027+MainloopWakeupTimer::MainloopWakeupTimer(const std::shared_ptr<Clock>& clock):
1028+ p(new Impl(clock))
1029+{
1030+}
1031+
1032+MainloopWakeupTimer::~MainloopWakeupTimer()
1033+{
1034+}
1035+
1036+void MainloopWakeupTimer::set_wakeup_time(const DateTime& d)
1037+{
1038+ p->set_wakeup_time(d);
1039+}
1040+
1041+core::Signal<>& MainloopWakeupTimer::timeout()
1042+{
1043+ return p->timeout();
1044+}
1045+
1046+/***
1047+****
1048+***/
1049+
1050+} // namespace datetime
1051+} // namespace indicator
1052+} // namespace unity
1053
1054=== added file 'src/wakeup-timer-uha.cpp'
1055--- src/wakeup-timer-uha.cpp 1970-01-01 00:00:00 +0000
1056+++ src/wakeup-timer-uha.cpp 2014-06-11 04:07:06 +0000
1057@@ -0,0 +1,175 @@
1058+/*
1059+ * Copyright 2014 Canonical Ltd.
1060+ *
1061+ * This program is free software: you can redistribute it and/or modify it
1062+ * under the terms of the GNU General Public License version 3, as published
1063+ * by the Free Software Foundation.
1064+ *
1065+ * This program is distributed in the hope that it will be useful, but
1066+ * WITHOUT ANY WARRANTY; without even the implied warranties of
1067+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
1068+ * PURPOSE. See the GNU General Public License for more details.
1069+ *
1070+ * You should have received a copy of the GNU General Public License along
1071+ * with this program. If not, see <http://www.gnu.org/licenses/>.
1072+ *
1073+ * Authors:
1074+ * Charles Kerr <charles.kerr@canonical.com>
1075+ */
1076+
1077+#include <datetime/wakeup-timer-uha.h>
1078+
1079+#include <ubuntu/hardware/alarm.h>
1080+
1081+#include <glib.h>
1082+
1083+#include <unistd.h>
1084+
1085+#include <ctime> // struct timespec
1086+#include <mutex>
1087+#include <thread>
1088+
1089+namespace unity {
1090+namespace indicator {
1091+namespace datetime {
1092+
1093+/***
1094+****
1095+***/
1096+
1097+class UhaWakeupTimer::Impl
1098+{
1099+
1100+public:
1101+
1102+ Impl(const std::shared_ptr<Clock>& clock):
1103+ m_clock(clock),
1104+ m_hardware_alarm(u_hardware_alarm_create())
1105+ {
1106+ // fire up a worker thread that initially just sleeps
1107+ set_wakeup_time_to_the_distant_future();
1108+ m_thread = std::move(std::thread([&](){threadfunc();}));
1109+ }
1110+
1111+ ~Impl()
1112+ {
1113+ // tell the worker thread to wake up and exit
1114+ m_yielding = true;
1115+ set_wakeup_time(m_clock->localtime().add_full(0,0,0,0,0,0.1));
1116+
1117+ // wait for it to happen
1118+ if (m_thread.joinable())
1119+ m_thread.join();
1120+
1121+ g_idle_remove_by_data(this);
1122+
1123+ u_hardware_alarm_unref(m_hardware_alarm);
1124+ }
1125+
1126+ void set_wakeup_time(const DateTime& d)
1127+ {
1128+ g_debug("%s %s", G_STRLOC, G_STRFUNC);
1129+ std::lock_guard<std::recursive_mutex> lg(m_mutex);
1130+
1131+ const auto wakeup_time = d.to_unix();
1132+
1133+ // simple sanity check: don't try to wait for something that's already passed
1134+ const auto now = m_clock->localtime().to_unix();
1135+ g_return_if_fail (wakeup_time >= now);
1136+
1137+ struct timespec sleep_interval;
1138+ sleep_interval.tv_sec = wakeup_time;
1139+ sleep_interval.tv_nsec = 0;
1140+ g_debug("%s %s setting hardware wakeup time to %s (%zu seconds from now)",
1141+ G_STRLOC, G_STRFUNC,
1142+ d.format("%F %T").c_str(),
1143+ (size_t)(wakeup_time - now));
1144+ u_hardware_alarm_set_relative_to_with_behavior(m_hardware_alarm,
1145+ U_HARDWARE_ALARM_TIME_REFERENCE_RTC,
1146+ U_HARDWARE_ALARM_SLEEP_BEHAVIOR_WAKEUP_DEVICE,
1147+ &sleep_interval);
1148+ }
1149+
1150+ core::Signal<>& timeout() { return m_timeout; }
1151+
1152+private:
1153+
1154+ void set_wakeup_time_to_the_distant_future()
1155+ {
1156+ const auto tomorrow = m_clock->localtime().add_full(0,0,1,0,0,0);
1157+ set_wakeup_time(tomorrow);
1158+ }
1159+
1160+ static gboolean kick_idle (gpointer gself)
1161+ {
1162+ static_cast<Impl*>(gself)->m_timeout();
1163+
1164+ return G_SOURCE_REMOVE;
1165+ }
1166+
1167+ void threadfunc()
1168+ {
1169+ while (!m_yielding)
1170+ {
1171+ // wait for the next hw alarm
1172+ UHardwareAlarmWaitResult wait_result;
1173+ g_debug ("calling wait_for_next_alarm");
1174+ auto rc = u_hardware_alarm_wait_for_next_alarm(m_hardware_alarm, &wait_result);
1175+ g_return_if_fail (rc == U_STATUS_SUCCESS);
1176+
1177+ // set a long wakeup interval for the next iteration of the loop.
1178+ // if there's another Appointment queued up by the Planner,
1179+ // our timeout() listener will call set_wakeup_time() to set the
1180+ // real wakeup interval.
1181+ set_wakeup_time_to_the_distant_future();
1182+
1183+ // delegate the kick back to the main thread
1184+ g_idle_add (kick_idle, this);
1185+ }
1186+ }
1187+
1188+ core::Signal<> m_timeout;
1189+ std::recursive_mutex m_mutex;
1190+ bool m_yielding = false;
1191+ const std::shared_ptr<Clock>& m_clock;
1192+ UHardwareAlarm m_hardware_alarm = nullptr;
1193+ std::thread m_thread;
1194+};
1195+
1196+/***
1197+****
1198+***/
1199+
1200+UhaWakeupTimer::UhaWakeupTimer(const std::shared_ptr<Clock>& clock):
1201+ p(new Impl(clock))
1202+{
1203+}
1204+
1205+UhaWakeupTimer::~UhaWakeupTimer()
1206+{
1207+}
1208+
1209+bool UhaWakeupTimer::is_supported()
1210+{
1211+ auto hw_alarm = u_hardware_alarm_create();
1212+ g_debug ("%s hardware alarm %p", G_STRFUNC, hw_alarm);
1213+ return hw_alarm != nullptr;
1214+}
1215+
1216+void UhaWakeupTimer::set_wakeup_time(const DateTime& d)
1217+{
1218+ p->set_wakeup_time(d);
1219+}
1220+
1221+core::Signal<>& UhaWakeupTimer::timeout()
1222+{
1223+ return p->timeout();
1224+}
1225+
1226+/***
1227+****
1228+***/
1229+
1230+} // namespace datetime
1231+} // namespace indicator
1232+} // namespace unity
1233
1234=== modified file 'tests/CMakeLists.txt'
1235--- tests/CMakeLists.txt 2014-02-04 19:00:22 +0000
1236+++ tests/CMakeLists.txt 2014-06-11 04:07:06 +0000
1237@@ -41,8 +41,8 @@
1238 target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS})
1239 endfunction()
1240 add_test_by_name(test-actions)
1241+add_test_by_name(test-alarm-queue)
1242 add_test_by_name(test-clock)
1243-add_test_by_name(test-clock-watcher)
1244 add_test_by_name(test-exporter)
1245 add_test_by_name(test-formatter)
1246 add_test_by_name(test-live-actions)
1247
1248=== renamed file 'tests/test-clock-watcher.cpp' => 'tests/test-alarm-queue.cpp'
1249--- tests/test-clock-watcher.cpp 2014-03-10 02:08:47 +0000
1250+++ tests/test-alarm-queue.cpp 2014-06-11 04:07:06 +0000
1251@@ -17,7 +17,8 @@
1252 * Charles Kerr <charles.kerr@canonical.com>
1253 */
1254
1255-#include <datetime/clock-watcher.h>
1256+#include <datetime/alarm-queue-simple.h>
1257+#include <datetime/wakeup-timer-mainloop.h>
1258
1259 #include <gtest/gtest.h>
1260
1261@@ -25,7 +26,7 @@
1262
1263 using namespace unity::indicator::datetime;
1264
1265-class ClockWatcherFixture: public StateFixture
1266+class AlarmQueueFixture: public StateFixture
1267 {
1268 private:
1269
1270@@ -34,7 +35,8 @@
1271 protected:
1272
1273 std::vector<std::string> m_triggered;
1274- std::unique_ptr<ClockWatcher> m_watcher;
1275+ std::shared_ptr<WakeupTimer> m_wakeup_timer;
1276+ std::unique_ptr<AlarmQueue> m_watcher;
1277 std::shared_ptr<RangePlanner> m_range_planner;
1278 std::shared_ptr<UpcomingPlanner> m_upcoming;
1279
1280@@ -42,9 +44,10 @@
1281 {
1282 super::SetUp();
1283
1284+ m_wakeup_timer.reset(new MainloopWakeupTimer(m_state->clock));
1285 m_range_planner.reset(new MockRangePlanner);
1286 m_upcoming.reset(new UpcomingPlanner(m_range_planner, m_state->clock->localtime()));
1287- m_watcher.reset(new ClockWatcherImpl(m_state->clock, m_upcoming));
1288+ m_watcher.reset(new SimpleAlarmQueue(m_state->clock, m_upcoming, m_wakeup_timer));
1289 m_watcher->alarm_reached().connect([this](const Appointment& appt){
1290 m_triggered.push_back(appt.uid);
1291 });
1292@@ -108,7 +111,7 @@
1293 ****
1294 ***/
1295
1296-TEST_F(ClockWatcherFixture, AppointmentsChanged)
1297+TEST_F(AlarmQueueFixture, AppointmentsChanged)
1298 {
1299 // Add some appointments to the planner.
1300 // One of these matches our state's localtime, so that should get triggered.
1301@@ -117,12 +120,12 @@
1302 m_range_planner->appointments().set(a);
1303
1304 // Confirm that it got fired
1305- EXPECT_EQ(1, m_triggered.size());
1306+ ASSERT_EQ(1, m_triggered.size());
1307 EXPECT_EQ(a[0].uid, m_triggered[0]);
1308 }
1309
1310
1311-TEST_F(ClockWatcherFixture, TimeChanged)
1312+TEST_F(AlarmQueueFixture, TimeChanged)
1313 {
1314 // Add some appointments to the planner.
1315 // Neither of these match the state's localtime, so nothing should be triggered.
1316@@ -132,26 +135,27 @@
1317
1318 // Set the state's clock to a time that matches one of the appointments().
1319 // That appointment should get triggered.
1320+g_message ("%s setting clock to %s", G_STRLOC, a[1].begin.format("%F %T").c_str());
1321 m_mock_state->mock_clock->set_localtime(a[1].begin);
1322- EXPECT_EQ(1, m_triggered.size());
1323+ ASSERT_EQ(1, m_triggered.size());
1324 EXPECT_EQ(a[1].uid, m_triggered[0]);
1325 }
1326
1327
1328-TEST_F(ClockWatcherFixture, MoreThanOne)
1329+TEST_F(AlarmQueueFixture, MoreThanOne)
1330 {
1331 const auto now = m_state->clock->localtime();
1332 std::vector<Appointment> a = build_some_appointments();
1333 a[0].begin = a[1].begin = now;
1334 m_range_planner->appointments().set(a);
1335
1336- EXPECT_EQ(2, m_triggered.size());
1337+ ASSERT_EQ(2, m_triggered.size());
1338 EXPECT_EQ(a[0].uid, m_triggered[0]);
1339 EXPECT_EQ(a[1].uid, m_triggered[1]);
1340 }
1341
1342
1343-TEST_F(ClockWatcherFixture, NoDuplicates)
1344+TEST_F(AlarmQueueFixture, NoDuplicates)
1345 {
1346 // Setup: add an appointment that gets triggered.
1347 const auto now = m_state->clock->localtime();
1348@@ -160,13 +164,13 @@
1349 a.push_back(appointments[0]);
1350 a[0].begin = now;
1351 m_range_planner->appointments().set(a);
1352- EXPECT_EQ(1, m_triggered.size());
1353+ ASSERT_EQ(1, m_triggered.size());
1354 EXPECT_EQ(a[0].uid, m_triggered[0]);
1355
1356 // Now change the appointment vector by adding one to it.
1357- // Confirm that the ClockWatcher doesn't re-trigger a[0]
1358+ // Confirm that the AlarmQueue doesn't re-trigger a[0]
1359 a.push_back(appointments[1]);
1360 m_range_planner->appointments().set(a);
1361- EXPECT_EQ(1, m_triggered.size());
1362+ ASSERT_EQ(1, m_triggered.size());
1363 EXPECT_EQ(a[0].uid, m_triggered[0]);
1364 }

Subscribers

People subscribed via source and target branches