diff --git a/data/default.json b/data/default.json
index 4be8cec..f1a4c40 100644
--- a/data/default.json
+++ b/data/default.json
@@ -97,10 +97,8 @@
{
"event-name" : "alarm-clock-elapsed",
"type" : "VibraPeriodic",
- "magnitude" : 32767,
- "duration" : 10000,
- "fade-in-time" : 10000,
- "fade-in-level": 4096
+ "magnitude" : 0.5,
+ "duration" : 1000
},
{
"event-name" : "bell-terminal",
@@ -120,9 +118,9 @@
},
{
"event-name" : "message-new-cellbroadcast",
- "type" : "VibraPeriodic",
- "magnitude" : 10000,
- "duration" : 3000
+ "type" : "VibraPattern",
+ "magnitudes" : [1.0, 0.0],
+ "durations" : [200, 200]
},
{
"event-name" : "message-new-email",
@@ -157,7 +155,8 @@
{
"event-name" : "phone-incoming-call",
"type" : "VibraPeriodic",
- "duration" : 10000
+ "magnitude" : 0.5,
+ "duration" : 1000
},
{
"event-name" : "timeout-completed",
@@ -167,8 +166,8 @@
{
"event-name" : "theme-demo",
"type" : "VibraPeriodic",
- "magnitude" : 32767,
- "duration" : 5000
+ "magnitude" : 0.5,
+ "duration" : 1000
},
{
"event-name" : "window-close",
diff --git a/doc/feedbackd.rst b/doc/feedbackd.rst
index d7713d1..5894c65 100644
--- a/doc/feedbackd.rst
+++ b/doc/feedbackd.rst
@@ -30,6 +30,8 @@ app that triggered it crashes.
For details refer to the event and feedback theme specs at
``__
+Feedbackd reloads the feedback theme on `SIGHUP` (i.e. `pkill -HUP feedbackd`).
+
Options
=======
diff --git a/src/fbd-dev-vibra.c b/src/fbd-dev-vibra.c
index 85368a4..f764a6c 100644
--- a/src/fbd-dev-vibra.c
+++ b/src/fbd-dev-vibra.c
@@ -272,33 +272,27 @@ fbd_dev_vibra_rumble (FbdDevVibra *self, double magnitude, guint duration, gbool
/* TODO: fall back to multiple rumbles when sine not supported */
gboolean
-fbd_dev_vibra_periodic (FbdDevVibra *self, guint duration, guint magnitude,
- guint fade_in_level, guint fade_in_time)
+fbd_dev_vibra_periodic (FbdDevVibra *self,
+ guint duration,
+ double magnitude,
+ double fade_in_level,
+ guint fade_in_time)
{
struct input_event event;
struct ff_effect effect = { 0 };
g_return_val_if_fail (FBD_IS_DEV_VIBRA (self), FALSE);
- if (!magnitude)
- magnitude = 0x7FFF;
-
- if (!fade_in_level)
- fade_in_level = magnitude;
-
- if (!fade_in_time)
- fade_in_time = duration;
-
effect.type = FF_PERIODIC;
effect.id = -1;
effect.u.periodic.waveform = FF_SINE;
effect.u.periodic.period = 10;
- effect.u.periodic.magnitude = magnitude;
+ effect.u.periodic.magnitude = 0x7FFF * magnitude;
effect.u.periodic.offset = 0;
effect.u.periodic.phase = 0;
effect.direction = 0x4000;
effect.u.periodic.envelope.attack_length = fade_in_time;
- effect.u.periodic.envelope.attack_level = fade_in_level;;
+ effect.u.periodic.envelope.attack_level = 0x7FFF * fade_in_level;
effect.u.periodic.envelope.fade_length = 0;
effect.u.periodic.envelope.fade_level = 0;
effect.trigger.button = 0;
diff --git a/src/fbd-dev-vibra.h b/src/fbd-dev-vibra.h
index ef5891b..3cf3e3b 100644
--- a/src/fbd-dev-vibra.h
+++ b/src/fbd-dev-vibra.h
@@ -19,8 +19,11 @@ gboolean fbd_dev_vibra_rumble (FbdDevVibra *device,
double magnitude,
guint duration,
gboolean upload);
-gboolean fbd_dev_vibra_periodic (FbdDevVibra *self, guint duration, guint magnitude,
- guint fade_in_level, guint fade_in_time);
+gboolean fbd_dev_vibra_periodic (FbdDevVibra *self,
+ guint duration,
+ double magnitude,
+ double fade_in_level,
+ guint fade_in_time);
gboolean fbd_dev_vibra_stop (FbdDevVibra *self);
gboolean fbd_dev_vibra_remove_effect (FbdDevVibra *self);
GUdevDevice *fbd_dev_vibra_get_device(FbdDevVibra *self);
diff --git a/src/fbd-feedback-vibra-periodic.c b/src/fbd-feedback-vibra-periodic.c
index bb7c69f..f1b81ff 100644
--- a/src/fbd-feedback-vibra-periodic.c
+++ b/src/fbd-feedback-vibra-periodic.c
@@ -11,18 +11,18 @@
#include "fbd-feedback-vibra-periodic.h"
#include "fbd-feedback-manager.h"
+#include
+
/**
- * SECTION:fbd-feedback-vibra-periodic
- * @short_description: Describes a periodic feedback via a haptic motor
- * @Title: FbdFeedbackVibraPeriodic
+ * FbdFeedbackVibraPeriodic:
+ *
+ * Describes a periodic feedback via a haptic motor
*
* The #FbdVibraVibraPeriodic describes the properties of a haptic feedback
* event. It knows nothing about the hardware itself but calls
* #FbdDevVibra for that.
*/
-#define MAX_MAGNITUDE 0xFFFF
-
enum {
PROP_0,
PROP_MAGNITUDE,
@@ -35,27 +35,73 @@ static GParamSpec *props[PROP_LAST_PROP];
typedef struct _FbdFeedbackVibraPeriodic {
FbdFeedbackVibra parent;
- guint magnitude;
- guint fade_in_level;
- guint fade_in_time;
+ double magnitude;
+ double fade_in_level;
+ guint fade_in_time;
} FbdFeedbackVibraPeriodic;
-G_DEFINE_TYPE (FbdFeedbackVibraPeriodic, fbd_feedback_vibra_periodic, FBD_TYPE_FEEDBACK_VIBRA);
+static void json_serializable_iface_init (JsonSerializableIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (FbdFeedbackVibraPeriodic, fbd_feedback_vibra_periodic,
+ FBD_TYPE_FEEDBACK_VIBRA,
+ G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE,
+ json_serializable_iface_init));
+
+static gboolean
+fbd_feedback_vibra_periodic_serializable_deserialize_property (JsonSerializable *serializable,
+ const gchar *property_name,
+ GValue *value,
+ GParamSpec *pspec,
+ JsonNode *property_node)
+{
+ if (g_strcmp0 (property_name, "magnitude") == 0) {
+ if (JSON_NODE_TYPE (property_node) == JSON_NODE_VALUE) {
+ double magnitude = json_node_get_double (property_node);
+
+ /* Backward compat handling: Initially magnitude was given as [0, 0xFFFF] */
+ if (magnitude > 1.0) {
+ g_warning_once ("Too large magnitude %.2f detected, please update the theme", magnitude);
+ magnitude = magnitude / 0xFFFF;
+ }
+
+
+ g_value_set_double (value, magnitude);
+ return TRUE;
+ }
+ } else if (g_strcmp0 (property_name, "fade-in-level") == 0) {
+ if (JSON_NODE_TYPE (property_node) == JSON_NODE_VALUE) {
+ double fade_in_level = json_node_get_double (property_node);
+
+ /* Backward compat handling: Initially duration was given as [0, 0xFFFF] */
+ if (fade_in_level > 1.0) {
+ g_warning_once ("Too large fade-in-level %.2f detected, please update the theme",
+ fade_in_level);
+ fade_in_level = fade_in_level / 0xFFFF;
+ }
+
+ g_value_set_double (value, fade_in_level);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
static void
fbd_feedback_vibra_periodic_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
FbdFeedbackVibraPeriodic *self = FBD_FEEDBACK_VIBRA_PERIODIC (object);
switch (property_id) {
case PROP_MAGNITUDE:
- self->magnitude = g_value_get_uint (value);
+ self->magnitude = g_value_get_double (value);
break;
case PROP_FADE_IN_LEVEL:
- self->fade_in_level = g_value_get_uint (value);
+ self->fade_in_level = g_value_get_double (value);
break;
case PROP_FADE_IN_TIME:
self->fade_in_time = g_value_get_uint (value);
@@ -68,18 +114,18 @@ fbd_feedback_vibra_periodic_set_property (GObject *object,
static void
fbd_feedback_vibra_periodic_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
FbdFeedbackVibraPeriodic *self = FBD_FEEDBACK_VIBRA_PERIODIC (object);
switch (property_id) {
case PROP_MAGNITUDE:
- g_value_set_uint (value, self->magnitude);
+ g_value_set_double (value, self->magnitude);
break;
case PROP_FADE_IN_LEVEL:
- g_value_set_uint (value, self->fade_in_level);
+ g_value_set_double (value, self->fade_in_level);
break;
case PROP_FADE_IN_TIME:
g_value_set_uint (value, self->fade_in_time);
@@ -107,15 +153,15 @@ fbd_feedback_vibra_periodic_start_vibra (FbdFeedbackVibra *vibra)
FbdDevVibra *dev = fbd_feedback_manager_get_dev_vibra (manager);
guint duration = fbd_feedback_vibra_get_duration (vibra);
double max_strength = fbd_feedback_vibra_get_max_strength (FBD_FEEDBACK_VIBRA (self));
- double fade_in_ratio = (double)self->fade_in_level / self->magnitude;
- guint max_magnitude, fade_in_level;
+ double fade_in_ratio = self->fade_in_level / self->magnitude;
+ double max_magnitude, fade_in_level;
g_return_if_fail (FBD_IS_DEV_VIBRA (dev));
- max_magnitude = MIN (MAX_MAGNITUDE * max_strength, self->magnitude);
+ max_magnitude = MIN (max_strength, self->magnitude);
fade_in_level = MIN (max_magnitude * fade_in_ratio, self->fade_in_level);
- g_debug ("Periodic Vibra: %d %d %d %d",
- duration, max_magnitude, fade_in_level, self->fade_in_time);
+ g_debug ("Periodic Vibra: (%f,%d) (%f,%d)",
+ max_magnitude, duration, fade_in_level, self->fade_in_time);
fbd_dev_vibra_periodic (dev, duration, max_magnitude, fade_in_level, self->fade_in_time);
}
@@ -129,6 +175,14 @@ fbd_feedback_vibra_periodic_is_available (FbdFeedbackBase *base)
return FBD_IS_DEV_VIBRA (dev);
}
+
+static void
+json_serializable_iface_init (JsonSerializableIface *iface)
+{
+ iface->deserialize_property = fbd_feedback_vibra_periodic_serializable_deserialize_property;
+}
+
+
static void
fbd_feedback_vibra_periodic_class_init (FbdFeedbackVibraPeriodicClass *klass)
{
@@ -145,28 +199,19 @@ fbd_feedback_vibra_periodic_class_init (FbdFeedbackVibraPeriodicClass *klass)
vibra_class->end_vibra = fbd_feedback_vibra_periodic_end_vibra;
props[PROP_MAGNITUDE] =
- g_param_spec_uint (
- "magnitude",
- "Magnitude",
- "total magnitude",
- 0, MAX_MAGNITUDE, 0x7FFF,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_param_spec_double ("magnitude", "", "",
+ 0.0, 1.0, 0.5,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
props[PROP_FADE_IN_TIME] =
- g_param_spec_uint (
- "fade-in-time",
- "Fade in time",
- "Fade in time until full strength",
- 0, G_MAXINT, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_param_spec_uint ("fade-in-time", "", "",
+ 0, G_MAXINT, 500,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
props[PROP_FADE_IN_LEVEL] =
- g_param_spec_uint (
- "fade-in-level",
- "Fade in level",
- "Fade in start level",
- 0, MAX_MAGNITUDE, 0x7FFF,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_param_spec_double ("fade-in-level", "", "",
+ 0.0, 1.0, 0.0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties (object_class, PROP_LAST_PROP, props);
}
@@ -174,4 +219,7 @@ fbd_feedback_vibra_periodic_class_init (FbdFeedbackVibraPeriodicClass *klass)
static void
fbd_feedback_vibra_periodic_init (FbdFeedbackVibraPeriodic *self)
{
+ self->magnitude = 0.5;
+ self->fade_in_level = 0.0;
+ self->fade_in_time = 500;
}
diff --git a/tests/test-fbd-feedback-vibra.c b/tests/test-fbd-feedback-vibra.c
index 73e4dac..d0c14b8 100644
--- a/tests/test-fbd-feedback-vibra.c
+++ b/tests/test-fbd-feedback-vibra.c
@@ -9,6 +9,7 @@
#define GMOBILE_USE_UNSTABLE_API
#include "fbd-feedback-manager.h"
#include "fbd-feedback-vibra-pattern.h"
+#include "fbd-feedback-vibra-periodic.h"
#include "fbd-feedback-vibra-rumble.h"
#include
@@ -95,6 +96,86 @@ test_fbd_feedback_vibra_pattern (void)
}
+static void
+test_fbd_feedback_vibra_periodic (void)
+{
+ /* Create manager upfront so we can dispose it, otherwise creating
+ * any feedback would create it implicitly */
+ FbdFeedbackManager *manager = fbd_feedback_manager_get_default ();
+ g_autoptr (GError) err = NULL;
+ g_autoptr (JsonNode) node = NULL;
+ GObject *object;
+ double magnitude, fade_in_level;
+ guint fade_in_time;
+
+ node = json_from_string("{"
+ " \"event-name\" : \"button-pressed\","
+ " \"type\" : \"VibraPeriodic\","
+ " \"magnitude\" : 0.7,"
+ " \"fade-in-level\" : 0.3"
+ "}", &err);
+ g_assert_no_error (err);
+
+ object = json_gobject_deserialize (FBD_TYPE_FEEDBACK_VIBRA_PERIODIC, node);
+ g_object_get (object,
+ "magnitude", &magnitude,
+ "fade-in-level", &fade_in_level,
+ "fade-in-time", &fade_in_time,
+ NULL);
+
+ g_assert_cmpfloat_with_epsilon (magnitude, 0.7, FLT_EPSILON);
+ g_assert_cmpfloat_with_epsilon (fade_in_level, 0.3, FLT_EPSILON);
+ g_assert_cmpint (fade_in_time, ==, 500);
+
+ g_assert_finalize_object (object);
+ g_assert_finalize_object (manager);
+}
+
+
+static void
+test_fbd_feedback_vibra_periodic_fallback (void)
+{
+ /* Create manager upfront so we can dispose it, otherwise creating
+ * any feedback would create it implicitly */
+ FbdFeedbackManager *manager = fbd_feedback_manager_get_default ();
+ g_autoptr (GError) err = NULL;
+ g_autoptr (JsonNode) node = NULL;
+ GObject *object;
+ double magnitude, fade_in_level;
+ guint fade_in_time;
+
+ node = json_from_string("{"
+ " \"event-name\" : \"button-pressed\","
+ " \"type\" : \"VibraPeriodic\","
+ " \"magnitude\" : 65535,"
+ " \"fade-in-level\" : 13107"
+ "}", &err);
+ g_assert_no_error (err);
+
+ g_test_expect_message ("fbd-feedback-vibra-periodic",
+ G_LOG_LEVEL_WARNING,
+ "Too large magnitude 65535.00 detected*");
+ g_test_expect_message ("fbd-feedback-vibra-periodic",
+ G_LOG_LEVEL_WARNING,
+ "Too large fade-in-level 13107.00 detected*");
+ object = json_gobject_deserialize (FBD_TYPE_FEEDBACK_VIBRA_PERIODIC, node);
+ g_test_assert_expected_messages ();
+
+ g_object_get (object,
+ "magnitude", &magnitude,
+ "fade-in-level", &fade_in_level,
+ "fade-in-time", &fade_in_time,
+ NULL);
+
+ g_assert_cmpfloat_with_epsilon (magnitude, 1.0, FLT_EPSILON);
+ g_assert_cmpfloat_with_epsilon (fade_in_level, 0.2, FLT_EPSILON);
+ g_assert_cmpint (fade_in_time, ==, 500);
+
+ g_assert_finalize_object (object);
+ g_assert_finalize_object (manager);
+}
+
+
gint
main (gint argc, gchar *argv[])
{
@@ -102,6 +183,9 @@ main (gint argc, gchar *argv[])
g_test_add_func("/feedbackd/fbd/feedback-vibra/rumble", test_fbd_feedback_vibra_rumble);
g_test_add_func("/feedbackd/fbd/feedback-vibra/pattern", test_fbd_feedback_vibra_pattern);
+ g_test_add_func("/feedbackd/fbd/feedback-vibra/periodic", test_fbd_feedback_vibra_periodic);
+ g_test_add_func("/feedbackd/fbd/feedback-vibra/periodic/fallback",
+ test_fbd_feedback_vibra_periodic_fallback);
return g_test_run();
}