PipeWire  1.4.3
hook.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_HOOK_H
6 #define SPA_HOOK_H
7 
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 
12 #include <spa/utils/defs.h>
13 #include <spa/utils/list.h>
14 
15 #ifndef SPA_API_HOOK
16  #ifdef SPA_API_IMPL
17  #define SPA_API_HOOK SPA_API_IMPL
18  #else
19  #define SPA_API_HOOK static inline
20  #endif
21 #endif
22 
118 struct spa_callbacks {
119  const void *funcs;
120  void *data;
121 };
122 
124 #define SPA_CALLBACK_VERSION_MIN(c,v) ((c) && ((v) == 0 || (c)->version > (v)-1))
125 
127 #define SPA_CALLBACK_CHECK(c,m,v) (SPA_CALLBACK_VERSION_MIN(c,v) && (c)->m)
128 
133 #define SPA_CALLBACKS_INIT(_funcs,_data) ((struct spa_callbacks){ (_funcs), (_data), })
134 
138  const char *type;
139  uint32_t version;
140  struct spa_callbacks cb;
141 };
142 
156 #define SPA_INTERFACE_INIT(_type,_version,_funcs,_data) \
157  ((struct spa_interface){ (_type), (_version), SPA_CALLBACKS_INIT(_funcs,_data), })
158 
164 #define spa_callbacks_call(callbacks,type,method,vers,...) \
165 ({ \
166  const type *_f = (const type *) (callbacks)->funcs; \
167  bool _res = SPA_CALLBACK_CHECK(_f,method,vers); \
168  if (SPA_LIKELY(_res)) \
169  (_f->method)((callbacks)->data, ## __VA_ARGS__); \
170  _res; \
171 })
172 
173 #define spa_callbacks_call_fast(callbacks,type,method,vers,...) \
174 ({ \
175  const type *_f = (const type *) (callbacks)->funcs; \
176  (_f->method)((callbacks)->data, ## __VA_ARGS__); \
177  true; \
178 })
179 
180 
184 #define spa_callback_version_min(callbacks,type,vers) \
185 ({ \
186  const type *_f = (const type *) (callbacks)->funcs; \
187  SPA_CALLBACK_VERSION_MIN(_f,vers); \
188 })
189 
194 #define spa_callback_check(callbacks,type,method,vers) \
195 ({ \
196  const type *_f = (const type *) (callbacks)->funcs; \
197  SPA_CALLBACK_CHECK(_f,method,vers); \
198 })
199 
206 #define spa_callbacks_call_res(callbacks,type,res,method,vers,...) \
207 ({ \
208  const type *_f = (const type *) (callbacks)->funcs; \
209  if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers))) \
210  res = (_f->method)((callbacks)->data, ## __VA_ARGS__); \
211  res; \
212 })
213 #define spa_callbacks_call_fast_res(callbacks,type,res,method,vers,...) \
214 ({ \
215  const type *_f = (const type *) (callbacks)->funcs; \
216  res = (_f->method)((callbacks)->data, ## __VA_ARGS__); \
217 })
218 
222 #define spa_interface_callback_version_min(iface,method_type,vers) \
223  spa_callback_version_min(&(iface)->cb, method_type, vers)
224 
229 #define spa_interface_callback_check(iface,method_type,method,vers) \
230  spa_callback_check(&(iface)->cb, method_type, method, vers)
231 
237 #define spa_interface_call(iface,method_type,method,vers,...) \
238  spa_callbacks_call(&(iface)->cb,method_type,method,vers,##__VA_ARGS__)
239 
240 #define spa_interface_call_fast(iface,method_type,method,vers,...) \
241  spa_callbacks_call_fast(&(iface)->cb,method_type,method,vers,##__VA_ARGS__)
242 
250 #define spa_interface_call_res(iface,method_type,res,method,vers,...) \
251  spa_callbacks_call_res(&(iface)->cb,method_type,res,method,vers,##__VA_ARGS__)
252 
253 #define spa_interface_call_fast_res(iface,method_type,res,method,vers,...) \
254  spa_callbacks_call_fast_res(&(iface)->cb,method_type,res,method,vers,##__VA_ARGS__)
255 
256 
257 #define spa_api_func_v(o,method,version,...) \
258 ({ \
259  if (SPA_LIKELY(SPA_CALLBACK_CHECK(o,method,version))) \
260  ((o)->method)(o, ##__VA_ARGS__); \
261 })
262 #define spa_api_func_r(rtype,def,o,method,version,...) \
263 ({ \
264  rtype _res = def; \
265  if (SPA_LIKELY(SPA_CALLBACK_CHECK(o,method,version))) \
266  _res = ((o)->method)(o, ##__VA_ARGS__); \
267  _res; \
268 })
269 #define spa_api_func_fast(o,method,...) \
270 ({ \
271  ((o)->method)(o, ##__VA_ARGS__); \
272 })
273 
274 #define spa_api_method_v(type,o,method,version,...) \
275 ({ \
276  struct spa_interface *_i = o; \
277  spa_interface_call(_i, struct type ##_methods, \
278  method, version, ##__VA_ARGS__); \
279 })
280 #define spa_api_method_r(rtype,def,type,o,method,version,...) \
281 ({ \
282  rtype _res = def; \
283  struct spa_interface *_i = o; \
284  spa_interface_call_res(_i, struct type ##_methods, \
285  _res, method, version, ##__VA_ARGS__); \
286  _res; \
287 })
288 #define spa_api_method_null_v(type,co,o,method,version,...) \
289 ({ \
290  struct type *_co = co; \
291  if (SPA_LIKELY(_co != NULL)) { \
292  struct spa_interface *_i = o; \
293  spa_interface_call(_i, struct type ##_methods, \
294  method, version, ##__VA_ARGS__); \
295  } \
296 })
297 #define spa_api_method_null_r(rtype,def,type,co,o,method,version,...) \
298 ({ \
299  rtype _res = def; \
300  struct type *_co = co; \
301  if (SPA_LIKELY(_co != NULL)) { \
302  struct spa_interface *_i = o; \
303  spa_interface_call_res(_i, struct type ##_methods, \
304  _res, method, version, ##__VA_ARGS__); \
305  } \
306  _res; \
307 })
308 #define spa_api_method_fast_v(type,o,method,version,...) \
309 ({ \
310  struct spa_interface *_i = o; \
311  spa_interface_call_fast(_i, struct type ##_methods, \
312  method, version, ##__VA_ARGS__); \
313 })
314 #define spa_api_method_fast_r(rtype,def,type,o,method,version,...) \
315 ({ \
316  rtype _res = def; \
317  struct spa_interface *_i = o; \
318  spa_interface_call_fast_res(_i, struct type ##_methods, \
319  _res, method, version, ##__VA_ARGS__); \
320  _res; \
321 })
322 
405 struct spa_hook_list {
406  struct spa_list list;
407 };
408 
409 
416 struct spa_hook {
417  struct spa_list link;
418  struct spa_callbacks cb;
421  void (*removed) (struct spa_hook *hook);
422  void *priv;
423 };
424 
427 {
428  spa_list_init(&list->list);
429 }
430 
432 {
433  return spa_list_is_empty(&list->list);
434 }
435 
438  struct spa_hook *hook,
439  const void *funcs, void *data)
440 {
441  spa_zero(*hook);
442  hook->cb = SPA_CALLBACKS_INIT(funcs, data);
443  spa_list_append(&list->list, &hook->link);
444 }
445 
448  struct spa_hook *hook,
449  const void *funcs, void *data)
450 {
451  spa_zero(*hook);
452  hook->cb = SPA_CALLBACKS_INIT(funcs, data);
453  spa_list_prepend(&list->list, &hook->link);
454 }
455 
457 SPA_API_HOOK void spa_hook_remove(struct spa_hook *hook)
458 {
459  if (spa_list_is_initialized(&hook->link))
460  spa_list_remove(&hook->link);
461  if (hook->removed)
462  hook->removed(hook);
463 }
464 
467 {
468  struct spa_hook *h;
469  spa_list_consume(h, &list->list, link)
470  spa_hook_remove(h);
471 }
472 
473 SPA_API_HOOK void
475  struct spa_hook_list *save,
476  struct spa_hook *hook,
477  const void *funcs, void *data)
478 {
479  /* init save list and move hooks to it */
480  spa_hook_list_init(save);
481  spa_list_insert_list(&save->list, &list->list);
482  /* init hooks and add single hook */
483  spa_hook_list_init(list);
484  spa_hook_list_append(list, hook, funcs, data);
485 }
486 
487 SPA_API_HOOK void
488 spa_hook_list_join(struct spa_hook_list *list,
489  struct spa_hook_list *save)
490 {
491  spa_list_insert_list(&list->list, &save->list);
492 }
493 
494 #define spa_hook_list_call_simple(l,type,method,vers,...) \
495 ({ \
496  struct spa_hook_list *_l = l; \
497  struct spa_hook *_h, *_t; \
498  spa_list_for_each_safe(_h, _t, &_l->list, link) \
499  spa_callbacks_call(&_h->cb,type,method,vers, ## __VA_ARGS__); \
500 })
501 
505 #define spa_hook_list_do_call(l,start,type,method,vers,once,...) \
506 ({ \
507  struct spa_hook_list *_list = l; \
508  struct spa_list *_s = start ? (struct spa_list *)start : &_list->list; \
509  struct spa_hook _cursor = { 0 }, *_ci; \
510  int _count = 0; \
511  spa_list_cursor_start(_cursor, _s, link); \
512  spa_list_for_each_cursor(_ci, _cursor, &_list->list, link) { \
513  if (spa_callbacks_call(&_ci->cb,type,method,vers, ## __VA_ARGS__)) { \
514  _count++; \
515  if (once) \
516  break; \
517  } \
518  } \
519  spa_list_cursor_end(_cursor, link); \
520  _count; \
521 })
522 
527 #define spa_hook_list_call(l,t,m,v,...) spa_hook_list_do_call(l,NULL,t,m,v,false,##__VA_ARGS__)
533 #define spa_hook_list_call_once(l,t,m,v,...) spa_hook_list_do_call(l,NULL,t,m,v,true,##__VA_ARGS__)
534 
535 #define spa_hook_list_call_start(l,s,t,m,v,...) spa_hook_list_do_call(l,s,t,m,v,false,##__VA_ARGS__)
536 #define spa_hook_list_call_once_start(l,s,t,m,v,...) spa_hook_list_do_call(l,s,t,m,v,true,##__VA_ARGS__)
537 
542 #ifdef __cplusplus
543 }
544 #endif
545 
546 #endif /* SPA_HOOK_H */
spa/utils/defs.h
SPA_API_HOOK bool spa_hook_list_is_empty(struct spa_hook_list *list)
Definition: hook.h:442
SPA_API_HOOK void spa_hook_list_clean(struct spa_hook_list *list)
Remove all hooks from the list.
Definition: hook.h:477
SPA_API_HOOK void spa_hook_list_isolate(struct spa_hook_list *list, struct spa_hook_list *save, struct spa_hook *hook, const void *funcs, void *data)
Definition: hook.h:485
SPA_API_HOOK void spa_hook_remove(struct spa_hook *hook)
Remove a hook.
Definition: hook.h:468
SPA_API_HOOK void spa_hook_list_join(struct spa_hook_list *list, struct spa_hook_list *save)
Definition: hook.h:499
SPA_API_HOOK void spa_hook_list_prepend(struct spa_hook_list *list, struct spa_hook *hook, const void *funcs, void *data)
Prepend a hook.
Definition: hook.h:458
SPA_API_HOOK void spa_hook_list_append(struct spa_hook_list *list, struct spa_hook *hook, const void *funcs, void *data)
Append a hook.
Definition: hook.h:448
SPA_API_HOOK void spa_hook_list_init(struct spa_hook_list *list)
Initialize a hook list to the empty list.
Definition: hook.h:437
#define SPA_CALLBACKS_INIT(_funcs, _data)
Initialize the set of functions funcs as a spa_callbacks, together with _data.
Definition: hook.h:144
SPA_API_LIST int spa_list_is_initialized(struct spa_list *list)
Definition: list.h:52
#define spa_list_consume(pos, head, member)
Definition: list.h:104
SPA_API_LIST void spa_list_insert_list(struct spa_list *list, struct spa_list *other)
Definition: list.h:67
SPA_API_LIST void spa_list_init(struct spa_list *list)
Definition: list.h:47
SPA_API_LIST void spa_list_remove(struct spa_list *elem)
Definition: list.h:77
#define spa_list_prepend(list, item)
Definition: list.h:92
#define spa_list_is_empty(l)
Definition: list.h:57
#define spa_list_append(list, item)
Definition: list.h:89
#define spa_zero(x)
Definition: defs.h:508
#define SPA_API_HOOK
Definition: hook.h:27
spa/utils/list.h
Callbacks, contains the structure with functions and the data passed to the functions.
Definition: hook.h:126
const void * funcs
Definition: hook.h:127
void * data
Definition: hook.h:128
A list of hooks.
Definition: hook.h:416
struct spa_list list
Definition: hook.h:417
A hook, contains the structure with functions and the data passed to the functions.
Definition: hook.h:427
void(* removed)(struct spa_hook *hook)
callback and data for the hook list, private to the hook_list implementor
Definition: hook.h:432
struct spa_callbacks cb
Definition: hook.h:429
struct spa_list link
Definition: hook.h:428
void * priv
Definition: hook.h:433
Definition: hook.h:148
uint32_t version
Definition: hook.h:150
const char * type
Definition: hook.h:149
struct spa_callbacks cb
Definition: hook.h:151
Definition: list.h:39