From 559d185dd7d51e56fbd8246970ef520d3edd18ae Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Wed, 30 Jul 2014 16:01:03 -0500 Subject: initial draft of haptic feedback when alarms play --- include/notifications/haptic.h | 57 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 include/notifications/haptic.h (limited to 'include/notifications/haptic.h') diff --git a/include/notifications/haptic.h b/include/notifications/haptic.h new file mode 100644 index 0000000..3036485 --- /dev/null +++ b/include/notifications/haptic.h @@ -0,0 +1,57 @@ +/* + * 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 + */ + +#ifndef UNITY_INDICATOR_NOTIFICATIONS_HAPTIC_H +#define UNITY_INDICATOR_NOTIFICATIONS_HAPTIC_H + +#include + +namespace unity { +namespace indicator { +namespace notifications { + +/*** +**** +***/ + +/** + * A class that forces the screen display on and inhibits sleep + */ +class Haptic +{ +public: + enum Mode { VIBRATE_DEFAULT }; + + Haptic(const Mode& mode = VIBRATE_DEFAULT); + ~Haptic(); + +private: + class Impl; + std::unique_ptr impl; +}; + +/*** +**** +***/ + +} // namespace notifications +} // namespace indicator +} // namespace unity + +#endif // UNITY_INDICATOR_NOTIFICATIONS_HAPTIC_H -- cgit v1.2.3 From 9d32289feda6d72e53bcf7e77e2cbef09f88165e Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 31 Jul 2014 10:33:14 -0500 Subject: in indicator::noficiations::Haptic, better naming of the Mode enum --- include/notifications/haptic.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'include/notifications/haptic.h') diff --git a/include/notifications/haptic.h b/include/notifications/haptic.h index 3036485..d82d1c9 100644 --- a/include/notifications/haptic.h +++ b/include/notifications/haptic.h @@ -36,9 +36,12 @@ namespace notifications { class Haptic { public: - enum Mode { VIBRATE_DEFAULT }; + enum Mode + { + MODE_PULSE + }; - Haptic(const Mode& mode = VIBRATE_DEFAULT); + Haptic(const Mode& mode = MODE_PULSE); ~Haptic(); private: -- cgit v1.2.3 From d129112ad9ce04fad979af95b5b5cd4fd87f5b2b Mon Sep 17 00:00:00 2001 From: Charles Kerr Date: Thu, 31 Jul 2014 19:52:42 -0500 Subject: in Haptic, make the looping logic easier to read. --- include/notifications/haptic.h | 2 +- src/haptic.cpp | 51 ++++++++++++++++++++++-------------------- 2 files changed, 28 insertions(+), 25 deletions(-) (limited to 'include/notifications/haptic.h') diff --git a/include/notifications/haptic.h b/include/notifications/haptic.h index d82d1c9..bfb5679 100644 --- a/include/notifications/haptic.h +++ b/include/notifications/haptic.h @@ -31,7 +31,7 @@ namespace notifications { ***/ /** - * A class that forces the screen display on and inhibits sleep + * Tries to emit haptic feedback to match the user-specified mode. */ class Haptic { diff --git a/src/haptic.cpp b/src/haptic.cpp index a27c334..54a7d49 100644 --- a/src/haptic.cpp +++ b/src/haptic.cpp @@ -22,6 +22,7 @@ #include +#include #include namespace unity { @@ -88,60 +89,62 @@ private: switch (m_mode) { case MODE_PULSE: // the only mode currently supported... :) + // one second on, one second off. - m_vibrate_pattern_msec = std::vector({1000, 1000}); + m_pattern = std::vector({1000u, 1000u}); break; } - // Set up a loop so that the pattern keeps repeating. - // NB: VibratePattern takes a repeat arg, but we avoid it because - // there's no way to cancel a pattern once it's started... - // The phone would keep vibrating long after the alarm was dismissed! - // So we stick to a short pattern and handle the repeat loop manually. - guint interval_msec = 0; - for (const auto& msec : m_vibrate_pattern_msec) - interval_msec += msec; - m_tag = g_timeout_add (interval_msec, on_timeout, this); - on_timeout (this); + // Set up a loop to keep repeating the pattern + auto msec = std::accumulate(m_pattern.begin(), m_pattern.end(), 0u); + m_tag = g_timeout_add(msec, call_vibrate_pattern_static, this); + call_vibrate_pattern(); } - static gboolean on_timeout (gpointer gself) + static gboolean call_vibrate_pattern_static (gpointer gself) { - auto self = static_cast(gself); + static_cast(gself)->call_vibrate_pattern(); + return G_SOURCE_CONTINUE; + } - // build the pattern array of uint32s + void call_vibrate_pattern() + { + // build the vibrate pattern GVariantBuilder builder; g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY); - for (const auto& msec : self->m_vibrate_pattern_msec) + for (const auto& msec : m_pattern) g_variant_builder_add_value (&builder, g_variant_new_uint32(msec)); auto pattern_array = g_variant_builder_end (&builder); - // build the argument list + /* Use a repeat_count of 1 here because we handle looping ourselves. + NB: VibratePattern could do it for us, but doesn't let us cancel + a running loop -- we could keep vibrating even after "this" was + destructed */ + auto repeat_count = g_variant_new_uint32 (1u); + g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE); g_variant_builder_add_value (&builder, pattern_array); - g_variant_builder_add_value (&builder, g_variant_new_uint32(1u)); - auto args = g_variant_builder_end (&builder); + g_variant_builder_add_value (&builder, repeat_count); + auto vibrate_pattern_args = g_variant_builder_end (&builder); - g_dbus_connection_call (self->m_bus, + g_dbus_connection_call (m_bus, BUS_HAPTIC_NAME, BUS_HAPTIC_PATH, BUS_HAPTIC_INTERFACE, "VibratePattern", - args, + vibrate_pattern_args, nullptr, G_DBUS_CALL_FLAGS_NONE, -1, - self->m_cancellable, + m_cancellable, nullptr, nullptr); - - return G_SOURCE_CONTINUE; } const Mode m_mode; GCancellable * m_cancellable = nullptr; GDBusConnection * m_bus = nullptr; - std::vector m_vibrate_pattern_msec; + std::vector m_pattern; guint m_tag = 0; }; -- cgit v1.2.3