From 7b19feb25f4122eae0d448e36e165dfa38e3e051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Guido=20G=C3=BCnther?= Date: Sat, 1 Mar 2025 21:20:29 +0100 Subject: [PATCH] fbd-feedback-vibra-pattern: Deserialize properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This allows us to use them in feedback themes Signed-off-by: Guido Günther --- src/fbd-feedback-profile.c | 2 + src/fbd-feedback-vibra-pattern.c | 70 +++++++++++++++++++++++++++++++- tests/meson.build | 3 ++ tests/test-fbd-feedback-vibra.c | 66 ++++++++++++++++++++++++++++++ 4 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 tests/test-fbd-feedback-vibra.c diff --git a/src/fbd-feedback-profile.c b/src/fbd-feedback-profile.c index 94cbb36..d1bb605 100644 --- a/src/fbd-feedback-profile.c +++ b/src/fbd-feedback-profile.c @@ -10,6 +10,7 @@ #include "fbd-feedback-profile.h" #include "fbd-feedback-sound.h" #include "fbd-feedback-led.h" +#include "fbd-feedback-vibra-pattern.h" #include "fbd-feedback-vibra-periodic.h" #include "fbd-feedback-vibra-rumble.h" @@ -85,6 +86,7 @@ feedback_get_type (JsonNode *feedback_node) /* Ensure all feedback types so the json parsing can use them */ g_type_ensure (FBD_TYPE_FEEDBACK_DUMMY); g_type_ensure (FBD_TYPE_FEEDBACK_LED); + g_type_ensure (FBD_TYPE_FEEDBACK_VIBRA_PATTERN); g_type_ensure (FBD_TYPE_FEEDBACK_VIBRA_PERIODIC); g_type_ensure (FBD_TYPE_FEEDBACK_VIBRA_RUMBLE); g_type_ensure (FBD_TYPE_FEEDBACK_SOUND); diff --git a/src/fbd-feedback-vibra-pattern.c b/src/fbd-feedback-vibra-pattern.c index 48b5733..4807ede 100644 --- a/src/fbd-feedback-vibra-pattern.c +++ b/src/fbd-feedback-vibra-pattern.c @@ -13,6 +13,8 @@ #include "fbd-feedback-vibra-priv.h" #include "fbd-feedback-manager.h" +#include + /** * FbdFeedbackVibraPattern: * @@ -41,7 +43,68 @@ typedef struct _FbdFeedbackVibraPattern { guint timer_id; } FbdFeedbackVibraPattern; -G_DEFINE_TYPE (FbdFeedbackVibraPattern, fbd_feedback_vibra_pattern, FBD_TYPE_FEEDBACK_VIBRA); +static void json_serializable_iface_init (JsonSerializableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (FbdFeedbackVibraPattern, fbd_feedback_vibra_pattern, + FBD_TYPE_FEEDBACK_VIBRA, + G_IMPLEMENT_INTERFACE (JSON_TYPE_SERIALIZABLE, + json_serializable_iface_init)); + + +static gboolean +fbd_feedback_vibra_pattern_serializable_deserialize_property (JsonSerializable *serializable, + const gchar *property_name, + GValue *value, + GParamSpec *pspec, + JsonNode *property_node) +{ + if (g_strcmp0 (property_name, "magnitudes") == 0) { + if (JSON_NODE_TYPE (property_node) == JSON_NODE_ARRAY) { + JsonArray *array = json_node_get_array (property_node); + guint array_len = json_array_get_length (array); + g_autoptr (GArray) magnitudes = g_array_sized_new (FALSE, FALSE, sizeof (double), array_len); + + for (guint i = 0; i < array_len; i++) { + JsonNode *element_node = json_array_get_element (array, i); + + if (JSON_NODE_HOLDS_VALUE (element_node)) { + double magnitude; + + magnitude = json_node_get_double (element_node); + magnitude = MAX (0.0, MIN (magnitude, 1.0)); + g_array_append_val (magnitudes, magnitude); + } else { + return FALSE; + } + } + g_value_set_boxed (value, magnitudes); + return TRUE; + } + } else if (g_strcmp0 (property_name, "durations") == 0) { + if (JSON_NODE_TYPE (property_node) == JSON_NODE_ARRAY) { + JsonArray *array = json_node_get_array (property_node); + guint array_len = json_array_get_length (array); + g_autoptr (GArray) durations = g_array_sized_new (FALSE, FALSE, sizeof (guint), array_len); + + for (guint i = 0; i < array_len; i++) { + JsonNode *element_node = json_array_get_element (array, i); + + if (JSON_NODE_HOLDS_VALUE (element_node)) { + guint duration; + + duration = json_node_get_int (element_node); + g_array_append_val (durations, duration); + } else { + return FALSE; + } + } + g_value_set_boxed (value, durations); + return TRUE; + } + } + + return FALSE; +} static void @@ -227,6 +290,11 @@ fbd_feedback_vibra_pattern_finalize (GObject *object) G_OBJECT_CLASS (fbd_feedback_vibra_pattern_parent_class)->finalize (object); } +static void +json_serializable_iface_init (JsonSerializableIface *iface) +{ + iface->deserialize_property = fbd_feedback_vibra_pattern_serializable_deserialize_property; +} static void fbd_feedback_vibra_pattern_class_init (FbdFeedbackVibraPatternClass *klass) diff --git a/tests/meson.build b/tests/meson.build index f9d4264..20c9c74 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -14,6 +14,8 @@ if get_option('tests') test_env.set('MALLOC_CHECK_', '2') test_env.set('XDG_CONFIG_HOME', meson.current_source_dir() / 'data' / 'user-config') test_env.set('XDG_CONFIG_DIRS', meson.current_source_dir()) + # Override desktop so we don't depend on GNOME schemas in the tests + test_env.set('XDG_CURRENT_DESKTOP', 'doesnotexist') # Shared library Unit tests @@ -66,6 +68,7 @@ if get_option('tests') fbd_tests = [ 'fbd-feedback-led', 'fbd-feedback-profile', + 'fbd-feedback-vibra', 'fbd-feedback-theme', 'fbd-event', 'fbd-theme-expander', diff --git a/tests/test-fbd-feedback-vibra.c b/tests/test-fbd-feedback-vibra.c new file mode 100644 index 0000000..fca6845 --- /dev/null +++ b/tests/test-fbd-feedback-vibra.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2025 The Phosh Developers + * + * SPDX-License-Identifier: GPL-3.0+ + * + * Author: Guido Günther + */ + +#define GMOBILE_USE_UNSTABLE_API +#include "fbd-feedback-manager.h" +#include "fbd-feedback-vibra-pattern.h" + +#include + + +static void +test_fbd_feedback_vibra_pattern (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; + g_autoptr (GArray) durations = NULL, magnitudes = NULL; + GObject *object; + guint *duration; + double *magnitude; + + node = json_from_string("{" + " \"event-name\" : \"button-pressed\"," + " \"type\" : \"VibraPattern\"," + " \"magnitudes\" : [ 0.2, 1.0 ]," + " \"durations\" : [ 7, 3 ]" + "}", &err); + g_assert_no_error (err); + + object = json_gobject_deserialize (FBD_TYPE_FEEDBACK_VIBRA_PATTERN, node); + g_object_get (object, "durations", &durations, "magnitudes", &magnitudes, NULL); + + g_assert_nonnull(durations); + g_assert_nonnull(magnitudes); + + duration = &g_array_index (durations, guint, 0); + g_assert_cmpint (*duration, ==, 7); + duration = &g_array_index (durations, guint, 1); + g_assert_cmpint (*duration, ==, 3); + + magnitude = &g_array_index (magnitudes, double, 0); + g_assert_cmpfloat (*magnitude, ==, 0.2); + magnitude = &g_array_index (magnitudes, double, 1); + g_assert_cmpfloat (*magnitude, ==, 1.0); + + g_assert_finalize_object (object); + g_assert_finalize_object (manager); +} + + +gint +main (gint argc, gchar *argv[]) +{ + g_test_init (&argc, &argv, NULL); + + g_test_add_func("/feedbackd/fbd/feedback-vibra/pattern", test_fbd_feedback_vibra_pattern); + + return g_test_run(); +}