mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	Add create_link message
Add create_link for completeness Add some more docs
This commit is contained in:
		
							parent
							
								
									6a3b5b1bf7
								
							
						
					
					
						commit
						e48c361a66
					
				
					 12 changed files with 329 additions and 64 deletions
				
			
		| 
						 | 
				
			
			@ -153,11 +153,11 @@ core_event_update_types(void *object, uint32_t first_id, uint32_t n_types, const
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_core_events core_events = {
 | 
			
		||||
	&core_event_info,
 | 
			
		||||
	&core_event_update_types,
 | 
			
		||||
	&core_event_done,
 | 
			
		||||
	&core_event_error,
 | 
			
		||||
	&core_event_remove_id,
 | 
			
		||||
	&core_event_update_types
 | 
			
		||||
	&core_event_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void module_event_info(void *object, struct pw_module_info *info)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,6 +47,16 @@ extern "C" {
 | 
			
		|||
 * The most convenient way to deal with the asynchronous calls is probably
 | 
			
		||||
 * with the thread loop (See \subpage page_thread_loop for more details).
 | 
			
		||||
 *
 | 
			
		||||
 * \subsection ssec_client_api_context_proxy Proxy
 | 
			
		||||
 *
 | 
			
		||||
 * Proxies are client side representations of server side resources. They
 | 
			
		||||
 * allow communication between client and server objects.
 | 
			
		||||
 *
 | 
			
		||||
 * The context maintains a list of all proxies, including a core proxy
 | 
			
		||||
 * object and a registry object.
 | 
			
		||||
 *
 | 
			
		||||
 * See also \subpage page_proxy
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_client_api_context Context
 | 
			
		||||
 *
 | 
			
		||||
 * \subsection ssec_context_create Create
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,7 +33,7 @@ extern "C" {
 | 
			
		|||
#include <pipewire/client/introspect.h>
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \page page_pipewire The PipeWire protocol
 | 
			
		||||
 * \page page_pipewire_protocol The PipeWire protocol
 | 
			
		||||
 * \section page_ifaces_pipewire Interfaces
 | 
			
		||||
 * - \subpage page_iface_pw_core - core global object
 | 
			
		||||
 * - \subpage page_iface_pw_registry - global registry object
 | 
			
		||||
| 
						 | 
				
			
			@ -48,13 +48,14 @@ extern "C" {
 | 
			
		|||
 * \section page_iface_pw_core API
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#define PW_CORE_METHOD_CLIENT_UPDATE		0
 | 
			
		||||
#define PW_CORE_METHOD_UPDATE_TYPES		0
 | 
			
		||||
#define PW_CORE_METHOD_SYNC			1
 | 
			
		||||
#define PW_CORE_METHOD_GET_REGISTRY		2
 | 
			
		||||
#define PW_CORE_METHOD_CREATE_NODE		3
 | 
			
		||||
#define PW_CORE_METHOD_CREATE_CLIENT_NODE	4
 | 
			
		||||
#define PW_CORE_METHOD_UPDATE_TYPES		5
 | 
			
		||||
#define PW_CORE_METHOD_NUM			6
 | 
			
		||||
#define PW_CORE_METHOD_CLIENT_UPDATE		3
 | 
			
		||||
#define PW_CORE_METHOD_CREATE_NODE		4
 | 
			
		||||
#define PW_CORE_METHOD_CREATE_CLIENT_NODE	5
 | 
			
		||||
#define PW_CORE_METHOD_CREATE_LINK		6
 | 
			
		||||
#define PW_CORE_METHOD_NUM			7
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * \struct pw_core_methods
 | 
			
		||||
| 
						 | 
				
			
			@ -66,10 +67,18 @@ extern "C" {
 | 
			
		|||
 */
 | 
			
		||||
struct pw_core_methods {
 | 
			
		||||
	/**
 | 
			
		||||
	 * Update the client properties
 | 
			
		||||
	 * \param props the new client properties
 | 
			
		||||
	 * Update the type map
 | 
			
		||||
	 *
 | 
			
		||||
	 * Send a type map update to the PipeWire server. The server uses this
 | 
			
		||||
	 * information to keep a mapping between client types and the server types.
 | 
			
		||||
	 * \param first_id the id of the first type
 | 
			
		||||
	 * \param n_types the number of types
 | 
			
		||||
	 * \param types the types as a string
 | 
			
		||||
	 */
 | 
			
		||||
	void (*client_update) (void *object, const struct spa_dict *props);
 | 
			
		||||
	void (*update_types) (void *object,
 | 
			
		||||
			      uint32_t first_id,
 | 
			
		||||
			      uint32_t n_types,
 | 
			
		||||
			      const char **types);
 | 
			
		||||
	/**
 | 
			
		||||
	 * Do server roundtrip
 | 
			
		||||
	 *
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +97,11 @@ struct pw_core_methods {
 | 
			
		|||
	 * \param id the client proxy id
 | 
			
		||||
	 */
 | 
			
		||||
	void (*get_registry) (void *object, uint32_t new_id);
 | 
			
		||||
	/**
 | 
			
		||||
	 * Update the client properties
 | 
			
		||||
	 * \param props the new client properties
 | 
			
		||||
	 */
 | 
			
		||||
	void (*client_update) (void *object, const struct spa_dict *props);
 | 
			
		||||
	/**
 | 
			
		||||
	 * Create a new node on the PipeWire server from a factory
 | 
			
		||||
	 *
 | 
			
		||||
| 
						 | 
				
			
			@ -114,32 +128,39 @@ struct pw_core_methods {
 | 
			
		|||
				    const struct spa_dict *props,
 | 
			
		||||
				    uint32_t new_id);
 | 
			
		||||
	/**
 | 
			
		||||
	 * Update the type map
 | 
			
		||||
	 * Create a new link between two node ports
 | 
			
		||||
	 *
 | 
			
		||||
	 * Send a type map update to the PipeWire server. The server uses this
 | 
			
		||||
	 * information to keep a mapping between client types and the server types.
 | 
			
		||||
	 * \param first_id the id of the first type
 | 
			
		||||
	 * \param n_types the number of types
 | 
			
		||||
	 * \param types the types as a string
 | 
			
		||||
	 * \param output_node_id the global id of the output node
 | 
			
		||||
	 * \param output_port_id the id of the output port
 | 
			
		||||
	 * \param input_node_id the global id of the input node
 | 
			
		||||
	 * \param input_port_id the id of the input port
 | 
			
		||||
	 * \param filter an optional format filter
 | 
			
		||||
	 * \param props optional properties
 | 
			
		||||
	 * \param new_id the client proxy id
 | 
			
		||||
	 */
 | 
			
		||||
	void (*update_types) (void *object,
 | 
			
		||||
			      uint32_t first_id,
 | 
			
		||||
			      uint32_t n_types,
 | 
			
		||||
			      const char **types);
 | 
			
		||||
	void (*create_link) (void *object,
 | 
			
		||||
			     uint32_t output_node_id,
 | 
			
		||||
			     uint32_t output_port_id,
 | 
			
		||||
			     uint32_t input_node_id,
 | 
			
		||||
			     uint32_t input_port_id,
 | 
			
		||||
			     const struct spa_format *filter,
 | 
			
		||||
			     const struct spa_dict *props,
 | 
			
		||||
			     uint32_t new_id);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define pw_core_do_client_update(r,...)      ((struct pw_core_methods*)r->iface->methods)->client_update(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_do_update_types(r,...)       ((struct pw_core_methods*)r->iface->methods)->update_types(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_do_sync(r,...)               ((struct pw_core_methods*)r->iface->methods)->sync(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_do_get_registry(r,...)       ((struct pw_core_methods*)r->iface->methods)->get_registry(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_do_client_update(r,...)      ((struct pw_core_methods*)r->iface->methods)->client_update(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_do_create_node(r,...)        ((struct pw_core_methods*)r->iface->methods)->create_node(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_do_create_client_node(r,...) ((struct pw_core_methods*)r->iface->methods)->create_client_node(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_do_update_types(r,...)       ((struct pw_core_methods*)r->iface->methods)->update_types(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_do_create_link(r,...)        ((struct pw_core_methods*)r->iface->methods)->create_link(r,__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
#define PW_CORE_EVENT_INFO         0
 | 
			
		||||
#define PW_CORE_EVENT_UPDATE_TYPES 0
 | 
			
		||||
#define PW_CORE_EVENT_DONE         1
 | 
			
		||||
#define PW_CORE_EVENT_ERROR        2
 | 
			
		||||
#define PW_CORE_EVENT_REMOVE_ID    3
 | 
			
		||||
#define PW_CORE_EVENT_UPDATE_TYPES 4
 | 
			
		||||
#define PW_CORE_EVENT_INFO         4
 | 
			
		||||
#define PW_CORE_EVENT_NUM          5
 | 
			
		||||
 | 
			
		||||
/** \struct pw_core_events
 | 
			
		||||
| 
						 | 
				
			
			@ -148,11 +169,18 @@ struct pw_core_methods {
 | 
			
		|||
 */
 | 
			
		||||
struct pw_core_events {
 | 
			
		||||
	/**
 | 
			
		||||
	 * Notify new core info
 | 
			
		||||
	 * Update the type map
 | 
			
		||||
	 *
 | 
			
		||||
	 * \param info new core info
 | 
			
		||||
	 * Send a type map update to the client. The client uses this
 | 
			
		||||
	 * information to keep a mapping between server types and the client types.
 | 
			
		||||
	 * \param first_id the id of the first type
 | 
			
		||||
	 * \param n_types the number of types
 | 
			
		||||
	 * \param types the types as a string
 | 
			
		||||
	 */
 | 
			
		||||
	void (*info) (void *object, struct pw_core_info *info);
 | 
			
		||||
	void (*update_types) (void *object,
 | 
			
		||||
			      uint32_t first_id,
 | 
			
		||||
			      uint32_t n_types,
 | 
			
		||||
			      const char **types);
 | 
			
		||||
	/**
 | 
			
		||||
	 * Emit a done event
 | 
			
		||||
	 *
 | 
			
		||||
| 
						 | 
				
			
			@ -186,25 +214,18 @@ struct pw_core_events {
 | 
			
		|||
	 */
 | 
			
		||||
	void (*remove_id) (void *object, uint32_t id);
 | 
			
		||||
	/**
 | 
			
		||||
	 * Update the type map
 | 
			
		||||
	 * Notify new core info
 | 
			
		||||
	 *
 | 
			
		||||
	 * Send a type map update to the client. The client uses this
 | 
			
		||||
	 * information to keep a mapping between server types and the client types.
 | 
			
		||||
	 * \param first_id the id of the first type
 | 
			
		||||
	 * \param n_types the number of types
 | 
			
		||||
	 * \param types the types as a string
 | 
			
		||||
	 * \param info new core info
 | 
			
		||||
	 */
 | 
			
		||||
	void (*update_types) (void *object,
 | 
			
		||||
			      uint32_t first_id,
 | 
			
		||||
			      uint32_t n_types,
 | 
			
		||||
			      const char **types);
 | 
			
		||||
	void (*info) (void *object, struct pw_core_info *info);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define pw_core_notify_info(r,...)         ((struct pw_core_events*)r->iface->events)->info(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_notify_update_types(r,...) ((struct pw_core_events*)r->iface->events)->update_types(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_notify_done(r,...)         ((struct pw_core_events*)r->iface->events)->done(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_notify_error(r,...)        ((struct pw_core_events*)r->iface->events)->error(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_notify_remove_id(r,...)    ((struct pw_core_events*)r->iface->events)->remove_id(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_notify_update_types(r,...) ((struct pw_core_events*)r->iface->events)->update_types(r,__VA_ARGS__)
 | 
			
		||||
#define pw_core_notify_info(r,...)         ((struct pw_core_events*)r->iface->events)->info(r,__VA_ARGS__)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define PW_REGISTRY_METHOD_BIND      0
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -193,6 +193,50 @@ core_marshal_create_client_node(void *object,
 | 
			
		|||
				b.b.offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
core_marshal_create_link(void *object,
 | 
			
		||||
			 uint32_t output_node_id,
 | 
			
		||||
			 uint32_t output_port_id,
 | 
			
		||||
			 uint32_t input_node_id,
 | 
			
		||||
			 uint32_t input_port_id,
 | 
			
		||||
			 const struct spa_format *filter,
 | 
			
		||||
			 const struct spa_dict *props,
 | 
			
		||||
			 uint32_t new_id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_proxy *proxy = object;
 | 
			
		||||
	struct pw_connection *connection = proxy->context->protocol_private;
 | 
			
		||||
	struct builder b = { {NULL, 0, 0, NULL, write_pod}, connection };
 | 
			
		||||
	struct spa_pod_frame f;
 | 
			
		||||
	uint32_t i, n_items;
 | 
			
		||||
 | 
			
		||||
	if (connection == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	core_update_map(proxy->context);
 | 
			
		||||
 | 
			
		||||
	n_items = props ? props->n_items : 0;
 | 
			
		||||
 | 
			
		||||
	spa_pod_builder_add(&b.b,
 | 
			
		||||
			    SPA_POD_TYPE_STRUCT, &f,
 | 
			
		||||
			    SPA_POD_TYPE_INT, output_node_id,
 | 
			
		||||
			    SPA_POD_TYPE_INT, output_port_id,
 | 
			
		||||
			    SPA_POD_TYPE_INT, input_node_id,
 | 
			
		||||
			    SPA_POD_TYPE_INT, input_port_id,
 | 
			
		||||
			    SPA_POD_TYPE_POD, filter,
 | 
			
		||||
			    SPA_POD_TYPE_INT, n_items, 0);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < n_items; i++) {
 | 
			
		||||
		spa_pod_builder_add(&b.b,
 | 
			
		||||
				    SPA_POD_TYPE_STRING, props->items[i].key,
 | 
			
		||||
				    SPA_POD_TYPE_STRING, props->items[i].value, 0);
 | 
			
		||||
	}
 | 
			
		||||
	spa_pod_builder_add(&b.b,
 | 
			
		||||
			    SPA_POD_TYPE_INT, new_id,
 | 
			
		||||
			    -SPA_POD_TYPE_STRUCT, &f, 0);
 | 
			
		||||
 | 
			
		||||
	pw_connection_end_write(connection, proxy->id, PW_CORE_METHOD_CREATE_LINK, b.b.offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
core_marshal_update_types(void *object, uint32_t first_id, uint32_t n_types, const char **types)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -891,20 +935,21 @@ static void registry_marshal_bind(void *object, uint32_t id, uint32_t version, u
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_core_methods pw_protocol_native_client_core_methods = {
 | 
			
		||||
	&core_marshal_client_update,
 | 
			
		||||
	&core_marshal_update_types,
 | 
			
		||||
	&core_marshal_sync,
 | 
			
		||||
	&core_marshal_get_registry,
 | 
			
		||||
	&core_marshal_client_update,
 | 
			
		||||
	&core_marshal_create_node,
 | 
			
		||||
	&core_marshal_create_client_node,
 | 
			
		||||
	&core_marshal_update_types,
 | 
			
		||||
	&core_marshal_create_link
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const demarshal_func_t pw_protocol_native_client_core_demarshal[] = {
 | 
			
		||||
	&core_demarshal_info,
 | 
			
		||||
static const demarshal_func_t pw_protocol_native_client_core_demarshal[PW_CORE_EVENT_NUM] = {
 | 
			
		||||
	&core_demarshal_update_types,
 | 
			
		||||
	&core_demarshal_done,
 | 
			
		||||
	&core_demarshal_error,
 | 
			
		||||
	&core_demarshal_remove_id,
 | 
			
		||||
	&core_demarshal_update_types,
 | 
			
		||||
	&core_demarshal_info
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct pw_interface pw_protocol_native_client_core_interface = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,53 @@ extern "C" {
 | 
			
		|||
#include <pipewire/client/type.h>
 | 
			
		||||
#include <pipewire/client/utils.h>
 | 
			
		||||
 | 
			
		||||
/** \page page_proxy Proxy
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_proxy_overview Overview
 | 
			
		||||
 *
 | 
			
		||||
 * The proxy object is a client side representation of a resource
 | 
			
		||||
 * that lives on the server.
 | 
			
		||||
 *
 | 
			
		||||
 * It is used to communicate with the server side object.
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_proxy_create Create
 | 
			
		||||
 *
 | 
			
		||||
 * A client first creates a new proxy object with pw_proxy_new(). A
 | 
			
		||||
 * type must be provided for this object.
 | 
			
		||||
 *
 | 
			
		||||
 * The protocol of the context will usually install an interface to
 | 
			
		||||
 * translate method calls and events to the wire format.
 | 
			
		||||
 *
 | 
			
		||||
 * The creator of the proxy will usually also install an event
 | 
			
		||||
 * implementation of the particular object type.
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_proxy_bind Bind
 | 
			
		||||
 *
 | 
			
		||||
 * To actually use the proxy object, one needs to create a server
 | 
			
		||||
 * side resource for it. This can be done by, for example, binding
 | 
			
		||||
 * to a global object or by calling a method that creates and binds
 | 
			
		||||
 * to a new remote object. In all cases, the local id is passed to
 | 
			
		||||
 * the server and is used to create a resource with the same id.
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_proxy_methods Methods
 | 
			
		||||
 *
 | 
			
		||||
 * To call a method on the proxy use the interface methods. Calling
 | 
			
		||||
 * any interface method will result in a request to the server to
 | 
			
		||||
 * perform the requested action on the corresponding resource.
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_proxy_events Events
 | 
			
		||||
 *
 | 
			
		||||
 * Events send from the server to the proxy will be demarshalled by
 | 
			
		||||
 * the protocol and will then result in a call to the installed
 | 
			
		||||
 * implementation of the proxy.
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_proxy_destroy Destroy
 | 
			
		||||
 *
 | 
			
		||||
 * Use pw_proxy_destroy() to destroy the client side object. This
 | 
			
		||||
 * is usually done automatically when the server removes the resource
 | 
			
		||||
 * associated to the proxy.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \class pw_proxy
 | 
			
		||||
 *
 | 
			
		||||
 * \brief Represents an object on the client side.
 | 
			
		||||
| 
						 | 
				
			
			@ -37,6 +84,8 @@ extern "C" {
 | 
			
		|||
 * pipewire server. The proxy is responsible for converting interface functions
 | 
			
		||||
 * invoked by the client to PipeWire messages. Events will call the handlers
 | 
			
		||||
 * set in implementation.
 | 
			
		||||
 *
 | 
			
		||||
 * See \ref page_proxy
 | 
			
		||||
 */
 | 
			
		||||
struct pw_proxy {
 | 
			
		||||
	/** the owner context of this proxy */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -34,7 +34,8 @@ extern "C" {
 | 
			
		|||
 * \section sec_overview Overview
 | 
			
		||||
 *
 | 
			
		||||
 * Media streams are used to exchange data with the PipeWire server. A
 | 
			
		||||
 * stream is a wrapper around a \ref pw_client_node with one port.
 | 
			
		||||
 * stream is a wrapper around a proxy for a \ref pw_client_node with
 | 
			
		||||
 * just one port.
 | 
			
		||||
 *
 | 
			
		||||
 * Streams can be used to:
 | 
			
		||||
 *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,7 @@ struct pw_access_data {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * struct pw_access:
 | 
			
		||||
 * \struct pw_access
 | 
			
		||||
 *
 | 
			
		||||
 * PipeWire Access support struct.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -33,6 +33,36 @@ extern "C" {
 | 
			
		|||
#include <pipewire/server/core.h>
 | 
			
		||||
#include <pipewire/server/resource.h>
 | 
			
		||||
 | 
			
		||||
/** \page page_client Client
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_client_overview Overview
 | 
			
		||||
 *
 | 
			
		||||
 * The \ref pw_client object is created by a protocol implementation when
 | 
			
		||||
 * a new client connects.
 | 
			
		||||
 *
 | 
			
		||||
 * The client is used to keep track of all resources belonging to one
 | 
			
		||||
 * connection with the PipeWire server.
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_client_credentials Credentials
 | 
			
		||||
 *
 | 
			
		||||
 * The client object will have its credentials filled in by the protocol.
 | 
			
		||||
 * This information is used to check if a resource or action is available
 | 
			
		||||
 * for this client. See also \ref page_access
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_client_types Types
 | 
			
		||||
 *
 | 
			
		||||
 * The client and server maintain a mapping between the client and server
 | 
			
		||||
 * types. All type ids that are in messages exchanged between the client
 | 
			
		||||
 * and server will automatically be remapped. See also \ref page_types.
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_client_resources Resources
 | 
			
		||||
 *
 | 
			
		||||
 * When a client binds to core global object, a resource is made for this
 | 
			
		||||
 * binding and a unique id is assigned to the resources. The client and
 | 
			
		||||
 * server will use this id as the destination when exchanging messages.
 | 
			
		||||
 * See also \ref page_resource
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \class pw_client
 | 
			
		||||
 *
 | 
			
		||||
 * \brief PipeWire client object class.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -263,6 +263,24 @@ core_create_client_node(void *object,
 | 
			
		|||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
core_create_link(void *object,
 | 
			
		||||
		 uint32_t output_node_id,
 | 
			
		||||
		 uint32_t output_port_id,
 | 
			
		||||
		 uint32_t input_node_id,
 | 
			
		||||
		 uint32_t input_port_id,
 | 
			
		||||
		 const struct spa_format *filter,
 | 
			
		||||
		 const struct spa_dict *props,
 | 
			
		||||
		 uint32_t new_id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
	struct pw_client *client = resource->client;
 | 
			
		||||
 | 
			
		||||
	pw_log_error("can't create link");
 | 
			
		||||
	pw_core_notify_error(client->core_resource,
 | 
			
		||||
			     resource->id, SPA_RESULT_NOT_IMPLEMENTED, "not implemented");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void core_update_types(void *object, uint32_t first_id, uint32_t n_types, const char **types)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -278,12 +296,13 @@ static void core_update_types(void *object, uint32_t first_id, uint32_t n_types,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
static struct pw_core_methods core_methods = {
 | 
			
		||||
	&core_client_update,
 | 
			
		||||
	&core_update_types,
 | 
			
		||||
	&core_sync,
 | 
			
		||||
	&core_get_registry,
 | 
			
		||||
	&core_client_update,
 | 
			
		||||
	&core_create_node,
 | 
			
		||||
	&core_create_client_node,
 | 
			
		||||
	&core_update_types
 | 
			
		||||
	&core_create_link
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void core_unbind_func(void *data)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,18 +40,41 @@ struct pw_global;
 | 
			
		|||
 *
 | 
			
		||||
 * \section page_server_overview Overview
 | 
			
		||||
 *
 | 
			
		||||
 * \subpage page_core
 | 
			
		||||
 *
 | 
			
		||||
 * \subpage page_global
 | 
			
		||||
 *
 | 
			
		||||
 * \subpage page_client
 | 
			
		||||
 *
 | 
			
		||||
 * \subpage page_resource
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/** \page page_core Core
 | 
			
		||||
 *
 | 
			
		||||
 * \section page_core_overview Overview
 | 
			
		||||
 *
 | 
			
		||||
 * The core object is a singleton object that manages the state and
 | 
			
		||||
 * resources of the PipeWire server.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
typedef int (*pw_bind_func_t) (struct pw_global *global,
 | 
			
		||||
			       struct pw_client *client, uint32_t version, uint32_t id);
 | 
			
		||||
 | 
			
		||||
/** \page page_global Global
 | 
			
		||||
 *
 | 
			
		||||
 * Global objects represent resources that are available on the server and
 | 
			
		||||
 * accessible to clients.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
/** \class pw_global
 | 
			
		||||
 *
 | 
			
		||||
 * \brief A global object visible to all clients
 | 
			
		||||
 *
 | 
			
		||||
 * A global object is visible to all clients and represents a resource
 | 
			
		||||
 * that can be used or inspected.
 | 
			
		||||
 *
 | 
			
		||||
 * See \ref page_server_api
 | 
			
		||||
 */
 | 
			
		||||
struct pw_global {
 | 
			
		||||
	struct pw_core *core;		/**< the core */
 | 
			
		||||
| 
						 | 
				
			
			@ -89,7 +112,7 @@ struct pw_core {
 | 
			
		|||
 | 
			
		||||
	struct pw_map objects;		/**< map of known objects */
 | 
			
		||||
 | 
			
		||||
	struct spa_list resource_list;		/**< list of resources */
 | 
			
		||||
	struct spa_list resource_list;		/**< list of core resources */
 | 
			
		||||
	struct spa_list registry_resource_list;	/**< list of registry resources */
 | 
			
		||||
	struct spa_list global_list;		/**< list of globals */
 | 
			
		||||
	struct spa_list client_list;		/**< list of clients */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -276,6 +276,47 @@ static bool core_demarshal_create_client_node(void *object, void *data, size_t s
 | 
			
		|||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool core_demarshal_create_link(void *object, void *data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
	struct spa_pod_iter it;
 | 
			
		||||
	uint32_t new_id, i;
 | 
			
		||||
	uint32_t output_node_id, output_port_id, input_node_id, input_port_id;
 | 
			
		||||
	struct spa_format *filter = NULL;
 | 
			
		||||
	struct spa_dict props;
 | 
			
		||||
 | 
			
		||||
	if (!spa_pod_iter_struct(&it, data, size) ||
 | 
			
		||||
	    !pw_pod_remap_data(SPA_POD_TYPE_STRUCT, data, size, &resource->client->types) ||
 | 
			
		||||
	    !spa_pod_iter_get(&it,
 | 
			
		||||
			      SPA_POD_TYPE_INT, &output_node_id,
 | 
			
		||||
			      SPA_POD_TYPE_INT, &output_port_id,
 | 
			
		||||
			      SPA_POD_TYPE_INT, &input_node_id,
 | 
			
		||||
			      SPA_POD_TYPE_INT, &input_port_id,
 | 
			
		||||
			      -SPA_POD_TYPE_OBJECT, &filter,
 | 
			
		||||
			      SPA_POD_TYPE_INT, &props.n_items, 0))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
 | 
			
		||||
	for (i = 0; i < props.n_items; i++) {
 | 
			
		||||
		if (!spa_pod_iter_get(&it,
 | 
			
		||||
				      SPA_POD_TYPE_STRING, &props.items[i].key,
 | 
			
		||||
				      SPA_POD_TYPE_STRING, &props.items[i].value, 0))
 | 
			
		||||
			return false;
 | 
			
		||||
	}
 | 
			
		||||
	if (!spa_pod_iter_get(&it, SPA_POD_TYPE_INT, &new_id, 0))
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	((struct pw_core_methods *) resource->implementation)->create_link(resource,
 | 
			
		||||
									   output_node_id,
 | 
			
		||||
									   output_port_id,
 | 
			
		||||
									   input_node_id,
 | 
			
		||||
									   input_port_id,
 | 
			
		||||
									   filter,
 | 
			
		||||
									   &props,
 | 
			
		||||
									   new_id);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static bool core_demarshal_update_types(void *object, void *data, size_t size)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -847,21 +888,22 @@ static void link_marshal_info(void *object, struct pw_link_info *info)
 | 
			
		|||
	pw_connection_end_write(connection, resource->id, PW_LINK_EVENT_INFO, b.b.offset);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const demarshal_func_t pw_protocol_native_server_core_demarshal[] = {
 | 
			
		||||
	&core_demarshal_client_update,
 | 
			
		||||
static const demarshal_func_t pw_protocol_native_server_core_demarshal[PW_CORE_METHOD_NUM] = {
 | 
			
		||||
	&core_demarshal_update_types,
 | 
			
		||||
	&core_demarshal_sync,
 | 
			
		||||
	&core_demarshal_get_registry,
 | 
			
		||||
	&core_demarshal_client_update,
 | 
			
		||||
	&core_demarshal_create_node,
 | 
			
		||||
	&core_demarshal_create_client_node,
 | 
			
		||||
	&core_demarshal_update_types
 | 
			
		||||
	&core_demarshal_create_link
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct pw_core_events pw_protocol_native_server_core_events = {
 | 
			
		||||
	&core_marshal_info,
 | 
			
		||||
	&core_marshal_update_types,
 | 
			
		||||
	&core_marshal_done,
 | 
			
		||||
	&core_marshal_error,
 | 
			
		||||
	&core_marshal_remove_id,
 | 
			
		||||
	&core_marshal_update_types
 | 
			
		||||
	&core_marshal_info
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const struct pw_interface pw_protocol_native_server_core_interface = {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,20 +32,45 @@ extern "C" {
 | 
			
		|||
#include <pipewire/client/sig.h>
 | 
			
		||||
#include <pipewire/server/core.h>
 | 
			
		||||
 | 
			
		||||
/** \page page_resource Resource
 | 
			
		||||
 *
 | 
			
		||||
 * \section sec_page_resource Overview
 | 
			
		||||
 *
 | 
			
		||||
 * Resources represent objects owned by a \ref pw_client. They are
 | 
			
		||||
 * the result of binding to a global resource or by calling API that
 | 
			
		||||
 * creates client owned objects.
 | 
			
		||||
 *
 | 
			
		||||
 * The client usually has a proxy object associated with the resource
 | 
			
		||||
 * that it can use to communicate with the resource. See \ref page_proxy.
 | 
			
		||||
 *
 | 
			
		||||
 * Resources are destroyed when the client or the bound object is
 | 
			
		||||
 * destroyed.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
/** \class pw_resource
 | 
			
		||||
 *
 | 
			
		||||
 * \brief Client owned objects
 | 
			
		||||
 *
 | 
			
		||||
 * Resources are objects owned by a client and are destroyed when the
 | 
			
		||||
 * client disappears.
 | 
			
		||||
 *
 | 
			
		||||
 * See also \ref page_resource
 | 
			
		||||
 */
 | 
			
		||||
struct pw_resource {
 | 
			
		||||
	struct pw_core *core;
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
	struct pw_core *core;		/**< the core object */
 | 
			
		||||
	struct spa_list link;		/**< link in object resource_list */
 | 
			
		||||
 | 
			
		||||
	struct pw_client *client;
 | 
			
		||||
	struct pw_client *client;	/**< owner client */
 | 
			
		||||
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
	uint32_t type;
 | 
			
		||||
	void *object;
 | 
			
		||||
	pw_destroy_t destroy;
 | 
			
		||||
	uint32_t id;			/**< per client unique id, index in client objects */
 | 
			
		||||
	uint32_t type;			/**< type id of the object */
 | 
			
		||||
	void *object;			/**< pointer to the object */
 | 
			
		||||
	pw_destroy_t destroy;		/**< function to clean up the object */
 | 
			
		||||
 | 
			
		||||
	const struct pw_interface *iface;
 | 
			
		||||
	const void *implementation;
 | 
			
		||||
	const struct pw_interface *iface;	/**< protocol specific interface functions */
 | 
			
		||||
	const void *implementation;		/**< implementation */
 | 
			
		||||
 | 
			
		||||
	/** Emited when the resource is destroyed */
 | 
			
		||||
	PW_SIGNAL(destroy_signal, (struct pw_listener *listener, struct pw_resource *resource));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue