mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Add proxy destroy
Make the current destroy method on the core for proxies to remove the server side resource. Make a new destroy method on the registry to destroy globals. Remove the destroy method on the client-node media-session: monitor the dsp and device node states to manage the session state
This commit is contained in:
		
							parent
							
								
									ce4cfd78e7
								
							
						
					
					
						commit
						59f10ad453
					
				
					 10 changed files with 276 additions and 157 deletions
				
			
		| 
						 | 
				
			
			@ -42,6 +42,8 @@
 | 
			
		|||
#define DEFAULT_CHANNELS	2
 | 
			
		||||
#define DEFAULT_SAMPLERATE	48000
 | 
			
		||||
 | 
			
		||||
#define DEFAULT_IDLE_SECONDS	3
 | 
			
		||||
 | 
			
		||||
#define MIN_QUANTUM_SIZE	64
 | 
			
		||||
#define MAX_QUANTUM_SIZE	1024
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +88,7 @@ struct node {
 | 
			
		|||
	struct spa_list session_link;
 | 
			
		||||
	struct session *session;
 | 
			
		||||
 | 
			
		||||
	struct session *manager;
 | 
			
		||||
	struct spa_list port_list;
 | 
			
		||||
 | 
			
		||||
	enum pw_direction direction;
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +129,8 @@ struct session {
 | 
			
		|||
 | 
			
		||||
	struct node *node;
 | 
			
		||||
	struct node *dsp;
 | 
			
		||||
	struct link *link;
 | 
			
		||||
	struct pw_link_proxy *link;
 | 
			
		||||
	struct spa_hook link_listener;
 | 
			
		||||
 | 
			
		||||
	struct spa_list node_list;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -173,18 +177,152 @@ static void schedule_rescan(struct impl *impl)
 | 
			
		|||
static void remove_idle_timeout(struct session *sess)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = sess->impl;
 | 
			
		||||
	struct pw_loop *main_loop = pw_core_get_main_loop(impl->core);
 | 
			
		||||
 | 
			
		||||
	if (sess->idle_timeout) {
 | 
			
		||||
		pw_loop_destroy_source(pw_core_get_main_loop(impl->core), sess->idle_timeout);
 | 
			
		||||
		pw_loop_destroy_source(main_loop, sess->idle_timeout);
 | 
			
		||||
		sess->idle_timeout = NULL;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void idle_timeout(void *data, uint64_t expirations)
 | 
			
		||||
{
 | 
			
		||||
	struct session *sess = data;
 | 
			
		||||
	struct impl *impl = sess->impl;
 | 
			
		||||
	struct spa_command *cmd = &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: session %d idle timeout", impl, sess->id);
 | 
			
		||||
 | 
			
		||||
	remove_idle_timeout(sess);
 | 
			
		||||
 | 
			
		||||
	pw_node_proxy_send_command((struct pw_node_proxy*)sess->node->obj.proxy, cmd);
 | 
			
		||||
	if (sess->dsp)
 | 
			
		||||
		pw_node_proxy_send_command((struct pw_node_proxy*)sess->dsp->obj.proxy, cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void add_idle_timeout(struct session *sess)
 | 
			
		||||
{
 | 
			
		||||
	struct timespec value;
 | 
			
		||||
	struct impl *impl = sess->impl;
 | 
			
		||||
	struct pw_loop *main_loop = pw_core_get_main_loop(impl->core);
 | 
			
		||||
 | 
			
		||||
	if (sess->idle_timeout == NULL)
 | 
			
		||||
		sess->idle_timeout = pw_loop_add_timer(main_loop, idle_timeout, sess);
 | 
			
		||||
 | 
			
		||||
	value.tv_sec = DEFAULT_IDLE_SECONDS;
 | 
			
		||||
	value.tv_nsec = 0;
 | 
			
		||||
	pw_loop_update_timer(main_loop, sess->idle_timeout, &value, NULL, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int unlink_session_dsp(struct impl *impl, struct session *session)
 | 
			
		||||
{
 | 
			
		||||
	pw_core_proxy_destroy(impl->core_proxy, (struct pw_proxy*)session->link);
 | 
			
		||||
	session->link = NULL;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int on_node_idle(struct impl *impl, struct node *node)
 | 
			
		||||
{
 | 
			
		||||
	struct session *sess = node->manager;
 | 
			
		||||
 | 
			
		||||
	if (sess == NULL)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	switch (node->type) {
 | 
			
		||||
	case NODE_TYPE_DSP:
 | 
			
		||||
		pw_log_debug(NAME" %p: dsp idle for session %d", impl, sess->id);
 | 
			
		||||
		if (sess->link)
 | 
			
		||||
			unlink_session_dsp(impl, sess);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NODE_TYPE_DEVICE:
 | 
			
		||||
		pw_log_debug(NAME" %p: device idle for session %d", impl, sess->id);
 | 
			
		||||
		sess->busy = false;
 | 
			
		||||
		sess->exclusive = false;
 | 
			
		||||
		add_idle_timeout(sess);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int link_session_dsp(struct impl *impl, struct session *session)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: link session dsp '%d'", impl, session->id);
 | 
			
		||||
 | 
			
		||||
	props = pw_properties_new(NULL, NULL);
 | 
			
		||||
//	pw_properties_set(props, PW_LINK_PROP_PASSIVE, "true");
 | 
			
		||||
	if (session->direction == PW_DIRECTION_OUTPUT) {
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_OUTPUT_NODE_ID, "%d", session->dsp->info->id);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_OUTPUT_PORT_ID, "%d", -1);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_INPUT_NODE_ID, "%d", session->node->info->id);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_INPUT_PORT_ID, "%d", -1);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_OUTPUT_NODE_ID, "%d", session->node->info->id);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_OUTPUT_PORT_ID, "%d", -1);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_INPUT_NODE_ID, "%d", session->dsp->info->id);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_INPUT_PORT_ID, "%d", -1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        session->link = pw_core_proxy_create_object(impl->core_proxy,
 | 
			
		||||
                                          "link-factory",
 | 
			
		||||
                                          PW_TYPE_INTERFACE_Link,
 | 
			
		||||
                                          PW_VERSION_LINK,
 | 
			
		||||
                                          &props->dict,
 | 
			
		||||
					  0);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int on_node_running(struct impl *impl, struct node *node)
 | 
			
		||||
{
 | 
			
		||||
	struct session *sess = node->manager;
 | 
			
		||||
 | 
			
		||||
	if (sess == NULL)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	switch (node->type) {
 | 
			
		||||
	case NODE_TYPE_DSP:
 | 
			
		||||
		pw_log_debug(NAME" %p: dsp running for session %d", impl, sess->id);
 | 
			
		||||
		if (sess->link == NULL)
 | 
			
		||||
			link_session_dsp(impl, sess);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case NODE_TYPE_DEVICE:
 | 
			
		||||
		pw_log_debug(NAME" %p: device running or session %d", impl, sess->id);
 | 
			
		||||
		remove_idle_timeout(sess);
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_event_info(void *object, struct pw_node_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct node *n = object;
 | 
			
		||||
	pw_log_debug(NAME" %p: info for node %d", n->obj.impl, n->obj.id);
 | 
			
		||||
	struct impl *impl = n->obj.impl;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME" %p: info for node %d type %d", impl, n->obj.id, n->type);
 | 
			
		||||
	n->info = pw_node_info_update(n->info, info);
 | 
			
		||||
 | 
			
		||||
	switch (info->state) {
 | 
			
		||||
	case PW_NODE_STATE_IDLE:
 | 
			
		||||
		on_node_idle(impl, n);
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_NODE_STATE_RUNNING:
 | 
			
		||||
		on_node_running(impl, n);
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_NODE_STATE_SUSPENDED:
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_node_proxy_events node_events = {
 | 
			
		||||
| 
						 | 
				
			
			@ -299,6 +437,7 @@ handle_node(struct impl *impl, uint32_t id, uint32_t parent_id,
 | 
			
		|||
 | 
			
		||||
		node->direction = direction;
 | 
			
		||||
		node->type = NODE_TYPE_DEVICE;
 | 
			
		||||
		node->manager = sess;
 | 
			
		||||
 | 
			
		||||
		pw_log_debug(NAME" %p: new session for device node %d", impl, id);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -432,23 +571,9 @@ registry_global(void *data,uint32_t id, uint32_t parent_id,
 | 
			
		|||
	schedule_rescan(impl);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
registry_global_remove(void *data, uint32_t id)
 | 
			
		||||
static void remove_session(struct impl *impl, struct session *sess)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
	struct object *obj;
 | 
			
		||||
	struct session *sess;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: remove global '%d'", impl, id);
 | 
			
		||||
 | 
			
		||||
	if ((obj = find_object(impl, id)) == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(sess, &impl->session_list, l) {
 | 
			
		||||
		struct node *node = (struct node *)obj, *n, *t;
 | 
			
		||||
 | 
			
		||||
		if (sess->node != node)
 | 
			
		||||
			continue;
 | 
			
		||||
	struct node *n, *t;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: remove session '%d'", impl, sess->id);
 | 
			
		||||
	remove_idle_timeout(sess);
 | 
			
		||||
| 
						 | 
				
			
			@ -459,15 +584,36 @@ registry_global_remove(void *data, uint32_t id)
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if (sess->dsp) {
 | 
			
		||||
			uint32_t id = ((struct object *)sess->dsp)->id;
 | 
			
		||||
			pw_log_debug(NAME " %p: destroy dsp '%d'", impl, id);
 | 
			
		||||
			pw_core_proxy_destroy(impl->core_proxy, id);
 | 
			
		||||
		pw_log_debug(NAME " %p: destroy dsp", impl);
 | 
			
		||||
		pw_core_proxy_destroy(impl->core_proxy, sess->dsp->obj.proxy);
 | 
			
		||||
	}
 | 
			
		||||
	spa_list_remove(&sess->l);
 | 
			
		||||
	free(sess);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
registry_global_remove(void *data, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
	struct object *obj;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: remove global '%d'", impl, id);
 | 
			
		||||
 | 
			
		||||
	if ((obj = find_object(impl, id)) == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	switch (obj->type) {
 | 
			
		||||
	case PW_TYPE_INTERFACE_Node:
 | 
			
		||||
	{
 | 
			
		||||
		struct node *node = (struct node*) obj;
 | 
			
		||||
		if (node->manager)
 | 
			
		||||
			remove_session(impl, node->manager);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	}
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	remove_object(impl, obj);
 | 
			
		||||
	schedule_rescan(impl);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -479,39 +625,6 @@ static const struct pw_registry_proxy_events registry_events = {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int link_session_dsp(struct session *session)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = session->impl;
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: link session dsp '%d'", impl, session->id);
 | 
			
		||||
 | 
			
		||||
	props = pw_properties_new(NULL, NULL);
 | 
			
		||||
	pw_properties_set(props, PW_LINK_PROP_PASSIVE, "true");
 | 
			
		||||
	if (session->direction == PW_DIRECTION_OUTPUT) {
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_OUTPUT_NODE_ID, "%d", session->dsp->info->id);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_OUTPUT_PORT_ID, "%d", -1);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_INPUT_NODE_ID, "%d", session->node->info->id);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_INPUT_PORT_ID, "%d", -1);
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_OUTPUT_NODE_ID, "%d", session->node->info->id);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_OUTPUT_PORT_ID, "%d", -1);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_INPUT_NODE_ID, "%d", session->dsp->info->id);
 | 
			
		||||
		pw_properties_setf(props, PW_LINK_INPUT_PORT_ID, "%d", -1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
        session->link = pw_core_proxy_create_object(impl->core_proxy,
 | 
			
		||||
                                          "link-factory",
 | 
			
		||||
                                          PW_TYPE_INTERFACE_Link,
 | 
			
		||||
                                          PW_VERSION_LINK,
 | 
			
		||||
                                          &props->dict,
 | 
			
		||||
					  0);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct find_data {
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
	uint32_t path_id;
 | 
			
		||||
| 
						 | 
				
			
			@ -618,7 +731,6 @@ static int rescan_node(struct impl *impl, struct node *node)
 | 
			
		|||
	struct pw_node_info *info;
 | 
			
		||||
	struct node *peer;
 | 
			
		||||
	enum pw_direction direction;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	if (node->type == NODE_TYPE_DSP || node->type == NODE_TYPE_DEVICE)
 | 
			
		||||
		return 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -722,10 +834,6 @@ static int rescan_node(struct impl *impl, struct node *node)
 | 
			
		|||
		session->exclusive = exclusive;
 | 
			
		||||
	}
 | 
			
		||||
	else {
 | 
			
		||||
		if (session->link == NULL) {
 | 
			
		||||
			if ((res = link_session_dsp(session)) < 0)
 | 
			
		||||
				return res;
 | 
			
		||||
		}
 | 
			
		||||
		peer = session->dsp;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -734,7 +842,6 @@ static int rescan_node(struct impl *impl, struct node *node)
 | 
			
		|||
        session->busy = true;
 | 
			
		||||
	node->session = session;
 | 
			
		||||
	spa_list_append(&session->node_list, &node->session_link);
 | 
			
		||||
	remove_idle_timeout(session);
 | 
			
		||||
 | 
			
		||||
	link_nodes(peer, direction, node);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -756,6 +863,7 @@ static void dsp_node_event_info(void *object, struct pw_node_info *info)
 | 
			
		|||
 | 
			
		||||
	dsp->direction = s->direction;
 | 
			
		||||
	dsp->type = NODE_TYPE_DSP;
 | 
			
		||||
	dsp->manager = s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_node_proxy_events dsp_node_events = {
 | 
			
		||||
| 
						 | 
				
			
			@ -763,36 +871,8 @@ static const struct pw_node_proxy_events dsp_node_events = {
 | 
			
		|||
	.info = dsp_node_event_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void idle_timeout(void *data, uint64_t expirations)
 | 
			
		||||
{
 | 
			
		||||
	struct session *sess = data;
 | 
			
		||||
	struct impl *impl = sess->impl;
 | 
			
		||||
	struct spa_command *cmd = &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: session %d idle timeout", impl, sess->id);
 | 
			
		||||
 | 
			
		||||
	remove_idle_timeout(sess);
 | 
			
		||||
 | 
			
		||||
	pw_node_proxy_send_command((struct pw_node_proxy*)sess->node->obj.proxy, cmd);
 | 
			
		||||
	if (sess->dsp)
 | 
			
		||||
		pw_node_proxy_send_command((struct pw_node_proxy*)sess->dsp->obj.proxy, cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void rescan_session(struct impl *impl, struct session *sess)
 | 
			
		||||
{
 | 
			
		||||
	if (spa_list_is_empty(&sess->node_list) && sess->busy) {
 | 
			
		||||
                struct pw_loop *main_loop = pw_core_get_main_loop(impl->core);
 | 
			
		||||
		struct timespec value;
 | 
			
		||||
 | 
			
		||||
		pw_log_debug(NAME "%p: session %d became idle", impl, sess->id);
 | 
			
		||||
		sess->exclusive = false;
 | 
			
		||||
		sess->busy = false;
 | 
			
		||||
 | 
			
		||||
		sess->idle_timeout = pw_loop_add_timer(main_loop, idle_timeout, sess);
 | 
			
		||||
		value.tv_sec = 3;
 | 
			
		||||
		value.tv_nsec = 0;
 | 
			
		||||
		pw_loop_update_timer(main_loop, sess->idle_timeout, &value, NULL, false);
 | 
			
		||||
	}
 | 
			
		||||
	if (sess->need_dsp && sess->dsp == NULL && !sess->dsp_pending) {
 | 
			
		||||
		struct pw_properties *props;
 | 
			
		||||
		struct node *node = sess->node;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,8 +58,7 @@ struct pw_client_node_position {
 | 
			
		|||
#define PW_CLIENT_NODE_PROXY_METHOD_PORT_UPDATE		2
 | 
			
		||||
#define PW_CLIENT_NODE_PROXY_METHOD_SET_ACTIVE		3
 | 
			
		||||
#define PW_CLIENT_NODE_PROXY_METHOD_EVENT		4
 | 
			
		||||
#define PW_CLIENT_NODE_PROXY_METHOD_DESTROY		5
 | 
			
		||||
#define PW_CLIENT_NODE_PROXY_METHOD_NUM			6
 | 
			
		||||
#define PW_CLIENT_NODE_PROXY_METHOD_NUM			5
 | 
			
		||||
 | 
			
		||||
/** \ref pw_client_node methods */
 | 
			
		||||
struct pw_client_node_proxy_methods {
 | 
			
		||||
| 
						 | 
				
			
			@ -120,10 +119,6 @@ struct pw_client_node_proxy_methods {
 | 
			
		|||
	 * \param event the event to send
 | 
			
		||||
	 */
 | 
			
		||||
	void (*event) (void *object, struct spa_event *event);
 | 
			
		||||
	/**
 | 
			
		||||
	 * Destroy the client_node
 | 
			
		||||
	 */
 | 
			
		||||
	void (*destroy) (void *object);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
| 
						 | 
				
			
			@ -176,13 +171,6 @@ pw_client_node_proxy_event(struct pw_client_node_proxy *p, struct spa_event *eve
 | 
			
		|||
        pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods, event, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
pw_client_node_proxy_destroy(struct pw_client_node_proxy *p)
 | 
			
		||||
{
 | 
			
		||||
        pw_proxy_do((struct pw_proxy*)p, struct pw_client_node_proxy_methods, destroy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define PW_CLIENT_NODE_PROXY_EVENT_ADD_MEM		0
 | 
			
		||||
#define PW_CLIENT_NODE_PROXY_EVENT_TRANSPORT		1
 | 
			
		||||
#define PW_CLIENT_NODE_PROXY_EVENT_SET_PARAM		2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1086,12 +1086,6 @@ static void client_node_event(void *data, struct spa_event *event)
 | 
			
		|||
	this->callbacks->event(this->callbacks_data, event);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void client_node_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
	pw_client_node_destroy(&impl->this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct pw_client_node_proxy_methods client_node_methods = {
 | 
			
		||||
	PW_VERSION_CLIENT_NODE_PROXY_METHODS,
 | 
			
		||||
	.done = client_node_done,
 | 
			
		||||
| 
						 | 
				
			
			@ -1099,7 +1093,6 @@ static struct pw_client_node_proxy_methods client_node_methods = {
 | 
			
		|||
	.port_update = client_node_port_update,
 | 
			
		||||
	.set_active = client_node_set_active,
 | 
			
		||||
	.event = client_node_event,
 | 
			
		||||
	.destroy = client_node_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void node_on_data_fd_events(struct spa_source *source)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -153,18 +153,6 @@ static void client_node_marshal_event_method(void *object, struct spa_event *eve
 | 
			
		|||
	pw_protocol_native_end_proxy(proxy, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void client_node_marshal_destroy(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_proxy *proxy = object;
 | 
			
		||||
	struct spa_pod_builder *b;
 | 
			
		||||
 | 
			
		||||
	b = pw_protocol_native_begin_proxy(proxy, PW_CLIENT_NODE_PROXY_METHOD_DESTROY);
 | 
			
		||||
 | 
			
		||||
	spa_pod_builder_add_struct(b);
 | 
			
		||||
 | 
			
		||||
	pw_protocol_native_end_proxy(proxy, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_node_demarshal_add_mem(void *object, void *data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_proxy *proxy = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -874,27 +862,13 @@ static int client_node_demarshal_event_method(void *object, void *data, size_t s
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_node_demarshal_destroy(void *object, void *data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
	struct spa_pod_parser prs;
 | 
			
		||||
 | 
			
		||||
	spa_pod_parser_init(&prs, data, size, 0);
 | 
			
		||||
	if (spa_pod_parser_get(&prs, "[", NULL) < 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	pw_resource_do(resource, struct pw_client_node_proxy_methods, destroy, 0);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_client_node_proxy_methods pw_protocol_native_client_node_method_marshal = {
 | 
			
		||||
	PW_VERSION_CLIENT_NODE_PROXY_METHODS,
 | 
			
		||||
	&client_node_marshal_done,
 | 
			
		||||
	&client_node_marshal_update,
 | 
			
		||||
	&client_node_marshal_port_update,
 | 
			
		||||
	&client_node_marshal_set_active,
 | 
			
		||||
	&client_node_marshal_event_method,
 | 
			
		||||
	&client_node_marshal_destroy
 | 
			
		||||
	&client_node_marshal_event_method
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct pw_protocol_native_demarshal pw_protocol_native_client_node_method_demarshal[] = {
 | 
			
		||||
| 
						 | 
				
			
			@ -902,8 +876,7 @@ static const struct pw_protocol_native_demarshal pw_protocol_native_client_node_
 | 
			
		|||
	{ &client_node_demarshal_update, 0 },
 | 
			
		||||
	{ &client_node_demarshal_port_update, 0 },
 | 
			
		||||
	{ &client_node_demarshal_set_active, 0 },
 | 
			
		||||
	{ &client_node_demarshal_event_method, 0 },
 | 
			
		||||
	{ &client_node_demarshal_destroy, 0 },
 | 
			
		||||
	{ &client_node_demarshal_event_method, 0 }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct pw_client_node_proxy_events pw_protocol_native_client_node_event_marshal = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -509,6 +509,22 @@ static int registry_demarshal_bind(void *object, void *data, size_t size)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int registry_demarshal_destroy(void *object, void *data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
	struct spa_pod_parser prs;
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
 | 
			
		||||
	spa_pod_parser_init(&prs, data, size, 0);
 | 
			
		||||
	if (spa_pod_parser_get(&prs,
 | 
			
		||||
			"["
 | 
			
		||||
			"i", &id, NULL) < 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	pw_resource_do(resource, struct pw_registry_proxy_methods, destroy, 0, id);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void module_marshal_info(void *object, struct pw_module_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -1127,6 +1143,17 @@ static void registry_marshal_bind(void *object, uint32_t id,
 | 
			
		|||
	pw_protocol_native_end_proxy(proxy, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void registry_marshal_destroy(void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_proxy *proxy = object;
 | 
			
		||||
	struct spa_pod_builder *b;
 | 
			
		||||
 | 
			
		||||
	b = pw_protocol_native_begin_proxy(proxy, PW_REGISTRY_PROXY_METHOD_DESTROY);
 | 
			
		||||
	spa_pod_builder_add_struct(b,
 | 
			
		||||
			       "i", id);
 | 
			
		||||
	pw_protocol_native_end_proxy(proxy, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_core_proxy_methods pw_protocol_native_core_method_marshal = {
 | 
			
		||||
	PW_VERSION_CORE_PROXY_METHODS,
 | 
			
		||||
	&core_marshal_hello,
 | 
			
		||||
| 
						 | 
				
			
			@ -1177,10 +1204,12 @@ static const struct pw_protocol_marshal pw_protocol_native_core_marshal = {
 | 
			
		|||
static const struct pw_registry_proxy_methods pw_protocol_native_registry_method_marshal = {
 | 
			
		||||
	PW_VERSION_REGISTRY_PROXY_METHODS,
 | 
			
		||||
	®istry_marshal_bind,
 | 
			
		||||
	®istry_marshal_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct pw_protocol_native_demarshal pw_protocol_native_registry_method_demarshal[] = {
 | 
			
		||||
	{ ®istry_demarshal_bind, 0, },
 | 
			
		||||
	{ ®istry_demarshal_destroy, 0, },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct pw_registry_proxy_events pw_protocol_native_registry_event_marshal = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -89,9 +89,38 @@ static void registry_bind(void *object, uint32_t id,
 | 
			
		|||
	pw_core_resource_remove_id(client->core_resource, new_id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void registry_destroy(void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
	struct pw_client *client = resource->client;
 | 
			
		||||
	struct pw_core *core = resource->core;
 | 
			
		||||
	struct pw_global *global;
 | 
			
		||||
	uint32_t permissions;
 | 
			
		||||
 | 
			
		||||
	if ((global = pw_core_find_global(core, id)) == NULL)
 | 
			
		||||
		goto no_id;
 | 
			
		||||
 | 
			
		||||
	permissions = pw_global_get_permissions(global, client);
 | 
			
		||||
 | 
			
		||||
	if (!PW_PERM_IS_X(permissions))
 | 
			
		||||
		goto no_id;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("global %p: destroy global id %d", global, id);
 | 
			
		||||
 | 
			
		||||
	pw_global_destroy(global);
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
      no_id:
 | 
			
		||||
	pw_log_debug("registry %p: no global with id %u to destroy", resource, id);
 | 
			
		||||
	goto exit;
 | 
			
		||||
      exit:
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_registry_proxy_methods registry_methods = {
 | 
			
		||||
	PW_VERSION_REGISTRY_PROXY_METHODS,
 | 
			
		||||
	.bind = registry_bind
 | 
			
		||||
	.bind = registry_bind,
 | 
			
		||||
	.destroy = registry_destroy
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void destroy_registry_resource(void *object)
 | 
			
		||||
| 
						 | 
				
			
			@ -254,16 +283,24 @@ core_create_object(void *object,
 | 
			
		|||
static void core_destroy(void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
	struct pw_core *this = resource->core;
 | 
			
		||||
	struct pw_global *global;
 | 
			
		||||
	struct pw_client *client = resource->client;
 | 
			
		||||
	struct pw_resource *r;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("core %p: destroy %d from resource %p", resource->core, id, resource);
 | 
			
		||||
 | 
			
		||||
	global = pw_core_find_global(this, id);
 | 
			
		||||
	if (global == NULL)
 | 
			
		||||
	if ((r = pw_client_find_resource(client, id)) == NULL)
 | 
			
		||||
		goto no_resource;
 | 
			
		||||
 | 
			
		||||
	pw_resource_destroy(r);
 | 
			
		||||
 | 
			
		||||
      done:
 | 
			
		||||
	return;
 | 
			
		||||
 | 
			
		||||
	pw_global_destroy(global);
 | 
			
		||||
      no_resource:
 | 
			
		||||
	pw_log_error("can't find resouce %d", id);
 | 
			
		||||
	pw_core_resource_error(client->core_resource,
 | 
			
		||||
			       resource->id, -EINVAL, "unknown resouce %d", id);
 | 
			
		||||
	goto done;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_core_proxy_methods core_methods = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -259,9 +259,9 @@ void pw_global_destroy(struct pw_global *global)
 | 
			
		|||
{
 | 
			
		||||
	struct pw_core *core = global->core;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("global %p: destroy %u", global, global->id);
 | 
			
		||||
	global_unregister(global);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("global %p: destroy %u", global, global->id);
 | 
			
		||||
	pw_global_events_destroy(global);
 | 
			
		||||
 | 
			
		||||
	pw_map_remove(&core->globals, global->id);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -172,11 +172,12 @@ struct pw_core_proxy_methods {
 | 
			
		|||
			       uint32_t version,
 | 
			
		||||
			       const struct spa_dict *props,
 | 
			
		||||
			       uint32_t new_id);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Destroy an object id
 | 
			
		||||
	 * Destroy an resource
 | 
			
		||||
	 *
 | 
			
		||||
	 * \param id the object id to destroy
 | 
			
		||||
	 * Destroy the server resource with the given proxy id.
 | 
			
		||||
	 *
 | 
			
		||||
	 * \param id the client proxy id to destroy
 | 
			
		||||
	 */
 | 
			
		||||
	void (*destroy) (void *object, uint32_t id);
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -228,9 +229,9 @@ pw_core_proxy_create_object(struct pw_core_proxy *core,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
pw_core_proxy_destroy(struct pw_core_proxy *core, uint32_t id)
 | 
			
		||||
pw_core_proxy_destroy(struct pw_core_proxy *core, struct pw_proxy *proxy)
 | 
			
		||||
{
 | 
			
		||||
	pw_proxy_do((struct pw_proxy*)core, struct pw_core_proxy_methods, destroy, id);
 | 
			
		||||
	pw_proxy_do((struct pw_proxy*)core, struct pw_core_proxy_methods, destroy, pw_proxy_get_id(proxy));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define PW_CORE_PROXY_EVENT_DONE         0
 | 
			
		||||
| 
						 | 
				
			
			@ -336,7 +337,8 @@ pw_core_proxy_add_listener(struct pw_core_proxy *core,
 | 
			
		|||
 * the access permissions on an object.
 | 
			
		||||
 */
 | 
			
		||||
#define PW_REGISTRY_PROXY_METHOD_BIND		0
 | 
			
		||||
#define PW_REGISTRY_PROXY_METHOD_NUM		1
 | 
			
		||||
#define PW_REGISTRY_PROXY_METHOD_DESTROY	1
 | 
			
		||||
#define PW_REGISTRY_PROXY_METHOD_NUM		2
 | 
			
		||||
 | 
			
		||||
/** Registry methods */
 | 
			
		||||
struct pw_registry_proxy_methods {
 | 
			
		||||
| 
						 | 
				
			
			@ -355,6 +357,15 @@ struct pw_registry_proxy_methods {
 | 
			
		|||
	 * \param new_id the client proxy to use
 | 
			
		||||
	 */
 | 
			
		||||
	void (*bind) (void *object, uint32_t id, uint32_t type, uint32_t version, uint32_t new_id);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Attempt to destroy a global object
 | 
			
		||||
	 *
 | 
			
		||||
	 * Try to destroy the global object.
 | 
			
		||||
	 *
 | 
			
		||||
	 * \param id the global id to destroy
 | 
			
		||||
	 */
 | 
			
		||||
	void (*destroy) (void *object, uint32_t id);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Registry */
 | 
			
		||||
| 
						 | 
				
			
			@ -369,6 +380,13 @@ pw_registry_proxy_bind(struct pw_registry_proxy *registry,
 | 
			
		|||
	return p;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static inline void
 | 
			
		||||
pw_registry_proxy_destroy(struct pw_registry_proxy *registry, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_proxy *reg = (struct pw_proxy*)registry;
 | 
			
		||||
	pw_proxy_do(reg, struct pw_registry_proxy_methods, destroy, id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define PW_REGISTRY_PROXY_EVENT_GLOBAL             0
 | 
			
		||||
#define PW_REGISTRY_PROXY_EVENT_GLOBAL_REMOVE      1
 | 
			
		||||
#define PW_REGISTRY_PROXY_EVENT_NUM                2
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1270,8 +1270,9 @@ static void do_node_init(struct pw_proxy *proxy)
 | 
			
		|||
static void node_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct node_data *d = data;
 | 
			
		||||
	struct pw_remote *remote = d->remote;
 | 
			
		||||
	pw_log_debug("%p: destroy", d);
 | 
			
		||||
	pw_client_node_proxy_destroy(d->node_proxy);
 | 
			
		||||
	pw_core_proxy_destroy(remote->core_proxy, (struct pw_proxy *)d->node_proxy);
 | 
			
		||||
	pw_proxy_destroy((struct pw_proxy *)d->node_proxy);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -992,7 +992,7 @@ static bool do_destroy(struct data *data, const char *cmd, char *args, char **er
 | 
			
		|||
		asprintf(error, "%s: unknown global %d", cmd, id);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
	pw_core_proxy_destroy(rd->core_proxy, id);
 | 
			
		||||
	pw_registry_proxy_destroy(rd->registry_proxy, id);
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue