summaryrefslogtreecommitdiffstats
path: root/src/modules/module-client-node/v0/ext-client-node.h
blob: 21ba59718bd9aa4d592f21ef21bc0aa50d8e447a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
/* PipeWire
 *
 * Copyright © 2016 Wim Taymans <wim.taymans@gmail.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice (including the next
 * paragraph) shall be included in all copies or substantial portions of the
 * Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 */

#ifndef __PIPEWIRE_EXT_CLIENT_NODE0_H__
#define __PIPEWIRE_EXT_CLIENT_NODE0_H__

#ifdef __cplusplus
extern "C" {
#endif

#include <spa/utils/defs.h>
#include <spa/param/param.h>
#include <spa/node/node.h>

#include <pipewire/proxy.h>

#define PW_TYPE_INTERFACE_ClientNode            PW_TYPE_INFO_INTERFACE_BASE "ClientNode"

#define PW_VERSION_CLIENT_NODE0		0

struct pw_client_node0_message;

/** Shared structure between client and server \memberof pw_client_node */
struct pw_client_node0_area {
	uint32_t max_input_ports;	/**< max input ports of the node */
	uint32_t n_input_ports;		/**< number of input ports of the node */
	uint32_t max_output_ports;	/**< max output ports of the node */
	uint32_t n_output_ports;	/**< number of output ports of the node */
};

/** \class pw_client_node0_transport
 *
 * \brief Transport object
 *
 * The transport object contains shared data and ringbuffers to exchange
 * events and data between the server and the client in a low-latency and
 * lockfree way.
 */
struct pw_client_node0_transport {
	struct pw_client_node0_area *area;	/**< the transport area */
	struct spa_io_buffers *inputs;		/**< array of buffer input io */
	struct spa_io_buffers *outputs;		/**< array of buffer output io */
	void *input_data;			/**< input memory for ringbuffer */
	struct spa_ringbuffer *input_buffer;	/**< ringbuffer for input memory */
	void *output_data;			/**< output memory for ringbuffer */
	struct spa_ringbuffer *output_buffer;	/**< ringbuffer for output memory */

	/** Destroy a transport
	 * \param trans a transport to destroy
	 * \memberof pw_client_node0_transport
	 */
	void (*destroy) (struct pw_client_node0_transport *trans);

	/** Add a message to the transport
	 * \param trans the transport to send the message on
	 * \param message the message to add
	 * \return 0 on success, < 0 on error
	 *
	 * Write \a message to the shared ringbuffer.
	 */
	int (*add_message) (struct pw_client_node0_transport *trans, struct pw_client_node0_message *message);

	/** Get next message from a transport
	 * \param trans the transport to get the message of
	 * \param[out] message the message to read
	 * \return < 0 on error, 1 when a message is available,
	 *           0 when no more messages are available.
	 *
	 * Get the skeleton next message from \a trans into \a message. This function will
	 * only read the head and object body of the message.
	 *
	 * After the complete size of the message has been calculated, you should call
	 * \ref parse_message() to read the complete message contents.
	 */
	int (*next_message) (struct pw_client_node0_transport *trans, struct pw_client_node0_message *message);

	/** Parse the complete message on transport
	 * \param trans the transport to read from
	 * \param[out] message memory that can hold the complete message
	 * \return 0 on success, < 0 on error
	 *
	 * Use this function after \ref next_message().
	 */
	int (*parse_message) (struct pw_client_node0_transport *trans, void *message);
};

#define pw_client_node0_transport_destroy(t)		((t)->destroy((t)))
#define pw_client_node0_transport_add_message(t,m)	((t)->add_message((t), (m)))
#define pw_client_node0_transport_next_message(t,m)	((t)->next_message((t), (m)))
#define pw_client_node0_transport_parse_message(t,m)	((t)->parse_message((t), (m)))

enum pw_client_node0_message_type {
	PW_CLIENT_NODE0_MESSAGE_HAVE_OUTPUT,		/*< signal that the node has output */
	PW_CLIENT_NODE0_MESSAGE_NEED_INPUT,		/*< signal that the node needs input */
	PW_CLIENT_NODE0_MESSAGE_PROCESS_INPUT,		/*< instruct the node to process input */
	PW_CLIENT_NODE0_MESSAGE_PROCESS_OUTPUT,		/*< instruct the node output is processed */
	PW_CLIENT_NODE0_MESSAGE_PORT_REUSE_BUFFER,	/*< reuse a buffer */
};

struct pw_client_node0_message_body {
	struct spa_pod_int type		SPA_ALIGNED(8);	/*< one of enum pw_client_node0_message_type */
};

struct pw_client_node0_message {
	struct spa_pod_struct pod;
	struct pw_client_node0_message_body body;
};

struct pw_client_node0_message_port_reuse_buffer_body {
	struct spa_pod_int type		SPA_ALIGNED(8);	/*< PW_CLIENT_NODE0_MESSAGE_PORT_REUSE_BUFFER */
	struct spa_pod_int port_id	SPA_ALIGNED(8);	/*< port id */
	struct spa_pod_int buffer_id	SPA_ALIGNED(8); /*< buffer id to reuse */
};

struct pw_client_node0_message_port_reuse_buffer {
	struct spa_pod_struct pod;
	struct pw_client_node0_message_port_reuse_buffer_body body;
};

#define PW_CLIENT_NODE0_MESSAGE_TYPE(message)	(((struct pw_client_node0_message*)(message))->body.type.value)

#define PW_CLIENT_NODE0_MESSAGE_INIT(message) ((struct pw_client_node0_message)			\
	{ { { sizeof(struct pw_client_node0_message_body), SPA_TYPE_Struct } },			\
	  { SPA_POD_INIT_Int(message) } })

#define PW_CLIENT_NODE0_MESSAGE_INIT_FULL(type,size,message,...) (type)				\
	{ { { size, SPA_TYPE_Struct } },							\
	  { SPA_POD_INIT_Int(message), ##__VA_ARGS__ } }					\

#define PW_CLIENT_NODE0_MESSAGE_PORT_REUSE_BUFFER_INIT(port_id,buffer_id)			\
	PW_CLIENT_NODE0_MESSAGE_INIT_FULL(struct pw_client_node0_message_port_reuse_buffer,	\
		sizeof(struct pw_client_node0_message_port_reuse_buffer_body),			\
		PW_CLIENT_NODE0_MESSAGE_PORT_REUSE_BUFFER,					\
		SPA_POD_INIT_Int(port_id),							\
		SPA_POD_INIT_Int(buffer_id))

/** information about a buffer */
struct pw_client_node0_buffer {
	uint32_t mem_id;		/**< the memory id for the metadata */
	uint32_t offset;		/**< offset in memory */
	uint32_t size;			/**< size in memory */
	struct spa_buffer *buffer;	/**< buffer describing metadata and buffer memory */
};

#define PW_CLIENT_NODE0_METHOD_DONE		0
#define PW_CLIENT_NODE0_METHOD_UPDATE		1
#define PW_CLIENT_NODE0_METHOD_PORT_UPDATE	2
#define PW_CLIENT_NODE0_METHOD_SET_ACTIVE		3
#define PW_CLIENT_NODE0_METHOD_EVENT		4
#define PW_CLIENT_NODE0_METHOD_DESTROY		5
#define PW_CLIENT_NODE0_METHOD_NUM		6

/** \ref pw_client_node methods */
struct pw_client_node0_methods {
#define PW_VERSION_CLIENT_NODE0_METHODS		0
	uint32_t version;

	/** Complete an async operation */
	void (*done) (void *object, int seq, int res);

	/**
	 * Update the node ports and properties
	 *
	 * Update the maximum number of ports and the params of the
	 * client node.
	 * \param change_mask bitfield with changed parameters
	 * \param max_input_ports new max input ports
	 * \param max_output_ports new max output ports
	 * \param params new params
	 */
	void (*update) (void *object,
#define PW_CLIENT_NODE0_UPDATE_MAX_INPUTS   (1 << 0)
#define PW_CLIENT_NODE0_UPDATE_MAX_OUTPUTS  (1 << 1)
#define PW_CLIENT_NODE0_UPDATE_PARAMS       (1 << 2)
			uint32_t change_mask,
			uint32_t max_input_ports,
			uint32_t max_output_ports,
			uint32_t n_params,
			const struct spa_pod **params);

	/**
	 * Update a node port
	 *
	 * Update the information of one port of a node.
	 * \param direction the direction of the port
	 * \param port_id the port id to update
	 * \param change_mask a bitfield of changed items
	 * \param n_params number of port parameters
	 * \param params array of port parameters
	 * \param info port information
	 */
	void (*port_update) (void *object,
			     enum spa_direction direction,
			     uint32_t port_id,
#define PW_CLIENT_NODE0_PORT_UPDATE_PARAMS            (1 << 0)
#define PW_CLIENT_NODE0_PORT_UPDATE_INFO              (1 << 1)
			     uint32_t change_mask,
			     uint32_t n_params,
			     const struct spa_pod **params,
			     const struct spa_port_info *info);
	/**
	 * Activate or deactivate the node
	 */
	void (*set_active) (void *object, bool active);
	/**
	 * Send an event to the node
	 * \param event the event to send
	 */
	void (*event) (void *object, struct spa_event *event);
	/**
	 * Destroy the client_node
	 */
	void (*destroy) (void *object);
};

#define PW_CLIENT_NODE0_EVENT_ADD_MEM		0
#define PW_CLIENT_NODE0_EVENT_TRANSPORT		1
#define PW_CLIENT_NODE0_EVENT_SET_PARAM		2
#define PW_CLIENT_NODE0_EVENT_EVENT		3
#define PW_CLIENT_NODE0_EVENT_COMMAND		4
#define PW_CLIENT_NODE0_EVENT_ADD_PORT		5
#define PW_CLIENT_NODE0_EVENT_REMOVE_PORT	6
#define PW_CLIENT_NODE0_EVENT_PORT_SET_PARAM	7
#define PW_CLIENT_NODE0_EVENT_PORT_USE_BUFFERS	8
#define PW_CLIENT_NODE0_EVENT_PORT_COMMAND	9
#define PW_CLIENT_NODE0_EVENT_PORT_SET_IO	10
#define PW_CLIENT_NODE0_EVENT_NUM		11

/** \ref pw_client_node events */
struct pw_client_node0_events {
#define PW_VERSION_CLIENT_NODE0_EVENTS		0
	uint32_t version;
	/**
	 * Memory was added to a node
	 *
	 * \param mem_id the id of the memory
	 * \param type the memory type
	 * \param memfd the fd of the memory
	 * \param flags flags for the \a memfd
	 */
	void (*add_mem) (void *data,
			 uint32_t mem_id,
			 uint32_t type,
			 int memfd,
			 uint32_t flags);
	/**
	 * Notify of a new transport area
	 *
	 * The transport area is used to exchange real-time commands between
	 * the client and the server.
	 *
	 * \param node_id the node id created for this client node
	 * \param readfd fd for signal data can be read
	 * \param writefd fd for signal data can be written
	 * \param transport the shared transport area
	 */
	void (*transport) (void *data,
			   uint32_t node_id,
			   int readfd,
			   int writefd,
			   struct pw_client_node0_transport *transport);
	/**
	 * Notify of a property change
	 *
	 * When the server configures the properties on the node
	 * this event is sent
	 *
	 * \param seq a sequence number
	 * \param id the id of the parameter
	 * \param flags parameter flags
	 * \param param the param to set
	 */
	void (*set_param) (void *data, uint32_t seq,
			   uint32_t id, uint32_t flags,
			   const struct spa_pod *param);
	/**
	 * Receive an event from the client node
	 * \param event the received event */
	void (*event) (void *data, const struct spa_event *event);
	/**
	 * Notify of a new node command
	 *
	 * \param seq a sequence number
	 * \param command the command
	 */
	void (*command) (void *data, uint32_t seq, const struct spa_command *command);
	/**
	 * A new port was added to the node
	 *
	 * The server can at any time add a port to the node when there
	 * are free ports available.
	 *
	 * \param seq a sequence number
	 * \param direction the direction of the port
	 * \param port_id the new port id
	 */
	void (*add_port) (void *data,
			  uint32_t seq,
			  enum spa_direction direction,
			  uint32_t port_id);
	/**
	 * A port was removed from the node
	 *
	 * \param seq a sequence number
	 * \param direction a port direction
	 * \param port_id the remove port id
	 */
	void (*remove_port) (void *data,
			     uint32_t seq,
			     enum spa_direction direction,
			     uint32_t port_id);
	/**
	 * A parameter was configured on the port
	 *
	 * \param seq a sequence number
	 * \param direction a port direction
	 * \param port_id the port id
	 * \param id the id of the parameter
	 * \param flags flags used when setting the param
	 * \param param the new param
	 */
	void (*port_set_param) (void *data,
				uint32_t seq,
				enum spa_direction direction,
				uint32_t port_id,
				uint32_t id, uint32_t flags,
				const struct spa_pod *param);
	/**
	 * Notify the port of buffers
	 *
	 * \param seq a sequence number
	 * \param direction a port direction
	 * \param port_id the port id
	 * \param n_buffer the number of buffers
	 * \param buffers and array of buffer descriptions
	 */
	void (*port_use_buffers) (void *data,
				  uint32_t seq,
				  enum spa_direction direction,
				  uint32_t port_id,
				  uint32_t n_buffers,
				  struct pw_client_node0_buffer *buffers);
	/**
	 * Notify of a new port command
	 *
	 * \param direction a port direction
	 * \param port_id the port id
	 * \param command the command
	 */
	void (*port_command) (void *data,
			      enum spa_direction direction,
			      uint32_t port_id,
			      const struct spa_command *command);

	/**
	 * Configure the io area with \a id of \a port_id.
	 *
	 * \param seq a sequence number
	 * \param direction the direction of the port
	 * \param port_id the port id
	 * \param id the id of the io area to set
	 * \param mem_id the id of the memory to use
	 * \param offset offset of io area in memory
	 * \param size size of the io area
	 */
	void (*port_set_io) (void *data,
			     uint32_t seq,
			     enum spa_direction direction,
			     uint32_t port_id,
			     uint32_t id,
			     uint32_t mem_id,
			     uint32_t offset,
			     uint32_t size);
};
#define pw_client_node0_resource(r,m,v,...) pw_resource_call(r, struct pw_client_node0_events, m, v, ##__VA_ARGS__)

#define pw_client_node0_resource_add_mem(r,...)		 pw_client_node0_resource(r,add_mem,0,__VA_ARGS__)
#define pw_client_node0_resource_transport(r,...)	 pw_client_node0_resource(r,transport,0,__VA_ARGS__)
#define pw_client_node0_resource_set_param(r,...)	 pw_client_node0_resource(r,set_param,0,__VA_ARGS__)
#define pw_client_node0_resource_event(r,...)		 pw_client_node0_resource(r,event,0,__VA_ARGS__)
#define pw_client_node0_resource_command(r,...)		 pw_client_node0_resource(r,command,0,__VA_ARGS__)
#define pw_client_node0_resource_add_port(r,...)	 pw_client_node0_resource(r,add_port,0,__VA_ARGS__)
#define pw_client_node0_resource_remove_port(r,...)	 pw_client_node0_resource(r,remove_port,0,__VA_ARGS__)
#define pw_client_node0_resource_port_set_param(r,...)	 pw_client_node0_resource(r,port_set_param,0,__VA_ARGS__)
#define pw_client_node0_resource_port_use_buffers(r,...) pw_client_node0_resource(r,port_use_buffers,0,__VA_ARGS__)
#define pw_client_node0_resource_port_command(r,...)	 pw_client_node0_resource(r,port_command,0,__VA_ARGS__)
#define pw_client_node0_resource_port_set_io(r,...)	 pw_client_node0_resource(r,port_set_io,0,__VA_ARGS__)

#ifdef __cplusplus
}  /* extern "C" */
#endif

#endif /* __PIPEWIRE_EXT_CLIENT_NODE0_H__ */