mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	node: add flag to always assign a driver to a node
Add flag to always assign a node to a driver. This makes sure that even when the node is not linked to anything, it will still be scheduled by an active driver. This is needed for JACK support.
This commit is contained in:
		
							parent
							
								
									bc88e1cbf8
								
							
						
					
					
						commit
						f36daaedea
					
				
					 5 changed files with 57 additions and 4 deletions
				
			
		| 
						 | 
					@ -653,8 +653,11 @@ struct spa_node_methods {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** node keys */
 | 
					/** node keys */
 | 
				
			||||||
#define SPA_KEY_NODE_NAME		"node.name"		/**< a node name */
 | 
					#define SPA_KEY_NODE_NAME		"node.name"		/**< a node name */
 | 
				
			||||||
#define SPA_KEY_NODE_DRIVER		"node.driver"		/**< the node can be a driver */
 | 
					 | 
				
			||||||
#define SPA_KEY_NODE_LATENCY		"node.latency"		/**< the requested node latency */
 | 
					#define SPA_KEY_NODE_LATENCY		"node.latency"		/**< the requested node latency */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define SPA_KEY_NODE_DRIVER		"node.driver"		/**< the node can be a driver */
 | 
				
			||||||
 | 
					#define SPA_KEY_NODE_ALWAYS_PROCESS	"node.always-process"	/**< call the process function even if
 | 
				
			||||||
 | 
													  *  not linked. */
 | 
				
			||||||
#define SPA_KEY_NODE_PAUSE_ON_IDLE	"node.pause-on-idle"	/**< if the node should be paused
 | 
					#define SPA_KEY_NODE_PAUSE_ON_IDLE	"node.pause-on-idle"	/**< if the node should be paused
 | 
				
			||||||
								  *  immediately when idle. */
 | 
													  *  immediately when idle. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1101,22 +1101,63 @@ static int collect_nodes(struct pw_node *driver)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pw_core_recalc_graph(struct pw_core *core)
 | 
					int pw_core_recalc_graph(struct pw_core *core)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pw_node *n, *s;
 | 
						struct pw_node *n, *s, *target;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* start from all drivers and group all nodes that are linked
 | 
				
			||||||
 | 
						 * to it. Some nodes are not (yet) linked to anything and they
 | 
				
			||||||
 | 
						 * will end up 'unassigned' to a master. Other nodes are master
 | 
				
			||||||
 | 
						 * and if they have active slaves, we can use them to schedule
 | 
				
			||||||
 | 
						 * the unassigned nodes. */
 | 
				
			||||||
 | 
						target = NULL;
 | 
				
			||||||
	spa_list_for_each(n, &core->driver_list, driver_link) {
 | 
						spa_list_for_each(n, &core->driver_list, driver_link) {
 | 
				
			||||||
		if (!n->visited)
 | 
							uint32_t active_slaves;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (n->active && !n->visited)
 | 
				
			||||||
			collect_nodes(n);
 | 
								collect_nodes(n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* from now on we are only interested in nodes that are
 | 
				
			||||||
 | 
							 * a master. We're going to count the number of slaves it
 | 
				
			||||||
 | 
							 * has. */
 | 
				
			||||||
 | 
							if (!n->master)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							active_slaves = 0;
 | 
				
			||||||
 | 
							spa_list_for_each(s, &n->slave_list, slave_link) {
 | 
				
			||||||
 | 
								pw_log_info(NAME" %p: driver %p: slave %p %s: %d",
 | 
				
			||||||
 | 
										core, n, s, s->name, s->active);
 | 
				
			||||||
 | 
								if (s != n && s->active)
 | 
				
			||||||
 | 
									active_slaves++;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							pw_log_info(NAME" %p: driver %p active slaves %d",
 | 
				
			||||||
 | 
									core, n, active_slaves);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* if the master has active slaves, it is a target for our
 | 
				
			||||||
 | 
							 * unassigned nodes */
 | 
				
			||||||
 | 
							if (active_slaves > 0) {
 | 
				
			||||||
 | 
								if (target == NULL)
 | 
				
			||||||
 | 
									target = n;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* now go through all available nodes. The ones we didn't visit
 | 
				
			||||||
 | 
						 * in collect_nodes() are not linked to any master. We assign them
 | 
				
			||||||
 | 
						 * to an active master */
 | 
				
			||||||
	spa_list_for_each(n, &core->node_list, link) {
 | 
						spa_list_for_each(n, &core->node_list, link) {
 | 
				
			||||||
		if (!n->visited) {
 | 
							if (!n->visited) {
 | 
				
			||||||
			pw_log_info(NAME" %p: unassigned node %p: '%s' %d", core,
 | 
								pw_log_info(NAME" %p: unassigned node %p: '%s' %d", core,
 | 
				
			||||||
					n, n->name, n->active);
 | 
										n, n->name, n->active);
 | 
				
			||||||
 | 
								if (!n->want_driver)
 | 
				
			||||||
				pw_node_set_driver(n, NULL);
 | 
									pw_node_set_driver(n, NULL);
 | 
				
			||||||
 | 
								else {
 | 
				
			||||||
 | 
									pw_node_set_driver(n, target);
 | 
				
			||||||
 | 
									pw_node_set_state(n, target && n->active ?
 | 
				
			||||||
 | 
											PW_NODE_STATE_RUNNING : PW_NODE_STATE_IDLE);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		n->visited = false;
 | 
							n->visited = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* debug only here to list all masters and their slaves */
 | 
				
			||||||
	spa_list_for_each(n, &core->driver_list, driver_link) {
 | 
						spa_list_for_each(n, &core->driver_list, driver_link) {
 | 
				
			||||||
		if (!n->master)
 | 
							if (!n->master)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -121,6 +121,7 @@ extern "C" {
 | 
				
			||||||
#define PW_KEY_NODE_LATENCY		"node.latency"		/**< the requested latency of the node as
 | 
					#define PW_KEY_NODE_LATENCY		"node.latency"		/**< the requested latency of the node as
 | 
				
			||||||
								  *  a fraction. Ex: 128/48000 */
 | 
													  *  a fraction. Ex: 128/48000 */
 | 
				
			||||||
#define PW_KEY_NODE_DONT_RECONNECT	"node.dont-reconnect"	/**< don't reconnect this node */
 | 
					#define PW_KEY_NODE_DONT_RECONNECT	"node.dont-reconnect"	/**< don't reconnect this node */
 | 
				
			||||||
 | 
					#define PW_KEY_NODE_ALWAYS_PROCESS	"node.always-process"	/**< process even when unlinked */
 | 
				
			||||||
#define PW_KEY_NODE_PAUSE_ON_IDLE	"node.pause-on-idle"	/**< pause the node when idle */
 | 
					#define PW_KEY_NODE_PAUSE_ON_IDLE	"node.pause-on-idle"	/**< pause the node when idle */
 | 
				
			||||||
#define PW_KEY_NODE_DRIVER		"node.driver"		/**< node can drive the graph */
 | 
					#define PW_KEY_NODE_DRIVER		"node.driver"		/**< node can drive the graph */
 | 
				
			||||||
#define PW_KEY_NODE_STREAM		"node.stream"		/**< node is a stream, the server side should
 | 
					#define PW_KEY_NODE_STREAM		"node.stream"		/**< node is a stream, the server side should
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -601,6 +601,8 @@ int pw_node_register(struct pw_node *this,
 | 
				
			||||||
	spa_list_for_each(port, &this->output_ports, link)
 | 
						spa_list_for_each(port, &this->output_ports, link)
 | 
				
			||||||
		pw_port_register(port, NULL);
 | 
							pw_port_register(port, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_core_recalc_graph(core);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
error_existed:
 | 
					error_existed:
 | 
				
			||||||
| 
						 | 
					@ -706,6 +708,11 @@ static void check_properties(struct pw_node *node)
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		driver = false;
 | 
							driver = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ((str = pw_properties_get(node->properties, PW_KEY_NODE_ALWAYS_PROCESS)))
 | 
				
			||||||
 | 
							node->want_driver = pw_properties_parse_bool(str);
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							node->want_driver = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->driver != driver) {
 | 
						if (node->driver != driver) {
 | 
				
			||||||
		pw_log_info(NAME" %p: driver %d -> %d", node, node->driver, driver);
 | 
							pw_log_info(NAME" %p: driver %d -> %d", node, node->driver, driver);
 | 
				
			||||||
		node->driver = driver;
 | 
							node->driver = driver;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -419,6 +419,7 @@ struct pw_node {
 | 
				
			||||||
	unsigned int master:1;		/**< a master node is one of the driver nodes that
 | 
						unsigned int master:1;		/**< a master node is one of the driver nodes that
 | 
				
			||||||
					  *  is selected to drive the graph */
 | 
										  *  is selected to drive the graph */
 | 
				
			||||||
	unsigned int visited:1;		/**< for sorting */
 | 
						unsigned int visited:1;		/**< for sorting */
 | 
				
			||||||
 | 
						unsigned int want_driver:1;	/**< this node wants to be assigned to a driver */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t port_user_data_size;	/**< extra size for port user data */
 | 
						uint32_t port_user_data_size;	/**< extra size for port user data */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue