diff --git a/lib/wp/core.c b/lib/wp/core.c index d3299dc564782a9a74a7bd71cebfd86bdff468b9..4520a0cda26ad6fd6a511afef9918dd2a890b68d 100644 --- a/lib/wp/core.c +++ b/lib/wp/core.c @@ -274,6 +274,7 @@ wp_core_class_init (WpCoreClass * klass) GObjectClass *object_class = (GObjectClass *) klass; pw_init (NULL, NULL); + wp_spa_type_init (TRUE); object_class->constructed = wp_core_constructed; object_class->dispose = wp_core_dispose; diff --git a/lib/wp/device.c b/lib/wp/device.c index 481eb78cd7872323041048fd4d1b8b459bf61365..d38d9f3388a74220fd5771161065162715fd523a 100644 --- a/lib/wp/device.c +++ b/lib/wp/device.c @@ -83,14 +83,14 @@ wp_device_get_properties (WpProxy * self) static gint wp_device_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { struct pw_device *pwp; int device_enum_params_result; pwp = (struct pw_device *) wp_proxy_get_pw_proxy (self); device_enum_params_result = pw_device_enum_params (pwp, 0, id, start, num, - filter); + wp_spa_pod_get_spa_pod (filter)); g_warn_if_fail (device_enum_params_result >= 0); return device_enum_params_result; @@ -98,13 +98,14 @@ wp_device_enum_params (WpProxy * self, guint32 id, guint32 start, static gint wp_device_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param) + const WpSpaPod *param) { struct pw_device *pwp; int device_set_param_result; pwp = (struct pw_device *) wp_proxy_get_pw_proxy (self); - device_set_param_result = pw_device_set_param (pwp, id, flags, param); + device_set_param_result = pw_device_set_param (pwp, id, flags, + wp_spa_pod_get_spa_pod (param)); g_warn_if_fail (device_set_param_result >= 0); return device_set_param_result; @@ -350,13 +351,13 @@ wp_spa_device_get_properties (WpProxy * proxy) static gint wp_spa_device_enum_params (WpProxy * proxy, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { WpSpaDevice *self = WP_SPA_DEVICE (proxy); int device_enum_params_result; device_enum_params_result = spa_device_enum_params (self->interface, - 0, id, start, num, filter); + 0, id, start, num, wp_spa_pod_get_spa_pod (filter)); g_warn_if_fail (device_enum_params_result >= 0); return device_enum_params_result; @@ -364,13 +365,13 @@ wp_spa_device_enum_params (WpProxy * proxy, guint32 id, guint32 start, static gint wp_spa_device_set_param (WpProxy * proxy, guint32 id, guint32 flags, - const struct spa_pod *param) + const WpSpaPod *param) { WpSpaDevice *self = WP_SPA_DEVICE (proxy); int device_set_param_result; device_set_param_result = spa_device_set_param (self->interface, - id, flags, param); + id, flags, wp_spa_pod_get_spa_pod (param)); g_warn_if_fail (device_set_param_result >= 0); return device_set_param_result; diff --git a/lib/wp/endpoint-link.c b/lib/wp/endpoint-link.c index 24046eca0a555b3024a97336d1a753f90d95fc13..8e191f713cba0d1c5e1ef24ec7ef0afe8379dffc 100644 --- a/lib/wp/endpoint-link.c +++ b/lib/wp/endpoint-link.c @@ -87,14 +87,15 @@ wp_endpoint_link_get_properties (WpProxy * proxy) static gint wp_endpoint_link_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { WpEndpointLinkPrivate *priv = wp_endpoint_link_get_instance_private (WP_ENDPOINT_LINK (self)); int endpoint_link_enum_params_result; endpoint_link_enum_params_result = - pw_endpoint_link_enum_params (priv->iface, 0, id, start, num, filter); + pw_endpoint_link_enum_params (priv->iface, 0, id, start, num, + wp_spa_pod_get_spa_pod (filter)); g_warn_if_fail (endpoint_link_enum_params_result >= 0); return endpoint_link_enum_params_result; @@ -116,14 +117,15 @@ wp_endpoint_link_subscribe_params (WpProxy * self, guint32 n_ids, guint32 *ids) static gint wp_endpoint_link_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param) + const WpSpaPod *param) { WpEndpointLinkPrivate *priv = wp_endpoint_link_get_instance_private (WP_ENDPOINT_LINK (self)); int endpoint_link_set_param_result; endpoint_link_set_param_result = - pw_endpoint_link_set_param (priv->iface, id, flags, param); + pw_endpoint_link_set_param (priv->iface, id, flags, + wp_spa_pod_get_spa_pod (param)); g_warn_if_fail (endpoint_link_set_param_result >= 0); return endpoint_link_set_param_result; diff --git a/lib/wp/endpoint-stream.c b/lib/wp/endpoint-stream.c index 88dd12af6958e67e9a6c426a5c2187374661fb63..72c0abea928029a56be782c2a222642d195ce2f7 100644 --- a/lib/wp/endpoint-stream.c +++ b/lib/wp/endpoint-stream.c @@ -110,14 +110,15 @@ wp_endpoint_stream_get_properties (WpProxy * proxy) static gint wp_endpoint_stream_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { WpEndpointStreamPrivate *priv = wp_endpoint_stream_get_instance_private (WP_ENDPOINT_STREAM (self)); int endpoint_stream_enum_params_result; endpoint_stream_enum_params_result = - pw_endpoint_stream_enum_params (priv->iface, 0, id, start, num, filter); + pw_endpoint_stream_enum_params (priv->iface, 0, id, start, num, + wp_spa_pod_get_spa_pod (filter)); g_warn_if_fail (endpoint_stream_enum_params_result >= 0); return endpoint_stream_enum_params_result; @@ -139,14 +140,15 @@ wp_endpoint_stream_subscribe_params (WpProxy * self, guint32 n_ids, guint32 *ids static gint wp_endpoint_stream_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param) + const WpSpaPod *param) { WpEndpointStreamPrivate *priv = wp_endpoint_stream_get_instance_private (WP_ENDPOINT_STREAM (self)); int endpoint_stream_set_param_result; endpoint_stream_set_param_result = - pw_endpoint_stream_set_param (priv->iface, id, flags, param); + pw_endpoint_stream_set_param (priv->iface, id, flags, + wp_spa_pod_get_spa_pod (param)); g_warn_if_fail (endpoint_stream_set_param_result >= 0); return endpoint_stream_set_param_result; @@ -190,30 +192,29 @@ wp_endpoint_stream_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy } static void -wp_endpoint_stream_param (WpProxy * proxy, gint seq, guint32 id, guint32 index, - guint32 next, const struct spa_pod *param) +wp_endpoint_stream_param (WpProxy * proxy, gint seq, const gchar * id_name, + guint32 index, guint32 next, const WpSpaPod *param) { WpEndpointStream *self = WP_ENDPOINT_STREAM (proxy); WpEndpointStreamPrivate *priv = wp_endpoint_stream_get_instance_private (self); - g_autoptr (GArray) changed_ids = NULL; - guint32 prop_id; + g_autoptr (GPtrArray) changed_ids = NULL; + const gchar * prop_id; - switch (id) { - case SPA_PARAM_PropInfo: + if (g_strcmp0 ("PropInfo", id_name) == 0) { wp_spa_props_register_from_prop_info (&priv->spa_props, param); - break; - case SPA_PARAM_Props: - changed_ids = g_array_new (FALSE, FALSE, sizeof (uint32_t)); + } + + else if (g_strcmp0 ("Props", id_name) == 0) { + changed_ids = g_ptr_array_new_with_free_func (g_free); wp_spa_props_store_from_props (&priv->spa_props, param, changed_ids); for (guint i = 0; i < changed_ids->len; i++) { - prop_id = g_array_index (changed_ids, uint32_t, i); + prop_id = g_ptr_array_index (changed_ids, i); g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, prop_id); } wp_proxy_set_feature_ready (WP_PROXY (self), WP_ENDPOINT_STREAM_FEATURE_CONTROLS); - break; } } @@ -224,26 +225,26 @@ get_name (WpEndpointStream * self) return priv->info->name; } -static const struct spa_pod * -get_control (WpEndpointStream * self, guint32 control_id) +WpSpaPod * +get_control (WpEndpointStream * self, const gchar * id_name) { WpEndpointStreamPrivate *priv = wp_endpoint_stream_get_instance_private (self); - return wp_spa_props_get_stored (&priv->spa_props, control_id); + return wp_spa_props_get_stored (&priv->spa_props, id_name); } static gboolean -set_control (WpEndpointStream * self, guint32 control_id, - const struct spa_pod * pod) +set_control (WpEndpointStream * self, const gchar * id_name, + const WpSpaPod * pod) { - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof (buf)); + g_autoptr (WpSpaPod) param = wp_spa_pod_new_object ( + "Props", "Props", + id_name, "P", pod, + NULL); /* our spa_props will be updated by the param event */ WP_PROXY_GET_CLASS (self)->set_param (WP_PROXY (self), SPA_PARAM_Props, 0, - spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - control_id, SPA_POD_Pod (pod))); + param); return TRUE; } @@ -282,7 +283,7 @@ wp_endpoint_stream_class_init (WpEndpointStreamClass * klass) */ signals[SIGNAL_CONTROL_CHANGED] = g_signal_new ( "control-changed", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); } /** @@ -303,146 +304,40 @@ wp_endpoint_stream_get_name (WpEndpointStream * self) /** * wp_endpoint_stream_get_control: * @self: the endpoint stream - * @control_id: the control id (a #WpEndpointControl) + * @id_name: the control id (a #WpEndpointControl) * - * Returns: (transfer none) (nullable): the `spa_pod` containing the value + * Returns: (transfer full) (nullable): the `spa_pod` containing the value * of this control, or %NULL if @control_id does not exist on this endpoint * stream */ -const struct spa_pod * -wp_endpoint_stream_get_control (WpEndpointStream * self, guint32 control_id) +WpSpaPod * +wp_endpoint_stream_get_control (WpEndpointStream * self, const gchar * id_name) { g_return_val_if_fail (WP_IS_ENDPOINT_STREAM (self), NULL); g_return_val_if_fail (WP_ENDPOINT_STREAM_GET_CLASS (self)->get_control, NULL); - return WP_ENDPOINT_STREAM_GET_CLASS (self)->get_control (self, control_id); -} - -/** - * wp_endpoint_stream_get_control_boolean: - * @self: the endpoint stream - * @control_id: the control id (a #WpEndpointControl) - * @value: (out): the boolean value of this control - * - * Returns: %TRUE on success, %FALSE if the control does not exist on this - * endpoint stream or if it is not a boolean - */ -gboolean -wp_endpoint_stream_get_control_boolean (WpEndpointStream * self, - guint32 control_id, gboolean * value) -{ - const struct spa_pod *pod = wp_endpoint_stream_get_control (self, control_id); - bool val; - if (pod && spa_pod_get_bool (pod, &val) == 0) { - *value = val; - return TRUE; - } - return FALSE; -} - -/** - * wp_endpoint_stream_get_control_int: - * @self: the endpoint stream - * @control_id: the control id (a #WpEndpointControl) - * @value: (out): the integer value of this control - * - * Returns: %TRUE on success, %FALSE if the control does not exist on this - * endpoint stream or if it is not an integer - */ -gboolean -wp_endpoint_stream_get_control_int (WpEndpointStream * self, guint32 control_id, - gint * value) -{ - const struct spa_pod *pod = wp_endpoint_stream_get_control (self, control_id); - return (pod && spa_pod_get_int (pod, value) == 0); -} - -/** - * wp_endpoint_stream_get_control_float: - * @self: the endpoint stream - * @control_id: the control id (a #WpEndpointControl) - * @value: (out): the floating-point number value of this control - * - * Returns: %TRUE on success, %FALSE if the control does not exist on this - * endpoint stream or if it is not a floating-point number - */ -gboolean -wp_endpoint_stream_get_control_float (WpEndpointStream * self, guint32 control_id, - gfloat * value) -{ - const struct spa_pod *pod = wp_endpoint_stream_get_control (self, control_id); - return (pod && spa_pod_get_float (pod, value) == 0); + return WP_ENDPOINT_STREAM_GET_CLASS (self)->get_control (self, id_name); } /** * wp_endpoint_stream_set_control: * @self: the endpoint stream - * @control_id: the control id (a #WpEndpointControl) + * @id_name: the control id (a #WpEndpointControl) * @value: the new value for this control, as a `spa_pod` * * Returns: %TRUE on success, %FALSE if an error occurred */ gboolean -wp_endpoint_stream_set_control (WpEndpointStream * self, guint32 control_id, - const struct spa_pod * value) +wp_endpoint_stream_set_control (WpEndpointStream * self, const gchar * id_name, + const WpSpaPod * value) { g_return_val_if_fail (WP_IS_ENDPOINT_STREAM (self), FALSE); g_return_val_if_fail (WP_ENDPOINT_STREAM_GET_CLASS (self)->set_control, FALSE); - return WP_ENDPOINT_STREAM_GET_CLASS (self)->set_control (self, control_id, + return WP_ENDPOINT_STREAM_GET_CLASS (self)->set_control (self, id_name, value); } -/** - * wp_endpoint_stream_set_control_boolean: - * @self: the endpoint stream - * @control_id: the control id (a #WpEndpointControl) - * @value: the new value for this control, as a boolean - * - * Returns: %TRUE on success, %FALSE if an error occurred - */ -gboolean -wp_endpoint_stream_set_control_boolean (WpEndpointStream * self, - guint32 control_id, gboolean value) -{ - gchar buffer[512]; - return wp_endpoint_stream_set_control (self, control_id, - wp_spa_props_build_pod (buffer, sizeof (buffer), SPA_POD_Bool (value), 0)); -} - -/** - * wp_endpoint_stream_set_control_int: - * @self: the endpoint stream - * @control_id: the control id (a #WpEndpointControl) - * @value: the new value for this control, as an integer - * - * Returns: %TRUE on success, %FALSE if an error occurred - */ -gboolean -wp_endpoint_stream_set_control_int (WpEndpointStream * self, guint32 control_id, - gint value) -{ - gchar buffer[512]; - return wp_endpoint_stream_set_control (self, control_id, - wp_spa_props_build_pod (buffer, sizeof (buffer), SPA_POD_Int (value), 0)); -} - -/** - * wp_endpoint_stream_set_control_float: - * @self: the endpoint stream - * @control_id: the control id (a #WpEndpointControl) - * @value: the new value for this control, as a floating-point number - * - * Returns: %TRUE on success, %FALSE if an error occurred - */ -gboolean -wp_endpoint_stream_set_control_float (WpEndpointStream * self, - guint32 control_id, gfloat value) -{ - gchar buffer[512]; - return wp_endpoint_stream_set_control (self, control_id, - wp_spa_props_build_pod (buffer, sizeof (buffer), SPA_POD_Float (value), 0)); -} /* WpImplEndpointStream */ @@ -515,10 +410,11 @@ impl_enum_params (void *object, int seq, switch (id) { case SPA_PARAM_PropInfo: { g_autoptr (GPtrArray) params = - wp_spa_props_build_propinfo (&priv->spa_props, &b); + wp_spa_props_build_propinfo (&priv->spa_props); for (guint i = start; i < params->len; i++) { - struct spa_pod *param = g_ptr_array_index (params, i); + WpSpaPod *pod = g_ptr_array_index (params, i); + const struct spa_pod *param = wp_spa_pod_get_spa_pod (pod); if (spa_pod_filter (&b, &result, param, filter) == 0) { pw_endpoint_stream_emit_param (&self->hooks, seq, id, i, i+1, result); @@ -531,7 +427,8 @@ impl_enum_params (void *object, int seq, } case SPA_PARAM_Props: { if (start == 0) { - struct spa_pod *param = wp_spa_props_build_props (&priv->spa_props, &b); + g_autoptr (WpSpaPod) pod = wp_spa_props_build_props (&priv->spa_props); + const struct spa_pod *param = wp_spa_pod_get_spa_pod (pod); if (spa_pod_filter (&b, &result, param, filter) == 0) { pw_endpoint_stream_emit_param (&self->hooks, seq, id, 0, 1, result); wp_proxy_handle_event_param (self, seq, id, 0, 1, result); @@ -566,13 +463,14 @@ impl_set_param (void *object, uint32_t id, uint32_t flags, WpImplEndpointStream *self = WP_IMPL_ENDPOINT_STREAM (object); WpEndpointStreamPrivate *priv = wp_endpoint_stream_get_instance_private (WP_ENDPOINT_STREAM (self)); - g_autoptr (GArray) changed_ids = NULL; + g_autoptr (GPtrArray) changed_ids = NULL; if (id != SPA_PARAM_Props) return -ENOENT; - changed_ids = g_array_new (FALSE, FALSE, sizeof (guint32)); - wp_spa_props_store_from_props (&priv->spa_props, param, changed_ids); + changed_ids = g_ptr_array_new_with_free_func (g_free); + g_autoptr (WpSpaPod) pod = wp_spa_pod_new_regular_wrap_copy (param); + wp_spa_props_store_from_props (&priv->spa_props, pod, changed_ids); /* notify subscribers */ if (self->subscribed) @@ -580,7 +478,7 @@ impl_set_param (void *object, uint32_t id, uint32_t flags, /* notify controls locally */ for (guint i = 0; i < changed_ids->len; i++) { - guint32 prop_id = g_array_index (changed_ids, guint32, i); + const gchar * prop_id = g_ptr_array_index (changed_ids, i); g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, prop_id); } diff --git a/lib/wp/endpoint-stream.h b/lib/wp/endpoint-stream.h index f27a76cbcdc40cd101cd2bd006727a0ae6a76a2b..51e575e297dd7186d09d87e7793be98869d6fae6 100644 --- a/lib/wp/endpoint-stream.h +++ b/lib/wp/endpoint-stream.h @@ -10,6 +10,7 @@ #define __WIREPLUMBER_ENDPOINT_STREAM_H__ #include "proxy.h" +#include "spa-pod.h" G_BEGIN_DECLS @@ -42,46 +43,21 @@ struct _WpEndpointStreamClass const gchar * (*get_name) (WpEndpointStream * self); - const struct spa_pod * (*get_control) (WpEndpointStream * self, - guint32 control_id); - gboolean (*set_control) (WpEndpointStream * self, guint32 control_id, - const struct spa_pod * value); + WpSpaPod * (*get_control) (WpEndpointStream * self, const gchar * id_name); + gboolean (*set_control) (WpEndpointStream * self, const gchar * id_name, + const WpSpaPod * value); }; WP_API const gchar * wp_endpoint_stream_get_name (WpEndpointStream * self); WP_API -const struct spa_pod * wp_endpoint_stream_get_control (WpEndpointStream * self, - guint32 control_id); - -WP_API -gboolean wp_endpoint_stream_get_control_boolean (WpEndpointStream * self, - guint32 control_id, gboolean * value); - -WP_API -gboolean wp_endpoint_stream_get_control_int (WpEndpointStream * self, - guint32 control_id, gint * value); - -WP_API -gboolean wp_endpoint_stream_get_control_float (WpEndpointStream * self, - guint32 control_id, gfloat * value); +WpSpaPod * wp_endpoint_stream_get_control (WpEndpointStream * self, + const gchar *id_name); WP_API gboolean wp_endpoint_stream_set_control (WpEndpointStream * self, - guint32 control_id, const struct spa_pod * value); - -WP_API -gboolean wp_endpoint_stream_set_control_boolean (WpEndpointStream * self, - guint32 control_id, gboolean value); - -WP_API -gboolean wp_endpoint_stream_set_control_int (WpEndpointStream * self, - guint32 control_id, gint value); - -WP_API -gboolean wp_endpoint_stream_set_control_float (WpEndpointStream * self, - guint32 control_id, gfloat value); + const gchar *id_name, const WpSpaPod * value); G_END_DECLS diff --git a/lib/wp/endpoint.c b/lib/wp/endpoint.c index 7a597c43d71d553379e34d361db3650ec2e14c83..c6dc234223a4edf4948315cf91b4d988731d281c 100644 --- a/lib/wp/endpoint.c +++ b/lib/wp/endpoint.c @@ -172,14 +172,14 @@ wp_endpoint_get_properties (WpProxy * proxy) static gint wp_endpoint_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { WpEndpointPrivate *priv = wp_endpoint_get_instance_private (WP_ENDPOINT (self)); int endpoint_enum_params_result; endpoint_enum_params_result = pw_endpoint_enum_params (priv->iface, 0, id, - start, num, filter); + start, num, wp_spa_pod_get_spa_pod (filter)); g_warn_if_fail (endpoint_enum_params_result >= 0); return endpoint_enum_params_result; @@ -201,14 +201,14 @@ wp_endpoint_subscribe_params (WpProxy * self, guint32 n_ids, guint32 *ids) static gint wp_endpoint_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param) + const WpSpaPod *param) { WpEndpointPrivate *priv = wp_endpoint_get_instance_private (WP_ENDPOINT (self)); int endpoint_set_param_result; endpoint_set_param_result = pw_endpoint_set_param (priv->iface, id, flags, - param); + wp_spa_pod_get_spa_pod (param)); g_warn_if_fail (endpoint_set_param_result >= 0); return endpoint_set_param_result; @@ -262,30 +262,29 @@ wp_endpoint_bound (WpProxy * proxy, guint32 id) } static void -wp_endpoint_param (WpProxy * proxy, gint seq, guint32 id, guint32 index, - guint32 next, const struct spa_pod *param) +wp_endpoint_param (WpProxy * proxy, gint seq, const gchar * id_name, + guint32 index, guint32 next, const WpSpaPod *param) { WpEndpoint *self = WP_ENDPOINT (proxy); WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); - g_autoptr (GArray) changed_ids = NULL; - guint32 prop_id; + g_autoptr (GPtrArray) changed_ids = NULL; + const gchar * prop_id; - switch (id) { - case SPA_PARAM_PropInfo: + if (g_strcmp0 ("PropInfo", id_name) == 0) { wp_spa_props_register_from_prop_info (&priv->spa_props, param); - break; - case SPA_PARAM_Props: - changed_ids = g_array_new (FALSE, FALSE, sizeof (uint32_t)); + } + + else if (g_strcmp0 ("Props", id_name) == 0) { + changed_ids = g_ptr_array_new_with_free_func (g_free); wp_spa_props_store_from_props (&priv->spa_props, param, changed_ids); for (guint i = 0; i < changed_ids->len; i++) { - prop_id = g_array_index (changed_ids, uint32_t, i); + prop_id = g_ptr_array_index (changed_ids, i); g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, prop_id); } wp_proxy_set_feature_ready (WP_PROXY (self), WP_ENDPOINT_FEATURE_CONTROLS); - break; } } @@ -310,26 +309,25 @@ get_direction (WpEndpoint * self) return priv->info->direction; } -static const struct spa_pod * -get_control (WpEndpoint * self, guint32 control_id) +static WpSpaPod * +get_control (WpEndpoint * self, const gchar * id_name) { WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); - return wp_spa_props_get_stored (&priv->spa_props, control_id); + return wp_spa_props_get_stored (&priv->spa_props, id_name); } static gboolean -set_control (WpEndpoint * self, guint32 control_id, - const struct spa_pod * pod) +set_control (WpEndpoint * self, const gchar * id_name, const WpSpaPod * pod) { - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof (buf)); + g_autoptr (WpSpaPod) param = wp_spa_pod_new_object ( + "Props", "Props", + id_name, "P", pod, + NULL); /* our spa_props will be updated by the param event */ WP_PROXY_GET_CLASS (self)->set_param (WP_PROXY (self), SPA_PARAM_Props, 0, - spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - control_id, SPA_POD_Pod (pod))); + param); return TRUE; } @@ -371,7 +369,7 @@ wp_endpoint_class_init (WpEndpointClass * klass) */ signals[SIGNAL_CONTROL_CHANGED] = g_signal_new ( "control-changed", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); } /** @@ -422,143 +420,36 @@ wp_endpoint_get_direction (WpEndpoint * self) /** * wp_endpoint_get_control: * @self: the endpoint - * @control_id: the control id (a #WpEndpointControl) + * @id_name: the control id name * - * Returns: (transfer none) (nullable): the `spa_pod` containing the value + * Returns: (transfer full) (nullable): the spa pod containing the value * of this control, or %NULL if @control_id does not exist on this endpoint */ -const struct spa_pod * -wp_endpoint_get_control (WpEndpoint * self, guint32 control_id) +WpSpaPod * +wp_endpoint_get_control (WpEndpoint * self, const gchar * id_name) { g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL); g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_control, NULL); - return WP_ENDPOINT_GET_CLASS (self)->get_control (self, control_id); -} - -/** - * wp_endpoint_get_control_boolean: - * @self: the endpoint - * @control_id: the control id (a #WpEndpointControl) - * @value: (out): the boolean value of this control - * - * Returns: %TRUE on success, %FALSE if the control does not exist on this - * endpoint or if it is not a boolean - */ -gboolean -wp_endpoint_get_control_boolean (WpEndpoint * self, guint32 control_id, - gboolean * value) -{ - const struct spa_pod *pod = wp_endpoint_get_control (self, control_id); - bool val; - if (pod && spa_pod_get_bool (pod, &val) == 0) { - *value = val; - return TRUE; - } - return FALSE; -} - -/** - * wp_endpoint_get_control_int: - * @self: the endpoint - * @control_id: the control id (a #WpEndpointControl) - * @value: (out): the integer value of this control - * - * Returns: %TRUE on success, %FALSE if the control does not exist on this - * endpoint or if it is not an integer - */ -gboolean -wp_endpoint_get_control_int (WpEndpoint * self, guint32 control_id, - gint * value) -{ - const struct spa_pod *pod = wp_endpoint_get_control (self, control_id); - return (pod && spa_pod_get_int (pod, value) == 0); -} - -/** - * wp_endpoint_get_control_float: - * @self: the endpoint - * @control_id: the control id (a #WpEndpointControl) - * @value: (out): the floating-point number value of this control - * - * Returns: %TRUE on success, %FALSE if the control does not exist on this - * endpoint or if it is not a floating-point number - */ -gboolean -wp_endpoint_get_control_float (WpEndpoint * self, guint32 control_id, - gfloat * value) -{ - const struct spa_pod *pod = wp_endpoint_get_control (self, control_id); - return (pod && spa_pod_get_float (pod, value) == 0); + return WP_ENDPOINT_GET_CLASS (self)->get_control (self, id_name); } /** * wp_endpoint_set_control: * @self: the endpoint - * @control_id: the control id (a #WpEndpointControl) + * @id_name: the control id name * @value: the new value for this control, as a `spa_pod` * * Returns: %TRUE on success, %FALSE if an error occurred */ gboolean -wp_endpoint_set_control (WpEndpoint * self, guint32 control_id, - const struct spa_pod * value) +wp_endpoint_set_control (WpEndpoint * self, const gchar * id_name, + const WpSpaPod * value) { g_return_val_if_fail (WP_IS_ENDPOINT (self), FALSE); g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->set_control, FALSE); - return WP_ENDPOINT_GET_CLASS (self)->set_control (self, control_id, value); -} - -/** - * wp_endpoint_set_control_boolean: - * @self: the endpoint - * @control_id: the control id (a #WpEndpointControl) - * @value: the new value for this control, as a boolean - * - * Returns: %TRUE on success, %FALSE if an error occurred - */ -gboolean -wp_endpoint_set_control_boolean (WpEndpoint * self, guint32 control_id, - gboolean value) -{ - gchar buffer[512]; - return wp_endpoint_set_control (self, control_id, wp_spa_props_build_pod ( - buffer, sizeof (buffer), SPA_POD_Bool (value), 0)); -} - -/** - * wp_endpoint_set_control_int: - * @self: the endpoint - * @control_id: the control id (a #WpEndpointControl) - * @value: the new value for this control, as an integer - * - * Returns: %TRUE on success, %FALSE if an error occurred - */ -gboolean -wp_endpoint_set_control_int (WpEndpoint * self, guint32 control_id, - gint value) -{ - gchar buffer[512]; - return wp_endpoint_set_control (self, control_id, wp_spa_props_build_pod ( - buffer, sizeof (buffer), SPA_POD_Int (value), 0)); -} - -/** - * wp_endpoint_set_control_float: - * @self: the endpoint - * @control_id: the control id (a #WpEndpointControl) - * @value: the new value for this control, as a floating-point number - * - * Returns: %TRUE on success, %FALSE if an error occurred - */ -gboolean -wp_endpoint_set_control_float (WpEndpoint * self, guint32 control_id, - gfloat value) -{ - gchar buffer[512]; - return wp_endpoint_set_control (self, control_id, wp_spa_props_build_pod ( - buffer, sizeof (buffer), SPA_POD_Float (value), 0)); + return WP_ENDPOINT_GET_CLASS (self)->set_control (self, id_name, value); } /** @@ -684,10 +575,11 @@ impl_enum_params (void *object, int seq, switch (id) { case SPA_PARAM_PropInfo: { g_autoptr (GPtrArray) params = - wp_spa_props_build_propinfo (&priv->spa_props, &b); + wp_spa_props_build_propinfo (&priv->spa_props); for (guint i = start; i < params->len; i++) { - struct spa_pod *param = g_ptr_array_index (params, i); + WpSpaPod *pod = g_ptr_array_index (params, i); + const struct spa_pod *param = wp_spa_pod_get_spa_pod (pod); if (spa_pod_filter (&b, &result, param, filter) == 0) { pw_endpoint_emit_param (&self->hooks, seq, id, i, i+1, result); @@ -700,7 +592,8 @@ impl_enum_params (void *object, int seq, } case SPA_PARAM_Props: { if (start == 0) { - struct spa_pod *param = wp_spa_props_build_props (&priv->spa_props, &b); + g_autoptr (WpSpaPod) pod = wp_spa_props_build_props (&priv->spa_props); + const struct spa_pod *param = wp_spa_pod_get_spa_pod (pod); if (spa_pod_filter (&b, &result, param, filter) == 0) { pw_endpoint_emit_param (&self->hooks, seq, id, 0, 1, result); wp_proxy_handle_event_param (self, seq, id, 0, 1, result); @@ -735,13 +628,14 @@ impl_set_param (void *object, uint32_t id, uint32_t flags, WpImplEndpoint *self = WP_IMPL_ENDPOINT (object); WpEndpointPrivate *priv = wp_endpoint_get_instance_private (WP_ENDPOINT (self)); - g_autoptr (GArray) changed_ids = NULL; + g_autoptr (GPtrArray) changed_ids = NULL; if (id != SPA_PARAM_Props) return -ENOENT; - changed_ids = g_array_new (FALSE, FALSE, sizeof (guint32)); - wp_spa_props_store_from_props (&priv->spa_props, param, changed_ids); + changed_ids = g_ptr_array_new_with_free_func (g_free); + g_autoptr (WpSpaPod) pod = wp_spa_pod_new_regular_wrap_copy (param); + wp_spa_props_store_from_props (&priv->spa_props, pod, changed_ids); /* notify subscribers */ if (self->subscribed) @@ -749,7 +643,7 @@ impl_set_param (void *object, uint32_t id, uint32_t flags, /* notify controls locally */ for (guint i = 0; i < changed_ids->len; i++) { - guint32 prop_id = g_array_index (changed_ids, guint32, i); + const gchar * prop_id = g_ptr_array_index (changed_ids, i); g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, prop_id); } @@ -1158,7 +1052,7 @@ wp_impl_endpoint_new (WpCore * core, WpSiEndpoint * item) /** * wp_impl_endpoint_register_control: * @self: the endpoint implementation - * @control: the control to make available + * @id_name: the control id name to make available * * Registers the specified @control as a SPA property of this endpoint, * making it appear to remote clients. @@ -1168,29 +1062,24 @@ wp_impl_endpoint_new (WpCore * core, WpSiEndpoint * item) */ void wp_impl_endpoint_register_control (WpImplEndpoint * self, - WpEndpointControl control) + const gchar *id_name) { WpImplEndpointPrivate *priv; g_return_if_fail (WP_IS_IMPL_ENDPOINT (self)); priv = wp_impl_endpoint_get_instance_private (self); - switch (control) { - case WP_ENDPOINT_CONTROL_VOLUME: - wp_spa_props_register (&priv->pp->spa_props, control, - "Volume", SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0)); - break; - case WP_ENDPOINT_CONTROL_MUTE: - wp_spa_props_register (&priv->pp->spa_props, control, - "Mute", SPA_POD_CHOICE_Bool (false)); - break; - case WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES: - wp_spa_props_register (&priv->pp->spa_props, control, - "Channel Volumes", SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0)); - break; - default: - g_warning ("Unknown endpoint control: 0x%x", control); - break; + if (g_strcmp0 ("volume", id_name) == 0) { + wp_spa_props_register (&priv->pp->spa_props, id_name, "Volume", + wp_spa_pod_new_choice ("Range", "f", 1.0, "f", 0.0, "f", 10.0, NULL)); + } else if (g_strcmp0 ("mute", id_name) == 0) { + wp_spa_props_register (&priv->pp->spa_props, id_name, "Mute", + wp_spa_pod_new_boolean (FALSE)); + } else if (g_strcmp0 ("channelVolumes", id_name) == 0) { + wp_spa_props_register (&priv->pp->spa_props, id_name, "Channel Volumes", + wp_spa_pod_new_choice ("Range", "f", 1.0, "f", 0.0, "f", 10.0, NULL)); + } else { + g_warning ("Unknown endpoint control: %s", id_name); } } #endif diff --git a/lib/wp/endpoint.h b/lib/wp/endpoint.h index 4e75d7851c9262adae374ca9a30d5bfce4eb1270..7bd15a18904bcb9a9bf3cad6e44dd50303657548 100644 --- a/lib/wp/endpoint.h +++ b/lib/wp/endpoint.h @@ -9,6 +9,7 @@ #ifndef __WIREPLUMBER_ENDPOINT_H__ #define __WIREPLUMBER_ENDPOINT_H__ +#include "spa-pod.h" #include "proxy.h" #include "endpoint-stream.h" #include "iterator.h" @@ -27,18 +28,6 @@ typedef enum { WP_DIRECTION_OUTPUT, } WpDirection; -/** - * WpEndpointControl: - * @WP_ENDPOINT_CONTROL_VOLUME: a volume control (type: float) - * @WP_ENDPOINT_CONTROL_MUTE: a mute control (type: boolean) - * @WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES: - */ -typedef enum { - WP_ENDPOINT_CONTROL_VOLUME = 0x10003 /* SPA_PROP_volume */, - WP_ENDPOINT_CONTROL_MUTE = 0x10004 /* SPA_PROP_mute */, - WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES = 0x10008 /* SPA_PROP_channelVolumes */, -} WpEndpointControl; - /** * WpEndpointFeatures: * @WP_ENDPOINT_FEATURE_CONTROLS: enables the use of the @@ -83,9 +72,9 @@ struct _WpEndpointClass const gchar * (*get_media_class) (WpEndpoint * self); WpDirection (*get_direction) (WpEndpoint * self); - const struct spa_pod * (*get_control) (WpEndpoint * self, guint32 control_id); - gboolean (*set_control) (WpEndpoint * self, guint32 control_id, - const struct spa_pod * value); + WpSpaPod * (*get_control) (WpEndpoint * self, const gchar * id_name); + gboolean (*set_control) (WpEndpoint * self, const gchar * id_name, + const WpSpaPod * value); }; WP_API @@ -98,36 +87,11 @@ WP_API WpDirection wp_endpoint_get_direction (WpEndpoint * self); WP_API -const struct spa_pod * wp_endpoint_get_control (WpEndpoint * self, - guint32 control_id); - -WP_API -gboolean wp_endpoint_get_control_boolean (WpEndpoint * self, guint32 control_id, - gboolean * value); - -WP_API -gboolean wp_endpoint_get_control_int (WpEndpoint * self, guint32 control_id, - gint * value); - -WP_API -gboolean wp_endpoint_get_control_float (WpEndpoint * self, guint32 control_id, - gfloat * value); - -WP_API -gboolean wp_endpoint_set_control (WpEndpoint * self, guint32 control_id, - const struct spa_pod * value); - -WP_API -gboolean wp_endpoint_set_control_boolean (WpEndpoint * self, guint32 control_id, - gboolean value); - -WP_API -gboolean wp_endpoint_set_control_int (WpEndpoint * self, guint32 control_id, - gint value); +WpSpaPod * wp_endpoint_get_control (WpEndpoint * self, const gchar * id_name); WP_API -gboolean wp_endpoint_set_control_float (WpEndpoint * self, guint32 control_id, - gfloat value); +gboolean wp_endpoint_set_control (WpEndpoint * self, const gchar * id_name, + const WpSpaPod * value); WP_API guint wp_endpoint_get_n_streams (WpEndpoint * self); diff --git a/lib/wp/node.c b/lib/wp/node.c index 1fc286bd674441f99f06feefc7d87d67276c633c..93946eb5c547fcd7068145283811697ad87822be 100644 --- a/lib/wp/node.c +++ b/lib/wp/node.c @@ -76,13 +76,14 @@ wp_node_get_properties (WpProxy * self) static gint wp_node_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { struct pw_node *pwp; int node_enum_params_result; pwp = (struct pw_node *) wp_proxy_get_pw_proxy (self); - node_enum_params_result = pw_node_enum_params (pwp, 0, id, start, num, filter); + node_enum_params_result = pw_node_enum_params (pwp, 0, id, start, num, + filter ? wp_spa_pod_get_spa_pod (filter) : NULL); g_warn_if_fail (node_enum_params_result >= 0); return node_enum_params_result; @@ -103,13 +104,14 @@ wp_node_subscribe_params (WpProxy * self, guint32 n_ids, guint32 *ids) static gint wp_node_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param) + const WpSpaPod *param) { struct pw_node *pwp; int node_set_param_result; pwp = (struct pw_node *) wp_proxy_get_pw_proxy (self); - node_set_param_result = pw_node_set_param (pwp, id, flags, param); + node_set_param_result = pw_node_set_param (pwp, id, flags, + wp_spa_pod_get_spa_pod (param)); g_warn_if_fail (node_set_param_result >= 0); return node_set_param_result; diff --git a/lib/wp/port.c b/lib/wp/port.c index 922bbac42d71c512b4bc5424d33f7b6e71033958..735e73373cf9773584d4722bbe69c7c290086139 100644 --- a/lib/wp/port.c +++ b/lib/wp/port.c @@ -66,13 +66,14 @@ wp_port_get_properties (WpProxy * self) static gint wp_port_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { struct pw_port *pwp; int port_enum_params_result; pwp = (struct pw_port *) wp_proxy_get_pw_proxy (self); - port_enum_params_result = pw_port_enum_params (pwp, 0, id, start, num, filter); + port_enum_params_result = pw_port_enum_params (pwp, 0, id, start, num, + wp_spa_pod_get_spa_pod (filter)); g_warn_if_fail (port_enum_params_result >= 0); return port_enum_params_result; diff --git a/lib/wp/private.h b/lib/wp/private.h index b064f5ea27631edb9a38867e7f20e72a75b419f4..3934b46822763b3ed6c46b3e79bd2c8246753ba3 100644 --- a/lib/wp/private.h +++ b/lib/wp/private.h @@ -149,7 +149,7 @@ WpSpaPod * wp_spa_pod_new_property_wrap_copy (WpSpaTypeTable table, guint32 key, guint32 flags, const struct spa_pod *pod); WpSpaPod * wp_spa_pod_new_control_wrap_copy (guint32 offset, guint32 type, const struct spa_pod *pod); -struct spa_pod *wp_spa_pod_get_spa_pod (WpSpaPod *self); +const struct spa_pod *wp_spa_pod_get_spa_pod (const WpSpaPod *self); /* spa props */ @@ -160,54 +160,22 @@ struct _WpSpaProps void wp_spa_props_clear (WpSpaProps * self); -void wp_spa_props_register_pod (WpSpaProps * self, - guint32 id, const gchar *name, const struct spa_pod *type); -gint wp_spa_props_register_from_prop_info (WpSpaProps * self, - const struct spa_pod * prop_info); +void wp_spa_props_register (WpSpaProps * self, + const char *id_name, const gchar *description, WpSpaPod *type); +gboolean wp_spa_props_register_from_prop_info (WpSpaProps * self, + const WpSpaPod * prop_info); -const struct spa_pod * wp_spa_props_get_stored (WpSpaProps * self, guint32 id); +WpSpaPod * +wp_spa_props_get_stored (WpSpaProps * self, const char * id_name); -gint wp_spa_props_store_pod (WpSpaProps * self, guint32 id, - const struct spa_pod * value); -gint wp_spa_props_store_from_props (WpSpaProps * self, - const struct spa_pod * props, GArray * changed_ids); +gboolean wp_spa_props_store (WpSpaProps * self, const char *id_name, + const WpSpaPod * value); +gboolean wp_spa_props_store_from_props (WpSpaProps * self, + const WpSpaPod * props, GPtrArray * changed_ids); -struct spa_pod * wp_spa_props_build_props (WpSpaProps * self, - struct spa_pod_builder * b); -GPtrArray * wp_spa_props_build_propinfo (WpSpaProps * self, - struct spa_pod_builder * b); -GPtrArray * wp_spa_props_build_all_pods (WpSpaProps * self, - struct spa_pod_builder * b); -struct spa_pod * wp_spa_props_build_update (WpSpaProps * self, guint32 id, - const struct spa_pod * value, struct spa_pod_builder * b); - -const struct spa_pod * wp_spa_props_build_pod_valist (gchar * buffer, - gsize size, va_list args); - -static inline const struct spa_pod * -wp_spa_props_build_pod (gchar * buffer, gsize size, ...) -{ - const struct spa_pod *ret; - va_list args; - va_start (args, size); - ret = wp_spa_props_build_pod_valist (buffer, size, args); - va_end (args); - return ret; -} - -#define wp_spa_props_register(self, id, name, ...) \ -({ \ - gchar b[512]; \ - wp_spa_props_register_pod (self, id, name, \ - wp_spa_props_build_pod (b, sizeof (b), ##__VA_ARGS__, NULL)); \ -}) - -#define wp_spa_props_store(self, id, ...) \ -({ \ - gchar b[512]; \ - wp_spa_props_store_pod (self, id, \ - wp_spa_props_build_pod (b, sizeof (b), ##__VA_ARGS__, NULL)); \ -}) +WpSpaPod * wp_spa_props_build_props (WpSpaProps * self); +GPtrArray * wp_spa_props_build_propinfo (WpSpaProps * self); +GPtrArray * wp_spa_props_build_all_pods (WpSpaProps * self); /* impl endpoint */ diff --git a/lib/wp/proxy.c b/lib/wp/proxy.c index 414153ec6b1b5573b2a94c595a990e8ae2e24b85..820d8a7c44ae5883a567fad485372c47a3c12095 100644 --- a/lib/wp/proxy.c +++ b/lib/wp/proxy.c @@ -368,7 +368,7 @@ wp_proxy_class_init (WpProxyClass * klass) wp_proxy_signals[SIGNAL_PARAM] = g_signal_new ( "param", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_FIRST, G_STRUCT_OFFSET (WpProxyClass, param), NULL, NULL, NULL, G_TYPE_NONE, 5, - G_TYPE_INT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_POINTER); + G_TYPE_INT, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, WP_TYPE_SPA_POD); } void @@ -667,7 +667,7 @@ wp_proxy_find_async_task (WpProxy * self, int seq, gboolean steal) */ gint wp_proxy_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { g_return_val_if_fail (WP_IS_PROXY (self), -EINVAL); @@ -721,7 +721,7 @@ enum_params_done (WpCore * core, GAsyncResult * res, gpointer data) */ void wp_proxy_enum_params_collect (WpProxy * self, - guint32 id, guint32 start, guint32 num, const struct spa_pod *filter, + guint32 id, guint32 start, guint32 num, const WpSpaPod * filter, GCancellable * cancellable, GAsyncReadyCallback callback, gpointer user_data) { @@ -733,7 +733,7 @@ wp_proxy_enum_params_collect (WpProxy * self, /* create task for enum_params */ task = g_task_new (self, cancellable, callback, user_data); - params = g_ptr_array_new_with_free_func (free); + params = g_ptr_array_new_with_free_func ((GDestroyNotify) wp_spa_pod_unref); g_task_set_task_data (task, params, (GDestroyNotify) g_ptr_array_unref); /* call enum_params */ @@ -756,7 +756,7 @@ wp_proxy_enum_params_collect (WpProxy * self, /** * wp_proxy_enum_params_collect_finish: * - * Returns: (transfer full) (element-type spa_pod*): + * Returns: (transfer full) (element-type WpSpaPod*): * the collected params */ GPtrArray * @@ -847,7 +847,7 @@ wp_proxy_subscribe_params_array (WpProxy * self, guint32 n_ids, guint32 *ids) */ gint wp_proxy_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param) + const WpSpaPod *param) { g_return_val_if_fail (WP_IS_PROXY (self), -EINVAL); @@ -866,14 +866,19 @@ wp_proxy_handle_event_param (void * proxy, int seq, uint32_t id, WpProxy *self = WP_PROXY (proxy); GTask *task; - g_signal_emit (self, wp_proxy_signals[SIGNAL_PARAM], 0, seq, id, index, next, - param); + const gchar *id_name = NULL; + wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PARAM, id, NULL, &id_name, NULL); + g_return_if_fail (id_name); + + g_autoptr (WpSpaPod) pod = wp_spa_pod_new_regular_wrap_copy (param); + g_signal_emit (self, wp_proxy_signals[SIGNAL_PARAM], 0, seq, id_name, index, + next, pod); /* if this param event was emited because of enum_params_collect(), * copy the param in the result array of that API */ task = wp_proxy_find_async_task (self, seq, FALSE); if (task) { GPtrArray *array = g_task_get_task_data (task); - g_ptr_array_add (array, spa_pod_copy (param)); + g_ptr_array_add (array, g_steal_pointer (&pod)); } } diff --git a/lib/wp/proxy.h b/lib/wp/proxy.h index 9144dddc938bd93f0f2b510c671a704cc33939ce..4808a7f9932b705551c114c5b33fd3653de26bbb 100644 --- a/lib/wp/proxy.h +++ b/lib/wp/proxy.h @@ -12,12 +12,12 @@ #include <gio/gio.h> +#include "spa-pod.h" #include "properties.h" G_BEGIN_DECLS struct pw_proxy; -struct spa_pod; typedef struct _WpCore WpCore; /** @@ -79,18 +79,18 @@ struct _WpProxyClass WpProperties * (*get_properties) (WpProxy * self); gint (*enum_params) (WpProxy * self, guint32 id, guint32 start, guint32 num, - const struct spa_pod * filter); + const WpSpaPod * filter); gint (*subscribe_params) (WpProxy * self, guint32 n_ids, guint32 *ids); gint (*set_param) (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod * param); + const WpSpaPod * param); /* signals */ void (*pw_proxy_created) (WpProxy * self, struct pw_proxy * proxy); void (*pw_proxy_destroyed) (WpProxy * self); void (*bound) (WpProxy * self, guint32 id); - void (*param) (WpProxy * self, gint seq, guint32 id, guint32 index, - guint32 next, const struct spa_pod *param); + void (*param) (WpProxy * self, gint seq, const gchar * id_name, guint32 index, + guint32 next, const WpSpaPod *param); }; /* features API */ @@ -142,11 +142,11 @@ guint32 wp_proxy_get_bound_id (WpProxy * self); WP_API gint wp_proxy_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter); + guint32 num, const WpSpaPod * filter); WP_API void wp_proxy_enum_params_collect (WpProxy * self, - guint32 id, guint32 start, guint32 num, const struct spa_pod *filter, + guint32 id, guint32 start, guint32 num, const WpSpaPod *filter, GCancellable * cancellable, GAsyncReadyCallback callback, gpointer user_data); @@ -163,7 +163,7 @@ gint wp_proxy_subscribe_params_array (WpProxy * self, guint32 n_ids, WP_API gint wp_proxy_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param); + const WpSpaPod *param); G_END_DECLS diff --git a/lib/wp/session.c b/lib/wp/session.c index c87fcc4f9b8db62498c03063b5e9182c45ea362a..baac77a452baf24577ee34ea94c46fda52cde446 100644 --- a/lib/wp/session.c +++ b/lib/wp/session.c @@ -22,6 +22,8 @@ #define G_LOG_DOMAIN "wp-session" +#include "spa-type.h" +#include "spa-pod.h" #include "session.h" #include "private.h" #include "error.h" @@ -98,13 +100,13 @@ wp_session_get_properties (WpProxy * proxy) static gint wp_session_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) + guint32 num, const WpSpaPod * filter) { WpSessionPrivate *priv = wp_session_get_instance_private (WP_SESSION (self)); int session_enum_params_result; session_enum_params_result = pw_session_enum_params (priv->iface, 0, id, - start, num, filter); + start, num, wp_spa_pod_get_spa_pod (filter)); g_warn_if_fail (session_enum_params_result >= 0); return session_enum_params_result; @@ -125,13 +127,13 @@ wp_session_subscribe_params (WpProxy * self, guint32 n_ids, guint32 *ids) static gint wp_session_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param) + const WpSpaPod *param) { WpSessionPrivate *priv = wp_session_get_instance_private (WP_SESSION (self)); int session_set_param_result; session_set_param_result = pw_session_set_param (priv->iface, id, flags, - param); + wp_spa_pod_get_spa_pod (param)); g_warn_if_fail (session_set_param_result >= 0); return session_set_param_result; @@ -174,35 +176,34 @@ wp_session_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy) } static void -wp_session_param (WpProxy * proxy, gint seq, guint32 id, guint32 index, - guint32 next, const struct spa_pod *param) +wp_session_param (WpProxy * proxy, gint seq, const gchar * id_name, + guint32 index, guint32 next, const WpSpaPod *param) { WpSession *self = WP_SESSION (proxy); WpSessionPrivate *priv = wp_session_get_instance_private (self); - g_autoptr (GArray) changed_ids = NULL; - guint32 prop_id; + g_autoptr (GPtrArray) changed_ids = NULL; + g_autoptr (WpSpaPod) stored = NULL; + const gchar * prop_id; gint32 value; - switch (id) { - case SPA_PARAM_PropInfo: + if (g_strcmp0 ("PropInfo", id_name) == 0) { wp_spa_props_register_from_prop_info (&priv->spa_props, param); - break; - case SPA_PARAM_Props: - changed_ids = g_array_new (FALSE, FALSE, sizeof (uint32_t)); + } + + else if (g_strcmp0 ("Props", id_name) == 0) { + changed_ids = g_ptr_array_new_with_free_func (g_free); wp_spa_props_store_from_props (&priv->spa_props, param, changed_ids); for (guint i = 0; i < changed_ids->len; i++) { - prop_id = g_array_index (changed_ids, uint32_t, i); - param = wp_spa_props_get_stored (&priv->spa_props, prop_id); - if (spa_pod_get_int (param, &value) == 0) { - g_signal_emit (self, signals[SIGNAL_DEFAULT_ENDPOINT_CHANGED], 0, - prop_id, value); - } + prop_id = g_ptr_array_index (changed_ids, i); + stored = wp_spa_props_get_stored (&priv->spa_props, prop_id); + wp_spa_pod_get_int (stored, &value); + g_signal_emit (self, signals[SIGNAL_DEFAULT_ENDPOINT_CHANGED], 0, prop_id, + value); } wp_proxy_set_feature_ready (WP_PROXY (self), WP_SESSION_FEATURE_DEFAULT_ENDPOINT); - break; } } @@ -348,31 +349,31 @@ wp_session_augment (WpProxy * proxy, WpProxyFeatures features) } static guint32 -get_default_endpoint (WpSession * self, WpDefaultEndpointType type) +get_default_endpoint (WpSession * self, const gchar * type_name) { WpSessionPrivate *priv = wp_session_get_instance_private (self); - const struct spa_pod *pod; + g_autoptr (WpSpaPod) pod = NULL; gint32 value; - pod = wp_spa_props_get_stored (&priv->spa_props, type); - if (pod && spa_pod_get_int (pod, &value) == 0) + pod = wp_spa_props_get_stored (&priv->spa_props, type_name); + if (pod && wp_spa_pod_get_int (pod, &value)) return (guint32) value; return 0; } static void -set_default_endpoint (WpSession * self, WpDefaultEndpointType type, guint32 id) +set_default_endpoint (WpSession * self, const gchar * type_name, guint32 id) { - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof (buf)); + g_autoptr (WpSpaPod) param = wp_spa_pod_new_object ( + "Props", "Props", + type_name, "i", id, + NULL); /* set the default endpoint id as a property param on the session; our spa_props cache will be updated by the param event */ WP_PROXY_GET_CLASS (self)->set_param (WP_PROXY (self), SPA_PARAM_Props, 0, - spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - type, SPA_POD_Int (id))); + param); } static void @@ -381,6 +382,17 @@ wp_session_class_init (WpSessionClass * klass) GObjectClass *object_class = (GObjectClass *) klass; WpProxyClass *proxy_class = (WpProxyClass *) klass; + /* Register custom wireplumber session types */ + wp_spa_type_register (WP_SPA_TYPE_TABLE_PROPS, + "Wp:Session:Default:Endpoint:Audio:Source", + "wp-session-default-endpoint-audio-source"); + wp_spa_type_register (WP_SPA_TYPE_TABLE_PROPS, + "Wp:Session:Default:Endpoint:Audio:Sink", + "wp-session-default-endpoint-audio-sink"); + wp_spa_type_register (WP_SPA_TYPE_TABLE_PROPS, + "Wp:Session:Default:Endpoint:Video:Source", + "wp-session-default-endpoint-video-source"); + object_class->finalize = wp_session_finalize; proxy_class->pw_iface_type = PW_TYPE_INTERFACE_Session; @@ -413,43 +425,43 @@ wp_session_class_init (WpSessionClass * klass) signals[SIGNAL_DEFAULT_ENDPOINT_CHANGED] = g_signal_new ( "default-endpoint-changed", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 2, - WP_TYPE_DEFAULT_ENDPOINT_TYPE, G_TYPE_UINT); + G_TYPE_STRING, G_TYPE_UINT); } /** * wp_session_get_default_endpoint: * @self: the session - * @type: the endpoint type + * @type_name: the endpoint type name * * Returns: the bound id of the default endpoint of this @type */ guint32 wp_session_get_default_endpoint (WpSession * self, - WpDefaultEndpointType type) + const gchar * type_name) { g_return_val_if_fail (WP_IS_SESSION (self), SPA_ID_INVALID); g_return_val_if_fail (WP_SESSION_GET_CLASS (self)->get_default_endpoint, SPA_ID_INVALID); - return WP_SESSION_GET_CLASS (self)->get_default_endpoint (self, type); + return WP_SESSION_GET_CLASS (self)->get_default_endpoint (self, type_name); } /** * wp_session_set_default_endpoint: * @self: the session - * @type: the endpoint type + * @type_name: the endpoint type name * @id: the bound id of the endpoint to set as the default for this @type * * Sets the default endpoint for this @type to be the one identified with @id */ void -wp_session_set_default_endpoint (WpSession * self, - WpDefaultEndpointType type, guint32 id) +wp_session_set_default_endpoint (WpSession * self, const char * type_name, + guint32 id) { g_return_if_fail (WP_IS_SESSION (self)); g_return_if_fail (WP_SESSION_GET_CLASS (self)->set_default_endpoint); - WP_SESSION_GET_CLASS (self)->set_default_endpoint (self, type, id); + WP_SESSION_GET_CLASS (self)->set_default_endpoint (self, type_name, id); } /** @@ -624,10 +636,11 @@ impl_enum_params (void *object, int seq, switch (id) { case SPA_PARAM_PropInfo: { g_autoptr (GPtrArray) params = - wp_spa_props_build_propinfo (&priv->spa_props, &b); + wp_spa_props_build_propinfo (&priv->spa_props); for (guint i = start; i < params->len; i++) { - struct spa_pod *param = g_ptr_array_index (params, i); + WpSpaPod *pod = g_ptr_array_index (params, i); + const struct spa_pod *param = wp_spa_pod_get_spa_pod (pod); pw_session_emit_param (&self->hooks, seq, id, i, i+1, param); wp_proxy_handle_event_param (self, seq, id, i, i+1, param); if (++count == num) @@ -637,7 +650,8 @@ impl_enum_params (void *object, int seq, } case SPA_PARAM_Props: { if (start == 0) { - struct spa_pod *param = wp_spa_props_build_props (&priv->spa_props, &b); + g_autoptr (WpSpaPod) pod = wp_spa_props_build_props (&priv->spa_props); + const struct spa_pod *param = wp_spa_pod_get_spa_pod (pod); if (spa_pod_filter (&b, &result, param, filter) == 0) { pw_session_emit_param (&self->hooks, seq, id, 0, 1, result); wp_proxy_handle_event_param (self, seq, id, 0, 1, result); @@ -656,7 +670,6 @@ static int impl_subscribe_params (void *object, uint32_t *ids, uint32_t n_ids) { WpImplSession *self = WP_IMPL_SESSION (object); - for (guint i = 0; i < n_ids; i++) { if (ids[i] == SPA_PARAM_Props) self->subscribed = TRUE; @@ -670,15 +683,15 @@ impl_set_param (void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { WpImplSession *self = WP_IMPL_SESSION (object); - WpSessionPrivate *priv = - wp_session_get_instance_private (WP_SESSION (self)); - g_autoptr (GArray) changed_ids = NULL; + WpSessionPrivate *priv = wp_session_get_instance_private (WP_SESSION (self)); + g_autoptr (GPtrArray) changed_ids = NULL; if (id != SPA_PARAM_Props) return -ENOENT; - changed_ids = g_array_new (FALSE, FALSE, sizeof (guint32)); - wp_spa_props_store_from_props (&priv->spa_props, param, changed_ids); + changed_ids = g_ptr_array_new_with_free_func (g_free); + g_autoptr (WpSpaPod) pod = wp_spa_pod_new_regular_wrap_copy (param); + wp_spa_props_store_from_props (&priv->spa_props, pod, changed_ids); /* notify subscribers */ if (self->subscribed) @@ -686,15 +699,13 @@ impl_set_param (void *object, uint32_t id, uint32_t flags, /* notify controls locally */ for (guint i = 0; i < changed_ids->len; i++) { - guint32 prop_id = g_array_index (changed_ids, guint32, i); - const struct spa_pod *param = - wp_spa_props_get_stored (&priv->spa_props, prop_id); + const gchar * prop_id = g_ptr_array_index (changed_ids, i); + g_autoptr (WpSpaPod) pod = wp_spa_props_get_stored (&priv->spa_props, + prop_id); gint value; - - if (spa_pod_get_int (param, &value) == 0) { - g_signal_emit (self, signals[SIGNAL_DEFAULT_ENDPOINT_CHANGED], 0, - prop_id, value); - } + if (wp_spa_pod_get_int (pod, &value)) + g_signal_emit (self, signals[SIGNAL_DEFAULT_ENDPOINT_CHANGED], 0, prop_id, + value); } return 0; @@ -736,16 +747,16 @@ wp_impl_session_init (WpImplSession * self) wp_proxy_set_feature_ready (WP_PROXY (self), WP_PROXY_FEATURE_INFO); - /* prepare DEFAULT_ENDPOINT */ + /* prepare default endpoint */ wp_spa_props_register (&priv->spa_props, - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE, - "Default Audio Source", SPA_POD_Int (0)); + "wp-session-default-endpoint-audio-source", + "Default Audio Source", wp_spa_pod_new_int (0)); wp_spa_props_register (&priv->spa_props, - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK, - "Default Audio Sink", SPA_POD_Int (0)); + "wp-session-default-endpoint-audio-sink", + "Default Audio Sink", wp_spa_pod_new_int (0)); wp_spa_props_register (&priv->spa_props, - WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE, - "Default Video Source", SPA_POD_Int (0)); + "wp-session-default-endpoint-video-source", + "Default Video Source", wp_spa_pod_new_int (0)); wp_proxy_set_feature_ready (WP_PROXY (self), WP_SESSION_FEATURE_DEFAULT_ENDPOINT); diff --git a/lib/wp/session.h b/lib/wp/session.h index 2bcb7dc80eab09bfa5a0fff7f9b3143d741355fc..d501105a8c0dde3c4d06f91959f8bf002f916a30 100644 --- a/lib/wp/session.h +++ b/lib/wp/session.h @@ -15,20 +15,6 @@ G_BEGIN_DECLS -/** - * WpDefaultEndpointType: - * @WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE: the default audio source (capture) - * endpoint - * @WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK: the default audio sink (playback) - * endpoint - * @WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE: the default video source endpoint - */ -typedef enum { - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE = 0x1000000 /* SPA_PROP_START_CUSTOM */, - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK, - WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE, -} WpDefaultEndpointType; - /** * WpSessionFeatures: * @WP_SESSION_FEATURE_DEFAULT_ENDPOINT: enables the use of @@ -74,19 +60,18 @@ struct _WpSessionClass { WpProxyClass parent_class; - guint32 (*get_default_endpoint) (WpSession * self, - WpDefaultEndpointType type); - void (*set_default_endpoint) (WpSession * self, - WpDefaultEndpointType type, guint32 id); + guint32 (*get_default_endpoint) (WpSession * self, const gchar * type_name); + void (*set_default_endpoint) (WpSession * self, const gchar * type_name, + guint32 id); }; WP_API guint32 wp_session_get_default_endpoint (WpSession * self, - WpDefaultEndpointType type); + const gchar * type_name); WP_API -void wp_session_set_default_endpoint (WpSession * self, - WpDefaultEndpointType type, guint32 id); +void wp_session_set_default_endpoint (WpSession * self, const gchar * type_name, + guint32 id); WP_API guint wp_session_get_n_endpoints (WpSession * self); diff --git a/lib/wp/spa-props.c b/lib/wp/spa-props.c index 772d7a18888a18953e0ac6b75783e8a0ef416229..108779a06b4c05829dd2f17a44a632e52457c23d 100644 --- a/lib/wp/spa-props.c +++ b/lib/wp/spa-props.c @@ -16,12 +16,14 @@ #include <spa/utils/defs.h> #include <spa/utils/result.h> +#include "spa-pod.h" +#include "spa-type.h" + struct entry { - guint32 id; - gchar *name; - struct spa_pod *type; - struct spa_pod *value; + gchar *id_name; + gchar *description; + WpSpaPod *value; }; struct entry * @@ -34,9 +36,9 @@ entry_new (void) static void entry_free (struct entry *e) { - g_free (e->name); - free (e->type); - free (e->value); + g_free (e->id_name); + g_free (e->description); + g_clear_pointer (&e->value, wp_spa_pod_unref); g_slice_free (struct entry, e); } @@ -47,217 +49,163 @@ wp_spa_props_clear (WpSpaProps * self) self->entries = NULL; } +// Takes ownership of pod void -wp_spa_props_register_pod (WpSpaProps * self, - guint32 id, const gchar *name, const struct spa_pod *type) +wp_spa_props_register (WpSpaProps * self, const char *id_name, + const gchar *description, WpSpaPod *pod) { struct entry *e = entry_new (); - e->id = id; - e->name = g_strdup (name); - e->type = spa_pod_copy (type); - - if (!spa_pod_is_choice (type)) - e->value = spa_pod_copy (type); - else - e->value = spa_pod_copy (SPA_POD_CHOICE_CHILD (type)); - + e->id_name = g_strdup (id_name); + e->description = g_strdup (description); + e->value = pod; self->entries = g_list_append (self->entries, e); } -gint +gboolean wp_spa_props_register_from_prop_info (WpSpaProps * self, - const struct spa_pod * prop_info) + const WpSpaPod * prop_info) { guint32 id; - gchar *name; - const struct spa_pod *type; - int res; - - res = spa_pod_parse_object (prop_info, - SPA_TYPE_OBJECT_PropInfo, NULL, - SPA_PROP_INFO_id, SPA_POD_Id (&id), - SPA_PROP_INFO_name, SPA_POD_String (&name), - SPA_PROP_INFO_type, SPA_POD_Pod (&type)); - - if (res < 0) { - g_debug ("Bad prop info object"); - return res; + const gchar *id_name, *description; + g_autoptr (WpSpaPod) type = NULL; + + + if (!wp_spa_pod_get_object (prop_info, + "PropInfo", NULL, + "id", "I", &id, + "name", "s", &description, + "type", "P", &type, + NULL)) { + g_assert_true (FALSE); + g_warning ("Bad prop info object"); + return FALSE; + } + + if (!wp_spa_type_get_by_id (WP_SPA_TYPE_TABLE_PROPS, id, NULL, &id_name, + NULL)) { + g_warning ("Id '%d' is not registered", id); + return FALSE; } - wp_spa_props_register_pod (self, id, name, type); - return 0; + wp_spa_props_register (self, id_name, description, g_steal_pointer (&type)); + return TRUE; } // get <-- cached -const struct spa_pod * -wp_spa_props_get_stored (WpSpaProps * self, guint32 id) +WpSpaPod * +wp_spa_props_get_stored (WpSpaProps * self, const char * id_name) { GList *l = self->entries; - while (l && ((struct entry *) l->data)->id != id) + struct entry * e; + while (l && g_strcmp0 (((struct entry *) l->data)->id_name, id_name) != 0) l = g_list_next (l); + if (!l) + return NULL; - return l ? ((struct entry *) l->data)->value : NULL; + e = (struct entry *) l->data; + return wp_spa_pod_is_choice (e->value) ? + wp_spa_pod_get_choice_child (e->value) : wp_spa_pod_ref (e->value); } // exported set --> cache + update(variant to pod -> push) -gint -wp_spa_props_store_pod (WpSpaProps * self, guint32 id, - const struct spa_pod * value) +gboolean +wp_spa_props_store (WpSpaProps * self, const char * id_name, + const WpSpaPod *value) { GList *l = self->entries; struct entry * e; - uint32_t expected_type; + g_autoptr (WpSpaPod) pod = NULL; - while (l && ((struct entry *) l->data)->id != id) + while (l && g_strcmp0 (((struct entry *) l->data)->id_name, id_name) != 0) l = g_list_next (l); - if (!l) - return -ESRCH; + return FALSE; e = (struct entry *) l->data; - expected_type = spa_pod_is_choice (e->type) ? - SPA_POD_CHOICE_VALUE_TYPE (e->type) : SPA_POD_TYPE (e->type); - if (SPA_POD_TYPE (value) != expected_type) - return -EINVAL; - -#define GET_VAL(pod, type) ((struct spa_pod_##type *) pod)->value - - switch (SPA_POD_TYPE (value)) { - //TODO bounds checking on integer types - case SPA_TYPE_Id: - if (GET_VAL (e->value, id) != GET_VAL (value, id)) { - GET_VAL (e->value, id) = GET_VAL (value, id); - return 1; - } - break; - case SPA_TYPE_Bool: - if (GET_VAL (e->value, bool) != GET_VAL (value, bool)) { - GET_VAL (e->value, bool) = GET_VAL (value, bool); - return 1; - } - break; - case SPA_TYPE_Int: - if (GET_VAL (e->value, int) != GET_VAL (value, int)) { - GET_VAL (e->value, int) = GET_VAL (value, int); - return 1; - } - break; - case SPA_TYPE_Long: - if (GET_VAL (e->value, long) != GET_VAL (value, long)) { - GET_VAL (e->value, long) = GET_VAL (value, long); - return 1; - } - break; - case SPA_TYPE_Fd: - if (GET_VAL (e->value, fd) != GET_VAL (value, fd)) { - GET_VAL (e->value, fd) = GET_VAL (value, fd); - return 1; - } - break; - case SPA_TYPE_Float: - if (GET_VAL (e->value, float) != GET_VAL (value, float)) { - GET_VAL (e->value, float) = GET_VAL (value, float); - return 1; - } - break; - case SPA_TYPE_Double: - if (GET_VAL (e->value, double) != GET_VAL (value, double)) { - GET_VAL (e->value, double) = GET_VAL (value, double); - return 1; - } - break; - case SPA_TYPE_Rectangle: - if (GET_VAL (e->value, rectangle).width != GET_VAL (value, rectangle).width || - GET_VAL (e->value, rectangle).height != GET_VAL (value, rectangle).height) { - GET_VAL (e->value, rectangle) = GET_VAL (value, rectangle); - return 1; - } - break; - case SPA_TYPE_Fraction: - if (GET_VAL (e->value, fraction).num != GET_VAL (value, fraction).num || - GET_VAL (e->value, fraction).denom != GET_VAL (value, fraction).denom) { - GET_VAL (e->value, fraction) = GET_VAL (value, fraction); - return 1; - } - break; - default: - g_clear_pointer (&e->value, free); - e->value = spa_pod_copy (value); - return 1; - } - -#undef GET_VAL + pod = wp_spa_pod_is_choice (e->value) ? + wp_spa_pod_get_choice_child (e->value) : wp_spa_pod_ref (e->value); - return 0; + return !wp_spa_pod_equal (pod, value) && wp_spa_pod_set_pod (pod, value); } // exported event set --> pod to variant -> cache // proxy event param --> pod to variant -> cache -gint -wp_spa_props_store_from_props (WpSpaProps * self, const struct spa_pod * props, - GArray * changed_ids) +gboolean +wp_spa_props_store_from_props (WpSpaProps * self, const WpSpaPod * props, + GPtrArray * changed_ids) { - const struct spa_pod_object *obj; - const struct spa_pod_prop *iter; - gint ret, count = 0; - - g_return_val_if_fail (!changed_ids || - g_array_get_element_size (changed_ids) == sizeof (uint32_t), -EINVAL); - - if (!spa_pod_is_object_type (props, SPA_TYPE_OBJECT_Props)) - return -EINVAL; - - obj = (const struct spa_pod_object *) props; - iter = spa_pod_prop_first (&obj->body); - - for (iter = spa_pod_prop_first (&obj->body); - spa_pod_prop_is_inside (&obj->body, obj->pod.size, iter); - iter = spa_pod_prop_next (iter)) { - if ((ret = wp_spa_props_store_pod (self, iter->key, &iter->value)) < 0) { - g_debug ("error storing property 0x%x: %s", iter->key, - spa_strerror (ret)); - } else if (ret == 1 && changed_ids) { - g_array_append_val (changed_ids, iter->key); - count++; - } + g_autoptr (WpSpaPod) pod = NULL; + g_autoptr (WpIterator) it = NULL; + GValue next = G_VALUE_INIT; + + g_return_val_if_fail (self, FALSE); + g_return_val_if_fail (props, FALSE); + g_return_val_if_fail (changed_ids, FALSE); + + if (g_strcmp0 (wp_spa_pod_get_object_type_name (props), "Props") != 0) + return FALSE; + + it = wp_spa_pod_iterator_new (props); + while (wp_iterator_next (it, &next)) { + WpSpaPod *p = g_value_get_boxed (&next); + const char *key_name = NULL; + g_autoptr (WpSpaPod) v = NULL; + wp_spa_pod_get_property (p, &key_name, &v); + + if (wp_spa_props_store (self, key_name, v) && changed_ids) + g_ptr_array_add (changed_ids, g_strdup (key_name)); + + g_value_unset (&next); } - return count; + return TRUE; } -struct spa_pod * -wp_spa_props_build_props (WpSpaProps * self, struct spa_pod_builder * b) +WpSpaPod * +wp_spa_props_build_props (WpSpaProps * self) { - struct spa_pod_frame f; + g_autoptr (WpSpaPodBuilder) b = NULL; GList *l; - spa_pod_builder_push_object (b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); + g_return_val_if_fail (self, NULL); + + b = wp_spa_pod_builder_new_object ("Props", "Props"); for (l = self->entries; l != NULL; l = g_list_next (l)) { struct entry * e = (struct entry *) l->data; - if (e->value) { - spa_pod_builder_prop (b, e->id, 0); - spa_pod_builder_primitive (b, e->value); + if (e->id_name && e->value) { + g_autoptr (WpSpaPod) pod = wp_spa_pod_is_choice (e->value) ? + wp_spa_pod_get_choice_child (e->value) : wp_spa_pod_ref (e->value); + wp_spa_pod_builder_add_property (b, e->id_name); + wp_spa_pod_builder_add_pod (b, pod); } } - return spa_pod_builder_pop (b, &f); + + return wp_spa_pod_builder_end (b); } GPtrArray * -wp_spa_props_build_propinfo (WpSpaProps * self, struct spa_pod_builder * b) +wp_spa_props_build_propinfo (WpSpaProps * self) { - GPtrArray *res = g_ptr_array_new (); + GPtrArray *res = g_ptr_array_new_with_free_func ( + (GDestroyNotify) wp_spa_pod_unref); GList *l; - struct spa_pod *pod; for (l = self->entries; l != NULL; l = g_list_next (l)) { struct entry * e = (struct entry *) l->data; - pod = spa_pod_builder_add_object (b, - SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, - SPA_PROP_INFO_id, SPA_POD_Id (e->id), - SPA_PROP_INFO_name, SPA_POD_String (e->name), - SPA_PROP_INFO_type, SPA_POD_Pod (e->type)); - g_ptr_array_add (res, pod); + guint32 id; + if (!wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PROPS, e->id_name, &id, + NULL, NULL)) { + g_warning ("Id name '%s' is not registered", e->id_name); + continue; + } + + g_ptr_array_add (res, wp_spa_pod_new_object ( + "PropInfo", "PropInfo", + "id", "I", id, + "name", "s", e->description, + "type", "P", e->value, + NULL)); } return res; @@ -265,40 +213,9 @@ wp_spa_props_build_propinfo (WpSpaProps * self, struct spa_pod_builder * b) // for exported update / prop_info + props GPtrArray * -wp_spa_props_build_all_pods (WpSpaProps * self, struct spa_pod_builder * b) +wp_spa_props_build_all_pods (WpSpaProps * self) { - GPtrArray *res; - struct spa_pod *pod; - - pod = wp_spa_props_build_props (self, b); - res = wp_spa_props_build_propinfo (self, b); - g_ptr_array_insert (res, 0, pod); - + GPtrArray *res = wp_spa_props_build_propinfo (self); + g_ptr_array_insert (res, 0, wp_spa_props_build_props (self)); return res; } - -// proxy set --> value to props object -> push -struct spa_pod * -wp_spa_props_build_update (WpSpaProps * self, guint32 id, - const struct spa_pod * value, struct spa_pod_builder * b) -{ - struct spa_pod_frame f; - - spa_pod_builder_push_object (b, &f, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); - spa_pod_builder_prop (b, id, 0); - spa_pod_builder_primitive (b, value); - return spa_pod_builder_pop (b, &f); -} - -const struct spa_pod * -wp_spa_props_build_pod_valist (gchar * buffer, gsize size, va_list args) -{ - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, size); - struct spa_pod_frame f; - void *pod; - - spa_pod_builder_push_struct (&b, &f); - spa_pod_builder_addv (&b, args); - pod = spa_pod_builder_pop (&b, &f); - return SPA_POD_CONTENTS (struct spa_pod_struct, pod); -} diff --git a/modules/module-config-policy/config-policy.c b/modules/module-config-policy/config-policy.c index 099888592eba31c0b4d99de8511f482900763cde..e3380f6e0b4410cdf887e3b176362b7ae5cdbba1 100644 --- a/modules/module-config-policy/config-policy.c +++ b/modules/module-config-policy/config-policy.c @@ -300,13 +300,13 @@ wp_config_policy_find_endpoint (WpPolicy *policy, GVariant *props, /* Otherwise, use the default session endpoint if the session is valid */ else if (session) { /* Get the default type */ - WpDefaultEndpointType type; + const gchar * type_name; switch (data->me.endpoint_data.direction) { case PW_DIRECTION_INPUT: - type = WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE; + type_name = "wp-session-default-endpoint-audio-source"; break; case PW_DIRECTION_OUTPUT: - type = WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK; + type_name = "wp-session-default-endpoint-audio-sink"; break; default: g_warn_if_reached (); @@ -321,7 +321,7 @@ wp_config_policy_find_endpoint (WpPolicy *policy, GVariant *props, /* Find the default session endpoint */ for (i = 0; i < endpoints->len; i++) { target = g_ptr_array_index (endpoints, i); - guint def_id = wp_session_get_default_endpoint (session, type); + guint def_id = wp_session_get_default_endpoint (session, type_name); if (def_id == wp_base_endpoint_get_global_id (target)) break; } diff --git a/modules/module-monitor.c b/modules/module-monitor.c index 91715be02af9389ccf56a22da7388b7c5c26f3bd..c02059cac5c4ee862be5d22705f88c58eef9173f 100644 --- a/modules/module-monitor.c +++ b/modules/module-monitor.c @@ -362,14 +362,11 @@ device_created (GObject * proxy, GAsyncResult * res, gpointer user_data) if (data->flags & FLAG_ACTIVATE_DEVICES && !(data->flags & FLAG_DBUS_RESERVATION)) { - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); - - wp_proxy_set_param (WP_PROXY (proxy), - SPA_PARAM_Profile, 0, - spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_ParamProfile, 0, - SPA_PARAM_PROFILE_index, SPA_POD_Int (1))); + g_autoptr (WpSpaPod) profile = wp_spa_pod_new_object ( + "Profile", "Profile", + "index", "i", 1, + NULL); + wp_proxy_set_param (WP_PROXY (proxy), SPA_PARAM_Profile, 0, profile); } } diff --git a/modules/module-monitor/reservation-data.c b/modules/module-monitor/reservation-data.c index 2688390929fac4632dfb1ac47293588a4d982520..57b5b6420fd100dae16ba391952a6c642f73cb30 100644 --- a/modules/module-monitor/reservation-data.c +++ b/modules/module-monitor/reservation-data.c @@ -47,8 +47,7 @@ on_reservation_acquired (GObject *obj, GAsyncResult *res, gpointer user_data) WP_MONITOR_DBUS_DEVICE_RESERVATION (obj); g_autoptr (GError) error = NULL; g_autoptr (WpProxy) device = NULL; - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof(buf)); + g_autoptr (WpSpaPod) profile = NULL; /* Finish */ if (!wp_monitor_dbus_device_reservation_async_finish (reserv, res, &error)) { @@ -62,10 +61,11 @@ on_reservation_acquired (GObject *obj, GAsyncResult *res, gpointer user_data) return; /* Set profile 1 */ - wp_proxy_set_param (device, SPA_PARAM_Profile, 0, - spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile, - SPA_PARAM_PROFILE_index, SPA_POD_Int(1))); + profile = wp_spa_pod_new_object ( + "Profile", "Profile", + "index", "i", 1, + NULL); + wp_proxy_set_param (device, SPA_PARAM_Profile, 0, profile); } static void @@ -74,8 +74,7 @@ on_reservation_release (WpMonitorDbusDeviceReservation *reservation, int forced, { g_autoptr (WpProxy) device = NULL; g_autoptr (WpCore) core = NULL; - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof(buf)); + g_autoptr (WpSpaPod) profile = NULL; /* Get the device and core */ device = g_weak_ref_get (&self->device); @@ -86,10 +85,11 @@ on_reservation_release (WpMonitorDbusDeviceReservation *reservation, int forced, return; /* Set profile 0 */ - wp_proxy_set_param (device, SPA_PARAM_Profile, 0, - spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile, - SPA_PARAM_PROFILE_index, SPA_POD_Int(0))); + profile = wp_spa_pod_new_object ( + "Profile", "Profile", + "index", "i", 0, + NULL); + wp_proxy_set_param (device, SPA_PARAM_Profile, 0, profile); /* Complete release on done */ wp_core_sync (core, NULL, (GAsyncReadyCallback)on_device_done, self); diff --git a/modules/module-pipewire/algorithms.c b/modules/module-pipewire/algorithms.c index a7a9c93cc9ef39089dad9f03378269ac72553c28..1b74353cce1bde69f644a68ddcac97a23a3cac88 100644 --- a/modules/module-pipewire/algorithms.c +++ b/modules/module-pipewire/algorithms.c @@ -129,9 +129,11 @@ invalid_argument: static enum spa_audio_format -select_format (uint32_t *vals, uint32_t n_vals, uint32_t choice) +select_format (WpSpaPod *value) { - enum spa_audio_format fmt_order[] = { + enum spa_audio_format ret = SPA_AUDIO_FORMAT_UNKNOWN; + + static enum spa_audio_format fmt_order[] = { /* float 32 is the best because it needs no conversion from our internal pipeline format */ SPA_AUDIO_FORMAT_F32, @@ -188,97 +190,149 @@ select_format (uint32_t *vals, uint32_t n_vals, uint32_t choice) SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_U8P, }; - uint32_t i, j, best = SPA_N_ELEMENTS(fmt_order); + guint32 best = SPA_N_ELEMENTS(fmt_order); + + /* Just return the value if it is not a choice value */ + if (!wp_spa_pod_is_choice (value)) { + wp_spa_pod_get_id (value, &ret); + return ret; + } - switch (choice) { - case SPA_CHOICE_None: - g_return_val_if_fail (n_vals != 0, SPA_AUDIO_FORMAT_UNKNOWN); - return vals[0]; + const gchar * choice_type_name = wp_spa_pod_get_choice_type_name (value); + + /* None */ + if (g_strcmp0 ("None", choice_type_name) == 0) { + g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value); + wp_spa_pod_get_id (child, &ret); + } - case SPA_CHOICE_Enum: - for (i = 0; i < n_vals; ++i, ++vals) { - for (j = 0; j < SPA_N_ELEMENTS(fmt_order); j++) { - if (*vals == fmt_order[j] && best > j) { + /* Enum */ + else if (g_strcmp0 ("Enum", choice_type_name) == 0) { + g_autoptr (WpIterator) it = wp_spa_pod_iterator_new (value); + GValue next = G_VALUE_INIT; + while (wp_iterator_next (it, &next)) { + enum spa_audio_format *format_id = (enum spa_audio_format *) + g_value_get_pointer (&next); + for (guint j = 0; j < SPA_N_ELEMENTS(fmt_order); j++) { + if (*format_id == fmt_order[j] && best > j) { best = j; break; } } + g_value_unset (&next); } - return (best < SPA_N_ELEMENTS(fmt_order)) ? - fmt_order[best] : SPA_AUDIO_FORMAT_UNKNOWN; - - default: - g_return_val_if_reached (SPA_AUDIO_FORMAT_UNKNOWN); + if (best < SPA_N_ELEMENTS(fmt_order)) + ret = fmt_order[best]; } + + return ret; } -static int32_t -select_rate (int32_t *vals, uint32_t n_vals, uint32_t choice) +static gint +select_rate (WpSpaPod *value) { - uint32_t i; - int32_t result = 0, min, max; + gint ret = 0; - switch (choice) { - case SPA_CHOICE_None: - g_return_val_if_fail (n_vals != 0, 0); - return vals[0]; + /* Just return the value if it is not a choice value */ + if (!wp_spa_pod_is_choice (value)) { + wp_spa_pod_get_int (value, &ret); + return ret; + } - case SPA_CHOICE_Enum: + const gchar * choice_type_name = wp_spa_pod_get_choice_type_name (value); + + /* None */ + if (g_strcmp0 ("None", choice_type_name) == 0) { + g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value); + wp_spa_pod_get_int (child, &ret); + } + + /* Enum */ + else if (g_strcmp0 ("Enum", choice_type_name) == 0) { /* pick the one closest to 48Khz */ - g_return_val_if_fail (n_vals != 0, 0); - result = vals[0]; - for (i = 1, ++vals; i < n_vals; ++i, ++vals) { - if (abs(*vals - 48000) < abs(result - 48000)) - result = *vals; + g_autoptr (WpIterator) it = wp_spa_pod_iterator_new (value); + GValue next = G_VALUE_INIT; + while (wp_iterator_next (it, &next)) { + gint *rate = (gint *) g_value_get_pointer (&next); + if (abs (*rate - 48000) < abs (ret - 48000)) + ret = *rate; + g_value_unset (&next); } - return result; + } - case SPA_CHOICE_Range: + /* Range */ + else if (g_strcmp0 ("Range", choice_type_name) == 0) { /* a range is typically 3 items: default, min, max; however, sometimes ALSA drivers give bad min & max values and pipewire picks a bad default... try to fix that here; the default should be the one closest to 48K */ - g_return_val_if_fail (n_vals == 3, 0); + g_autoptr (WpIterator) it = wp_spa_pod_iterator_new (value); + GValue next = G_VALUE_INIT; + gint vals[3]; + gint i = 0, min, max; + while (wp_iterator_next (it, &next) && i < 3) { + vals[i] = *(gint *) g_value_get_pointer (&next); + g_value_unset (&next); + i++; + } min = SPA_MIN (vals[1], vals[2]); max = SPA_MAX (vals[1], vals[2]); - return SPA_CLAMP(48000, min, max); - - default: - g_return_val_if_reached (0); + ret = SPA_CLAMP (48000, min, max); } + + return ret; } -static uint32_t -select_channels (uint32_t *vals, uint32_t n_vals, uint32_t choice) +static gint +select_channels (WpSpaPod *value) { - uint32_t i; - uint32_t result = 0; + gint ret = 0; - switch (choice) { - case SPA_CHOICE_None: - g_return_val_if_fail (n_vals != 0, 0); - return vals[0]; + /* Just return the value if it is not a choice value */ + if (!wp_spa_pod_is_choice (value)) { + wp_spa_pod_get_int (value, &ret); + return ret; + } + + const gchar * choice_type_name = wp_spa_pod_get_choice_type_name (value); + + /* None */ + if (g_strcmp0 ("None", choice_type_name) == 0) { + g_autoptr (WpSpaPod) child = wp_spa_pod_get_choice_child (value); + wp_spa_pod_get_int (child, &ret); + } - case SPA_CHOICE_Enum: + /* Enum */ + else if (g_strcmp0 ("Enum", choice_type_name) == 0) { /* choose the most channels */ - g_return_val_if_fail (n_vals != 0, 0); - result = vals[0]; - for (i = 1, ++vals; i < n_vals; ++i, ++vals) { - if (*vals > result) - result = *vals; + g_autoptr (WpIterator) it = wp_spa_pod_iterator_new (value); + GValue next = G_VALUE_INIT; + while (wp_iterator_next (it, &next)) { + gint *channel = (gint *) g_value_get_pointer (&next); + if (*channel > ret) + ret = *channel; + g_value_unset (&next); } - return result; + } - case SPA_CHOICE_Range: + /* Range */ + else if (g_strcmp0 ("Range", choice_type_name) == 0) { /* a range is typically 3 items: default, min, max; we want the most channels, but let's not trust max to really be the max... ALSA drivers can be broken */ - g_return_val_if_fail (n_vals == 3, 0); - return SPA_MAX (vals[1], vals[2]); - - default: - g_return_val_if_reached (0); + g_autoptr (WpIterator) it = wp_spa_pod_iterator_new (value); + GValue next = G_VALUE_INIT; + gint vals[3]; + gint i = 0; + while (wp_iterator_next (it, &next) && i < 3) { + vals[i] = *(gint *) g_value_get_pointer (&next); + g_value_unset (&next); + i++; + } + ret = SPA_MAX (vals[1], vals[2]); } + + return ret; } gboolean @@ -291,8 +345,7 @@ choose_sensible_raw_audio_format (GPtrArray *formats, raw = g_alloca (sizeof (struct spa_audio_info_raw) * formats->len); for (i = 0; i < formats->len; i++) { - struct spa_pod *pod; - struct spa_pod_prop *prop; + WpSpaPod *pod = g_ptr_array_index (formats, i); uint32_t mtype, mstype; /* initialize all fields to zero (SPA_AUDIO_FORMAT_UNKNOWN etc) and set @@ -300,14 +353,16 @@ choose_sensible_raw_audio_format (GPtrArray *formats, spa_memzero (&raw[i], sizeof(struct spa_audio_info_raw)); SPA_FLAG_SET(raw[i].flags, SPA_AUDIO_FLAG_UNPOSITIONED); - pod = g_ptr_array_index (formats, i); - - if (!spa_pod_is_object (pod)) { + if (!wp_spa_pod_is_object (pod)) { g_warning ("non-object POD appeared on formats list; this node is buggy"); continue; } - if (spa_format_parse (pod, &mtype, &mstype) < 0) { + if (!wp_spa_pod_get_object (pod, + "Format", NULL, + "mediaType", "I", &mtype, + "mediaSubtype", "I", &mstype, + NULL)) { g_warning ("format does not have media type / subtype"); continue; } @@ -316,60 +371,48 @@ choose_sensible_raw_audio_format (GPtrArray *formats, continue; /* go through the fields and populate raw[i] */ - SPA_POD_OBJECT_FOREACH ((struct spa_pod_object *) pod, prop) { - uint32_t type, size, n_vals, choice; - const struct spa_pod *val; - void *vals; - - if (prop->key == SPA_FORMAT_mediaType || - prop->key == SPA_FORMAT_mediaSubtype) - continue; - - val = spa_pod_get_values (&prop->value, &n_vals, &choice); - type = val->type; - size = val->size; - vals = SPA_POD_BODY(val); - -#define test_invariant(x) \ - G_STMT_START { \ - if (G_LIKELY (x)) ; \ - else { \ - g_warn_message (G_LOG_DOMAIN, __FILE__, __LINE__, G_STRFUNC, #x); \ - raw[i].format = SPA_AUDIO_FORMAT_UNKNOWN; \ - goto next; \ - } \ - } G_STMT_END - - switch (prop->key) { - case SPA_FORMAT_AUDIO_format: - test_invariant (type == SPA_TYPE_Id); - test_invariant (size == sizeof(uint32_t)); - raw[i].format = select_format ((uint32_t *) vals, n_vals, choice); - break; - case SPA_FORMAT_AUDIO_rate: - test_invariant (type == SPA_TYPE_Int); - test_invariant (size == sizeof(int32_t)); - raw[i].rate = select_rate ((int32_t *) vals, n_vals, choice); - break; - case SPA_FORMAT_AUDIO_channels: - test_invariant (type == SPA_TYPE_Int); - test_invariant (size == sizeof(uint32_t)); - raw[i].channels = select_channels ((uint32_t *) vals, n_vals, choice); - break; - case SPA_FORMAT_AUDIO_position: - /* just copy the array, there is no choice here */ - SPA_FLAG_CLEAR (raw[i].flags, SPA_AUDIO_FLAG_UNPOSITIONED); - spa_pod_copy_array (val, SPA_TYPE_Id, raw[i].position, - SPA_AUDIO_MAX_CHANNELS); - break; - default: - if (prop->value.type == SPA_TYPE_Choice) - SPA_POD_CHOICE_TYPE(&prop->value) = SPA_CHOICE_None; - break; + g_autoptr (WpIterator) it = wp_spa_pod_iterator_new (pod); + GValue next = G_VALUE_INIT; + while (wp_iterator_next (it, &next)) { + WpSpaPod *p = g_value_get_boxed (&next); + const gchar *key = NULL; + g_autoptr (WpSpaPod) value = NULL; + wp_spa_pod_get_property (p, &key, &value); + + /* format */ + if (g_strcmp0 (key, "format") == 0) { + raw[i].format = select_format (value); + } + + /* rate */ + else if (g_strcmp0 (key, "rate") == 0) { + raw[i].rate = select_rate (value); + } + + /* channels */ + else if (g_strcmp0 (key, "channels") == 0) { + raw[i].channels = select_channels (value); } + + /* position */ + else if (g_strcmp0 (key, "position") == 0) { + /* just copy the array, there is no choice here */ + g_return_val_if_fail (wp_spa_pod_is_array (value), FALSE); + SPA_FLAG_CLEAR (raw[i].flags, SPA_AUDIO_FLAG_UNPOSITIONED); + g_autoptr (WpIterator) array_it = wp_spa_pod_iterator_new (value); + GValue array_next = G_VALUE_INIT; + guint j = 0; + while (wp_iterator_next (array_it, &array_next)) { + guint32 *pos_id = (guint32 *)g_value_get_pointer (&array_next); + raw[i].position[j] = *pos_id; + g_value_unset (&array_next); + j++; + } + } + + g_value_unset (&next); } -next: /* figure out if this one is the best so far */ if (raw[i].format != SPA_AUDIO_FORMAT_UNKNOWN && raw[i].channels > most_channels ) { diff --git a/modules/module-pipewire/audio-softdsp-endpoint.c b/modules/module-pipewire/audio-softdsp-endpoint.c index ae4c748f55a2bc5034aca94051ce6935ad576d1a..576d67b7313c5721074a3cc1e8f59edb22e19f3f 100644 --- a/modules/module-pipewire/audio-softdsp-endpoint.c +++ b/modules/module-pipewire/audio-softdsp-endpoint.c @@ -142,29 +142,26 @@ endpoint_begin_fade (WpBaseEndpoint * ep, guint32 stream_id, guint duration, #if 0 static void -on_exported_control_changed (WpEndpoint * ep, guint32 control_id, +on_exported_control_changed (WpEndpoint * ep, const gchar *id_name, WpPwAudioSoftdspEndpoint *self) { - switch (control_id) { - case WP_ENDPOINT_CONTROL_VOLUME: { + g_autoptr (WpSpaPod) ctrl = NULL; + + if (g_strcmp0 (id_name, "volume") == 0) { gfloat vol; - wp_endpoint_get_control_float (ep, control_id, &vol); + ctrl = wp_endpoint_get_control (ep, id_name); + wp_spa_pod_get_float (ctrl, &vol); wp_audio_stream_set_volume (self->adapter, vol); - break; - } - case WP_ENDPOINT_CONTROL_MUTE: { + } else if (g_strcmp0 (id_name, "mute") == 0) { gboolean m; - wp_endpoint_get_control_boolean (ep, control_id, &m); + ctrl = wp_endpoint_get_control (ep, id_name); + wp_spa_pod_get_boolean (ctrl, &m); wp_audio_stream_set_mute (self->adapter, m); - break; - } - default: - break; } } static void -on_adapter_control_changed (WpAudioStream * s, guint32 control_id, +on_adapter_control_changed (WpAudioStream * s, const gchar *id_name, WpPwAudioSoftdspEndpoint *self) { /* block to avoid recursion - WpEndpoint emits the "control-changed" @@ -172,21 +169,14 @@ on_adapter_control_changed (WpAudioStream * s, guint32 control_id, g_signal_handlers_block_by_func (self->impl_ep, on_exported_control_changed, self); - switch (control_id) { - case WP_ENDPOINT_CONTROL_VOLUME: { + if (g_strcmp0 (id_name, "volume") == 0) { gfloat vol = wp_audio_stream_get_volume (s); - wp_endpoint_set_control_float (WP_ENDPOINT (self->impl_ep), - control_id, vol); - break; - } - case WP_ENDPOINT_CONTROL_MUTE: { + g_autoptr (WpSpaPod) vol_ctrl = wp_spa_pod_new_float (vol); + wp_endpoint_set_control (WP_ENDPOINT (self->impl_ep), id_name, vol_ctrl); + } else if (g_strcmp0 (id_name, "mute") == 0) { gboolean m = wp_audio_stream_get_mute (s); - wp_endpoint_set_control_boolean (WP_ENDPOINT (self->impl_ep), - control_id, m); - break; - } - default: - break; + g_autoptr (WpSpaPod) m_ctrl = wp_spa_pod_new_boolean (m); + wp_endpoint_set_control (WP_ENDPOINT (self->impl_ep), id_name, m_ctrl); } g_signal_handlers_unblock_by_func (self->impl_ep, @@ -220,17 +210,15 @@ do_export (WpPwAudioSoftdspEndpoint *self) g_autoptr (WpCore) core = wp_base_endpoint_get_core (WP_BASE_ENDPOINT (self)); g_autoptr (WpProperties) props = NULL; g_autoptr (WpProperties) extra_props = NULL; + g_autoptr (WpSpaPod) ctrl = NULL; g_return_if_fail (!self->impl_ep); self->impl_ep = wp_impl_endpoint_new (core); - wp_impl_endpoint_register_control (self->impl_ep, - WP_ENDPOINT_CONTROL_VOLUME); - wp_impl_endpoint_register_control (self->impl_ep, - WP_ENDPOINT_CONTROL_MUTE); - // wp_impl_endpoint_register_control (self->impl_ep, - // WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES); + wp_impl_endpoint_register_control (self->impl_ep, "volume"); + wp_impl_endpoint_register_control (self->impl_ep, "mute"); + // wp_impl_endpoint_register_control (self->impl_ep, "channelVolumes"); props = wp_proxy_get_properties (WP_PROXY (self->node)); @@ -252,10 +240,10 @@ do_export (WpPwAudioSoftdspEndpoint *self) wp_impl_endpoint_set_direction (self->impl_ep, wp_base_endpoint_get_direction (WP_BASE_ENDPOINT (self))); - wp_endpoint_set_control_float (WP_ENDPOINT (self->impl_ep), - WP_ENDPOINT_CONTROL_VOLUME, wp_audio_stream_get_volume (self->adapter)); - wp_endpoint_set_control_boolean (WP_ENDPOINT (self->impl_ep), - WP_ENDPOINT_CONTROL_MUTE, wp_audio_stream_get_mute (self->adapter)); + ctrl = wp_spa_pod_new_float (wp_audio_stream_get_volume (self->adapter)); + wp_endpoint_set_control (WP_ENDPOINT (self->impl_ep), "volume", ctrl); + ctrl = wp_spa_pod_new_boolean (wp_audio_stream_get_mute (self->adapter)); + wp_endpoint_set_control (WP_ENDPOINT (self->impl_ep), "mute", ctrl); g_signal_connect_object (self->impl_ep, "control-changed", (GCallback) on_exported_control_changed, self, 0); diff --git a/modules/module-pipewire/audio-softdsp-endpoint/adapter.c b/modules/module-pipewire/audio-softdsp-endpoint/adapter.c index bb8a3d096ca2c60e26bf1bea32e948ba6be550a2..206301e312a6abd75474720e05d1f9163771fe8c 100644 --- a/modules/module-pipewire/audio-softdsp-endpoint/adapter.c +++ b/modules/module-pipewire/audio-softdsp-endpoint/adapter.c @@ -38,6 +38,34 @@ G_DEFINE_TYPE_WITH_CODE (WpAudioAdapter, wp_audio_adapter, WP_TYPE_AUDIO_STREAM, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, wp_audio_adapter_async_initable_init)) +static WpSpaPod * +format_audio_raw_build (const struct spa_audio_info_raw *info) +{ + g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_object ( + "Format", "Format"); + wp_spa_pod_builder_add (builder, + "mediaType", "I", SPA_MEDIA_TYPE_audio, + "mediaSubtype", "I", SPA_MEDIA_SUBTYPE_raw, + "format", "I", info->format, + "rate", "i", info->rate, + "channels", "i", info->channels, + NULL); + + if (!SPA_FLAG_IS_SET (info->flags, SPA_AUDIO_FLAG_UNPOSITIONED)) { + /* Build the position array spa pod */ + g_autoptr (WpSpaPodBuilder) position_builder = wp_spa_pod_builder_new_array (); + for (guint i = 0; i < info->channels; i++) + wp_spa_pod_builder_add_id (position_builder, info->position[i]); + + /* Add the position property */ + wp_spa_pod_builder_add_property (builder, "position"); + g_autoptr (WpSpaPod) position = wp_spa_pod_builder_end (position_builder); + wp_spa_pod_builder_add_pod (builder, position); + } + + return wp_spa_pod_builder_end (builder); +} + static void on_proxy_enum_format_done (WpProxy *proxy, GAsyncResult *res, WpAudioAdapter *self) @@ -46,9 +74,9 @@ on_proxy_enum_format_done (WpProxy *proxy, GAsyncResult *res, g_autoptr (GError) error = NULL; enum pw_direction direction = wp_audio_stream_get_direction (WP_AUDIO_STREAM (self)); - uint8_t buf[1024]; - struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); struct spa_pod *param; + g_autoptr (WpSpaPod) pod = NULL; + g_autoptr (WpSpaPod) format = NULL; gboolean control; formats = wp_proxy_enum_params_collect_finish (proxy, res, &error); @@ -83,9 +111,8 @@ on_proxy_enum_format_done (WpProxy *proxy, GAsyncResult *res, } /* set the chosen device/client format on the node */ - param = spa_format_audio_raw_build (&pod_builder, SPA_PARAM_Format, - &self->format); - wp_proxy_set_param (proxy, SPA_PARAM_Format, 0, param); + format = format_audio_raw_build (&self->format); + wp_proxy_set_param (proxy, SPA_PARAM_Format, 0, format); /* now choose the DSP format: keep the chanels but use F32 plannar @ 48K */ self->format.format = SPA_AUDIO_FORMAT_F32P; @@ -95,22 +122,23 @@ on_proxy_enum_format_done (WpProxy *proxy, GAsyncResult *res, control = direction == PW_DIRECTION_INPUT; if (self->convert) { - param = spa_pod_builder_add_object(&pod_builder, - SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_convert), - SPA_PARAM_PORT_CONFIG_control, SPA_POD_Bool(control)); + pod = wp_spa_pod_new_object ("PortConfig", "PortConfig", + "direction", "I", pw_direction_reverse(direction), + "mode", "I", SPA_PARAM_PORT_CONFIG_MODE_convert, + "control", "b", control, + NULL); } else { - param = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, &self->format); - param = spa_pod_builder_add_object(&pod_builder, - SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp), - SPA_PARAM_PORT_CONFIG_control, SPA_POD_Bool(control), - SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); + /* now choose the DSP format: keep the chanels but use F32 plannar @ 48K */ + format = format_audio_raw_build (&self->format); + pod = wp_spa_pod_new_object ("PortConfig", "PortConfig", + "direction", "I", direction, + "mode", "I", SPA_PARAM_PORT_CONFIG_MODE_dsp, + "control", "b", control, + "format", "P", format, + NULL); } - wp_audio_stream_set_port_config (WP_AUDIO_STREAM (self), param); + wp_audio_stream_set_port_config (WP_AUDIO_STREAM (self), pod); wp_audio_stream_finish_port_config (WP_AUDIO_STREAM (self)); } diff --git a/modules/module-pipewire/audio-softdsp-endpoint/convert.c b/modules/module-pipewire/audio-softdsp-endpoint/convert.c index fc68a6f4287f53ff35da7550581f3dd16fe7f016..a61304e0c372a160b3a7fd14b52bb786402de02a 100644 --- a/modules/module-pipewire/audio-softdsp-endpoint/convert.c +++ b/modules/module-pipewire/audio-softdsp-endpoint/convert.c @@ -106,6 +106,34 @@ wp_audio_convert_event_info (WpProxy * proxy, GParamSpec *spec, } } +static WpSpaPod * +format_audio_raw_build (const struct spa_audio_info_raw *info) +{ + g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_object ( + "Format", "Format"); + wp_spa_pod_builder_add (builder, + "mediaType", "I", SPA_MEDIA_TYPE_audio, + "mediaSubtype", "I", SPA_MEDIA_SUBTYPE_raw, + "format", "I", info->format, + "rate", "i", info->rate, + "channels", "i", info->channels, + NULL); + + if (!SPA_FLAG_IS_SET (info->flags, SPA_AUDIO_FLAG_UNPOSITIONED)) { + /* Build the position array spa pod */ + g_autoptr (WpSpaPodBuilder) position_builder = wp_spa_pod_builder_new_array (); + for (guint i = 0; i < info->channels; i++) + wp_spa_pod_builder_add_id (position_builder, info->position[i]); + + /* Add the position property */ + wp_spa_pod_builder_add_property (builder, "position"); + g_autoptr (WpSpaPod) position = wp_spa_pod_builder_end (position_builder); + wp_spa_pod_builder_add_pod (builder, position); + } + + return wp_spa_pod_builder_end (builder); +} + static void on_audio_convert_core_done (WpCore *core, GAsyncResult *res, WpAudioConvert *self) @@ -113,10 +141,8 @@ on_audio_convert_core_done (WpCore *core, GAsyncResult *res, g_autoptr (GError) error = NULL; enum pw_direction direction = wp_audio_stream_get_direction (WP_AUDIO_STREAM (self)); - uint8_t buf[1024]; - struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf)); - struct spa_pod *format; - struct spa_pod *param; + g_autoptr (WpSpaPod) format = NULL; + g_autoptr (WpSpaPod) pod = NULL; gboolean control; wp_core_sync_finish (core, res, &error); @@ -129,8 +155,7 @@ on_audio_convert_core_done (WpCore *core, GAsyncResult *res, g_debug ("%s:%p setting format", G_OBJECT_TYPE_NAME (self), self); - format = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_Format, - &self->format); + format = format_audio_raw_build (&self->format); /* Only enable control port for input streams */ control = @@ -145,20 +170,20 @@ on_audio_convert_core_done (WpCore *core, GAsyncResult *res, same format, but with altered volume. In the future we need to consider writing a simpler volume node for this, as doing merge + split is heavy for our needs */ - param = spa_pod_builder_add_object(&pod_builder, - SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(pw_direction_reverse(direction)), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp), - SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(format)); - wp_audio_stream_set_port_config (WP_AUDIO_STREAM (self), param); - - param = spa_pod_builder_add_object(&pod_builder, - SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(direction), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp), - SPA_PARAM_PORT_CONFIG_control, SPA_POD_Bool(control), - SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(format)); - wp_audio_stream_set_port_config (WP_AUDIO_STREAM (self), param); + pod = wp_spa_pod_new_object ("PortConfig", "PortConfig", + "direction", "I", pw_direction_reverse(direction), + "mode", "I", SPA_PARAM_PORT_CONFIG_MODE_dsp, + "format", "P", format, + NULL); + wp_audio_stream_set_port_config (WP_AUDIO_STREAM (self), pod); + + pod = wp_spa_pod_new_object ("PortConfig", "PortConfig", + "direction", "I", direction, + "mode", "I", SPA_PARAM_PORT_CONFIG_MODE_dsp, + "control", "b", control, + "format", "P", format, + NULL); + wp_audio_stream_set_port_config (WP_AUDIO_STREAM (self), pod); wp_audio_stream_finish_port_config (WP_AUDIO_STREAM (self)); } diff --git a/modules/module-pipewire/audio-softdsp-endpoint/stream.c b/modules/module-pipewire/audio-softdsp-endpoint/stream.c index 1bb914898f4db6a535a16cf220e73131e116f8ab..efe01c209f2706cbae4cffa15379f20493e2ff66 100644 --- a/modules/module-pipewire/audio-softdsp-endpoint/stream.c +++ b/modules/module-pipewire/audio-softdsp-endpoint/stream.c @@ -17,10 +17,6 @@ #include "stream.h" #if !defined(HAVE_AUDIOFADE) -# define SPA_PROP_audioFadeDuration 0x30001 -# define SPA_PROP_audioFadeStep 0x30002 -# define SPA_PROP_audioFadeDirection 0x30003 -# define SPA_PROP_audioFadeType 0x30004 # define SPA_NAME_CONTROL_AUDIO_FADE_SOURCE "control.audio.fade.source" #endif @@ -101,14 +97,12 @@ audio_stream_event_param (WpProxy *proxy, int seq, uint32_t id, case SPA_PROP_volume: spa_pod_get_float(&prop->value, &volume); priv->volume = volume; - g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, - WP_ENDPOINT_CONTROL_VOLUME); + g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, "volume"); break; case SPA_PROP_mute: spa_pod_get_bool(&prop->value, &mute); priv->mute = mute; - g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, - WP_ENDPOINT_CONTROL_MUTE); + g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, "mute"); break; default: break; @@ -566,7 +560,7 @@ wp_audio_stream_class_init (WpAudioStreamClass * klass) signals[SIGNAL_CONTROL_CHANGED] = g_signal_new ( "control-changed", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_UINT); + G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING); } WpAudioStream * @@ -747,9 +741,7 @@ wp_audio_stream_begin_fade (WpAudioStream * self, guint duration, WpAudioStreamPrivate *priv = wp_audio_stream_get_instance_private (self); g_autoptr (WpCore) core = wp_audio_stream_get_core (self); GTask *task = NULL; - struct spa_pod *props; - uint8_t buffer[1024]; - struct spa_pod_builder b = { 0 }; + g_autoptr (WpSpaPod) props = NULL; /* Create the fade callback */ task = g_task_new (self, cancellable, callback, user_data); @@ -776,12 +768,13 @@ wp_audio_stream_begin_fade (WpAudioStream * self, guint duration, priv->fade_task = task; /* Send the fade */ - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - props = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Props, 0, - SPA_PROP_audioFadeDuration, SPA_POD_Int(duration), - SPA_PROP_audioFadeStep, SPA_POD_Double(step), - SPA_PROP_audioFadeDirection, SPA_POD_Id(direction), - SPA_PROP_audioFadeType, SPA_POD_Id(type)); + props = wp_spa_pod_new_object ( + "Props", "Props", + "audioFadeDuration", "i", duration, + "audioFadeStep", "d", step, + "audioFadeDirection", "I", direction, + "audioFadeType", "I", type, + NULL); wp_proxy_set_param (WP_PROXY (priv->audio_fade_source), SPA_PARAM_Props, 0, props); @@ -824,7 +817,7 @@ wp_audio_stream_init_task_finish (WpAudioStream * self, GError * err) void wp_audio_stream_set_port_config (WpAudioStream * self, - const struct spa_pod * param) + const WpSpaPod * param) { WpAudioStreamPrivate *priv = wp_audio_stream_get_instance_private (self); diff --git a/modules/module-pipewire/audio-softdsp-endpoint/stream.h b/modules/module-pipewire/audio-softdsp-endpoint/stream.h index 3604cc6a3dfcdc3bc280a7161820094795c83083..487a87d7954661e6e513599b24f4d9f0e6814106 100644 --- a/modules/module-pipewire/audio-softdsp-endpoint/stream.h +++ b/modules/module-pipewire/audio-softdsp-endpoint/stream.h @@ -45,7 +45,7 @@ void wp_audio_stream_begin_fade (WpAudioStream * self, guint duration, WpCore *wp_audio_stream_get_core (WpAudioStream * self); void wp_audio_stream_init_task_finish (WpAudioStream * self, GError * error); void wp_audio_stream_set_port_config (WpAudioStream * self, - const struct spa_pod * param); + const WpSpaPod * param); void wp_audio_stream_finish_port_config (WpAudioStream * self); G_END_DECLS diff --git a/modules/module-si-adapter.c b/modules/module-si-adapter.c index 0cd8d5b0c75d615f17629da06c22a5e47371665f..17f8a933d5bde527be35d66ba75626fa2f3782c4 100644 --- a/modules/module-si-adapter.c +++ b/modules/module-si-adapter.c @@ -260,6 +260,34 @@ on_ports_changed (WpObjectManager *om, WpTransition * transition) wp_transition_advance (transition); } +static WpSpaPod * +format_audio_raw_build (const struct spa_audio_info_raw *info) +{ + g_autoptr (WpSpaPodBuilder) builder = wp_spa_pod_builder_new_object ( + "Format", "Format"); + wp_spa_pod_builder_add (builder, + "mediaType", "I", SPA_MEDIA_TYPE_audio, + "mediaSubtype", "I", SPA_MEDIA_SUBTYPE_raw, + "format", "I", info->format, + "rate", "i", info->rate, + "channels", "i", info->channels, + NULL); + + if (!SPA_FLAG_IS_SET (info->flags, SPA_AUDIO_FLAG_UNPOSITIONED)) { + /* Build the position array spa pod */ + g_autoptr (WpSpaPodBuilder) position_builder = wp_spa_pod_builder_new_array (); + for (guint i = 0; i < info->channels; i++) + wp_spa_pod_builder_add_id (position_builder, info->position[i]); + + /* Add the position property */ + wp_spa_pod_builder_add_property (builder, "position"); + g_autoptr (WpSpaPod) position = wp_spa_pod_builder_end (position_builder); + wp_spa_pod_builder_add_pod (builder, position); + } + + return wp_spa_pod_builder_end (builder); +} + static void si_adapter_activate_execute_step (WpSessionItem * item, WpTransition * transition, guint step) @@ -283,30 +311,26 @@ si_adapter_activate_execute_step (WpSessionItem * item, break; case STEP_CONFIGURE_PORTS: { - uint8_t buf[1024]; - struct spa_pod_builder pod_builder = SPA_POD_BUILDER_INIT (buf, sizeof(buf)); - struct spa_pod *param; + g_autoptr (WpSpaPod) format = NULL; + g_autoptr (WpSpaPod) pod = NULL; /* set the chosen device/client format on the node */ - param = spa_format_audio_raw_build (&pod_builder, SPA_PARAM_Format, - &self->format); - wp_proxy_set_param (WP_PROXY (self->node), SPA_PARAM_Format, 0, param); + format = format_audio_raw_build (&self->format); + wp_proxy_set_param (WP_PROXY (self->node), SPA_PARAM_Format, 0, format); /* now choose the DSP format: keep the chanels but use F32 plannar @ 48K */ self->format.format = SPA_AUDIO_FORMAT_F32P; self->format.rate = 48000; - param = spa_format_audio_raw_build (&pod_builder, - SPA_PARAM_Format, &self->format); - param = spa_pod_builder_add_object (&pod_builder, - SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(self->direction), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp), - SPA_PARAM_PORT_CONFIG_monitor, SPA_POD_Bool(self->monitor), - SPA_PARAM_PORT_CONFIG_control, SPA_POD_Bool(self->control_port), - SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); - - wp_proxy_set_param (WP_PROXY (self->node), SPA_PARAM_PortConfig, 0, param); + format = format_audio_raw_build (&self->format); + pod = wp_spa_pod_new_object ("PortConfig", "PortConfig", + "direction", "I", self->direction, + "mode", "I", SPA_PARAM_PORT_CONFIG_MODE_dsp, + "monitor", "b", self->monitor, + "control", "b", self->control_port, + "format", "P", format, + NULL); + wp_proxy_set_param (WP_PROXY (self->node), SPA_PARAM_PortConfig, 0, pod); g_autoptr (WpCore) core = wp_proxy_get_core (WP_PROXY (self->node)); wp_core_sync (core, NULL, diff --git a/tests/modules/algorithms.c b/tests/modules/algorithms.c index 0993aa944cd4f21336798dd8bf23091cc641ffb5..9a7908f3d0ffbbc60c3469216a20d6944ec46ec1 100644 --- a/tests/modules/algorithms.c +++ b/tests/modules/algorithms.c @@ -19,76 +19,66 @@ static void test_choose_sensible_raw_audio_format (void) { + wp_spa_type_init (TRUE); + uint32_t layout[] = { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR }; - guint8 buffer[2048]; - struct spa_pod_builder b; - struct spa_pod_frame f; - struct spa_pod *param; struct spa_audio_info_raw info; - g_autoptr (GPtrArray) formats = g_ptr_array_new (); + g_autoptr (GPtrArray) formats = + g_ptr_array_new_with_free_func ((GDestroyNotify) wp_spa_pod_unref); /* test 1 */ g_ptr_array_remove_range (formats, 0, formats->len); - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - spa_pod_builder_push_object (&b, &f, SPA_TYPE_OBJECT_Format, 0); - spa_pod_builder_add (&b, - SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), - SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(3, - SPA_AUDIO_FORMAT_F32_OE, - SPA_AUDIO_FORMAT_S16, - SPA_AUDIO_FORMAT_S20), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(22000, 44100, 8000), - SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(2, 1, 8), - 0); - param = (struct spa_pod *) spa_pod_builder_pop (&b, &f); - g_assert_nonnull (param); - g_ptr_array_add (formats, param); - + g_autoptr (WpSpaPod) param1 = wp_spa_pod_new_object ( + "Format", "Format", + "mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio), + "mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), + "format", SPA_POD_CHOICE_ENUM_Id(3, + SPA_AUDIO_FORMAT_F32_OE, + SPA_AUDIO_FORMAT_S16, + SPA_AUDIO_FORMAT_S20), + "rate", SPA_POD_CHOICE_RANGE_Int(22000, 44100, 8000), + "channels", SPA_POD_CHOICE_RANGE_Int(2, 1, 8), + NULL); + g_assert_nonnull (param1); + g_ptr_array_add (formats, g_steal_pointer (¶m1)); g_assert_true (choose_sensible_raw_audio_format (formats, &info)); g_assert_cmpint (info.format, ==, SPA_AUDIO_FORMAT_S16); g_assert_cmpint (info.rate, ==, 44100); g_assert_cmpint (info.channels, ==, 8); g_assert_cmpint (info.flags, ==, SPA_AUDIO_FLAG_UNPOSITIONED); - /* test 2 */ g_ptr_array_remove_range (formats, 0, formats->len); - spa_pod_builder_init (&b, buffer, sizeof(buffer)); - spa_pod_builder_push_object (&b, &f, SPA_TYPE_OBJECT_Format, 0); - spa_pod_builder_add (&b, - SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), - SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(3, - SPA_AUDIO_FORMAT_S32, - SPA_AUDIO_FORMAT_U8, - SPA_AUDIO_FORMAT_F32), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(56000, 44100, 96000), - SPA_FORMAT_AUDIO_channels, SPA_POD_Int(2), - SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, 2, layout), - 0); - param = (struct spa_pod *) spa_pod_builder_pop (&b, &f); - g_assert_nonnull (param); - g_ptr_array_add (formats, param); - - spa_pod_builder_push_object (&b, &f, SPA_TYPE_OBJECT_Format, 0); - spa_pod_builder_add (&b, - SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), - SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), - SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(3, - SPA_AUDIO_FORMAT_S32, - SPA_AUDIO_FORMAT_U8, - SPA_AUDIO_FORMAT_F32), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(56000, 44100, 96000), - SPA_FORMAT_AUDIO_channels, SPA_POD_Int(5), - SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, 5, layout), - 0); - param = (struct spa_pod *) spa_pod_builder_pop (&b, &f); - g_assert_nonnull (param); - g_ptr_array_add (formats, param); - + g_autoptr (WpSpaPod) param2 = wp_spa_pod_new_object ( + "Format", "Format", + "mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio), + "mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), + "format", SPA_POD_CHOICE_ENUM_Id(3, + SPA_AUDIO_FORMAT_S32, + SPA_AUDIO_FORMAT_U8, + SPA_AUDIO_FORMAT_F32), + "rate", SPA_POD_CHOICE_RANGE_Int(56000, 44100, 96000), + "channels", SPA_POD_Int(2), + "position", SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, 2, layout), + NULL); + g_assert_nonnull (param2); + g_ptr_array_add (formats, g_steal_pointer (¶m2)); + g_autoptr (WpSpaPod) param3 = wp_spa_pod_new_object ( + "Format", "Format", + "mediaType", SPA_POD_Id(SPA_MEDIA_TYPE_audio), + "mediaSubtype", SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), + "format", SPA_POD_CHOICE_ENUM_Id(3, + SPA_AUDIO_FORMAT_S32, + SPA_AUDIO_FORMAT_U8, + SPA_AUDIO_FORMAT_F32), + "rate", SPA_POD_CHOICE_RANGE_Int(56000, 44100, 96000), + "channels", SPA_POD_Int(5), + "position", SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, 5, layout), + NULL); + g_assert_nonnull (param3); + g_ptr_array_add (formats, g_steal_pointer (¶m3)); g_assert_true (choose_sensible_raw_audio_format (formats, &info)); g_assert_cmpint (info.format, ==, SPA_AUDIO_FORMAT_F32); g_assert_cmpint (info.rate, ==, 48000); @@ -100,6 +90,8 @@ test_choose_sensible_raw_audio_format (void) g_assert_cmpint (info.position[3], ==, layout[3]); g_assert_cmpint (info.position[4], ==, layout[4]); g_assert_cmpint (info.position[5], ==, 0); + + wp_spa_type_deinit (); } int diff --git a/tests/wp/endpoint.c b/tests/wp/endpoint.c index b9d944371c62825712f3cf88f2f88ce9bcb1db6c..06e2aabd65bbb3d23c89a6a511b28eb8971dbd8f 100644 --- a/tests/wp/endpoint.c +++ b/tests/wp/endpoint.c @@ -159,6 +159,8 @@ test_endpoint_disconnected (WpCore *core, TestEndpointFixture *fixture) static void test_endpoint_setup (TestEndpointFixture *self, gconstpointer user_data) { + wp_spa_type_init (TRUE); + g_autoptr (WpProperties) props = NULL; wp_test_server_setup (&self->server); @@ -208,6 +210,8 @@ test_endpoint_teardown (TestEndpointFixture *self, gconstpointer user_data) g_clear_pointer (&self->loop, g_main_loop_unref); g_clear_pointer (&self->context, g_main_context_unref); wp_test_server_teardown (&self->server); + + wp_spa_type_deinit (); } static void @@ -320,10 +324,9 @@ test_endpoint_basic_session_bound (WpProxy * session, GAsyncResult * res, #if 0 static void test_endpoint_basic_control_changed (WpEndpoint * endpoint, - guint32 control_id, TestEndpointFixture *fixture) + const gchar * id_name, TestEndpointFixture *fixture) { - g_debug ("endpoint changed: %s (0x%x)", G_OBJECT_TYPE_NAME (endpoint), - control_id); + g_debug ("endpoint changed: %s (%s)", G_OBJECT_TYPE_NAME (endpoint), id_name); g_assert_true (WP_IS_ENDPOINT (endpoint)); @@ -351,6 +354,7 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) g_autoptr (WpImplSession) session = NULL; // gfloat float_value; // gboolean boolean_value; + // g_autoptr (WpSpaPod) ctrl = NULL; /* set up the export side */ g_signal_connect (fixture->export_om, "object-added", @@ -467,9 +471,9 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) (GCallback) test_endpoint_basic_notify_properties, fixture); /* change control on the proxy */ - g_assert_true (wp_endpoint_set_control_float ( - WP_ENDPOINT (fixture->proxy_endpoint), - WP_ENDPOINT_CONTROL_VOLUME, 1.0f)); + ctrl = wp_spa_pod_new_float (1.0f); + g_assert_true (wp_endpoint_set_control (WP_ENDPOINT (fixture->proxy_endpoint), + "volume", ctrl)); /* run until the change is on both sides */ fixture->n_events = 0; @@ -478,26 +482,28 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) /* test round 2: verify the value change on both sides */ - g_assert_true (wp_endpoint_get_control_float ( - WP_ENDPOINT (fixture->proxy_endpoint), - WP_ENDPOINT_CONTROL_VOLUME, &float_value)); - g_assert_true (wp_endpoint_get_control_boolean ( - WP_ENDPOINT (fixture->proxy_endpoint), - WP_ENDPOINT_CONTROL_MUTE, &boolean_value)); + ctrl = wp_endpoint_get_control (WP_ENDPOINT (fixture->proxy_endpoint), "volume"); + g_assert_nonnull (ctrl); + g_assert_true (wp_spa_pod_get_float (ctrl, &float_value)); + ctrl = wp_endpoint_get_control (WP_ENDPOINT (fixture->proxy_endpoint), "mute"); + g_assert_nonnull (ctrl); + g_assert_true (wp_spa_pod_get_boolean (ctrl, &boolean_value)); g_assert_cmpfloat_with_epsilon (float_value, 1.0f, 0.001); g_assert_cmpint (boolean_value, ==, TRUE); - g_assert_true (wp_endpoint_get_control_float (WP_ENDPOINT (endpoint), - WP_ENDPOINT_CONTROL_VOLUME, &float_value)); - g_assert_true (wp_endpoint_get_control_boolean (WP_ENDPOINT (endpoint), - WP_ENDPOINT_CONTROL_MUTE, &boolean_value)); + ctrl = wp_endpoint_get_control (WP_ENDPOINT (endpoint), "volume"); + g_assert_nonnull (ctrl); + g_assert_true (wp_spa_pod_get_float (ctrl, &float_value)); + ctrl = wp_endpoint_get_control (WP_ENDPOINT (endpoint), "mute"); + g_assert_nonnull (ctrl); + g_assert_true (wp_spa_pod_get_boolean (ctrl, &boolean_value)); g_assert_cmpfloat_with_epsilon (float_value, 1.0f, 0.001); g_assert_cmpint (boolean_value, ==, TRUE); /* change control on the impl */ fixture->n_events = 0; - g_assert_true (wp_endpoint_set_control_boolean (WP_ENDPOINT (endpoint), - WP_ENDPOINT_CONTROL_MUTE, FALSE)); + ctrl = wp_spa_pod_new_boolean (FALSE); + g_assert_true (wp_endpoint_set_control (WP_ENDPOINT (endpoint), "mute", ctrl)); /* run until the change is on both sides */ g_main_loop_run (fixture->loop); @@ -505,19 +511,21 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) /* test round 3: verify the value change on both sides */ - g_assert_true (wp_endpoint_get_control_float ( - WP_ENDPOINT (fixture->proxy_endpoint), - WP_ENDPOINT_CONTROL_VOLUME, &float_value)); - g_assert_true (wp_endpoint_get_control_boolean ( - WP_ENDPOINT (fixture->proxy_endpoint), - WP_ENDPOINT_CONTROL_MUTE, &boolean_value)); + ctrl = wp_endpoint_get_control (WP_ENDPOINT (fixture->proxy_endpoint), "volume"); + g_assert_nonnull (ctrl); + g_assert_true (wp_spa_pod_get_float (ctrl, &float_value)); + ctrl = wp_endpoint_get_control (WP_ENDPOINT (fixture->proxy_endpoint), "mute"); + g_assert_nonnull (ctrl); + g_assert_true (wp_spa_pod_get_boolean (ctrl, &boolean_value)); g_assert_cmpfloat_with_epsilon (float_value, 1.0f, 0.001); g_assert_cmpint (boolean_value, ==, FALSE); - g_assert_true (wp_endpoint_get_control_float (WP_ENDPOINT (endpoint), - WP_ENDPOINT_CONTROL_VOLUME, &float_value)); - g_assert_true (wp_endpoint_get_control_boolean (WP_ENDPOINT (endpoint), - WP_ENDPOINT_CONTROL_MUTE, &boolean_value)); + ctrl = wp_endpoint_get_control (WP_ENDPOINT (endpoint), "volume"); + g_assert_nonnull (ctrl); + g_assert_true (wp_spa_pod_get_float (ctrl, &float_value)); + ctrl = wp_endpoint_get_control (WP_ENDPOINT (endpoint), "mute"); + g_assert_nonnull (ctrl); + g_assert_true (wp_spa_pod_get_boolean (ctrl, &boolean_value)); g_assert_cmpfloat_with_epsilon (float_value, 1.0f, 0.001); g_assert_cmpint (boolean_value, ==, FALSE); diff --git a/tests/wp/proxy.c b/tests/wp/proxy.c index f0fa81c5f2c7e3d1496b7f07b606e4eb91f69be2..df311e0dfd60c5b85e5ead28037df08b41c6c97a 100644 --- a/tests/wp/proxy.c +++ b/tests/wp/proxy.c @@ -173,8 +173,8 @@ test_node_enum_params_done (WpProxy *node, GAsyncResult *res, g_assert_cmpint (params->len, ==, data->n_params); for (i = 0; i < params->len; i++) { - struct spa_pod *pod = g_ptr_array_index(params, i); - g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo)); + WpSpaPod *pod = g_ptr_array_index (params, i); + g_assert_cmpstr ("PropInfo", ==, wp_spa_pod_get_object_type_name (pod)); } g_main_loop_quit (data->fixture->loop); @@ -213,8 +213,9 @@ test_node_object_added (WpObjectManager *om, WpProxy *proxy, g_signal_connect (proxy, "param", (GCallback) test_node_param, param_data); + g_autoptr (WpSpaPod) filter = wp_spa_pod_new_none (); wp_proxy_enum_params_collect (proxy, SPA_PARAM_PropInfo, 0, -1, - NULL, NULL, (GAsyncReadyCallback) test_node_enum_params_done, + filter, NULL, (GAsyncReadyCallback) test_node_enum_params_done, param_data); } diff --git a/tests/wp/session.c b/tests/wp/session.c index 20da891bcb33836a32b31eee274150447118a79d..5709c0fc179f5727003bb278f3284e2c43b5e442 100644 --- a/tests/wp/session.c +++ b/tests/wp/session.c @@ -57,6 +57,9 @@ test_session_disconnected (WpCore *core, TestSessionFixture *fixture) static void test_session_setup (TestSessionFixture *self, gconstpointer user_data) { + /* Register custom wireplumber session types */ + wp_spa_type_init (TRUE); + g_autoptr (WpProperties) props = NULL; wp_test_server_setup (&self->server); @@ -106,6 +109,8 @@ test_session_teardown (TestSessionFixture *self, gconstpointer user_data) g_clear_pointer (&self->loop, g_main_loop_unref); g_clear_pointer (&self->context, g_main_context_unref); wp_test_server_teardown (&self->server); + + wp_spa_type_deinit (); } static void @@ -187,10 +192,10 @@ test_session_basic_export_done (WpProxy * session, GAsyncResult * res, static void test_session_basic_default_endpoint_changed (WpSession * session, - WpDefaultEndpointType type, guint32 id, TestSessionFixture *fixture) + const char *type_name, guint32 id, TestSessionFixture *fixture) { - g_debug ("endpoint changed: %s (%u, %u)", G_OBJECT_TYPE_NAME (session), - type, id); + g_debug ("endpoint changed: %s (%s, %u)", G_OBJECT_TYPE_NAME (session), + type_name, id); g_assert_true (WP_IS_SESSION (session)); @@ -243,9 +248,9 @@ test_session_basic (TestSessionFixture *fixture, gconstpointer data) session = wp_impl_session_new (fixture->export_core); wp_impl_session_set_property (session, "test.property", "test-value"); wp_session_set_default_endpoint (WP_SESSION (session), - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK, 5); + "wp-session-default-endpoint-audio-sink", 5); wp_session_set_default_endpoint (WP_SESSION (session), - WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE, 9); + "wp-session-default-endpoint-video-source", 9); /* verify properties are set before export */ { @@ -255,9 +260,9 @@ test_session_basic (TestSessionFixture *fixture, gconstpointer data) "test-value"); } g_assert_cmpuint (wp_session_get_default_endpoint (WP_SESSION (session), - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK), ==, 5); + "wp-session-default-endpoint-audio-sink"), ==, 5); g_assert_cmpuint (wp_session_get_default_endpoint (WP_SESSION (session), - WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE), ==, 9); + "wp-session-default-endpoint-video-source"), ==, 9); /* do export */ wp_proxy_augment (WP_PROXY (session), WP_PROXY_FEATURE_BOUND, NULL, @@ -290,10 +295,10 @@ test_session_basic (TestSessionFixture *fixture, gconstpointer data) } g_assert_cmpuint (wp_session_get_default_endpoint ( WP_SESSION (fixture->proxy_session), - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK), ==, 5); + "wp-session-default-endpoint-audio-sink"), ==, 5); g_assert_cmpuint (wp_session_get_default_endpoint ( WP_SESSION (fixture->proxy_session), - WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE), ==, 9); + "wp-session-default-endpoint-video-source"), ==, 9); /* setup change signals */ g_signal_connect (fixture->proxy_session, "default-endpoint-changed", @@ -307,7 +312,7 @@ test_session_basic (TestSessionFixture *fixture, gconstpointer data) /* change default endpoint on the proxy */ wp_session_set_default_endpoint (WP_SESSION (fixture->proxy_session), - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK, 73); + "wp-session-default-endpoint-audio-sink", 73); /* run until the change is on both sides */ fixture->n_events = 0; @@ -318,20 +323,20 @@ test_session_basic (TestSessionFixture *fixture, gconstpointer data) g_assert_cmpuint (wp_session_get_default_endpoint ( WP_SESSION (fixture->proxy_session), - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK), ==, 73); + "wp-session-default-endpoint-audio-sink"), ==, 73); g_assert_cmpuint (wp_session_get_default_endpoint ( WP_SESSION (fixture->proxy_session), - WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE), ==, 9); + "wp-session-default-endpoint-video-source"), ==, 9); g_assert_cmpuint (wp_session_get_default_endpoint ( - WP_SESSION (session), WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK), ==, 73); + WP_SESSION (session), "wp-session-default-endpoint-audio-sink"), ==, 73); g_assert_cmpuint (wp_session_get_default_endpoint ( - WP_SESSION (session), WP_DEFAULT_ENDPOINT_TYPE_VIDEO_SOURCE), ==, 9); + WP_SESSION (session), "wp-session-default-endpoint-video-source"), ==, 9); /* change default endpoint on the exported */ fixture->n_events = 0; wp_session_set_default_endpoint (WP_SESSION (session), - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE, 44); + "wp-session-default-endpoint-audio-source", 44); /* run until the change is on both sides */ g_main_loop_run (fixture->loop); @@ -340,10 +345,10 @@ test_session_basic (TestSessionFixture *fixture, gconstpointer data) /* test round 3: verify the value change on both sides */ g_assert_cmpuint (wp_session_get_default_endpoint ( - WP_SESSION (session), WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE), ==, 44); + WP_SESSION (session), "wp-session-default-endpoint-audio-source"), ==, 44); g_assert_cmpuint (wp_session_get_default_endpoint ( WP_SESSION (fixture->proxy_session), - WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE), ==, 44); + "wp-session-default-endpoint-audio-source"), ==, 44); /* change a property on the exported */ fixture->n_events = 0; diff --git a/tests/wp/spa-props.c b/tests/wp/spa-props.c index 415c37a8c835a1a2bf283619a916d45a830fa467..a67cece74b05adf3c6d1d344bdedb41538c62538 100644 --- a/tests/wp/spa-props.c +++ b/tests/wp/spa-props.c @@ -8,240 +8,251 @@ /* private functions, they should be hidden in the shared library */ #include "wp/spa-props.c" +#include "wp/spa-type.c" +#include "wp/iterator.c" +#include "wp/spa-pod.c" #include <spa/pod/iter.h> +#include <wp/wp.h> + static void test_spa_props_set_get (void) { + wp_spa_type_init (TRUE); + g_assert_true (wp_spa_type_register (WP_SPA_TYPE_TABLE_PROPS, "Wp:Test:Property", "wp-test-property")); + WpSpaProps props = {0}; - const struct spa_pod *pod; + g_autoptr (WpSpaPod) pod = NULL; float float_value = 0.0; const gchar *string_value = NULL; - wp_spa_props_register (&props, SPA_PROP_volume, "Volume", - SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0)); - wp_spa_props_register (&props, SPA_PROP_START_CUSTOM + 1, "Test property", - SPA_POD_String ("default value")); + wp_spa_props_register (&props, "volume", "Volume", + wp_spa_pod_new_choice ("Range", "f", 1.0, "f", 0.0, "f", 10.0, NULL)); + wp_spa_props_register (&props, "wp-test-property", "Test property", + wp_spa_pod_new_string ("default value")); - g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_volume)); - g_assert_cmpint (spa_pod_get_float (pod, &float_value), ==, 0); + g_assert_nonnull (pod = wp_spa_props_get_stored (&props, "volume")); + g_assert_true (wp_spa_pod_get_float (pod, &float_value)); g_assert_cmpfloat_with_epsilon (float_value, 1.0, 0.001); - g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_START_CUSTOM + 1)); - g_assert_cmpint (spa_pod_get_string (pod, &string_value), ==, 0); + g_assert_nonnull (pod = wp_spa_props_get_stored (&props, "wp-test-property")); + g_assert_true (wp_spa_pod_get_string (pod, &string_value)); g_assert_cmpstr (string_value, ==, "default value"); - g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_volume, - SPA_POD_Float (0.8)), ==, 1); - g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_START_CUSTOM + 1, - SPA_POD_String ("test value")), ==, 1); + g_autoptr (WpSpaPod) new_float = wp_spa_pod_new_float (0.8); + g_autoptr (WpSpaPod) new_str = wp_spa_pod_new_string ("test value"); + g_assert_true (wp_spa_props_store (&props, "volume", new_float)); + g_assert_true (wp_spa_props_store (&props, "wp-test-property", new_str)); - g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_volume)); - g_assert_cmpint (spa_pod_get_float (pod, &float_value), ==, 0); + g_assert_nonnull (pod = wp_spa_props_get_stored (&props, "volume")); + g_assert_true (wp_spa_pod_get_float (pod, &float_value)); g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001); - g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_START_CUSTOM + 1)); - g_assert_cmpint (spa_pod_get_string (pod, &string_value), ==, 0); + g_assert_nonnull (pod = wp_spa_props_get_stored (&props, "wp-test-property")); + g_assert_true (wp_spa_pod_get_string (pod, &string_value)); g_assert_cmpstr (string_value, ==, "test value"); wp_spa_props_clear (&props); + + wp_spa_type_deinit (); } static void test_spa_props_build_all (void) { + wp_spa_type_init (TRUE); + g_assert_true (wp_spa_type_register (WP_SPA_TYPE_TABLE_PROPS, "Wp:Test:Property", "wp-test-property")); + WpSpaProps props = {0}; - gchar buffer[512]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer)); - struct spa_pod *pod; + WpSpaPod *pod = NULL; float float_value = 0.0; const gchar *string_value = NULL; - guint32 id; + g_autoptr (WpSpaPod) pod_value = NULL; g_autoptr (GPtrArray) arr = NULL; + const gchar *id_name; + guint32 id; - wp_spa_props_register (&props, SPA_PROP_volume, "Volume", - SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0)); - wp_spa_props_register (&props, SPA_PROP_START_CUSTOM + 1, "Test property", - SPA_POD_String ("default value")); + wp_spa_props_register (&props, "volume", "Volume", + wp_spa_pod_new_choice ("Range", "f", 1.0, "f", 0.0, "f", 10.0, NULL)); + wp_spa_props_register (&props, "wp-test-property", "Test property", + wp_spa_pod_new_string ("default value")); - g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_volume, - SPA_POD_Float (0.8)), ==, 1); - g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_START_CUSTOM + 1, - SPA_POD_String ("test value")), ==, 1); + g_autoptr (WpSpaPod) new_float = wp_spa_pod_new_float (0.8); + g_autoptr (WpSpaPod) new_str = wp_spa_pod_new_string ("test value"); + g_assert_true (wp_spa_props_store (&props, "volume", new_float)); + g_assert_true (wp_spa_props_store (&props, "wp-test-property", new_str)); - arr = wp_spa_props_build_all_pods (&props, &b); + arr = wp_spa_props_build_all_pods (&props); g_assert_nonnull (arr); g_assert_cmpint (arr->len, ==, 3); pod = g_ptr_array_index (arr, 0); g_assert_nonnull (pod); - g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_Props)); - g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_Props)); - g_assert_cmpint (spa_pod_parse_object (pod, - SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_volume, SPA_POD_Float (&float_value), - SPA_PROP_START_CUSTOM + 1, SPA_POD_String (&string_value)), - ==, 2); + g_assert_true (wp_spa_pod_get_object (pod, + "Props", &id_name, + "volume", "f", &float_value, + "wp-test-property", "s", &string_value, + NULL)); g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001); g_assert_cmpstr (string_value, ==, "test value"); pod = g_ptr_array_index (arr, 1); g_assert_nonnull (pod); - g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo)); - g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_PropInfo)); - - g_assert_cmpint (spa_pod_parse_object (pod, - SPA_TYPE_OBJECT_PropInfo, NULL, - SPA_PROP_INFO_id, SPA_POD_Id (&id), - SPA_PROP_INFO_name, SPA_POD_String (&string_value), - SPA_PROP_INFO_type, SPA_POD_Pod (&pod)), - ==, 3); + g_assert_true (wp_spa_pod_get_object (pod, + "PropInfo", &id_name, + "id", "I", &id, + "name", "s", &string_value, + "type", "P", &pod_value, + NULL)); g_assert_cmpuint (id, ==, SPA_PROP_volume); g_assert_cmpstr (string_value, ==, "Volume"); - g_assert_nonnull (pod); - g_assert_true (spa_pod_is_choice (pod)); - g_assert_true (SPA_POD_CHOICE_VALUE_TYPE (pod) == SPA_TYPE_Float); + g_assert_nonnull (pod_value); + g_assert_true (wp_spa_pod_is_choice (pod_value)); pod = g_ptr_array_index (arr, 2); g_assert_nonnull (pod); - g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo)); - g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_PropInfo)); - - g_assert_cmpint (spa_pod_parse_object (pod, - SPA_TYPE_OBJECT_PropInfo, NULL, - SPA_PROP_INFO_id, SPA_POD_Id (&id), - SPA_PROP_INFO_name, SPA_POD_String (&string_value), - SPA_PROP_INFO_type, SPA_POD_Pod (&pod)), - ==, 3); - g_assert_cmpuint (id, ==, SPA_PROP_START_CUSTOM + 1); + g_assert_true (wp_spa_pod_get_object (pod, + "PropInfo", &id_name, + "id", "I", &id, + "name", "s", &string_value, + "type", "P", &pod_value, + NULL)); + g_assert_cmpuint (id, >, SPA_PROP_START_CUSTOM); g_assert_cmpstr (string_value, ==, "Test property"); - g_assert_nonnull (pod); - g_assert_true (spa_pod_is_string (pod)); + g_assert_nonnull (pod_value); + g_assert_true (wp_spa_pod_is_string (pod_value)); wp_spa_props_clear (&props); + + wp_spa_type_deinit (); } static void test_spa_props_store_from_props (void) { + wp_spa_type_init (TRUE); + g_assert_true (wp_spa_type_register (WP_SPA_TYPE_TABLE_PROPS, "Wp:Test:Property", "wp-test-property")); + WpSpaProps props = {0}; - gchar buffer[512]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer)); - const struct spa_pod *pod; + g_autoptr (WpSpaPod) pod = NULL; float float_value = 0.0; const gchar *string_value = NULL; - g_autoptr (GArray) arr = g_array_new (FALSE, FALSE, sizeof (guint32)); - - wp_spa_props_register (&props, SPA_PROP_volume, "Volume", - SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0)); - wp_spa_props_register (&props, SPA_PROP_START_CUSTOM + 1, "Test property", - SPA_POD_String ("default value")); - - pod = spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - SPA_PROP_volume, SPA_POD_Float (0.8), - SPA_PROP_START_CUSTOM + 1, SPA_POD_String ("test value")); - - g_assert_cmpint (wp_spa_props_store_from_props (&props, pod, arr), ==, 2); + g_autoptr (GPtrArray) arr = g_ptr_array_new_with_free_func (g_free); + + wp_spa_props_register (&props, "volume", "Volume", + wp_spa_pod_new_choice ("Range", "f", 1.0, "f", 0.0, "f", 10.0, NULL)); + wp_spa_props_register (&props, "wp-test-property", "Test property", + wp_spa_pod_new_string ("default value")); + + pod = wp_spa_pod_new_object ( + "Props", "Props", + "volume", "f", 0.8, + "wp-test-property", "s", "test value", + NULL); + g_assert_nonnull (pod); + g_assert_true (wp_spa_props_store_from_props (&props, pod, arr)); g_assert_cmpint (arr->len, ==, 2); - g_assert_cmpint (((guint32 *)arr->data)[0], ==, SPA_PROP_volume); - g_assert_cmpint (((guint32 *)arr->data)[1], ==, SPA_PROP_START_CUSTOM + 1); + g_assert_cmpstr ((const gchar *)g_ptr_array_index (arr, 0), ==, "volume"); + g_assert_cmpstr ((const gchar *)g_ptr_array_index (arr, 1), ==, "wp-test-property"); - g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_volume)); - g_assert_cmpint (spa_pod_get_float (pod, &float_value), ==, 0); + g_assert_nonnull (pod = wp_spa_props_get_stored (&props, "volume")); + g_assert_true (wp_spa_pod_get_float (pod, &float_value)); g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001); - g_assert_nonnull (pod = wp_spa_props_get_stored (&props, SPA_PROP_START_CUSTOM + 1)); - g_assert_cmpint (spa_pod_get_string (pod, &string_value), ==, 0); + g_assert_nonnull (pod = wp_spa_props_get_stored (&props, "wp-test-property")); + g_assert_true (wp_spa_pod_get_string (pod, &string_value)); g_assert_cmpstr (string_value, ==, "test value"); wp_spa_props_clear (&props); + + wp_spa_type_deinit (); } static void test_spa_props_register_from_prop_info (void) { + wp_spa_type_init (TRUE); + g_assert_true (wp_spa_type_register (WP_SPA_TYPE_TABLE_PROPS, "Wp:Test:Property", "wp-test-property")); + guint test_property_id = 0; + wp_spa_type_get_by_nick (WP_SPA_TYPE_TABLE_PROPS, "wp-test-property", &test_property_id, NULL, NULL); + WpSpaProps props = {0}; - gchar buffer[512]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buffer, sizeof (buffer)); - const struct spa_pod *pod; + g_autoptr (WpSpaPod) prop_info = NULL; + WpSpaPod *pod = NULL; float float_value = 0.0; const gchar *string_value = NULL; + g_autoptr (WpSpaPod) pod_value = NULL; g_autoptr (GPtrArray) arr = NULL; + const gchar *id_name; guint32 id; - pod = spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, - SPA_PROP_INFO_id, SPA_POD_Id (SPA_PROP_volume), - SPA_PROP_INFO_name, SPA_POD_String ("Volume"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0)); - - g_assert_cmpint (wp_spa_props_register_from_prop_info (&props, pod), ==, 0); - - pod = spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, - SPA_PROP_INFO_id, SPA_POD_Id (SPA_PROP_START_CUSTOM + 1), - SPA_PROP_INFO_name, SPA_POD_String ("Test property"), - SPA_PROP_INFO_type, SPA_POD_String ("default value")); - - g_assert_cmpint (wp_spa_props_register_from_prop_info (&props, pod), ==, 0); - - g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_volume, - SPA_POD_Float (0.8)), ==, 1); - g_assert_cmpint (wp_spa_props_store (&props, SPA_PROP_START_CUSTOM + 1, - SPA_POD_String ("test value")), ==, 1); - - arr = wp_spa_props_build_all_pods (&props, &b); + prop_info = wp_spa_pod_new_object ( + "PropInfo", "PropInfo", + "id", "I", SPA_PROP_volume, + "name", "s", "Volume", + "type", SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0), + NULL); + g_assert_nonnull (prop_info); + g_assert_true (wp_spa_props_register_from_prop_info (&props, prop_info)); + + prop_info = wp_spa_pod_new_object ( + "PropInfo", "PropInfo", + "id", "I", test_property_id, + "name", "s", "Test property", + "type", "s", "default value", + NULL); + g_assert_nonnull (prop_info); + g_assert_true (wp_spa_props_register_from_prop_info (&props, prop_info)); + + g_autoptr (WpSpaPod) float_pod = wp_spa_pod_new_float (0.8); + g_autoptr (WpSpaPod) string_pod = wp_spa_pod_new_string ("test value"); + g_assert_true (wp_spa_props_store (&props, "volume", float_pod)); + g_assert_true (wp_spa_props_store (&props, "wp-test-property", string_pod)); + + arr = wp_spa_props_build_all_pods (&props); g_assert_nonnull (arr); g_assert_cmpint (arr->len, ==, 3); pod = g_ptr_array_index (arr, 0); g_assert_nonnull (pod); - g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_Props)); - g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_Props)); - g_assert_cmpint (spa_pod_parse_object (pod, - SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_volume, SPA_POD_Float (&float_value), - SPA_PROP_START_CUSTOM + 1, SPA_POD_String (&string_value)), - ==, 2); + g_assert_true (wp_spa_pod_get_object (pod, + "Props", &id_name, + "volume", "f", &float_value, + "wp-test-property", "s", &string_value, + NULL)); g_assert_cmpfloat_with_epsilon (float_value, 0.8, 0.001); g_assert_cmpstr (string_value, ==, "test value"); pod = g_ptr_array_index (arr, 1); g_assert_nonnull (pod); - g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo)); - g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_PropInfo)); - - g_assert_cmpint (spa_pod_parse_object (pod, - SPA_TYPE_OBJECT_PropInfo, NULL, - SPA_PROP_INFO_id, SPA_POD_Id (&id), - SPA_PROP_INFO_name, SPA_POD_String (&string_value), - SPA_PROP_INFO_type, SPA_POD_Pod (&pod)), - ==, 3); + g_assert_true (wp_spa_pod_get_object (pod, + "PropInfo", &id_name, + "id", "I", &id, + "name", "s", &string_value, + "type", "P", &pod_value, + NULL)); g_assert_cmpuint (id, ==, SPA_PROP_volume); g_assert_cmpstr (string_value, ==, "Volume"); - g_assert_nonnull (pod); - g_assert_true (spa_pod_is_choice (pod)); - g_assert_true (SPA_POD_CHOICE_VALUE_TYPE (pod) == SPA_TYPE_Float); + g_assert_nonnull (pod_value); + g_assert_true (wp_spa_pod_is_choice (pod_value)); pod = g_ptr_array_index (arr, 2); g_assert_nonnull (pod); - g_assert_true (spa_pod_is_object_type (pod, SPA_TYPE_OBJECT_PropInfo)); - g_assert_true (spa_pod_is_object_id (pod, SPA_PARAM_PropInfo)); - - g_assert_cmpint (spa_pod_parse_object (pod, - SPA_TYPE_OBJECT_PropInfo, NULL, - SPA_PROP_INFO_id, SPA_POD_Id (&id), - SPA_PROP_INFO_name, SPA_POD_String (&string_value), - SPA_PROP_INFO_type, SPA_POD_Pod (&pod)), - ==, 3); - g_assert_cmpuint (id, ==, SPA_PROP_START_CUSTOM + 1); + g_assert_true (wp_spa_pod_get_object (pod, + "PropInfo", &id_name, + "id", "I", &id, + "name", "s", &string_value, + "type", "P", &pod_value, + NULL)); + g_assert_cmpuint (id, ==, test_property_id); g_assert_cmpstr (string_value, ==, "Test property"); - g_assert_nonnull (pod); - g_assert_true (spa_pod_is_string (pod)); + g_assert_nonnull (pod_value); + g_assert_true (wp_spa_pod_is_string (pod_value)); wp_spa_props_clear (&props); + + wp_spa_type_deinit (); } int diff --git a/tools/wireplumber-cli.c b/tools/wireplumber-cli.c index 83e245f7f14ceb77331af4666668b317d75f9dfa..3ade45495f1025c36936c55e9961a52f6c2d6394 100644 --- a/tools/wireplumber-cli.c +++ b/tools/wireplumber-cli.c @@ -38,16 +38,19 @@ async_quit (WpCore *core, GAsyncResult *res, struct WpCliData * d) } static void -print_dev_endpoint (WpEndpoint *ep, WpSession *session, WpDefaultEndpointType type) +print_dev_endpoint (WpEndpoint *ep, WpSession *session, const gchar *type_name) { guint32 id = wp_proxy_get_bound_id (WP_PROXY (ep)); - gboolean is_default = (session && type != 0 && - wp_session_get_default_endpoint (session, type) == id); + gboolean is_default = (session && type_name != NULL && + wp_session_get_default_endpoint (session, type_name) == id); + g_autoptr (WpSpaPod) ctrl = NULL; gfloat volume = 0.0; gboolean mute = FALSE; - wp_endpoint_get_control_float (ep, WP_ENDPOINT_CONTROL_VOLUME, &volume); - wp_endpoint_get_control_boolean (ep, WP_ENDPOINT_CONTROL_MUTE, &mute); + ctrl = wp_endpoint_get_control (ep, "volume"); + wp_spa_pod_get_float (ctrl, &volume); + ctrl = wp_endpoint_get_control (ep, "mute"); + wp_spa_pod_get_boolean (ctrl, &mute); g_print (" %c %4u. %60s\tvol: %.2f %s\n", is_default ? '*' : ' ', id, wp_endpoint_get_name (ep), volume, mute ? "MUTE" : ""); @@ -87,7 +90,7 @@ list_endpoints (WpObjectManager * om, struct WpCliData * d) { WpEndpoint *ep = g_value_get_object (&val); if (g_strcmp0 (wp_endpoint_get_media_class (ep), "Audio/Source") == 0) - print_dev_endpoint (ep, session, WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE); + print_dev_endpoint (ep, session, "wp-session-default-endpoint-audio-source"); } wp_iterator_reset (it); @@ -99,7 +102,7 @@ list_endpoints (WpObjectManager * om, struct WpCliData * d) { WpEndpoint *ep = g_value_get_object (&val); if (g_strcmp0 (wp_endpoint_get_media_class (ep), "Audio/Sink") == 0) - print_dev_endpoint (ep, session, WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK); + print_dev_endpoint (ep, session, "wp-session-default-endpoint-audio-sink"); } wp_iterator_reset (it); @@ -151,18 +154,18 @@ set_default (WpObjectManager * om, struct WpCliData * d) guint32 id = wp_proxy_get_bound_id (WP_PROXY (ep)); if (id == d->params.set_default.id) { - WpDefaultEndpointType type; + const gchar * type_name; if (g_strcmp0 (wp_endpoint_get_media_class (ep), "Audio/Sink") == 0) - type = WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SINK; + type_name = "wp-session-default-endpoint-audio-sink"; else if (g_strcmp0 (wp_endpoint_get_media_class (ep), "Audio/Source") == 0) - type = WP_DEFAULT_ENDPOINT_TYPE_AUDIO_SOURCE; + type_name = "wp-session-default-endpoint-audio-source"; else { g_print ("%u: not a device endpoint\n", id); g_main_loop_quit (d->loop); return; } - wp_session_set_default_endpoint (session, type, id); + wp_session_set_default_endpoint (session, type_name, id); wp_core_sync (d->core, NULL, (GAsyncReadyCallback) async_quit, d); return; } @@ -185,8 +188,8 @@ set_volume (WpObjectManager * om, struct WpCliData * d) guint32 id = wp_proxy_get_bound_id (WP_PROXY (ep)); if (id == d->params.set_volume.id) { - wp_endpoint_set_control_float (ep, WP_ENDPOINT_CONTROL_VOLUME, - d->params.set_volume.volume); + g_autoptr (WpSpaPod) vol = wp_spa_pod_new_float (d->params.set_volume.volume); + wp_endpoint_set_control (ep, "volume", vol); wp_core_sync (d->core, NULL, (GAsyncReadyCallback) async_quit, d); return; } @@ -274,6 +277,18 @@ main (gint argc, gchar **argv) g_log_set_writer_func (wp_log_writer_default, NULL, NULL); + /* Register custom wireplumber session types */ + wp_spa_type_init (TRUE); + wp_spa_type_register (WP_SPA_TYPE_TABLE_BASIC, + "Wp:Session:Default:Endpoint:Audio:Source", + "wp-session-default-endpoint-audio-source"); + wp_spa_type_register (WP_SPA_TYPE_TABLE_BASIC, + "Wp:Session:Default:Endpoint:Audio:Sink", + "wp-session-default-endpoint-audio-sink"); + wp_spa_type_register (WP_SPA_TYPE_TABLE_BASIC, + "Wp:Session:Default:Endpoint:Video:Source", + "wp-session-default-endpoint-video-source"); + context = g_option_context_new ("- PipeWire Session/Policy Manager Helper CLI"); g_option_context_add_main_entries (context, entries, NULL); g_option_context_set_description (context, usage_string);