mirror of
https://gitlab.freedesktop.org/pipewire/wireplumber.git
synced 2026-05-09 06:18:04 +02:00
modules: add support for multiple channels linking
This commit is contained in:
parent
be6256fb0a
commit
ff2420b70a
3 changed files with 71 additions and 44 deletions
|
|
@ -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);
|
||||
/* 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;
|
||||
|
||||
/* Create the link */
|
||||
pw_core_proxy_create_object(self->core_proxy, "link-factory",
|
||||
PW_TYPE_INTERFACE_Link, PW_VERSION_LINK, &props->dict, 0);
|
||||
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;
|
||||
|
||||
/* Clean up */
|
||||
pw_properties_free(props);
|
||||
/* 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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue