3107 lines
84 KiB
C
3107 lines
84 KiB
C
/* WirePlumber
|
|
*
|
|
* Copyright © 2020 Collabora Ltd.
|
|
* @author Julian Bouzas <julian.bouzas@collabora.com>
|
|
*
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "spa-pod.h"
|
|
#include "spa-type.h"
|
|
#include "log.h"
|
|
|
|
#include <spa/utils/type-info.h>
|
|
#include <spa/pod/builder.h>
|
|
#include <spa/pod/parser.h>
|
|
#include <spa/pod/filter.h>
|
|
|
|
WP_DEFINE_LOCAL_LOG_TOPIC ("wp-spa-pod")
|
|
|
|
#define WP_SPA_POD_BUILDER_REALLOC_STEP_SIZE 64
|
|
#define WP_SPA_POD_ID_PROPERTY_NAME_MAX 16
|
|
|
|
/*! \defgroup wpspapod WpSpaPod */
|
|
/*!
|
|
* \struct WpSpaPod
|
|
*/
|
|
/*!
|
|
* \struct WpSpaPodBuilder
|
|
*/
|
|
/*!
|
|
* \struct WpSpaPodParser
|
|
*/
|
|
|
|
enum {
|
|
FLAG_NO_OWNERSHIP = (1 << 0),
|
|
FLAG_CONSTANT = (1 << 1)
|
|
};
|
|
|
|
typedef enum {
|
|
WP_SPA_POD_REGULAR = 0,
|
|
WP_SPA_POD_PROPERTY,
|
|
WP_SPA_POD_CONTROL,
|
|
} WpSpaPodType;
|
|
|
|
struct _WpSpaPod
|
|
{
|
|
grefcount ref;
|
|
guint32 flags;
|
|
|
|
/* The pipewire spa pod API does not have a type for Property and Control,
|
|
* so we create our own and separate them with their data from the regular
|
|
* spa pod types */
|
|
WpSpaPodType type;
|
|
|
|
/* Pod */
|
|
union {
|
|
struct spa_pod pod_none;
|
|
struct spa_pod_bool pod_bool;
|
|
struct spa_pod_id pod_id;
|
|
struct spa_pod_int pod_int;
|
|
struct spa_pod_long pod_long;
|
|
struct spa_pod_float pod_float;
|
|
struct spa_pod_double pod_double;
|
|
struct spa_pod_pointer pod_pointer;
|
|
struct spa_pod_fd pod_fd;
|
|
struct spa_pod_rectangle pod_rectangle;
|
|
struct spa_pod_fraction pod_fraction;
|
|
struct wp_property_data {
|
|
WpSpaIdTable table;
|
|
guint32 key;
|
|
guint32 flags;
|
|
gchar id_key_name[WP_SPA_POD_ID_PROPERTY_NAME_MAX];
|
|
} data_property; /* Only used for property pods */
|
|
struct wp_control_data {
|
|
guint32 offset;
|
|
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 */
|
|
struct spa_pod *pod;
|
|
};
|
|
|
|
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;
|
|
};
|
|
|
|
G_DEFINE_BOXED_TYPE (WpSpaPodBuilder, wp_spa_pod_builder,
|
|
wp_spa_pod_builder_ref, wp_spa_pod_builder_unref)
|
|
|
|
struct _WpSpaPodParser
|
|
{
|
|
struct spa_pod_parser parser;
|
|
struct spa_pod_frame frame;
|
|
WpSpaType type;
|
|
WpSpaPod *pod;
|
|
};
|
|
|
|
G_DEFINE_BOXED_TYPE (WpSpaPodParser, wp_spa_pod_parser,
|
|
wp_spa_pod_parser_ref, wp_spa_pod_parser_unref)
|
|
|
|
static int
|
|
wp_spa_pod_builder_overflow (gpointer data, uint32_t size)
|
|
{
|
|
WpSpaPodBuilder *self = data;
|
|
const uint32_t next_size = self->size + WP_SPA_POD_BUILDER_REALLOC_STEP_SIZE;
|
|
const uint32_t new_size = size > next_size ? size : next_size;
|
|
self->buf = g_realloc (self->buf, new_size);
|
|
self->builder.data = self->buf;
|
|
self->builder.size = new_size;
|
|
self->size = new_size;
|
|
return 0;
|
|
}
|
|
|
|
static const struct spa_pod_builder_callbacks builder_callbacks = {
|
|
SPA_VERSION_POD_BUILDER_CALLBACKS,
|
|
.overflow = wp_spa_pod_builder_overflow
|
|
};
|
|
|
|
static WpSpaPodBuilder *
|
|
wp_spa_pod_builder_new (size_t size, WpSpaType type)
|
|
{
|
|
WpSpaPodBuilder *self = g_rc_box_new0 (WpSpaPodBuilder);
|
|
self->size = size;
|
|
self->buf = g_new0 (guint8, self->size);
|
|
self->builder = SPA_POD_BUILDER_INIT (self->buf, self->size);
|
|
self->type = type;
|
|
|
|
spa_pod_builder_set_callbacks (&self->builder, &builder_callbacks, self);
|
|
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Increases the reference count of a spa pod object
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod object
|
|
* \returns (transfer full): \a self with an additional reference count on it
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_ref (WpSpaPod *self)
|
|
{
|
|
g_ref_count_inc (&self->ref);
|
|
return self;
|
|
}
|
|
|
|
static void
|
|
wp_spa_pod_free (WpSpaPod *self)
|
|
{
|
|
g_clear_pointer (&self->builder, wp_spa_pod_builder_unref);
|
|
self->pod = NULL;
|
|
g_slice_free (WpSpaPod, self);
|
|
}
|
|
|
|
/*!
|
|
* \brief Decreases the reference count on \a self and frees it when the ref
|
|
* count reaches zero.
|
|
* \ingroup wpspapod
|
|
* \param self (transfer full): a spa pod object
|
|
*/
|
|
void
|
|
wp_spa_pod_unref (WpSpaPod *self)
|
|
{
|
|
if (g_ref_count_dec (&self->ref))
|
|
wp_spa_pod_free (self);
|
|
}
|
|
|
|
static WpSpaPod *
|
|
wp_spa_pod_new (const struct spa_pod *pod, WpSpaPodType type, guint32 flags)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->flags = flags;
|
|
self->type = type;
|
|
|
|
/* Copy the reference if no ownership, otherwise copy the pod */
|
|
if (self->flags & FLAG_NO_OWNERSHIP) {
|
|
self->pod = (struct spa_pod *)pod;
|
|
} else {
|
|
self->builder = wp_spa_pod_builder_new (
|
|
SPA_ROUND_UP_N (sizeof (*pod) + pod->size, 8), pod->type);
|
|
self->pod = self->builder->builder.data;
|
|
spa_pod_builder_primitive (&self->builder->builder, pod);
|
|
}
|
|
|
|
/* Set the prop table if it is an object */
|
|
if (pod->type == SPA_TYPE_Object) {
|
|
self->static_pod.data_property.table =
|
|
wp_spa_type_get_values_table (((struct spa_pod_object *) pod)->body.type);
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Constructs a new WpSpaPod that wraps the given `spa_pod`.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param pod a spa_pod
|
|
* \returns a new WpSpaPod that references the data in \a pod. \a pod is not
|
|
* copied, so it needs to stay alive. The returned WpSpaPod can be modified
|
|
* by using the setter functions, in which case \a pod will be modified
|
|
* underneath.
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_wrap (struct spa_pod *pod)
|
|
{
|
|
return wp_spa_pod_new (pod, WP_SPA_POD_REGULAR, FLAG_NO_OWNERSHIP);
|
|
}
|
|
|
|
/*!
|
|
* \brief Constructs a new immutable WpSpaPod that wraps the given `spa_pod`.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param pod a constant spa_pod
|
|
* \returns a new WpSpaPod that references the data in \a pod. \a pod is not
|
|
* copied, so it needs to stay alive. The returned WpSpaPod cannot be
|
|
* modified, unless it's copied first.
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_wrap_const (const struct spa_pod *pod)
|
|
{
|
|
return wp_spa_pod_new (pod, WP_SPA_POD_REGULAR,
|
|
FLAG_NO_OWNERSHIP | FLAG_CONSTANT);
|
|
}
|
|
|
|
static WpSpaPod *
|
|
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);
|
|
self->static_pod.data_property.table = table;
|
|
self->static_pod.data_property.key = key;
|
|
self->static_pod.data_property.flags = flags;
|
|
return self;
|
|
}
|
|
|
|
static WpSpaPod *
|
|
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);
|
|
self->static_pod.data_control.offset = offset;
|
|
self->static_pod.data_control.type = type;
|
|
return self;
|
|
}
|
|
|
|
#if 0
|
|
/* 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 (WpSpaIdTable table, guint32 key,
|
|
guint32 flags, const struct spa_pod *pod)
|
|
{
|
|
WpSpaPod *self = wp_spa_pod_new (pod, WP_SPA_POD_PROPERTY,
|
|
FLAG_NO_OWNERSHIP | FLAG_CONSTANT);
|
|
self->static_pod.data_property.table = table;
|
|
self->static_pod.data_property.key = key;
|
|
self->static_pod.data_property.flags = flags;
|
|
return self;
|
|
}
|
|
|
|
static WpSpaPod *
|
|
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,
|
|
FLAG_NO_OWNERSHIP | FLAG_CONSTANT);
|
|
self->static_pod.data_control.offset = offset;
|
|
self->static_pod.data_control.type = type;
|
|
return self;
|
|
}
|
|
#endif
|
|
|
|
static WpSpaPod *
|
|
wp_spa_pod_new_wrap_copy (const struct spa_pod *pod)
|
|
{
|
|
return wp_spa_pod_new (pod, WP_SPA_POD_REGULAR, 0);
|
|
}
|
|
|
|
static WpSpaPod *
|
|
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);
|
|
self->static_pod.data_property.table = table;
|
|
self->static_pod.data_property.key = key;
|
|
self->static_pod.data_property.flags = flags;
|
|
return self;
|
|
}
|
|
|
|
static WpSpaPod *
|
|
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);
|
|
self->static_pod.data_control.offset = offset;
|
|
self->static_pod.data_control.type = type;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Converts a WpSpaPod pointer to a `struct spa_pod` one, for use with
|
|
* native pipewire & spa functions. The returned pointer is owned by WpSpaPod
|
|
* and may not be modified or freed.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod object
|
|
* \returns a const pointer to the underlying spa_pod structure
|
|
*/
|
|
const struct spa_pod *
|
|
wp_spa_pod_get_spa_pod (const WpSpaPod *self)
|
|
{
|
|
return self->pod;
|
|
}
|
|
|
|
/*!
|
|
* \brief 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.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod
|
|
* \returns (transfer none): the type of the spa pod
|
|
*/
|
|
WpSpaType
|
|
wp_spa_pod_get_spa_type (WpSpaPod *self)
|
|
{
|
|
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);
|
|
}
|
|
|
|
/*!
|
|
* \brief If the pod is a Choice, this gets the choice type
|
|
* (Range, Step, Enum, ...)
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self a choice pod
|
|
* \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);
|
|
return wp_spa_id_value_from_number (
|
|
SPA_TYPE_INFO_Choice, SPA_POD_CHOICE_TYPE (self->pod));
|
|
}
|
|
|
|
/*!
|
|
* \brief Copies a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param other a spa pod object
|
|
* \returns (transfer full): The newly copied spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_copy (WpSpaPod *other)
|
|
{
|
|
g_return_val_if_fail (other, NULL);
|
|
switch (other->type) {
|
|
case WP_SPA_POD_PROPERTY:
|
|
return wp_spa_pod_new_property_wrap_copy (
|
|
other->static_pod.data_property.table,
|
|
other->static_pod.data_property.key,
|
|
other->static_pod.data_property.flags, other->pod);
|
|
case WP_SPA_POD_CONTROL:
|
|
return wp_spa_pod_new_control_wrap_copy (
|
|
other->static_pod.data_control.offset,
|
|
other->static_pod.data_control.type, other->pod);
|
|
case WP_SPA_POD_REGULAR:
|
|
default:
|
|
break;
|
|
}
|
|
return wp_spa_pod_new_wrap_copy (other->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks if the pod is the unique owner of its data or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod object
|
|
* \returns TRUE if the pod owns the data, FALSE otherwise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_unique_owner (WpSpaPod *self)
|
|
{
|
|
return g_ref_count_compare (&self->ref, 1) &&
|
|
!(self->flags & FLAG_NO_OWNERSHIP);
|
|
}
|
|
|
|
/*!
|
|
* \brief If \a self is not uniquely owned already, then it is unrefed and a
|
|
* copy of it is returned instead. You should always consider \a self as unsafe
|
|
* to use after this call and you should use the returned object instead.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self (transfer full): a spa pod object
|
|
* \returns (transfer full): the uniquely owned spa pod object which may or may
|
|
* not be the same as \a self.
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_ensure_unique_owner (WpSpaPod *self)
|
|
{
|
|
WpSpaPod *copy = NULL;
|
|
|
|
if (wp_spa_pod_is_unique_owner (self))
|
|
return self;
|
|
|
|
copy = wp_spa_pod_copy (self);
|
|
wp_spa_pod_unref (self);
|
|
return copy;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type None
|
|
* \ingroup wpspapod
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_none (void)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_none = SPA_POD_INIT_None();
|
|
self->pod = &self->static_pod.pod_none;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type boolean
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the boolean value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_boolean (gboolean value)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_bool = SPA_POD_INIT_Bool (value ? true : false);
|
|
self->pod = &self->static_pod.pod_bool.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type Id
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the Id value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_id (guint32 value)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_id = SPA_POD_INIT_Id (value);
|
|
self->pod = &self->static_pod.pod_id.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type int
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the int value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_int (gint32 value)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_int = SPA_POD_INIT_Int (value);
|
|
self->pod = &self->static_pod.pod_int.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type long
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the long value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_long (gint64 value)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_long = SPA_POD_INIT_Long (value);
|
|
self->pod = &self->static_pod.pod_long.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type float
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the float value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_float (float value)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_float = SPA_POD_INIT_Float (value);
|
|
self->pod = &self->static_pod.pod_float.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type double
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the double value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_double (double value)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_double = SPA_POD_INIT_Double (value);
|
|
self->pod = &self->static_pod.pod_double.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type string
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the string value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_string (const char *value)
|
|
{
|
|
const uint32_t len = value ? strlen (value) : 0;
|
|
const char *str = value ? value : "";
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
|
|
struct spa_pod_string p = SPA_POD_INIT_String (len + 1);
|
|
self->builder = wp_spa_pod_builder_new (
|
|
SPA_ROUND_UP_N (sizeof (p) + len + 1, 8), SPA_TYPE_String);
|
|
|
|
self->pod = self->builder->builder.data;
|
|
|
|
spa_pod_builder_raw (&self->builder->builder, &p, sizeof(p));
|
|
spa_pod_builder_write_string (&self->builder->builder, str, len);
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type bytes
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the bytes value
|
|
* \param len the length of the bytes value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_bytes (gconstpointer value, guint32 len)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
const struct spa_pod_bytes p = SPA_POD_INIT_Bytes (len);
|
|
self->builder = wp_spa_pod_builder_new (
|
|
SPA_ROUND_UP_N (sizeof (p) + p.pod.size, 8),
|
|
SPA_TYPE_Bytes);
|
|
|
|
self->pod = self->builder->builder.data;
|
|
|
|
spa_pod_builder_raw (&self->builder->builder, &p, sizeof(p));
|
|
spa_pod_builder_raw_padded (&self->builder->builder, value, len);
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type pointer
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param type_name the name of the type of the pointer
|
|
* \param value the pointer value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
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;
|
|
self->static_pod.pod_pointer = SPA_POD_INIT_Pointer (type, value);
|
|
self->pod = &self->static_pod.pod_pointer.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type Fd
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param value the Fd value
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_fd (gint64 value)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_fd = SPA_POD_INIT_Fd (value);
|
|
self->pod = &self->static_pod.pod_fd.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type rectangle
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param width the width value of the rectangle
|
|
* \param height the height value of the rectangle
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_rectangle (guint32 width, guint32 height)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_rectangle =
|
|
SPA_POD_INIT_Rectangle (SPA_RECTANGLE (width, height));
|
|
self->pod = &self->static_pod.pod_rectangle.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type fraction
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param num the numerator value of the fraction
|
|
* \param denom the denominator value of the fraction
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_fraction (guint32 num, guint32 denom)
|
|
{
|
|
WpSpaPod *self = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&self->ref);
|
|
self->type = WP_SPA_POD_REGULAR;
|
|
self->static_pod.pod_fraction =
|
|
SPA_POD_INIT_Fraction (SPA_FRACTION (num, denom));
|
|
self->pod = &self->static_pod.pod_fraction.pod;
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type choice
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param choice_type the name of the choice type ("Range", "Step", ...),
|
|
* \param ... a list of choice values, followed by NULL
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_choice (const char *choice_type, ...)
|
|
{
|
|
WpSpaPod *self;
|
|
va_list args;
|
|
|
|
va_start (args, choice_type);
|
|
self = wp_spa_pod_new_choice_valist (choice_type, args);
|
|
va_end (args);
|
|
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief This is the `va_list` version of wp_spa_pod_new_choice()
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param choice_type the name of the choice type ("Range", "Step", ...)
|
|
* \param args the variable arguments passed to wp_spa_pod_new_choice()
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_choice_valist (const char *choice_type, va_list args)
|
|
{
|
|
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);
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param type_name the type name of the object type
|
|
* \param id_name the id name of the object,
|
|
* \param ... a list of object properties with their values, followed by NULL
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_object (const char *type_name, const char *id_name, ...)
|
|
{
|
|
WpSpaPod *self;
|
|
va_list args;
|
|
|
|
va_start (args, id_name);
|
|
self = wp_spa_pod_new_object_valist (type_name, id_name, args);
|
|
va_end (args);
|
|
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief This is the `va_list` version of wp_spa_pod_new_object()
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param type_name the type name of the object type
|
|
* \param id_name the id name of the object
|
|
* \param args the variable arguments passed to wp_spa_pod_new_object()
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_object_valist (const char *type_name, const char *id_name,
|
|
va_list args)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) b = wp_spa_pod_builder_new_object (type_name,
|
|
id_name);
|
|
wp_spa_pod_builder_add_valist (b, args);
|
|
return wp_spa_pod_builder_end (b);
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod of type sequence
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param unit the unit of the sequence
|
|
* \param ... a list of sequence controls with their values, followed by NULL
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_sequence (guint unit, ...)
|
|
{
|
|
WpSpaPod *self;
|
|
va_list args;
|
|
|
|
va_start(args, unit);
|
|
self = wp_spa_pod_new_sequence_valist (unit, args);
|
|
va_end(args);
|
|
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief This is the `va_list` version of wp_spa_pod_new_sequence()
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param unit the unit of the sequence
|
|
* \param args the variable arguments passed to wp_spa_pod_new_sequence()
|
|
* \returns (transfer full): The new spa pod
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_new_sequence_valist (guint unit, va_list args)
|
|
{
|
|
g_autoptr (WpSpaPodBuilder) b = wp_spa_pod_builder_new_sequence (unit);
|
|
wp_spa_pod_builder_add_valist (b, args);
|
|
return wp_spa_pod_builder_end (b);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type none or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type none, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_none (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_none (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type boolean or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type boolean, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_boolean (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_bool (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type Id or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type Id, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_id (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_id (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type int or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type int, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_int (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_int (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type long or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type long, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_long (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_long (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type float or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type float, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_float (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_float (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type double or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type double, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_double (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_double (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type string or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type string, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_string (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_string (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type bytes or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type bytes, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_bytes (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_bytes (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type pointer or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type pointer, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_pointer (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_pointer (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type Fd or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type Fd, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_fd (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_fd (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type rectangle or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type rectangle, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_rectangle (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_rectangle (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type fraction or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type fraction, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_fraction (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_fraction (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type array or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type array, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_array (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_array (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type choice or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type choice, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_choice (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_choice (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type object or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type object, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_object (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_object (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type struct or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type struct, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_struct (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_struct (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type sequence or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type sequence, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_sequence (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_REGULAR && spa_pod_is_sequence (self->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type property or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type property, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_property (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_PROPERTY;
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks wether the spa pod is of type control or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \returns TRUE if it is of type control, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_is_control (WpSpaPod *self)
|
|
{
|
|
return self->type == WP_SPA_POD_CONTROL;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the boolean value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the boolean value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_boolean (WpSpaPod *self, gboolean *value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
bool v = FALSE;
|
|
const int res = spa_pod_get_bool (self->pod, &v);
|
|
*value = v ? TRUE : FALSE;
|
|
return res >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the Id value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the Id value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_id (WpSpaPod *self, guint32 *value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
uint32_t v = 0;
|
|
const int res = spa_pod_get_id (self->pod, &v);
|
|
*value = v;
|
|
return res >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the int value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the int value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_int (WpSpaPod *self, gint32 *value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_get_int (self->pod, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the long value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the long value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_long (WpSpaPod *self, gint64 *value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_get_long (self->pod, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the float value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the float value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_float (WpSpaPod *self, float *value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_get_float (self->pod, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the double value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the double value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_double (WpSpaPod *self, double *value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_get_double (self->pod, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the string value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the string value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_string (WpSpaPod *self, const char **value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_get_string (self->pod, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the bytes value and its len of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the bytes value
|
|
* \param len (out): the length of the bytes value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_bytes (WpSpaPod *self, gconstpointer *value, guint32 *len)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
g_return_val_if_fail (len, FALSE);
|
|
return spa_pod_get_bytes (self->pod, value, len) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the pointer value and its type name of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the pointer value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_pointer (WpSpaPod *self, gconstpointer *value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
|
|
guint32 type = 0;
|
|
return spa_pod_get_pointer (self->pod, &type, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the Fd value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value (out): the Fd value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_fd (WpSpaPod *self, gint64 *value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_get_fd (self->pod, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the rectangle's width and height value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param width (out): the rectangle's width value
|
|
* \param height (out): the rectangle's height value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_rectangle (WpSpaPod *self, guint32 *width, guint32 *height)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
struct spa_rectangle rectangle = { 0, };
|
|
const gboolean res = spa_pod_get_rectangle (self->pod, &rectangle) >= 0;
|
|
if (width)
|
|
*width = rectangle.width;
|
|
if (height)
|
|
*height = rectangle.height;
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the fractions's numerator and denominator value of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param num (out): the fractions's numerator value
|
|
* \param denom (out): the fractions's denominator value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_fraction (WpSpaPod *self, guint32 *num, guint32 *denom)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
struct spa_fraction fraction = { 0, };
|
|
const gboolean res = spa_pod_get_fraction (self->pod, &fraction) >= 0;
|
|
if (num)
|
|
*num = fraction.num;
|
|
if (denom)
|
|
*denom = fraction.denom;
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets a boolean value in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value the boolean value
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_boolean (WpSpaPod *self, gboolean value)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_boolean (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_bool *)self->pod)->value = value ? true : false;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets an Id value in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value the Id value
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_id (WpSpaPod *self, guint32 value)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_id (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_id *)self->pod)->value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets an int value in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value the int value
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_int (WpSpaPod *self, gint32 value)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_int (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_int *)self->pod)->value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets a long value in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value the long value
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_long (WpSpaPod *self, gint64 value)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_long (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_long *)self->pod)->value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets a float value in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value the float value
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_float (WpSpaPod *self, float value)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_float (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_float *)self->pod)->value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets a double value in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value the double value
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_double (WpSpaPod *self, double value)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_double (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_double *)self->pod)->value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets a pointer value with its type name in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param type_name the name of the type of the pointer
|
|
* \param value the pointer value
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_pointer (WpSpaPod *self, const char *type_name,
|
|
gconstpointer value)
|
|
{
|
|
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);
|
|
|
|
((struct spa_pod_pointer *)self->pod)->body.type = type;
|
|
((struct spa_pod_pointer *)self->pod)->body.value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets a Fd value in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param value the Fd value
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_fd (WpSpaPod *self, gint64 value)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_fd (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_fd *)self->pod)->value = value;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the width and height values of a rectangle in the spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param width the width value of the rectangle
|
|
* \param height the height value of the rectangle
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_rectangle (WpSpaPod *self, guint32 width, guint32 height)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_rectangle (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_rectangle *)self->pod)->value.width = width;
|
|
((struct spa_pod_rectangle *)self->pod)->value.height = height;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the numerator and denominator values of a fraction in the
|
|
* spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param num the numerator value of the farction
|
|
* \param denom the denominator value of the fraction
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_fraction (WpSpaPod *self, guint32 num, guint32 denom)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_fraction (self), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
((struct spa_pod_fraction *)self->pod)->value.num = num;
|
|
((struct spa_pod_fraction *)self->pod)->value.denom = denom;
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Sets the value of a spa pod object in the current spa pod object.
|
|
* The spa pod objects must be of the same value.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param pod the pod with the value to be set
|
|
* \returns TRUE if the value could be set, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_set_pod (WpSpaPod *self, WpSpaPod *pod)
|
|
{
|
|
g_return_val_if_fail (self->type == pod->type, FALSE);
|
|
g_return_val_if_fail (SPA_POD_TYPE (self->pod) == SPA_POD_TYPE (pod->pod), FALSE);
|
|
g_return_val_if_fail (!(self->flags & FLAG_CONSTANT), FALSE);
|
|
|
|
switch (SPA_POD_TYPE (self->pod)) {
|
|
case SPA_TYPE_None:
|
|
break;
|
|
case SPA_TYPE_Bool:
|
|
((struct spa_pod_bool *)self->pod)->value = ((struct spa_pod_bool *)pod->pod)->value;
|
|
break;
|
|
case SPA_TYPE_Id:
|
|
((struct spa_pod_id *)self->pod)->value = ((struct spa_pod_id *)pod->pod)->value;
|
|
break;
|
|
case SPA_TYPE_Int:
|
|
((struct spa_pod_int *)self->pod)->value = ((struct spa_pod_int *)pod->pod)->value;
|
|
break;
|
|
case SPA_TYPE_Long:
|
|
((struct spa_pod_long *)self->pod)->value = ((struct spa_pod_long *)pod->pod)->value;
|
|
break;
|
|
case SPA_TYPE_Float:
|
|
((struct spa_pod_float *)self->pod)->value = ((struct spa_pod_float *)pod->pod)->value;
|
|
break;
|
|
case SPA_TYPE_Double:
|
|
((struct spa_pod_double *)self->pod)->value = ((struct spa_pod_double *)pod->pod)->value;
|
|
break;
|
|
case SPA_TYPE_Pointer:
|
|
((struct spa_pod_pointer *)self->pod)->body.type = ((struct spa_pod_pointer *)pod->pod)->body.type;
|
|
((struct spa_pod_pointer *)self->pod)->body.value = ((struct spa_pod_pointer *)pod->pod)->body.value;
|
|
break;
|
|
case SPA_TYPE_Fd:
|
|
((struct spa_pod_fd *)self->pod)->value = ((struct spa_pod_fd *)pod->pod)->value;
|
|
break;
|
|
case SPA_TYPE_Rectangle:
|
|
((struct spa_pod_rectangle *)self->pod)->value.width = ((struct spa_pod_rectangle *)pod->pod)->value.width;
|
|
((struct spa_pod_rectangle *)self->pod)->value.height = ((struct spa_pod_rectangle *)pod->pod)->value.height;
|
|
break;
|
|
case SPA_TYPE_Fraction:
|
|
((struct spa_pod_fraction *)self->pod)->value.num = ((struct spa_pod_fraction *)pod->pod)->value.num;
|
|
((struct spa_pod_fraction *)self->pod)->value.denom = ((struct spa_pod_fraction *)pod->pod)->value.denom;
|
|
break;
|
|
default:
|
|
g_return_val_if_fail (self->pod->size >= pod->pod->size, FALSE);
|
|
memcpy (SPA_MEMBER (self->pod, sizeof (struct spa_pod), void),
|
|
SPA_MEMBER (pod->pod, sizeof (struct spa_pod), void),
|
|
SPA_MIN (self->pod->size, pod->pod->size));
|
|
self->pod->type = pod->pod->type;
|
|
self->pod->size = pod->pod->size;
|
|
break;
|
|
}
|
|
|
|
switch (self->type) {
|
|
case WP_SPA_POD_PROPERTY:
|
|
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;
|
|
break;
|
|
case WP_SPA_POD_CONTROL:
|
|
self->static_pod.data_control.offset = pod->static_pod.data_control.offset;
|
|
self->static_pod.data_control.type = pod->static_pod.data_control.type;
|
|
break;
|
|
case WP_SPA_POD_REGULAR:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Checks whether two spa pod objects have the same value or not
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param pod the pod with the value to be compared with
|
|
* \returns TRUE if both spa pod objects have the same values, FALSE othewrise.
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_equal (WpSpaPod *self, WpSpaPod *pod)
|
|
{
|
|
g_return_val_if_fail (self != NULL, FALSE);
|
|
g_return_val_if_fail (pod != NULL, FALSE);
|
|
|
|
if (self->type != pod->type)
|
|
return FALSE;
|
|
if (SPA_POD_TYPE (self->pod) != SPA_POD_TYPE (pod->pod))
|
|
return FALSE;
|
|
|
|
switch (SPA_POD_TYPE (self->pod)) {
|
|
case SPA_TYPE_None:
|
|
break;
|
|
case SPA_TYPE_Bool:
|
|
if (((struct spa_pod_bool *)self->pod)->value != ((struct spa_pod_bool *)pod->pod)->value)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Id:
|
|
if (((struct spa_pod_id *)self->pod)->value != ((struct spa_pod_id *)pod->pod)->value)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Int:
|
|
if (((struct spa_pod_int *)self->pod)->value != ((struct spa_pod_int *)pod->pod)->value)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Long:
|
|
if (((struct spa_pod_long *)self->pod)->value != ((struct spa_pod_long *)pod->pod)->value)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Float:
|
|
if (((struct spa_pod_float *)self->pod)->value != ((struct spa_pod_float *)pod->pod)->value)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Double:
|
|
if (((struct spa_pod_double *)self->pod)->value != ((struct spa_pod_double *)pod->pod)->value)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Pointer:
|
|
if (((struct spa_pod_pointer *)self->pod)->body.type != ((struct spa_pod_pointer *)pod->pod)->body.type ||
|
|
((struct spa_pod_pointer *)self->pod)->body.value != ((struct spa_pod_pointer *)pod->pod)->body.value)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Fd:
|
|
if (((struct spa_pod_fd *)self->pod)->value != ((struct spa_pod_fd *)pod->pod)->value)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Rectangle:
|
|
if (((struct spa_pod_rectangle *)self->pod)->value.width != ((struct spa_pod_rectangle *)pod->pod)->value.width ||
|
|
((struct spa_pod_rectangle *)self->pod)->value.height != ((struct spa_pod_rectangle *)pod->pod)->value.height)
|
|
return FALSE;
|
|
break;
|
|
case SPA_TYPE_Fraction:
|
|
if (((struct spa_pod_fraction *)self->pod)->value.num != ((struct spa_pod_fraction *)pod->pod)->value.num ||
|
|
((struct spa_pod_fraction *)self->pod)->value.denom != ((struct spa_pod_fraction *)pod->pod)->value.denom)
|
|
return FALSE;
|
|
break;
|
|
default:
|
|
if (self->pod->size != pod->pod->size ||
|
|
memcmp (SPA_MEMBER (self->pod, sizeof (struct spa_pod), void),
|
|
SPA_MEMBER (pod->pod, sizeof (struct spa_pod), void),
|
|
self->pod->size) != 0)
|
|
return FALSE;
|
|
break;
|
|
}
|
|
|
|
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.key != pod->static_pod.data_property.key ||
|
|
self->static_pod.data_property.flags != pod->static_pod.data_property.flags)
|
|
return FALSE;
|
|
break;
|
|
case WP_SPA_POD_CONTROL:
|
|
if (self->static_pod.data_control.offset != pod->static_pod.data_control.offset ||
|
|
self->static_pod.data_control.type != pod->static_pod.data_control.type)
|
|
return FALSE;
|
|
break;
|
|
case WP_SPA_POD_REGULAR:
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the object properties values of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param id_name (out): the id name of the object,
|
|
* \param ... (out): the list of the object properties values, followed by NULL
|
|
* \returns TRUE if the object properties values were obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
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, id_name, args);
|
|
va_end (args);
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief This is the `va_list` version of wp_spa_pod_get_object()
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param id_name (out): the id name of the object
|
|
* \param args (out): the variable arguments passed to wp_spa_pod_get_object()
|
|
* \returns TRUE if the object properties values were obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
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, id_name);
|
|
const gboolean res = wp_spa_pod_parser_get_valist (p, args);
|
|
wp_spa_pod_parser_end (p);
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the struct's values of a spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param ... (out): the list of the struct values, followed by NULL
|
|
* \returns TRUE if the struct values were obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_struct (WpSpaPod *self, ...)
|
|
{
|
|
va_list args;
|
|
gboolean res;
|
|
va_start (args, self);
|
|
res = wp_spa_pod_get_struct_valist (self, args);
|
|
va_end (args);
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief This is the `va_list` version of wp_spa_pod_get_struct()
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param args (out): the variable arguments passed to wp_spa_pod_get_struct()
|
|
* \returns TRUE if the struct values were obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_struct_valist (WpSpaPod *self, va_list args)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (wp_spa_pod_is_struct (self), FALSE);
|
|
g_autoptr (WpSpaPodParser) p = wp_spa_pod_parser_new_struct (self);
|
|
const gboolean res = wp_spa_pod_parser_get_valist (p, args);
|
|
wp_spa_pod_parser_end (p);
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the name, flags and spa pod value of a spa pod property
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param key (out) (optional): the name of the property
|
|
* \param value (out) (optional): the spa pod value of the property
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_property (WpSpaPod *self, const char **key,
|
|
WpSpaPod **value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (wp_spa_pod_is_property (self), FALSE);
|
|
|
|
if (key) {
|
|
WpSpaIdValue key_val = wp_spa_id_table_find_value (
|
|
self->static_pod.data_property.table,
|
|
self->static_pod.data_property.key);
|
|
if (key_val) {
|
|
*key = wp_spa_id_value_short_name (key_val);
|
|
} else {
|
|
g_snprintf (self->static_pod.data_property.id_key_name,
|
|
WP_SPA_POD_ID_PROPERTY_NAME_MAX, "id-%08x",
|
|
self->static_pod.data_property.key);
|
|
*key = self->static_pod.data_property.id_key_name;
|
|
}
|
|
}
|
|
if (value)
|
|
*value = wp_spa_pod_new_wrap (self->pod);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the offset, type name and spa pod value of a spa pod control
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod object
|
|
* \param offset (out) (optional): the offset of the control
|
|
* \param ctl_type (out) (optional): the control type (Properties, Midi, ...)
|
|
* \param value (out) (optional): the spa pod value of the control
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_get_control (WpSpaPod *self, guint32 *offset, const char **ctl_type,
|
|
WpSpaPod **value)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
g_return_val_if_fail (wp_spa_pod_is_control (self), FALSE);
|
|
|
|
if (offset)
|
|
*offset = self->static_pod.data_control.offset;
|
|
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);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the child of a spa pod choice object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod choice object
|
|
* \returns (transfer full): the child of the spa pod choice object
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_get_choice_child (WpSpaPod *self)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_choice (self), NULL);
|
|
return wp_spa_pod_new_wrap (SPA_POD_CHOICE_CHILD (self->pod));
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the child of a spa pod array object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod choice object
|
|
* \returns (transfer full): the child of the spa pod array object
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_get_array_child (WpSpaPod *self)
|
|
{
|
|
g_return_val_if_fail (wp_spa_pod_is_array (self), NULL);
|
|
return wp_spa_pod_new_wrap (SPA_POD_ARRAY_CHILD (self->pod));
|
|
}
|
|
|
|
/*!
|
|
* \brief Fixates choices in an object pod so that they only have one value
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod
|
|
* \returns TRUE if the pod was an object and it went through the fixation
|
|
* procedure, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_fixate (WpSpaPod *self)
|
|
{
|
|
g_return_val_if_fail (self, FALSE);
|
|
|
|
if (wp_spa_pod_is_object (self))
|
|
return spa_pod_object_fixate ((struct spa_pod_object *) self->pod) == 0;
|
|
return FALSE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Returns the intersection between \a self and \a filter
|
|
*
|
|
* This is typically used to intersect pods that describe formats, in order to
|
|
* find a common format that is accceptable by both sides. For that purpose,
|
|
* this is not exactly an intersection with its mathematical meaning.
|
|
* Object properties can be thought of as format constraints. When one side does
|
|
* not specify a specific property, it is considered to accept any value for it,
|
|
* so the value of this property from the other side is added in the result.
|
|
*
|
|
* Both input pods are left unmodified after this function call.
|
|
*
|
|
* If NULL is passed in the \a filter, this function just copies \a self and
|
|
* returns the copy.
|
|
*
|
|
* \param self the first pod
|
|
* \param filter (nullable): the second pod
|
|
* \return (transfer full) (nullable): a new pod that contains the intersection
|
|
* between \a self and \a filter, or NULL if the intersection was not possible
|
|
* to make
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_filter (WpSpaPod *self, WpSpaPod *filter)
|
|
{
|
|
char buffer[1024];
|
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(&buffer, sizeof(buffer));
|
|
struct spa_pod *result = NULL;
|
|
|
|
g_return_val_if_fail (self, NULL);
|
|
|
|
if (spa_pod_filter(&b, &result, self->pod, filter ? filter->pod : NULL) >= 0)
|
|
return wp_spa_pod_new_wrap_copy (result);
|
|
return NULL;
|
|
}
|
|
|
|
/*!
|
|
* \brief Increases the reference count of a spa pod builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod builder object
|
|
* \returns (transfer full): \a self with an additional reference count on it
|
|
*/
|
|
WpSpaPodBuilder *
|
|
wp_spa_pod_builder_ref (WpSpaPodBuilder *self)
|
|
{
|
|
return (WpSpaPodBuilder *) g_rc_box_acquire ((gpointer) self);
|
|
}
|
|
|
|
static void
|
|
wp_spa_pod_builder_free (WpSpaPodBuilder *self)
|
|
{
|
|
g_clear_pointer (&self->buf, g_free);
|
|
}
|
|
|
|
/*!
|
|
* \brief Decreases the reference count on \a self and frees it when the ref
|
|
* count reaches zero.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self (transfer full): a spa pod builder object
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_unref (WpSpaPodBuilder *self)
|
|
{
|
|
g_rc_box_release_full (self, (GDestroyNotify) wp_spa_pod_builder_free);
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod builder of type array
|
|
* \ingroup wpspapod
|
|
* \returns (transfer full): the new spa pod builder
|
|
*/
|
|
WpSpaPodBuilder *
|
|
wp_spa_pod_builder_new_array (void)
|
|
{
|
|
WpSpaPodBuilder *self = wp_spa_pod_builder_new (
|
|
WP_SPA_POD_BUILDER_REALLOC_STEP_SIZE, SPA_TYPE_Array);
|
|
spa_pod_builder_push_array (&self->builder, &self->frame);
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod builder of type choice
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param choice_type the name of the choice type ("Range", "Step", ...)
|
|
* \returns (transfer full): the new spa pod builder
|
|
*/
|
|
WpSpaPodBuilder *
|
|
wp_spa_pod_builder_new_choice (const char *choice_type)
|
|
{
|
|
WpSpaPodBuilder *self = NULL;
|
|
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);
|
|
|
|
/* Push the array */
|
|
spa_pod_builder_push_choice (&self->builder, &self->frame,
|
|
wp_spa_id_value_number (type), 0);
|
|
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod builder of type object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param type_name the type name of the object type
|
|
* \param id_name the Id name of the object
|
|
* \returns (transfer full): the new spa pod builder
|
|
*/
|
|
WpSpaPodBuilder *
|
|
wp_spa_pod_builder_new_object (const char *type_name, const char *id_name)
|
|
{
|
|
WpSpaPodBuilder *self = NULL;
|
|
WpSpaType type;
|
|
WpSpaIdTable table;
|
|
WpSpaIdValue id;
|
|
|
|
/* Find the type */
|
|
type = wp_spa_type_from_name (type_name);
|
|
g_return_val_if_fail (wp_spa_type_is_object (type), NULL);
|
|
|
|
/* Find the id */
|
|
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,
|
|
wp_spa_id_value_number (id));
|
|
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod builder of type struct
|
|
*
|
|
* \ingroup wpspapod
|
|
* \returns (transfer full): the new spa pod builder
|
|
*/
|
|
WpSpaPodBuilder *
|
|
wp_spa_pod_builder_new_struct (void)
|
|
{
|
|
WpSpaPodBuilder *self = NULL;
|
|
self = wp_spa_pod_builder_new (WP_SPA_POD_BUILDER_REALLOC_STEP_SIZE,
|
|
SPA_TYPE_Struct);
|
|
spa_pod_builder_push_struct (&self->builder, &self->frame);
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a spa pod builder of type sequence
|
|
*
|
|
* \ingroup wpspapod
|
|
* \returns (transfer full): the new spa pod builder
|
|
*/
|
|
WpSpaPodBuilder *
|
|
wp_spa_pod_builder_new_sequence (guint unit)
|
|
{
|
|
WpSpaPodBuilder *self = NULL;
|
|
self = wp_spa_pod_builder_new (WP_SPA_POD_BUILDER_REALLOC_STEP_SIZE,
|
|
SPA_TYPE_Sequence);
|
|
spa_pod_builder_push_sequence (&self->builder, &self->frame, unit);
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a none value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
*/
|
|
|
|
void
|
|
wp_spa_pod_builder_add_none (WpSpaPodBuilder *self)
|
|
{
|
|
spa_pod_builder_none (&self->builder);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a boolean value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the boolean value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_boolean (WpSpaPodBuilder *self, gboolean value)
|
|
{
|
|
spa_pod_builder_bool (&self->builder, value ? true : false);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a Id value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the Id value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_id (WpSpaPodBuilder *self, guint32 value)
|
|
{
|
|
spa_pod_builder_id (&self->builder, value);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a int value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the int value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_int (WpSpaPodBuilder *self, gint32 value)
|
|
{
|
|
spa_pod_builder_int (&self->builder, value);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a long value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the long value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_long (WpSpaPodBuilder *self, gint64 value)
|
|
{
|
|
spa_pod_builder_long (&self->builder, value);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a float value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the float value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_float (WpSpaPodBuilder *self, float value)
|
|
{
|
|
spa_pod_builder_float (&self->builder, value);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a double value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the double value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_double (WpSpaPodBuilder *self, double value)
|
|
{
|
|
spa_pod_builder_double (&self->builder, value);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a string value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the string value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_string (WpSpaPodBuilder *self, const char *value)
|
|
{
|
|
spa_pod_builder_string (&self->builder, value);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a bytes value with its length into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the bytes value
|
|
* \param len the length of the bytes value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_bytes (WpSpaPodBuilder *self, gconstpointer value,
|
|
guint32 len)
|
|
{
|
|
spa_pod_builder_bytes (&self->builder, value, len);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a pointer value with its type name into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param type_name the type name that the pointer points to
|
|
* \param value the pointer vaue
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_pointer (WpSpaPodBuilder *self, const char *type_name,
|
|
gconstpointer value)
|
|
{
|
|
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);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a Fd value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param value the Fd value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_fd (WpSpaPodBuilder *self, gint64 value)
|
|
{
|
|
spa_pod_builder_fd (&self->builder, value);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds the width and height values of a rectangle into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param width the width value of the rectangle
|
|
* \param height the height value of the rectangle
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_rectangle (WpSpaPodBuilder *self, guint32 width,
|
|
guint32 height)
|
|
{
|
|
spa_pod_builder_rectangle (&self->builder, width, height);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds the numerator and denominator values of a fraction into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param num the numerator value of the fraction
|
|
* \param denom the denominator value of the fraction
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_fraction (WpSpaPodBuilder *self, guint32 num,
|
|
guint32 denom)
|
|
{
|
|
spa_pod_builder_fraction (&self->builder, num, denom);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a pod value into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param pod the pod value
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_pod (WpSpaPodBuilder *self, WpSpaPod *pod)
|
|
{
|
|
spa_pod_builder_primitive (&self->builder, pod->pod);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a property into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param key the name of the property
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_property (WpSpaPodBuilder *self, const char *key)
|
|
{
|
|
guint key_id;
|
|
if (g_str_has_prefix (key, "id-")) {
|
|
g_return_if_fail (sscanf (key, "id-%08x", &key_id) == 1);
|
|
} else {
|
|
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);
|
|
key_id = wp_spa_id_value_number (id);
|
|
}
|
|
spa_pod_builder_prop (&self->builder, key_id, 0);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a property into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param id the id of the property
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_property_id (WpSpaPodBuilder *self, guint32 id)
|
|
{
|
|
spa_pod_builder_prop (&self->builder, id, 0);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a control into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param offset the offset of the control
|
|
* \param ctl_type the type name of the control
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_control (WpSpaPodBuilder *self, guint32 offset,
|
|
const char *ctl_type)
|
|
{
|
|
WpSpaIdValue id = wp_spa_id_value_from_short_name (
|
|
SPA_TYPE_INFO_Control, ctl_type);
|
|
g_return_if_fail (id != NULL);
|
|
spa_pod_builder_control (&self->builder, offset, wp_spa_id_value_number (id));
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a list of values into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param ... a list of additional values, followed by NULL
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add (WpSpaPodBuilder *self, ...)
|
|
{
|
|
va_list args;
|
|
va_start (args, self);
|
|
wp_spa_pod_builder_add_valist (self, args);
|
|
va_end (args);
|
|
}
|
|
|
|
/*!
|
|
* \brief Adds a list of values into the builder
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \param args the variable arguments passed to wp_spa_pod_builder_add()
|
|
*/
|
|
void
|
|
wp_spa_pod_builder_add_valist (WpSpaPodBuilder *self, va_list args)
|
|
{
|
|
WpSpaIdTable table = wp_spa_type_get_values_table (self->type);
|
|
|
|
do {
|
|
WpSpaIdValue key = NULL;
|
|
const char *format;
|
|
int n_values = 1;
|
|
struct spa_pod_frame f;
|
|
gboolean choice;
|
|
|
|
if (wp_spa_type_is_object (self->type)) {
|
|
guint key_id;
|
|
const char *key_name = va_arg(args, const char *);
|
|
if (!key_name)
|
|
return;
|
|
if (g_str_has_prefix (key_name, "id-")) {
|
|
g_return_if_fail (sscanf (key_name, "id-%08x", &key_id) == 1);
|
|
} else {
|
|
key = wp_spa_id_table_find_value_from_short_name (table, key_name);
|
|
g_return_if_fail (key != NULL);
|
|
key_id = wp_spa_id_value_number (key);
|
|
}
|
|
spa_pod_builder_prop (&self->builder, key_id, 0);
|
|
}
|
|
else if (self->type == SPA_TYPE_Sequence) {
|
|
guint32 offset = va_arg(args, uint32_t);
|
|
if (offset == 0)
|
|
return;
|
|
const char *control_name = va_arg(args, const char *);
|
|
if (!control_name)
|
|
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,
|
|
wp_spa_id_value_number (type));
|
|
}
|
|
|
|
if ((format = va_arg(args, const char *)) == NULL)
|
|
break;
|
|
|
|
choice = *format == '?';
|
|
if (choice) {
|
|
uint32_t type = spa_choice_from_id (*++format);
|
|
if (*format != '\0')
|
|
format++;
|
|
spa_pod_builder_push_choice (&self->builder, &f, type, 0);
|
|
n_values = va_arg(args, int);
|
|
}
|
|
while (n_values-- > 0) {
|
|
switch (*format) {
|
|
case 'P': /* Pod */
|
|
case 'V': /* Choice */
|
|
case 'O': /* Object */
|
|
case 'T': { /* Struct */
|
|
WpSpaPod *arg = va_arg(args, WpSpaPod *);
|
|
if (arg == NULL)
|
|
spa_pod_builder_none (&self->builder);
|
|
else
|
|
spa_pod_builder_primitive (&self->builder, arg->pod);
|
|
break;
|
|
}
|
|
case 'K': { /* Id as string - WirePlumber extension */
|
|
const char * id = va_arg(args, const char *);
|
|
if (key) {
|
|
WpSpaIdTable id_table = NULL;
|
|
wp_spa_id_value_get_value_type (key, &id_table);
|
|
WpSpaIdValue id_val =
|
|
wp_spa_id_table_find_value_from_short_name (id_table, id);
|
|
spa_pod_builder_id (&self->builder, wp_spa_id_value_number (id_val));
|
|
}
|
|
break;
|
|
}
|
|
case 'b':
|
|
spa_pod_builder_bool(&self->builder,
|
|
va_arg(args, gboolean) ? true : false);
|
|
break;
|
|
default:
|
|
SPA_POD_BUILDER_COLLECT(&self->builder, *format, args);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (choice)
|
|
spa_pod_builder_pop (&self->builder, &f);
|
|
|
|
} while (TRUE);
|
|
}
|
|
|
|
/*!
|
|
* \brief Ends the builder process and returns the constructed spa pod object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod builder object
|
|
* \returns (transfer full): the constructed spa pod object
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_builder_end (WpSpaPodBuilder *self)
|
|
{
|
|
WpSpaPod *ret = NULL;
|
|
|
|
/* Construct the pod */
|
|
ret = g_slice_new0 (WpSpaPod);
|
|
g_ref_count_init (&ret->ref);
|
|
ret->type = WP_SPA_POD_REGULAR;
|
|
ret->pod = spa_pod_builder_pop (&self->builder, &self->frame);
|
|
ret->builder = wp_spa_pod_builder_ref (self);
|
|
|
|
/* 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;
|
|
}
|
|
|
|
/*!
|
|
* \brief Increases the reference count of a spa pod parser
|
|
* \ingroup wpspapod
|
|
* \param self a spa pod sparser object
|
|
* \returns (transfer full): \a self with an additional reference count on it
|
|
*/
|
|
WpSpaPodParser *
|
|
wp_spa_pod_parser_ref (WpSpaPodParser *self)
|
|
{
|
|
return (WpSpaPodParser *) g_rc_box_acquire ((gpointer) self);
|
|
}
|
|
|
|
static void
|
|
wp_spa_pod_parser_free (WpSpaPodParser *self)
|
|
{
|
|
self->pod = NULL;
|
|
}
|
|
|
|
/*!
|
|
* \brief Decreases the reference count on \a self and frees it when the ref
|
|
* count reaches zero.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self (transfer full): a spa pod parser object
|
|
*/
|
|
void
|
|
wp_spa_pod_parser_unref (WpSpaPodParser *self)
|
|
{
|
|
g_rc_box_release_full (self, (GDestroyNotify) wp_spa_pod_parser_free);
|
|
}
|
|
|
|
static WpSpaPodParser *
|
|
wp_spa_pod_parser_new (WpSpaPod *pod, guint32 type)
|
|
{
|
|
WpSpaPodParser *self = g_rc_box_new0 (WpSpaPodParser);
|
|
self->type = type;
|
|
self->pod = pod;
|
|
spa_pod_parser_pod (&self->parser, self->pod->pod);
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates an object spa pod parser. The \a pod object must be valid for
|
|
* the entire life-cycle of the returned parser.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param pod the object spa pod to parse
|
|
* \param id_name the Id name of the object
|
|
* \returns (transfer full): The new spa pod parser
|
|
*/
|
|
WpSpaPodParser *
|
|
wp_spa_pod_parser_new_object (WpSpaPod *pod, const char **id_name)
|
|
{
|
|
WpSpaPodParser *self = NULL;
|
|
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, type);
|
|
spa_pod_parser_push_object (&self->parser, &self->frame, type, &id);
|
|
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;
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates an struct spa pod parser. The \a pod object must be valid for
|
|
* the entire life-cycle of the returned parser.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param pod the struct spa pod to parse
|
|
* \returns (transfer full): The new spa pod parser
|
|
*/
|
|
WpSpaPodParser *
|
|
wp_spa_pod_parser_new_struct (WpSpaPod *pod)
|
|
{
|
|
WpSpaPodParser *self = NULL;
|
|
|
|
g_return_val_if_fail (wp_spa_pod_is_struct (pod), NULL);
|
|
|
|
self = wp_spa_pod_parser_new (pod, SPA_TYPE_Struct);
|
|
spa_pod_parser_push_struct (&self->parser, &self->frame);
|
|
return self;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the boolean value from a spa pod parser
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the boolean value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_boolean (WpSpaPodParser *self, gboolean *value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
bool v = FALSE;
|
|
gboolean res = spa_pod_parser_get_bool (&self->parser, &v) >= 0;
|
|
*value = v ? TRUE : FALSE;
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the Id value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the Id value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_id (WpSpaPodParser *self, guint32 *value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_parser_get_id (&self->parser, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the int value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the int value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_int (WpSpaPodParser *self, gint32 *value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_parser_get_int (&self->parser, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the long value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the long value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_long (WpSpaPodParser *self, gint64 *value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_parser_get_long (&self->parser, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the float value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the float value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_float (WpSpaPodParser *self, float *value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_parser_get_float (&self->parser, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the double value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the double value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_double (WpSpaPodParser *self, double *value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_parser_get_double (&self->parser, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the string value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the string value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_string (WpSpaPodParser *self, const char **value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_parser_get_string (&self->parser, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the bytes value and its length from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the bytes value
|
|
* \param len (out): the length of the bytes value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_bytes (WpSpaPodParser *self, gconstpointer *value,
|
|
guint32 *len)
|
|
{
|
|
return spa_pod_parser_get_bytes (&self->parser, value, len) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the pointer value and its type name from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the pointer value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_pointer (WpSpaPodParser *self, gconstpointer *value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
guint32 type = 0;
|
|
return spa_pod_parser_get_pointer (&self->parser, &type, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the Fd value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param value (out): the Fd value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_fd (WpSpaPodParser *self, gint64 *value)
|
|
{
|
|
g_return_val_if_fail (value, FALSE);
|
|
return spa_pod_parser_get_fd (&self->parser, value) >= 0;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the rectangle's width and height value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param width (out): the rectangle's width value
|
|
* \param height (out): the rectangle's height value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_rectangle (WpSpaPodParser *self, guint32 *width,
|
|
guint32 *height)
|
|
{
|
|
struct spa_rectangle r = { 0, };
|
|
gboolean res = spa_pod_parser_get_rectangle (&self->parser, &r) >= 0;
|
|
if (width)
|
|
*width = r.width;
|
|
if (height)
|
|
*height = r.height;
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the fractions's numerator and denominator value from a spa pod
|
|
* parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param num (out): the fractions's numerator value
|
|
* \param denom (out): the fractions's denominator value
|
|
* \returns TRUE if the value was obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_fraction (WpSpaPodParser *self, guint32 *num,
|
|
guint32 *denom)
|
|
{
|
|
struct spa_fraction f = { 0, };
|
|
gboolean res = spa_pod_parser_get_fraction (&self->parser, &f) >= 0;
|
|
if (num)
|
|
*num = f.num;
|
|
if (denom)
|
|
*denom = f.denom;
|
|
return res;
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets the spa pod value from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \returns (transfer full): The spa pod value or NULL if it could not be
|
|
* obtained
|
|
*/
|
|
WpSpaPod *
|
|
wp_spa_pod_parser_get_pod (WpSpaPodParser *self)
|
|
{
|
|
struct spa_pod *p = NULL;
|
|
gboolean res = spa_pod_parser_get_pod (&self->parser, &p) >= 0;
|
|
if (!res || !p)
|
|
return NULL;
|
|
|
|
return wp_spa_pod_new_wrap (p);
|
|
}
|
|
|
|
/*!
|
|
* \brief Gets a list of values from a spa pod parser object
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param ... (out): a list of values to get, followed by NULL
|
|
* \returns TRUE if the values were obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get (WpSpaPodParser *self, ...)
|
|
{
|
|
gboolean res;
|
|
va_list args;
|
|
|
|
va_start (args, self);
|
|
res = wp_spa_pod_parser_get_valist (self, args);
|
|
va_end (args);
|
|
|
|
return res;
|
|
}
|
|
|
|
static inline gboolean
|
|
wp_spa_pod_parser_can_collect (const struct spa_pod *pod, char format)
|
|
{
|
|
format = (format == 'K') ? 'I' : format;
|
|
return spa_pod_parser_can_collect (pod, format);
|
|
}
|
|
|
|
/*!
|
|
* \brief This is the `va_list` version of wp_spa_pod_parser_get()
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
* \param args the variable arguments passed to wp_spa_pod_parser_get()
|
|
* \returns TRUE if the values were obtained, FALSE otherwise
|
|
*/
|
|
gboolean
|
|
wp_spa_pod_parser_get_valist (WpSpaPodParser *self, va_list args)
|
|
{
|
|
const struct spa_pod_prop *prop = NULL;
|
|
WpSpaIdTable table = wp_spa_type_get_values_table (self->type);
|
|
|
|
do {
|
|
WpSpaIdValue key = NULL;
|
|
bool optional;
|
|
const struct spa_pod *pod = NULL;
|
|
const char *format;
|
|
|
|
if (wp_spa_type_is_object (self->type)) {
|
|
guint key_id;
|
|
const struct spa_pod_object *object;
|
|
const char *key_name = va_arg(args, const char *);
|
|
if (!key_name)
|
|
break;
|
|
|
|
if (g_str_has_prefix (key_name, "id-")) {
|
|
if (sscanf (key_name, "id-%08x", &key_id) != 1)
|
|
return FALSE;
|
|
} else {
|
|
key = wp_spa_id_table_find_value_from_short_name (table, key_name);
|
|
g_return_val_if_fail (key != NULL, FALSE);
|
|
key_id = wp_spa_id_value_number (key);
|
|
}
|
|
|
|
object = (const struct spa_pod_object *)spa_pod_parser_frame
|
|
(&self->parser, &self->frame);
|
|
prop = spa_pod_object_find_prop (object, prop, key_id);
|
|
pod = prop ? &prop->value : NULL;
|
|
}
|
|
|
|
if ((format = va_arg(args, char *)) == NULL)
|
|
break;
|
|
|
|
if (self->type == SPA_TYPE_Struct)
|
|
pod = spa_pod_parser_next (&self->parser);
|
|
|
|
if ((optional = (*format == '?')))
|
|
format++;
|
|
|
|
if (!pod || !wp_spa_pod_parser_can_collect (pod, *format)) {
|
|
if (!optional)
|
|
return FALSE;
|
|
|
|
SPA_POD_PARSER_SKIP (*format, args);
|
|
} else {
|
|
if (pod->type == SPA_TYPE_Choice && *format != 'V' &&
|
|
SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None)
|
|
pod = SPA_POD_CHOICE_CHILD(pod);
|
|
|
|
switch (*format) {
|
|
case 'P': /* Pod */
|
|
case 'V': /* Choice */
|
|
case 'O': /* Object */
|
|
case 'T': /* Struct */
|
|
*va_arg(args, WpSpaPod**) = wp_spa_pod_new_wrap_copy (pod);
|
|
break;
|
|
case 'K': { /* Id as string - WirePlumber extension */
|
|
const char ** idstr = va_arg(args, const char **);
|
|
uint32_t id = SPA_POD_VALUE(struct spa_pod_id, pod);
|
|
if (key) {
|
|
WpSpaIdTable id_table = NULL;
|
|
wp_spa_id_value_get_value_type (key, &id_table);
|
|
WpSpaIdValue id_val = wp_spa_id_table_find_value (id_table, id);
|
|
*idstr = wp_spa_id_value_short_name (id_val);
|
|
}
|
|
break;
|
|
}
|
|
case 'b':
|
|
*va_arg(args, gboolean*) =
|
|
SPA_POD_VALUE(struct spa_pod_bool, pod) ? TRUE : FALSE;
|
|
break;
|
|
default:
|
|
SPA_POD_PARSER_COLLECT (pod, *format, args);
|
|
break;
|
|
}
|
|
}
|
|
} while (TRUE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/*!
|
|
* \brief Ends the parser process
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param self the spa pod parser object
|
|
*/
|
|
void
|
|
wp_spa_pod_parser_end (WpSpaPodParser *self)
|
|
{
|
|
spa_pod_parser_pop (&self->parser, &self->frame);
|
|
}
|
|
|
|
struct _WpSpaPodIterator
|
|
{
|
|
WpSpaPod *pod;
|
|
union {
|
|
gpointer value; /* Array and Choice */
|
|
struct spa_pod *pod; /* Struct */
|
|
struct spa_pod_prop *prop; /* Object */
|
|
struct spa_pod_control *control; /* Sequence */
|
|
} curr;
|
|
};
|
|
typedef struct _WpSpaPodIterator WpSpaPodIterator;
|
|
|
|
static gboolean
|
|
wp_spa_pod_iterator_next_choice (WpSpaPodIterator *self, GValue *item)
|
|
{
|
|
const struct spa_pod_choice *pod_choice =
|
|
(const struct spa_pod_choice *) self->pod->pod;
|
|
|
|
if (!self->curr.value)
|
|
self->curr.value = SPA_MEMBER (&pod_choice->body, sizeof(struct spa_pod_choice_body), void);
|
|
else
|
|
self->curr.value = SPA_MEMBER (self->curr.value, pod_choice->body.child.size, void);
|
|
|
|
if (self->curr.value >= SPA_MEMBER(&pod_choice->body, SPA_POD_BODY_SIZE (pod_choice), void))
|
|
return FALSE;
|
|
|
|
if (item) {
|
|
g_value_init (item, G_TYPE_POINTER);
|
|
g_value_set_pointer (item, self->curr.value);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
wp_spa_pod_iterator_next_array (WpSpaPodIterator *self, GValue *item)
|
|
{
|
|
const struct spa_pod_array *pod_arr =
|
|
(const struct spa_pod_array *) self->pod->pod;
|
|
|
|
if (!self->curr.value)
|
|
self->curr.value = SPA_MEMBER (&pod_arr->body, sizeof(struct spa_pod_array_body), void);
|
|
else
|
|
self->curr.value = SPA_MEMBER (self->curr.value, pod_arr->body.child.size, void);
|
|
|
|
if (self->curr.value >= SPA_MEMBER(&pod_arr->body, SPA_POD_BODY_SIZE (pod_arr), void))
|
|
return FALSE;
|
|
|
|
if (item) {
|
|
g_value_init (item, G_TYPE_POINTER);
|
|
g_value_set_pointer (item, self->curr.value);
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
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;
|
|
|
|
if (!self->curr.prop)
|
|
self->curr.prop = spa_pod_prop_first (&pod_obj->body);
|
|
else
|
|
self->curr.prop = spa_pod_prop_next (self->curr.prop);
|
|
|
|
if (!spa_pod_prop_is_inside (&pod_obj->body, SPA_POD_BODY_SIZE (pod_obj),
|
|
self->curr.prop))
|
|
return FALSE;
|
|
|
|
if (item) {
|
|
g_value_init (item, WP_TYPE_SPA_POD);
|
|
g_value_take_boxed (item, wp_spa_pod_new_property_wrap (
|
|
self->pod->static_pod.data_property.table, self->curr.prop->key,
|
|
self->curr.prop->flags, &self->curr.prop->value));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
wp_spa_pod_iterator_next_struct (WpSpaPodIterator *self, GValue *item)
|
|
{
|
|
if (!self->curr.pod)
|
|
self->curr.pod = SPA_POD_BODY (self->pod->pod);
|
|
else
|
|
self->curr.pod = spa_pod_next (self->curr.pod);
|
|
|
|
if (!spa_pod_is_inside (SPA_POD_BODY (self->pod->pod),
|
|
SPA_POD_BODY_SIZE (self->pod->pod), self->curr.pod))
|
|
return FALSE;
|
|
|
|
if (item) {
|
|
g_value_init (item, WP_TYPE_SPA_POD);
|
|
g_value_take_boxed (item, wp_spa_pod_new_wrap (self->curr.pod));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static gboolean
|
|
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;
|
|
|
|
if (!self->curr.control)
|
|
self->curr.control = spa_pod_control_first (&pod_seq->body);
|
|
else
|
|
self->curr.control = spa_pod_control_next (self->curr.control);
|
|
|
|
if (!spa_pod_control_is_inside (&pod_seq->body, SPA_POD_BODY_SIZE (pod_seq),
|
|
self->curr.control))
|
|
return FALSE;
|
|
|
|
if (item) {
|
|
g_value_init (item, WP_TYPE_SPA_POD);
|
|
g_value_take_boxed (item, wp_spa_pod_new_control_wrap (
|
|
self->curr.control->offset, self->curr.control->type,
|
|
&self->curr.control->value));
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
static void
|
|
wp_spa_pod_iterator_reset (WpIterator *iterator)
|
|
{
|
|
WpSpaPodIterator *self = wp_iterator_get_user_data (iterator);
|
|
self->curr.value = NULL;
|
|
self->curr.pod = NULL;
|
|
self->curr.prop = NULL;
|
|
self->curr.control = NULL;
|
|
}
|
|
|
|
static gboolean
|
|
wp_spa_pod_iterator_next (WpIterator *iterator, GValue *item)
|
|
{
|
|
WpSpaPodIterator *self = wp_iterator_get_user_data (iterator);
|
|
|
|
switch (self->pod->pod->type) {
|
|
case SPA_TYPE_Choice:
|
|
return wp_spa_pod_iterator_next_choice (self, item);
|
|
case SPA_TYPE_Array:
|
|
return wp_spa_pod_iterator_next_array (self, item);
|
|
case SPA_TYPE_Object:
|
|
return wp_spa_pod_iterator_next_object (self, item);
|
|
case SPA_TYPE_Struct:
|
|
return wp_spa_pod_iterator_next_struct (self, item);
|
|
case SPA_TYPE_Sequence:
|
|
return wp_spa_pod_iterator_next_sequence (self, item);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static gboolean
|
|
wp_spa_pod_iterator_fold (WpIterator *iterator, WpIteratorFoldFunc func,
|
|
GValue *ret, gpointer data)
|
|
{
|
|
WpSpaPodIterator *self = wp_iterator_get_user_data (iterator);
|
|
|
|
wp_iterator_reset (iterator);
|
|
|
|
switch (self->pod->pod->type) {
|
|
case SPA_TYPE_Choice:
|
|
{
|
|
const struct spa_pod_choice *pod_choice =
|
|
(const struct spa_pod_choice *) self->pod->pod;
|
|
gpointer p = NULL;
|
|
SPA_POD_CHOICE_FOREACH (pod_choice, p) {
|
|
GValue v = G_VALUE_INIT;
|
|
g_value_init (&v, G_TYPE_POINTER);
|
|
g_value_set_pointer (&v, p);
|
|
const gboolean res = func (&v, ret, data);
|
|
g_value_unset (&v);
|
|
if (!res)
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
case SPA_TYPE_Array:
|
|
{
|
|
const struct spa_pod_array *pod_arr =
|
|
(const struct spa_pod_array *) self->pod->pod;
|
|
gpointer p = NULL;
|
|
SPA_POD_ARRAY_FOREACH (pod_arr, p) {
|
|
GValue v = G_VALUE_INIT;
|
|
g_value_init (&v, G_TYPE_POINTER);
|
|
g_value_set_pointer (&v, p);
|
|
const gboolean res = func (&v, ret, data);
|
|
g_value_unset (&v);
|
|
if (!res)
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
case SPA_TYPE_Object:
|
|
{
|
|
const struct spa_pod_object *pod_obj =
|
|
(const struct spa_pod_object *) self->pod->pod;
|
|
struct spa_pod_prop *p = NULL;
|
|
SPA_POD_OBJECT_FOREACH (pod_obj, p) {
|
|
GValue v = G_VALUE_INIT;
|
|
g_value_init (&v, WP_TYPE_SPA_POD);
|
|
g_value_take_boxed (&v, wp_spa_pod_new_property_wrap (
|
|
self->pod->static_pod.data_property.table, p->key, p->flags,
|
|
&p->value));
|
|
const gboolean res = func (&v, ret, data);
|
|
g_value_unset (&v);
|
|
if (!res)
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
case SPA_TYPE_Struct:
|
|
{
|
|
struct spa_pod *p = NULL;
|
|
SPA_POD_STRUCT_FOREACH (self->pod->pod, p) {
|
|
GValue v = G_VALUE_INIT;
|
|
g_value_init (&v, WP_TYPE_SPA_POD);
|
|
g_value_take_boxed (&v, wp_spa_pod_new_wrap (p));
|
|
const gboolean res = func (&v, ret, data);
|
|
g_value_unset (&v);
|
|
if (!res)
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
case SPA_TYPE_Sequence:
|
|
{
|
|
const struct spa_pod_sequence *pod_seq =
|
|
(const struct spa_pod_sequence *) self->pod->pod;
|
|
struct spa_pod_control *p = NULL;
|
|
SPA_POD_SEQUENCE_FOREACH (pod_seq, p) {
|
|
GValue v = G_VALUE_INIT;
|
|
g_value_init (&v, WP_TYPE_SPA_POD);
|
|
g_value_take_boxed (&v, wp_spa_pod_new_control_wrap (p->offset, p->type,
|
|
&p->value));
|
|
const gboolean res = func (&v, ret, data);
|
|
g_value_unset (&v);
|
|
if (!res)
|
|
return FALSE;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
wp_spa_pod_iterator_finalize (WpIterator *iterator)
|
|
{
|
|
WpSpaPodIterator *self = wp_iterator_get_user_data (iterator);
|
|
g_clear_pointer (&self->pod, wp_spa_pod_unref);
|
|
}
|
|
|
|
/*!
|
|
* \brief Creates a new iterator for a spa pod object.
|
|
*
|
|
* \ingroup wpspapod
|
|
* \param pod a spa pod object
|
|
* \returns (transfer full): the new spa pod iterator
|
|
*/
|
|
WpIterator *
|
|
wp_spa_pod_new_iterator (WpSpaPod *pod)
|
|
{
|
|
static const WpIteratorMethods methods = {
|
|
.version = WP_ITERATOR_METHODS_VERSION,
|
|
.reset = wp_spa_pod_iterator_reset,
|
|
.next = wp_spa_pod_iterator_next,
|
|
.fold = wp_spa_pod_iterator_fold,
|
|
.foreach = NULL,
|
|
.finalize = wp_spa_pod_iterator_finalize
|
|
};
|
|
WpIterator *it = wp_iterator_new (&methods, sizeof (WpSpaPodIterator));
|
|
WpSpaPodIterator *self = wp_iterator_get_user_data (it);
|
|
|
|
self->pod = wp_spa_pod_ref (pod);
|
|
|
|
return it;
|
|
}
|