interface: add an interface struct

The interface struct has the type,version and methods of the
interface.
Make spa interfaces extend from spa_interface and make a
separate structure for the methods.
Pass a generic void* as the first argument of methods, like
we don in PipeWire.
Bundle the methods + implementation in a versioned inteface
and use that to invoke methods. This way we can do version
checks on the methods.
Make resource and proxy interfaces that we can can call. We
can then make the core interfaces independent on proxy/resource and
hide them in the lower layers.
Add add_listener method to methods of core interfaces, just
like SPA.
This commit is contained in:
Wim Taymans 2019-05-20 16:11:23 +02:00
parent eb6481efb3
commit ff946e3d4b
85 changed files with 3051 additions and 3000 deletions

View file

@ -29,15 +29,18 @@
extern "C" {
#endif
struct spa_loop;
struct spa_loop_control;
struct spa_loop_utils;
struct spa_source;
#include <spa/utils/defs.h>
#include <spa/utils/hook.h>
#include <spa/utils/result.h>
#define SPA_VERSION_LOOP 0
struct spa_loop { struct spa_interface iface; };
#define SPA_VERSION_LOOP_CONTROL 0
struct spa_loop_control { struct spa_interface iface; };
#define SPA_VERSION_LOOP_UTILS 0
struct spa_loop_utils { struct spa_interface iface; };
struct spa_source;
enum spa_io {
SPA_IO_IN = (1 << 0),
SPA_IO_OUT = (1 << 1),
@ -66,24 +69,26 @@ typedef int (*spa_invoke_func_t) (struct spa_loop *loop,
/**
* Register sources and work items to an event loop
*/
struct spa_loop {
struct spa_loop_methods {
/* the version of this structure. This can be used to expand this
* structure in the future */
#define SPA_VERSION_LOOP 0
#define SPA_VERSION_LOOP_METHODS 0
uint32_t version;
/** add a source to the loop */
int (*add_source) (struct spa_loop *loop,
int (*add_source) (void *object,
struct spa_source *source);
/** update the source io mask */
int (*update_source) (struct spa_source *source);
int (*update_source) (void *object,
struct spa_source *source);
/** remove a source from the loop */
void (*remove_source) (struct spa_source *source);
int (*remove_source) (void *object,
struct spa_source *source);
/** invoke a function in the context of this loop */
int (*invoke) (struct spa_loop *loop,
int (*invoke) (void *object,
spa_invoke_func_t func,
uint32_t seq,
const void *data,
@ -92,10 +97,20 @@ struct spa_loop {
void *user_data);
};
#define spa_loop_add_source(l,...) (l)->add_source((l),__VA_ARGS__)
#define spa_loop_update_source(l,...) (l)->update_source(__VA_ARGS__)
#define spa_loop_remove_source(l,...) (l)->remove_source(__VA_ARGS__)
#define spa_loop_invoke(l,...) (l)->invoke((l),__VA_ARGS__)
#define spa_loop_method(o,method,version,...) \
({ \
int _res = -ENOTSUP; \
struct spa_loop *_o = o; \
spa_interface_call_res(&_o->iface, \
struct spa_loop_methods, _res, \
method, version, ##__VA_ARGS__); \
_res; \
})
#define spa_loop_add_source(l,...) spa_loop_method(l,add_source,0,##__VA_ARGS__)
#define spa_loop_update_source(l,...) spa_loop_method(l,update_source,0,##__VA_ARGS__)
#define spa_loop_remove_source(l,...) spa_loop_method(l,remove_source,0,##__VA_ARGS__)
#define spa_loop_invoke(l,...) spa_loop_method(l,invoke,0,##__VA_ARGS__)
/** Control hooks */
@ -116,13 +131,13 @@ struct spa_loop_control_hooks {
/**
* Control an event loop
*/
struct spa_loop_control {
struct spa_loop_control_methods {
/* the version of this structure. This can be used to expand this
* structure in the future */
#define SPA_VERSION_LOOP_CONTROL 0
#define SPA_VERSION_LOOP_CONTROL_METHODS 0
uint32_t version;
int (*get_fd) (struct spa_loop_control *ctrl);
int (*get_fd) (void *object);
/** Add a hook
* \param ctrl the control to change
@ -130,7 +145,7 @@ struct spa_loop_control {
*
* Adds hooks to the loop controlled by \a ctrl.
*/
void (*add_hook) (struct spa_loop_control *ctrl,
void (*add_hook) (void *object,
struct spa_hook *hook,
const struct spa_loop_control_hooks *hooks,
void *data);
@ -142,14 +157,14 @@ struct spa_loop_control {
* before calling iterate and is typically used to capture the thread
* that this loop will run in.
*/
void (*enter) (struct spa_loop_control *ctrl);
void (*enter) (void *object);
/** Leave a loop
* \param ctrl the control
*
* Ends the iteration of a loop. This should be called after calling
* iterate.
*/
void (*leave) (struct spa_loop_control *ctrl);
void (*leave) (void *object);
/** Perform one iteration of the loop.
* \param ctrl the control
@ -160,14 +175,32 @@ struct spa_loop_control {
* up to \a timeout and then dispatch the fds with activity.
* The number of dispatched fds is returned.
*/
int (*iterate) (struct spa_loop_control *ctrl, int timeout);
int (*iterate) (void *object, int timeout);
};
#define spa_loop_control_get_fd(l) (l)->get_fd(l)
#define spa_loop_control_add_hook(l,...) (l)->add_hook((l),__VA_ARGS__)
#define spa_loop_control_enter(l) (l)->enter(l)
#define spa_loop_control_iterate(l,...) (l)->iterate((l),__VA_ARGS__)
#define spa_loop_control_leave(l) (l)->leave(l)
#define spa_loop_control_method_v(o,method,version,...) \
({ \
struct spa_loop_control *_o = o; \
spa_interface_call(&_o->iface, \
struct spa_loop_control_methods, \
method, version, ##__VA_ARGS__); \
})
#define spa_loop_control_method_r(o,method,version,...) \
({ \
int _res = -ENOTSUP; \
struct spa_loop_control *_o = o; \
spa_interface_call_res(&_o->iface, \
struct spa_loop_control_methods, _res, \
method, version, ##__VA_ARGS__); \
_res; \
})
#define spa_loop_control_get_fd(l) spa_loop_control_method_r(l,get_fd,0)
#define spa_loop_control_add_hook(l,...) spa_loop_control_method_v(l,add_hook,0,__VA_ARGS__)
#define spa_loop_control_enter(l) spa_loop_control_method_v(l,enter,0)
#define spa_loop_control_leave(l) spa_loop_control_method_v(l,leave,0)
#define spa_loop_control_iterate(l,...) spa_loop_control_method_r(l,iterate,0,__VA_ARGS__)
typedef void (*spa_source_io_func_t) (void *data, int fd, enum spa_io mask);
@ -179,55 +212,84 @@ typedef void (*spa_source_signal_func_t) (void *data, int signal_number);
/**
* Create sources for an event loop
*/
struct spa_loop_utils {
struct spa_loop_utils_methods {
/* the version of this structure. This can be used to expand this
* structure in the future */
#define SPA_VERSION_LOOP_UTILS 0
#define SPA_VERSION_LOOP_UTILS_METHODS 0
uint32_t version;
struct spa_source *(*add_io) (struct spa_loop_utils *utils,
struct spa_source *(*add_io) (void *object,
int fd,
enum spa_io mask,
bool close,
spa_source_io_func_t func, void *data);
int (*update_io) (struct spa_source *source, enum spa_io mask);
int (*update_io) (void *object, struct spa_source *source, enum spa_io mask);
struct spa_source *(*add_idle) (struct spa_loop_utils *utils,
struct spa_source *(*add_idle) (void *object,
bool enabled,
spa_source_idle_func_t func, void *data);
void (*enable_idle) (struct spa_source *source, bool enabled);
void (*enable_idle) (void *object, struct spa_source *source, bool enabled);
struct spa_source *(*add_event) (struct spa_loop_utils *utils,
struct spa_source *(*add_event) (void *object,
spa_source_event_func_t func, void *data);
void (*signal_event) (struct spa_source *source);
void (*signal_event) (void *object, struct spa_source *source);
struct spa_source *(*add_timer) (struct spa_loop_utils *utils,
struct spa_source *(*add_timer) (void *object,
spa_source_timer_func_t func, void *data);
int (*update_timer) (struct spa_source *source,
int (*update_timer) (void *object,
struct spa_source *source,
struct timespec *value,
struct timespec *interval,
bool absolute);
struct spa_source *(*add_signal) (struct spa_loop_utils *utils,
struct spa_source *(*add_signal) (void *object,
int signal_number,
spa_source_signal_func_t func, void *data);
/** destroy a source allocated with this interface. This function
* should only be called when the loop is not running or from the
* context of the running loop */
void (*destroy_source) (struct spa_source *source);
void (*destroy_source) (void *object, struct spa_source *source);
};
#define spa_loop_utils_add_io(l,...) (l)->add_io(l,__VA_ARGS__)
#define spa_loop_utils_update_io(l,...) (l)->update_io(__VA_ARGS__)
#define spa_loop_utils_add_idle(l,...) (l)->add_idle(l,__VA_ARGS__)
#define spa_loop_utils_enable_idle(l,...) (l)->enable_idle(__VA_ARGS__)
#define spa_loop_utils_add_event(l,...) (l)->add_event(l,__VA_ARGS__)
#define spa_loop_utils_signal_event(l,...) (l)->signal_event(__VA_ARGS__)
#define spa_loop_utils_add_timer(l,...) (l)->add_timer(l,__VA_ARGS__)
#define spa_loop_utils_update_timer(l,...) (l)->update_timer(__VA_ARGS__)
#define spa_loop_utils_add_signal(l,...) (l)->add_signal(l,__VA_ARGS__)
#define spa_loop_utils_destroy_source(l,...) (l)->destroy_source(__VA_ARGS__)
#define spa_loop_utils_method_v(o,method,version,...) \
({ \
struct spa_loop_utils *_o = o; \
spa_interface_call(&_o->iface, \
struct spa_loop_utils_methods, \
method, version, ##__VA_ARGS__); \
})
#define spa_loop_utils_method_r(o,method,version,...) \
({ \
int _res = -ENOTSUP; \
struct spa_loop_utils *_o = o; \
spa_interface_call_res(&_o->iface, \
struct spa_loop_utils_methods, _res, \
method, version, ##__VA_ARGS__); \
_res; \
})
#define spa_loop_utils_method_s(o,method,version,...) \
({ \
struct spa_source *_res = NULL; \
struct spa_loop_utils *_o = o; \
spa_interface_call_res(&_o->iface, \
struct spa_loop_utils_methods, _res, \
method, version, ##__VA_ARGS__); \
_res; \
})
#define spa_loop_utils_add_io(l,...) spa_loop_utils_method_s(l,add_io,0,__VA_ARGS__)
#define spa_loop_utils_update_io(l,...) spa_loop_utils_method_r(l,update_io,0,__VA_ARGS__)
#define spa_loop_utils_add_idle(l,...) spa_loop_utils_method_s(l,add_idle,0,__VA_ARGS__)
#define spa_loop_utils_enable_idle(l,...) spa_loop_utils_method_v(l,enable_idle,0,__VA_ARGS__)
#define spa_loop_utils_add_event(l,...) spa_loop_utils_method_s(l,add_event,0,__VA_ARGS__)
#define spa_loop_utils_signal_event(l,...) spa_loop_utils_method_v(l,signal_event,0,__VA_ARGS__)
#define spa_loop_utils_add_timer(l,...) spa_loop_utils_method_s(l,add_timer,0,__VA_ARGS__)
#define spa_loop_utils_update_timer(l,...) spa_loop_utils_method_r(l,update_timer,0,__VA_ARGS__)
#define spa_loop_utils_add_signal(l,...) spa_loop_utils_method_s(l,add_signal,0,__VA_ARGS__)
#define spa_loop_utils_destroy_source(l,...) spa_loop_utils_method_v(l,destroy_source,0,__VA_ARGS__)
#ifdef __cplusplus
} /* extern "C" */