From ff2420b70aa304507542cf22e5c73a9cc49b4690 Mon Sep 17 00:00:00 2001 From: Julian Bouzas <julian.bouzas@collabora.com> Date: Mon, 24 Jun 2019 14:27:52 -0400 Subject: [PATCH] modules: add support for multiple channels linking --- .../module-pipewire/simple-endpoint-link.c | 58 ++++++++++++++----- modules/module-pipewire/simple-endpoint.c | 18 +++++- modules/module-pw-audio-softdsp-endpoint.c | 43 +++++--------- 3 files changed, 73 insertions(+), 46 deletions(-) diff --git a/modules/module-pipewire/simple-endpoint-link.c b/modules/module-pipewire/simple-endpoint-link.c index 9b899369..a7e8edc7 100644 --- a/modules/module-pipewire/simple-endpoint-link.c +++ b/modules/module-pipewire/simple-endpoint-link.c @@ -48,31 +48,57 @@ simple_endpoint_link_create (WpEndpointLink * epl, GVariant * src_data, { WpPipewireSimpleEndpointLink *self = WP_PIPEWIRE_SIMPLE_ENDPOINT_LINK(epl); struct pw_properties *props; - guint32 output_node_id, input_node_id, output_port_id, input_port_id; + guint32 output_node_id, input_node_id; + GVariant *src_ports, *sink_ports; + GVariantIter *out_iter, *in_iter; + guint64 out_ptr, in_ptr; /* Get the node ids and port ids */ if (!g_variant_lookup (src_data, "node-id", "u", &output_node_id)) return FALSE; - if (!g_variant_lookup (src_data, "node-port-id", "u", &output_port_id)) + src_ports = g_variant_lookup_value (src_data, "ports", G_VARIANT_TYPE_ARRAY); + if (!src_ports) return FALSE; if (!g_variant_lookup (sink_data, "node-id", "u", &input_node_id)) return FALSE; - if (!g_variant_lookup (sink_data, "node-port-id", "u", &input_port_id)) + sink_ports = g_variant_lookup_value (sink_data, "ports", G_VARIANT_TYPE_ARRAY); + if (!sink_ports) return FALSE; - /* Create the properties */ - props = pw_properties_new(NULL, NULL); - pw_properties_setf(props, PW_LINK_OUTPUT_NODE_ID, "%d", output_node_id); - pw_properties_setf(props, PW_LINK_OUTPUT_PORT_ID, "%d", output_port_id); - pw_properties_setf(props, PW_LINK_INPUT_NODE_ID, "%d", input_node_id); - pw_properties_setf(props, PW_LINK_INPUT_PORT_ID, "%d", input_port_id); - - /* Create the link */ - pw_core_proxy_create_object(self->core_proxy, "link-factory", - PW_TYPE_INTERFACE_Link, PW_VERSION_LINK, &props->dict, 0); - - /* Clean up */ - pw_properties_free(props); + /* Link all the output ports with the input ports */ + g_variant_get (src_ports, "at", &out_iter); + while (g_variant_iter_loop (out_iter, "t", &out_ptr)) { + WpProxyPort *out_p = (gpointer)out_ptr; + enum pw_direction out_direction = wp_proxy_port_get_info(out_p)->direction; + guint out_id = wp_proxy_get_global_id(WP_PROXY(out_p)); + if (out_direction == PW_DIRECTION_INPUT) + continue; + + g_variant_get (sink_ports, "at", &in_iter); + while (g_variant_iter_loop (in_iter, "t", &in_ptr)) { + WpProxyPort *in_p = (gpointer)in_ptr; + enum pw_direction in_direction = wp_proxy_port_get_info(in_p)->direction; + guint in_id = wp_proxy_get_global_id(WP_PROXY(in_p)); + if (in_direction == PW_DIRECTION_OUTPUT) + continue; + + /* Create the properties */ + props = pw_properties_new(NULL, NULL); + pw_properties_setf(props, PW_LINK_OUTPUT_NODE_ID, "%d", output_node_id); + pw_properties_setf(props, PW_LINK_OUTPUT_PORT_ID, "%d", out_id); + pw_properties_setf(props, PW_LINK_INPUT_NODE_ID, "%d", input_node_id); + pw_properties_setf(props, PW_LINK_INPUT_PORT_ID, "%d", in_id); + + /* Create the link */ + pw_core_proxy_create_object(self->core_proxy, "link-factory", + PW_TYPE_INTERFACE_Link, PW_VERSION_LINK, &props->dict, 0); + + /* Clean up */ + pw_properties_free(props); + } + g_variant_iter_free (in_iter); + } + g_variant_iter_free (out_iter); return TRUE; } diff --git a/modules/module-pipewire/simple-endpoint.c b/modules/module-pipewire/simple-endpoint.c index d3d33766..6f617d50 100644 --- a/modules/module-pipewire/simple-endpoint.c +++ b/modules/module-pipewire/simple-endpoint.c @@ -363,19 +363,31 @@ simple_endpoint_get_property (GObject * object, guint property_id, } } +static void +proxies_port_foreach_func(gpointer data, gpointer user_data) +{ + GVariantBuilder *b = user_data; + g_variant_builder_add (b, "t", data); +} + static gboolean simple_endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id, WpEndpointLink * link, GVariant ** properties, GError ** error) { WpPipewireSimpleEndpoint *self = WP_PIPEWIRE_SIMPLE_ENDPOINT (ep); - GVariantBuilder b; + GVariantBuilder b, *b_ports; + GVariant *v_ports; + + /* Create a variant array with all the ports */ + b_ports = g_variant_builder_new (G_VARIANT_TYPE ("at")); + g_ptr_array_foreach(self->proxies_port, proxies_port_foreach_func, b_ports); + v_ports = g_variant_builder_end (b_ports); /* 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->global_id)); - g_variant_builder_add (&b, "{sv}", "node-port-id", - g_variant_new_uint32 (-1)); + g_variant_builder_add (&b, "{sv}", "ports", v_ports); *properties = g_variant_builder_end (&b); return TRUE; diff --git a/modules/module-pw-audio-softdsp-endpoint.c b/modules/module-pw-audio-softdsp-endpoint.c index f901508e..d7da449d 100644 --- a/modules/module-pw-audio-softdsp-endpoint.c +++ b/modules/module-pw-audio-softdsp-endpoint.c @@ -53,7 +53,6 @@ struct _WpPwAudioSoftdspEndpoint gboolean master_mute; /* DSP */ - uint32_t dsp_port_id; struct spa_hook dsp_listener; struct pw_proxy *link_proxy; }; @@ -80,24 +79,37 @@ G_DEFINE_TYPE_WITH_CODE (WpPwAudioSoftdspEndpoint, endpoint, WP_TYPE_ENDPOINT, G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, wp_endpoint_async_initable_init)) +static void +proxies_dsp_port_foreach_func(gpointer data, gpointer user_data) +{ + GVariantBuilder *b = user_data; + g_variant_builder_add (b, "t", data); +} + static gboolean endpoint_prepare_link (WpEndpoint * ep, guint32 stream_id, WpEndpointLink * link, GVariant ** properties, GError ** error) { WpPwAudioSoftdspEndpoint *self = WP_PW_AUDIO_SOFTDSP_ENDPOINT (ep); const struct pw_node_info *dsp_info = NULL; - GVariantBuilder b; + GVariantBuilder b, *b_ports; + GVariant *v_ports; /* Get the dsp info */ dsp_info = wp_proxy_node_get_info(self->proxy_dsp); g_return_val_if_fail (dsp_info, FALSE); + /* Create a variant array with all the ports */ + b_ports = g_variant_builder_new (G_VARIANT_TYPE ("at")); + g_ptr_array_foreach(self->proxies_dsp_port, proxies_dsp_port_foreach_func, + b_ports); + v_ports = g_variant_builder_end (b_ports); + /* Set the properties */ g_variant_builder_init (&b, G_VARIANT_TYPE_VARDICT); g_variant_builder_add (&b, "{sv}", "node-id", g_variant_new_uint32 (dsp_info->id)); - g_variant_builder_add (&b, "{sv}", "node-port-id", - g_variant_new_uint32 (self->dsp_port_id)); + g_variant_builder_add (&b, "{sv}", "ports", v_ports); *properties = g_variant_builder_end (&b); return TRUE; @@ -436,36 +448,13 @@ static void handle_dsp_port(WpPwAudioSoftdspEndpoint *self, guint id, guint parent_id, const struct spa_dict *props) { - const char *direction_prop = NULL; struct pw_port_proxy *port_proxy = NULL; - enum pw_direction direction; /* Create the proxy dsp port async */ port_proxy = wp_remote_pipewire_proxy_bind (self->remote_pipewire, id, PW_TYPE_INTERFACE_Port); g_return_if_fail(port_proxy); wp_proxy_port_new(id, port_proxy, on_proxy_dsp_port_created, self); - - /* Make sure the port has porperties */ - g_return_if_fail(props); - - /* TODO: For now we only handle 1 DSP port */ - if (self->dsp_port_id != 0) - return; - - /* Get the direction property */ - direction_prop = spa_dict_lookup(props, "port.direction"); - if (!direction_prop) - return; - direction = - !strcmp(direction_prop, "out") ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT; - - /* Only handle ports with the opposite direction of the endpoint */ - if (self->direction == direction) - return; - - /* Set the dsp port id */ - self->dsp_port_id = id; } static void -- GitLab