PipeWire  1.0.0
graph.h
Go to the documentation of this file.
1 /* Simple Plugin API */
2 /* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
3 /* SPDX-License-Identifier: MIT */
4 
5 #ifndef SPA_GRAPH_H
6 #define SPA_GRAPH_H
7 
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 
21 #include <spa/utils/atomic.h>
22 #include <spa/utils/defs.h>
23 #include <spa/utils/list.h>
24 #include <spa/utils/hook.h>
25 #include <spa/node/node.h>
26 #include <spa/node/io.h>
27 
28 #ifndef spa_debug
29 #define spa_debug(...)
30 #endif
31 
32 struct spa_graph;
33 struct spa_graph_node;
35 struct spa_graph_port;
36 
37 struct spa_graph_state {
38  int status;
39  int32_t required;
40  int32_t pending;
41 };
42 
43 static inline void spa_graph_state_reset(struct spa_graph_state *state)
44 {
45  state->pending = state->required;
46 }
47 
49  struct spa_list link;
50  struct spa_graph_state *state;
51  int (*signal) (void *data);
52  void *signal_data;
53 };
54 
55 #define spa_graph_link_signal(l) ((l)->signal((l)->signal_data))
56 
57 #define spa_graph_state_dec(s) (SPA_ATOMIC_DEC(s->pending) == 0)
58 
59 static inline int spa_graph_link_trigger(struct spa_graph_link *link)
60 {
61  struct spa_graph_state *state = link->state;
62 
63  spa_debug("link %p: state %p: pending %d/%d", link, state,
64  state->pending, state->required);
65 
66  if (spa_graph_state_dec(state))
68 
69  return state->status;
70 }
71 struct spa_graph {
72  uint32_t flags; /* flags */
73  struct spa_graph_node *parent; /* parent node or NULL when driver */
74  struct spa_graph_state *state; /* state of graph */
75  struct spa_list nodes; /* list of nodes of this graph */
76 };
77 
79 #define SPA_VERSION_GRAPH_NODE_CALLBACKS 0
80  uint32_t version;
81 
82  int (*process) (void *data, struct spa_graph_node *node);
83  int (*reuse_buffer) (void *data, struct spa_graph_node *node,
84  uint32_t port_id, uint32_t buffer_id);
85 };
86 
88  struct spa_list link;
89  struct spa_graph *graph;
90  struct spa_list ports[2];
91  struct spa_list links;
92  uint32_t flags;
94  struct spa_graph_link graph_link;
95  struct spa_graph *subgraph;
96  struct spa_callbacks callbacks;
98 };
99 
100 #define spa_graph_node_call(n,method,version,...) \
101 ({ \
102  int __res = 0; \
103  spa_callbacks_call_res(&(n)->callbacks, \
104  struct spa_graph_node_callbacks, __res, \
105  method, (version), ##__VA_ARGS__); \
106  __res; \
107 })
108 
109 #define spa_graph_node_process(n) spa_graph_node_call((n), process, 0, (n))
110 #define spa_graph_node_reuse_buffer(n,p,i) spa_graph_node_call((n), reuse_buffer, 0, (n), (p), (i))
111 
112 struct spa_graph_port {
113  struct spa_list link;
114  struct spa_graph_node *node;
115  enum spa_direction direction;
116  uint32_t port_id;
117  uint32_t flags;
118  struct spa_graph_port *peer;
119 };
120 
121 static inline int spa_graph_node_trigger(struct spa_graph_node *node)
122 {
123  struct spa_graph_link *l;
124  spa_debug("node %p trigger", node);
125  spa_list_for_each(l, &node->links, link)
127  return 0;
128 }
129 
130 static inline int spa_graph_run(struct spa_graph *graph)
131 {
132  struct spa_graph_node *n, *t;
133  struct spa_list pending;
134 
135  spa_graph_state_reset(graph->state);
136  spa_debug("graph %p run with state %p pending %d/%d", graph, graph->state,
137  graph->state->pending, graph->state->required);
138 
139  spa_list_init(&pending);
140 
141  spa_list_for_each(n, &graph->nodes, link) {
142  struct spa_graph_state *s = n->state;
144  spa_debug("graph %p node %p: state %p pending %d/%d status %d", graph, n,
145  s, s->pending, s->required, s->status);
146  if (--s->pending == 0)
147  spa_list_append(&pending, &n->sched_link);
148  }
149  spa_list_for_each_safe(n, t, &pending, sched_link)
151 
152  return 0;
153 }
154 
155 static inline int spa_graph_finish(struct spa_graph *graph)
156 {
157  spa_debug("graph %p finish", graph);
158  if (graph->parent)
159  return spa_graph_node_trigger(graph->parent);
160  return 0;
161 }
162 static inline int spa_graph_link_signal_node(void *data)
163 {
164  struct spa_graph_node *node = (struct spa_graph_node *)data;
165  spa_debug("node %p call process", node);
166  return spa_graph_node_process(node);
167 }
168 
169 static inline int spa_graph_link_signal_graph(void *data)
170 {
171  struct spa_graph_node *node = (struct spa_graph_node *)data;
172  return spa_graph_finish(node->graph);
173 }
174 
175 static inline void spa_graph_init(struct spa_graph *graph, struct spa_graph_state *state)
176 {
178  graph->flags = 0;
180  spa_debug("graph %p init state %p", graph, state);
181 }
182 
183 static inline void
186  struct spa_graph_link *link)
187 {
188  link->state = state;
189  state->required++;
190  spa_debug("node %p add link %p to state %p %d", out, link, state, state->required);
191  spa_list_append(&out->links, &link->link);
192 }
193 
194 static inline void spa_graph_link_remove(struct spa_graph_link *link)
195 {
196  link->state->required--;
197  spa_debug("link %p state %p remove %d", link, link->state, link->state->required);
198  spa_list_remove(&link->link);
199 }
200 
201 static inline void
203 {
206  spa_list_init(&node->links);
207  node->flags = 0;
208  node->subgraph = NULL;
209  node->state = state;
210  node->state->required = node->state->pending = 0;
211  node->state->status = SPA_STATUS_OK;
213  node->graph_link.signal_data = node;
214  spa_debug("node %p init state %p", node, state);
215 }
216 
217 
218 static inline int spa_graph_node_impl_sub_process(void *data SPA_UNUSED, struct spa_graph_node *node)
219 {
220  struct spa_graph *graph = node->subgraph;
221  spa_debug("node %p: sub process %p", node, graph);
222  return spa_graph_run(graph);
223 }
224 
228 };
229 
230 static inline void spa_graph_node_set_subgraph(struct spa_graph_node *node,
231  struct spa_graph *subgraph)
232 {
233  node->subgraph = subgraph;
234  subgraph->parent = node;
235  spa_debug("node %p set subgraph %p", node, subgraph);
236 }
237 
238 static inline void
240  const struct spa_graph_node_callbacks *callbacks,
241  void *data)
242 {
243  node->callbacks = SPA_CALLBACKS_INIT(callbacks, data);
244 }
245 
246 static inline void
247 spa_graph_node_add(struct spa_graph *graph,
248  struct spa_graph_node *node)
249 {
250  node->graph = graph;
251  spa_list_append(&graph->nodes, &node->link);
252  node->state->required++;
253  spa_debug("node %p add to graph %p, state %p required %d",
254  node, graph, node->state, node->state->required);
255  spa_graph_link_add(node, graph->state, &node->graph_link);
256 }
257 
258 static inline void spa_graph_node_remove(struct spa_graph_node *node)
259 {
260  spa_debug("node %p remove from graph %p, state %p required %d",
261  node, node->graph, node->state, node->state->required);
263  node->state->required--;
264  spa_list_remove(&node->link);
265 }
266 
267 
268 static inline void
270  enum spa_direction direction,
271  uint32_t port_id,
272  uint32_t flags)
273 {
274  spa_debug("port %p init type %d id %d", port, direction, port_id);
275  port->direction = direction;
276  port->port_id = port_id;
277  port->flags = flags;
278 }
279 
280 static inline void
282  struct spa_graph_port *port)
283 {
284  spa_debug("port %p add to node %p", port, node);
285  port->node = node;
286  spa_list_append(&node->ports[port->direction], &port->link);
287 }
288 
289 static inline void spa_graph_port_remove(struct spa_graph_port *port)
290 {
291  spa_debug("port %p remove", port);
292  spa_list_remove(&port->link);
293 }
294 
295 static inline void
296 spa_graph_port_link(struct spa_graph_port *out, struct spa_graph_port *in)
297 {
298  spa_debug("port %p link to %p %p %p", out, in, in->node, in->node->state);
299  out->peer = in;
300  in->peer = out;
301 }
302 
303 static inline void
305 {
306  spa_debug("port %p unlink from %p", port, port->peer);
307  if (port->peer) {
308  port->peer->peer = NULL;
309  port->peer = NULL;
310  }
311 }
312 
313 static inline int spa_graph_node_impl_process(void *data, struct spa_graph_node *node)
314 {
315  struct spa_node *n = (struct spa_node *)data;
316  struct spa_graph_state *state = node->state;
317 
318  spa_debug("node %p: process state %p: %d, node %p", node, state, state->status, n);
319  if ((state->status = spa_node_process(n)) != SPA_STATUS_OK)
321 
322  return state->status;
323 }
324 
325 static inline int spa_graph_node_impl_reuse_buffer(void *data, struct spa_graph_node *node SPA_UNUSED,
326  uint32_t port_id, uint32_t buffer_id)
327 {
328  struct spa_node *n = (struct spa_node *)data;
329  return spa_node_port_reuse_buffer(n, port_id, buffer_id);
330 }
331 
334  .process = spa_graph_node_impl_process,
336 };
337 
342 #ifdef __cplusplus
343 } /* extern "C" */
344 #endif
345 
346 #endif /* SPA_GRAPH_H */
spa/utils/defs.h
static void spa_graph_node_set_callbacks(struct spa_graph_node *node, const struct spa_graph_node_callbacks *callbacks, void *data)
Definition: graph.h:249
static void spa_graph_state_reset(struct spa_graph_state *state)
Definition: graph.h:52
static void spa_graph_link_add(struct spa_graph_node *out, struct spa_graph_state *state, struct spa_graph_link *link)
Definition: graph.h:194
static const struct spa_graph_node_callbacks spa_graph_node_impl_default
Definition: graph.h:342
static void spa_graph_port_remove(struct spa_graph_port *port)
Definition: graph.h:299
static void spa_graph_init(struct spa_graph *graph, struct spa_graph_state *state)
Definition: graph.h:185
static void spa_graph_node_add(struct spa_graph *graph, struct spa_graph_node *node)
Definition: graph.h:257
#define spa_graph_link_signal(l)
Definition: graph.h:64
static int spa_graph_run(struct spa_graph *graph)
Definition: graph.h:140
static int spa_graph_node_trigger(struct spa_graph_node *node)
Definition: graph.h:131
static int spa_graph_node_impl_process(void *data, struct spa_graph_node *node)
Definition: graph.h:323
static void spa_graph_node_set_subgraph(struct spa_graph_node *node, struct spa_graph *subgraph)
Definition: graph.h:240
static const struct spa_graph_node_callbacks spa_graph_node_sub_impl_default
Definition: graph.h:235
static int spa_graph_link_trigger(struct spa_graph_link *link)
Definition: graph.h:68
static void spa_graph_node_init(struct spa_graph_node *node, struct spa_graph_state *state)
Definition: graph.h:212
static void spa_graph_port_init(struct spa_graph_port *port, enum spa_direction direction, uint32_t port_id, uint32_t flags)
Definition: graph.h:279
static int spa_graph_finish(struct spa_graph *graph)
Definition: graph.h:165
#define spa_debug(...)
Definition: graph.h:34
static void spa_graph_node_remove(struct spa_graph_node *node)
Definition: graph.h:268
static void spa_graph_port_add(struct spa_graph_node *node, struct spa_graph_port *port)
Definition: graph.h:291
static int spa_graph_node_impl_sub_process(void *data 1, struct spa_graph_node *node)
Definition: graph.h:228
static int spa_graph_link_signal_graph(void *data)
Definition: graph.h:179
static void spa_graph_port_link(struct spa_graph_port *out, struct spa_graph_port *in)
Definition: graph.h:306
#define spa_graph_node_process(n)
Definition: graph.h:119
static void spa_graph_link_remove(struct spa_graph_link *link)
Definition: graph.h:204
static int spa_graph_link_signal_node(void *data)
Definition: graph.h:172
static int spa_graph_node_impl_reuse_buffer(void *data, struct spa_graph_node *node 1, uint32_t port_id, uint32_t buffer_id)
Definition: graph.h:335
#define SPA_VERSION_GRAPH_NODE_CALLBACKS
Definition: graph.h:89
#define spa_graph_state_dec(s)
Definition: graph.h:66
static void spa_graph_port_unlink(struct spa_graph_port *port)
Definition: graph.h:314
#define SPA_CALLBACKS_INIT(_funcs, _data)
Initialize the set of functions funcs as a spa_callbacks, together with _data.
Definition: hook.h:134
static void spa_list_init(struct spa_list *list)
Definition: list.h:35
static void spa_list_remove(struct spa_list *elem)
Definition: list.h:65
#define spa_list_for_each(pos, head, member)
Definition: list.h:107
#define spa_list_append(list, item)
Definition: list.h:77
#define spa_list_for_each_safe(pos, tmp, head, member)
Definition: list.h:125
#define SPA_STATUS_OK
Definition: io.h:80
#define spa_node_port_reuse_buffer(n,...)
Tell an output port to reuse a buffer.
Definition: node.h:759
#define spa_node_process(n)
Process the node.
Definition: node.h:763
#define SPA_UNUSED
Definition: defs.h:285
spa_direction
Definition: defs.h:92
@ SPA_DIRECTION_INPUT
Definition: defs.h:93
@ SPA_DIRECTION_OUTPUT
Definition: defs.h:94
spa/utils/hook.h
spa/node/io.h
spa/utils/list.h
spa/node/node.h
Callbacks, contains the structure with functions and the data passed to the functions.
Definition: hook.h:116
Definition: graph.h:87
int(* process)(void *data, struct spa_graph_node *node)
Definition: graph.h:92
int(* reuse_buffer)(void *data, struct spa_graph_node *node, uint32_t port_id, uint32_t buffer_id)
Definition: graph.h:93
uint32_t version
Definition: graph.h:90
Definition: graph.h:97
uint32_t flags
node flags
Definition: graph.h:102
struct spa_list link
link in graph nodes list
Definition: graph.h:98
struct spa_callbacks callbacks
Definition: graph.h:106
struct spa_graph * graph
owner graph
Definition: graph.h:99
struct spa_graph * subgraph
subgraph or NULL
Definition: graph.h:105
struct spa_graph_link graph_link
link in graph
Definition: graph.h:104
struct spa_list links
list of links to next nodes
Definition: graph.h:101
struct spa_graph_state * state
state of the node
Definition: graph.h:103
struct spa_list ports[2]
list of input and output ports
Definition: graph.h:100
struct spa_list sched_link
link for scheduler
Definition: graph.h:107
Definition: graph.h:122
struct spa_graph_node * node
owner node
Definition: graph.h:124
uint32_t port_id
port id
Definition: graph.h:126
struct spa_graph_port * peer
peer
Definition: graph.h:128
uint32_t flags
port flags
Definition: graph.h:127
enum spa_direction direction
port direction
Definition: graph.h:125
struct spa_list link
link in node port list
Definition: graph.h:123
Definition: graph.h:46
int32_t pending
number of pending signals
Definition: graph.h:49
int32_t required
required number of signals
Definition: graph.h:48
int status
current status
Definition: graph.h:47
Definition: graph.h:80
uint32_t flags
Definition: graph.h:81
struct spa_list nodes
Definition: graph.h:84
struct spa_graph_node * parent
Definition: graph.h:82
struct spa_graph_state * state
Definition: graph.h:83
Definition: list.h:27
Definition: node.h:41