mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	remote: move node export code to client-node module
Make the code to export objects more generic. Make it possible for modules to register a type to export. Make the client-node also able to export plain spa_nodes. Let the remote signal the global of the exported object if any. We can then remote the (unused) remote_id from the proxy.
This commit is contained in:
		
							parent
							
								
									7ec9de5ac6
								
							
						
					
					
						commit
						31dacd9d6f
					
				
					 20 changed files with 1236 additions and 1055 deletions
				
			
		| 
						 | 
					@ -72,7 +72,6 @@ struct data {
 | 
				
			||||||
	struct pw_remote *remote;
 | 
						struct pw_remote *remote;
 | 
				
			||||||
	struct spa_hook remote_listener;
 | 
						struct spa_hook remote_listener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct pw_node *node;
 | 
					 | 
				
			||||||
	struct spa_port_info port_info;
 | 
						struct spa_port_info port_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_node impl_node;
 | 
						struct spa_node impl_node;
 | 
				
			||||||
| 
						 | 
					@ -493,13 +492,8 @@ static void make_node(struct data *data)
 | 
				
			||||||
	pw_properties_set(props, PW_NODE_PROP_CATEGORY, "Capture");
 | 
						pw_properties_set(props, PW_NODE_PROP_CATEGORY, "Capture");
 | 
				
			||||||
	pw_properties_set(props, PW_NODE_PROP_ROLE, "Camera");
 | 
						pw_properties_set(props, PW_NODE_PROP_ROLE, "Camera");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data->node = pw_node_new(data->core, "SDL-sink", props, 0);
 | 
					 | 
				
			||||||
	data->impl_node = impl_node;
 | 
						data->impl_node = impl_node;
 | 
				
			||||||
	pw_node_set_implementation(data->node, &data->impl_node);
 | 
						pw_remote_export(data->remote, SPA_TYPE_INTERFACE_Node, props, &data->impl_node);
 | 
				
			||||||
	pw_node_register(data->node, NULL, NULL, NULL);
 | 
					 | 
				
			||||||
	pw_node_set_active(data->node, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pw_remote_export(data->remote, data->node);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
 | 
					static void on_state_changed(void *_data, enum pw_remote_state old, enum pw_remote_state state, const char *error)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -505,14 +505,8 @@ static void make_node(struct data *data)
 | 
				
			||||||
	if (data->path)
 | 
						if (data->path)
 | 
				
			||||||
		pw_properties_set(props, PW_NODE_PROP_TARGET_NODE, data->path);
 | 
							pw_properties_set(props, PW_NODE_PROP_TARGET_NODE, data->path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	data->node = pw_node_new(data->core, "export-source", props, 0);
 | 
					 | 
				
			||||||
	data->impl_node = impl_node;
 | 
						data->impl_node = impl_node;
 | 
				
			||||||
	pw_node_set_implementation(data->node, &data->impl_node);
 | 
						pw_remote_export(data->remote, SPA_TYPE_INTERFACE_Node, props, &data->impl_node);
 | 
				
			||||||
 | 
					 | 
				
			||||||
	pw_node_register(data->node, NULL, NULL, NULL);
 | 
					 | 
				
			||||||
	pw_node_set_active(data->node, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	pw_remote_export(data->remote, data->node);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void on_state_changed(void *_data, enum pw_remote_state old,
 | 
					static void on_state_changed(void *_data, enum pw_remote_state old,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,7 @@ static int make_node(struct data *data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_node_set_active(data->node, true);
 | 
						pw_node_set_active(data->node, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_remote_export(data->remote, data->node);
 | 
						pw_remote_export(data->remote, PW_TYPE_INTERFACE_Node, NULL, data->node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,6 +38,8 @@ struct pw_client_node_proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PW_VERSION_CLIENT_NODE			0
 | 
					#define PW_VERSION_CLIENT_NODE			0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define PW_EXTENSION_MODULE_CLIENT_NODE		PIPEWIRE_MODULE_PREFIX "module-client-node"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** information about a buffer */
 | 
					/** information about a buffer */
 | 
				
			||||||
struct pw_client_node_buffer {
 | 
					struct pw_client_node_buffer {
 | 
				
			||||||
	uint32_t mem_id;		/**< the memory id for the metadata */
 | 
						uint32_t mem_id;		/**< the memory id for the metadata */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,6 +25,7 @@ endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pipewire_module_client_node = shared_library('pipewire-module-client-node',
 | 
					pipewire_module_client_node = shared_library('pipewire-module-client-node',
 | 
				
			||||||
  [ 'module-client-node.c',
 | 
					  [ 'module-client-node.c',
 | 
				
			||||||
 | 
					    'module-client-node/remote-node.c',
 | 
				
			||||||
    'module-client-node/client-node.c',
 | 
					    'module-client-node/client-node.c',
 | 
				
			||||||
    'module-client-node/client-stream.c',
 | 
					    'module-client-node/client-stream.c',
 | 
				
			||||||
    'module-client-node/protocol-native.c',
 | 
					    'module-client-node/protocol-native.c',
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,6 +40,11 @@ static const struct spa_dict_item module_props[] = {
 | 
				
			||||||
	{ PW_MODULE_PROP_VERSION, PACKAGE_VERSION },
 | 
						{ PW_MODULE_PROP_VERSION, PACKAGE_VERSION },
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					struct pw_proxy *pw_remote_node_export(struct pw_remote *remote,
 | 
				
			||||||
 | 
							uint32_t type, struct pw_properties *props, void *object);
 | 
				
			||||||
 | 
					struct pw_proxy *pw_remote_spa_node_export(struct pw_remote *remote,
 | 
				
			||||||
 | 
							uint32_t type, struct pw_properties *props, void *object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct pw_protocol *pw_protocol_native_ext_client_node_init(struct pw_core *core);
 | 
					struct pw_protocol *pw_protocol_native_ext_client_node_init(struct pw_core *core);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct factory_data {
 | 
					struct factory_data {
 | 
				
			||||||
| 
						 | 
					@ -48,6 +53,9 @@ struct factory_data {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct pw_module *module;
 | 
						struct pw_module *module;
 | 
				
			||||||
	struct spa_hook module_listener;
 | 
						struct spa_hook module_listener;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct pw_export_type export_node;
 | 
				
			||||||
 | 
						struct pw_export_type export_spanode;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void *create_object(void *_data,
 | 
					static void *create_object(void *_data,
 | 
				
			||||||
| 
						 | 
					@ -103,6 +111,9 @@ static void module_destroy(void *data)
 | 
				
			||||||
	if (d->properties)
 | 
						if (d->properties)
 | 
				
			||||||
		pw_properties_free(d->properties);
 | 
							pw_properties_free(d->properties);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_list_remove(&d->export_node.link);
 | 
				
			||||||
 | 
						spa_list_remove(&d->export_spanode.link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_factory_destroy(d->this);
 | 
						pw_factory_destroy(d->this);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -141,6 +152,14 @@ static int module_init(struct pw_module *module, struct pw_properties *propertie
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_factory_register(factory, NULL, pw_module_get_global(module), NULL);
 | 
						pw_factory_register(factory, NULL, pw_module_get_global(module), NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data->export_node.type = PW_TYPE_INTERFACE_Node;
 | 
				
			||||||
 | 
						data->export_node.func = pw_remote_node_export;
 | 
				
			||||||
 | 
						pw_core_register_export_type(core, &data->export_node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data->export_spanode.type = SPA_TYPE_INTERFACE_Node;
 | 
				
			||||||
 | 
						data->export_spanode.func = pw_remote_spa_node_export;
 | 
				
			||||||
 | 
						pw_core_register_export_type(core, &data->export_spanode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_module_add_listener(module, &data->module_listener, &module_events, data);
 | 
						pw_module_add_listener(module, &data->module_listener, &module_events, data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
 | 
						pw_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										1093
									
								
								src/modules/module-client-node/remote-node.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1093
									
								
								src/modules/module-client-node/remote-node.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -445,6 +445,7 @@ struct pw_core *pw_core_new(struct pw_loop *main_loop,
 | 
				
			||||||
	spa_list_init(&this->link_list);
 | 
						spa_list_init(&this->link_list);
 | 
				
			||||||
	spa_list_init(&this->control_list[0]);
 | 
						spa_list_init(&this->control_list[0]);
 | 
				
			||||||
	spa_list_init(&this->control_list[1]);
 | 
						spa_list_init(&this->control_list[1]);
 | 
				
			||||||
 | 
						spa_list_init(&this->export_list);
 | 
				
			||||||
	spa_hook_list_init(&this->listener_list);
 | 
						spa_hook_list_init(&this->listener_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((name = pw_properties_get(properties, PW_CORE_PROP_NAME)) == NULL) {
 | 
						if ((name = pw_properties_get(properties, PW_CORE_PROP_NAME)) == NULL) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -116,8 +116,6 @@ struct pw_core_proxy_methods {
 | 
				
			||||||
	void (*get_registry) (void *object, uint32_t version, uint32_t new_id);
 | 
						void (*get_registry) (void *object, uint32_t version, uint32_t new_id);
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
	 * Create a new object on the PipeWire server from a factory.
 | 
						 * Create a new object on the PipeWire server from a factory.
 | 
				
			||||||
	 * Use a \a factory_name of "client-node" to create a
 | 
					 | 
				
			||||||
	 * \ref pw_client_node.
 | 
					 | 
				
			||||||
	 *
 | 
						 *
 | 
				
			||||||
	 * \param factory_name the factory name to use
 | 
						 * \param factory_name the factory name to use
 | 
				
			||||||
	 * \param type the interface to bind to
 | 
						 * \param type the interface to bind to
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -35,6 +35,7 @@ extern "C" {
 | 
				
			||||||
#include <pipewire/core.h>
 | 
					#include <pipewire/core.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PIPEWIRE_SYMBOL_MODULE_INIT "pipewire__module_init"
 | 
					#define PIPEWIRE_SYMBOL_MODULE_INIT "pipewire__module_init"
 | 
				
			||||||
 | 
					#define PIPEWIRE_MODULE_PREFIX "libpipewire-"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** \class pw_module
 | 
					/** \class pw_module
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -655,6 +655,9 @@ struct pw_node *pw_node_new(struct pw_core *core,
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (name == NULL)
 | 
				
			||||||
 | 
							name = "node";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this = &impl->this;
 | 
						this = &impl->this;
 | 
				
			||||||
	this->core = core;
 | 
						this->core = core;
 | 
				
			||||||
	pw_log_debug("node %p: new \"%s\"", this, name);
 | 
						pw_log_debug("node %p: new \"%s\"", this, name);
 | 
				
			||||||
| 
						 | 
					@ -687,7 +690,6 @@ struct pw_node *pw_node_new(struct pw_core *core,
 | 
				
			||||||
	spa_list_init(&this->output_ports);
 | 
						spa_list_init(&this->output_ports);
 | 
				
			||||||
	pw_map_init(&this->output_port_map, 64, 64);
 | 
						pw_map_init(&this->output_port_map, 64, 64);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	spa_graph_init(&impl->driver_graph, &impl->driver_state);
 | 
						spa_graph_init(&impl->driver_graph, &impl->driver_state);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->rt.driver = &impl->driver_graph;
 | 
						this->rt.driver = &impl->driver_graph;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -150,6 +150,19 @@ static int schedule_mix_input(struct spa_node *data)
 | 
				
			||||||
        return SPA_STATUS_HAVE_BUFFER | SPA_STATUS_NEED_BUFFER;
 | 
					        return SPA_STATUS_HAVE_BUFFER | SPA_STATUS_NEED_BUFFER;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int schedule_mix_port_set_param(struct spa_node *data,
 | 
				
			||||||
 | 
							enum spa_direction direction, uint32_t port_id,
 | 
				
			||||||
 | 
							uint32_t id, uint32_t flags,
 | 
				
			||||||
 | 
							const struct spa_pod *param)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						switch (id) {
 | 
				
			||||||
 | 
						case SPA_PARAM_Format:
 | 
				
			||||||
 | 
							pw_log_debug("port %d:%d: set format", direction, port_id);
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int schedule_mix_reuse_buffer(struct spa_node *data, uint32_t port_id, uint32_t buffer_id)
 | 
					static int schedule_mix_reuse_buffer(struct spa_node *data, uint32_t port_id, uint32_t buffer_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(data, struct impl, mix_node);
 | 
						struct impl *impl = SPA_CONTAINER_OF(data, struct impl, mix_node);
 | 
				
			||||||
| 
						 | 
					@ -170,6 +183,7 @@ static const struct spa_node schedule_mix_node = {
 | 
				
			||||||
	SPA_VERSION_NODE,
 | 
						SPA_VERSION_NODE,
 | 
				
			||||||
	NULL,
 | 
						NULL,
 | 
				
			||||||
	.process = schedule_mix_input,
 | 
						.process = schedule_mix_input,
 | 
				
			||||||
 | 
						.port_set_param = schedule_mix_port_set_param,
 | 
				
			||||||
	.port_reuse_buffer = schedule_mix_reuse_buffer,
 | 
						.port_reuse_buffer = schedule_mix_reuse_buffer,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -181,6 +181,7 @@ struct pw_core {
 | 
				
			||||||
	struct spa_list factory_list;		/**< list of factories */
 | 
						struct spa_list factory_list;		/**< list of factories */
 | 
				
			||||||
	struct spa_list link_list;		/**< list of links */
 | 
						struct spa_list link_list;		/**< list of links */
 | 
				
			||||||
	struct spa_list control_list[2];	/**< list of controls, indexed by direction */
 | 
						struct spa_list control_list[2];	/**< list of controls, indexed by direction */
 | 
				
			||||||
 | 
						struct spa_list export_list;		/**< list of export types */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_hook_list listener_list;
 | 
						struct spa_hook_list listener_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -537,7 +538,6 @@ struct pw_proxy {
 | 
				
			||||||
	struct spa_list link;		/**< link in the remote */
 | 
						struct spa_list link;		/**< link in the remote */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t id;			/**< client side id */
 | 
						uint32_t id;			/**< client side id */
 | 
				
			||||||
	uint32_t remote_id;		/**< remote id */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct spa_hook_list listener_list;
 | 
						struct spa_hook_list listener_list;
 | 
				
			||||||
	struct spa_hook_list proxy_listener_list;
 | 
						struct spa_hook_list proxy_listener_list;
 | 
				
			||||||
| 
						 | 
					@ -550,7 +550,7 @@ struct pw_proxy {
 | 
				
			||||||
#define pw_remote_events_emit(r,m,v,...) spa_hook_list_call(&r->listener_list, struct pw_remote_events, m, v, ##__VA_ARGS__)
 | 
					#define pw_remote_events_emit(r,m,v,...) spa_hook_list_call(&r->listener_list, struct pw_remote_events, m, v, ##__VA_ARGS__)
 | 
				
			||||||
#define pw_remote_events_destroy(r)		pw_remote_events_emit(r, destroy, 0)
 | 
					#define pw_remote_events_destroy(r)		pw_remote_events_emit(r, destroy, 0)
 | 
				
			||||||
#define pw_remote_events_state_changed(r,o,s,e)	pw_remote_events_emit(r, state_changed, 0, o, s, e)
 | 
					#define pw_remote_events_state_changed(r,o,s,e)	pw_remote_events_emit(r, state_changed, 0, o, s, e)
 | 
				
			||||||
#define pw_remote_events_exported(r,i)		pw_remote_events_emit(r, exported, 0, i)
 | 
					#define pw_remote_events_exported(r,i,g)	pw_remote_events_emit(r, exported, 0, i,g)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct pw_remote {
 | 
					struct pw_remote {
 | 
				
			||||||
	struct pw_core *core;			/**< core */
 | 
						struct pw_core *core;			/**< core */
 | 
				
			||||||
| 
						 | 
					@ -676,6 +676,8 @@ pw_core_find_port(struct pw_core *core,
 | 
				
			||||||
		  struct spa_pod **format_filters,
 | 
							  struct spa_pod **format_filters,
 | 
				
			||||||
		  char **error);
 | 
							  char **error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const struct pw_export_type *pw_core_find_export_type(struct pw_core *core, uint32_t type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Create a new port \memberof pw_port
 | 
					/** Create a new port \memberof pw_port
 | 
				
			||||||
 * \return a newly allocated port */
 | 
					 * \return a newly allocated port */
 | 
				
			||||||
struct pw_port *
 | 
					struct pw_port *
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,6 @@ struct pw_proxy *pw_proxy_new(struct pw_proxy *factory,
 | 
				
			||||||
	spa_hook_list_init(&this->proxy_listener_list);
 | 
						spa_hook_list_init(&this->proxy_listener_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->id = pw_map_insert_new(&remote->objects, this);
 | 
						this->id = pw_map_insert_new(&remote->objects, this);
 | 
				
			||||||
	this->remote_id = SPA_ID_INVALID;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (user_data_size > 0)
 | 
						if (user_data_size > 0)
 | 
				
			||||||
		this->user_data = SPA_MEMBER(impl, sizeof(struct proxy), void);
 | 
							this->user_data = SPA_MEMBER(impl, sizeof(struct proxy), void);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
					@ -138,7 +138,7 @@ struct pw_remote_events {
 | 
				
			||||||
	void (*state_changed) (void *data, enum pw_remote_state old,
 | 
						void (*state_changed) (void *data, enum pw_remote_state old,
 | 
				
			||||||
			       enum pw_remote_state state, const char *error);
 | 
								       enum pw_remote_state state, const char *error);
 | 
				
			||||||
        /** emited when a node was exported */
 | 
					        /** emited when a node was exported */
 | 
				
			||||||
	void (*exported) (void *data, uint32_t id);
 | 
						void (*exported) (void *data, uint32_t proxy_id, uint32_t global_id);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** Specify the name of the protocol to use, default is using the native protocol */
 | 
					/** Specify the name of the protocol to use, default is using the native protocol */
 | 
				
			||||||
| 
						 | 
					@ -203,7 +203,22 @@ struct pw_proxy *pw_remote_find_proxy(struct pw_remote *remote, uint32_t id);
 | 
				
			||||||
int pw_remote_disconnect(struct pw_remote *remote);
 | 
					int pw_remote_disconnect(struct pw_remote *remote);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** run a local node in a remote graph */
 | 
					/** run a local node in a remote graph */
 | 
				
			||||||
struct pw_proxy *pw_remote_export(struct pw_remote *remote, struct pw_node *node);
 | 
					struct pw_proxy *pw_remote_export(struct pw_remote *remote,		/**< the remote */
 | 
				
			||||||
 | 
									  uint32_t type,			/**< the type of object */
 | 
				
			||||||
 | 
									  struct pw_properties *properties,	/**< extra properties */
 | 
				
			||||||
 | 
									  void *object				/**< object to export */);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** data for registering export functions */
 | 
				
			||||||
 | 
					struct pw_export_type {
 | 
				
			||||||
 | 
						struct spa_list link;
 | 
				
			||||||
 | 
						uint32_t type;
 | 
				
			||||||
 | 
						struct pw_proxy * (*func) (struct pw_remote *remote,
 | 
				
			||||||
 | 
					                uint32_t type, struct pw_properties *properties, void *object);
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** register a type that can be exported on a remote. This is usually used by
 | 
				
			||||||
 | 
					 * extension modules */
 | 
				
			||||||
 | 
					int pw_core_register_export_type(struct pw_core *core, struct pw_export_type *type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,7 +41,6 @@
 | 
				
			||||||
#include "pipewire/pipewire.h"
 | 
					#include "pipewire/pipewire.h"
 | 
				
			||||||
#include "pipewire/stream.h"
 | 
					#include "pipewire/stream.h"
 | 
				
			||||||
#include "pipewire/private.h"
 | 
					#include "pipewire/private.h"
 | 
				
			||||||
#include "extensions/client-node.h"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_BUFFERS	64
 | 
					#define MAX_BUFFERS	64
 | 
				
			||||||
#define MIN_QUEUED	1
 | 
					#define MIN_QUEUED	1
 | 
				
			||||||
| 
						 | 
					@ -195,8 +194,10 @@ static inline struct buffer *pop_queue(struct stream *stream, struct queue *queu
 | 
				
			||||||
	uint32_t index, id;
 | 
						uint32_t index, id;
 | 
				
			||||||
	struct buffer *buffer;
 | 
						struct buffer *buffer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((avail = spa_ringbuffer_get_read_index(&queue->ring, &index)) < MIN_QUEUED)
 | 
						if ((avail = spa_ringbuffer_get_read_index(&queue->ring, &index)) < MIN_QUEUED) {
 | 
				
			||||||
 | 
							errno = EPIPE;
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	id = queue->ids[index & MASK_BUFFERS];
 | 
						id = queue->ids[index & MASK_BUFFERS];
 | 
				
			||||||
	spa_ringbuffer_read_update(&queue->ring, index + 1);
 | 
						spa_ringbuffer_read_update(&queue->ring, index + 1);
 | 
				
			||||||
| 
						 | 
					@ -236,6 +237,8 @@ static struct buffer *get_buffer(struct pw_stream *stream, uint32_t id)
 | 
				
			||||||
	struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
 | 
						struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this);
 | 
				
			||||||
	if (id < impl->n_buffers)
 | 
						if (id < impl->n_buffers)
 | 
				
			||||||
		return &impl->buffers[id];
 | 
							return &impl->buffers[id];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						errno = EINVAL;
 | 
				
			||||||
	return NULL;
 | 
						return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -806,6 +809,7 @@ static void proxy_destroy(void *_data)
 | 
				
			||||||
	struct pw_stream *stream = _data;
 | 
						struct pw_stream *stream = _data;
 | 
				
			||||||
	stream->proxy = NULL;
 | 
						stream->proxy = NULL;
 | 
				
			||||||
	spa_hook_remove(&stream->proxy_listener);
 | 
						spa_hook_remove(&stream->proxy_listener);
 | 
				
			||||||
 | 
						stream->node_id = SPA_ID_INVALID;
 | 
				
			||||||
	stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, NULL);
 | 
						stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, NULL);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -821,6 +825,9 @@ static int handle_connect(struct pw_stream *stream)
 | 
				
			||||||
	pw_log_debug("stream %p: creating node", stream);
 | 
						pw_log_debug("stream %p: creating node", stream);
 | 
				
			||||||
	impl->node = pw_node_new(impl->core, stream->name,
 | 
						impl->node = pw_node_new(impl->core, stream->name,
 | 
				
			||||||
			pw_properties_copy(stream->properties), 0);
 | 
								pw_properties_copy(stream->properties), 0);
 | 
				
			||||||
 | 
						if (impl->node == NULL)
 | 
				
			||||||
 | 
							goto no_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl->impl_node = impl_node;
 | 
						impl->impl_node = impl_node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->direction == SPA_DIRECTION_INPUT)
 | 
						if (impl->direction == SPA_DIRECTION_INPUT)
 | 
				
			||||||
| 
						 | 
					@ -835,10 +842,21 @@ static int handle_connect(struct pw_stream *stream)
 | 
				
			||||||
		pw_node_set_active(impl->node, true);
 | 
							pw_node_set_active(impl->node, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug("stream %p: export node %p", stream, impl->node);
 | 
						pw_log_debug("stream %p: export node %p", stream, impl->node);
 | 
				
			||||||
	stream->proxy = pw_remote_export(stream->remote, impl->node);
 | 
						stream->proxy = pw_remote_export(stream->remote,
 | 
				
			||||||
 | 
								PW_TYPE_INTERFACE_Node, NULL, impl->node);
 | 
				
			||||||
 | 
						if (stream->proxy == NULL)
 | 
				
			||||||
 | 
							goto no_proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_proxy_add_listener(stream->proxy, &stream->proxy_listener, &proxy_events, stream);
 | 
						pw_proxy_add_listener(stream->proxy, &stream->proxy_listener, &proxy_events, stream);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    no_node:
 | 
				
			||||||
 | 
						pw_log_error("stream %p: can't make node: %m", stream);
 | 
				
			||||||
 | 
						return -errno;
 | 
				
			||||||
 | 
					    no_proxy:
 | 
				
			||||||
 | 
						pw_log_error("stream %p: can't make proxy: %m", stream);
 | 
				
			||||||
 | 
						return -errno;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void on_remote_state_changed(void *_data, enum pw_remote_state old,
 | 
					static void on_remote_state_changed(void *_data, enum pw_remote_state old,
 | 
				
			||||||
| 
						 | 
					@ -866,12 +884,15 @@ static void on_remote_state_changed(void *_data, enum pw_remote_state old,
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static void on_remote_exported(void *_data, uint32_t id)
 | 
					
 | 
				
			||||||
 | 
					static void on_remote_exported(void *_data, uint32_t proxy_id, uint32_t global_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct pw_stream *stream = _data;
 | 
						struct pw_stream *stream = _data;
 | 
				
			||||||
	if (stream->proxy && stream->proxy->id == id)
 | 
						if (stream->proxy && stream->proxy->id == proxy_id) {
 | 
				
			||||||
 | 
							stream->node_id = global_id;
 | 
				
			||||||
		stream_set_state(stream, PW_STREAM_STATE_CONFIGURE, NULL);
 | 
							stream_set_state(stream, PW_STREAM_STATE_CONFIGURE, NULL);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct pw_remote_events remote_events = {
 | 
					static const struct pw_remote_events remote_events = {
 | 
				
			||||||
	PW_VERSION_REMOTE_EVENTS,
 | 
						PW_VERSION_REMOTE_EVENTS,
 | 
				
			||||||
| 
						 | 
					@ -916,6 +937,7 @@ struct pw_stream * pw_stream_new(struct pw_remote *remote, const char *name,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this->remote = remote;
 | 
						this->remote = remote;
 | 
				
			||||||
	this->name = name ? strdup(name) : NULL;
 | 
						this->name = name ? strdup(name) : NULL;
 | 
				
			||||||
 | 
						this->node_id = SPA_ID_INVALID;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	reset_props(&impl->props);
 | 
						reset_props(&impl->props);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1146,9 +1168,7 @@ pw_stream_connect(struct pw_stream *stream,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint32_t pw_stream_get_node_id(struct pw_stream *stream)
 | 
					uint32_t pw_stream_get_node_id(struct pw_stream *stream)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	if (stream->proxy == NULL)
 | 
						return stream->node_id;
 | 
				
			||||||
		return SPA_ID_INVALID;
 | 
					 | 
				
			||||||
	return stream->proxy->remote_id;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pw_stream_disconnect(struct pw_stream *stream)
 | 
					int pw_stream_disconnect(struct pw_stream *stream)
 | 
				
			||||||
| 
						 | 
					@ -1165,6 +1185,7 @@ int pw_stream_disconnect(struct pw_stream *stream)
 | 
				
			||||||
	if (stream->proxy) {
 | 
						if (stream->proxy) {
 | 
				
			||||||
		stream->proxy = NULL;
 | 
							stream->proxy = NULL;
 | 
				
			||||||
		spa_hook_remove(&stream->proxy_listener);
 | 
							spa_hook_remove(&stream->proxy_listener);
 | 
				
			||||||
 | 
							stream->node_id = SPA_ID_INVALID;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, NULL);
 | 
						stream_set_state(stream, PW_STREAM_STATE_UNCONNECTED, NULL);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -1277,6 +1298,7 @@ struct pw_buffer *pw_stream_dequeue_buffer(struct pw_stream *stream)
 | 
				
			||||||
	if ((b = pop_queue(impl, &impl->dequeued)) == NULL) {
 | 
						if ((b = pop_queue(impl, &impl->dequeued)) == NULL) {
 | 
				
			||||||
		pw_log_trace("stream %p: no more buffers", stream);
 | 
							pw_log_trace("stream %p: no more buffers", stream);
 | 
				
			||||||
		call_trigger(impl);
 | 
							call_trigger(impl);
 | 
				
			||||||
 | 
							errno = EPIPE;
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	pw_log_trace("stream %p: dequeue buffer %d", stream, b->id);
 | 
						pw_log_trace("stream %p: dequeue buffer %d", stream, b->id);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -34,6 +34,7 @@ extern "C" {
 | 
				
			||||||
enum {
 | 
					enum {
 | 
				
			||||||
	PW_TYPE_FIRST = SPA_TYPE_VENDOR_PipeWire,
 | 
						PW_TYPE_FIRST = SPA_TYPE_VENDOR_PipeWire,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_TYPE_INTERFACE_START = PW_TYPE_FIRST + SPA_TYPE_INTERFACE_START,
 | 
				
			||||||
	PW_TYPE_INTERFACE_Core,
 | 
						PW_TYPE_INTERFACE_Core,
 | 
				
			||||||
	PW_TYPE_INTERFACE_Registry,
 | 
						PW_TYPE_INTERFACE_Registry,
 | 
				
			||||||
	PW_TYPE_INTERFACE_Node,
 | 
						PW_TYPE_INTERFACE_Node,
 | 
				
			||||||
| 
						 | 
					@ -42,9 +43,12 @@ enum {
 | 
				
			||||||
	PW_TYPE_INTERFACE_Link,
 | 
						PW_TYPE_INTERFACE_Link,
 | 
				
			||||||
	PW_TYPE_INTERFACE_Client,
 | 
						PW_TYPE_INTERFACE_Client,
 | 
				
			||||||
	PW_TYPE_INTERFACE_Module,
 | 
						PW_TYPE_INTERFACE_Module,
 | 
				
			||||||
	PW_TYPE_INTERFACE_ClientNode,
 | 
					 | 
				
			||||||
	PW_TYPE_INTERFACE_Device,
 | 
						PW_TYPE_INTERFACE_Device,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* extensions */
 | 
				
			||||||
 | 
						PW_TYPE_INTERFACE_EXTENSIONS = PW_TYPE_INTERFACE_START + 0x1000,
 | 
				
			||||||
 | 
						PW_TYPE_INTERFACE_ClientNode,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PW_TYPE_INFO_BASE		"PipeWire:"
 | 
					#define PW_TYPE_INFO_BASE		"PipeWire:"
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -40,7 +40,7 @@ static void test_abi(void)
 | 
				
			||||||
		void (*destroy) (void *data);
 | 
							void (*destroy) (void *data);
 | 
				
			||||||
		void (*state_changed) (void *data, enum pw_remote_state old,
 | 
							void (*state_changed) (void *data, enum pw_remote_state old,
 | 
				
			||||||
				enum pw_remote_state state, const char *error);
 | 
									enum pw_remote_state state, const char *error);
 | 
				
			||||||
		void (*exported) (void *data, uint32_t id);
 | 
							void (*exported) (void *data, uint32_t proxy_id, uint32_t remote_id);
 | 
				
			||||||
	} test = { PW_VERSION_REMOTE_EVENTS, NULL };
 | 
						} test = { PW_VERSION_REMOTE_EVENTS, NULL };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	TEST_FUNC(ev, test, destroy);
 | 
						TEST_FUNC(ev, test, destroy);
 | 
				
			||||||
| 
						 | 
					@ -70,7 +70,7 @@ static void remote_state_changed_error(void *data, enum pw_remote_state old,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	spa_assert_not_reached();
 | 
						spa_assert_not_reached();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
static void remote_exported_error(void *data, uint32_t id)
 | 
					static void remote_exported_error(void *data, uint32_t proxy_id, uint32_t global_id)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	spa_assert_not_reached();
 | 
						spa_assert_not_reached();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1149,7 +1149,7 @@ static bool do_export_node(struct data *data, const char *cmd, char *args, char
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	node = pw_global_get_object(global);
 | 
						node = pw_global_get_object(global);
 | 
				
			||||||
	proxy = pw_remote_export(rd->remote, node);
 | 
						proxy = pw_remote_export(rd->remote, PW_TYPE_INTERFACE_Node, NULL, node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	id = pw_map_insert_new(&data->vars, proxy);
 | 
						id = pw_map_insert_new(&data->vars, proxy);
 | 
				
			||||||
	fprintf(stdout, "%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy));
 | 
						fprintf(stdout, "%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy));
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue