mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-20 08:56:56 -05:00
Introduce the concept of a Port
A port is an input or output on a Node. Channels are created from the ports and inherit the direction of the port. do automatic port selection based on the direction and caps and node/port name. Simplify stream_connect by passing the direction. Fix pinossink to connect in setcaps so that we know the format and can select a good sink to connect to.
This commit is contained in:
parent
b885d40390
commit
ba4ef9b5d9
35 changed files with 1939 additions and 2120 deletions
|
|
@ -23,7 +23,6 @@
|
|||
#include "pinos/client/enumtypes.h"
|
||||
|
||||
#include "pinos/server/node.h"
|
||||
#include "pinos/server/source.h"
|
||||
#include "pinos/server/daemon.h"
|
||||
|
||||
#include "pinos/dbus/org-pinos.h"
|
||||
|
|
@ -35,10 +34,18 @@
|
|||
struct _PinosNodePrivate
|
||||
{
|
||||
PinosDaemon *daemon;
|
||||
PinosObjectSkeleton *skeleton;
|
||||
PinosNode1 *iface;
|
||||
|
||||
gchar *object_path;
|
||||
PinosSource *source;
|
||||
PinosSink *sink;
|
||||
gchar *name;
|
||||
|
||||
PinosNodeState state;
|
||||
GError *error;
|
||||
guint idle_timeout;
|
||||
|
||||
PinosProperties *properties;
|
||||
|
||||
GList *ports;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (PinosNode, pinos_node, G_TYPE_OBJECT);
|
||||
|
|
@ -47,8 +54,10 @@ enum
|
|||
{
|
||||
PROP_0,
|
||||
PROP_DAEMON,
|
||||
PROP_SKELETON,
|
||||
PROP_OBJECT_PATH,
|
||||
PROP_NAME,
|
||||
PROP_STATE,
|
||||
PROP_PROPERTIES,
|
||||
};
|
||||
|
||||
static void
|
||||
|
|
@ -65,14 +74,22 @@ pinos_node_get_property (GObject *_object,
|
|||
g_value_set_object (value, priv->daemon);
|
||||
break;
|
||||
|
||||
case PROP_SKELETON:
|
||||
g_value_set_object (value, priv->skeleton);
|
||||
break;
|
||||
|
||||
case PROP_OBJECT_PATH:
|
||||
g_value_set_string (value, priv->object_path);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, priv->name);
|
||||
break;
|
||||
|
||||
case PROP_STATE:
|
||||
g_value_set_enum (value, priv->state);
|
||||
break;
|
||||
|
||||
case PROP_PROPERTIES:
|
||||
g_value_set_boxed (value, priv->properties);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -93,6 +110,19 @@ pinos_node_set_property (GObject *_object,
|
|||
priv->daemon = g_value_dup_object (value);
|
||||
break;
|
||||
|
||||
case PROP_NAME:
|
||||
priv->name = g_value_dup_string (value);
|
||||
break;
|
||||
|
||||
case PROP_PROPERTIES:
|
||||
if (priv->properties)
|
||||
pinos_properties_free (priv->properties);
|
||||
priv->properties = g_value_dup_boxed (value);
|
||||
if (priv->iface)
|
||||
pinos_node1_set_properties (priv->iface,
|
||||
priv->properties ? pinos_properties_to_variant (priv->properties) : NULL);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (node, prop_id, pspec);
|
||||
break;
|
||||
|
|
@ -104,11 +134,20 @@ node_register_object (PinosNode *node)
|
|||
{
|
||||
PinosNodePrivate *priv = node->priv;
|
||||
PinosDaemon *daemon = priv->daemon;
|
||||
PinosObjectSkeleton *skel;
|
||||
|
||||
priv->skeleton = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_NODE);
|
||||
skel = pinos_object_skeleton_new (PINOS_DBUS_OBJECT_NODE);
|
||||
|
||||
priv->iface = pinos_node1_skeleton_new ();
|
||||
pinos_node1_set_name (priv->iface, priv->name);
|
||||
if (priv->properties)
|
||||
pinos_node1_set_properties (priv->iface, pinos_properties_to_variant (priv->properties));
|
||||
pinos_node1_set_state (priv->iface, priv->state);
|
||||
pinos_object_skeleton_set_node1 (skel, priv->iface);
|
||||
|
||||
g_free (priv->object_path);
|
||||
priv->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (priv->skeleton));
|
||||
priv->object_path = pinos_daemon_export_uniquely (daemon, G_DBUS_OBJECT_SKELETON (skel));
|
||||
g_object_unref (skel);
|
||||
|
||||
pinos_daemon_add_node (daemon, node);
|
||||
|
||||
|
|
@ -122,7 +161,7 @@ node_unregister_object (PinosNode *node)
|
|||
|
||||
pinos_daemon_unexport (priv->daemon, priv->object_path);
|
||||
pinos_daemon_remove_node (priv->daemon, node);
|
||||
g_clear_object (&priv->skeleton);
|
||||
g_clear_object (&priv->iface);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -187,6 +226,37 @@ pinos_node_class_init (PinosNodeClass * klass)
|
|||
NULL,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NAME,
|
||||
g_param_spec_string ("name",
|
||||
"Name",
|
||||
"The node name",
|
||||
NULL,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_STATE,
|
||||
g_param_spec_enum ("state",
|
||||
"State",
|
||||
"The state of the node",
|
||||
PINOS_TYPE_NODE_STATE,
|
||||
PINOS_NODE_STATE_SUSPENDED,
|
||||
G_PARAM_READABLE |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PROPERTIES,
|
||||
g_param_spec_boxed ("properties",
|
||||
"Properties",
|
||||
"The properties of the node",
|
||||
PINOS_TYPE_PROPERTIES,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT |
|
||||
G_PARAM_STATIC_STRINGS));
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
@ -234,96 +304,210 @@ pinos_node_get_object_path (PinosNode *node)
|
|||
}
|
||||
|
||||
/**
|
||||
* pinos_node_set_source:
|
||||
* pinos_node_add_port:
|
||||
* @node: a #PinosNode
|
||||
* @source: a #PinosSource
|
||||
* @port: a #PinosPort
|
||||
*
|
||||
* Set the #PinosSource of @node
|
||||
* Add the #PinosPort to @node
|
||||
*/
|
||||
void
|
||||
pinos_node_set_source (PinosNode *node, PinosSource *source, GObject *iface)
|
||||
pinos_node_add_port (PinosNode *node, PinosPort *port)
|
||||
{
|
||||
PinosNodePrivate *priv;
|
||||
|
||||
g_return_if_fail (PINOS_IS_NODE (node));
|
||||
g_return_if_fail (source == NULL || PINOS_IS_SOURCE (source));
|
||||
g_return_if_fail (iface == NULL || PINOS_IS_SOURCE1 (iface));
|
||||
g_return_if_fail (PINOS_IS_PORT (port));
|
||||
priv = node->priv;
|
||||
|
||||
if (source) {
|
||||
pinos_object_skeleton_set_source1 (priv->skeleton, PINOS_SOURCE1 (iface));
|
||||
priv->source = source;
|
||||
} else {
|
||||
pinos_object_skeleton_set_source1 (priv->skeleton, NULL);
|
||||
priv->source = NULL;
|
||||
}
|
||||
priv->ports = g_list_append (priv->ports, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_get_source:
|
||||
* pinos_node_remove_port:
|
||||
* @node: a #PinosNode
|
||||
* @port: a #PinosPort
|
||||
*
|
||||
* Remove the #PinosPort from @node
|
||||
*/
|
||||
void
|
||||
pinos_node_remove_port (PinosNode *node, PinosPort *port)
|
||||
{
|
||||
PinosNodePrivate *priv;
|
||||
|
||||
g_return_if_fail (PINOS_IS_NODE (node));
|
||||
g_return_if_fail (PINOS_IS_PORT (port));
|
||||
priv = node->priv;
|
||||
|
||||
priv->ports = g_list_remove (priv->ports, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_get_ports:
|
||||
* @node: a #PinosNode
|
||||
*
|
||||
* Get the #PinosSource of @node
|
||||
* Get the list of ports in @node.
|
||||
*
|
||||
* Returns: the #PinosSource of @node or %NULL
|
||||
* Returns: a #GList of nodes owned by @node.
|
||||
*/
|
||||
PinosSource *
|
||||
pinos_node_get_source (PinosNode *node)
|
||||
GList *
|
||||
pinos_node_get_ports (PinosNode *node)
|
||||
{
|
||||
PinosNodePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_NODE (node), NULL);
|
||||
priv = node->priv;
|
||||
|
||||
return priv->source;
|
||||
return priv->ports;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* pinos_node_set_sink:
|
||||
* @node: a #PinosNode
|
||||
* @sink: a #PinosSink
|
||||
*
|
||||
* Set the #PinosSink of @node
|
||||
*/
|
||||
void
|
||||
pinos_node_set_sink (PinosNode *node, PinosSink *sink, GObject *iface)
|
||||
static void
|
||||
remove_idle_timeout (PinosNode *node)
|
||||
{
|
||||
PinosNodePrivate *priv;
|
||||
PinosNodePrivate *priv = node->priv;
|
||||
|
||||
g_return_if_fail (PINOS_IS_NODE (node));
|
||||
g_return_if_fail (sink == NULL || PINOS_IS_SINK (sink));
|
||||
g_return_if_fail (iface == NULL || PINOS_IS_SINK1 (iface));
|
||||
priv = node->priv;
|
||||
|
||||
if (sink) {
|
||||
pinos_object_skeleton_set_sink1 (priv->skeleton, PINOS_SINK1 (iface));
|
||||
priv->sink = sink;
|
||||
} else {
|
||||
pinos_object_skeleton_set_sink1 (priv->skeleton, NULL);
|
||||
priv->sink = NULL;
|
||||
if (priv->idle_timeout) {
|
||||
g_source_remove (priv->idle_timeout);
|
||||
priv->idle_timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_get_sink:
|
||||
* pinos_node_set_state:
|
||||
* @node: a #PinosNode
|
||||
* @state: a #PinosNodeState
|
||||
*
|
||||
* Get the #PinosSink of @node
|
||||
* Set the state of @node to @state.
|
||||
*
|
||||
* Returns: the #PinosSink of @node or %NULL
|
||||
* Returns: %TRUE on success.
|
||||
*/
|
||||
PinosSink *
|
||||
pinos_node_get_sink (PinosNode *node)
|
||||
gboolean
|
||||
pinos_node_set_state (PinosNode *node,
|
||||
PinosNodeState state)
|
||||
{
|
||||
PinosNodeClass *klass;
|
||||
gboolean res;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_NODE (node), FALSE);
|
||||
|
||||
klass = PINOS_NODE_GET_CLASS (node);
|
||||
|
||||
remove_idle_timeout (node);
|
||||
|
||||
if (klass->set_state)
|
||||
res = klass->set_state (node, state);
|
||||
else
|
||||
res = FALSE;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_update_state:
|
||||
* @node: a #PinosNode
|
||||
* @state: a #PinosNodeState
|
||||
*
|
||||
* Update the state of a node. This method is used from
|
||||
* inside @node itself.
|
||||
*/
|
||||
void
|
||||
pinos_node_update_state (PinosNode *node,
|
||||
PinosNodeState state)
|
||||
{
|
||||
PinosNodePrivate *priv;
|
||||
|
||||
g_return_val_if_fail (PINOS_IS_NODE (node), NULL);
|
||||
g_return_if_fail (PINOS_IS_NODE (node));
|
||||
priv = node->priv;
|
||||
|
||||
return priv->sink;
|
||||
if (priv->state != state) {
|
||||
priv->state = state;
|
||||
pinos_node1_set_state (priv->iface, state);
|
||||
g_object_notify (G_OBJECT (node), "state");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_report_error:
|
||||
* @node: a #PinosNode
|
||||
* @error: a #GError
|
||||
*
|
||||
* Report an error from within @node.
|
||||
*/
|
||||
void
|
||||
pinos_node_report_error (PinosNode *node,
|
||||
GError *error)
|
||||
{
|
||||
PinosNodePrivate *priv;
|
||||
|
||||
g_return_if_fail (PINOS_IS_NODE (node));
|
||||
priv = node->priv;
|
||||
|
||||
g_clear_error (&priv->error);
|
||||
remove_idle_timeout (node);
|
||||
priv->error = error;
|
||||
priv->state = PINOS_NODE_STATE_ERROR;
|
||||
g_debug ("got error state %s", error->message);
|
||||
pinos_node1_set_state (priv->iface, priv->state);
|
||||
g_object_notify (G_OBJECT (node), "state");
|
||||
}
|
||||
|
||||
static gboolean
|
||||
idle_timeout (PinosNode *node)
|
||||
{
|
||||
PinosNodePrivate *priv = node->priv;
|
||||
|
||||
priv->idle_timeout = 0;
|
||||
pinos_node_set_state (node, PINOS_NODE_STATE_SUSPENDED);
|
||||
|
||||
return G_SOURCE_REMOVE;
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_report_idle:
|
||||
* @node: a #PinosNode
|
||||
*
|
||||
* Mark @node as being idle. This will start a timeout that will
|
||||
* set the node to SUSPENDED.
|
||||
*/
|
||||
void
|
||||
pinos_node_report_idle (PinosNode *node)
|
||||
{
|
||||
PinosNodePrivate *priv;
|
||||
|
||||
g_return_if_fail (PINOS_IS_NODE (node));
|
||||
priv = node->priv;
|
||||
|
||||
pinos_node_set_state (node, PINOS_NODE_STATE_IDLE);
|
||||
|
||||
priv->idle_timeout = g_timeout_add_seconds (3,
|
||||
(GSourceFunc) idle_timeout,
|
||||
node);
|
||||
}
|
||||
|
||||
/**
|
||||
* pinos_node_report_busy:
|
||||
* @node: a #PinosNode
|
||||
*
|
||||
* Mark @node as being busy. This will set the state of the node
|
||||
* to the RUNNING state.
|
||||
*/
|
||||
void
|
||||
pinos_node_report_busy (PinosNode *node)
|
||||
{
|
||||
g_return_if_fail (PINOS_IS_NODE (node));
|
||||
|
||||
pinos_node_set_state (node, PINOS_NODE_STATE_RUNNING);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* pinos_node_new:
|
||||
* @daemon: a #PinosDaemon
|
||||
*
|
||||
* Make a new node
|
||||
*
|
||||
* Returns: a new #PinosNode
|
||||
*/
|
||||
PinosNode *
|
||||
pinos_node_new (PinosDaemon *daemon)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue