Merge lp:~vicamo/qtubuntu-sensors/reimplement-haptics-backend into lp:qtubuntu-sensors

Proposed by You-Sheng Yang
Status: Merged
Merged at revision: 93
Proposed branch: lp:~vicamo/qtubuntu-sensors/reimplement-haptics-backend
Merge into: lp:qtubuntu-sensors
Diff against target: 248 lines (+93/-46)
3 files modified
plugins/feedback/CMakeLists.txt (+3/-5)
plugins/feedback/core_feedback.cpp (+84/-38)
plugins/feedback/core_feedback.h (+6/-3)
To merge this branch: bzr merge lp:~vicamo/qtubuntu-sensors/reimplement-haptics-backend
Reviewer Review Type Date Requested Status
Thomas Voß Pending
Review via email: mp+300839@code.launchpad.net

Commit message

This change rewrites QtFeedbackHapticsEffect backend for ubuntu.

The original implementation is to call APIs in libubuntu-platform-api, which then issue D-Bus calls to usensord. However, it seems in some cases instantiating a D-Bus call in such Qt module may result in segmentation fault. This change rewrites QtFeedbackHapticsEffect backend with QtDBus directly and works around this issue.

This change also tries to conform to QtFeedbackHaptics features definitions. Duration/period is now correctly supported, although this doesn't mean much because usensord does not support variable vibration intensity. It also provides a chance to stop a periodical vibration. The enable/state properties are now correctly set and returned.

Description of the change

This change rewrites QtFeedbackHapticsEffect backend for ubuntu.

The original implementation is to call APIs in libubuntu-platform-api, which then issue D-Bus calls to usensord. However, it seems in some cases instantiating a D-Bus call in such Qt module may result in segmentation fault. This change rewrites QtFeedbackHapticsEffect backend with QtDBus directly and works around this issue.

This change also tries to conform to QtFeedbackHaptics features definitions. Duration/period is now correctly supported, although this doesn't mean much because usensord does not support variable vibration intensity. It also provides a chance to stop a periodical vibration. The enable/state properties are now correctly set and returned.

To post a comment you must log in.
Revision history for this message
You-Sheng Yang (vicamo) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'plugins/feedback/CMakeLists.txt'
--- plugins/feedback/CMakeLists.txt 2014-06-24 12:17:06 +0000
+++ plugins/feedback/CMakeLists.txt 2016-07-22 06:49:35 +0000
@@ -1,9 +1,8 @@
1find_package(PkgConfig)1find_package(PkgConfig)
2find_package(Qt5Core REQUIRED)2find_package(Qt5Core REQUIRED)
3find_package(Qt5DBus REQUIRED)
3find_package(Qt5Feedback REQUIRED)4find_package(Qt5Feedback REQUIRED)
45
5pkg_check_modules(UBUNTU_PLATFORM_API ubuntu-platform-api REQUIRED)
6
7qt5_add_resources(FEEDBACK_RESOURCES feedback.qrc)6qt5_add_resources(FEEDBACK_RESOURCES feedback.qrc)
87
9add_library(8add_library(
@@ -22,7 +21,7 @@
2221
23message(STATUS "Installing Qt5 feedback plugin to: ${PLUGIN_INSTALL_LOCATION}")22message(STATUS "Installing Qt5 feedback plugin to: ${PLUGIN_INSTALL_LOCATION}")
2423
25qt5_use_modules(qtfeedback_ubuntu Core Feedback)24qt5_use_modules(qtfeedback_ubuntu Core DBus Feedback)
2625
27target_link_libraries(26target_link_libraries(
28 qtfeedback_ubuntu27 qtfeedback_ubuntu
@@ -30,9 +29,8 @@
30 ${CMAKE_THREAD_LIBS_INIT}29 ${CMAKE_THREAD_LIBS_INIT}
3130
32 Qt5::Core31 Qt5::Core
32 Qt5::DBus
33 Qt5::Feedback33 Qt5::Feedback
34
35 ${UBUNTU_PLATFORM_API_LIBRARIES}
36)34)
3735
38install(36install(
3937
=== modified file 'plugins/feedback/core_feedback.cpp'
--- plugins/feedback/core_feedback.cpp 2015-09-29 12:53:18 +0000
+++ plugins/feedback/core_feedback.cpp 2016-07-22 06:49:35 +0000
@@ -29,24 +29,20 @@
29#include <QtCore/QTimer>29#include <QtCore/QTimer>
30#include <QtCore/QProcess>30#include <QtCore/QProcess>
31#include <QtCore/QFileInfo>31#include <QtCore/QFileInfo>
32#include <QDBusInterface>
33#include <QDBusPendingCall>
34#include <QDBusPendingCallWatcher>
35#include <QDBusPendingReply>
3236
33core::Feedback::Feedback() : QObject(),37core::Feedback::Feedback() : QObject(),
34 m_vibrator(NULL)38 enabled(false),
39 state(QFeedbackEffect::Stopped)
35{40{
36 actuatorList << createFeedbackActuator(this, 42);41 actuatorList << createFeedbackActuator(this, 42);
37
38 if (qgetenv("UBUNTU_PLATFORM_API_BACKEND").isNull())
39 return;
40
41 m_vibrator = ua_sensors_haptic_new();
42 ua_sensors_haptic_enable(m_vibrator);
43}42}
4443
45core::Feedback::~Feedback()44core::Feedback::~Feedback()
46{45{
47 if (m_vibrator) {
48 ua_sensors_haptic_destroy(m_vibrator);
49 }
50}46}
5147
52QFeedbackInterface::PluginPriority core::Feedback::pluginPriority()48QFeedbackInterface::PluginPriority core::Feedback::pluginPriority()
@@ -59,11 +55,12 @@
59 return actuatorList;55 return actuatorList;
60}56}
6157
62void core::Feedback::setActuatorProperty(const QFeedbackActuator&, ActuatorProperty prop, const QVariant &)58void core::Feedback::setActuatorProperty(const QFeedbackActuator&, ActuatorProperty prop, const QVariant &value)
63{59{
64 switch (prop)60 switch (prop)
65 {61 {
66 case Enabled:62 case Enabled:
63 enabled = value.toBool();
67 break;64 break;
68 default:65 default:
69 break;66 break;
@@ -78,7 +75,7 @@
78 {75 {
79 case Name: result = QString::fromLocal8Bit("Ubuntu Vibrator"); break;76 case Name: result = QString::fromLocal8Bit("Ubuntu Vibrator"); break;
80 case State: result = actuator.isValid() ? QFeedbackActuator::Ready : QFeedbackActuator::Unknown; break;77 case State: result = actuator.isValid() ? QFeedbackActuator::Ready : QFeedbackActuator::Unknown; break;
81 case Enabled: result = true; break;78 case Enabled: result = enabled; break;
82 }79 }
8380
84 return result;81 return result;
@@ -90,37 +87,88 @@
9087
91 switch(cap)88 switch(cap)
92 {89 {
93 case QFeedbackActuator::Envelope:90 case QFeedbackActuator::Envelope: result = true; break;
94 case QFeedbackActuator::Period: result = true; break;91 case QFeedbackActuator::Period: result = false; break;
95 }92 }
9693
97 return result;94 return result;
98}95}
9996
100void core::Feedback::updateEffectProperty(const QFeedbackHapticsEffect *effect, EffectProperty)97void core::Feedback::updateEffectProperty(const QFeedbackHapticsEffect *, EffectProperty)
101{98{
102 if (effect->period() != -1) {99}
103 /* Not currently supported */100
104 reportError(effect, QFeedbackEffect::UnknownError);101void core::Feedback::hapticsVibrateReply(QDBusPendingCallWatcher *watcher, int period, int repeat)
105 }102{
106}103 QDBusPendingReply<> reply = *watcher;
107104 if (reply.isError()) {
108void core::Feedback::vibrateOnce(const QFeedbackEffect* effect)105 qWarning() << "Failed to vibrate with pattern:" << reply.error().message();
109{106 state = QFeedbackEffect::Stopped;
110 int effectiveDuration = effect->duration();107 } else {
111 switch (effectiveDuration)108 if ((repeat == QFeedbackEffect::Infinite) || (--repeat > 0))
112 {109 QTimer::singleShot(period, [=]() { vibrate(period, repeat); });
113 case QFeedbackEffect::Infinite:110 else
114 case 0:111 state = QFeedbackEffect::Stopped;
115 effectiveDuration = 150;112 }
116 }113
117114 watcher->deleteLater();
118 if (m_vibrator)115}
119 ua_sensors_haptic_vibrate_once(m_vibrator, effectiveDuration);116
117void core::Feedback::vibrate(int period, int repeat)
118{
119 if (!(period && repeat))
120 state = QFeedbackEffect::Stopped;
121
122 if (state != QFeedbackEffect::Running) {
123 // Maybe stopped/paused before this async call.
124 return;
125 }
126
127
128 QDBusInterface iface("com.canonical.usensord",
129 "/com/canonical/usensord/haptic",
130 "com.canonical.usensord.haptic");
131
132 QDBusPendingCall call = iface.asyncCall("Vibrate", (uint)period);
133 QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
134 connect(watcher, &QDBusPendingCallWatcher::finished,
135 [=](){ hapticsVibrateReply(watcher, period, repeat); });
136}
137
138void core::Feedback::startVibration(const QFeedbackHapticsEffect *effect)
139{
140 int duration = effect->duration();
141 if (duration == 0)
142 duration = 150;
143
144 int period = effect->period();
145 int repeat;
146 if ((duration == QFeedbackEffect::Infinite) || (duration < 0)) {
147 // If duration is set to QFeedbackEffect::Infinite or a negative
148 // value, we repeat this effect forever until stopped. The
149 // effective period should have been set to a positive value or
150 // 150ms by default.
151 duration = QFeedbackEffect::Infinite;
152 repeat = QFeedbackEffect::Infinite;
153 if (period <= 0)
154 period = 150;
155 } else if (period <= 0) {
156 // If duration is set to a positive value and period is invalid,
157 // then use duration as period.
158 repeat = 1;
159 period = duration;
160 } else {
161 // Otherwise, repeat this effect as many times as the duration
162 // may cover the effect period.
163 repeat = (duration + period - 1) / period;
164 }
165
166 vibrate(period, repeat);
120}167}
121168
122void core::Feedback::setEffectState(const QFeedbackHapticsEffect *effect, QFeedbackEffect::State state)169void core::Feedback::setEffectState(const QFeedbackHapticsEffect *effect, QFeedbackEffect::State state)
123{170{
171 this->state = state;
124 switch (state)172 switch (state)
125 {173 {
126 case QFeedbackEffect::Stopped:174 case QFeedbackEffect::Stopped:
@@ -128,7 +176,7 @@
128 case QFeedbackEffect::Paused:176 case QFeedbackEffect::Paused:
129 break;177 break;
130 case QFeedbackEffect::Running:178 case QFeedbackEffect::Running:
131 vibrateOnce(effect);179 QTimer::singleShot(0, [=]() { startVibration(effect); });
132 break;180 break;
133 case QFeedbackEffect::Loading:181 case QFeedbackEffect::Loading:
134 break;182 break;
@@ -137,7 +185,5 @@
137185
138QFeedbackEffect::State core::Feedback::effectState(const QFeedbackHapticsEffect *)186QFeedbackEffect::State core::Feedback::effectState(const QFeedbackHapticsEffect *)
139{187{
140 // We don't currently support on-going vibrations188 return state;
141 // This can be added when moving to a vibration service
142 return QFeedbackEffect::Stopped;
143}189}
144190
=== modified file 'plugins/feedback/core_feedback.h'
--- plugins/feedback/core_feedback.h 2015-09-29 12:53:18 +0000
+++ plugins/feedback/core_feedback.h 2016-07-22 06:49:35 +0000
@@ -24,7 +24,7 @@
2424
25#include <qfeedbackplugininterfaces.h>25#include <qfeedbackplugininterfaces.h>
2626
27#include <ubuntu/application/sensors/haptic.h>27class QDBusPendingCallWatcher;
2828
29namespace core29namespace core
30{30{
@@ -56,9 +56,12 @@
56private:56private:
57 QList<QFeedbackActuator*> actuatorList;57 QList<QFeedbackActuator*> actuatorList;
5858
59 void vibrateOnce(const QFeedbackEffect* effect);59 void hapticsVibrateReply(QDBusPendingCallWatcher *watcher, int period, int repeat);
60 void vibrate(int period, int repeat);
61 void startVibration(const QFeedbackHapticsEffect *effect);
6062
61 UASensorsHaptic* m_vibrator;63 bool enabled;
64 QFeedbackEffect::State state;
62};65};
63}66}
6467

Subscribers

People subscribed via source and target branches