From fcd77b806a8826d5f694f78c63943d0f768ef6ec Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sat, 26 Jul 2014 23:35:38 -0500 Subject: refactor the Notifications / sound / awake code --- src/awake.cpp | 250 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) create mode 100644 src/awake.cpp (limited to 'src/awake.cpp') diff --git a/src/awake.cpp b/src/awake.cpp new file mode 100644 index 0000000..19826ae --- /dev/null +++ b/src/awake.cpp @@ -0,0 +1,250 @@ +/* + * Copyright 2014 Canonical Ltd. + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3, as published + * by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranties of + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see . + * + * Authors: + * Charles Kerr + */ + +#include +#include + +#include + +#include + +namespace unity { +namespace indicator { +namespace notifications { + +/*** +**** +***/ + +class Awake::Impl +{ +public: + + Impl(const std::string& app_name): + m_app_name(app_name), + m_cancellable(g_cancellable_new()) + { + g_bus_get(G_BUS_TYPE_SYSTEM, m_cancellable, on_system_bus_ready, this); + } + + ~Impl() + { + g_cancellable_cancel (m_cancellable); + g_object_unref (m_cancellable); + + if (m_system_bus != nullptr) + { + unforce_awake (); + unforce_screen (); + g_object_unref (m_system_bus); + } + } + +private: + + static void on_system_bus_ready (GObject *, GAsyncResult *res, gpointer gself) + { + GError * error; + GDBusConnection * system_bus; + + error = nullptr; + system_bus = g_bus_get_finish (res, &error); + if (error != nullptr) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) + g_warning ("Unable to get bus: %s", error->message); + + g_error_free (error); + } + else if (system_bus != nullptr) + { + auto self = static_cast(gself); + + self->m_system_bus = G_DBUS_CONNECTION (g_object_ref (system_bus)); + + // ask powerd to keep the system awake + static constexpr int32_t POWERD_SYS_STATE_ACTIVE = 1; + g_dbus_connection_call (system_bus, + BUS_POWERD_NAME, + BUS_POWERD_PATH, + BUS_POWERD_INTERFACE, + "requestSysState", + g_variant_new("(si)", self->m_app_name.c_str(), POWERD_SYS_STATE_ACTIVE), + G_VARIANT_TYPE("(s)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + self->m_cancellable, + on_force_awake_response, + self); + + // ask unity-system-compositor to turn on the screen + g_dbus_connection_call (system_bus, + BUS_SCREEN_NAME, + BUS_SCREEN_PATH, + BUS_SCREEN_INTERFACE, + "keepDisplayOn", + nullptr, + G_VARIANT_TYPE("(i)"), + G_DBUS_CALL_FLAGS_NONE, + -1, + self->m_cancellable, + on_force_screen_response, + self); + + g_object_unref (system_bus); + } + } + + static void on_force_awake_response (GObject * connection, + GAsyncResult * res, + gpointer gself) + { + GError * error; + GVariant * args; + + error = nullptr; + args = g_dbus_connection_call_finish (G_DBUS_CONNECTION(connection), res, &error); + if (error != nullptr) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && + !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) + { + g_warning ("Unable to inhibit sleep: %s", error->message); + } + + g_error_free (error); + } + else + { + auto self = static_cast(gself); + + g_clear_pointer (&self->m_awake_cookie, g_free); + g_variant_get (args, "(s)", &self->m_awake_cookie); + g_debug ("m_awake_cookie is now '%s'", self->m_awake_cookie); + + g_variant_unref (args); + } + } + + static void on_force_screen_response (GObject * connection, + GAsyncResult * res, + gpointer gself) + { + GError * error; + GVariant * args; + + error = nullptr; + args = g_dbus_connection_call_finish (G_DBUS_CONNECTION(connection), res, &error); + if (error != nullptr) + { + if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && + !g_error_matches (error, G_DBUS_ERROR, G_DBUS_ERROR_SERVICE_UNKNOWN)) + { + g_warning ("Unable to turn on the screen: %s", error->message); + } + + g_error_free (error); + } + else + { + auto self = static_cast(gself); + + self->m_screen_cookie = NO_SCREEN_COOKIE; + g_variant_get (args, "(i)", &self->m_screen_cookie); + g_debug ("m_screen_cookie is now '%d'", self->m_screen_cookie); + + g_variant_unref (args); + } + } + + void unforce_awake () + { + g_return_if_fail (G_IS_DBUS_CONNECTION(m_system_bus)); + + if (m_awake_cookie != nullptr) + { + g_dbus_connection_call (m_system_bus, + BUS_POWERD_NAME, + BUS_POWERD_PATH, + BUS_POWERD_INTERFACE, + "clearSysState", + g_variant_new("(s)", m_awake_cookie), + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + nullptr, + nullptr); + + g_clear_pointer (&m_awake_cookie, g_free); + } + } + + void unforce_screen () + { + g_return_if_fail (G_IS_DBUS_CONNECTION(m_system_bus)); + + if (m_screen_cookie != NO_SCREEN_COOKIE) + { + g_dbus_connection_call (m_system_bus, + BUS_SCREEN_NAME, + BUS_SCREEN_PATH, + BUS_SCREEN_INTERFACE, + "removeDisplayOnRequest", + g_variant_new("(i)", m_screen_cookie), + nullptr, + G_DBUS_CALL_FLAGS_NONE, + -1, + nullptr, + nullptr, + nullptr); + + m_screen_cookie = NO_SCREEN_COOKIE; + } + } + + const std::string m_app_name; + GCancellable * m_cancellable = nullptr; + GDBusConnection * m_system_bus = nullptr; + char * m_awake_cookie = nullptr; + int32_t m_screen_cookie = NO_SCREEN_COOKIE; + + static constexpr int32_t NO_SCREEN_COOKIE { std::numeric_limits::min() }; +}; + +/*** +**** +***/ + +Awake::Awake(const std::string& app_name): + impl(new Impl (app_name)) +{ +} + +Awake::~Awake() +{ +} + +/*** +**** +***/ + +} // namespace datetime +} // namespace indicator +} // namespace unity -- cgit v1.2.3 From b0936139bfef6fe169b5c17be4b2dafa3c2e2c3a Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Sun, 27 Jul 2014 11:01:30 -0500 Subject: copyediting: comments, use anonymous namespace --- include/notifications/notifications.h | 5 +++-- src/awake.cpp | 14 ++++++++++---- src/notifications.cpp | 27 +++++++++++++++++---------- src/snap.cpp | 11 ++++++++--- src/sound.cpp | 25 ++++--------------------- 5 files changed, 42 insertions(+), 40 deletions(-) (limited to 'src/awake.cpp') diff --git a/include/notifications/notifications.h b/include/notifications/notifications.h index 43442d3..c2e2d85 100644 --- a/include/notifications/notifications.h +++ b/include/notifications/notifications.h @@ -34,8 +34,7 @@ class Engine; /** * Helper class for showing notifications. * - * Populate the builder, with the relevant properites, - * then pass it to Engine::show(). + * Populate the builder, then pass it to Engine::show(). * * @see Engine::show(Builder) */ @@ -46,7 +45,9 @@ public: ~Builder(); void set_title (const std::string& title); + void set_body (const std::string& body); + void set_icon_name (const std::string& icon_name); /* Set an interval, after which the notification will automatically diff --git a/src/awake.cpp b/src/awake.cpp index 19826ae..57358ab 100644 --- a/src/awake.cpp +++ b/src/awake.cpp @@ -58,7 +58,9 @@ public: private: - static void on_system_bus_ready (GObject *, GAsyncResult *res, gpointer gself) + static void on_system_bus_ready (GObject *, + GAsyncResult *res, + gpointer gself) { GError * error; GDBusConnection * system_bus; @@ -119,7 +121,9 @@ private: GVariant * args; error = nullptr; - args = g_dbus_connection_call_finish (G_DBUS_CONNECTION(connection), res, &error); + args = g_dbus_connection_call_finish (G_DBUS_CONNECTION(connection), + res, + &error); if (error != nullptr) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && @@ -150,7 +154,9 @@ private: GVariant * args; error = nullptr; - args = g_dbus_connection_call_finish (G_DBUS_CONNECTION(connection), res, &error); + args = g_dbus_connection_call_finish (G_DBUS_CONNECTION(connection), + res, + &error); if (error != nullptr) { if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED) && @@ -233,7 +239,7 @@ private: ***/ Awake::Awake(const std::string& app_name): - impl(new Impl (app_name)) + impl(new Impl (app_name)) { } diff --git a/src/notifications.cpp b/src/notifications.cpp index 6d993df..bad4b1a 100644 --- a/src/notifications.cpp +++ b/src/notifications.cpp @@ -168,10 +168,11 @@ public: void close (int key) { - // if we've got this one... auto it = m_notifications.find(key); if (it != m_notifications.end()) { + // tell the server to close, call the close() callback, + // and immediately forget about the nn. GError * error = nullptr; if (!notify_notification_close (it->second.nn.get(), &error)) { @@ -187,9 +188,9 @@ public: int ret = -1; const auto& info = *builder.impl; - auto * nn = notify_notification_new (info.m_title.c_str(), - info.m_body.c_str(), - info.m_icon_name.c_str()); + auto nn = notify_notification_new (info.m_title.c_str(), + info.m_body.c_str(), + info.m_icon_name.c_str()); if (info.m_duration.count() != 0) { @@ -243,7 +244,9 @@ public: } else { - g_critical ("Unable to show notification for '%s': %s", info.m_title.c_str(), error->message); + g_critical ("Unable to show notification for '%s': %s", + info.m_title.c_str(), + error->message); g_error_free (error); g_object_unref (nn); } @@ -266,8 +269,8 @@ private: static void on_notification_closed (NotifyNotification * nn, gpointer gself) { const GQuark q = notification_key_quark(); - const int key = GPOINTER_TO_INT(g_object_get_qdata(G_OBJECT(nn), q)); - static_cast(gself)->on_closed (key); + const gpointer gkey = g_object_get_qdata(G_OBJECT(nn), q); + static_cast(gself)->on_closed(GPOINTER_TO_INT(gkey)); } void on_closed (int key) @@ -281,8 +284,8 @@ private: { std::string action; - const auto q = notification_action_quark(); - const auto p = g_object_get_qdata (G_OBJECT(nn), q); + const GQuark q = notification_action_quark(); + const gpointer p = g_object_get_qdata(G_OBJECT(nn), q); if (p != nullptr) action = static_cast(p); @@ -298,7 +301,11 @@ private: ***/ const std::string m_app_name; + + // key-to-data std::map m_notifications; + + // server capabilities std::set m_caps; static constexpr char const * HINT_TIMEOUT {"x-canonical-snap-decisions-timeout"}; @@ -320,7 +327,7 @@ Engine::~Engine() bool Engine::supports_actions() const { - return impl->supports_actions(); + return true;//impl->supports_actions(); } int diff --git a/src/snap.cpp b/src/snap.cpp index d99e5ef..e9df256 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -39,8 +39,11 @@ namespace datetime { **** ***/ -static std::string get_alarm_uri(const Appointment& appointment, - const std::shared_ptr& settings) +namespace // unnamed namespace +{ + +std::string get_alarm_uri(const Appointment& appointment, + const std::shared_ptr& settings) { const char* FALLBACK {"/usr/share/sounds/ubuntu/ringtones/Suru arpeggio.ogg"}; @@ -72,6 +75,8 @@ static std::string get_alarm_uri(const Appointment& appointment, return uri; } +} // unnamed namespace + /*** **** ***/ @@ -102,7 +107,7 @@ void Snap::operator()(const Appointment& appointment, // force the system to stay awake auto awake = std::make_shared(m_engine->app_name()); - // create the sound..., + // create the sound... const auto uri = get_alarm_uri(appointment, m_settings); const auto volume = m_settings->alarm_volume.get(); const bool loop = m_engine->supports_actions(); diff --git a/src/sound.cpp b/src/sound.cpp index 052b168..7658658 100644 --- a/src/sound.cpp +++ b/src/sound.cpp @@ -63,13 +63,14 @@ public: gst_object_unref(bus); g_debug("Playing '%s'", m_uri.c_str()); - play(); + g_object_set(G_OBJECT (m_play), "uri", m_uri.c_str(), + "volume", get_volume(), + nullptr); + gst_element_set_state (m_play, GST_STATE_PLAYING); } ~Impl() { - stop(); - g_source_remove(m_watch_source); if (m_play != nullptr) @@ -81,24 +82,6 @@ public: private: - void stop() - { - if (m_play != nullptr) - { - gst_element_set_state (m_play, GST_STATE_PAUSED); - } - } - - void play() - { - g_return_if_fail(m_play != nullptr); - - g_object_set(G_OBJECT (m_play), "uri", m_uri.c_str(), - "volume", get_volume(), - nullptr); - gst_element_set_state (m_play, GST_STATE_PLAYING); - } - // convert settings range [1..100] to gst playbin's range is [0...1.0] gdouble get_volume() const { -- cgit v1.2.3