~ps-jenkins/indicator-datetime/utopic-proposed

« back to all changes in this revision

Viewing changes to src/awake.cpp

Add haptic feedback support for alarms. Fixes: 1350017
Approved by: Antti Kaijanmäki, PS Jenkins bot, Nekhelesh Ramananthan

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 <notifications/awake.h>
 
21
#include <notifications/dbus-shared.h>
 
22
 
 
23
#include <gio/gio.h>
 
24
 
 
25
#include <limits>
 
26
 
 
27
namespace unity {
 
28
namespace indicator {
 
29
namespace notifications {
 
30
 
 
31
/***
 
32
****
 
33
***/
 
34
 
 
35
class Awake::Impl
 
36
{
 
37
public:
 
38
 
 
39
    Impl(const std::string& app_name):
 
40
        m_app_name(app_name),
 
41
        m_cancellable(g_cancellable_new())
 
42
    {
 
43
        g_bus_get(G_BUS_TYPE_SYSTEM, m_cancellable, on_system_bus_ready, this);
 
44
    }
 
45
 
 
46
    ~Impl()
 
47
    {
 
48
        g_cancellable_cancel (m_cancellable);
 
49
        g_object_unref (m_cancellable);
 
50
 
 
51
        if (m_system_bus != nullptr)
 
52
        {
 
53
            unforce_awake ();
 
54
            unforce_screen ();
 
55
            g_object_unref (m_system_bus);
 
56
        } 
 
57
    }
 
58
 
 
59
private:
 
60
 
 
61
    static void on_system_bus_ready (GObject *,
 
62
                                     GAsyncResult *res,
 
63
                                     gpointer gself)
 
64
    {
 
65
        GError * error;
 
66
        GDBusConnection * system_bus;
 
67
 
 
68
        error = nullptr;
 
69
        system_bus = g_bus_get_finish (res, &error);
 
70
        if (error != nullptr)
 
71
        {
 
72
            if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
 
73
                g_warning ("Unable to get bus: %s", error->message);
 
74
 
 
75
            g_error_free (error);
 
76
        }
 
77
        else if (system_bus != nullptr)
 
78
        {
 
79
            auto self = static_cast<Impl*>(gself);
 
80
 
 
81
            self->m_system_bus = G_DBUS_CONNECTION (g_object_ref (system_bus));
 
82
 
 
83
            // ask powerd to keep the system awake
 
84
            static constexpr int32_t POWERD_SYS_STATE_ACTIVE = 1;
 
85
            g_dbus_connection_call (system_bus,
 
86
                                    BUS_POWERD_NAME,
 
87
                                    BUS_POWERD_PATH,
 
88
                                    BUS_POWERD_INTERFACE,
 
89
                                    "requestSysState",
 
90
                                    g_variant_new("(si)", self->m_app_name.c_str(), POWERD_SYS_STATE_ACTIVE),
 
91
                                    G_VARIANT_TYPE("(s)"),
 
92
                                    G_DBUS_CALL_FLAGS_NONE,
 
93
                                    -1,
 
94
                                    self->m_cancellable,
 
95
                                    on_force_awake_response,
 
96
                                    self);
 
97
 
 
98
            // ask unity-system-compositor to turn on the screen
 
99
            g_dbus_connection_call (system_bus,
 
100
                                    BUS_SCREEN_NAME,
 
101
                                    BUS_SCREEN_PATH,
 
102
                                    BUS_SCREEN_INTERFACE,
 
103
                                    "keepDisplayOn",
 
104
                                    nullptr,
 
105
                                    G_VARIANT_TYPE("(i)"),
 
106
                                    G_DBUS_CALL_FLAGS_NONE,
 
107
                                    -1,
 
108
                                    self->m_cancellable,
 
109
                                    on_force_screen_response,
 
110
                                    self);
 
111
 
 
112
            g_object_unref (system_bus);
 
113
        }
 
114
    }
 
115
 
 
116
    static void on_force_awake_response (GObject      * connection,
 
117
                                         GAsyncResult * res,
 
118
                                         gpointer       gself)
 
119
    {
 
120
        GError * error;
 
121
        GVariant * args;
 
122
 
 
123
        error = nullptr;
 
124
        args = g_dbus_connection_call_finish (G_DBUS_CONNECTION(connection),
 
125
                                              res,
 
126
                                              &error);
 
127
        if (error != nullptr)
 
128
        {
 
129
            if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
 
130
                !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN))
 
131
            {
 
132
                g_warning ("Unable to inhibit sleep: %s", error->message);
 
133
            }
 
134
 
 
135
            g_error_free (error);
 
136
        }
 
137
        else
 
138
        {
 
139
            auto self = static_cast<Impl*>(gself);
 
140
 
 
141
            g_clear_pointer (&self->m_awake_cookie, g_free);
 
142
            g_variant_get (args, "(s)", &self->m_awake_cookie);
 
143
            g_debug ("m_awake_cookie is now '%s'", self->m_awake_cookie);
 
144
 
 
145
            g_variant_unref (args);
 
146
        }
 
147
    }
 
148
 
 
149
    static void on_force_screen_response (GObject      * connection,
 
150
                                          GAsyncResult * res,
 
151
                                          gpointer       gself)
 
152
    {
 
153
        GError * error;
 
154
        GVariant * args;
 
155
 
 
156
        error = nullptr;
 
157
        args = g_dbus_connection_call_finish (G_DBUS_CONNECTION(connection),
 
158
                                              res,
 
159
                                              &error);
 
160
        if (error != nullptr)
 
161
        {
 
162
            if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) &&
 
163
                !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN))
 
164
            {
 
165
                g_warning ("Unable to turn on the screen: %s", error->message);
 
166
            }
 
167
 
 
168
            g_error_free (error);
 
169
        }
 
170
        else
 
171
        {
 
172
            auto self = static_cast<Impl*>(gself);
 
173
 
 
174
            self->m_screen_cookie = NO_SCREEN_COOKIE;
 
175
            g_variant_get (args, "(i)", &self->m_screen_cookie);
 
176
            g_debug ("m_screen_cookie is now '%d'", self->m_screen_cookie);
 
177
 
 
178
            g_variant_unref (args);
 
179
        }
 
180
    }
 
181
 
 
182
    void unforce_awake ()
 
183
    {
 
184
        g_return_if_fail (G_IS_DBUS_CONNECTION(m_system_bus));
 
185
 
 
186
        if (m_awake_cookie != nullptr)
 
187
        {
 
188
            g_dbus_connection_call (m_system_bus,
 
189
                                    BUS_POWERD_NAME,
 
190
                                    BUS_POWERD_PATH,
 
191
                                    BUS_POWERD_INTERFACE,
 
192
                                    "clearSysState",
 
193
                                    g_variant_new("(s)", m_awake_cookie),
 
194
                                    nullptr,
 
195
                                    G_DBUS_CALL_FLAGS_NONE,
 
196
                                    -1,
 
197
                                    nullptr,
 
198
                                    nullptr,
 
199
                                    nullptr);
 
200
 
 
201
            g_clear_pointer (&m_awake_cookie, g_free);
 
202
        }
 
203
    }
 
204
 
 
205
    void unforce_screen ()
 
206
    {
 
207
        g_return_if_fail (G_IS_DBUS_CONNECTION(m_system_bus));
 
208
 
 
209
        if (m_screen_cookie != NO_SCREEN_COOKIE)
 
210
        {
 
211
            g_dbus_connection_call (m_system_bus,
 
212
                                    BUS_SCREEN_NAME,
 
213
                                    BUS_SCREEN_PATH,
 
214
                                    BUS_SCREEN_INTERFACE,
 
215
                                    "removeDisplayOnRequest",
 
216
                                    g_variant_new("(i)", m_screen_cookie),
 
217
                                    nullptr,
 
218
                                    G_DBUS_CALL_FLAGS_NONE,
 
219
                                    -1,
 
220
                                    nullptr,
 
221
                                    nullptr,
 
222
                                    nullptr);
 
223
 
 
224
            m_screen_cookie = NO_SCREEN_COOKIE;
 
225
        }
 
226
    }
 
227
 
 
228
    const std::string m_app_name;
 
229
    GCancellable * m_cancellable = nullptr;
 
230
    GDBusConnection * m_system_bus = nullptr;
 
231
    char * m_awake_cookie = nullptr;
 
232
    int32_t m_screen_cookie = NO_SCREEN_COOKIE;
 
233
 
 
234
    static constexpr int32_t NO_SCREEN_COOKIE { std::numeric_limits<int32_t>::min() };
 
235
};
 
236
 
 
237
/***
 
238
****
 
239
***/
 
240
 
 
241
Awake::Awake(const std::string& app_name):
 
242
    impl(new Impl (app_name))
 
243
{
 
244
}
 
245
 
 
246
Awake::~Awake()
 
247
{
 
248
}
 
249
 
 
250
/***
 
251
****
 
252
***/
 
253
 
 
254
} // namespace datetime
 
255
} // namespace indicator
 
256
} // namespace unity