diff --git a/modules/module-pw-audio-softdsp-endpoint.c b/modules/module-pw-audio-softdsp-endpoint.c index 6d9716d825fb32714427de7bf192428b95122d71..d3f351f47504a57dc2b4d249652a67510b08a9e7 100644 --- a/modules/module-pw-audio-softdsp-endpoint.c +++ b/modules/module-pw-audio-softdsp-endpoint.c @@ -55,88 +55,18 @@ struct _WpPwAudioSoftdspEndpoint { struct spa_list *port_list; }; +enum { + PROP_0, + PROP_NODE_PROXY, +}; + G_DECLARE_FINAL_TYPE (WpPwAudioSoftdspEndpoint, endpoint, WP_PW, AUDIO_SOFTDSP_ENDPOINT, WpEndpoint) G_DEFINE_TYPE (WpPwAudioSoftdspEndpoint, endpoint, WP_TYPE_ENDPOINT) static void -endpoint_init (WpPwAudioSoftdspEndpoint * self) -{ -} - -static void -endpoint_finalize (GObject * object) -{ - WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object); - - /* Remove and destroy the node_proxy */ - if (self->node_proxy) { - spa_hook_remove (&self->listener); - pw_proxy_destroy ((struct pw_proxy *) self->node_proxy); - } - - /* Remove and destroy the dsp_proxy */ - if (self->dsp_proxy) { - spa_hook_remove (&self->dsp_listener); - pw_proxy_destroy ((struct pw_proxy *) self->dsp_proxy); - } - - G_OBJECT_CLASS (endpoint_parent_class)->finalize (object); -} - -static gboolean -endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id, - WpEndpointLink * link, GVariant ** properties, GError ** error) -{ - WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (ep); - WpPort *port = NULL, *node_port = NULL, *dsp_port = NULL; - GVariantBuilder b; - - /* Find the node port */ - spa_list_for_each(port, self->port_list, l) { - if (self->node_info->id == port->parent_id) { - node_port = port; - break; - } - } - if (!node_port) - return FALSE; - - /* Find the first dsp port with the same direction as the node port */ - spa_list_for_each(port, self->port_list, l) { - if (self->dsp_info->id == port->parent_id - && port->direction == node_port->direction) { - dsp_port = port; - break; - } - } - if (!dsp_port) - return FALSE; - - /* Set the properties */ - g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); - g_variant_builder_add (&b, "{sv}", "node-id", - g_variant_new_uint32 (self->dsp_info->id)); - g_variant_builder_add (&b, "{sv}", "node-port-id", - g_variant_new_uint32 (dsp_port->id)); - *properties = g_variant_builder_end (&b); - - return TRUE; -} - -static void -endpoint_class_init (WpPwAudioSoftdspEndpointClass * klass) -{ - GObjectClass *object_class = (GObjectClass *) klass; - WpEndpointClass *endpoint_class = (WpEndpointClass *) klass; - - object_class->finalize = endpoint_finalize; - - endpoint_class->prepare_link = endpoint_prepare_link; -} - -static void on_dsp_running(WpPwAudioSoftdspEndpoint *self) +on_dsp_running (WpPwAudioSoftdspEndpoint *self) { struct pw_properties *props; @@ -169,7 +99,8 @@ static void on_dsp_running(WpPwAudioSoftdspEndpoint *self) pw_properties_free(props); } -static void dsp_node_event_info(void *data, const struct pw_node_info *info) +static void +dsp_node_event_info (void *data, const struct pw_node_info *info) { WpPwAudioSoftdspEndpoint *self = data; @@ -195,7 +126,8 @@ static const struct pw_node_proxy_events dsp_node_events = { .info = dsp_node_event_info, }; -static void emit_audio_dsp_node(WpPwAudioSoftdspEndpoint *self) +static void +emit_audio_dsp_node (WpPwAudioSoftdspEndpoint *self) { struct pw_properties *props; const char *dsp_name = NULL; @@ -220,7 +152,8 @@ static void emit_audio_dsp_node(WpPwAudioSoftdspEndpoint *self) /* Set the properties */ pw_properties_set(props, "audio-dsp.name", dsp_name); pw_properties_setf(props, "audio-dsp.direction", "%d", self->direction); - pw_properties_setf(props, "audio-dsp.maxbuffer", "%ld", MAX_QUANTUM_SIZE * sizeof(float)); + pw_properties_setf(props, "audio-dsp.maxbuffer", "%ld", + MAX_QUANTUM_SIZE * sizeof(float)); /* Set the DSP proxy and listener */ self->dsp_proxy = pw_core_proxy_create_object(self->core_proxy, "audio-dsp", @@ -242,7 +175,8 @@ static void emit_audio_dsp_node(WpPwAudioSoftdspEndpoint *self) pw_properties_free(props); } -static void node_event_info(void *data, const struct pw_node_info *info) +static void +node_event_info (void *data, const struct pw_node_info *info) { WpPwAudioSoftdspEndpoint *self = data; WpPort *port = NULL; @@ -280,10 +214,58 @@ static void node_event_info(void *data, const struct pw_node_info *info) } } -static void node_proxy_destroy(void *data) +static const struct pw_node_proxy_events node_events = { + PW_VERSION_NODE_PROXY_EVENTS, + .info = node_event_info, +}; + +static void +node_proxy_destroy(void *data) { WpPwAudioSoftdspEndpoint *self = data; + wp_endpoint_unregister (WP_ENDPOINT (self)); +} + +static const struct pw_proxy_events node_proxy_events = { + PW_VERSION_PROXY_EVENTS, + .destroy = node_proxy_destroy, +}; + +static void +endpoint_init (WpPwAudioSoftdspEndpoint * self) +{ +} + +static void +endpoint_constructed (GObject * object) +{ + WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object); + const gchar *media_class = wp_endpoint_get_media_class (WP_ENDPOINT (self)); + + /* Set the direction */ + if (g_str_has_suffix (media_class, "Source")) { + self->direction = PW_DIRECTION_INPUT; + } else if (g_str_has_suffix (media_class, "Sink")) { + self->direction = PW_DIRECTION_OUTPUT; + } else { + g_critical ("failed to parse direction"); + } + + /* Set the node and proxy listeners */ + pw_proxy_add_listener (self->node_proxy, &self->listener, &node_proxy_events, + self); + pw_node_proxy_add_listener((struct pw_node_proxy *) self->node_proxy, + &self->proxy_listener, &node_events, self); + + G_OBJECT_CLASS (endpoint_parent_class)->constructed (object); +} + +static void +endpoint_finalize (GObject * object) +{ + WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object); + /* Clear node_info */ if (self->node_info) pw_node_info_free(self->node_info); @@ -292,18 +274,111 @@ static void node_proxy_destroy(void *data) if (self->dsp_info) pw_node_info_free(self->dsp_info); - wp_endpoint_unregister (WP_ENDPOINT (self)); + /* Remove and destroy the node_proxy */ + if (self->node_proxy) { + spa_hook_remove (&self->listener); + pw_proxy_destroy ((struct pw_proxy *) self->node_proxy); + } + + /* Remove and destroy the dsp_proxy */ + if (self->dsp_proxy) { + spa_hook_remove (&self->dsp_listener); + pw_proxy_destroy ((struct pw_proxy *) self->dsp_proxy); + } + + G_OBJECT_CLASS (endpoint_parent_class)->finalize (object); } -static const struct pw_proxy_events node_proxy_events = { - PW_VERSION_PROXY_EVENTS, - .destroy = node_proxy_destroy, -}; +static void +endpoint_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object); -static const struct pw_node_proxy_events node_events = { - PW_VERSION_NODE_PROXY_EVENTS, - .info = node_event_info, -}; + switch (property_id) { + case PROP_NODE_PROXY: + self->node_proxy = g_value_get_pointer (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static void +endpoint_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (object); + + switch (property_id) { + case PROP_NODE_PROXY: + g_value_set_pointer (value, self->node_proxy); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +static gboolean +endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id, + WpEndpointLink * link, GVariant ** properties, GError ** error) +{ + WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (ep); + WpPort *port = NULL, *node_port = NULL, *dsp_port = NULL; + GVariantBuilder b; + + /* Find the node port */ + spa_list_for_each(port, self->port_list, l) { + if (self->node_info->id == port->parent_id) { + node_port = port; + break; + } + } + if (!node_port) + return FALSE; + + /* Find the first dsp port with the same direction as the node port */ + spa_list_for_each(port, self->port_list, l) { + if (self->dsp_info->id == port->parent_id + && port->direction == node_port->direction) { + dsp_port = port; + break; + } + } + if (!dsp_port) + return FALSE; + + /* Set the properties */ + g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); + g_variant_builder_add (&b, "{sv}", "node-id", + g_variant_new_uint32 (self->dsp_info->id)); + g_variant_builder_add (&b, "{sv}", "node-port-id", + g_variant_new_uint32 (dsp_port->id)); + *properties = g_variant_builder_end (&b); + + return TRUE; +} + +static void +endpoint_class_init (WpPwAudioSoftdspEndpointClass * klass) +{ + GObjectClass *object_class = (GObjectClass *) klass; + WpEndpointClass *endpoint_class = (WpEndpointClass *) klass; + + object_class->constructed = endpoint_constructed; + object_class->finalize = endpoint_finalize; + object_class->set_property = endpoint_set_property; + object_class->get_property = endpoint_get_property; + + endpoint_class->prepare_link = endpoint_prepare_link; + + g_object_class_install_property (object_class, PROP_NODE_PROXY, + g_param_spec_pointer ("node-proxy", "node-proxy", + "Pointer to the source/sink pw_node_proxy* of the device", + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); +} static gpointer endpoint_factory (WpFactory * factory, GType type, GVariant * properties) @@ -346,20 +421,11 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties) WpPwAudioSoftdspEndpoint *ep = g_object_new (endpoint_get_type (), "name", name, "media-class", media_class, + "node-proxy", (gpointer) proxy, NULL); if (!ep) return NULL; - /* Set the direction */ - if (g_str_has_suffix(media_class, "Source")) { - ep->direction = PW_DIRECTION_INPUT; - } else if (g_str_has_suffix(media_class, "Sink")) { - ep->direction = PW_DIRECTION_OUTPUT; - } else { - g_warning("failed to parse direction. Skipping..."); - return NULL; - } - /* Set the port list reference */ ep->port_list = (gpointer) port_list; @@ -370,13 +436,6 @@ endpoint_factory (WpFactory * factory, GType type, GVariant * properties) return NULL; } - /* Set the node proxy and listener */ - ep->node_proxy = (gpointer) proxy; - pw_proxy_add_listener (ep->node_proxy, &ep->listener, &node_proxy_events, - ep); - pw_proxy_add_proxy_listener(ep->node_proxy, &ep->proxy_listener, - &node_events, ep); - /* Return the object */ return ep; }