Skip to content
Snippets Groups Projects
Commit 3d032cc2 authored by George Kiagiadakis's avatar George Kiagiadakis
Browse files

lib: delete WpProps

This is no longer useful, we are going to use WpSpaPod directly
in combination with the param caching for WpPwObjectMixin
parent bd65517b
No related branches found
No related tags found
No related merge requests found
......@@ -21,7 +21,6 @@ wp_lib_sources = files(
'plugin.c',
'port.c',
'properties.c',
#'props.c',
'proxy.c',
'proxy-interfaces.c',
'session.c',
......@@ -58,7 +57,6 @@ wp_lib_headers = files(
'plugin.h',
'port.h',
'properties.h',
#'props.h',
'proxy.h',
'proxy-interfaces.h',
'session.h',
......
/* WirePlumber
*
* Copyright © 2020 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
/**
* SECTION: props
* @title: Dynamic Proxy Properties
*/
#define G_LOG_DOMAIN "wp-props"
#include "props.h"
#include "debug.h"
#include "spa-type.h"
#include "wpenums.h"
#include <spa/param/param.h>
struct entry
{
guint32 id;
gchar *description;
WpSpaPod *type;
WpSpaPod *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->description);
g_clear_pointer (&e->type, wp_spa_pod_unref);
g_clear_pointer (&e->value, wp_spa_pod_unref);
g_slice_free (struct entry, e);
}
struct _WpProps
{
GObject parent;
GWeakRef proxy;
WpPropsMode mode;
GList *entries;
};
enum {
PROP_0,
PROP_PROXY,
PROP_MODE,
};
enum
{
SIGNAL_PROP_CHANGED,
LAST_SIGNAL,
};
static guint signals[LAST_SIGNAL] = { 0 };
/**
* WpProps:
*
* #WpProps handles dynamic properties on PipeWire objects, which are
* known in PipeWire as "params" of type `SPA_PARAM_Props`.
*
* #WpProps has two modes of operation:
* - %WP_PROPS_MODE_CACHE: In this mode, this object caches properties that are
* actually stored and discovered from the associated proxy object.
* When setting a property, the property is first set on the proxy and the
* cache is updated asynchronously (so wp_props_get() will not immediately
* return the value that was set with wp_props_set()).
* - %WP_PROPS_MODE_STORE: In this mode, this object is the actual store of
* properties. This is used by object implementations, such as #WpImplSession.
* Before storing anything, properties need to be registered with
* wp_props_register().
*/
G_DEFINE_TYPE (WpProps, wp_props, G_TYPE_OBJECT)
static void
wp_props_init (WpProps * self)
{
g_weak_ref_init (&self->proxy, NULL);
}
static void
wp_props_finalize (GObject * object)
{
WpProps * self = WP_PROPS (object);
g_list_free_full (self->entries, (GDestroyNotify) entry_free);
g_weak_ref_clear (&self->proxy);
G_OBJECT_CLASS (wp_props_parent_class)->finalize (object);
}
static void
wp_props_set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
WpProps *self = WP_PROPS (object);
switch (property_id) {
case PROP_PROXY:
g_weak_ref_set (&self->proxy, g_value_get_object (value));
break;
case PROP_MODE:
self->mode = g_value_get_enum (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
wp_props_get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
{
WpProps *self = WP_PROPS (object);
switch (property_id) {
case PROP_PROXY:
g_value_take_object (value, g_weak_ref_get (&self->proxy));
break;
case PROP_MODE:
g_value_set_enum (value, self->mode);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
break;
}
}
static void
wp_props_class_init (WpPropsClass * klass)
{
GObjectClass * object_class = (GObjectClass *) klass;
object_class->finalize = wp_props_finalize;
object_class->set_property = wp_props_set_property;
object_class->get_property = wp_props_get_property;
g_object_class_install_property (object_class, PROP_PROXY,
g_param_spec_object ("proxy", "proxy", "The proxy", WP_TYPE_PROXY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_MODE,
g_param_spec_enum ("mode", "mode", "The mode",
WP_TYPE_PROPS_MODE, WP_PROPS_MODE_CACHE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
/**
* WpProps::prop-changed:
* @self: the props
* @name: the name of the property that changed
*/
signals[SIGNAL_PROP_CHANGED] = g_signal_new (
"prop-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING);
}
static struct entry *
find_entry (WpProps * self, const gchar * name)
{
GList *l = self->entries;
guint32 id;
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PROPS, name, &id,
NULL, NULL)) {
wp_critical_object (self, "prop id name '%s' is not registered", name);
return NULL;
}
while (l && ((struct entry *) l->data)->id != id)
l = g_list_next (l);
if (!l)
return NULL;
return (struct entry *) l->data;
}
/* public */
/**
* wp_props_new:
* @mode: the mode
* @proxy: (transfer none) (nullable): the associated proxy; can be %NULL
* if @mode is %WP_PROPS_MODE_STORE
*
* Returns: (transfer full): the newly created #WpProps object
*/
WpProps *
wp_props_new (WpPropsMode mode, WpProxy * proxy)
{
return g_object_new (WP_TYPE_PROPS, "mode", mode, "proxy", proxy, NULL);
}
/**
* wp_props_register:
* @self: the props
* @name: the name (registered spa type nick) of the property
* @description: the description of the property
* @pod: (transfer full): a pod that gives the type and the default value
*
* Registers a new property. This can only be used in %WP_PROPS_MODE_STORE mode.
*
* @name must be a valid spa type nickname, registered in the
* %WP_SPA_TYPE_TABLE_PROPS table.
*
* @pod can be a value (which is taken as the default value) or a choice
* (which defines the allowed values for this property)
*/
void
wp_props_register (WpProps * self, const gchar * name,
const gchar * description, WpSpaPod * pod)
{
guint32 id;
g_return_if_fail (self->mode == WP_PROPS_MODE_STORE);
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PROPS, name, &id,
NULL, NULL)) {
wp_critical_object (self, "prop id name '%s' is not registered", name);
return;
}
struct entry *e = entry_new ();
e->id = id;
e->description = g_strdup (description);
e->type = pod;
e->value = wp_spa_pod_is_choice (e->type) ?
wp_spa_pod_get_choice_child (e->type) : wp_spa_pod_ref (e->type);
self->entries = g_list_append (self->entries, e);
}
/**
* wp_props_register_from_info:
* @self: the props
* @pod: (transfer full): a `SPA_TYPE_OBJECT_PropInfo` pod
*
* Registers a new property using the information of the provided PropInfo @pod
*/
void
wp_props_register_from_info (WpProps * self, WpSpaPod * pod)
{
g_autoptr (WpSpaPod) prop_info = pod;
guint32 id;
const gchar *description;
g_autoptr (WpSpaPod) type = NULL;
if (!wp_spa_pod_get_object (prop_info,
"PropInfo", NULL,
"id", "I", &id,
"name", "s", &description,
"type", "P", &type,
NULL)) {
wp_warning_boxed (WP_TYPE_SPA_POD, prop_info, "bad prop info object");
return;
}
struct entry *e = entry_new ();
e->id = id;
e->description = g_strdup (description);
e->type = wp_spa_pod_ref (type);
e->value = wp_spa_pod_is_choice (e->type) ?
wp_spa_pod_get_choice_child (e->type) : wp_spa_pod_ref (e->type);
self->entries = g_list_append (self->entries, e);
}
/**
* wp_props_iterate_prop_info:
* @self: the props
*
* Returns: (transfer full): a #WpIterator that iterates over #WpSpaPod items
* where each pod is an object of type `SPA_TYPE_OBJECT_PropInfo`, and thus
* contains the id, the description and the type of each property.
*/
WpIterator *
wp_props_iterate_prop_info (WpProps * self)
{
g_autoptr (GPtrArray) res =
g_ptr_array_new_with_free_func ((GDestroyNotify) wp_spa_pod_unref);
g_return_val_if_fail (WP_IS_PROPS (self), NULL);
for (GList *l = self->entries; l != NULL; l = g_list_next (l)) {
struct entry * e = (struct entry *) l->data;
g_ptr_array_add (res, wp_spa_pod_new_object (
"PropInfo", "PropInfo",
"id", "I", e->id,
"name", "s", e->description,
"type", "P", e->type,
NULL));
}
return wp_iterator_new_ptr_array (g_steal_pointer (&res), WP_TYPE_SPA_POD);
}
/**
* wp_props_get_all:
* @self: the props
*
* Returns: (transfer full): a pod object of type `SPA_TYPE_OBJECT_Props`
* that contains all the properties, as they would appear on the PipeWire
* object
*/
WpSpaPod *
wp_props_get_all (WpProps * self)
{
g_autoptr (WpSpaPodBuilder) b = NULL;
g_return_val_if_fail (WP_IS_PROPS (self), NULL);
b = wp_spa_pod_builder_new_object ("Props", "Props");
for (GList *l = self->entries; l != NULL; l = g_list_next (l)) {
struct entry * e = (struct entry *) l->data;
if (e->id && e->value) {
wp_spa_pod_builder_add_property_id (b, e->id);
wp_spa_pod_builder_add_pod (b, e->value);
}
}
return wp_spa_pod_builder_end (b);
}
/**
* wp_props_get:
* @self: the props
* @name: the name (registered spa type nick) of the property to get
*
* Returns: (transfer full) (nullable): a pod with the current value of the
* property or %NULL if the property is not found
*/
WpSpaPod *
wp_props_get (WpProps * self, const gchar * name)
{
struct entry * e;
g_return_val_if_fail (WP_IS_PROPS (self), NULL);
if (!(e = find_entry (self, name)))
return NULL;
return wp_spa_pod_ref (e->value);
}
static void
wp_props_set_on_proxy (WpProps * self, const gchar * name, WpSpaPod * pod)
{
g_autoptr (WpSpaPod) val = pod;
g_autoptr (WpProxy) proxy = g_weak_ref_get (&self->proxy);
g_autoptr (WpSpaPod) param = NULL;
g_return_if_fail (proxy != NULL);
if (name) {
param = wp_spa_pod_new_object (
"Props", "Props",
name, "P", val,
NULL);
} else {
param = wp_spa_pod_ref (pod);
}
/* our store will be updated by the param event */
wp_proxy_set_param (proxy, "Props", param);
}
static void
wp_props_store_single (WpProps * self, const gchar * name, WpSpaPod * pod)
{
g_autoptr (WpSpaPod) val = pod;
struct entry * e;
if (!(e = find_entry (self, name))) {
wp_warning_object (self, "prop '%s' is not registered", name);
return;
}
wp_trace_object (self, "storing '%s', entry:%p", name, e);
/* TODO check the type */
if (!wp_spa_pod_equal (e->value, val)) {
g_clear_pointer (&e->value, wp_spa_pod_unref);
e->value = wp_spa_pod_ensure_unique_owner (g_steal_pointer (&val));
g_signal_emit (self, signals[SIGNAL_PROP_CHANGED], 0, name);
}
}
static void
wp_props_store_many (WpProps * self, WpSpaPod * pod)
{
g_autoptr (WpSpaPod) props = pod;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) item = G_VALUE_INIT;
for (it = wp_spa_pod_iterate (props);
wp_iterator_next (it, &item);
g_value_unset (&item)) {
WpSpaPod *p = g_value_get_boxed (&item);
const char *name = NULL;
WpSpaPod *val = NULL;
if (!wp_spa_pod_get_property (p, &name, &val)) {
wp_warning_object (self, "failed to get property name & value");
continue;
}
wp_props_store (self, name, val);
}
}
/**
* wp_props_set:
* @self: the props
* @name: (nullable): the name (registered spa type nick) of the property to set
* @value: (transfer full): the value to set
*
* Sets the property specified with @name to have the given @value.
* If the mode is %WP_PROPS_MODE_CACHE, this property will be set on the
* associated proxy first and will be updated asynchronously.
*
* If @name is %NULL, then @value must be an object of type
* `SPA_TYPE_OBJECT_Props`, which may contain multiple properties to set.
*
* If any value actually changes, the #WpProps::prop-changed signal will be
* emitted.
*/
void
wp_props_set (WpProps * self, const gchar * name, WpSpaPod * value)
{
g_return_if_fail (WP_IS_PROPS (self));
g_return_if_fail (value != NULL);
switch (self->mode) {
case WP_PROPS_MODE_CACHE:
wp_props_set_on_proxy (self, name, value);
break;
case WP_PROPS_MODE_STORE:
if (name)
wp_props_store_single (self, name, value);
else
wp_props_store_many (self, value);
break;
default:
g_return_if_reached ();
}
}
/**
* wp_props_store:
* @self: the props
* @name: (nullable): the name (registered spa type nick) of the property to set
* @value: (transfer full): the value to set
*
* Stores the given @value for the property specified with @name.
* This method always stores, even if the mode is %WP_PROPS_MODE_CACHE. This is
* useful for caching implementations only.
*
* If @name is %NULL, then @value must be an object of type
* `SPA_TYPE_OBJECT_Props`, which may contain multiple properties to set.
*
* If any value actually changes, the #WpProps::prop-changed signal will be
* emitted.
*/
void
wp_props_store (WpProps * self, const gchar * name, WpSpaPod * value)
{
g_return_if_fail (WP_IS_PROPS (self));
g_return_if_fail (value != NULL);
if (name)
wp_props_store_single (self, name, value);
else
wp_props_store_many (self, value);
}
/* WirePlumber
*
* Copyright © 2020 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#ifndef __WIREPLUMBER_PROPS_H__
#define __WIREPLUMBER_PROPS_H__
#include "iterator.h"
#include "spa-pod.h"
#include "proxy.h"
G_BEGIN_DECLS
/**
* WpPropsMode:
* @WP_PROPS_MODE_CACHE: props are stored on the proxy and cached here
* @WP_PROPS_MODE_STORE: props are stored here directly
*/
typedef enum {
WP_PROPS_MODE_CACHE,
WP_PROPS_MODE_STORE,
} WpPropsMode;
/**
* WP_TYPE_PROPS:
*
* The #WpProps #GType
*/
#define WP_TYPE_PROPS (wp_props_get_type ())
WP_API
G_DECLARE_FINAL_TYPE (WpProps, wp_props, WP, PROPS, GObject)
WP_API
WpProps * wp_props_new (WpPropsMode mode, WpProxy * proxy);
WP_API
void wp_props_register (WpProps * self, const gchar * name,
const gchar * description, WpSpaPod * pod);
WP_API
void wp_props_register_from_info (WpProps * self, WpSpaPod * pod);
WP_API
WpIterator * wp_props_iterate_prop_info (WpProps * self);
WP_API
WpSpaPod * wp_props_get_all (WpProps * self);
WP_API
WpSpaPod * wp_props_get (WpProps * self, const gchar * name);
WP_API
void wp_props_set (WpProps * self, const gchar * name, WpSpaPod * value);
WP_API
void wp_props_store (WpProps * self, const gchar * name, WpSpaPod * value);
WP_PRIVATE_API
void wp_props_handle_proxy_param_event (WpProps * self, guint32 id,
WpSpaPod * pod);
G_END_DECLS
#endif
......@@ -43,13 +43,6 @@ test(
env: common_env,
)
# test(
# 'test-props',
# executable('test-props', 'props.c',
# dependencies: common_deps, c_args: common_args),
# env: common_env,
# )
test(
'test-proxy',
executable('test-proxy', 'proxy.c',
......
/* WirePlumber
*
* Copyright © 2019 Collabora Ltd.
* @author George Kiagiadakis <george.kiagiadakis@collabora.com>
*
* SPDX-License-Identifier: MIT
*/
#include <wp/wp.h>
#include <spa/param/props.h>
#include <spa/pod/vararg.h>
static void
test_props_set_get (void)
{
g_autoptr (WpProps) props = NULL;
float float_value = 0.0;
const gchar *string_value = NULL;
props = wp_props_new (WP_PROPS_MODE_STORE, NULL);
wp_props_register (props, "volume", "Volume",
wp_spa_pod_new_choice ("Range", "f", 1.0, "f", 0.0, "f", 10.0, NULL));
wp_props_register (props, "wp-test-property", "Test property",
wp_spa_pod_new_string ("default value"));
{
g_autoptr (WpSpaPod) pod = wp_props_get (props, "volume");
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_float (pod, &float_value));
g_assert_cmpfloat_with_epsilon (float_value, 1.0, 0.001);
}
{
g_autoptr (WpSpaPod) pod = wp_props_get (props, "wp-test-property");
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_string (pod, &string_value));
g_assert_cmpstr (string_value, ==, "default value");
}
wp_props_set (props, "volume", wp_spa_pod_new_float (0.8));
wp_props_set (props, "wp-test-property",
wp_spa_pod_new_string ("test value"));
{
g_autoptr (WpSpaPod) pod = wp_props_get (props, "volume");
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_float (pod, &float_value));
g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001);
}
{
g_autoptr (WpSpaPod) pod = wp_props_get (props, "wp-test-property");
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_string (pod, &string_value));
g_assert_cmpstr (string_value, ==, "test value");
}
}
static void
test_props_get_all (void)
{
g_autoptr (WpProps) props = NULL;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) item = G_VALUE_INIT;
float float_value = 0.0;
const gchar *string_value = NULL;
const gchar *id_name;
guint32 id;
props = wp_props_new (WP_PROPS_MODE_STORE, NULL);
wp_props_register (props, "volume", "Volume",
wp_spa_pod_new_choice ("Range", "f", 1.0, "f", 0.0, "f", 10.0, NULL));
wp_props_register (props, "wp-test-property", "Test property",
wp_spa_pod_new_string ("default value"));
wp_props_set (props, "volume", wp_spa_pod_new_float (0.8));
wp_props_set (props, "wp-test-property",
wp_spa_pod_new_string ("test value"));
{
g_autoptr (WpSpaPod) pod = wp_props_get_all (props);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_object (pod,
"Props", &id_name,
"volume", "f", &float_value,
"wp-test-property", "s", &string_value,
NULL));
g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001);
g_assert_cmpstr (string_value, ==, "test value");
}
it = wp_props_iterate_prop_info (props);
g_assert_true (wp_iterator_next (it, &item));
{
g_autoptr (WpSpaPod) pod = g_value_dup_boxed (&item);
g_autoptr (WpSpaPod) pod_value = NULL;
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_object (pod,
"PropInfo", &id_name,
"id", "I", &id,
"name", "s", &string_value,
"type", "P", &pod_value,
NULL));
g_assert_cmpuint (id, ==, SPA_PROP_volume);
g_assert_cmpstr (string_value, ==, "Volume");
g_assert_nonnull (pod_value);
g_assert_true (wp_spa_pod_is_choice (pod_value));
}
g_value_unset (&item);
g_assert_true (wp_iterator_next (it, &item));
{
g_autoptr (WpSpaPod) pod = g_value_dup_boxed (&item);
g_autoptr (WpSpaPod) pod_value = NULL;
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_object (pod,
"PropInfo", &id_name,
"id", "I", &id,
"name", "s", &string_value,
"type", "P", &pod_value,
NULL));
g_assert_cmpuint (id, >, SPA_PROP_START_CUSTOM);
g_assert_cmpstr (string_value, ==, "Test property");
g_assert_nonnull (pod_value);
g_assert_true (wp_spa_pod_is_string (pod_value));
}
}
static void
test_props_store_from_props (void)
{
g_autoptr (WpProps) props = NULL;
float float_value = 0.0;
const gchar *string_value = NULL;
props = wp_props_new (WP_PROPS_MODE_STORE, NULL);
wp_props_register (props, "volume", "Volume",
wp_spa_pod_new_choice ("Range", "f", 1.0, "f", 0.0, "f", 10.0, NULL));
wp_props_register (props, "wp-test-property", "Test property",
wp_spa_pod_new_string ("default value"));
wp_props_set (props, NULL, wp_spa_pod_new_object (
"Props", "Props",
"volume", "f", 0.8,
"wp-test-property", "s", "test value",
NULL));
{
g_autoptr (WpSpaPod) pod = wp_props_get (props, "volume");
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_float (pod, &float_value));
g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001);
}
{
g_autoptr (WpSpaPod) pod = wp_props_get (props, "wp-test-property");
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_string (pod, &string_value));
g_assert_cmpstr (string_value, ==, "test value");
}
}
static void
test_props_register_from_info (void)
{
g_autoptr (WpProps) props = NULL;
g_autoptr (WpIterator) it = NULL;
g_auto (GValue) item = G_VALUE_INIT;
float float_value = 0.0;
const gchar *string_value = NULL;
const gchar *id_name;
guint32 id;
guint test_property_id = 0;
wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PROPS, "wp-test-property",
&test_property_id, NULL, NULL);
props = wp_props_new (WP_PROPS_MODE_STORE, NULL);
wp_props_register_from_info (props, wp_spa_pod_new_object (
"PropInfo", "PropInfo",
"id", "I", SPA_PROP_volume,
"name", "s", "Volume",
"type", SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0),
NULL));
wp_props_register_from_info (props, wp_spa_pod_new_object (
"PropInfo", "PropInfo",
"id", "I", test_property_id,
"name", "s", "Test property",
"type", "s", "default value",
NULL));
wp_props_set (props, "volume", wp_spa_pod_new_float (0.8));
wp_props_set (props, "wp-test-property",
wp_spa_pod_new_string ("test value"));
{
g_autoptr (WpSpaPod) pod = wp_props_get_all (props);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_object (pod,
"Props", &id_name,
"volume", "f", &float_value,
"wp-test-property", "s", &string_value,
NULL));
g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001);
g_assert_cmpstr (string_value, ==, "test value");
}
it = wp_props_iterate_prop_info (props);
g_assert_true (wp_iterator_next (it, &item));
{
g_autoptr (WpSpaPod) pod = g_value_dup_boxed (&item);
g_autoptr (WpSpaPod) pod_value = NULL;
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_object (pod,
"PropInfo", &id_name,
"id", "I", &id,
"name", "s", &string_value,
"type", "P", &pod_value,
NULL));
g_assert_cmpuint (id, ==, SPA_PROP_volume);
g_assert_cmpstr (string_value, ==, "Volume");
g_assert_nonnull (pod_value);
g_assert_true (wp_spa_pod_is_choice (pod_value));
}
g_value_unset (&item);
g_assert_true (wp_iterator_next (it, &item));
{
g_autoptr (WpSpaPod) pod = g_value_dup_boxed (&item);
g_autoptr (WpSpaPod) pod_value = NULL;
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_get_object (pod,
"PropInfo", &id_name,
"id", "I", &id,
"name", "s", &string_value,
"type", "P", &pod_value,
NULL));
g_assert_cmpuint (id, >, SPA_PROP_START_CUSTOM);
g_assert_cmpstr (string_value, ==, "Test property");
g_assert_nonnull (pod_value);
g_assert_true (wp_spa_pod_is_string (pod_value));
}
}
int
main (int argc, char *argv[])
{
g_test_init (&argc, &argv, NULL);
wp_init (WP_INIT_ALL);
g_assert_true (wp_spa_type_register (WP_SPA_TYPE_TABLE_PROPS,
"Wp:Test:Property", "wp-test-property"));
g_test_add_func ("/wp/props/set_get", test_props_set_get);
g_test_add_func ("/wp/props/get_all", test_props_get_all);
g_test_add_func ("/wp/props/store_from_props",
test_props_store_from_props);
g_test_add_func ("/wp/props/register_from_info",
test_props_register_from_info);
return g_test_run ();
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment