node: make add_listener method

Make struct spa_node_events for events emited from the main thread
and keep the spa_node_callbacks for the data thread callbacks.

The add_listener method installs the events and it's possible to
install multiple handles. Adding a listener first emits the info
and port_info events when installed, similar to how the PipeWire
proxy bind works.

This removes the need for the spa_pending_queue and makes it easier
to implement the _sync versions.

Add some helpers to make it easier for plugins to emit all the info
to new listeners.

Use the listeners for devices as well.
This commit is contained in:
Wim Taymans 2019-03-01 12:00:42 +01:00
parent 61ce4e77f6
commit 0390969228
53 changed files with 1774 additions and 1307 deletions

View file

@ -87,16 +87,43 @@ static inline void spa_hook_remove(struct spa_hook *hook)
hook->removed(hook);
}
static inline void
spa_hook_list_isolate(struct spa_hook_list *list,
struct spa_hook_list *save,
struct spa_hook *hook,
const void *funcs, void *data)
{
/* init save list and move hooks to it */
spa_hook_list_init(save);
if (!spa_list_is_empty(&list->list))
spa_list_insert_list(&save->list, &list->list);
/* init hooks and add single hook */
spa_hook_list_init(list);
spa_hook_list_append(list, hook, funcs, data);
}
static inline void
spa_hook_list_join(struct spa_hook_list *list,
struct spa_hook_list *save)
{
if (!spa_list_is_empty(&save->list))
spa_list_insert_list(&list->list, &save->list);
}
#define spa_hook_call(hook,type,method,vers,...) \
({ \
const type *cb = hook->funcs; \
if (cb && cb->version >= vers && cb->method) { \
cb->method(hook->data, ## __VA_ARGS__); \
} \
})
#define spa_hook_list_call_simple(l,type,method,vers,...) \
({ \
struct spa_hook_list *list = l; \
struct spa_hook *ci; \
spa_list_for_each(ci, &list->list, link) { \
const type *cb = ci->funcs; \
if (cb && cb->version >= vers && cb->method) { \
cb->method(ci->data, ## __VA_ARGS__); \
} \
} \
struct spa_hook_list *_l = l; \
struct spa_hook *_h, *_t; \
spa_list_for_each_safe(_h, _t, &_l->list, link) \
spa_hook_call(_h,type,method,vers, ## __VA_ARGS__); \
})
/** Call all hooks in a list, starting from the given one and optionally stopping

View file

@ -43,55 +43,6 @@ extern "C" {
#define SPA_RESULT_ASYNC_SEQ(res) ((res) & SPA_ASYNC_SEQ_MASK)
#define SPA_RESULT_RETURN_ASYNC(seq) (SPA_ASYNC_BIT | SPA_RESULT_ASYNC_SEQ(seq))
struct spa_pending;
typedef int (*spa_pending_func_t) (struct spa_pending *pending, const void *result);
struct spa_pending {
struct spa_list link; /**< link used internally */
int seq; /**< sequence number of pending result */
int res; /**< result code of operation, valid in callback */
spa_pending_func_t func; /**< callback function */
void *data; /**< extra user data */
};
static inline void spa_pending_remove(struct spa_pending *pending)
{
spa_list_remove(&pending->link);
}
struct spa_pending_queue {
struct spa_list pending;
int seq;
};
static inline void spa_pending_queue_init(struct spa_pending_queue *queue)
{
spa_list_init(&queue->pending);
}
static inline void spa_pending_queue_add(struct spa_pending_queue *queue,
int seq, struct spa_pending *pending, spa_pending_func_t func, void *data)
{
pending->seq = seq;
pending->func = func;
pending->data = data;
spa_list_append(&queue->pending, &pending->link);
}
static inline int spa_pending_queue_complete(struct spa_pending_queue *queue,
int seq, int res, const void *result)
{
struct spa_pending *p, *t;
spa_list_for_each_safe(p, t, &queue->pending, link) {
if (p->seq == seq) {
p->res = res;
p->func(p, result);
}
}
return 0;
}
#ifdef __cplusplus
} /* extern "C" */
#endif