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
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2014-03-23 14:45:38 +0000
+++ CMakeLists.txt 2014-06-11 04:07:06 +0000
@@ -29,6 +29,7 @@
29##29##
3030
31find_package (PkgConfig REQUIRED)31find_package (PkgConfig REQUIRED)
32include (CheckIncludeFile)
32include (FindPkgConfig)33include (FindPkgConfig)
3334
34pkg_check_modules (SERVICE_DEPS REQUIRED35pkg_check_modules (SERVICE_DEPS REQUIRED
@@ -43,6 +44,12 @@
43 properties-cpp>=0.0.1)44 properties-cpp>=0.0.1)
44include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})45include_directories (SYSTEM ${SERVICE_DEPS_INCLUDE_DIRS})
4546
47CHECK_INCLUDE_FILE(ubuntu/hardware/alarm.h HAVE_UBUNTU_HW_ALARM_H)
48if (HAVE_UBUNTU_HW_ALARM_H)
49 set (SERVICE_DEPS_LIBRARIES -lubuntu_platform_hardware_api ${SERVICE_DEPS_LIBRARIES})
50 add_definitions(-DHAVE_UBUNTU_HW_ALARM_H)
51endif ()
52
46##53##
47## custom targets54## custom targets
48##55##
4956
=== modified file 'MERGE-REVIEW'
--- MERGE-REVIEW 2014-01-31 20:17:55 +0000
+++ MERGE-REVIEW 2014-06-11 04:07:06 +0000
@@ -6,14 +6,39 @@
66
7 * Ensure the project compiles and the test suite executes without error7 * Ensure the project compiles and the test suite executes without error
8 * Ensure that non-obvious code has comments explaining it8 * Ensure that non-obvious code has comments explaining it
9 * If the change works on specific profiles, please include those in the merge description.9 * If the change affects specific features, please reference the appropriate
10 tags in the merge description so reviewers can test appropriately:
11 [phone profile], [desktop profile], [alarms]
1012
11== Reviewer Responsibilities ==13== Reviewer Responsibilities ==
1214
13 * Did the Jenkins build compile? Pass? Run unit tests successfully?15 * Did the Jenkins build compile? Pass? Run unit tests successfully?
14 * Are there appropriate tests to cover any new functionality?16 * Are there appropriate tests to cover any new functionality?
15 * If the description says this effects the phone profile:17 * Do the tag-specific tests pass?
16 * Run tests indicator-datetime/unity8*18
17 * If the description says this effects the desktop profile:19== Phone Profile Tests ==
18 * Run tests indicator-datetime/unity7*20
21 * Run tests indicator-datetime/unity8*
22
23== Desktop Profile Tests ==
24
25 * Run tests indicator-datetime/unity7*
26
27== Alarm Tests ==
28
29 * Hardware wakeups for new alarms:
30 1. Create and save an upcoming alarm in ubuntu-clock-app.
31 2. Unplug the phone from any USB connection and put it to sleep.
32 3. Confirm that the alarm sounds on time even if the phone is asleep.
33 (Note: if in doubt about sleep you can see in the syslog whether the
34 device actually suspended or whether the suspend was aborted)
35
36 * Hardware wakeups for edited alarms:
37 1. Edit an alarm that's already passed. (see previous test)
38 2. Unplug the phone from any USB connection and put it to sleep.
39 3. Confirm that the alarm sounds on time even if the phone is asleep.
40 (Note: if in doubt about sleep you can see in the syslog whether the
41 device actually suspended or whether the suspend was aborted.)
42
43
1944
2045
=== modified file 'debian/control'
--- debian/control 2014-03-23 20:11:06 +0000
+++ debian/control 2014-06-11 04:07:06 +0000
@@ -19,6 +19,8 @@
19 libedataserver1.2-dev (>= 3.5),19 libedataserver1.2-dev (>= 3.5),
20 liburl-dispatcher1-dev,20 liburl-dispatcher1-dev,
21 libproperties-cpp-dev,21 libproperties-cpp-dev,
22 libplatform-hardware-api-headers [armhf i386 amd64],
23 libplatform-hardware-api1-dev [armhf i386 amd64],
22 libdbustest1-dev,24 libdbustest1-dev,
23 locales,25 locales,
24Standards-Version: 3.9.326Standards-Version: 3.9.3
2527
=== added file 'include/datetime/alarm-queue-simple.h'
--- include/datetime/alarm-queue-simple.h 1970-01-01 00:00:00 +0000
+++ include/datetime/alarm-queue-simple.h 2014-06-11 04:07:06 +0000
@@ -0,0 +1,63 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef INDICATOR_DATETIME_ALARM_QUEUE_SIMPLE_H
21#define INDICATOR_DATETIME_ALARM_QUEUE_SIMPLE_H
22
23#include <datetime/alarm-queue.h>
24#include <datetime/clock.h>
25#include <datetime/planner.h>
26#include <datetime/wakeup-timer.h>
27
28namespace unity {
29namespace indicator {
30namespace datetime {
31
32/**
33 * \brief A #AlarmQueue implementation
34 */
35class SimpleAlarmQueue: public AlarmQueue
36{
37public:
38 SimpleAlarmQueue(const std::shared_ptr<Clock>& clock,
39 const std::shared_ptr<Planner>& upcoming_planner,
40 const std::shared_ptr<WakeupTimer>& timer);
41 ~SimpleAlarmQueue();
42 core::Signal<const Appointment&>& alarm_reached();
43
44private:
45 void requeue();
46 bool find_next_alarm(Appointment& setme) const;
47 std::vector<Appointment> find_current_alarms() const;
48 void check_alarms();
49
50 std::set<std::pair<std::string,DateTime>> m_triggered;
51 const std::shared_ptr<Clock> m_clock;
52 const std::shared_ptr<Planner> m_planner;
53 const std::shared_ptr<WakeupTimer> m_timer;
54 core::Signal<const Appointment&> m_alarm_reached;
55 DateTime m_datetime;
56};
57
58
59} // namespace datetime
60} // namespace indicator
61} // namespace unity
62
63#endif // INDICATOR_DATETIME_ALARM_QUEUE_H
064
=== renamed file 'include/datetime/clock-watcher.h' => 'include/datetime/alarm-queue.h'
--- include/datetime/clock-watcher.h 2014-03-10 02:08:47 +0000
+++ include/datetime/alarm-queue.h 2014-06-11 04:07:06 +0000
@@ -17,12 +17,10 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#ifndef INDICATOR_DATETIME_CLOCK_WATCHER_H20#ifndef INDICATOR_DATETIME_ALARM_QUEUE_H
21#define INDICATOR_DATETIME_CLOCK_WATCHER_H21#define INDICATOR_DATETIME_ALARM_QUEUE_H
2222
23#include <datetime/appointment.h>23#include <datetime/appointment.h>
24#include <datetime/clock.h>
25#include <datetime/planner-upcoming.h>
2624
27#include <core/signal.h>25#include <core/signal.h>
2826
@@ -34,42 +32,28 @@
34namespace indicator {32namespace indicator {
35namespace datetime {33namespace datetime {
3634
35/***
36****
37***/
3738
38/**39/**
39 * \brief Watches the clock and appointments to notify when an40 * \brief Watches the clock and appointments to notify when an
40 * appointment's time is reached.41 * appointment's time is reached.
41 */42 */
42class ClockWatcher43class AlarmQueue
43{44{
44public:45public:
45 ClockWatcher() =default;46 AlarmQueue() =default;
46 virtual ~ClockWatcher() =default;47 virtual ~AlarmQueue() =default;
47 virtual core::Signal<const Appointment&>& alarm_reached() = 0;48 virtual core::Signal<const Appointment&>& alarm_reached() = 0;
48};49};
4950
5051/***
51/**52****
52 * \brief A #ClockWatcher implementation 53***/
53 */
54class ClockWatcherImpl: public ClockWatcher
55{
56public:
57 ClockWatcherImpl(const std::shared_ptr<Clock>& clock,
58 const std::shared_ptr<UpcomingPlanner>& upcoming_planner);
59 ~ClockWatcherImpl() =default;
60 core::Signal<const Appointment&>& alarm_reached();
61
62private:
63 void pulse();
64 std::set<std::string> m_triggered;
65 const std::shared_ptr<Clock> m_clock;
66 const std::shared_ptr<UpcomingPlanner> m_upcoming_planner;
67 core::Signal<const Appointment&> m_alarm_reached;
68};
69
7054
71} // namespace datetime55} // namespace datetime
72} // namespace indicator56} // namespace indicator
73} // namespace unity57} // namespace unity
7458
75#endif // INDICATOR_DATETIME_CLOCK_WATCHER_H59#endif // INDICATOR_DATETIME_ALARM_QUEUE_H
7660
=== modified file 'include/datetime/date-time.h'
--- include/datetime/date-time.h 2014-03-10 02:08:47 +0000
+++ include/datetime/date-time.h 2014-06-11 04:07:06 +0000
@@ -61,10 +61,13 @@
61 bool operator<=(const DateTime& that) const;61 bool operator<=(const DateTime& that) const;
62 bool operator!=(const DateTime& that) const;62 bool operator!=(const DateTime& that) const;
63 bool operator==(const DateTime& that) const;63 bool operator==(const DateTime& that) const;
64 int64_t operator- (const DateTime& that) const;
6465
65 static bool is_same_day(const DateTime& a, const DateTime& b);66 static bool is_same_day(const DateTime& a, const DateTime& b);
66 static bool is_same_minute(const DateTime& a, const DateTime& b);67 static bool is_same_minute(const DateTime& a, const DateTime& b);
6768
69 bool is_set() const { return m_dt != nullptr; }
70
68private:71private:
69 std::shared_ptr<GDateTime> m_dt;72 std::shared_ptr<GDateTime> m_dt;
70};73};
7174
=== modified file 'include/datetime/planner-range.h'
--- include/datetime/planner-range.h 2014-03-10 03:26:26 +0000
+++ include/datetime/planner-range.h 2014-06-11 04:07:06 +0000
@@ -53,7 +53,7 @@
53{53{
54public:54public:
55 SimpleRangePlanner(const std::shared_ptr<Engine>& engine,55 SimpleRangePlanner(const std::shared_ptr<Engine>& engine,
56 const std::shared_ptr<Timezone>& timezone);56 const std::shared_ptr<Timezone>& timezone);
57 virtual ~SimpleRangePlanner();57 virtual ~SimpleRangePlanner();
5858
59 core::Property<std::vector<Appointment>>& appointments();59 core::Property<std::vector<Appointment>>& appointments();
6060
=== added file 'include/datetime/wakeup-timer-mainloop.h'
--- include/datetime/wakeup-timer-mainloop.h 1970-01-01 00:00:00 +0000
+++ include/datetime/wakeup-timer-mainloop.h 2014-06-11 04:07:06 +0000
@@ -0,0 +1,62 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef INDICATOR_DATETIME_WAKEUP_TIMER_MAINLOOP_H
21#define INDICATOR_DATETIME_WAKEUP_TIMER_MAINLOOP_H
22
23#include <datetime/clock.h>
24#include <datetime/wakeup-timer.h>
25
26#include <memory> // std::unique_ptr, std::shared_ptr
27
28namespace unity {
29namespace indicator {
30namespace datetime {
31
32/***
33****
34***/
35
36/**
37 * \brief a WakeupTimer implemented with g_timeout_add()
38 */
39class MainloopWakeupTimer: public WakeupTimer
40{
41public:
42 MainloopWakeupTimer(const std::shared_ptr<Clock>&);
43 ~MainloopWakeupTimer();
44 void set_wakeup_time (const DateTime&);
45 core::Signal<>& timeout();
46
47private:
48 MainloopWakeupTimer(const MainloopWakeupTimer&) =delete;
49 MainloopWakeupTimer& operator= (const MainloopWakeupTimer&) =delete;
50 class Impl;
51 std::unique_ptr<Impl> p;
52};
53
54/***
55****
56***/
57
58} // namespace datetime
59} // namespace indicator
60} // namespace unity
61
62#endif // INDICATOR_DATETIME_WAKEUP_TIMER_MAINLOOP_H
063
=== added file 'include/datetime/wakeup-timer-uha.h'
--- include/datetime/wakeup-timer-uha.h 1970-01-01 00:00:00 +0000
+++ include/datetime/wakeup-timer-uha.h 2014-06-11 04:07:06 +0000
@@ -0,0 +1,64 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef INDICATOR_DATETIME_WAKEUP_TIMER_UHA_H
21#define INDICATOR_DATETIME_WAKEUP_TIMER_UHA_H
22
23#include <datetime/clock.h>
24#include <datetime/wakeup-timer.h>
25
26#include <memory> // std::unique_ptr, std::shared_ptr
27
28namespace unity {
29namespace indicator {
30namespace datetime {
31
32/***
33****
34***/
35
36/**
37 * \brief a WakeupTimer implemented the UbuntuHardwareAlarm API
38 */
39class UhaWakeupTimer: public WakeupTimer
40{
41public:
42 UhaWakeupTimer(const std::shared_ptr<Clock>&);
43 ~UhaWakeupTimer();
44 void set_wakeup_time (const DateTime&);
45 core::Signal<>& timeout();
46
47 static bool is_supported();
48
49private:
50 UhaWakeupTimer(const UhaWakeupTimer&) =delete;
51 UhaWakeupTimer& operator= (const UhaWakeupTimer&) =delete;
52 class Impl;
53 std::unique_ptr<Impl> p;
54};
55
56/***
57****
58***/
59
60} // namespace datetime
61} // namespace indicator
62} // namespace unity
63
64#endif // INDICATOR_DATETIME_WAKEUP_TIMER_UHA_H
065
=== added file 'include/datetime/wakeup-timer.h'
--- include/datetime/wakeup-timer.h 1970-01-01 00:00:00 +0000
+++ include/datetime/wakeup-timer.h 2014-06-11 04:07:06 +0000
@@ -0,0 +1,55 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#ifndef INDICATOR_DATETIME_WAKEUP_TIMER_H
21#define INDICATOR_DATETIME_WAKEUP_TIMER_H
22
23#include <datetime/date-time.h>
24
25#include <core/signal.h>
26
27namespace unity {
28namespace indicator {
29namespace datetime {
30
31/***
32****
33***/
34
35/**
36 * \brief A one-shot timer that emits a signal when its timeout is reached.
37 */
38class WakeupTimer
39{
40public:
41 WakeupTimer() =default;
42 virtual ~WakeupTimer() =default;
43 virtual void set_wakeup_time (const DateTime&) =0;
44 virtual core::Signal<>& timeout() = 0;
45};
46
47/***
48****
49***/
50
51} // namespace datetime
52} // namespace indicator
53} // namespace unity
54
55#endif // INDICATOR_DATETIME_WAKEUP_TIMER_H
056
=== modified file 'src/CMakeLists.txt'
--- src/CMakeLists.txt 2014-03-10 03:26:26 +0000
+++ src/CMakeLists.txt 2014-06-11 04:07:06 +0000
@@ -7,30 +7,37 @@
7add_definitions (-DTIMEZONE_FILE="/etc/timezone"7add_definitions (-DTIMEZONE_FILE="/etc/timezone"
8 -DG_LOG_DOMAIN="Indicator-Datetime")8 -DG_LOG_DOMAIN="Indicator-Datetime")
99
10add_library (${SERVICE_LIB} STATIC10set (SERVICE_SOURCES
11 actions.cpp11 actions.cpp
12 actions-live.cpp12 actions-live.cpp
13 appointment.cpp13 alarm-queue-simple.cpp
14 clock.cpp14 appointment.cpp
15 clock-live.cpp15 clock.cpp
16 clock-watcher.cpp16 clock-live.cpp
17 date-time.cpp17 date-time.cpp
18 engine-eds.cpp18 engine-eds.cpp
19 exporter.cpp19 exporter.cpp
20 formatter.cpp20 formatter.cpp
21 formatter-desktop.cpp21 formatter-desktop.cpp
22 locations.cpp22 locations.cpp
23 locations-settings.cpp23 locations-settings.cpp
24 menu.cpp24 menu.cpp
25 planner-month.cpp25 planner-month.cpp
26 planner-range.cpp26 planner-range.cpp
27 planner-upcoming.cpp27 planner-upcoming.cpp
28 settings-live.cpp28 settings-live.cpp
29 snap.cpp29 snap.cpp
30 timezone-file.cpp30 timezone-file.cpp
31 timezone-geoclue.cpp31 timezone-geoclue.cpp
32 timezones-live.cpp32 timezones-live.cpp
33 utils.c)33 utils.c
34 wakeup-timer-mainloop.cpp)
35
36if (HAVE_UBUNTU_HW_ALARM_H)
37 set (SERVICE_SOURCES ${SERVICE_SOURCES} wakeup-timer-uha.cpp)
38endif ()
39
40add_library (${SERVICE_LIB} STATIC ${SERVICE_SOURCES})
34include_directories (${CMAKE_SOURCE_DIR})41include_directories (${CMAKE_SOURCE_DIR})
35link_directories (${SERVICE_DEPS_LIBRARY_DIRS})42link_directories (${SERVICE_DEPS_LIBRARY_DIRS})
3643
3744
=== renamed file 'src/clock-watcher.cpp' => 'src/alarm-queue-simple.cpp'
--- src/clock-watcher.cpp 2014-03-10 02:08:47 +0000
+++ src/alarm-queue-simple.cpp 2014-06-11 04:07:06 +0000
@@ -17,59 +17,137 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#include <datetime/clock-watcher.h>20#include <datetime/alarm-queue-simple.h>
21
22#include <cmath>
2123
22namespace unity {24namespace unity {
23namespace indicator {25namespace indicator {
24namespace datetime {26namespace datetime {
2527
26/***28/***
27****29**** Public API
28***/30***/
2931
30ClockWatcherImpl::ClockWatcherImpl(const std::shared_ptr<Clock>& clock,32SimpleAlarmQueue::SimpleAlarmQueue(const std::shared_ptr<Clock>& clock,
31 const std::shared_ptr<UpcomingPlanner>& upcoming_planner):33 const std::shared_ptr<Planner>& planner,
34 const std::shared_ptr<WakeupTimer>& timer):
32 m_clock(clock),35 m_clock(clock),
33 m_upcoming_planner(upcoming_planner)36 m_planner(planner),
37 m_timer(timer),
38 m_datetime(clock->localtime())
34{39{
35 m_clock->date_changed.connect([this](){40 m_planner->appointments().changed().connect([this](const std::vector<Appointment>&){
41 g_debug("AlarmQueue %p calling requeue() due to appointments changed", this);
42 requeue();
43 });
44
45 m_clock->minute_changed.connect([=]{
36 const auto now = m_clock->localtime();46 const auto now = m_clock->localtime();
37 g_debug("ClockWatcher %p refretching appointments due to date change: %s", this, now.format("%F %T").c_str());47 constexpr auto skew_threshold_usec = int64_t{90} * G_USEC_PER_SEC;
38 m_upcoming_planner->date().set(now);48 const bool clock_jumped = std::abs(now - m_datetime) > skew_threshold_usec;
39 });49 m_datetime = now;
4050 if (clock_jumped) {
41 m_clock->minute_changed.connect([this](){51 g_debug("AlarmQueue %p calling requeue() due to clock skew", this);
42 g_debug("ClockWatcher %p calling pulse() due to clock minute_changed", this);52 requeue();
43 pulse();53 }
44 });54 });
4555
46 m_upcoming_planner->appointments().changed().connect([this](const std::vector<Appointment>&){56 m_timer->timeout().connect([this](){
47 g_debug("ClockWatcher %p calling pulse() due to appointments changed", this);57 g_debug("AlarmQueue %p calling requeue() due to timeout", this);
48 pulse();58 requeue();
49 });59 });
5060
51 pulse();61 requeue();
52}62}
5363
54core::Signal<const Appointment&>& ClockWatcherImpl::alarm_reached()64SimpleAlarmQueue::~SimpleAlarmQueue()
65{
66}
67
68core::Signal<const Appointment&>& SimpleAlarmQueue::alarm_reached()
55{69{
56 return m_alarm_reached;70 return m_alarm_reached;
57}71}
5872
59void ClockWatcherImpl::pulse()73/***
60{74****
61 const auto now = m_clock->localtime();75***/
6276
63 for(const auto& appointment : m_upcoming_planner->appointments().get())77void SimpleAlarmQueue::requeue()
64 {78{
65 if (m_triggered.count(appointment.uid))79 // kick any current alarms
66 continue;80 for (auto current : find_current_alarms())
67 if (!DateTime::is_same_minute(now, appointment.begin))81 {
68 continue;82 const std::pair<std::string,DateTime> trig {current.uid, current.begin};
6983 m_triggered.insert(trig);
70 m_triggered.insert(appointment.uid);84 m_alarm_reached(current);
71 m_alarm_reached(appointment);85 }
72 }86
87 // idle until the next alarm
88 Appointment next;
89 if (find_next_alarm(next))
90 {
91 g_debug ("setting timer to wake up for next appointment '%s' at %s",
92 next.summary.c_str(),
93 next.begin.format("%F %T").c_str());
94
95 m_timer->set_wakeup_time(next.begin);
96 }
97}
98
99// find the next alarm that will kick now or in the future
100bool SimpleAlarmQueue::find_next_alarm(Appointment& setme) const
101{
102 bool found = false;
103 Appointment tmp;
104 const auto now = m_clock->localtime();
105 const auto beginning_of_minute = now.add_full (0, 0, 0, 0, 0, -now.seconds());
106
107 const auto appointments = m_planner->appointments().get();
108 g_debug ("planner has %zu appointments in it", (size_t)appointments.size());
109
110 for(const auto& walk : appointments)
111 {
112 const std::pair<std::string,DateTime> trig {walk.uid, walk.begin};
113 if (m_triggered.count(trig))
114 continue;
115
116 if (walk.begin < beginning_of_minute) // has this one already passed?
117 continue;
118
119 if (found && (tmp.begin < walk.begin)) // do we already have a better match?
120 continue;
121
122 tmp = walk;
123 found = true;
124 }
125
126 if (found)
127 setme = tmp;
128
129 return found;
130}
131
132// find the alarm(s) that should kick right now
133std::vector<Appointment> SimpleAlarmQueue::find_current_alarms() const
134{
135 std::vector<Appointment> appointments;
136
137 const auto now = m_clock->localtime();
138
139 for(const auto& walk : m_planner->appointments().get())
140 {
141 const std::pair<std::string,DateTime> trig {walk.uid, walk.begin};
142 if (m_triggered.count(trig)) // did we already use this one?
143 continue;
144 if (!DateTime::is_same_minute(now, walk.begin))
145 continue;
146
147 appointments.push_back(walk);
148 }
149
150 return appointments;
73}151}
74152
75/***153/***
76154
=== modified file 'src/date-time.cpp'
--- src/date-time.cpp 2014-03-10 02:08:47 +0000
+++ src/date-time.cpp 2014-06-11 04:07:06 +0000
@@ -174,6 +174,11 @@
174 return g_date_time_compare(get(), that.get()) == 0;174 return g_date_time_compare(get(), that.get()) == 0;
175}175}
176176
177int64_t DateTime::operator- (const DateTime& that) const
178{
179 return g_date_time_difference(get(), that.get());
180}
181
177bool DateTime::is_same_day(const DateTime& a, const DateTime& b)182bool DateTime::is_same_day(const DateTime& a, const DateTime& b)
178{183{
179 // it's meaningless to compare uninitialized dates184 // it's meaningless to compare uninitialized dates
180185
=== modified file 'src/engine-eds.cpp'
--- src/engine-eds.cpp 2014-04-15 16:11:34 +0000
+++ src/engine-eds.cpp 2014-06-11 04:07:06 +0000
@@ -418,6 +418,14 @@
418 auto status = ICAL_STATUS_NONE;418 auto status = ICAL_STATUS_NONE;
419 e_cal_component_get_status(component, &status);419 e_cal_component_get_status(component, &status);
420420
421 const auto begin_dt = DateTime(begin);
422 const auto end_dt = DateTime(end);
423 g_debug ("got appointment from %s to %s, uid %s status %d",
424 begin_dt.format("%F %T").c_str(),
425 end_dt.format("%F %T").c_str(),
426 uid,
427 (int)status);
428
421 if ((uid != nullptr) &&429 if ((uid != nullptr) &&
422 (status != ICAL_STATUS_COMPLETED) &&430 (status != ICAL_STATUS_COMPLETED) &&
423 (status != ICAL_STATUS_CANCELLED))431 (status != ICAL_STATUS_CANCELLED))
@@ -430,8 +438,8 @@
430 if (text.value)438 if (text.value)
431 appointment.summary = text.value;439 appointment.summary = text.value;
432440
433 appointment.begin = DateTime(begin);441 appointment.begin = begin_dt;
434 appointment.end = DateTime(end);442 appointment.end = end_dt;
435 appointment.color = subtask->color;443 appointment.color = subtask->color;
436 appointment.uid = uid;444 appointment.uid = uid;
437445
438446
=== modified file 'src/main.cpp'
--- src/main.cpp 2014-03-10 03:26:26 +0000
+++ src/main.cpp 2014-06-11 04:07:06 +0000
@@ -18,8 +18,8 @@
18 */18 */
1919
20#include <datetime/actions-live.h>20#include <datetime/actions-live.h>
21#include <datetime/alarm-queue-simple.h>
21#include <datetime/clock.h>22#include <datetime/clock.h>
22#include <datetime/clock-watcher.h>
23#include <datetime/engine-mock.h>23#include <datetime/engine-mock.h>
24#include <datetime/engine-eds.h>24#include <datetime/engine-eds.h>
25#include <datetime/exporter.h>25#include <datetime/exporter.h>
@@ -31,6 +31,11 @@
31#include <datetime/state.h>31#include <datetime/state.h>
32#include <datetime/timezone-file.h>32#include <datetime/timezone-file.h>
33#include <datetime/timezones-live.h>33#include <datetime/timezones-live.h>
34#include <datetime/wakeup-timer-mainloop.h>
35
36#ifdef HAVE_UBUNTU_HW_ALARM_H
37 #include <datetime/wakeup-timer-uha.h>
38#endif
3439
35#include <glib/gi18n.h> // bindtextdomain()40#include <glib/gi18n.h> // bindtextdomain()
36#include <gio/gio.h>41#include <gio/gio.h>
@@ -42,6 +47,81 @@
4247
43using namespace unity::indicator::datetime;48using namespace unity::indicator::datetime;
4449
50namespace
51{
52 std::shared_ptr<Engine> create_engine()
53 {
54 std::shared_ptr<Engine> engine;
55
56 // we don't show appointments in the greeter,
57 // so no need to connect to EDS there...
58 if (!g_strcmp0("lightdm", g_get_user_name()))
59 engine.reset(new MockEngine);
60 else
61 engine.reset(new EdsEngine);
62
63 return engine;
64 }
65
66 std::shared_ptr<WakeupTimer> create_wakeup_timer(const std::shared_ptr<Clock>& clock)
67 {
68 std::shared_ptr<WakeupTimer> wakeup_timer;
69
70#ifdef HAVE_UBUNTU_HW_ALARM_H
71 if (UhaWakeupTimer::is_supported()) // prefer to use the platform API
72 wakeup_timer = std::make_shared<UhaWakeupTimer>(clock);
73 else
74#endif
75 wakeup_timer = std::make_shared<MainloopWakeupTimer>(clock);
76
77 return wakeup_timer;
78 }
79
80 std::shared_ptr<State> create_state(const std::shared_ptr<Engine>& engine,
81 const std::shared_ptr<Timezone>& tz)
82 {
83 // create the live objects
84 auto live_settings = std::make_shared<LiveSettings>();
85 auto live_timezones = std::make_shared<LiveTimezones>(live_settings, TIMEZONE_FILE);
86 auto live_clock = std::make_shared<LiveClock>(live_timezones);
87
88 // create a full-month planner currently pointing to the current month
89 const auto now = live_clock->localtime();
90 auto range_planner = std::make_shared<SimpleRangePlanner>(engine, tz);
91 auto calendar_month = std::make_shared<MonthPlanner>(range_planner, now);
92
93 // create an upcoming-events planner currently pointing to the current date
94 range_planner = std::make_shared<SimpleRangePlanner>(engine, tz);
95 auto calendar_upcoming = std::make_shared<UpcomingPlanner>(range_planner, now);
96
97 // create the state
98 auto state = std::make_shared<State>();
99 state->settings = live_settings;
100 state->clock = live_clock;
101 state->locations = std::make_shared<SettingsLocations>(live_settings, live_timezones);
102 state->calendar_month = calendar_month;
103 state->calendar_upcoming = calendar_upcoming;
104 return state;
105 }
106
107 std::shared_ptr<AlarmQueue> create_simple_alarm_queue(const std::shared_ptr<Clock>& clock,
108 const std::shared_ptr<Engine>& engine,
109 const std::shared_ptr<Timezone>& tz)
110 {
111 // create an upcoming-events planner that =always= tracks the clock's date
112 auto range_planner = std::make_shared<SimpleRangePlanner>(engine, tz);
113 auto upcoming_planner = std::make_shared<UpcomingPlanner>(range_planner, clock->localtime());
114 clock->date_changed.connect([clock,upcoming_planner](){
115 const auto now = clock->localtime();
116 g_debug("refretching appointments due to date change: %s", now.format("%F %T").c_str());
117 upcoming_planner->date().set(now);
118 });
119
120 auto wakeup_timer = create_wakeup_timer(clock);
121 return std::make_shared<SimpleAlarmQueue>(clock, upcoming_planner, wakeup_timer);
122 }
123}
124
45int125int
46main(int /*argc*/, char** /*argv*/)126main(int /*argc*/, char** /*argv*/)
47{127{
@@ -54,35 +134,16 @@
54 bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR);134 bindtextdomain(GETTEXT_PACKAGE, GNOMELOCALEDIR);
55 textdomain(GETTEXT_PACKAGE);135 textdomain(GETTEXT_PACKAGE);
56136
57 // we don't show appointments in the greeter,137 auto engine = create_engine();
58 // so no need to connect to EDS there...138 auto timezone = std::make_shared<FileTimezone>(TIMEZONE_FILE);
59 std::shared_ptr<Engine> engine;139 auto state = create_state(engine, timezone);
60 if (!g_strcmp0("lightdm", g_get_user_name()))140 auto actions = std::make_shared<LiveActions>(state);
61 engine.reset(new MockEngine);
62 else
63 engine.reset(new EdsEngine);
64
65 // build the state, actions, and menufactory
66 std::shared_ptr<State> state(new State);
67 std::shared_ptr<Settings> live_settings(new LiveSettings);
68 std::shared_ptr<Timezones> live_timezones(new LiveTimezones(live_settings, TIMEZONE_FILE));
69 std::shared_ptr<Clock> live_clock(new LiveClock(live_timezones));
70 std::shared_ptr<Timezone> file_timezone(new FileTimezone(TIMEZONE_FILE));
71 const auto now = live_clock->localtime();
72 state->settings = live_settings;
73 state->clock = live_clock;
74 state->locations.reset(new SettingsLocations(live_settings, live_timezones));
75 auto calendar_month = new MonthPlanner(std::shared_ptr<RangePlanner>(new SimpleRangePlanner(engine, file_timezone)), now);
76 state->calendar_month.reset(calendar_month);
77 state->calendar_upcoming.reset(new UpcomingPlanner(std::shared_ptr<RangePlanner>(new SimpleRangePlanner(engine, file_timezone)), now));
78 std::shared_ptr<Actions> actions(new LiveActions(state));
79 MenuFactory factory(actions, state);141 MenuFactory factory(actions, state);
80142
81 // snap decisions143 // set up the snap decisions
82 std::shared_ptr<UpcomingPlanner> upcoming_planner(new UpcomingPlanner(std::shared_ptr<RangePlanner>(new SimpleRangePlanner(engine, file_timezone)), now));
83 ClockWatcherImpl clock_watcher(live_clock, upcoming_planner);
84 Snap snap;144 Snap snap;
85 clock_watcher.alarm_reached().connect([&snap](const Appointment& appt){145 auto alarm_queue = create_simple_alarm_queue(state->clock, engine, timezone);
146 alarm_queue->alarm_reached().connect([&snap](const Appointment& appt){
86 auto snap_show = [](const Appointment& a){147 auto snap_show = [](const Appointment& a){
87 const char* url;148 const char* url;
88 if(!a.url.empty())149 if(!a.url.empty())
89150
=== modified file 'src/planner-range.cpp'
--- src/planner-range.cpp 2014-03-10 03:26:26 +0000
+++ src/planner-range.cpp 2014-06-11 04:07:06 +0000
@@ -34,7 +34,7 @@
34 m_range(std::pair<DateTime,DateTime>(DateTime::NowLocal(), DateTime::NowLocal()))34 m_range(std::pair<DateTime,DateTime>(DateTime::NowLocal(), DateTime::NowLocal()))
35{35{
36 engine->changed().connect([this](){36 engine->changed().connect([this](){
37 g_debug("RangePlanner %p rebuilding soon because Engine %p emitted 'changed' signal%p", this, m_engine.get());37 g_debug("RangePlanner %p rebuilding soon because Engine %p emitted 'changed' signal", this, m_engine.get());
38 rebuild_soon();38 rebuild_soon();
39 });39 });
4040
4141
=== added file 'src/wakeup-timer-mainloop.cpp'
--- src/wakeup-timer-mainloop.cpp 1970-01-01 00:00:00 +0000
+++ src/wakeup-timer-mainloop.cpp 2014-06-11 04:07:06 +0000
@@ -0,0 +1,138 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include <datetime/wakeup-timer-mainloop.h>
21
22#include <glib.h>
23
24#include <cstdlib> // abs()
25
26namespace unity {
27namespace indicator {
28namespace datetime {
29
30/***
31****
32***/
33
34class MainloopWakeupTimer::Impl
35{
36
37public:
38
39 Impl(const std::shared_ptr<Clock>& clock):
40 m_clock(clock)
41 {
42 }
43
44 ~Impl()
45 {
46 cancel_timer();
47 }
48
49 void set_wakeup_time(const DateTime& d)
50 {
51 m_wakeup_time = d;
52
53 rebuild_timer();
54 }
55
56 core::Signal<>& timeout() { return m_timeout; }
57
58private:
59
60 void rebuild_timer()
61 {
62 cancel_timer();
63
64 g_return_if_fail(m_wakeup_time.is_set());
65
66 const auto now = m_clock->localtime();
67 const auto difference_usec = g_date_time_difference(m_wakeup_time.get(), now.get());
68 const guint interval_msec = std::abs(difference_usec) / 1000u;
69 g_debug("%s setting wakeup timer to kick at %s, which is in %zu seconds",
70 G_STRFUNC,
71 m_wakeup_time.format("%F %T").c_str(),
72 size_t{interval_msec/1000});
73
74 m_timeout_tag = g_timeout_add_full(G_PRIORITY_HIGH,
75 interval_msec,
76 on_timeout,
77 this,
78 nullptr);
79 }
80
81 static gboolean on_timeout(gpointer gself)
82 {
83 g_debug("%s %s", G_STRLOC, G_STRFUNC);
84 static_cast<Impl*>(gself)->on_timeout();
85 return G_SOURCE_REMOVE;
86 }
87
88 void on_timeout()
89 {
90 cancel_timer();
91 m_timeout();
92 }
93
94 void cancel_timer()
95 {
96 if (m_timeout_tag != 0)
97 {
98 g_source_remove(m_timeout_tag);
99 m_timeout_tag = 0;
100 }
101 }
102
103 core::Signal<> m_timeout;
104 const std::shared_ptr<Clock>& m_clock;
105 guint m_timeout_tag = 0;
106 DateTime m_wakeup_time;
107};
108
109/***
110****
111***/
112
113MainloopWakeupTimer::MainloopWakeupTimer(const std::shared_ptr<Clock>& clock):
114 p(new Impl(clock))
115{
116}
117
118MainloopWakeupTimer::~MainloopWakeupTimer()
119{
120}
121
122void MainloopWakeupTimer::set_wakeup_time(const DateTime& d)
123{
124 p->set_wakeup_time(d);
125}
126
127core::Signal<>& MainloopWakeupTimer::timeout()
128{
129 return p->timeout();
130}
131
132/***
133****
134***/
135
136} // namespace datetime
137} // namespace indicator
138} // namespace unity
0139
=== added file 'src/wakeup-timer-uha.cpp'
--- src/wakeup-timer-uha.cpp 1970-01-01 00:00:00 +0000
+++ src/wakeup-timer-uha.cpp 2014-06-11 04:07:06 +0000
@@ -0,0 +1,175 @@
1/*
2 * Copyright 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Charles Kerr <charles.kerr@canonical.com>
18 */
19
20#include <datetime/wakeup-timer-uha.h>
21
22#include <ubuntu/hardware/alarm.h>
23
24#include <glib.h>
25
26#include <unistd.h>
27
28#include <ctime> // struct timespec
29#include <mutex>
30#include <thread>
31
32namespace unity {
33namespace indicator {
34namespace datetime {
35
36/***
37****
38***/
39
40class UhaWakeupTimer::Impl
41{
42
43public:
44
45 Impl(const std::shared_ptr<Clock>& clock):
46 m_clock(clock),
47 m_hardware_alarm(u_hardware_alarm_create())
48 {
49 // fire up a worker thread that initially just sleeps
50 set_wakeup_time_to_the_distant_future();
51 m_thread = std::move(std::thread([&](){threadfunc();}));
52 }
53
54 ~Impl()
55 {
56 // tell the worker thread to wake up and exit
57 m_yielding = true;
58 set_wakeup_time(m_clock->localtime().add_full(0,0,0,0,0,0.1));
59
60 // wait for it to happen
61 if (m_thread.joinable())
62 m_thread.join();
63
64 g_idle_remove_by_data(this);
65
66 u_hardware_alarm_unref(m_hardware_alarm);
67 }
68
69 void set_wakeup_time(const DateTime& d)
70 {
71 g_debug("%s %s", G_STRLOC, G_STRFUNC);
72 std::lock_guard<std::recursive_mutex> lg(m_mutex);
73
74 const auto wakeup_time = d.to_unix();
75
76 // simple sanity check: don't try to wait for something that's already passed
77 const auto now = m_clock->localtime().to_unix();
78 g_return_if_fail (wakeup_time >= now);
79
80 struct timespec sleep_interval;
81 sleep_interval.tv_sec = wakeup_time;
82 sleep_interval.tv_nsec = 0;
83 g_debug("%s %s setting hardware wakeup time to %s (%zu seconds from now)",
84 G_STRLOC, G_STRFUNC,
85 d.format("%F %T").c_str(),
86 (size_t)(wakeup_time - now));
87 u_hardware_alarm_set_relative_to_with_behavior(m_hardware_alarm,
88 U_HARDWARE_ALARM_TIME_REFERENCE_RTC,
89 U_HARDWARE_ALARM_SLEEP_BEHAVIOR_WAKEUP_DEVICE,
90 &sleep_interval);
91 }
92
93 core::Signal<>& timeout() { return m_timeout; }
94
95private:
96
97 void set_wakeup_time_to_the_distant_future()
98 {
99 const auto tomorrow = m_clock->localtime().add_full(0,0,1,0,0,0);
100 set_wakeup_time(tomorrow);
101 }
102
103 static gboolean kick_idle (gpointer gself)
104 {
105 static_cast<Impl*>(gself)->m_timeout();
106
107 return G_SOURCE_REMOVE;
108 }
109
110 void threadfunc()
111 {
112 while (!m_yielding)
113 {
114 // wait for the next hw alarm
115 UHardwareAlarmWaitResult wait_result;
116 g_debug ("calling wait_for_next_alarm");
117 auto rc = u_hardware_alarm_wait_for_next_alarm(m_hardware_alarm, &wait_result);
118 g_return_if_fail (rc == U_STATUS_SUCCESS);
119
120 // set a long wakeup interval for the next iteration of the loop.
121 // if there's another Appointment queued up by the Planner,
122 // our timeout() listener will call set_wakeup_time() to set the
123 // real wakeup interval.
124 set_wakeup_time_to_the_distant_future();
125
126 // delegate the kick back to the main thread
127 g_idle_add (kick_idle, this);
128 }
129 }
130
131 core::Signal<> m_timeout;
132 std::recursive_mutex m_mutex;
133 bool m_yielding = false;
134 const std::shared_ptr<Clock>& m_clock;
135 UHardwareAlarm m_hardware_alarm = nullptr;
136 std::thread m_thread;
137};
138
139/***
140****
141***/
142
143UhaWakeupTimer::UhaWakeupTimer(const std::shared_ptr<Clock>& clock):
144 p(new Impl(clock))
145{
146}
147
148UhaWakeupTimer::~UhaWakeupTimer()
149{
150}
151
152bool UhaWakeupTimer::is_supported()
153{
154 auto hw_alarm = u_hardware_alarm_create();
155 g_debug ("%s hardware alarm %p", G_STRFUNC, hw_alarm);
156 return hw_alarm != nullptr;
157}
158
159void UhaWakeupTimer::set_wakeup_time(const DateTime& d)
160{
161 p->set_wakeup_time(d);
162}
163
164core::Signal<>& UhaWakeupTimer::timeout()
165{
166 return p->timeout();
167}
168
169/***
170****
171***/
172
173} // namespace datetime
174} // namespace indicator
175} // namespace unity
0176
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2014-02-04 19:00:22 +0000
+++ tests/CMakeLists.txt 2014-06-11 04:07:06 +0000
@@ -41,8 +41,8 @@
41 target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS})41 target_link_libraries (${TEST_NAME} indicatordatetimeservice gtest ${SERVICE_DEPS_LIBRARIES} ${GTEST_LIBS})
42endfunction()42endfunction()
43add_test_by_name(test-actions)43add_test_by_name(test-actions)
44add_test_by_name(test-alarm-queue)
44add_test_by_name(test-clock)45add_test_by_name(test-clock)
45add_test_by_name(test-clock-watcher)
46add_test_by_name(test-exporter)46add_test_by_name(test-exporter)
47add_test_by_name(test-formatter)47add_test_by_name(test-formatter)
48add_test_by_name(test-live-actions)48add_test_by_name(test-live-actions)
4949
=== renamed file 'tests/test-clock-watcher.cpp' => 'tests/test-alarm-queue.cpp'
--- tests/test-clock-watcher.cpp 2014-03-10 02:08:47 +0000
+++ tests/test-alarm-queue.cpp 2014-06-11 04:07:06 +0000
@@ -17,7 +17,8 @@
17 * Charles Kerr <charles.kerr@canonical.com>17 * Charles Kerr <charles.kerr@canonical.com>
18 */18 */
1919
20#include <datetime/clock-watcher.h>20#include <datetime/alarm-queue-simple.h>
21#include <datetime/wakeup-timer-mainloop.h>
2122
22#include <gtest/gtest.h>23#include <gtest/gtest.h>
2324
@@ -25,7 +26,7 @@
2526
26using namespace unity::indicator::datetime;27using namespace unity::indicator::datetime;
2728
28class ClockWatcherFixture: public StateFixture29class AlarmQueueFixture: public StateFixture
29{30{
30private:31private:
3132
@@ -34,7 +35,8 @@
34protected:35protected:
3536
36 std::vector<std::string> m_triggered;37 std::vector<std::string> m_triggered;
37 std::unique_ptr<ClockWatcher> m_watcher;38 std::shared_ptr<WakeupTimer> m_wakeup_timer;
39 std::unique_ptr<AlarmQueue> m_watcher;
38 std::shared_ptr<RangePlanner> m_range_planner;40 std::shared_ptr<RangePlanner> m_range_planner;
39 std::shared_ptr<UpcomingPlanner> m_upcoming;41 std::shared_ptr<UpcomingPlanner> m_upcoming;
4042
@@ -42,9 +44,10 @@
42 {44 {
43 super::SetUp();45 super::SetUp();
4446
47 m_wakeup_timer.reset(new MainloopWakeupTimer(m_state->clock));
45 m_range_planner.reset(new MockRangePlanner);48 m_range_planner.reset(new MockRangePlanner);
46 m_upcoming.reset(new UpcomingPlanner(m_range_planner, m_state->clock->localtime()));49 m_upcoming.reset(new UpcomingPlanner(m_range_planner, m_state->clock->localtime()));
47 m_watcher.reset(new ClockWatcherImpl(m_state->clock, m_upcoming));50 m_watcher.reset(new SimpleAlarmQueue(m_state->clock, m_upcoming, m_wakeup_timer));
48 m_watcher->alarm_reached().connect([this](const Appointment& appt){51 m_watcher->alarm_reached().connect([this](const Appointment& appt){
49 m_triggered.push_back(appt.uid);52 m_triggered.push_back(appt.uid);
50 });53 });
@@ -108,7 +111,7 @@
108****111****
109***/112***/
110113
111TEST_F(ClockWatcherFixture, AppointmentsChanged)114TEST_F(AlarmQueueFixture, AppointmentsChanged)
112{115{
113 // Add some appointments to the planner.116 // Add some appointments to the planner.
114 // One of these matches our state's localtime, so that should get triggered.117 // One of these matches our state's localtime, so that should get triggered.
@@ -117,12 +120,12 @@
117 m_range_planner->appointments().set(a);120 m_range_planner->appointments().set(a);
118121
119 // Confirm that it got fired122 // Confirm that it got fired
120 EXPECT_EQ(1, m_triggered.size());123 ASSERT_EQ(1, m_triggered.size());
121 EXPECT_EQ(a[0].uid, m_triggered[0]);124 EXPECT_EQ(a[0].uid, m_triggered[0]);
122}125}
123126
124127
125TEST_F(ClockWatcherFixture, TimeChanged)128TEST_F(AlarmQueueFixture, TimeChanged)
126{129{
127 // Add some appointments to the planner.130 // Add some appointments to the planner.
128 // Neither of these match the state's localtime, so nothing should be triggered.131 // Neither of these match the state's localtime, so nothing should be triggered.
@@ -132,26 +135,27 @@
132135
133 // Set the state's clock to a time that matches one of the appointments().136 // Set the state's clock to a time that matches one of the appointments().
134 // That appointment should get triggered.137 // That appointment should get triggered.
138g_message ("%s setting clock to %s", G_STRLOC, a[1].begin.format("%F %T").c_str());
135 m_mock_state->mock_clock->set_localtime(a[1].begin);139 m_mock_state->mock_clock->set_localtime(a[1].begin);
136 EXPECT_EQ(1, m_triggered.size());140 ASSERT_EQ(1, m_triggered.size());
137 EXPECT_EQ(a[1].uid, m_triggered[0]);141 EXPECT_EQ(a[1].uid, m_triggered[0]);
138}142}
139143
140144
141TEST_F(ClockWatcherFixture, MoreThanOne)145TEST_F(AlarmQueueFixture, MoreThanOne)
142{146{
143 const auto now = m_state->clock->localtime();147 const auto now = m_state->clock->localtime();
144 std::vector<Appointment> a = build_some_appointments();148 std::vector<Appointment> a = build_some_appointments();
145 a[0].begin = a[1].begin = now;149 a[0].begin = a[1].begin = now;
146 m_range_planner->appointments().set(a);150 m_range_planner->appointments().set(a);
147151
148 EXPECT_EQ(2, m_triggered.size());152 ASSERT_EQ(2, m_triggered.size());
149 EXPECT_EQ(a[0].uid, m_triggered[0]);153 EXPECT_EQ(a[0].uid, m_triggered[0]);
150 EXPECT_EQ(a[1].uid, m_triggered[1]);154 EXPECT_EQ(a[1].uid, m_triggered[1]);
151}155}
152156
153157
154TEST_F(ClockWatcherFixture, NoDuplicates)158TEST_F(AlarmQueueFixture, NoDuplicates)
155{159{
156 // Setup: add an appointment that gets triggered.160 // Setup: add an appointment that gets triggered.
157 const auto now = m_state->clock->localtime();161 const auto now = m_state->clock->localtime();
@@ -160,13 +164,13 @@
160 a.push_back(appointments[0]);164 a.push_back(appointments[0]);
161 a[0].begin = now;165 a[0].begin = now;
162 m_range_planner->appointments().set(a);166 m_range_planner->appointments().set(a);
163 EXPECT_EQ(1, m_triggered.size());167 ASSERT_EQ(1, m_triggered.size());
164 EXPECT_EQ(a[0].uid, m_triggered[0]);168 EXPECT_EQ(a[0].uid, m_triggered[0]);
165169
166 // Now change the appointment vector by adding one to it.170 // Now change the appointment vector by adding one to it.
167 // Confirm that the ClockWatcher doesn't re-trigger a[0]171 // Confirm that the AlarmQueue doesn't re-trigger a[0]
168 a.push_back(appointments[1]);172 a.push_back(appointments[1]);
169 m_range_planner->appointments().set(a);173 m_range_planner->appointments().set(a);
170 EXPECT_EQ(1, m_triggered.size());174 ASSERT_EQ(1, m_triggered.size());
171 EXPECT_EQ(a[0].uid, m_triggered[0]);175 EXPECT_EQ(a[0].uid, m_triggered[0]);
172}176}

Subscribers

People subscribed via source and target branches