~indicator-applet-developers/indicator-datetime/trunk.15.04

340.3.2 by Charles Kerr
hw alarms
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
340.4.4 by Charles Kerr
in wakeup-timer-mainloop, don't just cast to uint without checking sign. (h/t ted)
24
#include <cstdlib> // abs()
25
340.3.2 by Charles Kerr
hw alarms
26
namespace unity {
27
namespace indicator {
28
namespace datetime {
29
30
/***
31
****
32
***/
33
34
class MainloopWakeupTimer::Impl
35
{
36
37
public:
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
58
private:
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());
340.4.4 by Charles Kerr
in wakeup-timer-mainloop, don't just cast to uint without checking sign. (h/t ted)
68
        const guint interval_msec = std::abs(difference_usec) / 1000u;
340.4.1 by Charles Kerr
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.
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});
340.3.2 by Charles Kerr
hw alarms
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
    {
340.4.1 by Charles Kerr
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.
83
        g_debug("%s %s", G_STRLOC, G_STRFUNC);
340.3.2 by Charles Kerr
hw alarms
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
113
MainloopWakeupTimer::MainloopWakeupTimer(const std::shared_ptr<Clock>& clock):
114
    p(new Impl(clock))
115
{
116
}
117
118
MainloopWakeupTimer::~MainloopWakeupTimer()
119
{
120
}
121
122
void MainloopWakeupTimer::set_wakeup_time(const DateTime& d)
123
{
124
    p->set_wakeup_time(d);
125
}
126
127
core::Signal<>& MainloopWakeupTimer::timeout()
128
{
129
    return p->timeout();
130
}
131
132
/***
133
****
134
***/
135
136
} // namespace datetime
137
} // namespace indicator
138
} // namespace unity