PipeWire  1.0.0
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 
110 struct spa_callbacks {
111  const void *funcs;
112  void *data;
113 };
114 
116 #define SPA_CALLBACK_VERSION_MIN(c,v) ((c) && ((v) == 0 || (c)->version > (v)-1))
117 
119 #define SPA_CALLBACK_CHECK(c,m,v) (SPA_CALLBACK_VERSION_MIN(c,v) && (c)->m)
120 
125 #define SPA_CALLBACKS_INIT(_funcs,_data) ((struct spa_callbacks){ (_funcs), (_data), })
126 
129 struct spa_interface {
130  const char *type;
131  uint32_t version;
132  struct spa_callbacks cb;
133 };
134 
148 #define SPA_INTERFACE_INIT(_type,_version,_funcs,_data) \
149  ((struct spa_interface){ (_type), (_version), SPA_CALLBACKS_INIT(_funcs,_data), })
150 
156 #define spa_callbacks_call(callbacks,type,method,vers,...) \
157 ({ \
158  const type *_f = (const type *) (callbacks)->funcs; \
159  bool _res = SPA_CALLBACK_CHECK(_f,method,vers); \
160  if (SPA_LIKELY(_res)) \
161  _f->method((callbacks)->data, ## __VA_ARGS__); \
162  _res; \
163 })
164 
165 #define spa_callbacks_call_fast(callbacks,type,method,vers,...) \
166 ({ \
167  const type *_f = (const type *) (callbacks)->funcs; \
168  _f->method((callbacks)->data, ## __VA_ARGS__); \
169  true; \
170 })
171 
172 
176 #define spa_callback_version_min(callbacks,type,vers) \
177 ({ \
178  const type *_f = (const type *) (callbacks)->funcs; \
179  SPA_CALLBACK_VERSION_MIN(_f,vers); \
180 })
181 
186 #define spa_callback_check(callbacks,type,method,vers) \
187 ({ \
188  const type *_f = (const type *) (callbacks)->funcs; \
189  SPA_CALLBACK_CHECK(_f,method,vers); \
190 })
191 
198 #define spa_callbacks_call_res(callbacks,type,res,method,vers,...) \
199 ({ \
200  const type *_f = (const type *) (callbacks)->funcs; \
201  if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers))) \
202  res = _f->method((callbacks)->data, ## __VA_ARGS__); \
203  res; \
204 })
205 #define spa_callbacks_call_fast_res(callbacks,type,res,method,vers,...) \
206 ({ \
207  const type *_f = (const type *) (callbacks)->funcs; \
208  res = _f->method((callbacks)->data, ## __VA_ARGS__); \
209 })
210 
214 #define spa_interface_callback_version_min(iface,method_type,vers) \
215  spa_callback_version_min(&(iface)->cb, method_type, vers)
216 
221 #define spa_interface_callback_check(iface,method_type,method,vers) \
222  spa_callback_check(&(iface)->cb, method_type, method, vers)
223 
229 #define spa_interface_call(iface,method_type,method,vers,...) \
230  spa_callbacks_call(&(iface)->cb,method_type,method,vers,##__VA_ARGS__)
231 
232 #define spa_interface_call_fast(iface,method_type,method,vers,...) \
233  spa_callbacks_call_fast(&(iface)->cb,method_type,method,vers,##__VA_ARGS__)
234 
242 #define spa_interface_call_res(iface,method_type,res,method,vers,...) \
243  spa_callbacks_call_res(&(iface)->cb,method_type,res,method,vers,##__VA_ARGS__)
244 
245 #define spa_interface_call_fast_res(iface,method_type,res,method,vers,...) \
246  spa_callbacks_call_fast_res(&(iface)->cb,method_type,res,method,vers,##__VA_ARGS__)
247 
330 struct spa_hook_list {
331  struct spa_list list;
332 };
333 
334 
341 struct spa_hook {
342  struct spa_list link;
343  struct spa_callbacks cb;
346  void (*removed) (struct spa_hook *hook);
347  void *priv;
348 };
349 
351 static inline void spa_hook_list_init(struct spa_hook_list *list)
352 {
353  spa_list_init(&list->list);
354 }
355 
356 static inline bool spa_hook_list_is_empty(struct spa_hook_list *list)
357 {
358  return spa_list_is_empty(&list->list);
359 }
360 
362 static inline void spa_hook_list_append(struct spa_hook_list *list,
363  struct spa_hook *hook,
364  const void *funcs, void *data)
365 {
366  spa_zero(*hook);
367  hook->cb = SPA_CALLBACKS_INIT(funcs, data);
368  spa_list_append(&list->list, &hook->link);
369 }
370 
372 static inline void spa_hook_list_prepend(struct spa_hook_list *list,
373  struct spa_hook *hook,
374  const void *funcs, void *data)
375 {
376  spa_zero(*hook);
377  hook->cb = SPA_CALLBACKS_INIT(funcs, data);
378  spa_list_prepend(&list->list, &hook->link);
379 }
380 
382 static inline void spa_hook_remove(struct spa_hook *hook)
383 {
384  if (spa_list_is_initialized(&hook->link))
385  spa_list_remove(&hook->link);
386  if (hook->removed)
387  hook->removed(hook);
388 }
389 
391 static inline void spa_hook_list_clean(struct spa_hook_list *list)
392 {
393  struct spa_hook *h;
394  spa_list_consume(h, &list->list, link)
395  spa_hook_remove(h);
396 }
397 
398 static inline void
400  struct spa_hook_list *save,
401  struct spa_hook *hook,
402  const void *funcs, void *data)
403 {
404  /* init save list and move hooks to it */
405  spa_hook_list_init(save);
406  spa_list_insert_list(&save->list, &list->list);
407  /* init hooks and add single hook */
409  spa_hook_list_append(list, hook, funcs, data);
410 }
411 
412 static inline void
413 spa_hook_list_join(struct spa_hook_list *list,
414  struct spa_hook_list *save)
415 {
416  spa_list_insert_list(&list->list, &save->list);
417 }
418 
419 #define spa_hook_list_call_simple(l,type,method,vers,...) \
420 ({ \
421  struct spa_hook_list *_l = l; \
422  struct spa_hook *_h, *_t; \
423  spa_list_for_each_safe(_h, _t, &_l->list, link) \
424  spa_callbacks_call(&_h->cb,type,method,vers, ## __VA_ARGS__); \
425 })
426 
430 #define spa_hook_list_do_call(l,start,type,method,vers,once,...) \
431 ({ \
432  struct spa_hook_list *_list = l; \
433  struct spa_list *_s = start ? (struct spa_list *)start : &_list->list; \
434  struct spa_hook _cursor = { 0 }, *_ci; \
435  int _count = 0; \
436  spa_list_cursor_start(_cursor, _s, link); \
437  spa_list_for_each_cursor(_ci, _cursor, &_list->list, link) { \
438  if (spa_callbacks_call(&_ci->cb,type,method,vers, ## __VA_ARGS__)) { \
439  _count++; \
440  if (once) \
441  break; \
442  } \
443  } \
444  spa_list_cursor_end(_cursor, link); \
445  _count; \
446 })
447 
452 #define spa_hook_list_call(l,t,m,v,...) spa_hook_list_do_call(l,NULL,t,m,v,false,##__VA_ARGS__)
458 #define spa_hook_list_call_once(l,t,m,v,...) spa_hook_list_do_call(l,NULL,t,m,v,true,##__VA_ARGS__)
459 
460 #define spa_hook_list_call_start(l,s,t,m,v,...) spa_hook_list_do_call(l,s,t,m,v,false,##__VA_ARGS__)
461 #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__)
462 
467 #ifdef __cplusplus
468 }
469 #endif
470 
471 #endif /* SPA_HOOK_H */
spa/utils/defs.h
static bool spa_hook_list_is_empty(struct spa_hook_list *list)
Definition: hook.h:365
static 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:371
static void spa_hook_list_join(struct spa_hook_list *list, struct spa_hook_list *save)
Definition: hook.h:422
static void spa_hook_list_init(struct spa_hook_list *list)
Initialize a hook list to the empty list.
Definition: hook.h:360
static void spa_hook_remove(struct spa_hook *hook)
Remove a hook.
Definition: hook.h:391
static void spa_hook_list_clean(struct spa_hook_list *list)
Remove all hooks from the list.
Definition: hook.h:400
static 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:381
static 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:408
#define SPA_CALLBACKS_INIT(_funcs, _data)
Initialize the set of functions funcs as a spa_callbacks, together with _data.
Definition: hook.h:134
static int spa_list_is_initialized(struct spa_list *list)
Definition: list.h:40
#define spa_list_consume(pos, head, member)
Definition: list.h:92
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_prepend(list, item)
Definition: list.h:80
#define spa_list_is_empty(l)
Definition: list.h:45
#define spa_list_append(list, item)
Definition: list.h:77
static void spa_list_insert_list(struct spa_list *list, struct spa_list *other)
Definition: list.h:55
#define spa_zero(x)
Definition: defs.h:417
spa/utils/list.h
Callbacks, contains the structure with functions and the data passed to the functions.
Definition: hook.h:116
const void * funcs
Definition: hook.h:117
void * data
Definition: hook.h:118
A list of hooks.
Definition: hook.h:339
struct spa_list list
Definition: hook.h:340
A hook, contains the structure with functions and the data passed to the functions.
Definition: hook.h:350
void(* removed)(struct spa_hook *hook)
callback and data for the hook list, private to the hook_list implementor
Definition: hook.h:355
struct spa_callbacks cb
Definition: hook.h:352
struct spa_list link
Definition: hook.h:351
void * priv
Definition: hook.h:356
Definition: hook.h:138
uint32_t version
Definition: hook.h:140
const char * type
Definition: hook.h:139
struct spa_callbacks cb
Definition: hook.h:141
Definition: list.h:27