summaryrefslogtreecommitdiffstats
path: root/third_party/pipewire/spa/node/node.h
blob: f32adec16cd1e2563a93aa627c66e2eb3e6fcfc6 (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
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
/* Simple Plugin API
 *
 * Copyright © 2018 Wim Taymans
 *
 * 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 SPA_NODE_H
#define SPA_NODE_H

#ifdef __cplusplus
extern "C" {
#endif

/** \defgroup spa_node Node
 *
 * A spa_node is a component that can consume and produce buffers.
 */

/**
 * \addtogroup spa_node
 * \{
 */

#include <errno.h>
#include <spa/utils/defs.h>
#include <spa/utils/type.h>
#include <spa/utils/hook.h>
#include <spa/buffer/buffer.h>
#include <spa/node/event.h>
#include <spa/node/command.h>


#define SPA_TYPE_INTERFACE_Node		SPA_TYPE_INFO_INTERFACE_BASE "Node"

#define SPA_VERSION_NODE		0
struct spa_node { struct spa_interface iface; };

/**
 * Node information structure
 *
 * Contains the basic node information.
 */
struct spa_node_info {
	uint32_t max_input_ports;
	uint32_t max_output_ports;
#define SPA_NODE_CHANGE_MASK_FLAGS		(1u<<0)
#define SPA_NODE_CHANGE_MASK_PROPS		(1u<<1)
#define SPA_NODE_CHANGE_MASK_PARAMS		(1u<<2)
	uint64_t change_mask;

#define SPA_NODE_FLAG_RT			(1u<<0)	/**< node can do real-time processing */
#define SPA_NODE_FLAG_IN_DYNAMIC_PORTS		(1u<<1)	/**< input ports can be added/removed */
#define SPA_NODE_FLAG_OUT_DYNAMIC_PORTS		(1u<<2)	/**< output ports can be added/removed */
#define SPA_NODE_FLAG_IN_PORT_CONFIG		(1u<<3)	/**< input ports can be reconfigured with
							  *  PortConfig parameter */
#define SPA_NODE_FLAG_OUT_PORT_CONFIG		(1u<<4)	/**< output ports can be reconfigured with
							  *  PortConfig parameter */
#define SPA_NODE_FLAG_NEED_CONFIGURE		(1u<<5)	/**< node needs configuration before it can
							  *  be started. */
#define SPA_NODE_FLAG_ASYNC			(1u<<6)	/**< the process function might not
							  *  immediately produce or consume data
							  *  but might offload the work to a worker
							  *  thread. */
	uint64_t flags;
	struct spa_dict *props;			/**< extra node properties */
	struct spa_param_info *params;		/**< parameter information */
	uint32_t n_params;			/**< number of items in \a params */
};

#define SPA_NODE_INFO_INIT()	(struct spa_node_info) { 0, }

/**
 * Port information structure
 *
 * Contains the basic port information.
 */
struct spa_port_info {
#define SPA_PORT_CHANGE_MASK_FLAGS		(1u<<0)
#define SPA_PORT_CHANGE_MASK_RATE		(1u<<1)
#define SPA_PORT_CHANGE_MASK_PROPS		(1u<<2)
#define SPA_PORT_CHANGE_MASK_PARAMS		(1u<<3)
	uint64_t change_mask;

#define SPA_PORT_FLAG_REMOVABLE			(1u<<0)	/**< port can be removed */
#define SPA_PORT_FLAG_OPTIONAL			(1u<<1)	/**< processing on port is optional */
#define SPA_PORT_FLAG_CAN_ALLOC_BUFFERS		(1u<<2)	/**< the port can allocate buffer data */
#define SPA_PORT_FLAG_IN_PLACE			(1u<<3)	/**< the port can process data in-place and
							 *   will need a writable input buffer */
#define SPA_PORT_FLAG_NO_REF			(1u<<4)	/**< the port does not keep a ref on the buffer.
							 *   This means the node will always completely
							 *   consume the input buffer and it will be
							 *   recycled after process. */
#define SPA_PORT_FLAG_LIVE			(1u<<5)	/**< output buffers from this port are
							 *   timestamped against a live clock. */
#define SPA_PORT_FLAG_PHYSICAL			(1u<<6)	/**< connects to some device */
#define SPA_PORT_FLAG_TERMINAL			(1u<<7)	/**< data was not created from this port
							 *   or will not be made available on another
							 *   port */
#define SPA_PORT_FLAG_DYNAMIC_DATA		(1u<<8)	/**< data pointer on buffers can be changed.
							 *   Only the buffer data marked as DYNAMIC
							 *   can be changed. */
	uint64_t flags;				/**< port flags */
	struct spa_fraction rate;		/**< rate of sequence numbers on port */
	const struct spa_dict *props;		/**< extra port properties */
	struct spa_param_info *params;		/**< parameter information */
	uint32_t n_params;			/**< number of items in \a params */
};

#define SPA_PORT_INFO_INIT()	(struct spa_port_info) { 0, }

#define SPA_RESULT_TYPE_NODE_ERROR	1
#define SPA_RESULT_TYPE_NODE_PARAMS	2

/** an error result */
struct spa_result_node_error {
	const char *message;
};

/** the result of enum_params or port_enum_params. */
struct spa_result_node_params {
	uint32_t id;		/**< id of parameter */
	uint32_t index;		/**< index of parameter */
	uint32_t next;		/**< next index of iteration */
	struct spa_pod *param;	/**< the result param */
};

#define SPA_NODE_EVENT_INFO		0
#define SPA_NODE_EVENT_PORT_INFO	1
#define SPA_NODE_EVENT_RESULT		2
#define SPA_NODE_EVENT_EVENT		3
#define SPA_NODE_EVENT_NUM		4

/** events from the spa_node.
 *
 * All event are called from the main thread and multiple
 * listeners can be registered for the events with
 * spa_node_add_listener().
 */
struct spa_node_events {
#define SPA_VERSION_NODE_EVENTS	0
	uint32_t version;	/**< version of this structure */

	/** Emitted when info changes */
	void (*info) (void *data, const struct spa_node_info *info);

	/** Emitted when port info changes, NULL when port is removed */
	void (*port_info) (void *data,
			enum spa_direction direction, uint32_t port,
			const struct spa_port_info *info);

	/** notify a result.
	 *
	 * Some methods will trigger a result event with an optional
	 * result of the given type. Look at the documentation of the
	 * method to know when to expect a result event.
	 *
	 * The result event can be called synchronously, as an event
	 * called from inside the method itself, in which case the seq
	 * number passed to the method will be passed unchanged.
	 *
	 * The result event will be called asynchronously when the
	 * method returned an async return value. In this case, the seq
	 * number in the result will match the async return value of
	 * the method call. Users should match the seq number from
	 * request to the reply.
	 */
	void (*result) (void *data, int seq, int res,
			uint32_t type, const void *result);

	/**
	 * \param node a spa_node
	 * \param event the event that was emitted
	 *
	 * This will be called when an out-of-bound event is notified
	 * on \a node.
	 */
	void (*event) (void *data, const struct spa_event *event);
};

#define SPA_NODE_CALLBACK_READY		0
#define SPA_NODE_CALLBACK_REUSE_BUFFER	1
#define SPA_NODE_CALLBACK_XRUN		2
#define SPA_NODE_CALLBACK_NUM		3

/** Node callbacks
 *
 * Callbacks are called from the real-time data thread. Only
 * one callback structure can be set on an spa_node.
 */
struct spa_node_callbacks {
#define SPA_VERSION_NODE_CALLBACKS	0
	uint32_t version;
	/**
	 * \param node a spa_node
	 *
	 * The node is ready for processing.
	 *
	 * When this function is NULL, synchronous operation is requested
	 * on the ports.
	 */
	int (*ready) (void *data, int state);

	/**
	 * \param node a spa_node
	 * \param port_id an input port_id
	 * \param buffer_id the buffer id to be reused
	 *
	 * The node has a buffer that can be reused.
	 *
	 * When this function is NULL, the buffers to reuse will be set in
	 * the io area of the input ports.
	 */
	int (*reuse_buffer) (void *data,
			     uint32_t port_id,
			     uint32_t buffer_id);

	/**
	 * \param data user data
	 * \param trigger the timestamp in microseconds when the xrun happened
	 * \param delay the amount of microseconds of xrun.
	 * \param info an object with extra info (NULL for now)
	 *
	 * The node has encountered an over or underrun
	 *
	 * The info contains an object with more information
	 */
	int (*xrun) (void *data, uint64_t trigger, uint64_t delay,
			struct spa_pod *info);
};


/** flags that can be passed to set_param and port_set_param functions */
#define SPA_NODE_PARAM_FLAG_TEST_ONLY	(1 << 0)	/**< Just check if the param is accepted */
#define SPA_NODE_PARAM_FLAG_FIXATE	(1 << 1)	/**< Fixate the non-optional unset fields */
#define SPA_NODE_PARAM_FLAG_NEAREST	(1 << 2)	/**< Allow set fields to be rounded to the
							  *  nearest allowed field value. */

/** flags to pass to the use_buffers functions */
#define SPA_NODE_BUFFERS_FLAG_ALLOC	(1 << 0)	/**< Allocate memory for the buffers. This flag
							  *  is ignored when the port does not have the
							  *  SPA_PORT_FLAG_CAN_ALLOC_BUFFERS set. */


#define SPA_NODE_METHOD_ADD_LISTENER		0
#define SPA_NODE_METHOD_SET_CALLBACKS		1
#define SPA_NODE_METHOD_SYNC			2
#define SPA_NODE_METHOD_ENUM_PARAMS		3
#define SPA_NODE_METHOD_SET_PARAM		4
#define SPA_NODE_METHOD_SET_IO			5
#define SPA_NODE_METHOD_SEND_COMMAND		6
#define SPA_NODE_METHOD_ADD_PORT		7
#define SPA_NODE_METHOD_REMOVE_PORT		8
#define SPA_NODE_METHOD_PORT_ENUM_PARAMS	9
#define SPA_NODE_METHOD_PORT_SET_PARAM		10
#define SPA_NODE_METHOD_PORT_USE_BUFFERS	11
#define SPA_NODE_METHOD_PORT_SET_IO		12
#define SPA_NODE_METHOD_PORT_REUSE_BUFFER	13
#define SPA_NODE_METHOD_PROCESS			14
#define SPA_NODE_METHOD_NUM			15

/**
 * Node methods
 */
struct spa_node_methods {
	/* the version of the node methods. This can be used to expand this
	 * structure in the future */
#define SPA_VERSION_NODE_METHODS	0
	uint32_t version;

	/**
	 * Adds an event listener on \a node.
	 *
	 * Setting the events will trigger the info event and a
	 * port_info event for each managed port on the new
	 * listener.
	 *
	 * \param node a #spa_node
	 * \param listener a listener
	 * \param events a struct \ref spa_node_events
	 * \param data data passed as first argument in functions of \a events
	 * \return 0 on success
	 *	   < 0 errno on error
	 */
	int (*add_listener) (void *object,
			struct spa_hook *listener,
			const struct spa_node_events *events,
			void *data);
	/**
	 * Set callbacks to on \a node.
	 * if \a callbacks is NULL, the current callbacks are removed.
	 *
	 * This function must be called from the main thread.
	 *
	 * All callbacks are called from the data thread.
	 *
	 * \param node a spa_node
	 * \param callbacks callbacks to set
	 * \return 0 on success
	 *         -EINVAL when node is NULL
	 */
	int (*set_callbacks) (void *object,
			      const struct spa_node_callbacks *callbacks,
			      void *data);
	/**
	 * Perform a sync operation.
	 *
	 * This method will emit the result event with the given sequence
	 * number synchronously or with the returned async return value
	 * asynchronously.
	 *
	 * Because all methods are serialized in the node, this can be used
	 * to wait for completion of all previous method calls.
	 *
	 * \param seq a sequence number
	 * \return 0 on success
	 *         -EINVAL when node is NULL
	 *         an async result
	 */
	int (*sync) (void *object, int seq);

	/**
	 * Enumerate the parameters of a node.
	 *
	 * Parameters are identified with an \a id. Some parameters can have
	 * multiple values, see the documentation of the parameter id.
	 *
	 * Parameters can be filtered by passing a non-NULL \a filter.
	 *
	 * The function will emit the result event up to \a max times with
	 * the result value. The seq in the result will either be the \a seq
	 * number when executed synchronously or the async return value of
	 * this function when executed asynchronously.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param node a \ref spa_node
	 * \param seq a sequence number to pass to the result event when
	 *	this method is executed synchronously.
	 * \param id the param id to enumerate
	 * \param start the index of enumeration, pass 0 for the first item
	 * \param max the maximum number of parameters to enumerate
	 * \param filter and optional filter to use
	 *
	 * \return 0 when no more items can be iterated.
	 *         -EINVAL when invalid arguments are given
	 *         -ENOENT the parameter \a id is unknown
	 *         -ENOTSUP when there are no parameters
	 *                 implemented on \a node
	 *         an async return value when the result event will be
	 *             emitted later.
	 */
	int (*enum_params) (void *object, int seq,
			    uint32_t id, uint32_t start, uint32_t max,
			    const struct spa_pod *filter);

	/**
	 * Set the configurable parameter in \a node.
	 *
	 * Usually, \a param will be obtained from enum_params and then
	 * modified but it is also possible to set another spa_pod
	 * as long as its keys and types match a supported object.
	 *
	 * Objects with property keys that are not known are ignored.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param node a \ref spa_node
	 * \param id the parameter id to configure
	 * \param flags additional flags
	 * \param param the parameter to configure
	 *
	 * \return 0 on success
	 *         -EINVAL when node is NULL
	 *         -ENOTSUP when there are no parameters implemented on \a node
	 *         -ENOENT the parameter is unknown
	 */
	int (*set_param) (void *object,
			  uint32_t id, uint32_t flags,
			  const struct spa_pod *param);

	/**
	 * Configure the given memory area with \a id on \a node. This
	 * structure is allocated by the host and is used to exchange
	 * data and parameters with the node.
	 *
	 * Setting an \a io of NULL will disable the node io.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param id the id of the io area, the available ids can be
	 *        enumerated with the node parameters.
	 * \param data a io area memory
	 * \param size the size of \a data
	 * \return 0 on success
	 *         -EINVAL when invalid input is given
	 *         -ENOENT when \a id is unknown
	 *         -ENOSPC when \a size is too small
	 */
	int (*set_io) (void *object,
		       uint32_t id, void *data, size_t size);

	/**
	 * Send a command to a node.
	 *
	 * Upon completion, a command might change the state of a node.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param node a  spa_node
	 * \param command a spa_command
	 * \return 0 on success
	 *         -EINVAL when node or command is NULL
	 *         -ENOTSUP when this node can't process commands
	 *         -EINVAL \a command is an invalid command
	 */
	int (*send_command) (void *object, const struct spa_command *command);

	/**
	 * Make a new port with \a port_id. The caller should use the lowest unused
	 * port id for the given \a direction.
	 *
	 * Port ids should be between 0 and max_ports as obtained from the info
	 * event.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param node a  spa_node
	 * \param direction a enum \ref spa_direction
	 * \param port_id an unused port id
	 * \param props extra properties
	 * \return 0 on success
	 *         -EINVAL when node is NULL
	 */
	int (*add_port) (void *object,
			enum spa_direction direction, uint32_t port_id,
			const struct spa_dict *props);

	/**
	 * Remove a port with \a port_id.
	 *
	 * \param node a  spa_node
	 * \param direction a enum \ref spa_direction
	 * \param port_id a port id
	 * \return 0 on success
	 *         -EINVAL when node is NULL or when port_id is unknown or
	 *		when the port can't be removed.
	 */
	int (*remove_port) (void *object,
			enum spa_direction direction, uint32_t port_id);

	/**
	 * Enumerate all possible parameters of \a id on \a port_id of \a node
	 * that are compatible with \a filter.
	 *
	 * The result parameters can be queried and modified and ultimately be used
	 * to call port_set_param.
	 *
	 * The function will emit the result event up to \a max times with
	 * the result value. The seq in the result event will either be the
	 * \a seq number when executed synchronously or the async return
	 * value of this function when executed asynchronously.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param node a spa_node
	 * \param seq a sequence number to pass to the result event when
	 *	this method is executed synchronously.
	 * \param direction an spa_direction
	 * \param port_id the port to query
	 * \param id the parameter id to query
	 * \param start the first index to query, 0 to get the first item
	 * \param max the maximum number of params to query
	 * \param filter a parameter filter or NULL for no filter
	 *
	 * \return 0 when no more items can be iterated.
	 *         -EINVAL when invalid parameters are given
	 *         -ENOENT when \a id is unknown
	 *         an async return value when the result event will be
	 *             emitted later.
	 */
	int (*port_enum_params) (void *object, int seq,
				 enum spa_direction direction, uint32_t port_id,
				 uint32_t id, uint32_t start, uint32_t max,
				 const struct spa_pod *filter);
	/**
	 * Set a parameter on \a port_id of \a node.
	 *
	 * When \a param is NULL, the parameter will be unset.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param node a struct \ref spa_node
	 * \param direction a enum \ref spa_direction
	 * \param port_id the port to configure
	 * \param id the parameter id to set
	 * \param flags optional flags
	 * \param param a struct \ref spa_pod with the parameter to set
	 * \return 0 on success
	 *         1 on success, the value of \a param might have been
	 *                changed depending on \a flags and the final value can be found by
	 *                doing port_enum_params.
	 *         -EINVAL when node is NULL or invalid arguments are given
	 *         -ESRCH when one of the mandatory param
	 *                 properties is not specified and SPA_NODE_PARAM_FLAG_FIXATE was
	 *                 not set in \a flags.
	 *         -ESRCH when the type or size of a property is not correct.
	 *         -ENOENT when the param id is not found
	 */
	int (*port_set_param) (void *object,
			       enum spa_direction direction,
			       uint32_t port_id,
			       uint32_t id, uint32_t flags,
			       const struct spa_pod *param);

	/**
	 * Tell the port to use the given buffers
	 *
	 * When \a flags contains SPA_NODE_BUFFERS_FLAG_ALLOC, the data
	 * in the buffers should point to an array of at least 1 data entry
	 * with the desired supported type that will be filled by this function.
	 *
	 * The port should also have a spa_io_buffers io area configured to exchange
	 * the buffers with the port.
	 *
	 * For an input port, all the buffers will remain dequeued.
	 * Once a buffer has been queued on a port in the spa_io_buffers,
	 * it should not be reused until the reuse_buffer callback is notified
	 * or when the buffer has been returned in the spa_io_buffers of
	 * the port.
	 *
	 * For output ports, all buffers will be queued in the port. When process
	 * returns SPA_STATUS_HAVE_DATA, buffers are available in one or more
	 * of the spa_io_buffers areas.
	 *
	 * When a buffer can be reused, port_reuse_buffer() should be called or the
	 * buffer_id should be placed in the spa_io_buffers area before calling
	 * process.
	 *
	 * Passing NULL as \a buffers will remove the reference that the port has
	 * on the buffers.
	 *
	 * When this function returns async, use the spa_node_sync operation to
	 * wait for completion.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param object an object implementing the interface
	 * \param direction a port direction
	 * \param port_id a port id
	 * \param flags extra flags
	 * \param buffers an array of buffer pointers
	 * \param n_buffers number of elements in \a buffers
	 * \return 0 on success
	 */
	int (*port_use_buffers) (void *object,
				 enum spa_direction direction,
				 uint32_t port_id,
				 uint32_t flags,
				 struct spa_buffer **buffers,
				 uint32_t n_buffers);

	/**
	 * Configure the given memory area with \a id on \a port_id. This
	 * structure is allocated by the host and is used to exchange
	 * data and parameters with the port.
	 *
	 * Setting an \a io of NULL will disable the port io.
	 *
	 * This function must be called from the main thread.
	 *
	 * \param direction a spa_direction
	 * \param port_id a port id
	 * \param id the id of the io area, the available ids can be
	 *        enumerated with the port parameters.
	 * \param data a io area memory
	 * \param size the size of \a data
	 * \return 0 on success
	 *         -EINVAL when invalid input is given
	 *         -ENOENT when \a id is unknown
	 *         -ENOSPC when \a size is too small
	 */
	int (*port_set_io) (void *object,
			    enum spa_direction direction,
			    uint32_t port_id,
			    uint32_t id,
			    void *data, size_t size);

	/**
	 * Tell an output port to reuse a buffer.
	 *
	 * This function must be called from the data thread.
	 *
	 * \param node a spa_node
	 * \param port_id a port id
	 * \param buffer_id a buffer id to reuse
	 * \return 0 on success
	 *         -EINVAL when node is NULL
	 */
	int (*port_reuse_buffer) (void *object, uint32_t port_id, uint32_t buffer_id);

	/**
	 * Process the node
	 *
	 * This function must be called from the data thread.
	 *
	 * Output io areas with SPA_STATUS_NEED_DATA will recycle the
	 * buffers if any.
	 *
	 * Input areas with SPA_STATUS_HAVE_DATA are consumed if possible
	 * and the status is set to SPA_STATUS_NEED_DATA or SPA_STATUS_OK.
	 *
	 * When the node has new output buffers, the SPA_STATUS_HAVE_DATA
	 * bit will be set.
	 *
	 * When the node can accept new input in the next cycle, the
	 * SPA_STATUS_NEED_DATA bit will be set.
	 */
	int (*process) (void *object);
};

#define spa_node_method(o,method,version,...)				\
({									\
	int _res = -ENOTSUP;						\
	struct spa_node *_n = o;					\
	spa_interface_call_res(&_n->iface,				\
			struct spa_node_methods, _res,			\
			method, version, ##__VA_ARGS__);		\
	_res;								\
})

#define spa_node_add_listener(n,...)		spa_node_method(n, add_listener, 0, __VA_ARGS__)
#define spa_node_set_callbacks(n,...)		spa_node_method(n, set_callbacks, 0, __VA_ARGS__)
#define spa_node_sync(n,...)			spa_node_method(n, sync, 0, __VA_ARGS__)
#define spa_node_enum_params(n,...)		spa_node_method(n, enum_params, 0, __VA_ARGS__)
#define spa_node_set_param(n,...)		spa_node_method(n, set_param, 0, __VA_ARGS__)
#define spa_node_set_io(n,...)			spa_node_method(n, set_io, 0, __VA_ARGS__)
#define spa_node_send_command(n,...)		spa_node_method(n, send_command, 0, __VA_ARGS__)
#define spa_node_add_port(n,...)		spa_node_method(n, add_port, 0, __VA_ARGS__)
#define spa_node_remove_port(n,...)		spa_node_method(n, remove_port, 0, __VA_ARGS__)
#define spa_node_port_enum_params(n,...)	spa_node_method(n, port_enum_params, 0, __VA_ARGS__)
#define spa_node_port_set_param(n,...)		spa_node_method(n, port_set_param, 0, __VA_ARGS__)
#define spa_node_port_use_buffers(n,...)	spa_node_method(n, port_use_buffers, 0, __VA_ARGS__)
#define spa_node_port_set_io(n,...)		spa_node_method(n, port_set_io, 0, __VA_ARGS__)

#define spa_node_port_reuse_buffer(n,...)	spa_node_method(n, port_reuse_buffer, 0, __VA_ARGS__)
#define spa_node_process(n)			spa_node_method(n, process, 0)

/**
 * \}
 */

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

#endif /* SPA_NODE_H */