mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-01-06 18:30:10 +01:00
lib: add WpSpaProps, a helper to deal with SPA_PARAM_Props & SPA_PARAM_PropInfo
This commit is contained in:
parent
44e498ca01
commit
ce3883c1a2
5 changed files with 615 additions and 0 deletions
|
|
@ -14,6 +14,7 @@ wp_lib_sources = [
|
|||
'proxy-link.c',
|
||||
'proxy-node.c',
|
||||
'proxy-port.c',
|
||||
'spa-props.c',
|
||||
]
|
||||
|
||||
wp_lib_headers = [
|
||||
|
|
|
|||
|
|
@ -93,6 +93,64 @@ void wp_proxy_augment_error (WpProxy * self, GError * error);
|
|||
void wp_proxy_register_async_task (WpProxy * self, int seq, GTask * task);
|
||||
GTask * wp_proxy_find_async_task (WpProxy * self, int seq, gboolean steal);
|
||||
|
||||
/* spa props */
|
||||
|
||||
struct spa_pod;
|
||||
struct spa_pod_builder;
|
||||
|
||||
typedef struct _WpSpaProps WpSpaProps;
|
||||
struct _WpSpaProps
|
||||
{
|
||||
GList *entries;
|
||||
};
|
||||
|
||||
void wp_spa_props_clear (WpSpaProps * self);
|
||||
|
||||
void wp_spa_props_register_pod (WpSpaProps * self,
|
||||
guint32 id, const gchar *name, const struct spa_pod *type);
|
||||
gint wp_spa_props_register_from_prop_info (WpSpaProps * self,
|
||||
const struct spa_pod * prop_info);
|
||||
|
||||
const struct spa_pod * wp_spa_props_get_stored (WpSpaProps * self, guint32 id);
|
||||
|
||||
gint wp_spa_props_store_pod (WpSpaProps * self, guint32 id,
|
||||
const struct spa_pod * value);
|
||||
gint wp_spa_props_store_from_props (WpSpaProps * self,
|
||||
const struct spa_pod * props, GArray * changed_ids);
|
||||
|
||||
GPtrArray * wp_spa_props_build_all_pods (WpSpaProps * self,
|
||||
struct spa_pod_builder * b);
|
||||
struct spa_pod * wp_spa_props_build_update (WpSpaProps * self, guint32 id,
|
||||
const struct spa_pod * value, struct spa_pod_builder * b);
|
||||
|
||||
const struct spa_pod * wp_spa_props_build_pod_valist (gchar * buffer,
|
||||
gsize size, va_list args);
|
||||
|
||||
static inline const struct spa_pod *
|
||||
wp_spa_props_build_pod (gchar * buffer, gsize size, ...)
|
||||
{
|
||||
const struct spa_pod *ret;
|
||||
va_list args;
|
||||
va_start (args, size);
|
||||
ret = wp_spa_props_build_pod_valist (buffer, size, args);
|
||||
va_end (args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define wp_spa_props_register(self, id, name, ...) \
|
||||
({ \
|
||||
gchar b[512]; \
|
||||
wp_spa_props_register_pod (self, id, name, \
|
||||
wp_spa_props_build_pod (b, sizeof (b), ##__VA_ARGS__, NULL)); \
|
||||
})
|
||||
|
||||
#define wp_spa_props_store(self, id, ...) \
|
||||
({ \
|
||||
gchar b[512]; \
|
||||
wp_spa_props_store_pod (self, id, \
|
||||
wp_spa_props_build_pod (b, sizeof (b), ##__VA_ARGS__, NULL)); \
|
||||
})
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif
|
||||
|
|
|
|||
286
lib/wp/spa-props.c
Normal file
286
lib/wp/spa-props.c
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include "private.h"
|
||||
#include <spa/pod/pod.h>
|
||||
#include <spa/pod/builder.h>
|
||||
#include <spa/pod/parser.h>
|
||||
#include <spa/param/props.h>
|
||||
#include <spa/utils/defs.h>
|
||||
#include <spa/utils/result.h>
|
||||
|
||||
struct entry
|
||||
{
|
||||
guint32 id;
|
||||
gchar *name;
|
||||
struct spa_pod *type;
|
||||
struct spa_pod *value;
|
||||
};
|
||||
|
||||
struct entry *
|
||||
entry_new (void)
|
||||
{
|
||||
struct entry *e = g_slice_new0 (struct entry);
|
||||
return e;
|
||||
}
|
||||
|
||||
static void
|
||||
entry_free (struct entry *e)
|
||||
{
|
||||
g_free (e->name);
|
||||
free (e->type);
|
||||
free (e->value);
|
||||
g_slice_free (struct entry, e);
|
||||
}
|
||||
|
||||
void
|
||||
wp_spa_props_clear (WpSpaProps * self)
|
||||
{
|
||||
g_list_free_full (self->entries, (GDestroyNotify) entry_free);
|
||||
self->entries = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
wp_spa_props_register_pod (WpSpaProps * self,
|
||||
guint32 id, const gchar *name, const struct spa_pod *type)
|
||||
{
|
||||
struct entry *e = entry_new ();
|
||||
e->id = id;
|
||||
e->name = g_strdup (name);
|
||||
e->type = spa_pod_copy (type);
|
||||
|
||||
if (!spa_pod_is_choice (type))
|
||||
e->value = spa_pod_copy (type);
|
||||
else
|
||||
e->value = spa_pod_copy (SPA_POD_CHOICE_CHILD (type));
|
||||
|
||||
self->entries = g_list_append (self->entries, e);
|
||||
}
|
||||
|
||||
gint
|
||||
wp_spa_props_register_from_prop_info (WpSpaProps * self,
|
||||
const struct spa_pod * prop_info)
|
||||
{
|
||||
guint32 id;
|
||||
gchar *name;
|
||||
const struct spa_pod *type;
|
||||
int res;
|
||||
|
||||
res = spa_pod_parse_object (prop_info,
|
||||
SPA_TYPE_OBJECT_PropInfo, NULL,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id (&id),
|
||||
SPA_PROP_INFO_name, SPA_POD_String (&name),
|
||||
SPA_PROP_INFO_type, SPA_POD_Pod (&type));
|
||||
|
||||
if (res < 0) {
|
||||
g_debug ("Bad prop info object");
|
||||
return res;
|
||||
}
|
||||
|
||||
wp_spa_props_register_pod (self, id, name, type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// get <-- cached
|
||||
const struct spa_pod *
|
||||
wp_spa_props_get_stored (WpSpaProps * self, guint32 id)
|
||||
{
|
||||
GList *l = self->entries;
|
||||
while (l && ((struct entry *) l->data)->id != id)
|
||||
l = g_list_next (l);
|
||||
|
||||
return l ? ((struct entry *) l->data)->value : NULL;
|
||||
}
|
||||
|
||||
// exported set --> cache + update(variant to pod -> push)
|
||||
gint
|
||||
wp_spa_props_store_pod (WpSpaProps * self, guint32 id,
|
||||
const struct spa_pod * value)
|
||||
{
|
||||
GList *l = self->entries;
|
||||
struct entry * e;
|
||||
uint32_t expected_type;
|
||||
|
||||
while (l && ((struct entry *) l->data)->id != id)
|
||||
l = g_list_next (l);
|
||||
|
||||
if (!l)
|
||||
return -ESRCH;
|
||||
|
||||
e = (struct entry *) l->data;
|
||||
|
||||
expected_type = spa_pod_is_choice (e->type) ?
|
||||
SPA_POD_CHOICE_VALUE_TYPE (e->type) : SPA_POD_TYPE (e->type);
|
||||
if (SPA_POD_TYPE (value) != expected_type)
|
||||
return -EINVAL;
|
||||
|
||||
#define GET_VAL(pod, type) ((struct spa_pod_##type *) pod)->value
|
||||
|
||||
switch (SPA_POD_TYPE (value)) {
|
||||
//TODO bounds checking on integer types
|
||||
case SPA_TYPE_Id:
|
||||
if (GET_VAL (e->value, id) != GET_VAL (value, id)) {
|
||||
GET_VAL (e->value, id) = GET_VAL (value, id);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SPA_TYPE_Bool:
|
||||
if (GET_VAL (e->value, bool) != GET_VAL (value, bool)) {
|
||||
GET_VAL (e->value, bool) = GET_VAL (value, bool);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SPA_TYPE_Int:
|
||||
if (GET_VAL (e->value, int) != GET_VAL (value, int)) {
|
||||
GET_VAL (e->value, int) = GET_VAL (value, int);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SPA_TYPE_Long:
|
||||
if (GET_VAL (e->value, long) != GET_VAL (value, long)) {
|
||||
GET_VAL (e->value, long) = GET_VAL (value, long);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SPA_TYPE_Fd:
|
||||
if (GET_VAL (e->value, fd) != GET_VAL (value, fd)) {
|
||||
GET_VAL (e->value, fd) = GET_VAL (value, fd);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SPA_TYPE_Float:
|
||||
if (GET_VAL (e->value, float) != GET_VAL (value, float)) {
|
||||
GET_VAL (e->value, float) = GET_VAL (value, float);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SPA_TYPE_Double:
|
||||
if (GET_VAL (e->value, double) != GET_VAL (value, double)) {
|
||||
GET_VAL (e->value, double) = GET_VAL (value, double);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SPA_TYPE_Rectangle:
|
||||
if (GET_VAL (e->value, rectangle).width != GET_VAL (value, rectangle).width ||
|
||||
GET_VAL (e->value, rectangle).height != GET_VAL (value, rectangle).height) {
|
||||
GET_VAL (e->value, rectangle) = GET_VAL (value, rectangle);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case SPA_TYPE_Fraction:
|
||||
if (GET_VAL (e->value, fraction).num != GET_VAL (value, fraction).num ||
|
||||
GET_VAL (e->value, fraction).denom != GET_VAL (value, fraction).denom) {
|
||||
GET_VAL (e->value, fraction) = GET_VAL (value, fraction);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_clear_pointer (&e->value, free);
|
||||
e->value = spa_pod_copy (value);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#undef GET_VAL
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// exported event set --> pod to variant -> cache
|
||||
// proxy event param --> pod to variant -> cache
|
||||
gint
|
||||
wp_spa_props_store_from_props (WpSpaProps * self, const struct spa_pod * props,
|
||||
GArray * changed_ids)
|
||||
{
|
||||
const struct spa_pod_object *obj;
|
||||
const struct spa_pod_prop *iter;
|
||||
gint ret, count = 0;
|
||||
|
||||
g_return_val_if_fail (!changed_ids ||
|
||||
g_array_get_element_size (changed_ids) == sizeof (uint32_t), -EINVAL);
|
||||
|
||||
if (!spa_pod_is_object_type (props, SPA_TYPE_OBJECT_Props))
|
||||
return -EINVAL;
|
||||
|
||||
obj = (const struct spa_pod_object *) props;
|
||||
iter = spa_pod_prop_first (&obj->body);
|
||||
|
||||
for (iter = spa_pod_prop_first (&obj->body);
|
||||
spa_pod_prop_is_inside (&obj->body, obj->pod.size, iter);
|
||||
iter = spa_pod_prop_next (iter)) {
|
||||
if ((ret = wp_spa_props_store_pod (self, iter->key, &iter->value)) < 0) {
|
||||
g_debug ("error storing property 0x%x: %s", iter->key,
|
||||
spa_strerror (ret));
|
||||
} else if (ret == 1 && changed_ids) {
|
||||
g_array_append_val (changed_ids, iter->key);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
// for exported update / prop_info + props
|
||||
GPtrArray *
|
||||
wp_spa_props_build_all_pods (WpSpaProps * self, struct spa_pod_builder * b)
|
||||
{
|
||||
GPtrArray *res = g_ptr_array_new ();
|
||||
GList *l;
|
||||
struct spa_pod_frame f;
|
||||
struct spa_pod *pod;
|
||||
|
||||
/* Props */
|
||||
spa_pod_builder_push_object (b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
|
||||
for (l = self->entries; l != NULL; l = g_list_next (l)) {
|
||||
struct entry * e = (struct entry *) l->data;
|
||||
if (e->value) {
|
||||
spa_pod_builder_prop (b, e->id, 0);
|
||||
spa_pod_builder_primitive (b, e->value);
|
||||
}
|
||||
}
|
||||
pod = spa_pod_builder_pop (b, &f);
|
||||
g_ptr_array_add (res, pod);
|
||||
|
||||
/* PropInfo */
|
||||
for (l = self->entries; l != NULL; l = g_list_next (l)) {
|
||||
struct entry * e = (struct entry *) l->data;
|
||||
pod = spa_pod_builder_add_object (b,
|
||||
SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id (e->id),
|
||||
SPA_PROP_INFO_name, SPA_POD_String (e->name),
|
||||
SPA_PROP_INFO_type, SPA_POD_Pod (e->type));
|
||||
g_ptr_array_add (res, pod);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// proxy set --> value to props object -> push
|
||||
struct spa_pod *
|
||||
wp_spa_props_build_update (WpSpaProps * self, guint32 id,
|
||||
const struct spa_pod * value, struct spa_pod_builder * b)
|
||||
{
|
||||
struct spa_pod_frame f;
|
||||
|
||||
spa_pod_builder_push_object (b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props);
|
||||
spa_pod_builder_prop (b, id, 0);
|
||||
spa_pod_builder_primitive (b, value);
|
||||
return spa_pod_builder_pop (b, &f);
|
||||
}
|
||||
|
||||
const struct spa_pod *
|
||||
wp_spa_props_build_pod_valist (gchar * buffer, gsize size, va_list args)
|
||||
{
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, size);
|
||||
struct spa_pod_frame f;
|
||||
void *pod;
|
||||
|
||||
spa_pod_builder_push_struct (&b, &f);
|
||||
spa_pod_builder_addv (&b, args);
|
||||
pod = spa_pod_builder_pop (&b, &f);
|
||||
return SPA_POD_CONTENTS (struct spa_pod_struct, pod);
|
||||
}
|
||||
|
|
@ -15,3 +15,9 @@ test(
|
|||
executable('test-proxy', 'proxy.c', dependencies: common_deps),
|
||||
env: common_env,
|
||||
)
|
||||
|
||||
test(
|
||||
'test-spa-props',
|
||||
executable('test-spa-props', 'spa-props.c', dependencies: common_deps),
|
||||
env: common_env,
|
||||
)
|
||||
|
|
|
|||
264
tests/wp/spa-props.c
Normal file
264
tests/wp/spa-props.c
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
/* WirePlumber
|
||||
*
|
||||
* Copyright © 2019 Collabora Ltd.
|
||||
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
/* private functions, they should be hidden in the shared library */
|
||||
#include "wp/spa-props.c"
|
||||
|
||||
#include <spa/pod/iter.h>
|
||||
|
||||
static void
|
||||
test_spa_props_set_get (void)
|
||||
{
|
||||
WpSpaProps props = {0};
|
||||
const struct spa_pod *pod;
|
||||
float float_value = 0.0;
|
||||
const gchar *string_value = NULL;
|
||||
|
||||
wp_spa_props_register (&props, SPA_PROP_volume, "Volume",
|
||||
SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0));
|
||||
wp_spa_props_register (&props, SPA_PROP_START_CUSTOM + 1, "Test property",
|
||||
SPA_POD_String ("default value"));
|
||||
|
||||
g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_volume));
|
||||
g_assert_cmpint (spa_pod_get_float (pod, &float_value), ==, 0);
|
||||
g_assert_cmpfloat_with_epsilon (float_value, 1.0, 0.001);
|
||||
|
||||
g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_START_CUSTOM + 1));
|
||||
g_assert_cmpint (spa_pod_get_string (pod, &string_value), ==, 0);
|
||||
g_assert_cmpstr (string_value, ==, "default value");
|
||||
|
||||
g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_volume,
|
||||
SPA_POD_Float (0.8)), ==, 1);
|
||||
g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_START_CUSTOM + 1,
|
||||
SPA_POD_String ("test value")), ==, 1);
|
||||
|
||||
g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_volume));
|
||||
g_assert_cmpint (spa_pod_get_float (pod, &float_value), ==, 0);
|
||||
g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001);
|
||||
|
||||
g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_START_CUSTOM + 1));
|
||||
g_assert_cmpint (spa_pod_get_string (pod, &string_value), ==, 0);
|
||||
g_assert_cmpstr (string_value, ==, "test value");
|
||||
|
||||
wp_spa_props_clear (&props);
|
||||
}
|
||||
|
||||
static void
|
||||
test_spa_props_build_all (void)
|
||||
{
|
||||
WpSpaProps props = {0};
|
||||
gchar buffer[512];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||
struct spa_pod *pod;
|
||||
float float_value = 0.0;
|
||||
const gchar *string_value = NULL;
|
||||
guint32 id;
|
||||
g_autoptr (GPtrArray) arr = NULL;
|
||||
|
||||
wp_spa_props_register (&props, SPA_PROP_volume, "Volume",
|
||||
SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0));
|
||||
wp_spa_props_register (&props, SPA_PROP_START_CUSTOM + 1, "Test property",
|
||||
SPA_POD_String ("default value"));
|
||||
|
||||
g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_volume,
|
||||
SPA_POD_Float (0.8)), ==, 1);
|
||||
g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_START_CUSTOM + 1,
|
||||
SPA_POD_String ("test value")), ==, 1);
|
||||
|
||||
arr = wp_spa_props_build_all_pods (&props, &b);
|
||||
g_assert_nonnull (arr);
|
||||
g_assert_cmpint (arr->len, ==, 3);
|
||||
|
||||
pod = g_ptr_array_index (arr, 0);
|
||||
g_assert_nonnull (pod);
|
||||
g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_Props));
|
||||
g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_Props));
|
||||
g_assert_cmpint (spa_pod_parse_object (pod,
|
||||
SPA_TYPE_OBJECT_Props, NULL,
|
||||
SPA_PROP_volume, SPA_POD_Float (&float_value),
|
||||
SPA_PROP_START_CUSTOM + 1, SPA_POD_String (&string_value)),
|
||||
==, 2);
|
||||
g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001);
|
||||
g_assert_cmpstr (string_value, ==, "test value");
|
||||
|
||||
pod = g_ptr_array_index (arr, 1);
|
||||
g_assert_nonnull (pod);
|
||||
g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo));
|
||||
g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_PropInfo));
|
||||
|
||||
g_assert_cmpint (spa_pod_parse_object (pod,
|
||||
SPA_TYPE_OBJECT_PropInfo, NULL,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id (&id),
|
||||
SPA_PROP_INFO_name, SPA_POD_String (&string_value),
|
||||
SPA_PROP_INFO_type, SPA_POD_Pod (&pod)),
|
||||
==, 3);
|
||||
g_assert_cmpuint (id, ==, SPA_PROP_volume);
|
||||
g_assert_cmpstr (string_value, ==, "Volume");
|
||||
g_assert_nonnull (pod);
|
||||
/* https://gitlab.freedesktop.org/pipewire/pipewire/issues/196
|
||||
g_assert_true (spa_pod_is_choice (pod));
|
||||
g_assert_true (SPA_POD_CHOICE_VALUE_TYPE (pod) == SPA_TYPE_Float); */
|
||||
g_assert_true (SPA_POD_TYPE (pod) == SPA_TYPE_Float);
|
||||
|
||||
pod = g_ptr_array_index (arr, 2);
|
||||
g_assert_nonnull (pod);
|
||||
g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo));
|
||||
g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_PropInfo));
|
||||
|
||||
g_assert_cmpint (spa_pod_parse_object (pod,
|
||||
SPA_TYPE_OBJECT_PropInfo, NULL,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id (&id),
|
||||
SPA_PROP_INFO_name, SPA_POD_String (&string_value),
|
||||
SPA_PROP_INFO_type, SPA_POD_Pod (&pod)),
|
||||
==, 3);
|
||||
g_assert_cmpuint (id, ==, SPA_PROP_START_CUSTOM + 1);
|
||||
g_assert_cmpstr (string_value, ==, "Test property");
|
||||
g_assert_nonnull (pod);
|
||||
g_assert_true (spa_pod_is_string (pod));
|
||||
|
||||
wp_spa_props_clear (&props);
|
||||
}
|
||||
|
||||
static void
|
||||
test_spa_props_store_from_props (void)
|
||||
{
|
||||
WpSpaProps props = {0};
|
||||
gchar buffer[512];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||
const struct spa_pod *pod;
|
||||
float float_value = 0.0;
|
||||
const gchar *string_value = NULL;
|
||||
g_autoptr (GArray) arr = g_array_new (FALSE, FALSE, sizeof (guint32));
|
||||
|
||||
wp_spa_props_register (&props, SPA_PROP_volume, "Volume",
|
||||
SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0));
|
||||
wp_spa_props_register (&props, SPA_PROP_START_CUSTOM + 1, "Test property",
|
||||
SPA_POD_String ("default value"));
|
||||
|
||||
pod = spa_pod_builder_add_object (&b,
|
||||
SPA_TYPE_OBJECT_Props, SPA_PARAM_Props,
|
||||
SPA_PROP_volume, SPA_POD_Float (0.8),
|
||||
SPA_PROP_START_CUSTOM + 1, SPA_POD_String ("test value"));
|
||||
|
||||
g_assert_cmpint (wp_spa_props_store_from_props (&props, pod, arr), ==, 2);
|
||||
g_assert_cmpint (arr->len, ==, 2);
|
||||
g_assert_cmpint (((guint32 *)arr->data)[0], ==, SPA_PROP_volume);
|
||||
g_assert_cmpint (((guint32 *)arr->data)[1], ==, SPA_PROP_START_CUSTOM + 1);
|
||||
|
||||
g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_volume));
|
||||
g_assert_cmpint (spa_pod_get_float (pod, &float_value), ==, 0);
|
||||
g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001);
|
||||
|
||||
g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_START_CUSTOM + 1));
|
||||
g_assert_cmpint (spa_pod_get_string (pod, &string_value), ==, 0);
|
||||
g_assert_cmpstr (string_value, ==, "test value");
|
||||
|
||||
wp_spa_props_clear (&props);
|
||||
}
|
||||
|
||||
static void
|
||||
test_spa_props_register_from_prop_info (void)
|
||||
{
|
||||
WpSpaProps props = {0};
|
||||
gchar buffer[512];
|
||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer));
|
||||
const struct spa_pod *pod;
|
||||
float float_value = 0.0;
|
||||
const gchar *string_value = NULL;
|
||||
g_autoptr (GPtrArray) arr = NULL;
|
||||
guint32 id;
|
||||
|
||||
pod = spa_pod_builder_add_object (&b,
|
||||
SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id (SPA_PROP_volume),
|
||||
SPA_PROP_INFO_name, SPA_POD_String ("Volume"),
|
||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0));
|
||||
|
||||
g_assert_cmpint (wp_spa_props_register_from_prop_info (&props, pod), ==, 0);
|
||||
|
||||
pod = spa_pod_builder_add_object (&b,
|
||||
SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id (SPA_PROP_START_CUSTOM + 1),
|
||||
SPA_PROP_INFO_name, SPA_POD_String ("Test property"),
|
||||
SPA_PROP_INFO_type, SPA_POD_String ("default value"));
|
||||
|
||||
g_assert_cmpint (wp_spa_props_register_from_prop_info (&props, pod), ==, 0);
|
||||
|
||||
g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_volume,
|
||||
SPA_POD_Float (0.8)), ==, 1);
|
||||
g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_START_CUSTOM + 1,
|
||||
SPA_POD_String ("test value")), ==, 1);
|
||||
|
||||
arr = wp_spa_props_build_all_pods (&props, &b);
|
||||
g_assert_nonnull (arr);
|
||||
g_assert_cmpint (arr->len, ==, 3);
|
||||
|
||||
pod = g_ptr_array_index (arr, 0);
|
||||
g_assert_nonnull (pod);
|
||||
g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_Props));
|
||||
g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_Props));
|
||||
g_assert_cmpint (spa_pod_parse_object (pod,
|
||||
SPA_TYPE_OBJECT_Props, NULL,
|
||||
SPA_PROP_volume, SPA_POD_Float (&float_value),
|
||||
SPA_PROP_START_CUSTOM + 1, SPA_POD_String (&string_value)),
|
||||
==, 2);
|
||||
g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001);
|
||||
g_assert_cmpstr (string_value, ==, "test value");
|
||||
|
||||
pod = g_ptr_array_index (arr, 1);
|
||||
g_assert_nonnull (pod);
|
||||
g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo));
|
||||
g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_PropInfo));
|
||||
|
||||
g_assert_cmpint (spa_pod_parse_object (pod,
|
||||
SPA_TYPE_OBJECT_PropInfo, NULL,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id (&id),
|
||||
SPA_PROP_INFO_name, SPA_POD_String (&string_value),
|
||||
SPA_PROP_INFO_type, SPA_POD_Pod (&pod)),
|
||||
==, 3);
|
||||
g_assert_cmpuint (id, ==, SPA_PROP_volume);
|
||||
g_assert_cmpstr (string_value, ==, "Volume");
|
||||
g_assert_nonnull (pod);
|
||||
/* https://gitlab.freedesktop.org/pipewire/pipewire/issues/196
|
||||
g_assert_true (spa_pod_is_choice (pod));
|
||||
g_assert_true (SPA_POD_CHOICE_VALUE_TYPE (pod) == SPA_TYPE_Float); */
|
||||
g_assert_true (SPA_POD_TYPE (pod) == SPA_TYPE_Float);
|
||||
|
||||
pod = g_ptr_array_index (arr, 2);
|
||||
g_assert_nonnull (pod);
|
||||
g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo));
|
||||
g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_PropInfo));
|
||||
|
||||
g_assert_cmpint (spa_pod_parse_object (pod,
|
||||
SPA_TYPE_OBJECT_PropInfo, NULL,
|
||||
SPA_PROP_INFO_id, SPA_POD_Id (&id),
|
||||
SPA_PROP_INFO_name, SPA_POD_String (&string_value),
|
||||
SPA_PROP_INFO_type, SPA_POD_Pod (&pod)),
|
||||
==, 3);
|
||||
g_assert_cmpuint (id, ==, SPA_PROP_START_CUSTOM + 1);
|
||||
g_assert_cmpstr (string_value, ==, "Test property");
|
||||
g_assert_nonnull (pod);
|
||||
g_assert_true (spa_pod_is_string (pod));
|
||||
|
||||
wp_spa_props_clear (&props);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL);
|
||||
|
||||
g_test_add_func ("/wp/spa_props/set_get", test_spa_props_set_get);
|
||||
g_test_add_func ("/wp/spa_props/build_all", test_spa_props_build_all);
|
||||
g_test_add_func ("/wp/spa_props/store_from_props",
|
||||
test_spa_props_store_from_props);
|
||||
g_test_add_func ("/wp/spa_props/register_from_prop_info",
|
||||
test_spa_props_register_from_prop_info);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue