mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Rework how targets are managed
Manage them like we do on the client and reuse logic. Make a node function to safely add and remove a target. Activate the targets from the process loop when we can be sure that we can resume them. This avoids incrementing the pending state when we are not going to be able to resume the nodes (like when the cycle is ongoing and we have already been scheduled) and avoids glitches and xruns. When a node is added to the poll loop, it can activate its own targets. This is mostly for driver so that they have something to schedule and can then activate the other targets. Try to resume the target when it is removed and we are supposed to be scheduled. Also add targets to the target_list when the node is remote to make sure the profiler can see the targets as well. Keep the node in the INACTIVE state as long as the eventfd of the node is not added to the loop. Skip nodes in the INACTIVE state from going to the NOT_TRIGGERED status, which avoids scheduling the node. Make sure we remove any local targets we have in a node when we export it, we will receive new targets from the server. This should eliminate any glitches when adding and removing nodes from the graph. See #4026, #2468
This commit is contained in:
		
							parent
							
								
									ce985def73
								
							
						
					
					
						commit
						46f71b1cd2
					
				
					 6 changed files with 296 additions and 345 deletions
				
			
		| 
						 | 
				
			
			@ -1347,8 +1347,6 @@ void pw_impl_client_node_registered(struct pw_impl_client_node *this, struct pw_
 | 
			
		|||
					  0,
 | 
			
		||||
					  sizeof(struct pw_node_activation));
 | 
			
		||||
 | 
			
		||||
	node_peer_added(impl, node);
 | 
			
		||||
 | 
			
		||||
	if (impl->bind_node_id) {
 | 
			
		||||
		pw_global_bind(global, client, PW_PERM_ALL,
 | 
			
		||||
				impl->bind_node_version, impl->bind_node_id);
 | 
			
		||||
| 
						 | 
				
			
			@ -1707,16 +1705,6 @@ static void node_port_removed(void *data, struct pw_impl_port *port)
 | 
			
		|||
	clear_port(impl, p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_driver_changed(void *data, struct pw_impl_node *old, struct pw_impl_node *driver)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("%p: driver changed %p -> %p", impl, old, driver);
 | 
			
		||||
 | 
			
		||||
	node_peer_removed(data, old);
 | 
			
		||||
	node_peer_added(data, driver);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_impl_node_events node_events = {
 | 
			
		||||
	PW_VERSION_IMPL_NODE_EVENTS,
 | 
			
		||||
	.free = node_free,
 | 
			
		||||
| 
						 | 
				
			
			@ -1726,7 +1714,6 @@ static const struct pw_impl_node_events node_events = {
 | 
			
		|||
	.port_removed = node_port_removed,
 | 
			
		||||
	.peer_added = node_peer_added,
 | 
			
		||||
	.peer_removed = node_peer_removed,
 | 
			
		||||
	.driver_changed = node_driver_changed,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct pw_resource_events resource_events = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,21 +94,10 @@ static struct link *find_activation(struct spa_list *links, uint32_t node_id)
 | 
			
		|||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
do_deactivate_link(struct spa_loop *loop,
 | 
			
		||||
                bool async, uint32_t seq, const void *data, size_t size, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	struct link *link = user_data;
 | 
			
		||||
	pw_log_trace("link %p deactivate", link);
 | 
			
		||||
	spa_list_remove(&link->target.link);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void clear_link(struct node_data *data, struct link *link)
 | 
			
		||||
{
 | 
			
		||||
	pw_log_debug("link %p", link);
 | 
			
		||||
	pw_loop_invoke(data->data_loop,
 | 
			
		||||
		do_deactivate_link, SPA_ID_INVALID, NULL, 0, true, link);
 | 
			
		||||
	pw_impl_node_remove_target(data->node, &link->target);
 | 
			
		||||
	pw_memmap_free(link->map);
 | 
			
		||||
	spa_system_close(link->target.system, link->target.fd);
 | 
			
		||||
	spa_list_remove(&link->link);
 | 
			
		||||
| 
						 | 
				
			
			@ -802,17 +791,6 @@ exit:
 | 
			
		|||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
do_activate_link(struct spa_loop *loop,
 | 
			
		||||
                bool async, uint32_t seq, const void *data, size_t size, void *user_data)
 | 
			
		||||
{
 | 
			
		||||
	struct link *link = user_data;
 | 
			
		||||
	struct node_data *d = link->data;
 | 
			
		||||
	pw_log_trace("link %p activate", link);
 | 
			
		||||
	spa_list_append(&d->node->rt.target_list, &link->target.link);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
client_node_set_activation(void *_data,
 | 
			
		||||
                        uint32_t node_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -863,8 +841,7 @@ client_node_set_activation(void *_data,
 | 
			
		|||
		link->target.fd = signalfd;
 | 
			
		||||
		spa_list_append(&data->links, &link->link);
 | 
			
		||||
 | 
			
		||||
		pw_loop_invoke(data->data_loop,
 | 
			
		||||
                       do_activate_link, SPA_ID_INVALID, NULL, 0, false, link);
 | 
			
		||||
		pw_impl_node_add_target(node, &link->target);
 | 
			
		||||
 | 
			
		||||
		pw_log_debug("node %p: add link %p: memid:%u fd:%d id:%u state:%p pending:%d/%d",
 | 
			
		||||
				node, link, memid, signalfd, node_id,
 | 
			
		||||
| 
						 | 
				
			
			@ -1206,6 +1183,8 @@ static struct pw_proxy *node_export(struct pw_core *core, void *object, bool do_
 | 
			
		|||
	if (node->data_loop == NULL)
 | 
			
		||||
		goto error;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("%p: export node %p", core, object);
 | 
			
		||||
 | 
			
		||||
	user_data_size = SPA_ROUND_UP_N(user_data_size, __alignof__(struct node_data));
 | 
			
		||||
 | 
			
		||||
	client_node = pw_core_create_object(core,
 | 
			
		||||
| 
						 | 
				
			
			@ -1228,6 +1207,11 @@ static struct pw_proxy *node_export(struct pw_core *core, void *object, bool do_
 | 
			
		|||
	data->client_node = (struct pw_client_node *)client_node;
 | 
			
		||||
	data->remote_id = SPA_ID_INVALID;
 | 
			
		||||
 | 
			
		||||
	/* the node might have been registered and added to a driver. When we export,
 | 
			
		||||
	 * we will be assigned a new driver target from the server and we can forget our
 | 
			
		||||
	 * local ones. */
 | 
			
		||||
	pw_impl_node_remove_target(node, &node->rt.driver_target);
 | 
			
		||||
	pw_impl_node_remove_target(node->driver_node, &node->rt.target);
 | 
			
		||||
 | 
			
		||||
	data->allow_mlock = pw_properties_get_bool(node->properties, "mem.allow-mlock",
 | 
			
		||||
						   data->context->settings.mem_allow_mlock);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue