mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	node: add port_id
Decouple the SPA port ids from the pinos port ids, this allows us to more easily link and relink things and do dynamic connection later. Implement multiple output ports on a pinos node.
This commit is contained in:
		
							parent
							
								
									36bcdaa4bc
								
							
						
					
					
						commit
						e34ef88dac
					
				
					 5 changed files with 213 additions and 89 deletions
				
			
		| 
						 | 
					@ -214,12 +214,16 @@ on_port_added (PinosNode *node, PinosDirection direction, guint port_id, PinosCl
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    new_port = pinos_node_get_free_port_id (target, pinos_direction_reverse (direction));
 | 
					    new_port = pinos_node_get_free_port (target, pinos_direction_reverse (direction));
 | 
				
			||||||
    if (new_port == SPA_ID_INVALID) {
 | 
					    if (new_port == SPA_ID_INVALID) {
 | 
				
			||||||
      g_debug ("daemon %p: can't create free port", this);
 | 
					      g_debug ("daemon %p: can't create free port", this);
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (direction == PINOS_DIRECTION_OUTPUT)
 | 
				
			||||||
      link = pinos_node_link (node, port_id, target, new_port, NULL, NULL);
 | 
					      link = pinos_node_link (node, port_id, target, new_port, NULL, NULL);
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					      link = pinos_node_link (target, new_port, node, port_id, NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pinos_client_add_object (client, G_OBJECT (link));
 | 
					    pinos_client_add_object (client, G_OBJECT (link));
 | 
				
			||||||
    g_object_unref (link);
 | 
					    g_object_unref (link);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,8 +57,10 @@ enum
 | 
				
			||||||
  PROP_DAEMON,
 | 
					  PROP_DAEMON,
 | 
				
			||||||
  PROP_OBJECT_PATH,
 | 
					  PROP_OBJECT_PATH,
 | 
				
			||||||
  PROP_OUTPUT_NODE,
 | 
					  PROP_OUTPUT_NODE,
 | 
				
			||||||
 | 
					  PROP_OUTPUT_ID,
 | 
				
			||||||
  PROP_OUTPUT_PORT,
 | 
					  PROP_OUTPUT_PORT,
 | 
				
			||||||
  PROP_INPUT_NODE,
 | 
					  PROP_INPUT_NODE,
 | 
				
			||||||
 | 
					  PROP_INPUT_ID,
 | 
				
			||||||
  PROP_INPUT_PORT,
 | 
					  PROP_INPUT_PORT,
 | 
				
			||||||
  PROP_FORMAT_FILTER,
 | 
					  PROP_FORMAT_FILTER,
 | 
				
			||||||
  PROP_PROPERTIES,
 | 
					  PROP_PROPERTIES,
 | 
				
			||||||
| 
						 | 
					@ -94,6 +96,10 @@ pinos_link_get_property (GObject    *_object,
 | 
				
			||||||
      g_value_set_object (value, this->output_node);
 | 
					      g_value_set_object (value, this->output_node);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PROP_OUTPUT_ID:
 | 
				
			||||||
 | 
					      g_value_set_uint (value, this->output_id);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PROP_OUTPUT_PORT:
 | 
					    case PROP_OUTPUT_PORT:
 | 
				
			||||||
      g_value_set_uint (value, this->output_port);
 | 
					      g_value_set_uint (value, this->output_port);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
| 
						 | 
					@ -102,6 +108,10 @@ pinos_link_get_property (GObject    *_object,
 | 
				
			||||||
      g_value_set_object (value, this->input_node);
 | 
					      g_value_set_object (value, this->input_node);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PROP_INPUT_ID:
 | 
				
			||||||
 | 
					      g_value_set_uint (value, this->input_id);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PROP_INPUT_PORT:
 | 
					    case PROP_INPUT_PORT:
 | 
				
			||||||
      g_value_set_uint (value, this->input_port);
 | 
					      g_value_set_uint (value, this->input_port);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
| 
						 | 
					@ -142,6 +152,10 @@ pinos_link_set_property (GObject      *_object,
 | 
				
			||||||
      this->output_node = g_value_dup_object (value);
 | 
					      this->output_node = g_value_dup_object (value);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PROP_OUTPUT_ID:
 | 
				
			||||||
 | 
					      this->output_id = g_value_get_uint (value);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PROP_OUTPUT_PORT:
 | 
					    case PROP_OUTPUT_PORT:
 | 
				
			||||||
      this->output_port = g_value_get_uint (value);
 | 
					      this->output_port = g_value_get_uint (value);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
| 
						 | 
					@ -150,6 +164,10 @@ pinos_link_set_property (GObject      *_object,
 | 
				
			||||||
      this->input_node = g_value_dup_object (value);
 | 
					      this->input_node = g_value_dup_object (value);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    case PROP_INPUT_ID:
 | 
				
			||||||
 | 
					      this->input_id = g_value_get_uint (value);
 | 
				
			||||||
 | 
					      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case PROP_INPUT_PORT:
 | 
					    case PROP_INPUT_PORT:
 | 
				
			||||||
      this->input_port = g_value_get_uint (value);
 | 
					      this->input_port = g_value_get_uint (value);
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
| 
						 | 
					@ -279,7 +297,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
 | 
				
			||||||
  const SpaPortInfo *iinfo, *oinfo;
 | 
					  const SpaPortInfo *iinfo, *oinfo;
 | 
				
			||||||
  SpaPortInfoFlags in_flags, out_flags;
 | 
					  SpaPortInfoFlags in_flags, out_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (in_state != SPA_NODE_STATE_READY || out_state != SPA_NODE_STATE_READY)
 | 
					  if (in_state < SPA_NODE_STATE_READY || out_state < SPA_NODE_STATE_READY)
 | 
				
			||||||
    return SPA_RESULT_OK;
 | 
					    return SPA_RESULT_OK;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_debug ("link %p: doing alloc buffers %p %p", this, this->output_node, this->input_node);
 | 
					  g_debug ("link %p: doing alloc buffers %p %p", this, this->output_node, this->input_node);
 | 
				
			||||||
| 
						 | 
					@ -296,9 +314,6 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
 | 
				
			||||||
  spa_debug_port_info (oinfo);
 | 
					  spa_debug_port_info (oinfo);
 | 
				
			||||||
  spa_debug_port_info (iinfo);
 | 
					  spa_debug_port_info (iinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  priv->n_in_buffers = 16;
 | 
					 | 
				
			||||||
  priv->n_out_buffers = 16;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if ((oinfo->flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) &&
 | 
					  if ((oinfo->flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) &&
 | 
				
			||||||
      (iinfo->flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS)) {
 | 
					      (iinfo->flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS)) {
 | 
				
			||||||
    out_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
 | 
					    out_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
 | 
				
			||||||
| 
						 | 
					@ -309,6 +324,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
 | 
				
			||||||
    in_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
 | 
					    in_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
 | 
				
			||||||
  } else if ((oinfo->flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS) &&
 | 
					  } else if ((oinfo->flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS) &&
 | 
				
			||||||
      (iinfo->flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS)) {
 | 
					      (iinfo->flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS)) {
 | 
				
			||||||
 | 
					    priv->n_in_buffers = 16;
 | 
				
			||||||
    out_flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
 | 
					    out_flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
 | 
				
			||||||
    in_flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
 | 
					    in_flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -330,7 +346,13 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
 | 
				
			||||||
    goto error;
 | 
					    goto error;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (in_state > SPA_NODE_STATE_READY)
 | 
				
			||||||
 | 
					    in_flags &= ~SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
 | 
				
			||||||
 | 
					  if (out_state > SPA_NODE_STATE_READY)
 | 
				
			||||||
 | 
					    out_flags &= ~SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) {
 | 
					  if (in_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) {
 | 
				
			||||||
 | 
					    priv->n_in_buffers = 16;
 | 
				
			||||||
    if ((res = spa_node_port_alloc_buffers (this->input_node->node, this->input_port,
 | 
					    if ((res = spa_node_port_alloc_buffers (this->input_node->node, this->input_port,
 | 
				
			||||||
                                            oinfo->params, oinfo->n_params,
 | 
					                                            oinfo->params, oinfo->n_params,
 | 
				
			||||||
                                            priv->in_buffers, &priv->n_in_buffers)) < 0) {
 | 
					                                            priv->in_buffers, &priv->n_in_buffers)) < 0) {
 | 
				
			||||||
| 
						 | 
					@ -339,6 +361,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) {
 | 
					  if (out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) {
 | 
				
			||||||
 | 
					    priv->n_out_buffers = 16;
 | 
				
			||||||
    if ((res = spa_node_port_alloc_buffers (this->output_node->node, this->output_port,
 | 
					    if ((res = spa_node_port_alloc_buffers (this->output_node->node, this->output_port,
 | 
				
			||||||
                                            iinfo->params, iinfo->n_params,
 | 
					                                            iinfo->params, iinfo->n_params,
 | 
				
			||||||
                                            priv->out_buffers, &priv->n_out_buffers)) < 0) {
 | 
					                                            priv->out_buffers, &priv->n_out_buffers)) < 0) {
 | 
				
			||||||
| 
						 | 
					@ -460,8 +483,9 @@ pinos_link_constructed (GObject * object)
 | 
				
			||||||
  G_OBJECT_CLASS (pinos_link_parent_class)->constructed (object);
 | 
					  G_OBJECT_CLASS (pinos_link_parent_class)->constructed (object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  on_property_notify (G_OBJECT (this), NULL, this);
 | 
					  on_property_notify (G_OBJECT (this), NULL, this);
 | 
				
			||||||
  g_debug ("link %p: constructed %p:%d -> %p:%d", this, this->output_node, this->output_port,
 | 
					  g_debug ("link %p: constructed %p:%d:%d -> %p:%d:%d", this,
 | 
				
			||||||
                                                  this->input_node, this->input_port);
 | 
					                                                  this->output_node, this->output_id, this->output_port,
 | 
				
			||||||
 | 
					                                                  this->input_node, this->input_id, this->input_port);
 | 
				
			||||||
  link_register_object (this);
 | 
					  link_register_object (this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  check_states (this);
 | 
					  check_states (this);
 | 
				
			||||||
| 
						 | 
					@ -535,6 +559,18 @@ pinos_link_class_init (PinosLinkClass * klass)
 | 
				
			||||||
                                                        G_PARAM_CONSTRUCT |
 | 
					                                                        G_PARAM_CONSTRUCT |
 | 
				
			||||||
                                                        G_PARAM_STATIC_STRINGS));
 | 
					                                                        G_PARAM_STATIC_STRINGS));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_object_class_install_property (gobject_class,
 | 
				
			||||||
 | 
					                                   PROP_OUTPUT_ID,
 | 
				
			||||||
 | 
					                                   g_param_spec_uint ("output-id",
 | 
				
			||||||
 | 
					                                                      "Output Id",
 | 
				
			||||||
 | 
					                                                      "The output id",
 | 
				
			||||||
 | 
					                                                      0,
 | 
				
			||||||
 | 
					                                                      G_MAXUINT,
 | 
				
			||||||
 | 
					                                                      -1,
 | 
				
			||||||
 | 
					                                                      G_PARAM_READWRITE |
 | 
				
			||||||
 | 
					                                                      G_PARAM_CONSTRUCT |
 | 
				
			||||||
 | 
					                                                      G_PARAM_STATIC_STRINGS));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_object_class_install_property (gobject_class,
 | 
					  g_object_class_install_property (gobject_class,
 | 
				
			||||||
                                   PROP_OUTPUT_PORT,
 | 
					                                   PROP_OUTPUT_PORT,
 | 
				
			||||||
                                   g_param_spec_uint ("output-port",
 | 
					                                   g_param_spec_uint ("output-port",
 | 
				
			||||||
| 
						 | 
					@ -557,6 +593,18 @@ pinos_link_class_init (PinosLinkClass * klass)
 | 
				
			||||||
                                                        G_PARAM_CONSTRUCT |
 | 
					                                                        G_PARAM_CONSTRUCT |
 | 
				
			||||||
                                                        G_PARAM_STATIC_STRINGS));
 | 
					                                                        G_PARAM_STATIC_STRINGS));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_object_class_install_property (gobject_class,
 | 
				
			||||||
 | 
					                                   PROP_INPUT_ID,
 | 
				
			||||||
 | 
					                                   g_param_spec_uint ("input-id",
 | 
				
			||||||
 | 
					                                                      "Input Id",
 | 
				
			||||||
 | 
					                                                      "The input id",
 | 
				
			||||||
 | 
					                                                      0,
 | 
				
			||||||
 | 
					                                                      G_MAXUINT,
 | 
				
			||||||
 | 
					                                                      -1,
 | 
				
			||||||
 | 
					                                                      G_PARAM_READWRITE |
 | 
				
			||||||
 | 
					                                                      G_PARAM_CONSTRUCT |
 | 
				
			||||||
 | 
					                                                      G_PARAM_STATIC_STRINGS));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_object_class_install_property (gobject_class,
 | 
					  g_object_class_install_property (gobject_class,
 | 
				
			||||||
                                   PROP_INPUT_PORT,
 | 
					                                   PROP_INPUT_PORT,
 | 
				
			||||||
                                   g_param_spec_uint ("input-port",
 | 
					                                   g_param_spec_uint ("input-port",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,9 +48,11 @@ struct _PinosLink {
 | 
				
			||||||
  GObject object;
 | 
					  GObject object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PinosNode *output_node;
 | 
					  PinosNode *output_node;
 | 
				
			||||||
  guint      output_port;
 | 
					  guint      output_id;
 | 
				
			||||||
 | 
					  uint32_t   output_port;
 | 
				
			||||||
  PinosNode *input_node;
 | 
					  PinosNode *input_node;
 | 
				
			||||||
  guint      input_port;
 | 
					  guint      input_id;
 | 
				
			||||||
 | 
					  uint32_t   input_port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PinosLinkPrivate *priv;
 | 
					  PinosLinkPrivate *priv;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,10 @@
 | 
				
			||||||
#define PINOS_NODE_GET_PRIVATE(node)  \
 | 
					#define PINOS_NODE_GET_PRIVATE(node)  \
 | 
				
			||||||
   (G_TYPE_INSTANCE_GET_PRIVATE ((node), PINOS_TYPE_NODE, PinosNodePrivate))
 | 
					   (G_TYPE_INSTANCE_GET_PRIVATE ((node), PINOS_TYPE_NODE, PinosNodePrivate))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct {
 | 
				
			||||||
 | 
					  PinosLink *link;
 | 
				
			||||||
 | 
					} NodeLink;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct _PinosNodePrivate
 | 
					struct _PinosNodePrivate
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosDaemon *daemon;
 | 
					  PinosDaemon *daemon;
 | 
				
			||||||
| 
						 | 
					@ -69,7 +73,10 @@ struct _PinosNodePrivate
 | 
				
			||||||
  gboolean running;
 | 
					  gboolean running;
 | 
				
			||||||
  pthread_t thread;
 | 
					  pthread_t thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  GHashTable *links;
 | 
					  GArray *output_links;
 | 
				
			||||||
 | 
					  guint   n_used_output_links;
 | 
				
			||||||
 | 
					  GArray *input_links;
 | 
				
			||||||
 | 
					  guint   n_used_input_links;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaClock *clock;
 | 
					  SpaClock *clock;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -469,38 +476,47 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case SPA_NODE_EVENT_TYPE_HAVE_OUTPUT:
 | 
					    case SPA_NODE_EVENT_TYPE_HAVE_OUTPUT:
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      PinosLink *link;
 | 
					 | 
				
			||||||
      SpaPortOutputInfo oinfo[1] = { 0, };
 | 
					      SpaPortOutputInfo oinfo[1] = { 0, };
 | 
				
			||||||
      SpaResult res;
 | 
					      SpaResult res;
 | 
				
			||||||
 | 
					      guint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      if ((res = spa_node_port_pull_output (node, 1, oinfo)) < 0) {
 | 
					      if ((res = spa_node_port_pull_output (node, 1, oinfo)) < 0) {
 | 
				
			||||||
        g_warning ("node %p: got pull error %d, %d", this, res, oinfo[0].status);
 | 
					        g_warning ("node %p: got pull error %d, %d", this, res, oinfo[0].status);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      link = g_hash_table_lookup (priv->links, GUINT_TO_POINTER (oinfo[0].port_id));
 | 
					      for (i = 0; i < priv->output_links->len; i++) {
 | 
				
			||||||
      if (link) {
 | 
					        NodeLink *link = &g_array_index (priv->output_links, NodeLink, i);
 | 
				
			||||||
 | 
					        PinosLink *pl = link->link;
 | 
				
			||||||
        SpaPortInputInfo iinfo[1];
 | 
					        SpaPortInputInfo iinfo[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        iinfo[0].port_id = link->input_port;
 | 
					        if (pl == NULL || pl->output_node->node != node || pl->output_port != oinfo[0].port_id)
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        iinfo[0].port_id = pl->input_port;
 | 
				
			||||||
        iinfo[0].buffer_id = oinfo[0].buffer_id;
 | 
					        iinfo[0].buffer_id = oinfo[0].buffer_id;
 | 
				
			||||||
        iinfo[0].flags = SPA_PORT_INPUT_FLAG_NONE;
 | 
					        iinfo[0].flags = SPA_PORT_INPUT_FLAG_NONE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if ((res = spa_node_port_push_input (link->input_node->node, 1, iinfo)) < 0)
 | 
					        if ((res = spa_node_port_push_input (pl->input_node->node, 1, iinfo)) < 0)
 | 
				
			||||||
          g_warning ("node %p: error pushing buffer: %d, %d", this, res, iinfo[0].status);
 | 
					          g_warning ("node %p: error pushing buffer: %d, %d", this, res, iinfo[0].status);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case SPA_NODE_EVENT_TYPE_REUSE_BUFFER:
 | 
					    case SPA_NODE_EVENT_TYPE_REUSE_BUFFER:
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      PinosLink *link;
 | 
					 | 
				
			||||||
      SpaResult res;
 | 
					      SpaResult res;
 | 
				
			||||||
      SpaNodeEventReuseBuffer *rb = event->data;
 | 
					      SpaNodeEventReuseBuffer *rb = event->data;
 | 
				
			||||||
 | 
					      guint i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      link = g_hash_table_lookup (priv->links, GUINT_TO_POINTER (rb->port_id));
 | 
					      for (i = 0; i < priv->input_links->len; i++) {
 | 
				
			||||||
      if (link) {
 | 
					        NodeLink *link = &g_array_index (priv->input_links, NodeLink, i);
 | 
				
			||||||
        if ((res = spa_node_port_reuse_buffer (link->output_node->node,
 | 
					        PinosLink *pl = link->link;
 | 
				
			||||||
                                               link->output_port,
 | 
					
 | 
				
			||||||
 | 
					        if (pl == NULL || pl->input_node->node != node || pl->input_port != rb->port_id)
 | 
				
			||||||
 | 
					          continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ((res = spa_node_port_reuse_buffer (pl->output_node->node,
 | 
				
			||||||
 | 
					                                               pl->output_port,
 | 
				
			||||||
                                               rb->buffer_id)) < 0)
 | 
					                                               rb->buffer_id)) < 0)
 | 
				
			||||||
          g_warning ("node %p: error reuse buffer: %d", node, res);
 | 
					          g_warning ("node %p: error reuse buffer: %d", node, res);
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
| 
						 | 
					@ -715,7 +731,8 @@ pinos_node_dispose (GObject * obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  node_unregister_object (node);
 | 
					  node_unregister_object (node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_hash_table_unref (priv->links);
 | 
					  g_array_free (priv->input_links, TRUE);
 | 
				
			||||||
 | 
					  g_array_free (priv->output_links, TRUE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  G_OBJECT_CLASS (pinos_node_parent_class)->dispose (obj);
 | 
					  G_OBJECT_CLASS (pinos_node_parent_class)->dispose (obj);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -881,7 +898,8 @@ pinos_node_init (PinosNode * node)
 | 
				
			||||||
  priv->state = PINOS_NODE_STATE_SUSPENDED;
 | 
					  priv->state = PINOS_NODE_STATE_SUSPENDED;
 | 
				
			||||||
  pinos_node1_set_state (priv->iface, PINOS_NODE_STATE_SUSPENDED);
 | 
					  pinos_node1_set_state (priv->iface, PINOS_NODE_STATE_SUSPENDED);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  priv->links = g_hash_table_new (g_direct_hash, g_direct_equal);
 | 
					  priv->input_links = g_array_new (FALSE, TRUE, sizeof (NodeLink));
 | 
				
			||||||
 | 
					  priv->output_links = g_array_new (FALSE, TRUE, sizeof (NodeLink));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -1042,64 +1060,103 @@ pinos_node_remove (PinosNode *node)
 | 
				
			||||||
  g_signal_emit (node, signals[SIGNAL_REMOVE], 0, NULL);
 | 
					  g_signal_emit (node, signals[SIGNAL_REMOVE], 0, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					static uint32_t
 | 
				
			||||||
 * pinos_node_get_free_port_id:
 | 
					get_free_node_port (PinosNode      *node,
 | 
				
			||||||
 * @node: a #PinosNode
 | 
					 | 
				
			||||||
 * @direction: a #PinosDirection
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Find a new unused port id in @node with @direction
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns: the new port id of %SPA_INVALID_ID on error
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
guint
 | 
					 | 
				
			||||||
pinos_node_get_free_port_id (PinosNode       *node,
 | 
					 | 
				
			||||||
                    PinosDirection  direction)
 | 
					                    PinosDirection  direction)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosNodePrivate *priv;
 | 
					  PinosNodePrivate *priv = node->priv;
 | 
				
			||||||
  guint i, free_port = 0, n_ports, max_ports;
 | 
					  guint i, free_port, n_ports, max_ports;
 | 
				
			||||||
  uint32_t *ports;
 | 
					  uint32_t *ports;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_return_val_if_fail (PINOS_IS_NODE (node), -1);
 | 
					 | 
				
			||||||
  priv = node->priv;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (direction == PINOS_DIRECTION_INPUT) {
 | 
					  if (direction == PINOS_DIRECTION_INPUT) {
 | 
				
			||||||
    max_ports = priv->max_input_ports;
 | 
					    max_ports = priv->max_input_ports;
 | 
				
			||||||
    n_ports = priv->n_input_ports;
 | 
					    n_ports = priv->n_input_ports;
 | 
				
			||||||
    ports = priv->input_port_ids;
 | 
					    ports = priv->input_port_ids;
 | 
				
			||||||
 | 
					    free_port = 0;
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
    max_ports = priv->max_output_ports;
 | 
					    max_ports = priv->max_output_ports;
 | 
				
			||||||
    n_ports = priv->n_output_ports;
 | 
					    n_ports = priv->n_output_ports;
 | 
				
			||||||
    ports = priv->output_port_ids;
 | 
					    ports = priv->output_port_ids;
 | 
				
			||||||
 | 
					    free_port = priv->max_input_ports;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					  if (max_ports == n_ports)
 | 
				
			||||||
 | 
					    return SPA_ID_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_debug ("node %p: direction %d max %u, n %u", node, direction, max_ports, n_ports);
 | 
					  g_debug ("node %p: direction %d max %u, n %u", node, direction, max_ports, n_ports);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  for (i = 0; i < n_ports; i++) {
 | 
					  for (i = 0; i < n_ports; i++) {
 | 
				
			||||||
    if (free_port < ports[i])
 | 
					    if (free_port < ports[i])
 | 
				
			||||||
      break;
 | 
					      break;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (g_hash_table_lookup (priv->links, GUINT_TO_POINTER (free_port)) == NULL && free_port < max_ports)
 | 
					 | 
				
			||||||
      return free_port;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    free_port = ports[i] + 1;
 | 
					    free_port = ports[i] + 1;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  if (free_port >= max_ports)
 | 
					  if (free_port >= max_ports)
 | 
				
			||||||
    return -1;
 | 
					    return SPA_ID_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return free_port;
 | 
					  return free_port;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * pinos_node_get_free_port:
 | 
				
			||||||
 | 
					 * @node: a #PinosNode
 | 
				
			||||||
 | 
					 * @direction: a #PinosDirection
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Find a new unused port id in @node with @direction
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: the new port id or %SPA_ID_INVALID on error
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					guint
 | 
				
			||||||
 | 
					pinos_node_get_free_port (PinosNode       *node,
 | 
				
			||||||
 | 
					                          PinosDirection   direction)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosNodePrivate *priv;
 | 
				
			||||||
 | 
					  guint i, n_ports;
 | 
				
			||||||
 | 
					  NodeLink *links;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  g_return_val_if_fail (PINOS_IS_NODE (node), SPA_ID_INVALID);
 | 
				
			||||||
 | 
					  priv = node->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (direction == PINOS_DIRECTION_INPUT) {
 | 
				
			||||||
 | 
					    n_ports = priv->input_links->len;
 | 
				
			||||||
 | 
					    links = (NodeLink *)priv->input_links->data;
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    n_ports = priv->output_links->len;
 | 
				
			||||||
 | 
					    links = (NodeLink *)priv->output_links->data;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (i = 0; i < n_ports; i++) {
 | 
				
			||||||
 | 
					    if (!links[i].link)
 | 
				
			||||||
 | 
					      return i;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return n_ports;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
do_remove_link (PinosLink *link, PinosNode *node)
 | 
					do_remove_link (PinosLink *link, PinosNode *node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  g_hash_table_remove (link->output_node->priv->links, GUINT_TO_POINTER (link->output_port));
 | 
					  guint i, n_links;
 | 
				
			||||||
  if (g_hash_table_size (link->output_node->priv->links) == 0)
 | 
					  GArray *links;
 | 
				
			||||||
    pinos_node_report_idle (link->output_node);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_hash_table_remove (link->input_node->priv->links, GUINT_TO_POINTER (link->input_port));
 | 
					  links = link->output_node->priv->output_links;
 | 
				
			||||||
  if (g_hash_table_size (link->input_node->priv->links) == 0)
 | 
					  n_links = links->len;
 | 
				
			||||||
 | 
					  for (i = 0; i < n_links; i++) {
 | 
				
			||||||
 | 
					    NodeLink *l = &g_array_index (links, NodeLink, i);
 | 
				
			||||||
 | 
					    if (l->link == link) {
 | 
				
			||||||
 | 
					      l->link = NULL;
 | 
				
			||||||
 | 
					      if (--link->output_node->priv->n_used_output_links == 0)
 | 
				
			||||||
 | 
					        pinos_node_report_idle (link->output_node);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  links = link->input_node->priv->input_links;
 | 
				
			||||||
 | 
					  n_links = links->len;
 | 
				
			||||||
 | 
					  for (i = 0; i < n_links; i++) {
 | 
				
			||||||
 | 
					    NodeLink *l = &g_array_index (links, NodeLink, i);
 | 
				
			||||||
 | 
					    if (l->link == link) {
 | 
				
			||||||
 | 
					      l->link = NULL;
 | 
				
			||||||
 | 
					      if (--link->input_node->priv->n_used_input_links == 0)
 | 
				
			||||||
        pinos_node_report_idle (link->input_node);
 | 
					        pinos_node_report_idle (link->input_node);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * pinos_node_link:
 | 
					 * pinos_node_link:
 | 
				
			||||||
| 
						 | 
					@ -1121,61 +1178,74 @@ do_remove_link (PinosLink *link, PinosNode *node)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
PinosLink *
 | 
					PinosLink *
 | 
				
			||||||
pinos_node_link (PinosNode       *output_node,
 | 
					pinos_node_link (PinosNode       *output_node,
 | 
				
			||||||
                 guint            output_port,
 | 
					                 guint            output_id,
 | 
				
			||||||
                 PinosNode       *input_node,
 | 
					                 PinosNode       *input_node,
 | 
				
			||||||
                 guint            input_port,
 | 
					                 guint            input_id,
 | 
				
			||||||
                 GPtrArray       *format_filter,
 | 
					                 GPtrArray       *format_filter,
 | 
				
			||||||
                 PinosProperties *properties)
 | 
					                 PinosProperties *properties)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosNodePrivate *priv;
 | 
					  PinosNodePrivate *priv;
 | 
				
			||||||
  PinosLink *link;
 | 
					  NodeLink *olink, *ilink;
 | 
				
			||||||
 | 
					  PinosLink *pl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  g_return_val_if_fail (PINOS_IS_NODE (output_node), NULL);
 | 
					  g_return_val_if_fail (PINOS_IS_NODE (output_node), NULL);
 | 
				
			||||||
  g_return_val_if_fail (PINOS_IS_NODE (input_node), NULL);
 | 
					  g_return_val_if_fail (PINOS_IS_NODE (input_node), NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if (get_port_direction (output_node, output_port) != PINOS_DIRECTION_OUTPUT) {
 | 
					 | 
				
			||||||
    PinosNode *tmp;
 | 
					 | 
				
			||||||
    guint tmp_port;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tmp = output_node;
 | 
					 | 
				
			||||||
    output_node = input_node;
 | 
					 | 
				
			||||||
    input_node = tmp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    tmp_port = output_port;
 | 
					 | 
				
			||||||
    output_port = input_port;
 | 
					 | 
				
			||||||
    input_port = tmp_port;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  priv = output_node->priv;
 | 
					  priv = output_node->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  link = g_hash_table_lookup (priv->links, GUINT_TO_POINTER (output_port));
 | 
					  g_debug ("node %p: link %u %p:%u", output_node, output_id, input_node, input_id);
 | 
				
			||||||
  if (link) {
 | 
					
 | 
				
			||||||
    link->input_node = input_node;
 | 
					  if (output_id >= priv->output_links->len)
 | 
				
			||||||
    link->input_port = input_port;
 | 
					    g_array_set_size (priv->output_links, output_id + 1);
 | 
				
			||||||
    g_object_ref (link);
 | 
					  if (input_id >= input_node->priv->input_links->len)
 | 
				
			||||||
 | 
					    g_array_set_size (input_node->priv->input_links, input_id + 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  olink = &g_array_index (priv->output_links, NodeLink, output_id);
 | 
				
			||||||
 | 
					  ilink = &g_array_index (input_node->priv->input_links, NodeLink, input_id);
 | 
				
			||||||
 | 
					  pl = olink->link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (pl)  {
 | 
				
			||||||
 | 
					    /* FIXME */
 | 
				
			||||||
 | 
					    pl->input_node = input_node;
 | 
				
			||||||
 | 
					    pl->input_id = input_id;
 | 
				
			||||||
 | 
					    g_object_ref (pl);
 | 
				
			||||||
  } else {
 | 
					  } else {
 | 
				
			||||||
 | 
					    uint32_t input_port, output_port;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (output_node->priv->clock)
 | 
					    if (output_node->priv->clock)
 | 
				
			||||||
      input_node->priv->clock = output_node->priv->clock;
 | 
					      input_node->priv->clock = output_node->priv->clock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    link = g_object_new (PINOS_TYPE_LINK,
 | 
					    output_port = get_free_node_port (output_node, PINOS_DIRECTION_OUTPUT);
 | 
				
			||||||
 | 
					    if (output_port == SPA_ID_INVALID)
 | 
				
			||||||
 | 
					      output_port = output_node->priv->output_port_ids[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    input_port = get_free_node_port (input_node, PINOS_DIRECTION_INPUT);
 | 
				
			||||||
 | 
					    if (input_port == SPA_ID_INVALID)
 | 
				
			||||||
 | 
					      input_port = input_node->priv->input_port_ids[0];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pl = g_object_new (PINOS_TYPE_LINK,
 | 
				
			||||||
                       "daemon", priv->daemon,
 | 
					                       "daemon", priv->daemon,
 | 
				
			||||||
                       "output-node", output_node,
 | 
					                       "output-node", output_node,
 | 
				
			||||||
 | 
					                       "output-id", output_id,
 | 
				
			||||||
                       "output-port", output_port,
 | 
					                       "output-port", output_port,
 | 
				
			||||||
                       "input-node", input_node,
 | 
					                       "input-node", input_node,
 | 
				
			||||||
 | 
					                       "input-id", input_id,
 | 
				
			||||||
                       "input-port", input_port,
 | 
					                       "input-port", input_port,
 | 
				
			||||||
                       "format-filter", format_filter,
 | 
					                       "format-filter", format_filter,
 | 
				
			||||||
                       "properties", properties,
 | 
					                       "properties", properties,
 | 
				
			||||||
                       NULL);
 | 
					                       NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_signal_connect (link,
 | 
					    g_signal_connect (pl,
 | 
				
			||||||
                      "remove",
 | 
					                      "remove",
 | 
				
			||||||
                      (GCallback) do_remove_link,
 | 
					                      (GCallback) do_remove_link,
 | 
				
			||||||
                      output_node);
 | 
					                      output_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_hash_table_insert (priv->links, GUINT_TO_POINTER (output_port), link);
 | 
					    output_node->priv->n_used_output_links++;
 | 
				
			||||||
    g_hash_table_insert (input_node->priv->links, GUINT_TO_POINTER (input_port), link);
 | 
					    input_node->priv->n_used_input_links++;
 | 
				
			||||||
 | 
					    olink->link = pl;
 | 
				
			||||||
 | 
					    ilink->link = pl;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  return link;
 | 
					  return pl;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					@ -1194,7 +1264,7 @@ pinos_node_get_links (PinosNode *node)
 | 
				
			||||||
  g_return_val_if_fail (PINOS_IS_NODE (node), NULL);
 | 
					  g_return_val_if_fail (PINOS_IS_NODE (node), NULL);
 | 
				
			||||||
  priv = node->priv;
 | 
					  priv = node->priv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return g_hash_table_get_values (priv->links);
 | 
					  return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -86,13 +86,13 @@ PinosDaemon *       pinos_node_get_daemon              (PinosNode       *node);
 | 
				
			||||||
const gchar *       pinos_node_get_sender              (PinosNode       *node);
 | 
					const gchar *       pinos_node_get_sender              (PinosNode       *node);
 | 
				
			||||||
const gchar *       pinos_node_get_object_path         (PinosNode       *node);
 | 
					const gchar *       pinos_node_get_object_path         (PinosNode       *node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
guint               pinos_node_get_free_port_id        (PinosNode       *node,
 | 
					guint               pinos_node_get_free_port           (PinosNode       *node,
 | 
				
			||||||
                                                        PinosDirection   direction);
 | 
					                                                        PinosDirection   direction);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PinosLink *         pinos_node_link                    (PinosNode       *output_node,
 | 
					PinosLink *         pinos_node_link                    (PinosNode       *output_node,
 | 
				
			||||||
                                                        guint            output_port,
 | 
					                                                        guint            output_id,
 | 
				
			||||||
                                                        PinosNode       *input_node,
 | 
					                                                        PinosNode       *input_node,
 | 
				
			||||||
                                                        guint            input_port,
 | 
					                                                        guint            input_id,
 | 
				
			||||||
                                                        GPtrArray       *format_filter,
 | 
					                                                        GPtrArray       *format_filter,
 | 
				
			||||||
                                                        PinosProperties *properties);
 | 
					                                                        PinosProperties *properties);
 | 
				
			||||||
GList *             pinos_node_get_links               (PinosNode       *node);
 | 
					GList *             pinos_node_get_links               (PinosNode       *node);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue