mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-14 06:59:57 -05:00
node: add support for multiple input and output ports
Make it possible to have a mixer/spliter and converter for the gstreamer sources and sinks. Add logic to make a new input/output port when the existing ports are not of the required format.
This commit is contained in:
parent
e7e141a31d
commit
ca4f3d84cd
12 changed files with 568 additions and 186 deletions
|
|
@ -432,7 +432,8 @@ pinos_daemon_remove_node (PinosDaemon *daemon,
|
|||
*
|
||||
* Find the best port in @daemon that matches the given parameters.
|
||||
*
|
||||
* Returns: a #PinosPort or %NULL when no port could be found.
|
||||
* Returns: a #PinosPort or %NULL when no port could be found. unref the port
|
||||
* after usage.
|
||||
*/
|
||||
PinosPort *
|
||||
pinos_daemon_find_port (PinosDaemon *daemon,
|
||||
|
|
@ -445,7 +446,7 @@ pinos_daemon_find_port (PinosDaemon *daemon,
|
|||
PinosDaemonPrivate *priv;
|
||||
PinosServerPort *best = NULL;
|
||||
GList *nodes, *ports;
|
||||
gboolean have_name;
|
||||
gboolean have_name, created_port = FALSE;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_DAEMON (daemon), NULL);
|
||||
priv = daemon->priv;
|
||||
|
|
@ -456,6 +457,8 @@ pinos_daemon_find_port (PinosDaemon *daemon,
|
|||
PinosServerNode *n = nodes->data;
|
||||
gboolean node_found = FALSE;
|
||||
|
||||
g_debug ("name %s, node path %s", name, pinos_server_node_get_object_path (n));
|
||||
|
||||
/* we found the node */
|
||||
if (have_name && g_str_has_suffix (pinos_server_node_get_object_path (n), name)) {
|
||||
g_debug ("name \"%s\" matches node %p", name, n);
|
||||
|
|
@ -489,15 +492,23 @@ pinos_daemon_find_port (PinosDaemon *daemon,
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (node_found)
|
||||
break;
|
||||
if (best == NULL && node_found) {
|
||||
g_debug ("node %p: making port", n);
|
||||
best = pinos_server_node_create_port_sync (n, direction, name, format_filter, props);
|
||||
if (best != NULL) {
|
||||
created_port = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best == NULL) {
|
||||
if (error)
|
||||
*error = g_error_new (G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_FOUND,
|
||||
"No matching Port found");
|
||||
}
|
||||
g_set_error (error,
|
||||
G_IO_ERROR,
|
||||
G_IO_ERROR_NOT_FOUND,
|
||||
"No matching Port found");
|
||||
} else if (!created_port)
|
||||
g_object_ref (best);
|
||||
|
||||
return PINOS_PORT (best);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -61,16 +61,15 @@ server_node_set_state (PinosNode *node,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
server_node_create_port (PinosNode *node,
|
||||
PinosDirection direction,
|
||||
const gchar *name,
|
||||
GBytes *possible_formats,
|
||||
PinosProperties *props,
|
||||
GTask *task)
|
||||
static PinosServerPort *
|
||||
server_node_create_port_sync (PinosServerNode *node,
|
||||
PinosDirection direction,
|
||||
const gchar *name,
|
||||
GBytes *possible_formats,
|
||||
PinosProperties *props)
|
||||
{
|
||||
PinosServerNodePrivate *priv = PINOS_SERVER_NODE (node)->priv;
|
||||
PinosPort *port;
|
||||
PinosServerNodePrivate *priv = node->priv;
|
||||
PinosServerPort *port;
|
||||
|
||||
port = g_object_new (PINOS_TYPE_SERVER_PORT,
|
||||
"daemon", priv->daemon,
|
||||
|
|
@ -80,6 +79,26 @@ server_node_create_port (PinosNode *node,
|
|||
"possible-formats", possible_formats,
|
||||
"properties", props,
|
||||
NULL);
|
||||
pinos_node_add_port (PINOS_NODE (node), PINOS_PORT (port));
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
static void
|
||||
server_node_create_port (PinosNode *node,
|
||||
PinosDirection direction,
|
||||
const gchar *name,
|
||||
GBytes *possible_formats,
|
||||
PinosProperties *props,
|
||||
GTask *task)
|
||||
{
|
||||
PinosServerPort *port;
|
||||
|
||||
port = pinos_server_node_create_port_sync (PINOS_SERVER_NODE (node),
|
||||
direction,
|
||||
name,
|
||||
possible_formats,
|
||||
props);
|
||||
|
||||
g_task_return_pointer (task, port, (GDestroyNotify) g_object_unref);
|
||||
g_object_unref (task);
|
||||
|
|
@ -91,6 +110,18 @@ server_node_remove_port (PinosNode *node,
|
|||
{
|
||||
}
|
||||
|
||||
static void
|
||||
remove_port (PinosPort *port)
|
||||
{
|
||||
guint n_links;
|
||||
|
||||
pinos_port_get_links (port, &n_links);
|
||||
if (n_links == 0) {
|
||||
pinos_port_remove (port);
|
||||
}
|
||||
g_object_unref (port);
|
||||
}
|
||||
|
||||
static void
|
||||
on_port_created (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
|
|
@ -138,9 +169,11 @@ on_port_created (GObject *source_object,
|
|||
direction = pinos_port_get_direction (port);
|
||||
direction = pinos_direction_reverse (direction);
|
||||
|
||||
val = pinos_properties_get (props, "target-path");
|
||||
|
||||
peer = pinos_daemon_find_port (priv->daemon,
|
||||
direction,
|
||||
NULL,
|
||||
val,
|
||||
pinos_port_get_properties (port),
|
||||
pinos_port_get_possible_formats (port),
|
||||
&error);
|
||||
|
|
@ -149,6 +182,11 @@ on_port_created (GObject *source_object,
|
|||
|
||||
if (!pinos_port_link (port, peer))
|
||||
goto link_failed;
|
||||
|
||||
g_object_set_data_full (G_OBJECT (port),
|
||||
"autoconnect-peer-port",
|
||||
peer,
|
||||
(GDestroyNotify) remove_port);
|
||||
}
|
||||
|
||||
object_path = pinos_server_port_get_object_path (PINOS_SERVER_PORT (port));
|
||||
|
|
@ -198,6 +236,7 @@ link_failed:
|
|||
g_debug ("server-node %p: could not link port", node);
|
||||
g_dbus_method_invocation_return_dbus_error (invocation,
|
||||
"org.pinos.Error", "can't link port");
|
||||
g_object_unref (peer);
|
||||
g_object_unref (fdlist);
|
||||
return;
|
||||
}
|
||||
|
|
@ -458,6 +497,8 @@ pinos_server_node_class_init (PinosServerNodeClass * klass)
|
|||
node_class->set_state = server_node_set_state;
|
||||
node_class->create_port = server_node_create_port;
|
||||
node_class->remove_port = server_node_remove_port;
|
||||
|
||||
klass->create_port_sync = server_node_create_port_sync;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -558,3 +599,29 @@ pinos_server_node_get_object_path (PinosServerNode *node)
|
|||
|
||||
return priv->object_path;
|
||||
}
|
||||
|
||||
PinosServerPort *
|
||||
pinos_server_node_create_port_sync (PinosServerNode *node,
|
||||
PinosDirection direction,
|
||||
const gchar *name,
|
||||
GBytes *possible_formats,
|
||||
PinosProperties *props)
|
||||
{
|
||||
PinosServerNodeClass *klass;
|
||||
PinosServerPort *port;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_SERVER_NODE (node), NULL);
|
||||
|
||||
klass = PINOS_SERVER_NODE_GET_CLASS (node);
|
||||
if (!klass->create_port_sync)
|
||||
return NULL;
|
||||
|
||||
g_debug ("server-node %p: create port", node);
|
||||
port = klass->create_port_sync (node,
|
||||
direction,
|
||||
name,
|
||||
possible_formats,
|
||||
props);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -60,6 +60,12 @@ struct _PinosServerNode {
|
|||
*/
|
||||
struct _PinosServerNodeClass {
|
||||
PinosNodeClass parent_class;
|
||||
|
||||
PinosServerPort * (*create_port_sync) (PinosServerNode *node,
|
||||
PinosDirection direction,
|
||||
const gchar *name,
|
||||
GBytes *possible_formats,
|
||||
PinosProperties *props);
|
||||
};
|
||||
|
||||
/* normal GObject stuff */
|
||||
|
|
@ -74,6 +80,12 @@ PinosDaemon * pinos_server_node_get_daemon (PinosServerNode *
|
|||
const gchar * pinos_server_node_get_sender (PinosServerNode *node);
|
||||
const gchar * pinos_server_node_get_object_path (PinosServerNode *node);
|
||||
|
||||
PinosServerPort * pinos_server_node_create_port_sync (PinosServerNode *node,
|
||||
PinosDirection direction,
|
||||
const gchar *name,
|
||||
GBytes *possible_formats,
|
||||
PinosProperties *props);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __PINOS_SERVER_NODE_H__ */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue