spa-type: refactor

* Use a more complete API to introspect SPA types
* Avoid the need for the Tables enumeration; the tables
  are now registered with a string
* Avoid the need for initialization, work directly on spa_types
  and other static data
* Allow working with Object pods that are not Params;
  the PARAMS table was previously hardcoded in the pod implementation
* Add a different dynamic type registration system, closer to
  how spa type works. The only regression is that we can no longer
  register additional custom object fields (custom SPA_PROP_* for example),
  but this feature can be re-added later
This commit is contained in:
George Kiagiadakis 2021-01-13 20:11:41 +02:00
parent 7488ec0e25
commit 3762388831
23 changed files with 1422 additions and 818 deletions

View file

@ -535,19 +535,20 @@ wp_impl_endpoint_stream_set_param (gpointer instance, guint32 id, guint32 flags,
WpImplEndpointStream *self = WP_IMPL_ENDPOINT_STREAM (instance);
g_autoptr (WpPipewireObject) node = wp_session_item_get_associated_proxy (
WP_SESSION_ITEM (self->item), WP_TYPE_NODE);
const gchar *idstr = NULL;
if (!node) {
wp_warning_object (self, "associated node is no longer available");
return -EPIPE;
}
if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PARAM, id, NULL, &idstr, NULL)) {
WpSpaIdValue idval = wp_spa_id_value_from_number ("Spa:Enum:ParamId", id);
if (!idval) {
wp_critical_object (self, "invalid param id: %u", id);
return -EINVAL;
}
return wp_pipewire_object_set_param (node, idstr, flags, param) ? 0 : -EIO;
return wp_pipewire_object_set_param (node, wp_spa_id_value_short_name (idval),
flags, param) ? 0 : -EIO;
}
#define pw_endpoint_stream_emit(hooks,method,version,...) \

View file

@ -1081,19 +1081,20 @@ wp_impl_endpoint_set_param (gpointer instance, guint32 id, guint32 flags,
WpImplEndpoint *self = WP_IMPL_ENDPOINT (instance);
g_autoptr (WpPipewireObject) node = wp_session_item_get_associated_proxy (
WP_SESSION_ITEM (self->item), WP_TYPE_NODE);
const gchar *idstr = NULL;
if (!node) {
wp_warning_object (self, "associated node is no longer available");
return -EPIPE;
}
if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PARAM, id, NULL, &idstr, NULL)) {
WpSpaIdValue idval = wp_spa_id_value_from_number ("Spa:Enum:ParamId", id);
if (!idval) {
wp_critical_object (self, "invalid param id: %u", id);
return -EINVAL;
}
return wp_pipewire_object_set_param (node, idstr, flags, param) ? 0 : -EIO;
return wp_pipewire_object_set_param (node, wp_spa_id_value_short_name (idval),
flags, param) ? 0 : -EIO;
}
#define pw_endpoint_emit(hooks,method,version,...) \

View file

@ -83,12 +83,13 @@ wp_pw_object_mixin_get_param_info (WpPipewireObject * obj)
g_variant_builder_init (&b, G_VARIANT_TYPE ("a{ss}"));
for (guint i = 0; i < n_params; i++) {
WpSpaIdValue idval;
const gchar *nick = NULL;
gchar flags[3];
guint flags_idx = 0;
wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PARAM, info[i].id, NULL, &nick,
NULL);
idval = wp_spa_id_value_from_number ("Spa:Enum:ParamId", info[i].id);
nick = wp_spa_id_value_short_name (idval);
g_return_val_if_fail (nick != NULL, NULL);
if (info[i].flags & SPA_PARAM_INFO_READ)
@ -170,8 +171,8 @@ wp_pw_object_mixin_enum_params_unchecked (gpointer obj,
/* debug */
if (wp_log_level_is_enabled (G_LOG_LEVEL_DEBUG)) {
const gchar *name = NULL;
wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PARAM, id, &name, NULL, NULL);
name = wp_spa_id_value_short_name (
wp_spa_id_value_from_number ("Spa:Enum:ParamId", id));
wp_debug_object (obj, "enum id %u (%s), seq 0x%x (%u), task "
WP_OBJECT_FORMAT "%s", id, name, seq, seq, WP_OBJECT_ARGS (task),
iface->enum_params_sync ? ", sync" : "");
@ -199,7 +200,7 @@ wp_pw_object_mixin_enum_params (WpPipewireObject * obj, const gchar * id,
GAsyncReadyCallback callback, gpointer user_data)
{
WpPwObjectMixinPrivInterface *iface = WP_PW_OBJECT_MIXIN_PRIV_GET_IFACE (obj);
guint32 param_id = 0;
WpSpaIdValue param_id;
if (!(iface->enum_params || iface->enum_params_sync)) {
g_task_report_new_error (obj, callback, user_data, NULL,
@ -209,13 +210,14 @@ wp_pw_object_mixin_enum_params (WpPipewireObject * obj, const gchar * id,
}
/* translate the id */
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PARAM, id, &param_id,
NULL, NULL)) {
param_id = wp_spa_id_value_from_short_name ("Spa:Enum:ParamId", id);
if (!param_id) {
wp_critical_object (obj, "invalid param id: %s", id);
return;
}
wp_pw_object_mixin_enum_params_unchecked (obj, param_id, filter,
wp_pw_object_mixin_enum_params_unchecked (obj,
wp_spa_id_value_number (param_id), filter,
cancellable, callback, user_data);
}
@ -238,22 +240,24 @@ wp_pw_object_mixin_enum_params_sync (WpPipewireObject * obj, const gchar * id,
{
WpPwObjectMixinPrivInterface *iface = WP_PW_OBJECT_MIXIN_PRIV_GET_IFACE (obj);
GPtrArray *params = NULL;
guint32 param_id = 0;
WpSpaIdValue param_id;
/* translate the id */
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PARAM, id, &param_id,
NULL, NULL)) {
param_id = wp_spa_id_value_from_short_name ("Spa:Enum:ParamId", id);
if (!param_id) {
wp_critical_object (obj, "invalid param id: %s", id);
return NULL;
}
if (iface->enum_params_sync) {
/* use enum_params_sync if supported */
params = iface->enum_params_sync (obj, param_id, 0, -1, filter);
params = iface->enum_params_sync (obj, wp_spa_id_value_number (param_id),
0, -1, filter);
} else {
/* otherwise, find and return the cached params */
WpPwObjectMixinData *data = wp_pw_object_mixin_get_data (obj);
params = wp_pw_object_mixin_get_stored_params (data, param_id);
params = wp_pw_object_mixin_get_stored_params (data,
wp_spa_id_value_number (param_id));
/* TODO filter */
}
@ -265,7 +269,7 @@ wp_pw_object_mixin_set_param (WpPipewireObject * obj, const gchar * id,
guint32 flags, WpSpaPod * param)
{
WpPwObjectMixinPrivInterface *iface = WP_PW_OBJECT_MIXIN_PRIV_GET_IFACE (obj);
guint32 param_id = 0;
WpSpaIdValue param_id;
gint ret;
if (!iface->set_param) {
@ -273,14 +277,14 @@ wp_pw_object_mixin_set_param (WpPipewireObject * obj, const gchar * id,
return FALSE;
}
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PARAM, id, &param_id,
NULL, NULL)) {
param_id = wp_spa_id_value_from_short_name ("Spa:Enum:ParamId", id);
if (!param_id) {
wp_critical_object (obj, "invalid param id: %s", id);
wp_spa_pod_unref (param);
return FALSE;
}
ret = iface->set_param (obj, param_id, flags, param);
ret = iface->set_param (obj, wp_spa_id_value_number (param_id), flags, param);
if (G_UNLIKELY (SPA_RESULT_IS_ERROR (ret))) {
wp_message_object (obj, "set_param failed: %s", spa_strerror (ret));
@ -940,7 +944,8 @@ wp_pw_object_mixin_notify_params_changed (gpointer instance, guint32 id)
if (wp_log_level_is_enabled (G_LOG_LEVEL_DEBUG)) {
const gchar *name = NULL;
wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PARAM, id, &name, NULL, NULL);
name = wp_spa_id_value_short_name (wp_spa_id_value_from_number (
"Spa:Enum:ParamId", id));
wp_debug_object (instance, "notify param id:%u (%s)", id, name);
}

View file

@ -52,13 +52,13 @@ struct _WpSpaPod
struct spa_pod_rectangle pod_rectangle;
struct spa_pod_fraction pod_fraction;
struct wp_property_data {
WpSpaTypeTable table;
WpSpaIdTable table;
guint32 key;
guint32 flags;
} data_property; /* Only used for property pods */
struct wp_control_data {
guint32 offset;
guint32 type;
enum spa_control_type type;
} data_control; /* Only used for control pods */
} static_pod; /* Only used for statically allocated pods */
WpSpaPodBuilder *builder; /* Only used for dynamically allocated pods */
@ -69,12 +69,11 @@ G_DEFINE_BOXED_TYPE (WpSpaPod, wp_spa_pod, wp_spa_pod_ref, wp_spa_pod_unref)
struct _WpSpaPodBuilder
{
struct spa_pod_builder builder;
struct spa_pod_frame frame;
WpSpaType type;
size_t size;
guint8 *buf;
struct spa_pod_builder builder;
uint32_t type;
struct spa_pod_frame frame;
WpSpaTypeTable prop_table; /* Only used when parsing properties */
};
G_DEFINE_BOXED_TYPE (WpSpaPodBuilder, wp_spa_pod_builder,
@ -82,11 +81,10 @@ G_DEFINE_BOXED_TYPE (WpSpaPodBuilder, wp_spa_pod_builder,
struct _WpSpaPodParser
{
guint32 type;
struct spa_pod_parser parser;
WpSpaPod *pod;
struct spa_pod_frame frame;
WpSpaTypeTable prop_table; /* Only used when parsing properties */
WpSpaType type;
WpSpaPod *pod;
};
G_DEFINE_BOXED_TYPE (WpSpaPodParser, wp_spa_pod_parser,
@ -111,7 +109,7 @@ static const struct spa_pod_builder_callbacks builder_callbacks = {
};
static WpSpaPodBuilder *
wp_spa_pod_builder_new (size_t size, uint32_t type)
wp_spa_pod_builder_new (size_t size, WpSpaType type)
{
WpSpaPodBuilder *self = g_rc_box_new0 (WpSpaPodBuilder);
self->size = size;
@ -180,10 +178,8 @@ wp_spa_pod_new (const struct spa_pod *pod, WpSpaPodType type, guint32 flags)
/* Set the prop table if it is an object */
if (pod->type == SPA_TYPE_Object) {
WpSpaTypeTable prop_table = 0;
wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_BASIC,
((struct spa_pod_object *) pod)->body.type, NULL, NULL, &prop_table);
self->static_pod.data_property.table = prop_table;
self->static_pod.data_property.table =
wp_spa_type_get_values_table (((struct spa_pod_object *) pod)->body.type);
}
return self;
@ -220,7 +216,7 @@ wp_spa_pod_new_wrap_const (const struct spa_pod *pod)
}
static WpSpaPod *
wp_spa_pod_new_property_wrap (WpSpaTypeTable table, guint32 key, guint32 flags,
wp_spa_pod_new_property_wrap (WpSpaIdTable table, guint32 key, guint32 flags,
struct spa_pod *pod)
{
WpSpaPod *self = wp_spa_pod_new (pod, WP_SPA_POD_PROPERTY, FLAG_NO_OWNERSHIP);
@ -231,7 +227,7 @@ wp_spa_pod_new_property_wrap (WpSpaTypeTable table, guint32 key, guint32 flags,
}
static WpSpaPod *
wp_spa_pod_new_control_wrap (guint32 offset, guint32 type,
wp_spa_pod_new_control_wrap (guint32 offset, enum spa_control_type type,
struct spa_pod *pod)
{
WpSpaPod *self = wp_spa_pod_new (pod, WP_SPA_POD_CONTROL, FLAG_NO_OWNERSHIP);
@ -244,7 +240,7 @@ wp_spa_pod_new_control_wrap (guint32 offset, guint32 type,
/* there is no use for these _const variants, but let's keep them just in case */
static WpSpaPod *
wp_spa_pod_new_property_wrap_const (WpSpaTypeTable table, guint32 key,
wp_spa_pod_new_property_wrap_const (WpSpaIdTable table, guint32 key,
guint32 flags, const struct spa_pod *pod)
{
WpSpaPod *self = wp_spa_pod_new (pod, WP_SPA_POD_PROPERTY,
@ -256,7 +252,7 @@ wp_spa_pod_new_property_wrap_const (WpSpaTypeTable table, guint32 key,
}
static WpSpaPod *
wp_spa_pod_new_control_wrap_const (guint32 offset, guint32 type,
wp_spa_pod_new_control_wrap_const (guint32 offset, enum spa_control_type type,
const struct spa_pod *pod)
{
WpSpaPod *self = wp_spa_pod_new (pod, WP_SPA_POD_CONTROL,
@ -274,7 +270,7 @@ wp_spa_pod_new_wrap_copy (const struct spa_pod *pod)
}
static WpSpaPod *
wp_spa_pod_new_property_wrap_copy (WpSpaTypeTable table, guint32 key,
wp_spa_pod_new_property_wrap_copy (WpSpaIdTable table, guint32 key,
guint32 flags, const struct spa_pod *pod)
{
WpSpaPod *self = wp_spa_pod_new (pod, WP_SPA_POD_PROPERTY, 0);
@ -285,7 +281,7 @@ wp_spa_pod_new_property_wrap_copy (WpSpaTypeTable table, guint32 key,
}
static WpSpaPod *
wp_spa_pod_new_control_wrap_copy (guint32 offset, guint32 type,
wp_spa_pod_new_control_wrap_copy (guint32 offset, enum spa_control_type type,
const struct spa_pod *pod)
{
WpSpaPod *self = wp_spa_pod_new (pod, WP_SPA_POD_CONTROL, 0);
@ -311,45 +307,43 @@ wp_spa_pod_get_spa_pod (const WpSpaPod *self)
}
/**
* wp_spa_pod_get_type_name:
* @self: a spa pod object
* wp_spa_pod_get_spa_type:
* @self: a spa pod
*
* Gets the type name of the spa pod object
* Gets the SPA type of the spa pod.
* If the pod is an object or pointer, this will return the derived
* object/pointer type directly.
* If the pod is an object property or a control, this will return the type
* of the contained value.
*
* Returns: the type name of the spa pod object
* Returns: the type of the spa pod
*/
const char *
wp_spa_pod_get_type_name (WpSpaPod *self)
WpSpaType
wp_spa_pod_get_spa_type (WpSpaPod *self)
{
const char *nick = NULL;
if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_BASIC, SPA_POD_TYPE (self->pod),
NULL, &nick, NULL))
g_return_val_if_reached (NULL);
return nick;
g_return_val_if_fail (self != NULL, WP_SPA_TYPE_INVALID);
if (wp_spa_pod_is_object (self) || wp_spa_pod_is_pointer (self))
return SPA_POD_OBJECT_TYPE (self->pod);
else
return SPA_POD_TYPE (self->pod);
}
const char *
wp_spa_pod_get_choice_type_name (WpSpaPod *self)
/**
* wp_spa_pod_get_choice_type:
* @self: a choice pod
*
* If the pod is a Choice, this gets the choice type
* (Range, Step, Enum, ...)
*
* Returns: the choice type of the choice pod
*/
WpSpaIdValue
wp_spa_pod_get_choice_type (WpSpaPod *self)
{
g_return_val_if_fail (wp_spa_pod_is_choice (self), NULL);
const char *nick = NULL;
if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_CHOICE,
SPA_POD_CHOICE_TYPE (self->pod), NULL, &nick, NULL))
g_return_val_if_reached (NULL);
return nick;
}
const char *
wp_spa_pod_get_object_type_name (WpSpaPod *self)
{
g_return_val_if_fail (wp_spa_pod_is_object (self), NULL);
const char *nick = NULL;
if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_BASIC,
SPA_POD_OBJECT_TYPE (self->pod), NULL, &nick, NULL))
g_return_val_if_reached (NULL);
return nick;
return wp_spa_id_value_from_number (
SPA_TYPE_INFO_Choice, SPA_POD_CHOICE_TYPE (self->pod));
}
/**
@ -609,7 +603,7 @@ wp_spa_pod_new_bytes (gconstpointer value, guint32 len)
/**
* wp_spa_pod_new_pointer:
* @type_name: the type name the pointer points to
* @type_name: the name of the type of the pointer
* @value: the pointer value
*
* Creates a spa pod of type pointer
@ -619,13 +613,12 @@ wp_spa_pod_new_bytes (gconstpointer value, guint32 len)
WpSpaPod *
wp_spa_pod_new_pointer (const char *type_name, gconstpointer value)
{
WpSpaType type = wp_spa_type_from_name (type_name);
g_return_val_if_fail (type != WP_SPA_TYPE_INVALID, NULL);
WpSpaPod *self = g_slice_new0 (WpSpaPod);
g_ref_count_init (&self->ref);
self->type = WP_SPA_POD_REGULAR;
guint32 type = 0;
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, type_name, &type,
NULL, NULL))
g_return_val_if_reached (NULL);
self->static_pod.pod_pointer = SPA_POD_INIT_Pointer (type, value);
self->pod = &self->static_pod.pod_pointer.pod;
return self;
@ -694,7 +687,7 @@ wp_spa_pod_new_fraction (guint32 num, guint32 denom)
/**
* wp_spa_pod_new_choice:
* @type_name: the type name of the choice type
* @choice_type: the name of the choice type ("Range", "Step", ...)
* @...: a list of choice values, followed by %NULL
*
* Creates a spa pod of type choice
@ -702,13 +695,13 @@ wp_spa_pod_new_fraction (guint32 num, guint32 denom)
* Returns: (transfer full): The new spa pod
*/
WpSpaPod *
wp_spa_pod_new_choice (const char *type_name, ...)
wp_spa_pod_new_choice (const char *choice_type, ...)
{
WpSpaPod *self;
va_list args;
va_start (args, type_name);
self = wp_spa_pod_new_choice_valist (type_name, args);
va_start (args, choice_type);
self = wp_spa_pod_new_choice_valist (choice_type, args);
va_end (args);
return self;
@ -716,7 +709,7 @@ wp_spa_pod_new_choice (const char *type_name, ...)
/**
* wp_spa_pod_new_choice_valist:
* @type_name: the type name of the choice type
* @choice_type: the name of the choice type ("Range", "Step", ...)
* @args: the variable arguments passed to wp_spa_pod_new_choice()
*
* This is the `va_list` version of wp_spa_pod_new_choice()
@ -724,9 +717,9 @@ wp_spa_pod_new_choice (const char *type_name, ...)
* Returns: (transfer full): The new spa pod
*/
WpSpaPod *
wp_spa_pod_new_choice_valist (const char *type_name, va_list args)
wp_spa_pod_new_choice_valist (const char *choice_type, va_list args)
{
g_autoptr (WpSpaPodBuilder) b = wp_spa_pod_builder_new_choice (type_name);
g_autoptr (WpSpaPodBuilder) b = wp_spa_pod_builder_new_choice (choice_type);
wp_spa_pod_builder_add_valist (b, args);
return wp_spa_pod_builder_end (b);
}
@ -838,8 +831,7 @@ wp_spa_pod_is_none (WpSpaPod *self)
gboolean
wp_spa_pod_is_boolean (WpSpaPod *self)
{
return self->type == WP_SPA_POD_REGULAR &&
spa_pod_is_bool (self->pod) ? TRUE : FALSE;
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_bool (self->pod);
}
/**
@ -1241,7 +1233,6 @@ wp_spa_pod_get_bytes (WpSpaPod *self, gconstpointer *value, guint32 *len)
/**
* wp_spa_pod_get_pointer:
* @self: the spa pod object
* @type_name: (out): the type name of the pointer value
* @value: (out): the pointer value
*
* Gets the pointer value and its type name of a spa pod object
@ -1249,21 +1240,13 @@ wp_spa_pod_get_bytes (WpSpaPod *self, gconstpointer *value, guint32 *len)
* Returns: TRUE if the value was obtained, FALSE otherwise
*/
gboolean
wp_spa_pod_get_pointer (WpSpaPod *self, const char **type_name,
gconstpointer *value)
wp_spa_pod_get_pointer (WpSpaPod *self, gconstpointer *value)
{
gboolean res;
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (type_name, FALSE);
g_return_val_if_fail (value, FALSE);
guint32 type = 0;
res = spa_pod_get_pointer (self->pod, &type, value) >= 0;
if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_BASIC, type, NULL, type_name,
NULL))
g_return_val_if_reached (FALSE);
return res;
return spa_pod_get_pointer (self->pod, &type, value) >= 0;
}
/**
@ -1440,7 +1423,7 @@ wp_spa_pod_set_double (WpSpaPod *self, double value)
/**
* wp_spa_pod_set_pointer:
* @self: the spa pod object
* @type_name: the type name the pointer points to
* @type_name: the name of the type of the pointer
* @value: the pointer value
*
* Sets a pointer value with its type name in the spa pod object.
@ -1451,16 +1434,13 @@ gboolean
wp_spa_pod_set_pointer (WpSpaPod *self, const char *type_name,
gconstpointer value)
{
guint32 id = 0;
WpSpaType type = wp_spa_type_from_name (type_name);
g_return_val_if_fail (wp_spa_pod_is_pointer (self), FALSE);
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
g_return_val_if_fail (type != WP_SPA_TYPE_INVALID, FALSE);
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, type_name, &id, NULL,
NULL))
g_return_val_if_reached (FALSE);
((struct spa_pod_pointer *)self->pod)->body.type = id;
((struct spa_pod_pointer *)self->pod)->body.type = type;
((struct spa_pod_pointer *)self->pod)->body.value = value;
return TRUE;
}
@ -1679,7 +1659,7 @@ wp_spa_pod_equal (WpSpaPod *self, WpSpaPod *pod)
switch (self->type) {
case WP_SPA_POD_PROPERTY:
if (self->static_pod.data_property.table != pod->static_pod.data_property.table ||
self->static_pod.data_property.table != pod->static_pod.data_property.table ||
self->static_pod.data_property.key != pod->static_pod.data_property.key ||
self->static_pod.data_property.flags != pod->static_pod.data_property.flags)
return FALSE;
break;
@ -1699,7 +1679,6 @@ wp_spa_pod_equal (WpSpaPod *self, WpSpaPod *pod)
/**
* wp_spa_pod_get_object:
* @self: the spa pod object
* @type_name: the type name of the object type
* @id_name: (out): the id name of the object
* @...: (out): the list of the object properties values, followed by %NULL
*
@ -1708,13 +1687,12 @@ wp_spa_pod_equal (WpSpaPod *self, WpSpaPod *pod)
* Returns: TRUE if the object properties values were obtained, FALSE otherwise
*/
gboolean
wp_spa_pod_get_object (WpSpaPod *self, const char *type_name,
const char **id_name, ...)
wp_spa_pod_get_object (WpSpaPod *self, const char **id_name, ...)
{
va_list args;
gboolean res;
va_start (args, id_name);
res = wp_spa_pod_get_object_valist (self, type_name, id_name, args);
res = wp_spa_pod_get_object_valist (self, id_name, args);
va_end (args);
return res;
}
@ -1722,7 +1700,6 @@ wp_spa_pod_get_object (WpSpaPod *self, const char *type_name,
/**
* wp_spa_pod_get_object_valist:
* @self: the spa pod object
* @type_name: the type name of the object type
* @id_name: (out): the id name of the object
* @args: (out): the variable arguments passed to wp_spa_pod_get_object()
*
@ -1731,13 +1708,11 @@ wp_spa_pod_get_object (WpSpaPod *self, const char *type_name,
* Returns: TRUE if the object properties values were obtained, FALSE otherwise
*/
gboolean
wp_spa_pod_get_object_valist (WpSpaPod *self, const char *type_name,
const char **id_name, va_list args)
wp_spa_pod_get_object_valist (WpSpaPod *self, const char **id_name, va_list args)
{
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (wp_spa_pod_is_object (self), FALSE);
g_autoptr (WpSpaPodParser) p = wp_spa_pod_parser_new_object (self, type_name,
id_name);
g_autoptr (WpSpaPodParser) p = wp_spa_pod_parser_new_object (self, id_name);
const gboolean res = wp_spa_pod_parser_get_valist (p, args);
wp_spa_pod_parser_end (p);
return res;
@ -1800,9 +1775,13 @@ wp_spa_pod_get_property (WpSpaPod *self, const char **key,
g_return_val_if_fail (self, FALSE);
g_return_val_if_fail (wp_spa_pod_is_property (self), FALSE);
if (key && !wp_spa_type_get_by_id (self->static_pod.data_property.table,
self->static_pod.data_property.key, NULL, key, NULL))
return FALSE;
if (key) {
WpSpaIdValue key_val = wp_spa_id_table_find_value (
self->static_pod.data_property.table,
self->static_pod.data_property.key);
g_return_val_if_fail (key_val != NULL, FALSE);
*key = wp_spa_id_value_short_name (key_val);
}
if (value)
*value = wp_spa_pod_new_wrap (self->pod);
@ -1813,7 +1792,7 @@ wp_spa_pod_get_property (WpSpaPod *self, const char **key,
* wp_spa_pod_get_control:
* @self: the spa pod object
* @offset: (out) (optional): the offset of the control
* @type_name: (out) (optional): the type name of the control
* @ctl_type: (out) (optional): the control type (Properties, Midi, ...)
* @value: (out) (optional): the spa pod value of the control
*
* Gets the offset, type name and spa pod value of a spa pod control
@ -1821,7 +1800,7 @@ wp_spa_pod_get_property (WpSpaPod *self, const char **key,
* Returns: TRUE if the value was obtained, FALSE otherwise
*/
gboolean
wp_spa_pod_get_control (WpSpaPod *self, guint32 *offset, const char **type_name,
wp_spa_pod_get_control (WpSpaPod *self, guint32 *offset, const char **ctl_type,
WpSpaPod **value)
{
g_return_val_if_fail (self, FALSE);
@ -1829,9 +1808,12 @@ wp_spa_pod_get_control (WpSpaPod *self, guint32 *offset, const char **type_name,
if (offset)
*offset = self->static_pod.data_control.offset;
if (type_name && !wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_CONTROL,
self->static_pod.data_control.type, NULL, type_name, NULL))
g_return_val_if_reached (FALSE);
if (ctl_type) {
WpSpaIdValue type_val = wp_spa_id_value_from_number (
SPA_TYPE_INFO_Control, self->static_pod.data_control.type);
g_return_val_if_fail (type_val != NULL, FALSE);
*ctl_type = wp_spa_id_value_short_name (type_val);
}
if (value)
*value = wp_spa_pod_new_wrap (self->pod);
@ -1917,30 +1899,27 @@ wp_spa_pod_builder_new_array (void)
/**
* wp_spa_pod_builder_new_choice:
* @type_name: the type name of the choice type
* @choice_type: the name of the choice type ("Range", "Step", ...)
*
* Creates a spa pod builder of type choice
*
* Returns: (transfer full): the new spa pod builder
*/
WpSpaPodBuilder *
wp_spa_pod_builder_new_choice (const char *type_name)
wp_spa_pod_builder_new_choice (const char *choice_type)
{
WpSpaPodBuilder *self = NULL;
guint32 type = 0;
WpSpaIdValue type = wp_spa_id_value_from_short_name (
SPA_TYPE_INFO_Choice, choice_type);
g_return_val_if_fail (type != NULL, NULL);
/* Construct the builder */
self = wp_spa_pod_builder_new (WP_SPA_POD_BUILDER_REALLOC_STEP_SIZE,
SPA_TYPE_Choice);
/* Find the choice type */
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_CHOICE, type_name, &type,
NULL, NULL))
g_return_val_if_reached (NULL);
/* Push the array */
spa_pod_builder_push_choice (&self->builder, &self->frame, type,
WP_SPA_TYPE_TABLE_CHOICE);
spa_pod_builder_push_choice (&self->builder, &self->frame,
wp_spa_id_value_number (type), 0);
return self;
}
@ -1958,25 +1937,27 @@ WpSpaPodBuilder *
wp_spa_pod_builder_new_object (const char *type_name, const char *id_name)
{
WpSpaPodBuilder *self = NULL;
guint32 type = 0;
guint32 id = 0;
/* Construct the builder */
self = wp_spa_pod_builder_new (WP_SPA_POD_BUILDER_REALLOC_STEP_SIZE,
SPA_TYPE_Object);
WpSpaType type;
WpSpaIdTable table;
WpSpaIdValue id;
/* Find the type */
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, type_name, &type,
NULL, &self->prop_table))
g_return_val_if_reached (NULL);
type = wp_spa_type_from_name (type_name);
g_return_val_if_fail (wp_spa_type_is_object (type), NULL);
/* Find the id */
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PARAM, id_name, &id, NULL,
NULL))
g_return_val_if_reached (NULL);
table = wp_spa_type_get_object_id_values_table (type);
g_return_val_if_fail (table != NULL, NULL);
id = wp_spa_id_table_find_value_from_short_name (table, id_name);
g_return_val_if_fail (id != NULL, NULL);
/* Construct the builder */
self = wp_spa_pod_builder_new (WP_SPA_POD_BUILDER_REALLOC_STEP_SIZE, type);
/* Push the object */
spa_pod_builder_push_object (&self->builder, &self->frame, type, id);
spa_pod_builder_push_object (&self->builder, &self->frame, type,
wp_spa_id_value_number (id));
return self;
}
@ -2145,10 +2126,8 @@ void
wp_spa_pod_builder_add_pointer (WpSpaPodBuilder *self, const char *type_name,
gconstpointer value)
{
guint32 type = 0;
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, type_name, &type,
NULL, NULL))
g_return_if_reached ();
WpSpaType type = wp_spa_type_from_name (type_name);
g_return_if_fail (wp_spa_type_parent (type) == SPA_TYPE_Pointer);
spa_pod_builder_pointer (&self->builder, type, value);
}
@ -2218,10 +2197,10 @@ wp_spa_pod_builder_add_pod (WpSpaPodBuilder *self, WpSpaPod *pod)
void
wp_spa_pod_builder_add_property (WpSpaPodBuilder *self, const char *key)
{
guint32 id = 0;
if (!wp_spa_type_get_by_nick (self->prop_table, key, &id, NULL, NULL))
g_return_if_reached ();
spa_pod_builder_prop (&self->builder, id, 0);
WpSpaIdTable table = wp_spa_type_get_values_table (self->type);
WpSpaIdValue id = wp_spa_id_table_find_value_from_short_name (table, key);
g_return_if_fail (id != NULL);
spa_pod_builder_prop (&self->builder, wp_spa_id_value_number (id), 0);
}
/**
@ -2249,11 +2228,10 @@ void
wp_spa_pod_builder_add_control (WpSpaPodBuilder *self, guint32 offset,
const char *type_name)
{
guint type = 0;
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_CONTROL, type_name, &type,
NULL, NULL))
g_return_if_reached ();
spa_pod_builder_control (&self->builder, offset, type);
WpSpaIdValue id = wp_spa_id_value_from_short_name (
SPA_TYPE_INFO_Control, type_name);
g_return_if_fail (id != NULL);
spa_pod_builder_control (&self->builder, offset, wp_spa_id_value_number (id));
}
/**
@ -2288,41 +2266,30 @@ wp_spa_pod_builder_add_valist (WpSpaPodBuilder *self, va_list args)
struct spa_pod_frame f;
gboolean choice;
switch (self->type) {
case SPA_TYPE_Object:
{
guint32 key = 0;
if (wp_spa_type_is_object (self->type)) {
const char *key_name = va_arg(args, const char *);
if (!key_name)
return;
if (!wp_spa_type_get_by_nick (self->prop_table, key_name, &key, NULL,
NULL))
g_return_if_reached ();
if (key == 0)
return;
WpSpaIdTable table = wp_spa_type_get_values_table (self->type);
WpSpaIdValue key =
wp_spa_id_table_find_value_from_short_name (table, key_name);
g_return_if_fail (key != NULL);
spa_pod_builder_prop (&self->builder, key, 0);
break;
spa_pod_builder_prop (&self->builder, wp_spa_id_value_number (key), 0);
}
case SPA_TYPE_Sequence:
{
else if (self->type == SPA_TYPE_Sequence) {
guint32 offset = va_arg(args, uint32_t);
guint32 type = 0;
if (offset == 0)
return;
const char *control_name = va_arg(args, const char *);
if (!control_name)
return;
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_CONTROL, control_name,
&type, NULL, NULL))
g_return_if_reached ();
if (type == 0)
return;
WpSpaIdValue type = wp_spa_id_value_from_short_name (
SPA_TYPE_INFO_Control, control_name);
g_return_if_fail (type != NULL);
spa_pod_builder_control (&self->builder, offset, type);
}
default:
break;
spa_pod_builder_control (&self->builder, offset,
wp_spa_id_value_number (type));
}
if ((format = va_arg(args, const char *)) == NULL)
@ -2376,9 +2343,10 @@ wp_spa_pod_builder_end (WpSpaPodBuilder *self)
ret->pod = spa_pod_builder_pop (&self->builder, &self->frame);
ret->builder = wp_spa_pod_builder_ref (self);
/* Also copy the property table if it is an object type */
if (ret->builder->type == SPA_TYPE_Object)
ret->static_pod.data_property.table = ret->builder->prop_table;
/* Also copy the specific object type if it is an object */
if (spa_pod_is_object (ret->pod))
ret->static_pod.data_property.table =
wp_spa_type_get_values_table (ret->builder->type);
return ret;
}
@ -2427,7 +2395,6 @@ wp_spa_pod_parser_new (WpSpaPod *pod, guint32 type)
/**
* wp_spa_pod_parser_new:
* @pod: the object spa pod to parse
* @type_name: the type name of the object type
* @id_name: the Id name of the object
*
* Creates an object spa pod parser. The @pod object must be valid for the
@ -2436,22 +2403,21 @@ wp_spa_pod_parser_new (WpSpaPod *pod, guint32 type)
* Returns: (transfer full): The new spa pod parser
*/
WpSpaPodParser *
wp_spa_pod_parser_new_object (WpSpaPod *pod, const char *type_name,
const char **id_name)
wp_spa_pod_parser_new_object (WpSpaPod *pod, const char **id_name)
{
WpSpaPodParser *self = NULL;
guint32 type = 0;
guint32 id = 0;
WpSpaType type = wp_spa_pod_get_spa_type (pod);
guint32 id = SPA_ID_INVALID;
g_return_val_if_fail (wp_spa_pod_is_object (pod), NULL);
self = wp_spa_pod_parser_new (pod, SPA_TYPE_Object);
if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, type_name, &type,
NULL, &self->prop_table))
g_return_val_if_reached (NULL);
self = wp_spa_pod_parser_new (pod, type);
spa_pod_parser_push_object (&self->parser, &self->frame, type, &id);
if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PARAM, id, NULL, id_name, NULL))
g_return_val_if_reached (NULL);
if (id_name) {
WpSpaIdTable table = wp_spa_type_get_object_id_values_table (type);
*id_name = wp_spa_id_value_short_name (
wp_spa_id_table_find_value (table, id));
}
return self;
}
@ -2611,7 +2577,6 @@ wp_spa_pod_parser_get_bytes (WpSpaPodParser *self, gconstpointer *value,
/**
* wp_spa_pod_parser_get_pointer:
* @self: the spa pod parser object
* @type_name: (out): the type name of the pointer value
* @value: (out): the pointer value
*
* Gets the pointer value and its type name from a spa pod parser object
@ -2619,20 +2584,11 @@ wp_spa_pod_parser_get_bytes (WpSpaPodParser *self, gconstpointer *value,
* Returns: TRUE if the value was obtained, FALSE otherwise
*/
gboolean
wp_spa_pod_parser_get_pointer (WpSpaPodParser *self, const char **type_name,
gconstpointer *value)
wp_spa_pod_parser_get_pointer (WpSpaPodParser *self, gconstpointer *value)
{
guint32 type = 0;
gboolean res;
g_return_val_if_fail (value, FALSE);
res = spa_pod_parser_get_pointer (&self->parser, &type, value) >= 0;
if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_BASIC, type, NULL, type_name,
NULL))
g_return_val_if_reached (FALSE);
return res;
guint32 type = 0;
return spa_pod_parser_get_pointer (&self->parser, &type, value) >= 0;
}
/**
@ -2759,20 +2715,19 @@ wp_spa_pod_parser_get_valist (WpSpaPodParser *self, va_list args)
const struct spa_pod *pod = NULL;
const char *format;
if (self->type == SPA_TYPE_Object) {
guint32 key = 0;
const struct spa_pod_object *object;
if (wp_spa_type_is_object (self->type)) {
const char *key_name = va_arg(args, const char *);
if (!key_name)
break;
if (!wp_spa_type_get_by_nick (self->prop_table, key_name, &key, NULL, NULL))
g_return_val_if_reached (FALSE);
if (key == 0)
break;
WpSpaIdTable table = wp_spa_type_get_values_table (self->type);
WpSpaIdValue key =
wp_spa_id_table_find_value_from_short_name (table, key_name);
g_return_val_if_fail (key != NULL, FALSE);
object = (const struct spa_pod_object *)spa_pod_parser_frame (
&self->parser, &self->frame);
prop = spa_pod_object_find_prop (object, prop, key);
const struct spa_pod_object *object = (const struct spa_pod_object *)
spa_pod_parser_frame (&self->parser, &self->frame);
prop = spa_pod_object_find_prop (object, prop,
wp_spa_id_value_number (key));
pod = prop ? &prop->value : NULL;
}
@ -2884,7 +2839,6 @@ wp_spa_pod_iterator_next_object (WpSpaPodIterator *self, GValue *item)
{
const struct spa_pod_object *pod_obj =
(const struct spa_pod_object *) self->pod->pod;
g_autoptr (WpSpaPod) pod = NULL;
if (!self->curr.prop)
self->curr.prop = spa_pod_prop_first (&pod_obj->body);
@ -2928,7 +2882,6 @@ wp_spa_pod_iterator_next_sequence (WpSpaPodIterator *self, GValue *item)
{
const struct spa_pod_sequence *pod_seq =
(const struct spa_pod_sequence *) self->pod->pod;
g_autoptr (WpSpaPod) pod = NULL;
if (!self->curr.control)
self->curr.control = spa_pod_control_first (&pod_seq->body);

View file

@ -13,6 +13,7 @@
#include "defs.h"
#include "iterator.h"
#include "spa-type.h"
G_BEGIN_DECLS
@ -45,19 +46,16 @@ WP_API
const struct spa_pod * wp_spa_pod_get_spa_pod (const WpSpaPod *self);
WP_API
const char *wp_spa_pod_get_type_name (WpSpaPod *self);
WpSpaType wp_spa_pod_get_spa_type (WpSpaPod *self);
WP_API
const char *wp_spa_pod_get_choice_type_name (WpSpaPod *self);
WP_API
const char *wp_spa_pod_get_object_type_name (WpSpaPod *self);
WpSpaIdValue wp_spa_pod_get_choice_type (WpSpaPod *self);
WP_API
WpSpaPod *wp_spa_pod_copy (WpSpaPod *other);
WP_API
gboolean wp_spa_pod_is_unique_owner ( WpSpaPod *self);
gboolean wp_spa_pod_is_unique_owner (WpSpaPod *self);
WP_API
WpSpaPod *wp_spa_pod_ensure_unique_owner (WpSpaPod *self);
@ -102,11 +100,11 @@ WP_API
WpSpaPod *wp_spa_pod_new_fraction (guint32 num, guint32 denom);
WP_API
WpSpaPod *wp_spa_pod_new_choice (const char *type_name, ...)
WpSpaPod *wp_spa_pod_new_choice (const char *choice_type, ...)
G_GNUC_NULL_TERMINATED;
WP_API
WpSpaPod *wp_spa_pod_new_choice_valist (const char *type_name, va_list args);
WpSpaPod *wp_spa_pod_new_choice_valist (const char *choice_type, va_list args);
WP_API
WpSpaPod *wp_spa_pod_new_object (const char *type_name, const char *id_name,
@ -208,8 +206,7 @@ gboolean wp_spa_pod_get_bytes (WpSpaPod *self, gconstpointer *value,
guint32 *len);
WP_API
gboolean wp_spa_pod_get_pointer (WpSpaPod *self, const char **type_name,
gconstpointer *value);
gboolean wp_spa_pod_get_pointer (WpSpaPod *self, gconstpointer *value);
WP_API
gboolean wp_spa_pod_get_fd (WpSpaPod *self, gint64 *value);
@ -260,11 +257,11 @@ WP_API
gboolean wp_spa_pod_equal (WpSpaPod *self, WpSpaPod *pod);
WP_API
gboolean wp_spa_pod_get_object (WpSpaPod *self, const char *type_name,
gboolean wp_spa_pod_get_object (WpSpaPod *self,
const char **id_name, ...) G_GNUC_NULL_TERMINATED;
WP_API
gboolean wp_spa_pod_get_object_valist (WpSpaPod *self, const char *type_name,
gboolean wp_spa_pod_get_object_valist (WpSpaPod *self,
const char **id_name, va_list args);
WP_API
@ -279,7 +276,7 @@ gboolean wp_spa_pod_get_property (WpSpaPod *self, const char **key,
WP_API
gboolean wp_spa_pod_get_control (WpSpaPod *self, guint32 *offset,
const char **type_name, WpSpaPod **value);
const char **ctl_type, WpSpaPod **value);
WP_API
WpSpaPod *wp_spa_pod_get_choice_child (WpSpaPod *self);
@ -314,7 +311,7 @@ WP_API
WpSpaPodBuilder *wp_spa_pod_builder_new_array (void);
WP_API
WpSpaPodBuilder *wp_spa_pod_builder_new_choice (const char *type_name);
WpSpaPodBuilder *wp_spa_pod_builder_new_choice (const char *choice_type);
WP_API
WpSpaPodBuilder *wp_spa_pod_builder_new_object (const char *type_name,
@ -380,7 +377,7 @@ void wp_spa_pod_builder_add_property_id (WpSpaPodBuilder *self, guint32 id);
WP_API
void wp_spa_pod_builder_add_control (WpSpaPodBuilder *self, guint32 offset,
const char *type_name);
const char *ctl_type);
WP_API
void wp_spa_pod_builder_add (WpSpaPodBuilder *self, ...) G_GNUC_NULL_TERMINATED;
@ -413,7 +410,7 @@ void wp_spa_pod_parser_unref (WpSpaPodParser *self);
WP_API
WpSpaPodParser *wp_spa_pod_parser_new_object (WpSpaPod *pod,
const char *type_name, const char **id_name);
const char **id_name);
WP_API
WpSpaPodParser *wp_spa_pod_parser_new_struct (WpSpaPod *pod);
@ -446,7 +443,7 @@ gboolean wp_spa_pod_parser_get_bytes (WpSpaPodParser *self,
WP_API
gboolean wp_spa_pod_parser_get_pointer (WpSpaPodParser *self,
const char **type_name, gconstpointer *value);
gconstpointer *value);
WP_API
gboolean wp_spa_pod_parser_get_fd (WpSpaPodParser *self, gint64 *value);

View file

@ -6,336 +6,706 @@
* SPDX-License-Identifier: MIT
*/
#define G_LOG_DOMAIN "wp-spa-type"
/**
* SECTION: spa-type
* @title: Spa Type Information
*
* Spa has a type system that is represented by a set of arrays that contain
* `spa_type_info` structures. This type system is simple, yet complex to
* work with for a couple of reasons.
*
* WirePlumber uses this API to access the spa type system, which makes some
* things easier to understand and work with. The main benefit of using this
* API is that it makes it easy to work with string representations of the
* types, allowing easier access from script bindings.
*
* ### Type hierarchy
*
* On the top level, there is a list of types like Int, Bool, String, Id, Object.
* These are called fundamental types (terms borrowed from #GType).
* Fundamental types can be derived and therefore we can have other types
* that represent specific enums or objects, for instance.
*
* Enum and flag types are all derived directly from `SPA_TYPE_Id`. These types
* may have a list of possible values that one can select from (enums)
* or combine (flags). These values are accessed with the #WpSpaIdValue API.
*
* Object types can have fields. All objects always have a special "id" field,
* whose type can be given by wp_spa_object_type_get_id_type() and optionally,
* they can also have other object-specific fields, which are also accessed
* with the #WpSpaIdValue API.
*/
#include <spa/utils/type-info.h>
#define G_LOG_DOMAIN "wp-spa-type"
#include "spa-type.h"
static gboolean
name_equal_func (gconstpointer a, gconstpointer b) {
const struct spa_type_info *ti = a;
const char *name = b;
return g_strcmp0 (ti->name, name) == 0;
#include <spa/utils/type-info.h>
#include <spa/debug/types.h>
#include <pipewire/pipewire.h>
static const WpSpaType SPA_TYPE_VENDOR_WirePlumber = 0x03000000;
static GArray *extra_types = NULL;
static GArray *extra_id_tables = NULL;
typedef struct {
const char *name;
const struct spa_type_info *values;
} WpSpaIdTableInfo;
static const WpSpaIdTableInfo static_id_tables[] = {
{ SPA_TYPE_INFO_Choice, spa_type_choice },
{ SPA_TYPE_INFO_Direction, spa_type_direction },
{ SPA_TYPE_INFO_ParamId, spa_type_param },
{ SPA_TYPE_INFO_MediaType, spa_type_media_type },
{ SPA_TYPE_INFO_MediaSubtype, spa_type_media_subtype },
{ SPA_TYPE_INFO_ParamAvailability, spa_type_param_availability },
{ SPA_TYPE_INFO_ParamPortConfigMode, spa_type_param_port_config_mode },
{ SPA_TYPE_INFO_VideoFormat, spa_type_video_format },
{ SPA_TYPE_INFO_AudioFormat, spa_type_audio_format },
{ SPA_TYPE_INFO_AudioFlags, spa_type_audio_flags },
{ SPA_TYPE_INFO_AudioChannel, spa_type_audio_channel },
{ SPA_TYPE_INFO_IO, spa_type_io },
{ SPA_TYPE_INFO_Control, spa_type_control },
{ SPA_TYPE_INFO_Data, spa_type_data_type },
{ SPA_TYPE_INFO_Meta, spa_type_meta_type },
{ SPA_TYPE_INFO_NodeEvent, spa_type_node_event_id },
{ SPA_TYPE_INFO_NodeCommand, spa_type_node_command_id },
{ NULL, NULL }
};
/**
* WpSpaType:
*/
GType wp_spa_type_get_type (void)
{
static volatile gsize id__volatile = 0;
if (g_once_init_enter (&id__volatile)) {
GType id = g_type_register_static_simple (
G_TYPE_UINT, g_intern_static_string ("WpSpaType"),
0, NULL, 0, NULL, 0);
g_once_init_leave (&id__volatile, id);
}
return id__volatile;
}
/**
* WpSpaIdTable:
*/
G_DEFINE_POINTER_TYPE (WpSpaIdTable, wp_spa_id_table)
/**
* WpSpaIdValue:
*/
G_DEFINE_POINTER_TYPE (WpSpaIdValue, wp_spa_id_value)
static const struct spa_type_info *
spa_type_find (const struct spa_type_info *table, GEqualFunc func,
gconstpointer data)
wp_spa_type_info_find_by_type (WpSpaType type)
{
for (guint32 i = 0; table[i].name; i++)
if (func (table + i, data))
return table + i;
const struct spa_type_info *info;
g_return_val_if_fail (type != WP_SPA_TYPE_INVALID, NULL);
g_return_val_if_fail (type != 0, NULL);
if (extra_types)
info = spa_debug_type_find (
(const struct spa_type_info *) extra_types->data, type);
else
info = spa_debug_type_find (SPA_TYPE_ROOT, type);
return info;
}
/* similar to spa_debug_type_find() and unlike spa_debug_type_find_type(),
which steps into id values / object fields */
static const struct spa_type_info *
_spa_type_find_by_name (const struct spa_type_info * info, const char * name)
{
const struct spa_type_info * res;
while (info->name) {
if (info->type == SPA_ID_INVALID) {
if (info->values && (res = _spa_type_find_by_name (info->values, name)))
return res;
}
if (strcmp (info->name, name) == 0)
return info;
info++;
}
return NULL;
}
static const struct spa_type_info *
spa_type_find_by_name (const struct spa_type_info *table, const char *name)
wp_spa_type_info_find_by_name (const gchar *name)
{
return spa_type_find (table, name_equal_func, name);
const struct spa_type_info *info = NULL;
g_return_val_if_fail (name != NULL, NULL);
if (extra_types)
info = _spa_type_find_by_name (
(const struct spa_type_info *) extra_types->data, name);
else
info = _spa_type_find_by_name (SPA_TYPE_ROOT, name);
return info;
}
struct type_info {
gboolean is_spa_type;
union {
const struct spa_type_info *spa;
struct {
guint32 type;
char *name;
} custom;
} info;
char *nick;
/**
* wp_spa_type_from_name:
* @name: the name to look up
*
* Looks up the type id from a given type name
*
* Returns: the corresponding type id or %WP_SPA_TYPE_INVALID if not found
*/
WpSpaType
wp_spa_type_from_name (const gchar *name)
{
const struct spa_type_info *info = wp_spa_type_info_find_by_name (name);
return info ? info->type : WP_SPA_TYPE_INVALID;
}
/**
* wp_spa_type_parent:
* @type: a type id
*
* Returns: the direct parent type of the given @type; if the type is
* fundamental (i.e. has no parent), the returned type is the same as @type
*/
WpSpaType
wp_spa_type_parent (WpSpaType type)
{
const struct spa_type_info *info = wp_spa_type_info_find_by_type (type);
return info ? info->parent : WP_SPA_TYPE_INVALID;
}
/**
* wp_spa_type_name:
* @type: a type id
*
* Returns: the complete name of the given @type or %NULL if @type is invalid
*/
const gchar *
wp_spa_type_name (WpSpaType type)
{
const struct spa_type_info *info = wp_spa_type_info_find_by_type (type);
return info ? info->name : NULL;
}
/**
* wp_spa_type_is_fundamental:
* @type: a type id
*
* Returns: %TRUE if the @type has no parent, %FALSE otherwise
*/
gboolean
wp_spa_type_is_fundamental (WpSpaType type)
{
const struct spa_type_info *info = wp_spa_type_info_find_by_type (type);
return info ? (info->type == info->parent) : FALSE;
}
/**
* wp_spa_type_is_id:
* @type: a type id
*
* Returns: %TRUE if the @type is a SPA_TYPE_Id, %FALSE otherwise
*/
gboolean
wp_spa_type_is_id (WpSpaType type)
{
const struct spa_type_info *info = wp_spa_type_info_find_by_type (type);
return info ? (info->parent == SPA_TYPE_Id) : FALSE;
}
/**
* wp_spa_type_is_object:
* @type: a type id
*
* Returns: %TRUE if the @type is a SPA_TYPE_Object, %FALSE otherwise
*/
gboolean
wp_spa_type_is_object (WpSpaType type)
{
const struct spa_type_info *info = wp_spa_type_info_find_by_type (type);
return info ? (info->parent == SPA_TYPE_Object) : FALSE;
}
/**
* wp_spa_type_get_object_id_values_table:
* @type: the type id of an object type
*
* Object pods (see #WpSpaPod) always have a special "id" field along with
* other fields that can be defined. This "id" field can only store values
* of a specific `SPA_TYPE_Id` type. This function returns the table that
* contains the possible values for that field.
*
* Returns: the table with the values that can be stored in the special "id"
* field of an object of the given @type
*/
WpSpaIdTable
wp_spa_type_get_object_id_values_table (WpSpaType type)
{
const struct spa_type_info *info = wp_spa_type_info_find_by_type (type);
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (info->parent == SPA_TYPE_Object, NULL);
g_return_val_if_fail (info->values != NULL, NULL);
g_return_val_if_fail (info->values->name != NULL, NULL);
g_return_val_if_fail (info->values->parent == SPA_TYPE_Id, NULL);
return info->values->values;
}
/**
* wp_spa_type_get_values_table:
* @type: a type id
*
* Returns: the associated #WpSpaIdTable that contains possible
* values or object fields for this type, or %NULL
*/
WpSpaIdTable
wp_spa_type_get_values_table (WpSpaType type)
{
const struct spa_type_info *info = wp_spa_type_info_find_by_type (type);
g_return_val_if_fail (info != NULL, NULL);
return info->values;
}
struct spa_type_info_iterator_data
{
const struct spa_type_info *base;
const struct spa_type_info *cur;
};
static struct type_info *
type_info_new_spa (const struct spa_type_info *info, const char* nick) {
struct type_info *ti = g_slice_new0 (struct type_info);
ti->is_spa_type = TRUE;
ti->info.spa = info;
ti->nick = g_strdup (nick);
return ti;
}
static struct type_info *
type_info_new_custom (uint32_t type, const char *name, const char* nick) {
struct type_info *ti = g_slice_new0 (struct type_info);
ti->is_spa_type = FALSE;
ti->info.custom.type = type;
ti->info.custom.name = g_strdup (name);
ti->nick = g_strdup (nick);
return ti;
}
static void
type_info_free (struct type_info *ti) {
g_return_if_fail (ti);
if (!ti->is_spa_type)
g_clear_pointer (&ti->info.custom.name, g_free);
g_clear_pointer (&ti->nick, g_free);
g_slice_free (struct type_info, ti);
spa_type_info_iterator_reset (WpIterator *it)
{
struct spa_type_info_iterator_data *it_data = wp_iterator_get_user_data (it);
it_data->cur = it_data->base;
}
struct spa_type_table_data {
const struct spa_type_info *spa_table;
guint32 last_id;
GPtrArray *info_array;
GHashTable *id_table;
GHashTable *nick_table;
};
static struct spa_type_table_data s_tables [WP_SPA_TYPE_TABLE_LAST] = {
[WP_SPA_TYPE_TABLE_BASIC] = {spa_types, SPA_TYPE_VENDOR_Other, NULL, NULL, NULL },
[WP_SPA_TYPE_TABLE_PARAM] = {spa_type_param, SPA_N_ELEMENTS (spa_type_param), NULL, NULL, NULL, },
[WP_SPA_TYPE_TABLE_PROPS] = {spa_type_props, SPA_PROP_START_CUSTOM, NULL, NULL, NULL, },
[WP_SPA_TYPE_TABLE_PROP_INFO] = {spa_type_prop_info, SPA_N_ELEMENTS (spa_type_prop_info), NULL, NULL, NULL, },
[WP_SPA_TYPE_TABLE_FORMAT] = {spa_type_format, SPA_N_ELEMENTS (spa_type_format), NULL, NULL, NULL, },
[WP_SPA_TYPE_TABLE_PARAM_PORT_CONFIG] = {spa_type_param_port_config, SPA_N_ELEMENTS (spa_type_param_port_config), NULL, NULL, NULL, },
[WP_SPA_TYPE_TABLE_PARAM_PROFILE] = {spa_type_param_profile, SPA_N_ELEMENTS (spa_type_param_profile), NULL, NULL, NULL, },
[WP_SPA_TYPE_TABLE_CONTROL] = {spa_type_control, SPA_CONTROL_LAST, NULL, NULL, NULL, },
[WP_SPA_TYPE_TABLE_CHOICE] = {spa_type_choice, SPA_N_ELEMENTS (spa_type_choice), NULL, NULL, NULL, },
[WP_SPA_TYPE_TABLE_AUDIO_CHANNEL] = {spa_type_audio_channel, SPA_N_ELEMENTS (spa_type_audio_channel), NULL, NULL, NULL, },
};
static WpSpaTypeTable
wp_spa_type_table_find_by_spa_table (const struct spa_type_info *spa_table)
static gboolean
spa_type_info_iterator_next (WpIterator *it, GValue *item)
{
for (guint32 i = 0; i < WP_SPA_TYPE_TABLE_LAST; i++)
if (s_tables[i].spa_table == spa_table)
return i;
return 0;
}
struct spa_type_info_iterator_data *it_data = wp_iterator_get_user_data (it);
/**
* wp_spa_type_init:
* @register_spa: whether spa types will be registered or not
*
* Initializes the spa type registry
*/
void
wp_spa_type_init (gboolean register_spa)
{
/* Init the array and hash tables */
for (guint32 i = 0; i < WP_SPA_TYPE_TABLE_LAST; i++) {
struct spa_type_table_data *td = s_tables + i;
if (!td->info_array)
td->info_array = g_ptr_array_new_with_free_func ((GDestroyNotify)
type_info_free);
if (!td->id_table)
td->id_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
NULL, NULL);
if (!td->nick_table)
td->nick_table = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, NULL);
if (it_data->cur->name) {
g_value_init (item, WP_TYPE_SPA_ID_VALUE);
g_value_set_pointer (item, (gpointer) it_data->cur);
it_data->cur++;
return TRUE;
}
return FALSE;
}
/* Register the spa types if requested */
if (register_spa) {
for (guint32 i = 0; i < WP_SPA_TYPE_TABLE_LAST; i++) {
struct spa_type_table_data *td = s_tables + i;
for (guint32 j = 0; td->spa_table && td->spa_table[j].name; j++) {
const struct spa_type_info *t = td->spa_table + j;
const char *nick = strrchr (t->name, ':');
if (nick && strlen (nick) > 1)
wp_spa_type_register (i, t->name, nick + 1);
}
static gboolean
spa_type_info_iterator_fold (WpIterator *it, WpIteratorFoldFunc func,
GValue *ret, gpointer data)
{
struct spa_type_info_iterator_data *it_data = wp_iterator_get_user_data (it);
const struct spa_type_info *cur, *base;
cur = base = it_data->base;
while (cur->name) {
g_auto (GValue) item = G_VALUE_INIT;
g_value_init (&item, WP_TYPE_SPA_ID_VALUE);
g_value_set_pointer (&item, (gpointer) cur);
if (!func (&item, ret, data))
return FALSE;
cur++;
}
return TRUE;
}
static const WpIteratorMethods spa_type_info_iterator_methods = {
.version = WP_ITERATOR_METHODS_VERSION,
.reset = spa_type_info_iterator_reset,
.next = spa_type_info_iterator_next,
.fold = spa_type_info_iterator_fold,
};
WpSpaIdTable
wp_spa_id_table_from_name (const gchar *name)
{
g_return_val_if_fail (name != NULL, NULL);
const WpSpaIdTableInfo *info = NULL;
/* first look in dynamic id tables */
if (extra_id_tables) {
info = (const WpSpaIdTableInfo *) extra_id_tables->data;
while (info && info->name) {
if (strcmp (info->name, name) == 0)
return info->values;
info++;
}
}
/* then look at the well-known static ones */
info = static_id_tables;
while (info && info->name) {
if (strcmp (info->name, name) == 0)
return info->values;
info++;
}
/* then look into types, hoping to find an object type */
const struct spa_type_info *tinfo = wp_spa_type_info_find_by_name (name);
return tinfo ? tinfo->values : NULL;
}
/**
* wp_spa_type_deinit:
* wp_spa_id_table_iterate:
* @type: the id table
*
* Deinitializes the spa type registry
* This function returns an iterator that allows you to iterate through the
* values associated with this table.
* The items in the iterator are of type #WpSpaIdValue.
*
* Returns: a #WpIterator that iterates over #WpSpaIdValue items
*/
WpIterator *
wp_spa_id_table_iterate (WpSpaIdTable table)
{
g_return_val_if_fail (table != NULL, NULL);
WpIterator *it = wp_iterator_new (&spa_type_info_iterator_methods,
sizeof (struct spa_type_info_iterator_data));
struct spa_type_info_iterator_data *it_data = wp_iterator_get_user_data (it);
it_data->base = (const struct spa_type_info *) table;
it_data->cur = it_data->base;
return it;
}
WpSpaIdValue
wp_spa_id_table_find_value (WpSpaIdTable table, guint value)
{
g_return_val_if_fail (table != NULL, NULL);
const struct spa_type_info *info = table;
while (info && info->name) {
if (info->type == value)
return info;
info++;
}
return NULL;
}
WpSpaIdValue
wp_spa_id_table_find_value_from_name (WpSpaIdTable table, const gchar * name)
{
g_return_val_if_fail (table != NULL, NULL);
const struct spa_type_info *info = table;
while (info && info->name) {
if (!strcmp (info->name, name))
return info;
info++;
}
return NULL;
}
WpSpaIdValue
wp_spa_id_table_find_value_from_short_name (WpSpaIdTable table,
const gchar * short_name)
{
g_return_val_if_fail (table != NULL, NULL);
const struct spa_type_info *info = table;
while (info && info->name) {
if (!strcmp (spa_debug_type_short_name (info->name), short_name))
return info;
info++;
}
return NULL;
}
static WpSpaIdTable
wp_spa_id_name_find_id_table (const gchar * name)
{
WpSpaIdTable table = NULL;
g_autofree gchar *parent_name = g_strdup (name);
gchar *h;
if ((h = strrchr(parent_name, ':')) != NULL) {
/* chop the enum name to get the type, ex:
Spa:Enum:Direction:Input -> Spa:Enum:Direction */
*h = '\0';
table = wp_spa_id_table_from_name (parent_name);
/* in some cases, the parent name is one layer further up, ex:
Spa:Pod:Object:Param:Format:Audio:rate -> Spa:Pod:Object:Param:Format */
if (!table && (h = strrchr(parent_name, ':')) != NULL) {
*h = '\0';
table = wp_spa_id_table_from_name (parent_name);
}
}
return table;
}
/**
* wp_spa_id_value_from_name:
* @name: the full name of an id value
*
* Looks up an id value (enum, flag or object field) directly from its full
* name. For instance, "Spa:Enum:Direction:Input" will resolve to the
* id value that represents "Input" in the "Spa:Enum:Direction" enum.
*
* Returns: the id value for @name, or %NULL if no such id value was found
*/
WpSpaIdValue
wp_spa_id_value_from_name (const gchar * name)
{
g_return_val_if_fail (name != NULL, NULL);
WpSpaIdTable table = wp_spa_id_name_find_id_table (name);
return wp_spa_id_table_find_value_from_name (table, name);
}
/**
* wp_spa_id_value_from_short_name:
* @table_name: the name of the #WpSpaIdTable to look up the value in
* @short_name: the short name of the value to look up
*
* Looks up an id value given its container @table_name and its @short_name
*
* Returns: the id value or %NULL if it was not found
*/
WpSpaIdValue
wp_spa_id_value_from_short_name (const gchar * table_name,
const gchar * short_name)
{
g_return_val_if_fail (table_name != NULL, NULL);
g_return_val_if_fail (short_name != NULL, NULL);
WpSpaIdTable table = wp_spa_id_table_from_name (table_name);
return wp_spa_id_table_find_value_from_short_name (table, short_name);
}
/**
* wp_spa_id_value_from_number:
* @table_name: the name of the #WpSpaIdTable to look up the value in
* @id: the numeric representation of the value to look up
*
* Looks up an id value given its container @table_name and its numeric
* representation, @id
*
* Returns: the id value or %NULL if it was not found
*/
WpSpaIdValue
wp_spa_id_value_from_number (const gchar * table_name, guint id)
{
g_return_val_if_fail (table_name != NULL, NULL);
WpSpaIdTable table = wp_spa_id_table_from_name (table_name);
return wp_spa_id_table_find_value (table, id);
}
/**
* wp_spa_id_value_number:
* @id: an id value
*
* Returns: the numeric representation of this id value
*/
guint
wp_spa_id_value_number (WpSpaIdValue id)
{
g_return_val_if_fail (id != NULL, -1);
const struct spa_type_info *info = id;
return info->type;
}
/**
* wp_spa_id_value_name:
* @id: an id value
*
* Returns: the full name of this id value
*/
const gchar *
wp_spa_id_value_name (WpSpaIdValue id)
{
g_return_val_if_fail (id != NULL, NULL);
const struct spa_type_info *info = id;
return info->name;
}
/**
* wp_spa_id_value_short_name:
* @id: an id value
*
* Returns: the short name of this id value
*/
const gchar *
wp_spa_id_value_short_name (WpSpaIdValue id)
{
g_return_val_if_fail (id != NULL, NULL);
const struct spa_type_info *info = id;
return spa_debug_type_short_name (info->name);
}
/**
* wp_spa_id_value_get_value_type
* @id: an id value
* @table: (out) (optional): the associated #WpSpaIdTable
*
* Returns the value type associated with this #WpSpaIdValue. This information
* is useful when @id represents an object field, which can take a value
* of an arbitrary type.
*
* When the returned type is (or is derived from) `SPA_TYPE_Id` or
* `SPA_TYPE_Object`, @table is set to point to the #WpSpaIdTable that contains
* the possible Id values / object fields.
*
* Returns: the value type associated with @id
*/
WpSpaType
wp_spa_id_value_get_value_type (WpSpaIdValue id, WpSpaIdTable * table)
{
g_return_val_if_fail (id != NULL, WP_SPA_TYPE_INVALID);
const struct spa_type_info *info = id;
if (table) {
/* info->values has different semantics on Array types */
if (info->values && info->parent != SPA_TYPE_Array) {
*table = info->values;
}
/* derived object types normally don't have info->values directly set,
so we need to look them up */
else if (wp_spa_type_is_object (info->parent)) {
WpSpaIdTable t = wp_spa_type_get_values_table (info->parent);
if (t) *table = t;
}
}
return info->parent;
}
/**
* wp_spa_id_value_array_get_item_type:
* @id: an id value
* @table: (out) (optional): the associated #WpSpaIdTable
*
* If the value type of @id is `SPA_TYPE_Array`, this function returns the
* type that is allowed to be contained inside the array.
*
* When the returned type is (or is derived from) `SPA_TYPE_Id` or
* `SPA_TYPE_Object`, @table is set to point to the #WpSpaIdTable that contains
* the possible Id values / object fields.
*
* Returns: the type that is allowed in the array, if @id represents
* an object field that takes an array as value
*/
WpSpaType
wp_spa_id_value_array_get_item_type (WpSpaIdValue id, WpSpaIdTable * table)
{
g_return_val_if_fail (id != NULL, WP_SPA_TYPE_INVALID);
const struct spa_type_info *info = id;
g_return_val_if_fail (info->parent == SPA_TYPE_Array, WP_SPA_TYPE_INVALID);
return info->values ?
wp_spa_id_value_get_value_type (info->values, table) :
WP_SPA_TYPE_INVALID;
}
/**
* wp_spa_dynamic_type_init:
*
* Initializes the spa dynamic type registry.
* This allows registering new spa types at runtime. The spa type system
* still works if this function is not called.
*
* Normally called by wp_init() when %WP_INIT_SPA_TYPES is passed in its flags.
*/
void
wp_spa_type_deinit (void)
wp_spa_dynamic_type_init (void)
{
for (guint32 i = 0; i < WP_SPA_TYPE_TABLE_LAST; i++) {
struct spa_type_table_data *td = s_tables + i;
g_clear_pointer (&td->info_array, g_ptr_array_unref);
g_clear_pointer (&td->id_table, g_hash_table_unref);
g_clear_pointer (&td->nick_table, g_hash_table_unref);
}
extra_types = g_array_new (TRUE, FALSE, sizeof (struct spa_type_info));
extra_id_tables = g_array_new (TRUE, FALSE, sizeof (WpSpaIdTableInfo));
/* init to chain up to spa types */
struct spa_type_info info = {
SPA_ID_INVALID, SPA_ID_INVALID, "spa_types", SPA_TYPE_ROOT
};
g_array_append_val (extra_types, info);
}
/**
* wp_spa_type_get_table_size:
* @table: the table
* wp_spa_dynamic_type_deinit:
*
* Gets the number of registered types in a given table
*
* Returns: The number of registered types
* Deinitializes the spa type registry.
* You do not need to ever call this, unless you want to free memory at the
* end of the execution of a test, so that it doesn't show as leaked in
* the memory profiler.
*/
size_t
wp_spa_type_get_table_size (WpSpaTypeTable table)
void
wp_spa_dynamic_type_deinit (void)
{
struct spa_type_table_data *td = NULL;
g_return_val_if_fail (table < WP_SPA_TYPE_TABLE_LAST, 0);
/* Get the table data */
td = s_tables + table;
return td->info_array->len;
g_clear_pointer (&extra_types, g_array_unref);
g_clear_pointer (&extra_id_tables, g_array_unref);
}
/**
* wp_spa_type_register:
* @table: the table
* wp_spa_dynamic_type_register:
* @name: the name of the type
* @nick: the nick name of the type
* @parent: the parent type
* @values: an array of `spa_type_info` that contains the values of the type,
* used only for Object types
*
* Registers a type name with a nickname in the registry
* Registers an additional type in the spa type system.
* This is useful to add a custom pod object type.
*
* Returns: TRUE if the type could be registered, FALSE otherwise
* Note that both @name and @values must be statically allocated, or
* otherwise guaranteed to be kept in memory until wp_spa_dynamic_type_deinit()
* is called. No memory copy is done by this function.
*
* Returns: the new type
*/
gboolean
wp_spa_type_register (WpSpaTypeTable table, const char *name, const char *nick)
WpSpaType
wp_spa_dynamic_type_register (const gchar *name, WpSpaType parent,
const struct spa_type_info * values)
{
struct spa_type_table_data *td = NULL;
const struct spa_type_info *spa_info = NULL;
struct type_info *info = NULL;
guint32 id;
g_return_val_if_fail (table < WP_SPA_TYPE_TABLE_LAST, FALSE);
g_return_val_if_fail (name, FALSE);
g_return_val_if_fail (nick, FALSE);
/* Get the table data */
td = s_tables + table;
/* Return false if the nick already exists in the nick table */
if (g_hash_table_contains (td->nick_table, nick))
return FALSE;
/* Add the type in the custom table */
spa_info = spa_type_find_by_name (td->spa_table, name);
if (spa_info) {
id = spa_info->type;
info = type_info_new_spa (spa_info, nick);
} else {
id = ++td->last_id;
info = type_info_new_custom (id, name, nick);
}
g_ptr_array_add (td->info_array, info);
/* Insert the id and nick in the hash tables */
return g_hash_table_insert (td->id_table, GUINT_TO_POINTER (id), info) &&
g_hash_table_insert (td->nick_table, g_strdup (nick), info);
struct spa_type_info info;
info.type = SPA_TYPE_VENDOR_WirePlumber + extra_types->len;
info.name = name;
info.parent = parent;
info.values = values;
g_array_append_val (extra_types, info);
return info.type;
}
/**
* wp_spa_type_unregister:
* @table: the table
* @nick: the nick name of the type
* wp_spa_dynamic_id_table_register:
* @name: the name of the id table
* @values: an array of `spa_type_info` that contains the values of the table
*
* Unregisters a type given its nick name
* Registers an additional #WpSpaIdTable in the spa type system.
* This is useful to add custom enumeration types.
*
* Note that both @name and @values must be statically allocated, or
* otherwise guaranteed to be kept in memory until wp_spa_dynamic_type_deinit()
* is called. No memory copy is done by this function.
*
* Returns: the new table
*/
void
wp_spa_type_unregister (WpSpaTypeTable table, const char *nick)
WpSpaIdTable
wp_spa_dynamic_id_table_register (const gchar *name,
const struct spa_type_info * values)
{
struct spa_type_table_data *td = NULL;
struct type_info *info = NULL;
guint32 id;
g_return_if_fail (table < WP_SPA_TYPE_TABLE_LAST);
g_return_if_fail (nick);
/* Get the table data */
td = s_tables + table;
/* Lookup the info by nick */
info = g_hash_table_lookup (td->nick_table, nick);
if (!info)
return;
/* Get id */
id = info->is_spa_type ? info->info.spa->type : info->info.custom.type;
/* Remove info from hash tables */
g_hash_table_remove (td->nick_table, nick);
g_hash_table_remove (td->id_table, GUINT_TO_POINTER (id));
/* Remove info from array */
g_ptr_array_remove_fast (td->info_array, info);
}
/**
* wp_spa_type_get_by_nick:
* @table: the table
* @nick: the nick name of the type
* @id: (out) (optional): the id of the type
* @name: (out) (optional): the name of the type
* @values_table: (out) (optional): the values table of the type
*
* Gets the id and name of the registered type given its nick name
*
* Returns: TRUE if the type was found, FALSE otherwise
*/
gboolean
wp_spa_type_get_by_nick (WpSpaTypeTable table, const char *nick,
guint32 *id, const char **name, WpSpaTypeTable *values_table)
{
struct spa_type_table_data *td = NULL;
const struct type_info *info = NULL;
g_return_val_if_fail (table < WP_SPA_TYPE_TABLE_LAST, FALSE);
/* Make sure nick is valid */
if (!nick)
return FALSE;
/* Get the table data */
td = s_tables + table;
/* Lookup the info by nick */
info = g_hash_table_lookup (td->nick_table, nick);
if (!info)
return FALSE;
if (id)
*id = info->is_spa_type ? info->info.spa->type : info->info.custom.type;
if (name)
*name = info->is_spa_type ? info->info.spa->name : info->info.custom.name;
if (values_table && info->is_spa_type)
*values_table = wp_spa_type_table_find_by_spa_table (info->info.spa->values);
return TRUE;
}
/**
* wp_spa_type_get_by_id:
* @table: the table
* @id: the id of the type
* @name: (out) (optional): the name of the type
* @nick: (out) (optional): the nick name of the type
* @values_table: (out) (optional): the values table of the type
*
* Gets the name and nick name of the registered type given its id
*
* Returns: TRUE if the type was found, FALSE otherwise
*/
gboolean
wp_spa_type_get_by_id (WpSpaTypeTable table, guint32 id,
const char **name, const char **nick, WpSpaTypeTable *values_table)
{
struct spa_type_table_data *td = NULL;
const struct type_info *info = NULL;
g_return_val_if_fail (table < WP_SPA_TYPE_TABLE_LAST, FALSE);
/* Get the table data */
td = s_tables + table;
/* Lookup the info by id */
info = g_hash_table_lookup (td->id_table, GUINT_TO_POINTER (id));
if (!info)
return FALSE;
if (name)
*name = info->is_spa_type ? info->info.spa->name : info->info.custom.name;
if (nick)
*nick = info->nick;
if (values_table && info->is_spa_type)
*values_table = wp_spa_type_table_find_by_spa_table (info->info.spa->values);
return TRUE;
WpSpaIdTableInfo info;
info.name = name;
info.values = values;
g_array_append_val (extra_id_tables, info);
return values;
}

View file

@ -9,63 +9,121 @@
#ifndef __WIREPLUMBER_SPA_TYPE_H__
#define __WIREPLUMBER_SPA_TYPE_H__
#include <gio/gio.h>
#include "defs.h"
#include "iterator.h"
G_BEGIN_DECLS
/**
* WpSpaTypeTable:
* @WP_SPA_TYPE_TABLE_BASIC: The basic type table
* @WP_SPA_TYPE_TABLE_PARAM: The param type table (used as object id)
* @WP_SPA_TYPE_TABLE_PROPS: The object properties type table
* @WP_SPA_TYPE_TABLE_PROP_INFO: The object property info type table
* @WP_SPA_TYPE_TABLE_CONTROL: The sequence control type table
* @WP_SPA_TYPE_TABLE_CHOICE: The choice type table
* @WP_SPA_TYPE_TABLE_FORMAT: The object format type table
* @WP_SPA_TYPE_TABLE_PARAM_PORT_CONFIG: The object param port config type table
* @WP_SPA_TYPE_TABLE_PARAM_PROFILE: The sequence control type table
* @WP_SPA_TYPE_TABLE_AUDIO_CHANNEL: The audio channel type table
*
* The diferent tables (namespaces) the registry has.
*/
typedef enum {
WP_SPA_TYPE_TABLE_BASIC = 0,
WP_SPA_TYPE_TABLE_PARAM,
WP_SPA_TYPE_TABLE_PROPS,
WP_SPA_TYPE_TABLE_PROP_INFO,
WP_SPA_TYPE_TABLE_CONTROL,
WP_SPA_TYPE_TABLE_CHOICE,
WP_SPA_TYPE_TABLE_FORMAT,
WP_SPA_TYPE_TABLE_PARAM_PORT_CONFIG,
WP_SPA_TYPE_TABLE_PARAM_PROFILE,
WP_SPA_TYPE_TABLE_AUDIO_CHANNEL,
WP_SPA_TYPE_TABLE_LAST,
} WpSpaTypeTable;
typedef guint32 WpSpaType;
typedef gconstpointer WpSpaIdTable;
typedef gconstpointer WpSpaIdValue;
struct spa_type_info;
/* WpSpaType */
#define WP_TYPE_SPA_TYPE (wp_spa_type_get_type ())
WP_API
GType wp_spa_type_get_type (void);
static const WpSpaType WP_SPA_TYPE_INVALID = 0xffffffff;
WP_API
void wp_spa_type_init (gboolean register_spa);
WpSpaType wp_spa_type_from_name (const gchar *name);
WP_API
void wp_spa_type_deinit (void);
WpSpaType wp_spa_type_parent (WpSpaType type);
WP_API
size_t wp_spa_type_get_table_size (WpSpaTypeTable table);
const gchar * wp_spa_type_name (WpSpaType type);
WP_API
gboolean wp_spa_type_register (WpSpaTypeTable table, const char *name,
const char *nick);
gboolean wp_spa_type_is_fundamental (WpSpaType type);
WP_API
void wp_spa_type_unregister (WpSpaTypeTable table, const char *nick);
gboolean wp_spa_type_is_id (WpSpaType type);
WP_API
gboolean wp_spa_type_get_by_nick (WpSpaTypeTable table, const char *nick,
guint32 *id, const char **name, WpSpaTypeTable *values_table);
gboolean wp_spa_type_is_object (WpSpaType type);
WP_API
gboolean wp_spa_type_get_by_id (WpSpaTypeTable table, guint32 id,
const char **name, const char **nick, WpSpaTypeTable *values_table);
WpSpaIdTable wp_spa_type_get_object_id_values_table (WpSpaType type);
WP_API
WpSpaIdTable wp_spa_type_get_values_table (WpSpaType type);
/* WpSpaIdTable */
#define WP_TYPE_SPA_ID_TABLE (wp_spa_id_table_get_type ())
WP_API
GType wp_spa_id_table_get_type (void);
WP_API
WpSpaIdTable wp_spa_id_table_from_name (const gchar *name);
WP_API
WpIterator * wp_spa_id_table_iterate (WpSpaIdTable table);
WP_API
WpSpaIdValue wp_spa_id_table_find_value (WpSpaIdTable table, guint value);
WP_API
WpSpaIdValue wp_spa_id_table_find_value_from_name (WpSpaIdTable table,
const gchar * name);
WP_API
WpSpaIdValue wp_spa_id_table_find_value_from_short_name (WpSpaIdTable table,
const gchar * short_name);
/* WpSpaIdValue */
#define WP_TYPE_SPA_ID_VALUE (wp_spa_id_value_get_type ())
WP_API
GType wp_spa_id_value_get_type (void);
WP_API
WpSpaIdValue wp_spa_id_value_from_name (const gchar * name);
WP_API
WpSpaIdValue wp_spa_id_value_from_short_name (const gchar * table_name,
const gchar * short_name);
WP_API
WpSpaIdValue wp_spa_id_value_from_number (const gchar * table_name, guint id);
WP_API
guint wp_spa_id_value_number (WpSpaIdValue id);
WP_API
const gchar * wp_spa_id_value_name (WpSpaIdValue id);
WP_API
const gchar * wp_spa_id_value_short_name (WpSpaIdValue id);
WP_API
WpSpaType wp_spa_id_value_get_value_type (WpSpaIdValue id, WpSpaIdTable *table);
WP_API
WpSpaType wp_spa_id_value_array_get_item_type (WpSpaIdValue id,
WpSpaIdTable *table);
/* Dynamic type registration */
WP_API
void wp_spa_dynamic_type_init (void);
WP_API
void wp_spa_dynamic_type_deinit (void);
WP_API
WpSpaType wp_spa_dynamic_type_register (const gchar *name, WpSpaType parent,
const struct spa_type_info * values);
WP_API
WpSpaIdTable wp_spa_dynamic_id_table_register (const gchar *name,
const struct spa_type_info * values);
G_END_DECLS

View file

@ -63,7 +63,7 @@ wp_init (WpInitFlags flags)
pw_log_set_level (lvl);
if (flags & WP_INIT_SPA_TYPES)
wp_spa_type_init (TRUE);
wp_spa_dynamic_type_init ();
/* ensure WpProxy subclasses are loaded, which is needed to be able
to autodetect the GType of proxies created through wp_proxy_new_global() */

View file

@ -42,7 +42,7 @@ set_device_profile (WpPipewireObject *device, gint index)
{
g_return_if_fail (device);
g_autoptr (WpSpaPod) profile = wp_spa_pod_new_object (
"Profile", "Profile",
"Spa:Pod:Object:Param:Profile", "Profile",
"index", "i", index,
NULL);
wp_debug_object (device, "set profile %d", index);

View file

@ -63,8 +63,7 @@ find_device_profile (WpPipewireObject *device, const gchar *lookup_name)
const gchar *name = NULL;
/* Parse */
if (!wp_spa_pod_get_object (pod,
"Profile", NULL,
if (!wp_spa_pod_get_object (pod, NULL,
"index", "i", &index,
"name", "s", &name,
NULL)) {
@ -191,8 +190,7 @@ on_device_profile_notified (WpPipewireObject *device, GAsyncResult *res,
/* Parse the profile */
WpSpaPod *pod = g_value_get_boxed (&item);
if (!wp_spa_pod_get_object (pod,
"Profile", NULL,
if (!wp_spa_pod_get_object (pod, NULL,
"index", "i", &index,
"name", "s", &name,
NULL)) {

View file

@ -34,7 +34,7 @@ set_device_profile (WpDeviceActivation *self,
/* Set profile */
wp_pipewire_object_set_param (device, "Profile", 0,
wp_spa_pod_new_object (
"Profile", "Profile",
"Spa:Pod:Object:Param:Profile", "Profile",
"index", "i", index,
NULL));
@ -72,8 +72,7 @@ on_device_enum_profile_done (WpPipewireObject *proxy, GAsyncResult *res,
const gchar *n = NULL;
/* Parse */
if (!wp_spa_pod_get_object (pod,
"Profile", NULL,
if (!wp_spa_pod_get_object (pod, NULL,
"index", "i", &i,
"name", "s", &n,
NULL)) {

View file

@ -207,8 +207,7 @@ on_device_enum_profile_done (WpPipewireObject *proxy, GAsyncResult *res,
/* Parse profile */
{
g_autoptr (WpSpaPodParser) pp = wp_spa_pod_parser_new_object (pod,
"Profile", NULL);
g_autoptr (WpSpaPodParser) pp = wp_spa_pod_parser_new_object (pod, NULL);
g_return_if_fail (pp);
g_return_if_fail (wp_spa_pod_parser_get (pp, "index", "i", &index, NULL));
if (index == 0) {

View file

@ -259,7 +259,7 @@ static WpSpaPod *
format_audio_raw_build (const struct spa_audio_info_raw *info)
{
g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_object (
"Format", "Format");
"Spa:Pod:Object:Param:Format", "Format");
wp_spa_pod_builder_add (builder,
"mediaType", "I", SPA_MEDIA_TYPE_audio,
"mediaSubtype", "I", SPA_MEDIA_SUBTYPE_raw,
@ -327,7 +327,8 @@ si_adapter_activate_execute_step (WpSessionItem * item,
self->format.channels, self->format.rate);
port_format = format_audio_raw_build (&self->format);
pod = wp_spa_pod_new_object ("PortConfig", "PortConfig",
pod = wp_spa_pod_new_object (
"Spa:Pod:Object:Param:PortConfig", "PortConfig",
"direction", "I", self->direction,
"mode", "I", SPA_PARAM_PORT_CONFIG_MODE_dsp,
"monitor", "b", self->monitor,
@ -543,8 +544,12 @@ si_adapter_get_ports (WpSiPortInfo * item, const gchar * context)
/* try to find the audio channel; if channel is NULL, this will silently
leave the channel_id to its default value, 0 */
channel = wp_properties_get (props, PW_KEY_AUDIO_CHANNEL);
wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_AUDIO_CHANNEL, channel,
&channel_id, NULL, NULL);
if (channel) {
WpSpaIdValue idval = wp_spa_id_value_from_short_name (
"Spa:Enum:AudioChannel", channel);
if (idval)
channel_id = wp_spa_id_value_number (idval);
}
g_variant_builder_add (&b, "(uuu)", node_id, port_id, channel_id);
}

View file

@ -84,16 +84,17 @@ select_format (WpSpaPod *value)
return ret;
}
const gchar * choice_type_name = wp_spa_pod_get_choice_type_name (value);
guint32 choice_type =
wp_spa_id_value_number (wp_spa_pod_get_choice_type (value));
/* None */
if (g_strcmp0 ("None", choice_type_name) == 0) {
if (choice_type == SPA_CHOICE_None) {
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value);
wp_spa_pod_get_id (child, &ret);
}
/* Enum */
else if (g_strcmp0 ("Enum", choice_type_name) == 0) {
else if (choice_type == SPA_CHOICE_Enum) {
g_autoptr (WpIterator) it = wp_spa_pod_iterate (value);
GValue next = G_VALUE_INIT;
while (wp_iterator_next (it, &next)) {
@ -125,16 +126,17 @@ select_rate (WpSpaPod *value)
return ret;
}
const gchar * choice_type_name = wp_spa_pod_get_choice_type_name (value);
guint32 choice_type =
wp_spa_id_value_number (wp_spa_pod_get_choice_type (value));
/* None */
if (g_strcmp0 ("None", choice_type_name) == 0) {
if (choice_type == SPA_CHOICE_None) {
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value);
wp_spa_pod_get_int (child, &ret);
}
/* Enum */
else if (g_strcmp0 ("Enum", choice_type_name) == 0) {
else if (choice_type == SPA_CHOICE_Enum) {
/* pick the one closest to 48Khz */
g_autoptr (WpIterator) it = wp_spa_pod_iterate (value);
GValue next = G_VALUE_INIT;
@ -147,7 +149,7 @@ select_rate (WpSpaPod *value)
}
/* Range */
else if (g_strcmp0 ("Range", choice_type_name) == 0) {
else if (choice_type == SPA_CHOICE_Range) {
/* a range is typically 3 items: default, min, max;
however, sometimes ALSA drivers give bad min & max values
and pipewire picks a bad default... try to fix that here;
@ -180,16 +182,17 @@ select_channels (WpSpaPod *value, gint preference)
return ret;
}
const gchar * choice_type_name = wp_spa_pod_get_choice_type_name (value);
guint32 choice_type =
wp_spa_id_value_number (wp_spa_pod_get_choice_type (value));
/* None */
if (g_strcmp0 ("None", choice_type_name) == 0) {
if (choice_type == SPA_CHOICE_None) {
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value);
wp_spa_pod_get_int (child, &ret);
}
/* Enum */
else if (g_strcmp0 ("Enum", choice_type_name) == 0) {
else if (choice_type == SPA_CHOICE_Enum) {
/* choose the most channels */
g_autoptr (WpIterator) it = wp_spa_pod_iterate (value);
GValue next = G_VALUE_INIT;
@ -205,7 +208,7 @@ select_channels (WpSpaPod *value, gint preference)
}
/* Range */
else if (g_strcmp0 ("Range", choice_type_name) == 0) {
else if (choice_type == SPA_CHOICE_Range) {
/* a range is typically 3 items: default, min, max;
we want the most channels, but let's not trust max
to really be the max... ALSA drivers can be broken */
@ -247,8 +250,7 @@ choose_sensible_raw_audio_format (WpIterator *formats,
continue;
}
if (!wp_spa_pod_get_object (pod,
"Format", NULL,
if (!wp_spa_pod_get_object (pod, NULL,
"mediaType", "I", &mtype,
"mediaSubtype", "I", &mstype,
NULL)) {

View file

@ -453,7 +453,7 @@ set_device_profile (WpDevice *device, gint index)
{
g_return_if_fail (device);
g_autoptr (WpSpaPod) profile = wp_spa_pod_new_object (
"Profile", "Profile",
"Spa:Pod:Object:Param:Profile", "Profile",
"index", "i", index,
NULL);
wp_pipewire_object_set_param (WP_PIPEWIRE_OBJECT (device),

View file

@ -288,7 +288,7 @@ si_convert_activate_execute_step (WpSessionItem * item,
g_steal_pointer (&props));
format = wp_spa_pod_new_object (
"Format", "Format",
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", "I", SPA_MEDIA_TYPE_audio,
"mediaSubtype", "I", SPA_MEDIA_SUBTYPE_raw,
"format", "I", SPA_AUDIO_FORMAT_F32P,
@ -303,7 +303,8 @@ si_convert_activate_execute_step (WpSessionItem * item,
as doing merge + split is heavy for our needs */
wp_pipewire_object_set_param (WP_PIPEWIRE_OBJECT (self->node),
"PortConfig", 0,
wp_spa_pod_new_object ("PortConfig", "PortConfig",
wp_spa_pod_new_object (
"Spa:Pod:Object:Param:PortConfig", "PortConfig",
"direction", "I", pw_direction_reverse (self->direction),
"mode", "I", SPA_PARAM_PORT_CONFIG_MODE_dsp,
"format", "P", format,
@ -311,7 +312,8 @@ si_convert_activate_execute_step (WpSessionItem * item,
wp_pipewire_object_set_param (WP_PIPEWIRE_OBJECT (self->node),
"PortConfig", 0,
wp_spa_pod_new_object ("PortConfig", "PortConfig",
wp_spa_pod_new_object (
"Spa:Pod:Object:Param:PortConfig", "PortConfig",
"direction", "I", self->direction,
"mode", "I", SPA_PARAM_PORT_CONFIG_MODE_dsp,
"control", "b", self->control_port,
@ -460,8 +462,12 @@ si_convert_get_ports (WpSiPortInfo * item, const gchar * context)
leave the channel_id to its default value, 0 */
props = wp_pipewire_object_get_properties (WP_PIPEWIRE_OBJECT (port));
channel = wp_properties_get (props, PW_KEY_AUDIO_CHANNEL);
wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_AUDIO_CHANNEL, channel,
&channel_id, NULL, NULL);
if (channel) {
WpSpaIdValue idval = wp_spa_id_value_from_short_name (
"Spa:Enum:AudioChannel", channel);
if (idval)
channel_id = wp_spa_id_value_number (idval);
}
g_variant_builder_add (&b, "(uuu)", node_id, port_id, channel_id);
}

View file

@ -396,8 +396,12 @@ si_simple_node_endpoint_get_ports (WpSiPortInfo * item, const gchar * context)
/* try to find the audio channel; if channel is NULL, this will silently
leave the channel_id to its default value, 0 */
channel = wp_properties_get (props, PW_KEY_AUDIO_CHANNEL);
wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_AUDIO_CHANNEL, channel,
&channel_id, NULL, NULL);
if (channel) {
WpSpaIdValue idval = wp_spa_id_value_from_short_name (
"Spa:Enum:AudioChannel", channel);
if (idval)
channel_id = wp_spa_id_value_number (idval);
}
g_variant_builder_add (&b, "(uuu)", node_id, port_id, channel_id);
}

View file

@ -19,8 +19,6 @@
static void
test_choose_sensible_raw_audio_format (void)
{
wp_spa_type_init (TRUE);
uint32_t layout[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR,
SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE,
SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR };
@ -31,7 +29,7 @@ test_choose_sensible_raw_audio_format (void)
{
g_ptr_array_remove_range (formats, 0, formats->len);
g_autoptr (WpSpaPod) param1 = wp_spa_pod_new_object (
"Format", "Format",
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio),
"mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
"format", SPA_POD_CHOICE_ENUM_Id(3,
@ -56,7 +54,7 @@ test_choose_sensible_raw_audio_format (void)
{
g_ptr_array_remove_range (formats, 0, formats->len);
g_autoptr (WpSpaPod) param1 = wp_spa_pod_new_object (
"Format", "Format",
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio),
"mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
"format", SPA_POD_CHOICE_ENUM_Id(3,
@ -81,7 +79,7 @@ test_choose_sensible_raw_audio_format (void)
{
g_ptr_array_remove_range (formats, 0, formats->len);
g_autoptr (WpSpaPod) param2 = wp_spa_pod_new_object (
"Format", "Format",
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio),
"mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
"format", SPA_POD_CHOICE_ENUM_Id(3,
@ -95,7 +93,7 @@ test_choose_sensible_raw_audio_format (void)
g_assert_nonnull (param2);
g_ptr_array_add (formats, g_steal_pointer (&param2));
g_autoptr (WpSpaPod) param3 = wp_spa_pod_new_object (
"Format", "Format",
"Spa:Pod:Object:Param:Format", "Format",
"mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio),
"mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw),
"format", SPA_POD_CHOICE_ENUM_Id(3,
@ -123,8 +121,6 @@ test_choose_sensible_raw_audio_format (void)
g_assert_cmpint (info.position[4], ==, layout[4]);
g_assert_cmpint (info.position[5], ==, 0);
}
wp_spa_type_deinit ();
}
int

View file

@ -527,7 +527,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -547,7 +547,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
fixture->n_events = 0;
wp_pipewire_object_set_param (WP_PIPEWIRE_OBJECT (fixture->proxy_endpoint),
"Props", 0,
wp_spa_pod_new_object ("Props", "Props",
wp_spa_pod_new_object ("Spa:Pod:Object:Param:Props", "Props",
"volume", "f", 0.7f, NULL));
/* run until the change is on all sides */
@ -569,7 +569,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -590,7 +590,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -611,7 +611,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -623,7 +623,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
fixture->n_events = 0;
wp_pipewire_object_set_param (WP_PIPEWIRE_OBJECT (fixture->impl_endpoint),
"Props", 0,
wp_spa_pod_new_object ("Props", "Props",
wp_spa_pod_new_object ("Spa:Pod:Object:Param:Props", "Props",
"mute", "b", TRUE, NULL));
/* run until the change is on all sides */
@ -645,7 +645,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -666,7 +666,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -687,7 +687,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -699,7 +699,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
fixture->n_events = 0;
wp_pipewire_object_set_param (WP_PIPEWIRE_OBJECT (endpoint->node),
"Props", 0,
wp_spa_pod_new_object ("Props", "Props",
wp_spa_pod_new_object ("Spa:Pod:Object:Param:Props", "Props",
"volume", "f", 0.2f, NULL));
/* run until the change is on all sides */
@ -721,7 +721,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -742,7 +742,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));
@ -763,7 +763,7 @@ test_endpoint_with_props (TestEndpointFixture *fixture, gconstpointer data)
g_assert_true (wp_iterator_next (iterator, &item));
g_assert_nonnull ((pod = g_value_dup_boxed (&item)));
g_assert_true (wp_spa_pod_get_object (pod, "Props", NULL,
g_assert_true (wp_spa_pod_get_object (pod, NULL,
"volume", "f", &float_value,
"mute", "b", &boolean_value,
NULL));

View file

@ -106,7 +106,8 @@ test_node_enum_params_done (WpPipewireObject *node, GAsyncResult *res,
g_assert_cmpuint (G_VALUE_TYPE (&item), ==, WP_TYPE_SPA_POD);
g_assert_nonnull (pod = g_value_get_boxed (&item));
g_assert_true (wp_spa_pod_is_object (pod));
g_assert_cmpstr ("PropInfo", ==, wp_spa_pod_get_object_type_name (pod));
g_assert_cmpuint (wp_spa_type_from_name ("Spa:Pod:Object:Param:PropInfo"),
==, wp_spa_pod_get_spa_type (pod));
n_params++;
}
g_assert_cmpint (n_params, >, 0);

View file

@ -11,15 +11,14 @@
static void
test_spa_pod_basic (void)
{
wp_spa_type_init (TRUE);
/* None */
{
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_none ();
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_none (pod));
g_assert_false (wp_spa_pod_is_id (pod));
g_assert_cmpstr ("None", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:None", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_autoptr (WpSpaPod) other = wp_spa_pod_new_none ();
g_assert_true (wp_spa_pod_equal (pod, other));
}
@ -36,7 +35,8 @@ test_spa_pod_basic (void)
gboolean value = FALSE;
g_assert_true (wp_spa_pod_get_boolean (pod, &value));
g_assert_true (value);
g_assert_cmpstr ("Bool", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Bool", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_boolean (pod, FALSE));
g_assert_true (wp_spa_pod_get_boolean (pod, &value));
g_assert_false (value);
@ -49,7 +49,8 @@ test_spa_pod_basic (void)
gboolean value = FALSE;
g_assert_true (wp_spa_pod_get_boolean (copy, &value));
g_assert_false (value);
g_assert_cmpstr ("Bool", ==, wp_spa_pod_get_type_name (copy));
g_assert_cmpstr ("Spa:Bool", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (copy)));
g_autoptr (WpSpaPod) other = wp_spa_pod_new_boolean (TRUE);
g_assert_true (wp_spa_pod_set_pod (copy, other));
g_assert_true (wp_spa_pod_get_boolean (copy, &value));
@ -65,7 +66,8 @@ test_spa_pod_basic (void)
guint32 value = 0;
g_assert_true (wp_spa_pod_get_id (pod, &value));
g_assert_cmpuint (value, ==, 5);
g_assert_cmpstr ("Id", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Id", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_id (pod, 10));
g_assert_true (wp_spa_pod_get_id (pod, &value));
g_assert_cmpuint (value, ==, 10);
@ -84,7 +86,8 @@ test_spa_pod_basic (void)
gint value = 0;
g_assert_true (wp_spa_pod_get_int (pod, &value));
g_assert_cmpint (value, ==, -12);
g_assert_cmpstr ("Int", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Int", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_int (pod, 9999));
g_assert_true (wp_spa_pod_get_int (pod, &value));
g_assert_cmpint (value, ==, 9999);
@ -103,7 +106,8 @@ test_spa_pod_basic (void)
long value = 0;
g_assert_true (wp_spa_pod_get_long (pod, &value));
g_assert_cmpint (value, ==, LONG_MAX);
g_assert_cmpstr ("Long", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Long", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_long (pod, LONG_MIN));
g_assert_true (wp_spa_pod_get_long (pod, &value));
g_assert_cmpuint (value, ==, LONG_MIN);
@ -122,7 +126,8 @@ test_spa_pod_basic (void)
float value = 0;
g_assert_true (wp_spa_pod_get_float (pod, &value));
g_assert_cmpfloat_with_epsilon (value, 3.14, 0.001);
g_assert_cmpstr ("Float", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Float", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_float (pod, 1.0));
g_assert_true (wp_spa_pod_get_float (pod, &value));
g_assert_cmpfloat_with_epsilon (value, 1.0, 0.001);
@ -141,7 +146,8 @@ test_spa_pod_basic (void)
double value = 0;
g_assert_true (wp_spa_pod_get_double (pod, &value));
g_assert_cmpfloat_with_epsilon (value, 2.718281828, 0.0000000001);
g_assert_cmpstr ("Double", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Double", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_double (pod, 2.0));
g_assert_true (wp_spa_pod_get_double (pod, &value));
g_assert_cmpfloat_with_epsilon (value, 2.0, 0.0000000001);
@ -161,7 +167,8 @@ test_spa_pod_basic (void)
g_assert_true (wp_spa_pod_get_string (pod, &value));
g_assert_nonnull (value);
g_assert_cmpstr (value, ==, "WirePlumber");
g_assert_cmpstr ("String", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:String", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_autoptr (WpSpaPod) other = wp_spa_pod_new_string ("Other");
g_assert_nonnull (other);
g_assert_true (wp_spa_pod_set_pod (pod, other));
@ -182,7 +189,8 @@ test_spa_pod_basic (void)
g_assert_nonnull (value);
g_assert_cmpmem (value, len, "bytes", 5);
g_assert_cmpuint (len, ==, 5);
g_assert_cmpstr ("Bytes", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Bytes", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_autoptr (WpSpaPod) other = wp_spa_pod_new_bytes ("pod", 3);
g_assert_true (wp_spa_pod_set_pod (pod, other));
g_assert_true (wp_spa_pod_get_bytes (pod, &value, &len));
@ -195,35 +203,26 @@ test_spa_pod_basic (void)
/* Pointer */
{
gint i = 3;
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_pointer ("Int", &i);
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_pointer ("Spa:Pointer:Buffer", &i);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_pointer (pod));
const char *type_name = NULL;
gconstpointer p = NULL;
g_assert_true (wp_spa_pod_get_pointer (pod, &type_name, &p));
g_assert_nonnull (type_name);
g_assert_true (wp_spa_pod_get_pointer (pod, &p));
g_assert_nonnull (p);
g_assert_cmpstr (type_name, ==, "Int");
g_assert_true (p == &i);
g_assert_cmpint (*(gint *)p, ==, 3);
g_assert_cmpstr ("Pointer", ==, wp_spa_pod_get_type_name (pod));
gboolean b = TRUE;
g_assert_true (wp_spa_pod_set_pointer (pod, "Bool", &b));
g_assert_true (wp_spa_pod_get_pointer (pod, &type_name, &p));
g_assert_nonnull (type_name);
g_assert_nonnull (p);
g_assert_cmpstr (type_name, ==, "Bool");
g_assert_true (p == &b);
g_assert_cmpint (*(gboolean *)p, ==, TRUE);
g_assert_cmpstr ("Spa:Pointer:Buffer", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
float f = 1.1;
g_autoptr (WpSpaPod) other = wp_spa_pod_new_pointer ("Float", &f);
g_autoptr (WpSpaPod) other = wp_spa_pod_new_pointer ("Spa:Pointer:Meta", &f);
g_assert_true (wp_spa_pod_set_pod (pod, other));
g_assert_true (wp_spa_pod_get_pointer (pod, &type_name, &p));
g_assert_nonnull (type_name);
g_assert_true (wp_spa_pod_get_pointer (pod, &p));
g_assert_nonnull (p);
g_assert_cmpstr (type_name, ==, "Float");
g_assert_true (p == &f);
g_assert_cmpfloat_with_epsilon (*(float *)p, 1.1, 0.01);
g_assert_cmpstr ("Spa:Pointer:Meta", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_equal (pod, other));
}
@ -235,7 +234,8 @@ test_spa_pod_basic (void)
gint64 value = 0;
g_assert_true (wp_spa_pod_get_fd (pod, &value));
g_assert_cmpint (value, ==, 4);
g_assert_cmpstr ("Fd", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Fd", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_fd (pod, 1));
g_assert_true (wp_spa_pod_get_fd (pod, &value));
g_assert_cmpuint (value, ==, 1);
@ -256,7 +256,8 @@ test_spa_pod_basic (void)
g_assert_true (wp_spa_pod_get_rectangle (pod, &width, &height));
g_assert_cmpint (width, ==, 1920);
g_assert_cmpint (height, ==, 1080);
g_assert_cmpstr ("Rectangle", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Rectangle", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_rectangle (pod, 640, 480));
g_assert_true (wp_spa_pod_get_rectangle (pod, &width, &height));
g_assert_cmpint (width, ==, 640);
@ -279,7 +280,8 @@ test_spa_pod_basic (void)
g_assert_true (wp_spa_pod_get_fraction (pod, &num, &denom));
g_assert_cmpint (num, ==, 16);
g_assert_cmpint (denom, ==, 9);
g_assert_cmpstr ("Fraction", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Fraction", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_true (wp_spa_pod_set_fraction (pod, 4, 3));
g_assert_true (wp_spa_pod_get_fraction (pod, &num, &denom));
g_assert_cmpint (num, ==, 4);
@ -291,27 +293,26 @@ test_spa_pod_basic (void)
g_assert_cmpint (denom, ==, 1);
g_assert_true (wp_spa_pod_equal (pod, other));
}
wp_spa_type_deinit ();
}
static void
test_spa_pod_choice (void)
{
wp_spa_type_init (TRUE);
/* Static Enum */
{
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_choice (
"Enum", "i", 0, "i", 1, "i", 2, NULL);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_choice (pod));
g_assert_cmpstr ("Choice", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Enum", ==, wp_spa_pod_get_choice_type_name (pod));
g_assert_cmpstr ("Spa:Pod:Choice", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_assert_cmpstr ("Enum", ==,
wp_spa_id_value_short_name (wp_spa_pod_get_choice_type (pod)));
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (pod);
g_assert_nonnull (child);
g_assert_cmpstr ("Int", ==, wp_spa_pod_get_type_name (child));
g_assert_cmpstr ("Spa:Int", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (child)));
gint value = 1;
g_assert_true (wp_spa_pod_get_int (child, &value));
g_assert_cmpint (value, ==, 0);
@ -326,12 +327,14 @@ test_spa_pod_choice (void)
"default value", NULL);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_choice (pod));
g_assert_cmpstr ("Choice", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Pod:Choice", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
{
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (pod);
g_assert_nonnull (child);
g_assert_cmpstr ("String", ==, wp_spa_pod_get_type_name (child));
g_assert_cmpstr ("Spa:String", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (child)));
const char *value = NULL;
g_assert_true (wp_spa_pod_get_string (child, &value));
g_assert_nonnull (value);
@ -345,7 +348,8 @@ test_spa_pod_choice (void)
{
g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (pod);
g_assert_nonnull (child);
g_assert_cmpstr ("String", ==, wp_spa_pod_get_type_name (child));
g_assert_cmpstr ("Spa:String", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (child)));
const char *value = NULL;
g_assert_true (wp_spa_pod_get_string (child, &value));
g_assert_nonnull (value);
@ -362,21 +366,18 @@ test_spa_pod_choice (void)
g_autoptr (WpSpaPod) pod = wp_spa_pod_builder_end (b);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_choice (pod));
g_assert_cmpstr ("Choice", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Pod:Choice", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
}
/* It is not possible to use the parser to get the contents of a choice, you
* need to use the iterator API to achieve that. This is because there is no
* `spa_pod_parser_get_choice` API in the SPA library */
wp_spa_type_deinit ();
}
static void
test_spa_pod_array (void)
{
wp_spa_type_init (TRUE);
/* Dynamic */
{
WpSpaPodBuilder *b = wp_spa_pod_builder_new_array ();
@ -388,13 +389,15 @@ test_spa_pod_array (void)
g_autoptr (WpSpaPod) pod = wp_spa_pod_builder_end (b);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_array (pod));
g_assert_cmpstr ("Array", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Array", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
wp_spa_pod_builder_unref (b);
g_assert_true (wp_spa_pod_is_array (pod));
g_autoptr (WpSpaPod) child = wp_spa_pod_get_array_child (pod);
g_assert_nonnull (child);
g_assert_cmpstr ("Bool", ==, wp_spa_pod_get_type_name (child));
g_assert_cmpstr ("Spa:Bool", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (child)));
gboolean value = TRUE;
g_assert_true (wp_spa_pod_get_boolean (child, &value));
g_assert_false (value);
@ -403,19 +406,15 @@ test_spa_pod_array (void)
/* It is not possible to use the parser to get the contents of an array, you
* need to use the iterator API to achieve that. This is because there is no
* `spa_pod_parser_get_array` API in the SPA library. */
wp_spa_type_deinit ();
}
static void
test_spa_pod_object (void)
{
wp_spa_type_init (TRUE);
/* Static */
{
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_object (
"Props", "Props",
"Spa:Pod:Object:Param:Props", "Props",
"mute", "b", FALSE,
"volume", "f", 0.5,
"frequency", "i", 440,
@ -424,8 +423,8 @@ test_spa_pod_object (void)
NULL);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_object (pod));
g_assert_cmpstr ("Object", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Props", ==, wp_spa_pod_get_object_type_name (pod));
g_assert_cmpstr ("Spa:Pod:Object:Param:Props", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
const char *id_name;
gboolean mute = TRUE;
@ -434,7 +433,7 @@ test_spa_pod_object (void)
const char *device;
gint64 device_fd;
g_assert_true (wp_spa_pod_get_object (pod,
"Props", &id_name,
&id_name,
"mute", "b", &mute,
"volume", "f", &vol,
"frequency", "i", &frequency,
@ -452,7 +451,7 @@ test_spa_pod_object (void)
/* Dynamic */
{
g_autoptr (WpSpaPodBuilder) b = wp_spa_pod_builder_new_object (
"Props", "Props");
"Spa:Pod:Object:Param:Props", "Props");
wp_spa_pod_builder_add_property (b, "mute");
wp_spa_pod_builder_add_boolean (b, FALSE);
wp_spa_pod_builder_add_property (b, "volume");
@ -466,7 +465,8 @@ test_spa_pod_object (void)
g_autoptr (WpSpaPod) pod = wp_spa_pod_builder_end (b);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_object (pod));
g_assert_cmpstr ("Object", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Pod:Object:Param:Props", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
const char *id_name;
gboolean mute = TRUE;
@ -474,8 +474,7 @@ test_spa_pod_object (void)
gint frequency;
const char *device;
gint64 device_fd;
g_autoptr (WpSpaPodParser) p = wp_spa_pod_parser_new_object (pod,
"Props", &id_name);
g_autoptr (WpSpaPodParser) p = wp_spa_pod_parser_new_object (pod, &id_name);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_parser_get (p, "mute", "b", &mute, NULL));
g_assert_true (wp_spa_pod_parser_get (p, "volume", "f", &vol, NULL));
@ -490,15 +489,11 @@ test_spa_pod_object (void)
g_assert_cmpstr (device, ==, "device-name");
g_assert_cmpint (device_fd, ==, 5);
}
wp_spa_type_deinit ();
}
static void
test_spa_pod_struct (void)
{
wp_spa_type_init (TRUE);
/* Dynamic */
{
g_autoptr (WpSpaPodBuilder) b = wp_spa_pod_builder_new_struct ();
@ -510,7 +505,7 @@ test_spa_pod_struct (void)
wp_spa_pod_builder_add_double (b, 2.718281828);
wp_spa_pod_builder_add_string (b, "WirePlumber");
wp_spa_pod_builder_add_bytes (b, "bytes", 5);
wp_spa_pod_builder_add_pointer (b, "Struct", b);
wp_spa_pod_builder_add_pointer (b, "Spa:Pointer:Buffer", b);
wp_spa_pod_builder_add_fd (b, 4);
wp_spa_pod_builder_add_rectangle (b, 1920, 1080);
wp_spa_pod_builder_add_fraction (b, 16, 9);
@ -520,7 +515,7 @@ test_spa_pod_struct (void)
}
{
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_object (
"Props", "Props",
"Spa:Pod:Object:Param:Props", "Props",
"mute", "b", FALSE,
NULL);
wp_spa_pod_builder_add (b, "P", pod, NULL);
@ -528,7 +523,8 @@ test_spa_pod_struct (void)
g_autoptr (WpSpaPod) pod = wp_spa_pod_builder_end (b);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_struct (pod));
g_assert_cmpstr ("Struct", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Pod:Struct", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
g_autoptr (WpSpaPodParser) p = wp_spa_pod_parser_new_struct (pod);
g_assert_nonnull (pod);
@ -568,11 +564,8 @@ test_spa_pod_struct (void)
g_assert_cmpuint (len_bytes, ==, 5);
gconstpointer value_pointer;
const char *type_pointer;
g_assert_true (wp_spa_pod_parser_get_pointer (p, &type_pointer, &value_pointer));
g_assert_nonnull (type_pointer);
g_assert_true (wp_spa_pod_parser_get_pointer (p, &value_pointer));
g_assert_nonnull (value_pointer);
g_assert_cmpstr (type_pointer, ==, "Struct");
g_assert_true (value_pointer == b);
gint64 value_fd;
@ -604,28 +597,25 @@ test_spa_pod_struct (void)
gboolean mute = TRUE;
g_assert_true (wp_spa_pod_get_object (value_object,
"Props", &id_name,
&id_name,
"mute", "b", &mute,
NULL));
g_assert_cmpstr (id_name, ==, "Props");
g_assert_false (mute);
}
wp_spa_type_deinit ();
}
static void
test_spa_pod_sequence (void)
{
wp_spa_type_init (TRUE);
/* Static */
{
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_sequence (0,
10, "Properties", "l", 9999, NULL);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_sequence (pod));
g_assert_cmpstr ("Sequence", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Pod:Sequence", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
}
/* Dynamic */
@ -636,14 +626,13 @@ test_spa_pod_sequence (void)
g_autoptr (WpSpaPod) pod = wp_spa_pod_builder_end (b);
g_assert_nonnull (pod);
g_assert_true (wp_spa_pod_is_sequence (pod));
g_assert_cmpstr ("Sequence", ==, wp_spa_pod_get_type_name (pod));
g_assert_cmpstr ("Spa:Pod:Sequence", ==,
wp_spa_type_name (wp_spa_pod_get_spa_type (pod)));
}
/* It is not possible to use the parser to get the contents of a sequence, you
* need to use the iterator API to achieve that. This is because there is no
* `spa_pod_parser_get_sequence` API in the SPA library. */
wp_spa_type_deinit ();
}
static void
@ -692,8 +681,6 @@ sequence_foreach (const GValue *item, gpointer data)
static void
test_spa_pod_iterator (void)
{
wp_spa_type_init (TRUE);
/* Choice */
{
g_autoptr (WpSpaPodBuilder) b = wp_spa_pod_builder_new_choice ("Enum");
@ -794,7 +781,7 @@ test_spa_pod_iterator (void)
/* Object */
{
g_autoptr (WpSpaPodBuilder) b = wp_spa_pod_builder_new_object (
"Props", "Props");
"Spa:Pod:Object:Param:Props", "Props");
wp_spa_pod_builder_add_property (b, "mute");
wp_spa_pod_builder_add_boolean (b, FALSE);
wp_spa_pod_builder_add_property (b, "device");
@ -957,18 +944,14 @@ test_spa_pod_iterator (void)
g_assert_true (wp_iterator_foreach (it, sequence_foreach, &offset_total));
g_assert_cmpuint (offset_total, ==, 50);
}
wp_spa_type_deinit ();
}
static void
test_spa_pod_unique_owner (void)
{
wp_spa_type_init (TRUE);
/* Create an object */
WpSpaPod *pod = wp_spa_pod_new_object (
"PropInfo", "PropInfo",
"Spa:Pod:Object:Param:PropInfo", "PropInfo",
"id", "I", 1,
"name", "s", "prop-info-name",
NULL);
@ -1024,21 +1007,17 @@ test_spa_pod_unique_owner (void)
/* Destroy the property */
g_value_unset (&next);
wp_spa_type_deinit ();
}
static void
test_spa_pod_port_config (void)
{
wp_spa_type_init (TRUE);
const gint rate = 48000;
const gint channels = 2;
/* Build the format to make sure the types exist */
g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_object (
"Format", "Format");
"Spa:Pod:Object:Param:Format", "Format");
wp_spa_pod_builder_add (builder,
"mediaType", "I", 0,
"mediaSubtype", "I", 0,
@ -1056,7 +1035,8 @@ test_spa_pod_port_config (void)
g_assert_nonnull (format);
/* Build the port config to make sure the types exist */
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_object ("PortConfig", "PortConfig",
g_autoptr (WpSpaPod) pod = wp_spa_pod_new_object (
"Spa:Pod:Object:Param:PortConfig", "PortConfig",
"direction", "I", 0,
"mode", "I", 0,
"monitor", "b", FALSE,
@ -1064,8 +1044,6 @@ test_spa_pod_port_config (void)
"format", "P", format,
NULL);
g_assert_nonnull (pod);
wp_spa_type_deinit ();
}
int

View file

@ -12,143 +12,369 @@
static void
test_spa_type_basic (void)
{
wp_spa_type_init (TRUE);
g_assert_cmpuint (WP_SPA_TYPE_INVALID, ==, SPA_ID_INVALID);
/* Make sure table sizes are not 0 */
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_BASIC), >, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_PARAM), >, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_PROPS), >, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_PROP_INFO), >, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_CONTROL), >, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_CHOICE), >, 0);
/* Make sure SPA_TYPE_OBJECT_Props type from WP_SPA_TYPE_TABLE_BASIC is registered */
{
const char *name = NULL;
const char *nick = NULL;
WpSpaTypeTable table = WP_SPA_TYPE_TABLE_BASIC;
g_assert_true (wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_BASIC, SPA_TYPE_OBJECT_Props,
&name, &nick, &table));
g_assert_cmpstr (name, ==, "Spa:Pod:Object:Param:Props");
g_assert_cmpstr (nick, ==, "Props");
g_assert_cmpuint (table, ==, WP_SPA_TYPE_TABLE_PROPS);
WpSpaType type = SPA_TYPE_Int;
g_assert_cmpstr (wp_spa_type_name (type), ==, "Spa:Int");
g_assert_true (wp_spa_type_is_fundamental (type));
g_assert_cmpuint (wp_spa_type_parent (type), ==, SPA_TYPE_Int);
}
/* Make sure SPA_PARAM_Props type from WP_SPA_TYPE_TABLE_PARAM is registered */
{
const char *name = NULL;
const char *nick = NULL;
g_assert_true (wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PARAM, SPA_PARAM_Props, &name, &nick, NULL));
g_assert_cmpstr (name, ==, "Spa:Enum:ParamId:Props");
g_assert_cmpstr (nick, ==, "Props");
WpSpaType type = wp_spa_type_from_name ("Spa:Enum:ParamId");
g_assert_cmpuint (type, ==, WP_SPA_TYPE_INVALID);
WpSpaIdTable table = wp_spa_id_table_from_name ("Spa:Enum:ParamId");
g_assert_nonnull (table);
}
/* Make sure SPA_PROP_mute type from WP_SPA_TYPE_TABLE_PROPS is registered */
{
const char *name = NULL;
const char *nick = NULL;
g_assert_true (wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PROPS, SPA_PROP_mute, &name, &nick, NULL));
g_assert_cmpstr (name, ==, "Spa:Pod:Object:Param:Props:mute");
g_assert_cmpstr (nick, ==, "mute");
WpSpaType type = SPA_TYPE_OBJECT_Props;
g_assert_cmpstr (wp_spa_type_name (type), ==, "Spa:Pod:Object:Param:Props");
g_assert_cmpuint (wp_spa_type_from_name (SPA_TYPE_INFO_Props), ==, type);
g_assert_true (wp_spa_type_is_object (type));
g_assert_false (wp_spa_type_is_fundamental (type));
g_assert_cmpuint (wp_spa_type_parent (type), ==, SPA_TYPE_Object);
g_assert_nonnull (wp_spa_type_get_object_id_values_table (type));
g_assert_true (wp_spa_type_get_object_id_values_table (type) ==
wp_spa_id_table_from_name ("Spa:Enum:ParamId"));
}
/* Make sure SPA_PROP_INFO_id type from WP_SPA_TYPE_TABLE_PROP_INFO is registered */
/* enums */
{
const char *name = NULL;
const char *nick = NULL;
g_assert_true (wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PROP_INFO, SPA_PROP_INFO_id, &name, &nick, NULL));
g_assert_cmpstr (name, ==, "Spa:Pod:Object:Param:PropInfo:id");
g_assert_cmpstr (nick, ==, "id");
WpSpaIdValue id = wp_spa_id_value_from_name ("Spa:Enum:ParamId:Props");
g_assert_nonnull (id);
g_assert_cmpstr (wp_spa_id_value_name (id), ==, "Spa:Enum:ParamId:Props");
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Props");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PARAM_Props);
g_assert_true (id == wp_spa_id_value_from_short_name (
"Spa:Enum:ParamId", "Props"));
g_assert_true (id == wp_spa_id_value_from_number (
"Spa:Enum:ParamId", SPA_PARAM_Props));
}
/* Make sure SPA_CONTROL_Properties type from WP_SPA_TYPE_TABLE_CONTROL is registered */
{
const char *name = NULL;
const char *nick = NULL;
g_assert_true (wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_CONTROL, SPA_CONTROL_Properties, &name, &nick, NULL));
g_assert_cmpstr (name, ==, "Spa:Enum:Control:Properties");
g_assert_cmpstr (nick, ==, "Properties");
WpSpaIdValue id =
wp_spa_id_value_from_name ("Spa:Enum:Control:Properties");
g_assert_nonnull (id);
g_assert_cmpstr (wp_spa_id_value_name (id), ==,
"Spa:Enum:Control:Properties");
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Properties");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_CONTROL_Properties);
g_assert_true (id == wp_spa_id_value_from_short_name (
"Spa:Enum:Control", "Properties"));
g_assert_true (id == wp_spa_id_value_from_number (
"Spa:Enum:Control", SPA_CONTROL_Properties));
}
/* Make sure SPA_CHOICE_Enum type from WP_SPA_TYPE_TABLE_CHOICE is registered */
{
const char *name = NULL;
const char *nick = NULL;
g_assert_true (wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_CHOICE, SPA_CHOICE_Enum, &name, &nick, NULL));
g_assert_cmpstr (name, ==, "Spa:Enum:Choice:Enum");
g_assert_cmpstr (nick, ==, "Enum");
WpSpaIdValue id = wp_spa_id_value_from_name ("Spa:Enum:Choice:Enum");
g_assert_nonnull (id);
g_assert_cmpstr (wp_spa_id_value_name (id), ==, "Spa:Enum:Choice:Enum");
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Enum");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_CHOICE_Enum);
g_assert_true (id == wp_spa_id_value_from_short_name (
"Spa:Enum:Choice", "Enum"));
g_assert_true (id == wp_spa_id_value_from_number (
"Spa:Enum:Choice", SPA_CHOICE_Enum));
}
wp_spa_type_deinit ();
/* objects */
{
WpSpaIdValue id =
wp_spa_id_value_from_name ("Spa:Pod:Object:Param:Props:mute");
g_assert_nonnull (id);
g_assert_cmpstr (wp_spa_id_value_name (id), ==,
"Spa:Pod:Object:Param:Props:mute");
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "mute");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_mute);
g_assert_true (id == wp_spa_id_value_from_short_name (
SPA_TYPE_INFO_Props, "mute"));
g_assert_true (id == wp_spa_id_value_from_number (
SPA_TYPE_INFO_Props, SPA_PROP_mute));
}
{
WpSpaIdValue id =
wp_spa_id_value_from_name ("Spa:Pod:Object:Param:PropInfo:id");
g_assert_nonnull (id);
g_assert_cmpstr (wp_spa_id_value_name (id), ==,
"Spa:Pod:Object:Param:PropInfo:id");
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "id");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_INFO_id);
/* WpSpaIdValue is a pointer to static spa_type_info,
so it should be the same on all queries */
g_assert_true (id == wp_spa_id_value_from_short_name (
SPA_TYPE_INFO_PropInfo, "id"));
g_assert_true (id == wp_spa_id_value_from_number (
SPA_TYPE_INFO_PropInfo, SPA_PROP_INFO_id));
}
/* array value type check */
{
WpSpaIdValue id =
wp_spa_id_value_from_name ("Spa:Pod:Object:Param:Props:channelVolumes");
g_assert_nonnull (id);
g_assert_cmpstr (wp_spa_id_value_name (id), ==,
"Spa:Pod:Object:Param:Props:channelVolumes");
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "channelVolumes");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_channelVolumes);
g_assert_cmpuint (wp_spa_id_value_array_get_item_type (id, NULL), ==,
SPA_TYPE_Float);
}
{
WpSpaIdValue id =
wp_spa_id_value_from_name ("Spa:Pod:Object:Param:Props:channelMap");
g_assert_nonnull (id);
g_assert_cmpstr (wp_spa_id_value_name (id), ==,
"Spa:Pod:Object:Param:Props:channelMap");
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "channelMap");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_channelMap);
WpSpaIdTable table = NULL;
g_assert_cmpuint (wp_spa_id_value_array_get_item_type (id, &table), ==,
SPA_TYPE_Id);
g_assert_nonnull (table);
g_assert_true (table == wp_spa_id_table_from_name ("Spa:Enum:AudioChannel"));
}
}
static void
test_spa_type_iterate (void)
{
{
WpSpaType type = wp_spa_type_from_name (SPA_TYPE_INFO_PropInfo);
g_assert_cmpuint (type, !=, WP_SPA_TYPE_INVALID);
g_assert_true (wp_spa_type_is_object (type));
WpSpaIdTable table = wp_spa_type_get_values_table (type);
g_autoptr (WpIterator) it = wp_spa_id_table_iterate (table);
g_auto (GValue) value = G_VALUE_INIT;
WpSpaIdValue id = NULL;
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_INFO_START);
table = NULL;
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, &table), ==, SPA_TYPE_Id);
g_assert_nonnull (table);
g_assert_true (table == wp_spa_id_table_from_name ("Spa:Enum:ParamId"));
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "id");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_INFO_id);
table = NULL;
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, &table), ==, SPA_TYPE_Id);
g_assert_nonnull (table);
g_assert_true (table ==
wp_spa_id_table_from_name ("Spa:Pod:Object:Param:Props"));
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "name");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_INFO_name);
table = NULL;
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, &table), ==, SPA_TYPE_String);
g_assert_null (table);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "type");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_INFO_type);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, &table), ==, SPA_TYPE_Pod);
g_assert_null (table);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "labels");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_INFO_labels);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, &table), ==, SPA_TYPE_Struct);
g_assert_null (table);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "container");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_PROP_INFO_container);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, &table), ==, SPA_TYPE_Id);
g_assert_null (table);
g_value_unset (&value);
}
{
WpSpaIdTable table = wp_spa_id_table_from_name ("Spa:Enum:Choice");
g_assert_nonnull (table);
g_autoptr (WpIterator) it = wp_spa_id_table_iterate (table);
g_auto (GValue) value = G_VALUE_INIT;
WpSpaIdValue id = NULL;
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "None");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_CHOICE_None);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Int);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Range");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_CHOICE_Range);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Int);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Step");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_CHOICE_Step);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Int);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Enum");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_CHOICE_Enum);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Int);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Flags");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, SPA_CHOICE_Flags);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Int);
g_value_unset (&value);
}
}
static void
test_spa_type_register (void)
{
wp_spa_type_init (FALSE);
static const struct spa_type_info custom_enum_info[] = {
{ 0, SPA_TYPE_Int, "Spa:Enum:CustomEnum:Invalid", NULL },
{ 1, SPA_TYPE_Int, "Spa:Enum:CustomEnum:Valid", NULL },
{ 0, 0, NULL, NULL }
};
/* Make sure no types are registered */
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_BASIC), ==, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_PARAM), ==, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_PROPS), ==, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_CONTROL), ==, 0);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_CHOICE), ==, 0);
static const struct spa_type_info custom_obj_info[] = {
{ 0, SPA_TYPE_Id, "Spa:Pod:Object:CustomObj:", custom_enum_info },
{ 1, SPA_TYPE_Int, "Spa:Pod:Object:CustomObj:id", NULL },
{ 2, SPA_TYPE_String, "Spa:Pod:Object:CustomObj:name", NULL },
{ 3, SPA_TYPE_Float, "Spa:Pod:Object:CustomObj:volume", NULL },
{ 4, SPA_TYPE_Rectangle, "Spa:Pod:Object:CustomObj:box", NULL },
{ 5, SPA_TYPE_Bytes, "Spa:Pod:Object:CustomObj:data", NULL },
{ 0, 0, NULL, NULL },
};
wp_spa_dynamic_type_init ();
WpSpaIdTable enum_table =
wp_spa_dynamic_id_table_register ("Spa:Enum:CustomEnum", custom_enum_info);
WpSpaType obj_type = wp_spa_dynamic_type_register ("Spa:Pod:Object:CustomObj",
SPA_TYPE_Object, custom_obj_info);
g_assert_nonnull (enum_table);
g_assert_true (obj_type != WP_SPA_TYPE_INVALID);
g_assert_true (enum_table ==
wp_spa_id_table_from_name ("Spa:Enum:CustomEnum"));
/* Register SPA_TYPE_Bool */
{
g_assert_true (wp_spa_type_register (WP_SPA_TYPE_TABLE_BASIC, "Spa:Bool", "spa-bool"));
g_autoptr (WpIterator) it = wp_spa_id_table_iterate (enum_table);
g_auto (GValue) value = G_VALUE_INIT;
WpSpaIdValue id = NULL;
guint32 id = 0;
const char *name = NULL;
g_assert_true (wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, "spa-bool", &id, &name, NULL));
g_assert_cmpuint (id, ==, SPA_TYPE_Bool);
g_assert_cmpstr (name, ==, "Spa:Bool");
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Invalid");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, 0);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Int);
g_value_unset (&value);
name = NULL;
const char *nick = NULL;
g_assert_true (wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_BASIC, id, &name, &nick, NULL));
g_assert_cmpstr (name, ==, "Spa:Bool");
g_assert_cmpstr (nick, ==, "spa-bool");
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "Valid");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, 1);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Int);
g_value_unset (&value);
g_assert_false (wp_spa_type_register (WP_SPA_TYPE_TABLE_BASIC, "Spa:Bool", "spa-bool"));
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_BASIC), ==, 1);
g_assert_false (wp_iterator_next (it, &value));
}
/* Register Custom */
g_assert_cmpstr (wp_spa_type_name (obj_type), ==, "Spa:Pod:Object:CustomObj");
g_assert_true (wp_spa_type_is_object (obj_type));
g_assert_false (wp_spa_type_is_fundamental (obj_type));
g_assert_cmpuint (wp_spa_type_parent (obj_type), ==, SPA_TYPE_Object);
g_assert_cmpuint (obj_type, ==,
wp_spa_type_from_name ("Spa:Pod:Object:CustomObj"));
g_assert_true (enum_table ==
wp_spa_type_get_object_id_values_table (obj_type));
{
g_assert_true (wp_spa_type_register (WP_SPA_TYPE_TABLE_BASIC, "Wp:Bool", "wp-bool"));
WpSpaIdTable table = wp_spa_type_get_values_table (obj_type);
g_autoptr (WpIterator) it = wp_spa_id_table_iterate (table);
g_auto (GValue) value = G_VALUE_INIT;
WpSpaIdValue id = NULL;
guint32 id = 0;
const char *name = NULL;
g_assert_true (wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, "wp-bool", &id, &name, NULL));
g_assert_cmpuint (id, ==, SPA_TYPE_VENDOR_Other + 1);
g_assert_cmpstr (name, ==, "Wp:Bool");
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, 0);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Id);
g_value_unset (&value);
name = NULL;
const char *nick = NULL;
g_assert_true (wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_BASIC, id, &name, &nick, NULL));
g_assert_cmpstr (name, ==, "Wp:Bool");
g_assert_cmpstr (nick, ==, "wp-bool");
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "id");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, 1);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Int);
g_value_unset (&value);
g_assert_false (wp_spa_type_register (WP_SPA_TYPE_TABLE_BASIC, "Wp:Bool", "wp-bool"));
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "name");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, 2);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_String);
g_value_unset (&value);
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_BASIC), ==, 2);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "volume");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, 3);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Float);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "box");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, 4);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Rectangle);
g_value_unset (&value);
g_assert_true (wp_iterator_next (it, &value));
id = g_value_get_pointer (&value);
g_assert_cmpstr (wp_spa_id_value_short_name (id), ==, "data");
g_assert_cmpuint (wp_spa_id_value_number (id), ==, 5);
g_assert_cmpuint (wp_spa_id_value_get_value_type (id, NULL), ==, SPA_TYPE_Bytes);
g_value_unset (&value);
g_assert_false (wp_iterator_next (it, &value));
}
/* Unregister SPA_TYPE_Bool */
g_assert_true (wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, "spa-bool", NULL, NULL, NULL));
wp_spa_type_unregister (WP_SPA_TYPE_TABLE_BASIC, "spa-bool");
g_assert_false (wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, "spa-bool", NULL, NULL, NULL));
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_BASIC), ==, 1);
/* Unregister Custom */
g_assert_true (wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, "wp-bool", NULL, NULL, NULL));
wp_spa_type_unregister (WP_SPA_TYPE_TABLE_BASIC, "wp-bool");
g_assert_false (wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_BASIC, "wp-bool", NULL, NULL, NULL));
g_assert_cmpuint (wp_spa_type_get_table_size (WP_SPA_TYPE_TABLE_BASIC), ==, 0);
wp_spa_type_deinit ();
wp_spa_dynamic_type_deinit ();
}
int
@ -158,6 +384,7 @@ main (int argc, char *argv[])
g_log_set_writer_func (wp_log_writer_default, NULL, NULL);
g_test_add_func ("/wp/spa-type/basic", test_spa_type_basic);
g_test_add_func ("/wp/spa-type/iterate", test_spa_type_iterate);
g_test_add_func ("/wp/spa-type/register", test_spa_type_register);
return g_test_run ();

View file

@ -107,7 +107,7 @@ print_controls (WpPipewireObject * pwobj)
it = wp_pipewire_object_enum_params_sync (pwobj, "Props", NULL);
if (!it || !wp_iterator_next (it, &value) ||
!wp_spa_pod_get_object (g_value_get_boxed (&value), "Props", NULL,
!wp_spa_pod_get_object (g_value_get_boxed (&value), NULL,
"volume", "f", &volume,
"mute", "b", &mute,
NULL))
@ -654,14 +654,16 @@ set_volume_run (WpCtl * self)
it = wp_pipewire_object_enum_params_sync (proxy, "Props", NULL);
if (!it || !wp_iterator_next (it, &value) ||
!wp_spa_pod_get_object (g_value_get_boxed (&value), "Props", NULL,
!wp_spa_pod_get_object (g_value_get_boxed (&value), NULL,
"volume", "f", &volume, NULL)) {
printf ("Object '%d' does not support volume\n", cmdline.set_volume.id);
goto out;
}
wp_pipewire_object_set_param (proxy, "Props", 0, wp_spa_pod_new_object (
"Props", "Props", "volume", "f", cmdline.set_volume.volume, NULL));
"Spa:Pod:Object:Param:Props", "Props",
"volume", "f", cmdline.set_volume.volume,
NULL));
wp_core_sync (self->core, NULL, (GAsyncReadyCallback) async_quit, self);
return;
@ -741,7 +743,7 @@ set_mute_run (WpCtl * self)
it = wp_pipewire_object_enum_params_sync (proxy, "Props", NULL);
if (!it || !wp_iterator_next (it, &value) ||
!wp_spa_pod_get_object (g_value_get_boxed (&value), "Props", NULL,
!wp_spa_pod_get_object (g_value_get_boxed (&value), NULL,
"mute", "b", &mute, NULL)) {
printf ("Object '%d' does not support mute\n", cmdline.set_mute.id);
goto out;
@ -753,7 +755,9 @@ set_mute_run (WpCtl * self)
mute = !!cmdline.set_mute.mute;
wp_pipewire_object_set_param (proxy, "Props", 0, wp_spa_pod_new_object (
"Props", "Props", "mute", "b", mute, NULL));
"Spa:Pod:Object:Param:Props", "Props",
"mute", "b", mute,
NULL));
wp_core_sync (self->core, NULL, (GAsyncReadyCallback) async_quit, self);
return;
@ -810,7 +814,7 @@ set_profile_run (WpCtl * self)
}
wp_pipewire_object_set_param (proxy, "Profile", 0,
wp_spa_pod_new_object (
"Profile", "Profile",
"Spa:Pod:Object:Param:Profile", "Profile",
"index", "i", cmdline.set_profile.index,
NULL));
wp_core_sync (self->core, NULL, (GAsyncReadyCallback) async_quit, self);