diff --git a/lib/wp/core.c b/lib/wp/core.c index 1b361bef..a152c54f 100644 --- a/lib/wp/core.c +++ b/lib/wp/core.c @@ -413,7 +413,7 @@ wp_core_class_init (WpCoreClass * klass) to autodetect the GType of proxies created through wp_proxy_new_global() */ g_type_ensure (WP_TYPE_CLIENT); g_type_ensure (WP_TYPE_DEVICE); - g_type_ensure (WP_TYPE_PROXY_ENDPOINT); + g_type_ensure (WP_TYPE_ENDPOINT); g_type_ensure (WP_TYPE_LINK); g_type_ensure (WP_TYPE_NODE); g_type_ensure (WP_TYPE_PORT); diff --git a/lib/wp/endpoint.c b/lib/wp/endpoint.c index 3c8f839d..446e8c72 100644 --- a/lib/wp/endpoint.c +++ b/lib/wp/endpoint.c @@ -8,6 +8,7 @@ #include "endpoint.h" #include "private.h" +#include "error.h" #include "wpenums.h" #include @@ -15,12 +16,6 @@ #include #include -enum { - EXPORTED_PROP_0, - EXPORTED_PROP_GLOBAL_ID, - EXPORTED_PROP_PROPERTIES, -}; - enum { SIGNAL_CONTROL_CHANGED, N_SIGNALS, @@ -86,13 +81,255 @@ endpoint_info_free (struct pw_endpoint_info *info) free(info); } -/* interface */ +/* WpEndpoint */ -G_DEFINE_INTERFACE (WpEndpoint, wp_endpoint, G_TYPE_OBJECT) +typedef struct _WpEndpointPrivate WpEndpointPrivate; +struct _WpEndpointPrivate +{ + WpProperties *properties; + WpSpaProps spa_props; + struct pw_endpoint_info *info; + struct spa_hook listener; +}; + +G_DEFINE_TYPE_WITH_PRIVATE (WpEndpoint, wp_endpoint, WP_TYPE_PROXY) static void -wp_endpoint_default_init (WpEndpointInterface * klass) +wp_endpoint_init (WpEndpoint * self) { +} + +static void +wp_endpoint_finalize (GObject * object) +{ + WpEndpoint *self = WP_ENDPOINT (object); + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + + g_clear_pointer (&priv->info, endpoint_info_free); + g_clear_pointer (&priv->properties, wp_properties_unref); + wp_spa_props_clear (&priv->spa_props); + + G_OBJECT_CLASS (wp_endpoint_parent_class)->finalize (object); +} + +static void +wp_endpoint_augment (WpProxy * proxy, WpProxyFeatures features) +{ + /* call the parent impl first to ensure we have a pw proxy if necessary */ + WP_PROXY_CLASS (wp_endpoint_parent_class)->augment (proxy, features); + + if (features & WP_ENDPOINT_FEATURE_CONTROLS) { + struct pw_endpoint *pw_proxy = NULL; + uint32_t ids[] = { SPA_PARAM_Props }; + + pw_proxy = (struct pw_endpoint *) wp_proxy_get_pw_proxy (proxy); + if (!pw_proxy) + return; + + pw_endpoint_enum_params (pw_proxy, 0, SPA_PARAM_PropInfo, 0, -1, NULL); + pw_endpoint_subscribe_params (pw_proxy, ids, SPA_N_ELEMENTS (ids)); + } +} + +static gconstpointer +wp_endpoint_get_info (WpProxy * proxy) +{ + WpEndpoint *self = WP_ENDPOINT (proxy); + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + + return priv->info; +} + +static WpProperties * +wp_endpoint_get_properties (WpProxy * proxy) +{ + WpEndpoint *self = WP_ENDPOINT (proxy); + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + + return wp_properties_ref (priv->properties); +} + +static gint +wp_endpoint_enum_params (WpProxy * self, guint32 id, guint32 start, + guint32 num, const struct spa_pod *filter) +{ + struct pw_endpoint *pwp; + int endpoint_enum_params_result; + + pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self); + endpoint_enum_params_result = pw_endpoint_enum_params (pwp, 0, id, start, num, + filter); + g_warn_if_fail (endpoint_enum_params_result >= 0); + + return endpoint_enum_params_result; +} + +static gint +wp_endpoint_subscribe_params (WpProxy * self, guint32 n_ids, guint32 *ids) +{ + struct pw_endpoint *pwp; + int endpoint_subscribe_params_result; + + pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self); + endpoint_subscribe_params_result = pw_endpoint_subscribe_params (pwp, ids, + n_ids); + g_warn_if_fail (endpoint_subscribe_params_result >= 0); + + return endpoint_subscribe_params_result; +} + +static gint +wp_endpoint_set_param (WpProxy * self, guint32 id, guint32 flags, + const struct spa_pod *param) +{ + struct pw_endpoint *pwp; + int endpoint_set_param_result; + + pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self); + endpoint_set_param_result = pw_endpoint_set_param (pwp, id, flags, param); + g_warn_if_fail (endpoint_set_param_result >= 0); + + return endpoint_set_param_result; +} + +static void +endpoint_event_info (void *data, const struct pw_endpoint_info *info) +{ + WpEndpoint *self = WP_ENDPOINT (data); + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + + priv->info = endpoint_info_update (priv->info, &priv->properties, info); + wp_proxy_set_feature_ready (WP_PROXY (self), WP_PROXY_FEATURE_INFO); + + g_object_notify (G_OBJECT (self), "info"); + + if (info->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) + g_object_notify (G_OBJECT (self), "properties"); +} + +static const struct pw_endpoint_events endpoint_events = { + PW_VERSION_ENDPOINT_EVENTS, + .info = endpoint_event_info, + .param = wp_proxy_handle_event_param, +}; + +static void +wp_endpoint_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy) +{ + WpEndpoint *self = WP_ENDPOINT (proxy); + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + + pw_endpoint_add_listener ((struct pw_endpoint *) pw_proxy, + &priv->listener, &endpoint_events, self); +} + +static void +wp_endpoint_param (WpProxy * proxy, gint seq, guint32 id, guint32 index, + guint32 next, const struct spa_pod *param) +{ + WpEndpoint *self = WP_ENDPOINT (proxy); + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + g_autoptr (GArray) changed_ids = NULL; + guint32 prop_id; + + switch (id) { + case SPA_PARAM_PropInfo: + 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)); + 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); + g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, prop_id); + } + + wp_proxy_set_feature_ready (WP_PROXY (self), + WP_ENDPOINT_FEATURE_CONTROLS); + break; + } +} + +static const gchar * +get_name (WpEndpoint * self) +{ + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + return priv->info->name; +} + +static const gchar * +get_media_class (WpEndpoint * self) +{ + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + return priv->info->media_class; +} + +static WpDirection +get_direction (WpEndpoint * self) +{ + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + return priv->info->direction; +} + +static const struct spa_pod * +get_control (WpEndpoint * self, guint32 control_id) +{ + WpEndpointPrivate *priv = wp_endpoint_get_instance_private (self); + return wp_spa_props_get_stored (&priv->spa_props, control_id); +} + +static gboolean +set_control (WpEndpoint * self, guint32 control_id, + const struct spa_pod * pod) +{ + char buf[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof (buf)); + struct pw_endpoint *pw_proxy = NULL; + + /* set the default endpoint id as a property param on the endpoint; + our spa_props will be updated by the param event */ + + pw_proxy = (struct pw_endpoint *) wp_proxy_get_pw_proxy (WP_PROXY (self)); + if (!pw_proxy) + return FALSE; + + pw_endpoint_set_param (pw_proxy, + SPA_PARAM_Props, 0, + spa_pod_builder_add_object (&b, + SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, + control_id, SPA_POD_Pod (pod))); + + return TRUE; +} + +static void +wp_endpoint_class_init (WpEndpointClass * klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + WpProxyClass *proxy_class = (WpProxyClass *) klass; + + object_class->finalize = wp_endpoint_finalize; + + proxy_class->pw_iface_type = PW_TYPE_INTERFACE_Endpoint; + proxy_class->pw_iface_version = PW_VERSION_ENDPOINT; + + proxy_class->augment = wp_endpoint_augment; + proxy_class->get_info = wp_endpoint_get_info; + proxy_class->get_properties = wp_endpoint_get_properties; + proxy_class->enum_params = wp_endpoint_enum_params; + proxy_class->subscribe_params = wp_endpoint_subscribe_params; + proxy_class->set_param = wp_endpoint_set_param; + + proxy_class->pw_proxy_created = wp_endpoint_pw_proxy_created; + proxy_class->param = wp_endpoint_param; + + klass->get_name = get_name; + klass->get_media_class = get_media_class; + klass->get_direction = get_direction; + klass->get_control = get_control; + klass->set_control = set_control; + 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); @@ -102,36 +339,36 @@ const gchar * wp_endpoint_get_name (WpEndpoint * self) { g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL); - g_return_val_if_fail (WP_ENDPOINT_GET_IFACE (self)->get_name, NULL); + g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_name, NULL); - return WP_ENDPOINT_GET_IFACE (self)->get_name (self); + return WP_ENDPOINT_GET_CLASS (self)->get_name (self); } const gchar * wp_endpoint_get_media_class (WpEndpoint * self) { g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL); - g_return_val_if_fail (WP_ENDPOINT_GET_IFACE (self)->get_media_class, NULL); + g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_media_class, NULL); - return WP_ENDPOINT_GET_IFACE (self)->get_media_class (self); + return WP_ENDPOINT_GET_CLASS (self)->get_media_class (self); } WpDirection wp_endpoint_get_direction (WpEndpoint * self) { g_return_val_if_fail (WP_IS_ENDPOINT (self), 0); - g_return_val_if_fail (WP_ENDPOINT_GET_IFACE (self)->get_direction, 0); + g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_direction, 0); - return WP_ENDPOINT_GET_IFACE (self)->get_direction (self); + return WP_ENDPOINT_GET_CLASS (self)->get_direction (self); } const struct spa_pod * wp_endpoint_get_control (WpEndpoint * self, guint32 control_id) { g_return_val_if_fail (WP_IS_ENDPOINT (self), NULL); - g_return_val_if_fail (WP_ENDPOINT_GET_IFACE (self)->get_control, NULL); + g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->get_control, NULL); - return WP_ENDPOINT_GET_IFACE (self)->get_control (self, control_id); + return WP_ENDPOINT_GET_CLASS (self)->get_control (self, control_id); } gboolean @@ -168,9 +405,9 @@ wp_endpoint_set_control (WpEndpoint * self, guint32 control_id, const struct spa_pod * value) { g_return_val_if_fail (WP_IS_ENDPOINT (self), FALSE); - g_return_val_if_fail (WP_ENDPOINT_GET_IFACE (self)->set_control, FALSE); + g_return_val_if_fail (WP_ENDPOINT_GET_CLASS (self)->set_control, FALSE); - return WP_ENDPOINT_GET_IFACE (self)->set_control (self, control_id, value); + return WP_ENDPOINT_GET_CLASS (self)->set_control (self, control_id, value); } gboolean @@ -200,343 +437,72 @@ wp_endpoint_set_control_float (WpEndpoint * self, guint32 control_id, buffer, sizeof (buffer), SPA_POD_Float (value), 0)); } -/* proxy */ +/* WpImplEndpoint */ -struct _WpProxyEndpoint +typedef struct _WpImplEndpointPrivate WpImplEndpointPrivate; +struct _WpImplEndpointPrivate { - WpProxy parent; - - WpProperties *properties; - WpSpaProps spa_props; - struct pw_endpoint_info *info; - struct spa_hook listener; -}; - -static void wp_proxy_endpoint_iface_init (WpEndpointInterface * iface); - -G_DEFINE_TYPE_WITH_CODE (WpProxyEndpoint, wp_proxy_endpoint, WP_TYPE_PROXY, - G_IMPLEMENT_INTERFACE (WP_TYPE_ENDPOINT, wp_proxy_endpoint_iface_init)) - -static void -wp_proxy_endpoint_init (WpProxyEndpoint * self) -{ -} - -static void -wp_proxy_endpoint_finalize (GObject * object) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (object); - - g_clear_pointer (&self->info, endpoint_info_free); - g_clear_pointer (&self->properties, wp_properties_unref); - wp_spa_props_clear (&self->spa_props); - - G_OBJECT_CLASS (wp_proxy_endpoint_parent_class)->finalize (object); -} - -static void -wp_proxy_endpoint_augment (WpProxy * proxy, WpProxyFeatures features) -{ - /* call the parent impl first to ensure we have a pw proxy if necessary */ - WP_PROXY_CLASS (wp_proxy_endpoint_parent_class)->augment (proxy, features); - - if (features & WP_PROXY_ENDPOINT_FEATURE_CONTROLS) { - struct pw_endpoint *pw_proxy = NULL; - uint32_t ids[] = { SPA_PARAM_Props }; - - pw_proxy = (struct pw_endpoint *) wp_proxy_get_pw_proxy (proxy); - if (!pw_proxy) - return; - - pw_endpoint_enum_params (pw_proxy, 0, SPA_PARAM_PropInfo, 0, -1, NULL); - pw_endpoint_subscribe_params (pw_proxy, ids, SPA_N_ELEMENTS (ids)); - } -} - -static gconstpointer -wp_proxy_endpoint_get_info (WpProxy * proxy) -{ - return WP_PROXY_ENDPOINT (proxy)->info; -} - -static WpProperties * -wp_proxy_endpoint_get_properties (WpProxy * proxy) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (proxy); - return wp_properties_ref (self->properties); -} - -static gint -wp_proxy_endpoint_enum_params (WpProxy * self, guint32 id, guint32 start, - guint32 num, const struct spa_pod *filter) -{ - struct pw_endpoint *pwp; - int endpoint_enum_params_result; - - pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self); - endpoint_enum_params_result = pw_endpoint_enum_params (pwp, 0, id, start, num, - filter); - g_warn_if_fail (endpoint_enum_params_result >= 0); - - return endpoint_enum_params_result; -} - -static gint -wp_proxy_endpoint_subscribe_params (WpProxy * self, guint32 n_ids, guint32 *ids) -{ - struct pw_endpoint *pwp; - int endpoint_subscribe_params_result; - - pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self); - endpoint_subscribe_params_result = pw_endpoint_subscribe_params (pwp, ids, - n_ids); - g_warn_if_fail (endpoint_subscribe_params_result >= 0); - - return endpoint_subscribe_params_result; -} - -static gint -wp_proxy_endpoint_set_param (WpProxy * self, guint32 id, guint32 flags, - const struct spa_pod *param) -{ - struct pw_endpoint *pwp; - int endpoint_set_param_result; - - pwp = (struct pw_endpoint *) wp_proxy_get_pw_proxy (self); - endpoint_set_param_result = pw_endpoint_set_param (pwp, id, flags, param); - g_warn_if_fail (endpoint_set_param_result >= 0); - - return endpoint_set_param_result; -} - -static void -endpoint_event_info (void *data, const struct pw_endpoint_info *info) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (data); - - self->info = endpoint_info_update (self->info, &self->properties, info); - wp_proxy_set_feature_ready (WP_PROXY (self), WP_PROXY_FEATURE_INFO); - - g_object_notify (G_OBJECT (self), "info"); - - if (info->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) - g_object_notify (G_OBJECT (self), "properties"); -} - -static const struct pw_endpoint_events endpoint_events = { - PW_VERSION_ENDPOINT_EVENTS, - .info = endpoint_event_info, - .param = wp_proxy_handle_event_param, -}; - -static void -wp_proxy_endpoint_pw_proxy_created (WpProxy * proxy, struct pw_proxy * pw_proxy) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (proxy); - pw_endpoint_add_listener ((struct pw_endpoint *) pw_proxy, - &self->listener, &endpoint_events, self); -} - -static void -wp_proxy_endpoint_param (WpProxy * proxy, gint seq, guint32 id, guint32 index, - guint32 next, const struct spa_pod *param) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (proxy); - g_autoptr (GArray) changed_ids = NULL; - guint32 prop_id; - - switch (id) { - case SPA_PARAM_PropInfo: - wp_spa_props_register_from_prop_info (&self->spa_props, param); - break; - case SPA_PARAM_Props: - changed_ids = g_array_new (FALSE, FALSE, sizeof (uint32_t)); - wp_spa_props_store_from_props (&self->spa_props, param, changed_ids); - - for (guint i = 0; i < changed_ids->len; i++) { - prop_id = g_array_index (changed_ids, uint32_t, i); - g_signal_emit (self, signals[SIGNAL_CONTROL_CHANGED], 0, prop_id); - } - - wp_proxy_set_feature_ready (WP_PROXY (self), - WP_PROXY_ENDPOINT_FEATURE_CONTROLS); - break; - } -} - -static const gchar * -wp_proxy_endpoint_get_name (WpEndpoint * endpoint) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (endpoint); - return self->info->name; -} - -static const gchar * -wp_proxy_endpoint_get_media_class (WpEndpoint * endpoint) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (endpoint); - return self->info->media_class; -} - -static WpDirection -wp_proxy_endpoint_get_direction (WpEndpoint * endpoint) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (endpoint); - return self->info->direction; -} - -static const struct spa_pod * -wp_proxy_endpoint_get_control (WpEndpoint * endpoint, guint32 control_id) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (endpoint); - return wp_spa_props_get_stored (&self->spa_props, control_id); -} - -static gboolean -wp_proxy_endpoint_set_control (WpEndpoint * endpoint, guint32 control_id, - const struct spa_pod * pod) -{ - WpProxyEndpoint *self = WP_PROXY_ENDPOINT (endpoint); - char buf[1024]; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof (buf)); - struct pw_endpoint *pw_proxy = NULL; - - /* set the default endpoint id as a property param on the endpoint; - our spa_props will be updated by the param event */ - - pw_proxy = (struct pw_endpoint *) wp_proxy_get_pw_proxy (WP_PROXY (self)); - if (!pw_proxy) - return FALSE; - - pw_endpoint_set_param (pw_proxy, - SPA_PARAM_Props, 0, - spa_pod_builder_add_object (&b, - SPA_TYPE_OBJECT_Props, SPA_PARAM_Props, - control_id, SPA_POD_Pod (pod))); - - return TRUE; -} - -static void -wp_proxy_endpoint_class_init (WpProxyEndpointClass * klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - WpProxyClass *proxy_class = (WpProxyClass *) klass; - - object_class->finalize = wp_proxy_endpoint_finalize; - - proxy_class->pw_iface_type = PW_TYPE_INTERFACE_Endpoint; - proxy_class->pw_iface_version = PW_VERSION_ENDPOINT; - - proxy_class->augment = wp_proxy_endpoint_augment; - proxy_class->get_info = wp_proxy_endpoint_get_info; - proxy_class->get_properties = wp_proxy_endpoint_get_properties; - proxy_class->enum_params = wp_proxy_endpoint_enum_params; - proxy_class->subscribe_params = wp_proxy_endpoint_subscribe_params; - proxy_class->set_param = wp_proxy_endpoint_set_param; - - proxy_class->pw_proxy_created = wp_proxy_endpoint_pw_proxy_created; - proxy_class->param = wp_proxy_endpoint_param; -} - -static void -wp_proxy_endpoint_iface_init (WpEndpointInterface * iface) -{ - iface->get_name = wp_proxy_endpoint_get_name; - iface->get_media_class = wp_proxy_endpoint_get_media_class; - iface->get_direction = wp_proxy_endpoint_get_direction; - iface->get_control = wp_proxy_endpoint_get_control; - iface->set_control = wp_proxy_endpoint_set_control; -} - -/* exported */ - -typedef struct _WpExportedEndpointPrivate WpExportedEndpointPrivate; -struct _WpExportedEndpointPrivate -{ - WpProxy *client_ep; - struct spa_hook listener; - struct spa_hook proxy_listener; + WpEndpointPrivate *pp; struct pw_endpoint_info info; struct spa_param_info param_info[2]; - WpProperties *properties; - WpSpaProps spa_props; }; -static void wp_exported_endpoint_iface_init (WpEndpointInterface * iface); - -G_DEFINE_TYPE_WITH_CODE (WpExportedEndpoint, wp_exported_endpoint, WP_TYPE_EXPORTED, - G_IMPLEMENT_INTERFACE (WP_TYPE_ENDPOINT, wp_exported_endpoint_iface_init) - G_ADD_PRIVATE (WpExportedEndpoint)) +G_DEFINE_TYPE_WITH_PRIVATE (WpImplEndpoint, wp_impl_endpoint, WP_TYPE_ENDPOINT) static void -wp_exported_endpoint_init (WpExportedEndpoint * self) +wp_impl_endpoint_init (WpImplEndpoint * self) { - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); + WpImplEndpointPrivate *priv = wp_impl_endpoint_get_instance_private (self); - priv->properties = wp_properties_new_empty (); + /* store a pointer to the parent's private; we use that structure + as well to optimize memory usage and to be able to re-use some of the + parent's methods without reimplementing them */ + priv->pp = wp_endpoint_get_instance_private (WP_ENDPOINT (self)); + + priv->pp->properties = wp_properties_new_empty (); priv->param_info[0] = SPA_PARAM_INFO (SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE); priv->param_info[1] = SPA_PARAM_INFO (SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ); priv->info.version = PW_VERSION_ENDPOINT_INFO; - priv->info.props = (struct spa_dict *) wp_properties_peek_dict (priv->properties); + priv->info.props = + (struct spa_dict *) wp_properties_peek_dict (priv->pp->properties); priv->info.params = priv->param_info; priv->info.n_params = SPA_N_ELEMENTS (priv->param_info); + priv->pp->info = &priv->info; + wp_proxy_set_feature_ready (WP_PROXY (self), WP_PROXY_FEATURE_INFO); + wp_proxy_set_feature_ready (WP_PROXY (self), WP_ENDPOINT_FEATURE_CONTROLS); } static void -wp_exported_endpoint_finalize (GObject * object) +wp_impl_endpoint_finalize (GObject * object) { - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (object)); + WpImplEndpointPrivate *priv = + wp_impl_endpoint_get_instance_private (WP_IMPL_ENDPOINT (object)); - g_clear_pointer (&priv->properties, wp_properties_unref); - wp_spa_props_clear (&priv->spa_props); + /* set to NULL to prevent parent's finalize from calling free() on it */ + priv->pp->info = NULL; g_free (priv->info.name); g_free (priv->info.media_class); - G_OBJECT_CLASS (wp_exported_endpoint_parent_class)->finalize (object); + G_OBJECT_CLASS (wp_impl_endpoint_parent_class)->finalize (object); } static void -wp_exported_endpoint_get_property (GObject * object, guint property_id, - GValue * value, GParamSpec * pspec) -{ - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (object)); - - switch (property_id) { - case EXPORTED_PROP_GLOBAL_ID: - g_value_set_uint (value, priv->info.id); - break; - case EXPORTED_PROP_PROPERTIES: - g_value_set_boxed (value, priv->properties); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); - break; - } -} - -static void -client_endpoint_update (WpExportedEndpoint * self, guint32 change_mask, +client_endpoint_update (WpImplEndpoint * self, guint32 change_mask, guint32 info_change_mask) { - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (self); + WpImplEndpointPrivate *priv = wp_impl_endpoint_get_instance_private (self); char buf[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT (buf, sizeof (buf)); struct pw_client_endpoint *pw_proxy = NULL; struct pw_endpoint_info *info = NULL; g_autoptr (GPtrArray) params = NULL; - pw_proxy = (struct pw_client_endpoint *) wp_proxy_get_pw_proxy ( - priv->client_ep); + pw_proxy = (struct pw_client_endpoint *) wp_proxy_get_pw_proxy (WP_PROXY (self)); if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_PARAMS) { - params = wp_spa_props_build_all_pods (&priv->spa_props, &b); + params = wp_spa_props_build_all_pods (&priv->pp->spa_props, &b); } if (change_mask & PW_CLIENT_ENDPOINT_UPDATE_INFO) { info = &priv->info; @@ -557,9 +523,8 @@ static int client_endpoint_set_param (void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { - WpExportedEndpoint *self = WP_EXPORTED_ENDPOINT (object); - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (self); + WpImplEndpoint *self = WP_IMPL_ENDPOINT (object); + WpImplEndpointPrivate *priv = wp_impl_endpoint_get_instance_private (self); g_autoptr (GArray) changed_ids = NULL; guint32 prop_id; @@ -567,7 +532,7 @@ client_endpoint_set_param (void *object, return -ENOENT; changed_ids = g_array_new (FALSE, FALSE, sizeof (guint32)); - wp_spa_props_store_from_props (&priv->spa_props, param, changed_ids); + wp_spa_props_store_from_props (&priv->pp->spa_props, param, changed_ids); for (guint i = 0; i < changed_ids->len; i++) { prop_id = g_array_index (changed_ids, guint32, i); @@ -579,303 +544,216 @@ client_endpoint_set_param (void *object, return 0; } -static void -client_endpoint_proxy_bound (void *object, uint32_t global_id) -{ - WpExportedEndpoint *self = WP_EXPORTED_ENDPOINT (object); - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (self); - - priv->info.id = global_id; - wp_exported_notify_export_done (WP_EXPORTED (self), NULL); -} - static struct pw_client_endpoint_events client_endpoint_events = { PW_VERSION_CLIENT_ENDPOINT_EVENTS, .set_param = client_endpoint_set_param, }; -static struct pw_proxy_events client_ep_proxy_events = { - PW_VERSION_PROXY_EVENTS, - .bound = client_endpoint_proxy_bound, -}; - static void -wp_exported_endpoint_export (WpExported * self) +wp_impl_endpoint_augment (WpProxy * proxy, WpProxyFeatures features) { - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); - g_autoptr (WpCore) core = wp_exported_get_core (self); - struct pw_client_endpoint *pw_proxy = NULL; - struct pw_core *pw_core = wp_core_get_pw_core (core); + WpImplEndpoint *self = WP_IMPL_ENDPOINT (proxy); + WpImplEndpointPrivate *priv = wp_impl_endpoint_get_instance_private (self); - /* make sure these props are not present; they are added by the server */ - wp_properties_set (priv->properties, PW_KEY_OBJECT_ID, NULL); - wp_properties_set (priv->properties, PW_KEY_CLIENT_ID, NULL); - wp_properties_set (priv->properties, PW_KEY_FACTORY_ID, NULL); + /* if any of the default features is requested, make sure BOUND + is also requested, as they all depend on binding the endpoint */ + if (features & WP_PROXY_FEATURES_STANDARD) + features |= WP_PROXY_FEATURE_BOUND; - /* add must-have global properties */ - wp_properties_set (priv->properties, PW_KEY_ENDPOINT_NAME, priv->info.name); - wp_properties_set (priv->properties, PW_KEY_MEDIA_CLASS, priv->info.media_class); + if (features & WP_PROXY_FEATURE_BOUND) { + g_autoptr (WpCore) core = wp_proxy_get_core (proxy); + struct pw_core *pw_core = wp_core_get_pw_core (core); + struct pw_proxy *pw_proxy = NULL; - pw_proxy = pw_core_create_object (pw_core, "client-endpoint", - PW_TYPE_INTERFACE_ClientEndpoint, PW_VERSION_CLIENT_ENDPOINT, - wp_properties_peek_dict (priv->properties), 0); - priv->client_ep = g_object_new (WP_TYPE_PROXY, "core", core, - "pw-proxy", pw_proxy, NULL); + /* no pw_core -> we are not connected */ + if (!pw_core) { + wp_proxy_augment_error (proxy, g_error_new (WP_DOMAIN_LIBRARY, + WP_LIBRARY_ERROR_OPERATION_FAILED, + "The WirePlumber core is not connected; " + "object cannot be exported to PipeWire")); + return; + } - pw_client_endpoint_add_listener (pw_proxy, &priv->listener, - &client_endpoint_events, self); - pw_proxy_add_listener ((struct pw_proxy *) pw_proxy, &priv->proxy_listener, - &client_ep_proxy_events, self); + /* make sure these props are not present; they are added by the server */ + wp_properties_set (priv->pp->properties, PW_KEY_OBJECT_ID, NULL); + wp_properties_set (priv->pp->properties, PW_KEY_CLIENT_ID, NULL); + wp_properties_set (priv->pp->properties, PW_KEY_FACTORY_ID, NULL); - client_endpoint_update (WP_EXPORTED_ENDPOINT (self), - PW_CLIENT_ENDPOINT_UPDATE_PARAMS | PW_CLIENT_ENDPOINT_UPDATE_INFO, - PW_ENDPOINT_CHANGE_MASK_ALL); + /* add must-have global properties */ + wp_properties_set (priv->pp->properties, + PW_KEY_ENDPOINT_NAME, priv->info.name); + wp_properties_set (priv->pp->properties, + PW_KEY_MEDIA_CLASS, priv->info.media_class); + + pw_proxy = pw_core_create_object (pw_core, "client-endpoint", + PW_TYPE_INTERFACE_ClientEndpoint, PW_VERSION_CLIENT_ENDPOINT, + wp_properties_peek_dict (priv->pp->properties), 0); + wp_proxy_set_pw_proxy (proxy, pw_proxy); + + pw_client_endpoint_add_listener (pw_proxy, &priv->pp->listener, + &client_endpoint_events, self); + + client_endpoint_update (WP_IMPL_ENDPOINT (self), + PW_CLIENT_ENDPOINT_UPDATE_PARAMS | PW_CLIENT_ENDPOINT_UPDATE_INFO, + PW_ENDPOINT_CHANGE_MASK_ALL); + } } -static void -wp_exported_endpoint_unexport (WpExported * self) +static gint +wp_impl_endpoint_set_param (WpProxy * self, guint32 id, guint32 flags, + const struct spa_pod *param) { - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); - - g_clear_object (&priv->client_ep); - priv->info.id = 0; -} - -static WpProxy * -wp_exported_endpoint_get_proxy (WpExported * self) -{ - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); - - return priv->client_ep ? g_object_ref (priv->client_ep) : NULL; -} - -static const gchar * -wp_exported_endpoint_get_name (WpEndpoint * endpoint) -{ - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (endpoint)); - return priv->info.name; -} - -static const gchar * -wp_exported_endpoint_get_media_class (WpEndpoint * endpoint) -{ - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (endpoint)); - return priv->info.media_class; -} - -static WpDirection -wp_exported_endpoint_get_direction (WpEndpoint * endpoint) -{ - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (endpoint)); - return priv->info.direction; -} - -static const struct spa_pod * -wp_exported_endpoint_get_control (WpEndpoint * endpoint, guint32 control_id) -{ - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (endpoint)); - - return wp_spa_props_get_stored (&priv->spa_props, control_id); + return client_endpoint_set_param (self, id, flags, param); } static gboolean -wp_exported_endpoint_set_control (WpEndpoint * endpoint, guint32 control_id, +wp_impl_endpoint_set_control (WpEndpoint * endpoint, guint32 control_id, const struct spa_pod * pod) { - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (endpoint)); + WpImplEndpointPrivate *priv = + wp_impl_endpoint_get_instance_private (WP_IMPL_ENDPOINT (endpoint)); - if (wp_spa_props_store_pod (&priv->spa_props, control_id, pod) < 0) + if (wp_spa_props_store_pod (&priv->pp->spa_props, control_id, pod) < 0) return FALSE; g_signal_emit (endpoint, signals[SIGNAL_CONTROL_CHANGED], 0, control_id); /* update only after the endpoint has been exported */ - if (priv->info.id != 0) { - client_endpoint_update (WP_EXPORTED_ENDPOINT (endpoint), - PW_CLIENT_ENDPOINT_UPDATE_PARAMS, 0); + if (wp_proxy_get_features (WP_PROXY (endpoint)) & WP_PROXY_FEATURE_BOUND) { + client_endpoint_update (WP_IMPL_ENDPOINT (endpoint), + PW_CLIENT_ENDPOINT_UPDATE_PARAMS, 0); } return TRUE; } static void -wp_exported_endpoint_class_init (WpExportedEndpointClass * klass) +wp_impl_endpoint_class_init (WpImplEndpointClass * klass) { GObjectClass *object_class = (GObjectClass *) klass; - WpExportedClass *exported_class = (WpExportedClass *) klass; + WpProxyClass *proxy_class = (WpProxyClass *) klass; + WpEndpointClass *endpoint_class = (WpEndpointClass *) klass; - object_class->finalize = wp_exported_endpoint_finalize; - object_class->get_property = wp_exported_endpoint_get_property; + object_class->finalize = wp_impl_endpoint_finalize; - exported_class->export = wp_exported_endpoint_export; - exported_class->unexport = wp_exported_endpoint_unexport; - exported_class->get_proxy = wp_exported_endpoint_get_proxy; + proxy_class->augment = wp_impl_endpoint_augment; + proxy_class->enum_params = NULL; + proxy_class->subscribe_params = NULL; + proxy_class->set_param = wp_impl_endpoint_set_param; - g_object_class_install_property (object_class, EXPORTED_PROP_GLOBAL_ID, - g_param_spec_uint ("global-id", "global-id", - "The pipewire global id of the exported endpoint", 0, G_MAXUINT, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (object_class, EXPORTED_PROP_PROPERTIES, - g_param_spec_boxed ("properties", "properties", - "The pipewire properties of the object", WP_TYPE_PROPERTIES, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + proxy_class->pw_proxy_created = NULL; + proxy_class->param = NULL; + endpoint_class->set_control = wp_impl_endpoint_set_control; } -static void -wp_exported_endpoint_iface_init (WpEndpointInterface * iface) -{ - iface->get_name = wp_exported_endpoint_get_name; - iface->get_media_class = wp_exported_endpoint_get_media_class; - iface->get_direction = wp_exported_endpoint_get_direction; - iface->get_control = wp_exported_endpoint_get_control; - iface->set_control = wp_exported_endpoint_set_control; -} - -WpExportedEndpoint * -wp_exported_endpoint_new (WpCore * core) +WpImplEndpoint * +wp_impl_endpoint_new (WpCore * core) { g_return_val_if_fail (WP_IS_CORE (core), NULL); - return g_object_new (WP_TYPE_EXPORTED_ENDPOINT, + return g_object_new (WP_TYPE_IMPL_ENDPOINT, "core", core, NULL); } -/** - * wp_exported_endpoint_get_global_id: (method) - * @self: the endpoint - * - * Returns: the pipewire global id of the exported endpoint object. This - * is only valid after the wp_exported_export() async operation has finished. - */ -guint32 -wp_exported_endpoint_get_global_id (WpExportedEndpoint * self) -{ - WpExportedEndpointPrivate *priv; - - g_return_val_if_fail (WP_IS_EXPORTED_ENDPOINT (self), 0); - priv = wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); - - return priv->info.id; -} - -WpProperties * -wp_exported_endpoint_get_properties (WpExportedEndpoint * self) -{ - WpExportedEndpointPrivate *priv = - wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); - - return wp_properties_ref (priv->properties); -} - void -wp_exported_endpoint_set_property (WpExportedEndpoint * self, +wp_impl_endpoint_set_property (WpImplEndpoint * self, const gchar * key, const gchar * value) { - WpExportedEndpointPrivate *priv; + WpImplEndpointPrivate *priv; - g_return_if_fail (WP_IS_EXPORTED_ENDPOINT (self)); - priv = wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); + g_return_if_fail (WP_IS_IMPL_ENDPOINT (self)); + priv = wp_impl_endpoint_get_instance_private (self); - wp_properties_set (priv->properties, key, value); + wp_properties_set (priv->pp->properties, key, value); g_object_notify (G_OBJECT (self), "properties"); /* update only after the endpoint has been exported */ - if (priv->info.id != 0) { - client_endpoint_update (WP_EXPORTED_ENDPOINT (self), - PW_CLIENT_ENDPOINT_UPDATE_INFO, PW_ENDPOINT_CHANGE_MASK_PROPS); + if (wp_proxy_get_features (WP_PROXY (self)) & WP_PROXY_FEATURE_BOUND) { + client_endpoint_update (self, PW_CLIENT_ENDPOINT_UPDATE_INFO, + PW_ENDPOINT_CHANGE_MASK_PROPS); } } void -wp_exported_endpoint_update_properties (WpExportedEndpoint * self, +wp_impl_endpoint_update_properties (WpImplEndpoint * self, WpProperties * updates) { - WpExportedEndpointPrivate *priv; + WpImplEndpointPrivate *priv; - g_return_if_fail (WP_IS_EXPORTED_ENDPOINT (self)); - priv = wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); + g_return_if_fail (WP_IS_IMPL_ENDPOINT (self)); + priv = wp_impl_endpoint_get_instance_private (self); - wp_properties_update_from_dict (priv->properties, + wp_properties_update_from_dict (priv->pp->properties, wp_properties_peek_dict (updates)); g_object_notify (G_OBJECT (self), "properties"); /* update only after the endpoint has been exported */ - if (priv->info.id != 0) { - client_endpoint_update (WP_EXPORTED_ENDPOINT (self), - PW_CLIENT_ENDPOINT_UPDATE_INFO, PW_ENDPOINT_CHANGE_MASK_PROPS); + if (wp_proxy_get_features (WP_PROXY (self)) & WP_PROXY_FEATURE_BOUND) { + client_endpoint_update (self, PW_CLIENT_ENDPOINT_UPDATE_INFO, + PW_ENDPOINT_CHANGE_MASK_PROPS); } } void -wp_exported_endpoint_set_name (WpExportedEndpoint * self, const gchar * name) +wp_impl_endpoint_set_name (WpImplEndpoint * self, const gchar * name) { - WpExportedEndpointPrivate *priv; + WpImplEndpointPrivate *priv; - g_return_if_fail (WP_IS_EXPORTED_ENDPOINT (self)); - priv = wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); + g_return_if_fail (WP_IS_IMPL_ENDPOINT (self)); + priv = wp_impl_endpoint_get_instance_private (self); g_free (priv->info.name); priv->info.name = g_strdup (name); } void -wp_exported_endpoint_set_media_class (WpExportedEndpoint * self, +wp_impl_endpoint_set_media_class (WpImplEndpoint * self, const gchar * media_class) { - WpExportedEndpointPrivate *priv; + WpImplEndpointPrivate *priv; - g_return_if_fail (WP_IS_EXPORTED_ENDPOINT (self)); - priv = wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); + g_return_if_fail (WP_IS_IMPL_ENDPOINT (self)); + priv = wp_impl_endpoint_get_instance_private (self); g_free (priv->info.media_class); priv->info.media_class = g_strdup (media_class); } void -wp_exported_endpoint_set_direction (WpExportedEndpoint * self, WpDirection dir) +wp_impl_endpoint_set_direction (WpImplEndpoint * self, WpDirection dir) { - WpExportedEndpointPrivate *priv; + WpImplEndpointPrivate *priv; - g_return_if_fail (WP_IS_EXPORTED_ENDPOINT (self)); - priv = wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); + g_return_if_fail (WP_IS_IMPL_ENDPOINT (self)); + priv = wp_impl_endpoint_get_instance_private (self); priv->info.direction = (enum pw_direction) dir; } void -wp_exported_endpoint_register_control (WpExportedEndpoint * self, +wp_impl_endpoint_register_control (WpImplEndpoint * self, WpEndpointControl control) { - WpExportedEndpointPrivate *priv; + WpImplEndpointPrivate *priv; - g_return_if_fail (WP_IS_EXPORTED_ENDPOINT (self)); - priv = wp_exported_endpoint_get_instance_private (WP_EXPORTED_ENDPOINT (self)); + 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->spa_props, control, + 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->spa_props, control, + 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->spa_props, control, + wp_spa_props_register (&priv->pp->spa_props, control, "Channel Volumes", SPA_POD_CHOICE_RANGE_Float (1.0, 0.0, 10.0)); break; default: diff --git a/lib/wp/endpoint.h b/lib/wp/endpoint.h index 54bc378f..01857cf0 100644 --- a/lib/wp/endpoint.h +++ b/lib/wp/endpoint.h @@ -9,15 +9,10 @@ #ifndef __WIREPLUMBER_ENDPOINT_H__ #define __WIREPLUMBER_ENDPOINT_H__ -#include "exported.h" #include "proxy.h" G_BEGIN_DECLS -#define WP_TYPE_ENDPOINT (wp_endpoint_get_type ()) -WP_API -G_DECLARE_INTERFACE (WpEndpoint, wp_endpoint, WP, ENDPOINT, GObject) - /** * WpDirection: * @WP_DIRECTION_INPUT: a sink, consuming input @@ -36,9 +31,19 @@ typedef enum { WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES = 0x10008 /* SPA_PROP_channelVolumes */, } WpEndpointControl; -struct _WpEndpointInterface +typedef enum { /*< flags >*/ + WP_ENDPOINT_FEATURE_CONTROLS = WP_PROXY_FEATURE_LAST, +} WpEndpointFeatures; + +/* WpEndpoint */ + +#define WP_TYPE_ENDPOINT (wp_endpoint_get_type ()) +WP_API +G_DECLARE_DERIVABLE_TYPE (WpEndpoint, wp_endpoint, WP, ENDPOINT, WpProxy) + +struct _WpEndpointClass { - GTypeInterface parent; + WpProxyClass parent_class; const gchar * (*get_name) (WpEndpoint * self); const gchar * (*get_media_class) (WpEndpoint * self); @@ -47,8 +52,6 @@ struct _WpEndpointInterface const struct spa_pod * (*get_control) (WpEndpoint * self, guint32 control_id); gboolean (*set_control) (WpEndpoint * self, guint32 control_id, const struct spa_pod * value); - - // void (*create_link) (WpEndpoint * self, WpProperties * props); }; WP_API @@ -92,70 +95,45 @@ WP_API gboolean wp_endpoint_set_control_float (WpEndpoint * self, guint32 control_id, gfloat value); -// void wp_endpoint_create_link (WpEndpoint * self, WpProperties * props); +/* WpImplEndpoint */ -/* proxy */ - -typedef enum { /*< flags >*/ - WP_PROXY_ENDPOINT_FEATURE_CONTROLS = WP_PROXY_FEATURE_LAST, -} WpProxyEndpointFeatures; - -#define WP_TYPE_PROXY_ENDPOINT (wp_proxy_endpoint_get_type ()) +#define WP_TYPE_IMPL_ENDPOINT (wp_impl_endpoint_get_type ()) WP_API -G_DECLARE_FINAL_TYPE (WpProxyEndpoint, wp_proxy_endpoint, - WP, PROXY_ENDPOINT, WpProxy) +G_DECLARE_DERIVABLE_TYPE (WpImplEndpoint, wp_impl_endpoint, + WP, IMPL_ENDPOINT, WpEndpoint) -/* exported */ - -#define WP_TYPE_EXPORTED_ENDPOINT (wp_exported_endpoint_get_type ()) -WP_API -G_DECLARE_DERIVABLE_TYPE (WpExportedEndpoint, wp_exported_endpoint, - WP, EXPORTED_ENDPOINT, WpExported) - -struct _WpExportedEndpointClass +struct _WpImplEndpointClass { - WpExportedClass parent_class; + WpEndpointClass parent_class; }; WP_API -WpExportedEndpoint * wp_exported_endpoint_new (WpCore * core); +WpImplEndpoint * wp_impl_endpoint_new (WpCore * core); WP_API -guint32 wp_exported_endpoint_get_global_id (WpExportedEndpoint * self); - -WP_API -WpProperties * wp_exported_endpoint_get_properties (WpExportedEndpoint * self); - -WP_API -void wp_exported_endpoint_set_property (WpExportedEndpoint * self, +void wp_impl_endpoint_set_property (WpImplEndpoint * self, const gchar * key, const gchar * value); WP_API -void wp_exported_endpoint_update_properties (WpExportedEndpoint * self, +void wp_impl_endpoint_update_properties (WpImplEndpoint * self, WpProperties * updates); WP_API -void wp_exported_endpoint_set_name (WpExportedEndpoint * self, +void wp_impl_endpoint_set_name (WpImplEndpoint * self, const gchar * name); WP_API -void wp_exported_endpoint_set_media_class (WpExportedEndpoint * self, +void wp_impl_endpoint_set_media_class (WpImplEndpoint * self, const gchar * media_class); WP_API -void wp_exported_endpoint_set_direction (WpExportedEndpoint * self, +void wp_impl_endpoint_set_direction (WpImplEndpoint * self, WpDirection dir); WP_API -void wp_exported_endpoint_register_control (WpExportedEndpoint * self, +void wp_impl_endpoint_register_control (WpImplEndpoint * self, WpEndpointControl control); -// void wp_exported_endpoint_register_stream (WpExportedEndpoint * self, -// WpExportedEndpointStream * stream); -// void wp_exported_endpoint_remove_stream (WpExportedEndpoint * self, -// WpExportedEndpointStream * stream); -// GPtrArray * wp_exported_endpoint_list_streams (WpExportedEndpoint * self); - G_END_DECLS #endif diff --git a/modules/module-pipewire/audio-softdsp-endpoint.c b/modules/module-pipewire/audio-softdsp-endpoint.c index 6fb94560..8f3761f2 100644 --- a/modules/module-pipewire/audio-softdsp-endpoint.c +++ b/modules/module-pipewire/audio-softdsp-endpoint.c @@ -48,7 +48,7 @@ struct _WpPwAudioSoftdspEndpoint WpAudioStream *adapter; GPtrArray *converters; - WpExportedEndpoint *exported_ep; + WpImplEndpoint *impl_ep; }; enum { @@ -116,7 +116,7 @@ endpoint_get_global_id (WpBaseEndpoint *ep) { WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (ep); - return wp_exported_endpoint_get_global_id (self->exported_ep); + return wp_proxy_get_bound_id (WP_PROXY (self->impl_ep)); } static gboolean @@ -169,19 +169,19 @@ on_adapter_control_changed (WpAudioStream * s, guint32 control_id, { /* block to avoid recursion - WpEndpoint emits the "control-changed" signal when we change the value here */ - g_signal_handlers_block_by_func (self->exported_ep, + g_signal_handlers_block_by_func (self->impl_ep, on_exported_control_changed, self); switch (control_id) { case WP_ENDPOINT_CONTROL_VOLUME: { gfloat vol = wp_audio_stream_get_volume (s); - wp_endpoint_set_control_float (WP_ENDPOINT (self->exported_ep), + wp_endpoint_set_control_float (WP_ENDPOINT (self->impl_ep), control_id, vol); break; } case WP_ENDPOINT_CONTROL_MUTE: { gboolean m = wp_audio_stream_get_mute (s); - wp_endpoint_set_control_boolean (WP_ENDPOINT (self->exported_ep), + wp_endpoint_set_control_boolean (WP_ENDPOINT (self->impl_ep), control_id, m); break; } @@ -189,12 +189,12 @@ on_adapter_control_changed (WpAudioStream * s, guint32 control_id, break; } - g_signal_handlers_unblock_by_func (self->exported_ep, + g_signal_handlers_unblock_by_func (self->impl_ep, on_exported_control_changed, self); } static void -on_endpoint_exported (GObject * exported, GAsyncResult *res, gpointer data) +on_endpoint_exported (GObject * impl_ep, GAsyncResult *res, gpointer data) { WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (data); GError *error = NULL; @@ -202,7 +202,7 @@ on_endpoint_exported (GObject * exported, GAsyncResult *res, gpointer data) g_return_if_fail (self->init_task); /* Get the object */ - wp_exported_export_finish (WP_EXPORTED (exported), res, &error); + wp_proxy_augment_finish (WP_PROXY (impl_ep), res, &error); if (error) { g_warning ("WpPwAudioSoftdspEndpoint:%p Aborting construction", self); g_task_return_error (self->init_task, error); @@ -221,15 +221,15 @@ do_export (WpPwAudioSoftdspEndpoint *self) g_autoptr (WpProperties) props = NULL; g_autoptr (WpProperties) extra_props = NULL; - g_return_if_fail (!self->exported_ep); + g_return_if_fail (!self->impl_ep); - self->exported_ep = wp_exported_endpoint_new (core); + self->impl_ep = wp_impl_endpoint_new (core); - wp_exported_endpoint_register_control (self->exported_ep, + wp_impl_endpoint_register_control (self->impl_ep, WP_ENDPOINT_CONTROL_VOLUME); - wp_exported_endpoint_register_control (self->exported_ep, + wp_impl_endpoint_register_control (self->impl_ep, WP_ENDPOINT_CONTROL_MUTE); - // wp_exported_endpoint_register_control (self->exported_ep, + // wp_impl_endpoint_register_control (self->impl_ep, // WP_ENDPOINT_CONTROL_CHANNEL_VOLUMES); props = wp_proxy_get_properties (WP_PROXY (self->node)); @@ -242,28 +242,28 @@ do_export (WpPwAudioSoftdspEndpoint *self) wp_properties_setf (extra_props, "endpoint.priority", "%d", wp_base_endpoint_get_priority (WP_BASE_ENDPOINT (self))); - wp_exported_endpoint_update_properties (self->exported_ep, props); - wp_exported_endpoint_update_properties (self->exported_ep, extra_props); + wp_impl_endpoint_update_properties (self->impl_ep, props); + wp_impl_endpoint_update_properties (self->impl_ep, extra_props); - wp_exported_endpoint_set_name (self->exported_ep, + wp_impl_endpoint_set_name (self->impl_ep, wp_base_endpoint_get_name (WP_BASE_ENDPOINT (self))); - wp_exported_endpoint_set_media_class (self->exported_ep, + wp_impl_endpoint_set_media_class (self->impl_ep, wp_base_endpoint_get_media_class (WP_BASE_ENDPOINT (self))); - wp_exported_endpoint_set_direction (self->exported_ep, + 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->exported_ep), + 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->exported_ep), + wp_endpoint_set_control_boolean (WP_ENDPOINT (self->impl_ep), WP_ENDPOINT_CONTROL_MUTE, wp_audio_stream_get_mute (self->adapter)); - g_signal_connect_object (self->exported_ep, "control-changed", + g_signal_connect_object (self->impl_ep, "control-changed", (GCallback) on_exported_control_changed, self, 0); g_signal_connect_object (self->adapter, "control-changed", (GCallback) on_adapter_control_changed, self, 0); - wp_exported_export (WP_EXPORTED (self->exported_ep), NULL, - on_endpoint_exported, self); + wp_proxy_augment (WP_PROXY (self->impl_ep), WP_PROXY_FEATURE_BOUND, + NULL, on_endpoint_exported, self); } static void @@ -354,9 +354,7 @@ endpoint_finalize (GObject * object) { WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object); - if (self->exported_ep) - wp_exported_unexport (WP_EXPORTED (self->exported_ep)); - g_clear_object (&self->exported_ep); + g_clear_object (&self->impl_ep); g_clear_pointer(&self->streams, g_variant_unref); diff --git a/modules/module-session.c b/modules/module-session.c index 4104ea1d..06292aa1 100644 --- a/modules/module-session.c +++ b/modules/module-session.c @@ -26,7 +26,7 @@ select_new_default_ep (struct module_data * data, WpDefaultEndpointType type, for (guint i = 0; i < arr->len; i++) { WpEndpoint *ep = g_ptr_array_index (arr, i); - guint32 id = wp_exported_endpoint_get_global_id (WP_EXPORTED_ENDPOINT (ep)); + guint32 id = wp_proxy_get_bound_id (WP_PROXY (ep)); guint32 priority = 0; const gchar *priority_str; @@ -38,8 +38,7 @@ select_new_default_ep (struct module_data * data, WpDefaultEndpointType type, if (g_strcmp0 (media_class, wp_endpoint_get_media_class (ep)) != 0) continue; - g_autoptr (WpProperties) properties = - wp_exported_endpoint_get_properties (WP_EXPORTED_ENDPOINT (ep)); + g_autoptr (WpProperties) properties = wp_proxy_get_properties (WP_PROXY (ep)); priority_str = wp_properties_get (properties, "endpoint.priority"); if (priority_str) @@ -99,7 +98,7 @@ on_endpoint_removed (WpObjectManager * om, WpEndpoint * ep, else return; - ep_id = wp_exported_endpoint_get_global_id (WP_EXPORTED_ENDPOINT (ep)); + ep_id = wp_proxy_get_bound_id (WP_PROXY (ep)); def_id = wp_session_get_default_endpoint (WP_SESSION (data->session), type); if (ep_id == def_id) @@ -135,6 +134,6 @@ wireplumber__module_init (WpModule * module, WpCore * core, GVariant * args) g_signal_connect (data->om, "object-removed", (GCallback) on_endpoint_removed, data); wp_object_manager_add_object_interest (data->om, - WP_TYPE_EXPORTED_ENDPOINT, NULL); + WP_TYPE_IMPL_ENDPOINT, NULL); wp_core_install_object_manager (core, data->om); } diff --git a/tests/wp/endpoint.c b/tests/wp/endpoint.c index dbdfc212..b3700f69 100644 --- a/tests/wp/endpoint.c +++ b/tests/wp/endpoint.c @@ -29,7 +29,7 @@ typedef struct { WpCore *proxy_core; WpObjectManager *proxy_om; - WpExportedEndpoint *exported_endpoint; + WpImplEndpoint *impl_endpoint; WpProxy *proxy_endpoint; gint n_events; @@ -109,32 +109,30 @@ test_endpoint_teardown (TestEndpointFixture *self, gconstpointer user_data) } static void -test_endpoint_basic_exported_object_added (WpObjectManager *om, +test_endpoint_basic_impl_object_added (WpObjectManager *om, WpEndpoint *endpoint, TestEndpointFixture *fixture) { - g_debug ("exported object added"); + g_debug ("impl object added"); - g_assert_true (WP_IS_ENDPOINT (endpoint)); - g_assert_true (WP_IS_EXPORTED_ENDPOINT (endpoint)); + g_assert_true (WP_IS_IMPL_ENDPOINT (endpoint)); - g_assert_null (fixture->exported_endpoint); - fixture->exported_endpoint = WP_EXPORTED_ENDPOINT (endpoint); + g_assert_null (fixture->impl_endpoint); + fixture->impl_endpoint = WP_IMPL_ENDPOINT (endpoint); if (++fixture->n_events == 3) g_main_loop_quit (fixture->loop); } static void -test_endpoint_basic_exported_object_removed (WpObjectManager *om, +test_endpoint_basic_impl_object_removed (WpObjectManager *om, WpEndpoint *endpoint, TestEndpointFixture *fixture) { - g_debug ("exported object removed"); + g_debug ("impl object removed"); - g_assert_true (WP_IS_ENDPOINT (endpoint)); - g_assert_true (WP_IS_EXPORTED_ENDPOINT (endpoint)); + g_assert_true (WP_IS_IMPL_ENDPOINT (endpoint)); - g_assert_nonnull (fixture->exported_endpoint); - fixture->exported_endpoint = NULL; + g_assert_nonnull (fixture->impl_endpoint); + fixture->impl_endpoint = NULL; if (++fixture->n_events == 2) g_main_loop_quit (fixture->loop); @@ -147,7 +145,6 @@ test_endpoint_basic_proxy_object_added (WpObjectManager *om, g_debug ("proxy object added"); g_assert_true (WP_IS_ENDPOINT (endpoint)); - g_assert_true (WP_IS_PROXY_ENDPOINT (endpoint)); g_assert_null (fixture->proxy_endpoint); fixture->proxy_endpoint = WP_PROXY (endpoint); @@ -163,7 +160,6 @@ test_endpoint_basic_proxy_object_removed (WpObjectManager *om, g_debug ("proxy object removed"); g_assert_true (WP_IS_ENDPOINT (endpoint)); - g_assert_true (WP_IS_PROXY_ENDPOINT (endpoint)); g_assert_nonnull (fixture->proxy_endpoint); fixture->proxy_endpoint = NULL; @@ -173,17 +169,17 @@ test_endpoint_basic_proxy_object_removed (WpObjectManager *om, } static void -test_endpoint_basic_export_done (WpExported * endpoint, GAsyncResult * res, +test_endpoint_basic_export_done (WpProxy * endpoint, GAsyncResult * res, TestEndpointFixture *fixture) { g_autoptr (GError) error = NULL; g_debug ("export done"); - g_assert_true (wp_exported_export_finish (endpoint, res, &error)); + g_assert_true (wp_proxy_augment_finish (endpoint, res, &error)); g_assert_no_error (error); - g_assert_true (WP_IS_EXPORTED_ENDPOINT (endpoint)); + g_assert_true (WP_IS_IMPL_ENDPOINT (endpoint)); if (++fixture->n_events == 3) g_main_loop_quit (fixture->loop); @@ -217,17 +213,17 @@ test_endpoint_basic_notify_properties (WpEndpoint * endpoint, GParamSpec * param static void test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) { - g_autoptr (WpExportedEndpoint) endpoint = NULL; + g_autoptr (WpImplEndpoint) endpoint = NULL; gfloat float_value; gboolean boolean_value; /* set up the export side */ g_signal_connect (fixture->export_om, "object-added", - (GCallback) test_endpoint_basic_exported_object_added, fixture); + (GCallback) test_endpoint_basic_impl_object_added, fixture); g_signal_connect (fixture->export_om, "object-removed", - (GCallback) test_endpoint_basic_exported_object_removed, fixture); + (GCallback) test_endpoint_basic_impl_object_removed, fixture); wp_object_manager_add_object_interest (fixture->export_om, - WP_TYPE_EXPORTED_ENDPOINT, NULL); + WP_TYPE_IMPL_ENDPOINT, NULL); wp_core_install_object_manager (fixture->export_core, fixture->export_om); g_assert_true (wp_core_connect (fixture->export_core)); @@ -240,16 +236,16 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) wp_object_manager_add_proxy_interest (fixture->proxy_om, PW_TYPE_INTERFACE_Endpoint, NULL, WP_PROXY_FEATURE_INFO | WP_PROXY_FEATURE_BOUND | - WP_PROXY_ENDPOINT_FEATURE_CONTROLS); + WP_ENDPOINT_FEATURE_CONTROLS); wp_core_install_object_manager (fixture->proxy_core, fixture->proxy_om); g_assert_true (wp_core_connect (fixture->proxy_core)); /* create endpoint */ - endpoint = wp_exported_endpoint_new (fixture->export_core); - wp_exported_endpoint_set_property (endpoint, "test.property", "test-value"); - wp_exported_endpoint_register_control (endpoint, WP_ENDPOINT_CONTROL_VOLUME); - wp_exported_endpoint_register_control (endpoint, WP_ENDPOINT_CONTROL_MUTE); + endpoint = wp_impl_endpoint_new (fixture->export_core); + wp_impl_endpoint_set_property (endpoint, "test.property", "test-value"); + wp_impl_endpoint_register_control (endpoint, WP_ENDPOINT_CONTROL_VOLUME); + wp_impl_endpoint_register_control (endpoint, WP_ENDPOINT_CONTROL_MUTE); g_assert_true (wp_endpoint_set_control_float (WP_ENDPOINT (endpoint), WP_ENDPOINT_CONTROL_VOLUME, 0.7f)); g_assert_true (wp_endpoint_set_control_boolean (WP_ENDPOINT (endpoint), @@ -258,7 +254,7 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) /* verify properties are set before export */ { g_autoptr (WpProperties) props = - wp_exported_endpoint_get_properties (endpoint); + wp_proxy_get_properties (WP_PROXY (endpoint)); g_assert_cmpstr (wp_properties_get (props, "test.property"), ==, "test-value"); } @@ -270,16 +266,16 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) g_assert_cmpint (boolean_value, ==, TRUE); /* do export */ - wp_exported_export (WP_EXPORTED (endpoint), NULL, + wp_proxy_augment (WP_PROXY (endpoint), WP_PROXY_FEATURE_BOUND, NULL, (GAsyncReadyCallback) test_endpoint_basic_export_done, fixture); /* run until objects are created and features are cached */ fixture->n_events = 0; g_main_loop_run (fixture->loop); g_assert_cmpint (fixture->n_events, ==, 3); - g_assert_nonnull (fixture->exported_endpoint); + g_assert_nonnull (fixture->impl_endpoint); g_assert_nonnull (fixture->proxy_endpoint); - g_assert_true (fixture->exported_endpoint == endpoint); + g_assert_true (fixture->impl_endpoint == endpoint); /* test round 1: verify the values on the proxy */ @@ -287,10 +283,10 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) WP_PROXY_FEATURE_PW_PROXY | WP_PROXY_FEATURE_INFO | WP_PROXY_FEATURE_BOUND | - WP_PROXY_ENDPOINT_FEATURE_CONTROLS); + WP_ENDPOINT_FEATURE_CONTROLS); g_assert_cmpuint (wp_proxy_get_bound_id (fixture->proxy_endpoint), ==, - wp_exported_endpoint_get_global_id (endpoint)); + wp_proxy_get_bound_id (WP_PROXY (endpoint))); { g_autoptr (WpProperties) props = @@ -345,7 +341,7 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) g_assert_cmpfloat_with_epsilon (float_value, 1.0f, 0.001); g_assert_cmpint (boolean_value, ==, TRUE); - /* change control on the exported */ + /* 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)); @@ -372,9 +368,9 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) g_assert_cmpfloat_with_epsilon (float_value, 1.0f, 0.001); g_assert_cmpint (boolean_value, ==, FALSE); - /* change a property on the exported */ + /* change a property on the impl */ fixture->n_events = 0; - wp_exported_endpoint_set_property (endpoint, "test.property", "changed-value"); + wp_impl_endpoint_set_property (endpoint, "test.property", "changed-value"); /* run until the change is on both sides */ g_main_loop_run (fixture->loop); @@ -384,7 +380,7 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) { g_autoptr (WpProperties) props = - wp_exported_endpoint_get_properties (endpoint); + wp_proxy_get_properties (WP_PROXY (endpoint)); g_assert_cmpstr (wp_properties_get (props, "test.property"), ==, "changed-value"); } @@ -395,14 +391,14 @@ test_endpoint_basic (TestEndpointFixture *fixture, gconstpointer data) "changed-value"); } - /* unexport */ + /* destroy impl endpoint */ fixture->n_events = 0; - wp_exported_unexport (WP_EXPORTED (endpoint)); + g_clear_object (&endpoint); /* run until objects are destroyed */ g_main_loop_run (fixture->loop); g_assert_cmpint (fixture->n_events, ==, 2); - g_assert_null (fixture->exported_endpoint); + g_assert_null (fixture->impl_endpoint); g_assert_null (fixture->proxy_endpoint); } diff --git a/tools/wireplumber-cli.c b/tools/wireplumber-cli.c index 79476281..c4a0d91e 100644 --- a/tools/wireplumber-cli.c +++ b/tools/wireplumber-cli.c @@ -74,7 +74,7 @@ list_endpoints (WpObjectManager * om, struct WpCliData * d) session = WP_SESSION (g_object_ref (g_ptr_array_index (arr, 0))); g_clear_pointer (&arr, g_ptr_array_unref); - arr = wp_object_manager_get_objects (om, WP_TYPE_PROXY_ENDPOINT); + arr = wp_object_manager_get_objects (om, WP_TYPE_ENDPOINT); g_print ("Audio capture devices:\n"); for (i = 0; i < arr->len; i++) { @@ -118,7 +118,7 @@ set_default (WpObjectManager * om, struct WpCliData * d) return; } - arr = wp_object_manager_get_objects (om, WP_TYPE_PROXY_ENDPOINT); + arr = wp_object_manager_get_objects (om, WP_TYPE_ENDPOINT); for (i = 0; i < arr->len; i++) { WpEndpoint *ep = g_ptr_array_index (arr, i); @@ -152,7 +152,7 @@ set_volume (WpObjectManager * om, struct WpCliData * d) g_autoptr (GPtrArray) arr = NULL; guint i; - arr = wp_object_manager_get_objects (om, WP_TYPE_PROXY_ENDPOINT); + arr = wp_object_manager_get_objects (om, WP_TYPE_ENDPOINT); for (i = 0; i < arr->len; i++) { WpEndpoint *ep = g_ptr_array_index (arr, i); @@ -261,7 +261,7 @@ main (gint argc, gchar **argv) if (argc == 2 && !g_strcmp0 (argv[1], "ls-endpoints")) { wp_object_manager_add_proxy_interest (om, PW_TYPE_INTERFACE_Endpoint, NULL, WP_PROXY_FEATURE_INFO | WP_PROXY_FEATURE_BOUND | - WP_PROXY_ENDPOINT_FEATURE_CONTROLS); + WP_ENDPOINT_FEATURE_CONTROLS); wp_object_manager_add_proxy_interest (om, PW_TYPE_INTERFACE_Session, NULL, WP_PROXY_FEATURE_INFO | WP_PROXY_FEATURE_BOUND | WP_SESSION_FEATURE_DEFAULT_ENDPOINT); @@ -295,7 +295,7 @@ main (gint argc, gchar **argv) wp_object_manager_add_proxy_interest (om, PW_TYPE_INTERFACE_Endpoint, NULL, WP_PROXY_FEATURE_INFO | WP_PROXY_FEATURE_BOUND | - WP_PROXY_ENDPOINT_FEATURE_CONTROLS); + WP_ENDPOINT_FEATURE_CONTROLS); data.params.set_volume.id = id; data.params.set_volume.volume = volume;