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

@ -97,8 +97,6 @@ struct data {
bool rebuild_fds;
struct pollfd fds[16];
unsigned int n_fds;
struct spa_pending_queue pending;
};
#define MIN_LATENCY 1024
@ -377,8 +375,7 @@ static int negotiate_formats(struct data *data)
if ((res = spa_node_port_enum_params_sync(data->sink,
SPA_DIRECTION_INPUT, 0,
SPA_PARAM_EnumFormat, &state,
filter, &format, &b,
&data->pending)) != 1)
filter, &format, &b)) != 1)
return -EBADF;
spa_log_debug(&default_log.log, "sink set_param");
@ -514,8 +511,6 @@ int main(int argc, char *argv[])
data.data_loop.remove_source = do_remove_source;
data.data_loop.invoke = do_invoke;
spa_pending_queue_init(&data.pending);
if ((str = getenv("SPA_DEBUG")))
data.log->level = atoi(str);

View file

@ -68,6 +68,7 @@ struct data {
uint32_t n_support;
struct spa_node *source;
struct spa_hook listener;
struct spa_io_buffers source_output[1];
SDL_Renderer *renderer;
@ -89,8 +90,6 @@ struct data {
struct spa_buffer *bp[MAX_BUFFERS];
struct buffer buffers[MAX_BUFFERS];
unsigned int n_buffers;
struct spa_pending_queue pending;
};
static int load_handle(struct data *data, struct spa_handle **handle, const char *lib, const char *name)
@ -242,16 +241,9 @@ static int on_source_ready(void *_data, int status)
return 0;
}
static int on_source_result(void *_data, int seq, int res, const void *result)
{
struct data *data = _data;
return spa_pending_queue_complete(&data->pending, seq, res, result);
}
static const struct spa_node_callbacks source_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
.ready = on_source_ready,
.result = on_source_result,
};
static int make_nodes(struct data *data, const char *device)
@ -273,7 +265,7 @@ static int make_nodes(struct data *data, const char *device)
index = 0;
spa_pod_builder_init(&b, buffer, sizeof(buffer));
if ((res = spa_node_enum_params_sync(data->source, SPA_PARAM_Props,
&index, NULL, &props, &b, &data->pending)) == 1) {
&index, NULL, &props, &b)) == 1) {
spa_debug_pod(0, NULL, props);
}
@ -477,8 +469,6 @@ int main(int argc, char *argv[])
struct spa_handle *handle = NULL;
void *iface;
spa_pending_queue_init(&data.pending);
if ((res = load_handle(&data, &handle, PATH "support/libspa-support.so", "loop")) < 0)
return res;

View file

@ -39,8 +39,8 @@ extern "C" {
int spa_debug_port_info(int indent, const struct spa_port_info *info)
{
spa_debug("%*s" "struct spa_port_info %p:", indent, "", info);
spa_debug("%*s" " flags: \t%08x", indent, "", info->flags);
spa_debug("%*s" " rate: \t%u", indent, "", info->rate);
spa_debug("%*s" " flags: \t%08lx", indent, "", info->flags);
spa_debug("%*s" " rate: \t%d/%d", indent, "", info->rate.num, info->rate.denom);
spa_debug("%*s" " props:", indent, "");
if (info->props)
spa_debug_dict(indent + 2, info->props);

View file

@ -41,9 +41,11 @@ struct spa_device_info {
#define SPA_VERSION_DEVICE_INFO 0
uint32_t version;
#define SPA_DEVICE_CHANGE_MASK_PROPS (1<<0)
#define SPA_DEVICE_CHANGE_MASK_PARAMS (1<<1)
#define SPA_DEVICE_CHANGE_MASK_FLAGS (1u<<0)
#define SPA_DEVICE_CHANGE_MASK_PROPS (1u<<1)
#define SPA_DEVICE_CHANGE_MASK_PARAMS (1u<<2)
uint64_t change_mask;
uint64_t flags;
const struct spa_dict *props;
struct spa_param_info *params;
uint32_t n_params;
@ -58,8 +60,10 @@ struct spa_device_object_info {
uint32_t type;
const struct spa_handle_factory *factory;
#define SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS (1<<0)
#define SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS (1u<<0)
#define SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS (1u<<1)
uint64_t change_mask;
uint64_t flags;
const struct spa_dict *props;
};
@ -74,11 +78,13 @@ struct spa_result_device_params {
};
/**
* spa_device_callbacks:
* spa_device_events:
*
* Events are always emited from the main thread
*/
struct spa_device_callbacks {
struct spa_device_events {
/** version of the structure */
#define SPA_VERSION_DEVICE_CALLBACKS 0
#define SPA_VERSION_DEVICE_EVENTS 0
uint32_t version;
/** notify extra information about the device */
@ -96,6 +102,15 @@ struct spa_device_callbacks {
const struct spa_device_object_info *info);
};
#define spa_device_emit(hooks,method,version,...) \
spa_hook_list_call_simple(hooks, struct spa_device_events, \
method, version, ##__VA_ARGS__)
#define spa_device_emit_info(hooks,i) spa_device_emit(hooks,info, 0, i)
#define spa_device_emit_result(hooks,s,r,res) spa_device_emit(hooks,result, 0, s, r, res)
#define spa_device_emit_events(hooks,e) spa_device_emit(hooks,event, 0, e)
#define spa_device_emit_object_info(hooks,id,i) spa_device_emit(hooks,object_info, 0, id, i)
/**
* spa_device:
*
@ -108,20 +123,24 @@ struct spa_device {
uint32_t version;
/**
* Set callbacks to receive asynchronous notifications from
* Set events to receive asynchronous notifications from
* the device.
*
* Setting the callbacks will trigger the info event and an
* add event for each managed node.
* Setting the events will trigger the info event and an
* object_info event for each managed node on the new
* listener.
*
* \param device: a #spa_device
* \param callback: a #callbacks
* \param device a #spa_device
* \param listener a listener
* \param events a #struct spa_device_events
* \param data data passed as first argument in functions of \a events
* \return 0 on success
* < 0 errno on error
*/
int (*set_callbacks) (struct spa_device *device,
const struct spa_device_callbacks *callbacks,
void *data);
int (*add_listener) (struct spa_device *device,
struct spa_hook *listener,
const struct spa_device_events *events,
void *data);
/**
* Enumerate the parameters of a device.
*
@ -130,18 +149,16 @@ struct spa_device {
*
* Parameters can be filtered by passing a non-NULL \a filter.
*
* This function must be called from the main thread.
* The result callback will be called at most \max times with a
* struct spa_result_device_params as the result.
*
* The result callback will be called at most \num times with a
* struct spa_result_device_params as the result. If the result
* callback returns anything other than 0, this function will stop
* and return that value.
* This function must be called from the main thread.
*
* \param device a \ref spa_device
* \param seq a sequence numeber to pass to the result function
* \param id the param id to enumerate
* \param index the index of enumeration, pass 0 for the first item.
* \param num the maximum number of items to iterate
* \param max the maximum number of items to iterate
* \param filter and optional filter to use
* \return 0 when there are no more parameters to enumerate
* -EINVAL when invalid arguments are given
@ -150,7 +167,7 @@ struct spa_device {
* implemented on \a device
*/
int (*enum_params) (struct spa_device *device, int seq,
uint32_t id, uint32_t index, uint32_t num,
uint32_t id, uint32_t index, uint32_t max,
const struct spa_pod *filter);
/**
@ -179,7 +196,7 @@ struct spa_device {
const struct spa_pod *param);
};
#define spa_device_set_callbacks(d,...) (d)->set_callbacks((d),__VA_ARGS__)
#define spa_device_add_listener(d,...) (d)->add_listener((d),__VA_ARGS__)
#define spa_device_enum_params(d,...) (d)->enum_params((d),__VA_ARGS__)
#define spa_device_set_param(d,...) (d)->set_param((d),__VA_ARGS__)

View file

@ -36,11 +36,11 @@ struct spa_result_device_params_data {
struct spa_result_device_params data;
};
static inline int spa_result_func_device_params(struct spa_pending *pending,
static inline int spa_result_func_device_params(void *data, int seq, int res,
const void *result)
{
struct spa_result_device_params_data *d =
(struct spa_result_device_params_data *)pending->data;
(struct spa_result_device_params_data *)data;
const struct spa_result_device_params *r =
(const struct spa_result_device_params *)result;
uint32_t offset = d->builder->state.offset;
@ -54,17 +54,19 @@ static inline int spa_device_enum_params_sync(struct spa_device *device,
uint32_t id, uint32_t *index,
const struct spa_pod *filter,
struct spa_pod **param,
struct spa_pod_builder *builder,
struct spa_pending_queue *queue)
struct spa_pod_builder *builder)
{
struct spa_result_device_params_data data = { builder, };
struct spa_pending pending;
struct spa_hook listener = { 0 };
static const struct spa_device_events device_events = {
SPA_VERSION_DEVICE_EVENTS,
.result = spa_result_func_device_params,
};
int res;
spa_pending_queue_add(queue, 0, &pending,
spa_result_func_device_params, &data);
spa_device_add_listener(device, &listener, &device_events, &data);
res = spa_device_enum_params(device, 0, id, *index, 1, filter);
spa_pending_remove(&pending);
spa_hook_remove(&listener);
if (data.data.param == NULL) {
if (res > 0)

View file

@ -34,6 +34,7 @@ struct spa_node;
#include <spa/utils/defs.h>
#include <spa/utils/result.h>
#include <spa/utils/type.h>
#include <spa/utils/hook.h>
#include <spa/support/plugin.h>
@ -58,7 +59,7 @@ struct spa_node_info {
#define SPA_NODE_FLAG_DYNAMIC_INPUT_PORTS (1u<<0) /**< input ports can be added/removed */
#define SPA_NODE_FLAG_DYNAMIC_OUTPUT_PORTS (1u<<1) /**< output ports can be added/removed */
#define SPA_NODE_FLAG_RT (1u<<2) /**< node can do real-time processing */
uint32_t flags;
uint64_t flags;
struct spa_dict *props; /**< extra node properties */
struct spa_param_info *params; /**< parameter information */
uint32_t n_params; /**< number of items in \a params */
@ -92,8 +93,8 @@ struct spa_port_info {
* or will not be made available on another
* port */
#define SPA_PORT_FLAG_DYNAMIC_DATA (1u<<9) /**< data pointer on buffers can be changed */
uint32_t flags; /**< port flags */
uint32_t rate; /**< rate of sequence numbers on port */
uint64_t flags; /**< port flags */
struct spa_fraction rate; /**< rate of sequence numbers on port */
const struct spa_dict *props; /**< extra port properties */
struct spa_param_info *params; /**< parameter information */
uint32_t n_params; /**< number of items in \a params */
@ -114,8 +115,14 @@ struct spa_result_node_params {
struct spa_pod *param; /**< the result param */
};
struct spa_node_callbacks {
#define SPA_VERSION_NODE_CALLBACKS 0
/** events from the spa_node.
*
* All event are called from the main thread and multiple
* listeners can be registered for the events with
* spa_node_add_listener().
*/
struct spa_node_events {
#define SPA_VERSION_NODE_EVENTS 0
uint32_t version; /**< version of this structure */
/** Emited when info changes */
@ -128,17 +135,19 @@ struct spa_node_callbacks {
/** notify a result.
*
* Some method will return an async return value when called. Depending
* on the method, this can then trigger a result callback with an
* optional result. Look at the documentation of the method to know
* when to expect a result value.
* Some methods will trigger a result event with an optional
* result. Look at the documentation of the method to know
* when to expect a result event.
*
* The result callback can be called synchronously, as a callback
* The result event can be called synchronously, as an event
* called from inside the method itself, in which case the seq
* number passed to the method will be passed.
* number passed to the method will be passed unchanged.
*
* Users of the API will usually use a struct spa_pending_queue
* to dispatch result values to listeners.
* The result event will be called asynchronously when the
* method returned an async return value. In this case, the seq
* number in the result will match the async return value of
* the method call. Users should match the seq number from
* request to the reply.
*/
int (*result) (void *data, int seq, int res, const void *result);
@ -147,15 +156,31 @@ struct spa_node_callbacks {
* \param event the event that was emited
*
* This will be called when an out-of-bound event is notified
* on \a node. The callback will be called from the main thread.
* on \a node.
*/
int (*event) (void *data, struct spa_event *event);
};
#define spa_node_emit(hooks,method,version,...) \
spa_hook_list_call_simple(hooks, struct spa_node_events, \
method, version, ##__VA_ARGS__)
#define spa_node_emit_info(hooks,i) spa_node_emit(hooks,info, 0, i)
#define spa_node_emit_port_info(hooks,d,p,i) spa_node_emit(hooks,port_info, 0, d, p, i)
#define spa_node_emit_result(hooks,s,r,res) spa_node_emit(hooks,result, 0, s, r, res)
#define spa_node_emit_event(hooks,e) spa_node_emit(hooks,event, 0, e)
/** Node callbacks
*
* Callbacks are called from the real-time data thread. Only
* one callback structure can be set on an spa_node.
*/
struct spa_node_callbacks {
#define SPA_VERSION_NODE_CALLBACKS 0
/**
* \param node a spa_node
*
* The node is ready for processing. This callback is called from the
* data thread.
* The node is ready for processing.
*
* When this function is NULL, synchronous operation is requested
* on the ports.
@ -167,8 +192,7 @@ struct spa_node_callbacks {
* \param port_id an input port_id
* \param buffer_id the buffer id to be reused
*
* The node has a buffer that can be reused. This callback is called
* from the data thread.
* The node has a buffer that can be reused.
*
* When this function is NULL, the buffers to reuse will be set in
* the io area of the input ports.
@ -176,7 +200,6 @@ struct spa_node_callbacks {
int (*reuse_buffer) (void *data,
uint32_t port_id,
uint32_t buffer_id);
};
/** flags that can be passed to set_param and port_set_param functions */
@ -196,11 +219,31 @@ struct spa_node {
uint32_t version;
/**
* Set callbacks to receive events and scheduling callbacks from \a node.
* Adds an event listener on \a node.
*
* Setting the events will trigger the info event and a
* port_info event for each managed port on the new
* listener.
*
* \param node a #spa_node
* \param listener a listener
* \param events a #struct spa_node_events
* \param data data passed as first argument in functions of \a events
* \return 0 on success
* < 0 errno on error
*/
int (*add_listener) (struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data);
/**
* Set callbacks to on \a node.
* if \a callbacks is NULL, the current callbacks are removed.
*
* This function must be called from the main thread.
*
* All callbacks are called from the data thread.
*
* \param node a spa_node
* \param callbacks callbacks to set
* \return 0 on success
@ -212,7 +255,7 @@ struct spa_node {
/**
* Perform a sync operation.
*
* This method will emit the result callback with the given sequence
* This method will emit the result event with the given sequence
* number synchronously or with the returned async return value
* asynchronously.
*
@ -234,24 +277,28 @@ struct spa_node {
*
* Parameters can be filtered by passing a non-NULL \a filter.
*
* The function will emit the result event up to \a max times with
* the result value. The seq in the result will either be the \a seq
* number when executed synchronously or the async return value of
* this function when executed asynchrnously.
*
* This function must be called from the main thread.
*
* \param node a \ref spa_node
* \param seq a sequence number to pass to the result event when
* this method is executed synchronously.
* \param id the param id to enumerate
* \param start the index of enumeration, pass 0 for the first item
* \param num the number of parameters to enumerate
* \param max the maximum number of parameters to enumerate
* \param filter and optional filter to use
* \param func the callback with the result. The result will be
* of type struct spa_result_node_params. The next field
* can be used to continue the enumeration.
* \param data first argument to \a func
*
* \return the return value of \a func or 0 when no more
* items can be iterated.
* \return 0 when no more items can be iterated.
* -EINVAL when invalid arguments are given
* -ENOENT the parameter \a id is unknown
* -ENOTSUP when there are no parameters
* implemented on \a node
* an async return value when the result event will be
* emited later.
*/
int (*enum_params) (struct spa_node *node, int seq,
uint32_t id, uint32_t start, uint32_t max,
@ -320,10 +367,11 @@ struct spa_node {
int (*send_command) (struct spa_node *node, const struct spa_command *command);
/**
* Make a new port with \a port_id. The caller should use get_port_ids() to
* find an unused id for the given \a direction.
* Make a new port with \a port_id. The caller should use the lowest unused
* port id for the given \a direction.
*
* Port ids should be between 0 and max_ports as obtained from get_n_ports().
* Port ids should be between 0 and max_ports as obtained from the info
* event.
*
* This function must be called from the main thread.
*
@ -338,7 +386,18 @@ struct spa_node {
enum spa_direction direction, uint32_t port_id,
const struct spa_dict *props);
int (*remove_port) (struct spa_node *node, enum spa_direction direction, uint32_t port_id);
/**
* Remove a port with \a port_id.
*
* \param node a spa_node
* \param direction a #enum spa_direction
* \param port_id a port id
* \return 0 on success
* -EINVAL when node is NULL or when port_id is unknown or
* when the port can't be removed.
*/
int (*remove_port) (struct spa_node *node,
enum spa_direction direction, uint32_t port_id);
/**
* Enumerate all possible parameters of \a id on \a port_id of \a node
@ -347,30 +406,32 @@ struct spa_node {
* The result parameters can be queried and modified and ultimately be used
* to call port_set_param.
*
* The function will emit the result event up to \a max times with
* the result value. The seq in the result event will either be the
* \a seq number when executed synchronously or the async return
* value of this function when executed asynchronously.
*
* This function must be called from the main thread.
*
* The result callback will be called with a struct spa_result_node_params.
*
* \param node a spa_node
* \param seq a sequence number to pass to the result event when
* this method is executed synchronously.
* \param direction an spa_direction
* \param port_id the port to query
* \param seq a sequence number to pass to the synchronous result callback
* \param id the parameter id to query
* \param start the first index to query, 0 to get the first item
* \param num the maximum number of params to query
* \param max the maximum number of params to query
* \param filter a parameter filter or NULL for no filter
* \param func the callback with the result.
* \param data first argument to \a func
*
* \return the return value of \a func or 0 when no more
* items can be iterated.
* 0 when no more parameters exists
* \return 0 when no more items can be iterated.
* -EINVAL when invalid parameters are given
* -ENOENT when \a id is unknown
* an async return value when the result event will be
* emited later.
*/
int (*port_enum_params) (struct spa_node *node, int seq,
enum spa_direction direction, uint32_t port_id,
uint32_t id, uint32_t start, uint32_t num,
uint32_t id, uint32_t start, uint32_t max,
const struct spa_pod *filter);
/**
* Set a parameter on \a port_id of \a node.
@ -408,17 +469,19 @@ struct spa_node {
* The port should also have a spa_io_buffers io area configured to exchange
* the buffers with the port.
*
* For an input port, all the buffers will remain dequeued. Once a buffer
* has been pushed on a port with port_push_input, it should not be reused
* until the reuse_buffer event is notified or when the buffer has been
* returned in the spa_io_buffers of the port.
* For an input port, all the buffers will remain dequeued.
* Once a buffer has been queued on a port in the spa_io_buffers,
* it should not be reused until the reuse_buffer callback is notified
* or when the buffer has been returned in the spa_io_buffers of
* the port.
*
* For output ports, all buffers will be queued in the port. When process
* returns SPA_STATUS_HAVE_BUFFER, buffers are available in one or more
* of the spa_io_buffers areas.
*
* For output ports, all buffers will be queued in the port. When process_input
* or process_output return SPA_STATUS_HAVE_BUFFER, buffers are available in
* one or more of the spa_io_buffers areas.
* When a buffer can be reused, port_reuse_buffer() should be called or the
* buffer_id should be placed in the spa_io_buffers area before calling
* process_output.
* process.
*
* Passing NULL as \a buffers will remove the reference that the port has
* on the buffers.
@ -448,7 +511,7 @@ struct spa_node {
* with a 0 type that will be filled by this function.
*
* For input ports, the buffers will be dequeued and ready to be filled
* and pushed into the port. A notify should be configured so that you can
* and pushed into the port. A callback should be configured so that you can
* know when a buffer can be reused.
*
* For output ports, the buffers remain queued. port_reuse_buffer() should
@ -534,6 +597,7 @@ struct spa_node {
int (*process) (struct spa_node *node);
};
#define spa_node_add_listener(n,...) (n)->add_listener((n),__VA_ARGS__)
#define spa_node_set_callbacks(n,...) (n)->set_callbacks((n),__VA_ARGS__)
#define spa_node_sync(n,...) (n)->sync((n),__VA_ARGS__)
#define spa_node_enum_params(n,...) (n)->enum_params((n),__VA_ARGS__)
@ -547,6 +611,7 @@ struct spa_node {
#define spa_node_port_use_buffers(n,...) (n)->port_use_buffers((n),__VA_ARGS__)
#define spa_node_port_alloc_buffers(n,...) (n)->port_alloc_buffers((n),__VA_ARGS__)
#define spa_node_port_set_io(n,...) (n)->port_set_io((n),__VA_ARGS__)
#define spa_node_port_reuse_buffer(n,...) (n)->port_reuse_buffer((n),__VA_ARGS__)
#define spa_node_process(n) (n)->process((n))

View file

@ -36,13 +36,13 @@ struct spa_result_node_params_data {
struct spa_result_node_params data;
};
static inline int spa_result_func_node_params(struct spa_pending *pending,
const void *result)
static inline int spa_result_func_node_params(void *data,
int seq, int res, const void *result)
{
struct spa_result_node_params_data *d =
(struct spa_result_node_params_data *)pending->data;
(struct spa_result_node_params_data *) data;
const struct spa_result_node_params *r =
(const struct spa_result_node_params *)result;
(const struct spa_result_node_params *) result;
uint32_t offset = d->builder->state.offset;
spa_pod_builder_raw_padded(d->builder, r->param, SPA_POD_SIZE(r->param));
d->data.next = r->next;
@ -54,17 +54,19 @@ static inline int spa_node_enum_params_sync(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod *filter,
struct spa_pod **param,
struct spa_pod_builder *builder,
struct spa_pending_queue *queue)
struct spa_pod_builder *builder)
{
struct spa_result_node_params_data data = { builder, };
struct spa_pending pending;
struct spa_hook listener = { 0 };
static const struct spa_node_events node_events = {
SPA_VERSION_NODE_EVENTS,
.result = spa_result_func_node_params,
};
int res = 0;
spa_pending_queue_add(queue, 0, &pending,
spa_result_func_node_params, &data);
spa_node_add_listener(node, &listener, &node_events, &data);
res = spa_node_enum_params(node, 0, id, *index, 1, filter);
spa_pending_remove(&pending);
spa_hook_remove(&listener);
if (data.data.param == NULL) {
if (res > 0)
@ -82,18 +84,20 @@ static inline int spa_node_port_enum_params_sync(struct spa_node *node,
uint32_t id, uint32_t *index,
const struct spa_pod *filter,
struct spa_pod **param,
struct spa_pod_builder *builder,
struct spa_pending_queue *queue)
struct spa_pod_builder *builder)
{
struct spa_result_node_params_data data = { builder, };
struct spa_pending pending;
struct spa_hook listener = { 0 };
static const struct spa_node_events node_events = {
SPA_VERSION_NODE_EVENTS,
.result = spa_result_func_node_params,
};
int res;
spa_pending_queue_add(queue, 0, &pending,
spa_result_func_node_params, &data);
spa_node_add_listener(node, &listener, &node_events, &data);
res = spa_node_port_enum_params(node, 0, direction, port_id,
id, *index, 1, filter);
spa_pending_remove(&pending);
spa_hook_remove(&listener);
if (data.data.param == NULL) {
if (res > 0)

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

View file

@ -67,8 +67,7 @@ struct impl {
struct spa_log *log;
struct spa_loop *main_loop;
const struct spa_device_callbacks *callbacks;
void *callbacks_data;
struct spa_hook_list hooks;
struct props props;
uint32_t n_nodes;
@ -127,7 +126,7 @@ static int emit_node(struct impl *this, snd_pcm_info_t *pcminfo, uint32_t id)
items[5] = SPA_DICT_ITEM_INIT("alsa.pcm.subclass", get_subclass(pcminfo));
info.props = &SPA_DICT_INIT_ARRAY(items);
this->callbacks->object_info(this->callbacks_data, id, &info);
spa_device_emit_object_info(&this->hooks, id, &info);
return 0;
}
@ -141,11 +140,9 @@ static int activate_profile(struct impl *this, snd_ctl_t *ctl_hndl, uint32_t id)
spa_log_debug(this->log, "profile %d", id);
this->profile = id;
if (this->callbacks->object_info) {
for (i = 0; i < this->n_nodes; i++) {
this->callbacks->object_info(this->callbacks_data, i, NULL);
}
}
for (i = 0; i < this->n_nodes; i++)
spa_device_emit_object_info(&this->hooks, i, NULL);
this->n_nodes = 0;
if (id == 1)
@ -170,7 +167,7 @@ static int activate_profile(struct impl *this, snd_ctl_t *ctl_hndl, uint32_t id)
if (err != -ENOENT)
spa_log_error(this->log, "error pcm info: %s", snd_strerror(err));
}
if (err >= 0 && this->callbacks->object_info)
if (err >= 0)
emit_node(this, pcminfo, i++);
snd_pcm_info_set_stream(pcminfo, SND_PCM_STREAM_CAPTURE);
@ -178,7 +175,7 @@ static int activate_profile(struct impl *this, snd_ctl_t *ctl_hndl, uint32_t id)
if (err != -ENOENT)
spa_log_error(this->log, "error pcm info: %s", snd_strerror(err));
}
if (err >= 0 && this->callbacks->object_info)
if (err >= 0)
emit_node(this, pcminfo, i++);
}
this->n_nodes = i;
@ -206,7 +203,7 @@ static int set_profile(struct impl *this, uint32_t id)
return err;
}
static int emit_info(struct impl *this)
static int emit_info(struct impl *this, bool full)
{
int err = 0;
struct spa_dict_item items[10];
@ -249,8 +246,7 @@ static int emit_info(struct impl *this)
dinfo.n_params = SPA_N_ELEMENTS(params);
dinfo.params = params;
if (this->callbacks->info)
this->callbacks->info(this->callbacks_data, &dinfo);
spa_device_emit_info(&this->hooks, &dinfo);
activate_profile(this, ctl_hndl, 0);
@ -260,21 +256,24 @@ static int emit_info(struct impl *this)
return err;
}
static int impl_set_callbacks(struct spa_device *device,
const struct spa_device_callbacks *callbacks,
void *data)
static int impl_add_listener(struct spa_device *device,
struct spa_hook *listener,
const struct spa_device_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(device != NULL, -EINVAL);
spa_return_val_if_fail(events != NULL, -EINVAL);
this = SPA_CONTAINER_OF(device, struct impl, device);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
this->callbacks = callbacks;
this->callbacks_data = data;
if (events->info || events->object_info)
emit_info(this, true);
if (callbacks)
emit_info(this);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
@ -290,13 +289,11 @@ static int impl_enum_params(struct spa_device *device, int seq,
uint8_t buffer[1024];
struct spa_result_device_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(device != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(device, struct impl, device);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -346,8 +343,7 @@ static int impl_enum_params(struct spa_device *device, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_device_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -390,7 +386,7 @@ static int impl_set_param(struct spa_device *device,
static const struct spa_device impl_device = {
SPA_VERSION_DEVICE,
impl_set_callbacks,
impl_add_listener,
impl_enum_params,
impl_set_param,
};
@ -455,6 +451,7 @@ impl_init(const struct spa_handle_factory *factory,
}
this->device = impl_device;
spa_hook_list_init(&this->hooks);
reset_props(&this->props);

View file

@ -59,13 +59,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -146,8 +144,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -239,24 +236,50 @@ static const struct spa_dict_item node_info_items[] = {
{ "node.driver", "true" },
};
static void emit_node_info(struct state *this)
static void emit_node_info(struct state *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
this->info.props = &SPA_DICT_INIT_ARRAY(node_info_items);
this->callbacks->info(this->callbacks_data, &this->info);
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct state *this)
static void emit_port_info(struct state *this, bool full)
{
if (this->callbacks && this->callbacks->port_info && this->port_info.change_mask) {
this->callbacks->port_info(this->callbacks_data,
if (full)
this->port_info.change_mask = this->port_info_all;
if (this->port_info.change_mask) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_INPUT, 0, &this->port_info);
this->port_info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct state *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
@ -271,9 +294,6 @@ impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this);
return 0;
}
@ -301,13 +321,11 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -394,8 +412,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -450,7 +467,7 @@ static int port_set_format(struct spa_node *node,
}
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_RATE;
this->port_info.rate = this->rate;
this->port_info.rate = SPA_FRACTION(1, this->rate);
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (this->have_format) {
this->port_params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
@ -459,7 +476,7 @@ static int port_set_format(struct spa_node *node,
this->port_params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
this->port_params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this);
emit_port_info(this, false);
return 0;
}
@ -630,6 +647,7 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
@ -707,12 +725,16 @@ impl_init(const struct spa_handle_factory *factory,
}
this->node = impl_node;
spa_hook_list_init(&this->hooks);
this->stream = SND_PCM_STREAM_PLAYBACK;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PROPS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = 1;
this->info.change_mask = SPA_NODE_CHANGE_MASK_PROPS;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->info.flags = SPA_NODE_FLAG_RT;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
this->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
@ -720,14 +742,13 @@ impl_init(const struct spa_handle_factory *factory,
reset_props(&this->props);
this->port_info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
this->port_info = SPA_PORT_INFO_INIT();
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
this->port_info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_LIVE |
SPA_PORT_FLAG_PHYSICAL |
SPA_PORT_FLAG_TERMINAL;
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
this->port_params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
this->port_params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
this->port_params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -60,13 +60,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
struct props *p;
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
p = &this->props;
result.id = id;
@ -142,8 +140,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -239,24 +236,50 @@ static const struct spa_dict_item node_info_items[] = {
{ "node.driver", "true" },
};
static void emit_node_info(struct state *this)
static void emit_node_info(struct state *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
this->info.props = &SPA_DICT_INIT_ARRAY(node_info_items);
this->callbacks->info(this->callbacks_data, &this->info);
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct state *this)
static void emit_port_info(struct state *this, bool full)
{
if (this->callbacks && this->callbacks->port_info && this->port_info.change_mask) {
this->callbacks->port_info(this->callbacks_data,
if (full)
this->port_info.change_mask = this->port_info_all;
if (this->port_info.change_mask) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_OUTPUT, 0, &this->port_info);
this->port_info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct state *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
@ -271,9 +294,6 @@ impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this);
return 0;
}
@ -311,17 +331,14 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct state, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
result.id = id;
result.next = start;
next:
@ -399,8 +416,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -454,7 +470,7 @@ static int port_set_format(struct spa_node *node,
}
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_RATE;
this->port_info.rate = this->rate;
this->port_info.rate = SPA_FRACTION(1, this->rate);
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (this->have_format) {
this->port_params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
@ -463,7 +479,7 @@ static int port_set_format(struct spa_node *node,
this->port_params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
this->port_params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this);
emit_port_info(this, false);
return 0;
}
@ -647,11 +663,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -728,24 +745,27 @@ impl_init(const struct spa_handle_factory *factory,
}
this->node = impl_node;
spa_hook_list_init(&this->hooks);
this->stream = SND_PCM_STREAM_CAPTURE;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PROPS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info.max_output_ports = 1;
this->info.change_mask = SPA_NODE_CHANGE_MASK_PROPS;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->info.flags = SPA_NODE_FLAG_RT;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
this->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
this->info.n_params = 2;
reset_props(&this->props);
this->port_info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
this->port_info = SPA_PORT_INFO_INIT();
this->port_info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
this->port_info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_LIVE |
SPA_PORT_FLAG_PHYSICAL |
SPA_PORT_FLAG_TERMINAL;
this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
this->port_params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
this->port_params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
this->port_params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -359,15 +359,13 @@ spa_alsa_enum_format(struct state *state, int seq, uint32_t start, uint32_t num,
if ((res = spa_pod_filter(&b, &result.param, fmt, filter)) < 0)
goto next;
if ((res = state->callbacks->result(state->callbacks_data, seq, 0, &result)) != 0)
goto exit;
spa_node_emit_result(&state->hooks, seq, 0, &result);
if (++count != num)
goto next;
enum_end:
res = 0;
exit:
if (!opened)
spa_alsa_close(state);
return res;

View file

@ -87,9 +87,11 @@ struct state {
snd_pcm_stream_t stream;
snd_output_t *output;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[8];
struct props props;
@ -108,6 +110,7 @@ struct state {
int channels;
size_t frame_size;
uint64_t port_info_all;
struct spa_port_info port_info;
struct spa_param_info port_params[8];
struct spa_io_buffers *io;

View file

@ -67,8 +67,7 @@ struct impl {
struct spa_log *log;
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
int n_links;
struct link links[8];
@ -89,7 +88,8 @@ struct impl {
struct spa_node *channelmix;
struct spa_node *resample;
struct spa_pending_queue pending;
struct spa_hook listener[4];
int listening:1;
};
static int make_link(struct impl *this,
@ -151,8 +151,7 @@ static int debug_params(struct impl *this, struct spa_node *node,
res = spa_node_port_enum_params_sync(node,
direction, port_id,
id, &state,
NULL, &param, &b,
&this->pending);
NULL, &param, &b);
if (res != 1)
break;
@ -184,8 +183,7 @@ static int negotiate_link_format(struct impl *this, struct link *link)
if ((res = spa_node_port_enum_params_sync(link->out_node,
SPA_DIRECTION_OUTPUT, link->out_port,
SPA_PARAM_EnumFormat, &state,
filter, &format, &b,
&this->pending)) != 1) {
filter, &format, &b)) != 1) {
debug_params(this, link->out_node, SPA_DIRECTION_OUTPUT, link->out_port,
SPA_PARAM_EnumFormat, filter);
return -ENOTSUP;
@ -195,8 +193,7 @@ static int negotiate_link_format(struct impl *this, struct link *link)
if ((res = spa_node_port_enum_params_sync(link->in_node,
SPA_DIRECTION_INPUT, link->in_port,
SPA_PARAM_EnumFormat, &state,
filter, &format, &b,
&this->pending)) != 1) {
filter, &format, &b)) != 1) {
debug_params(this, link->in_node, SPA_DIRECTION_INPUT, link->in_port,
SPA_PARAM_EnumFormat, filter);
return -ENOTSUP;
@ -274,8 +271,7 @@ static int negotiate_link_buffers(struct impl *this, struct link *link)
if ((res = spa_node_port_enum_params_sync(link->in_node,
SPA_DIRECTION_INPUT, link->in_port,
SPA_PARAM_Buffers, &state,
param, &param, &b,
&this->pending)) != 1) {
param, &param, &b)) != 1) {
debug_params(this, link->out_node, SPA_DIRECTION_OUTPUT, link->out_port,
SPA_PARAM_Buffers, param);
return -ENOTSUP;
@ -284,8 +280,7 @@ static int negotiate_link_buffers(struct impl *this, struct link *link)
if ((res = spa_node_port_enum_params_sync(link->out_node,
SPA_DIRECTION_OUTPUT, link->out_port,
SPA_PARAM_Buffers, &state,
param, &param, &b,
&this->pending)) != 1) {
param, &param, &b)) != 1) {
debug_params(this, link->in_node, SPA_DIRECTION_INPUT, link->in_port,
SPA_PARAM_Buffers, param);
return -ENOTSUP;
@ -403,13 +398,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -451,8 +444,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -564,22 +556,11 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
static int on_node_result(void *data, int seq, int res, const void *result)
{
struct impl *this = data;
int r;
r = spa_pending_queue_complete(&this->pending, seq, res, result);
if (r == 0)
r = this->callbacks->result(this->user_data, seq, res, result);
return r;
spa_log_debug(this->log, "%p: result %d %d", this, seq, res);
spa_node_emit_result(&this->hooks, seq, res, result);
return 0;
}
static void emit_port_info(struct impl *this,
enum spa_direction direction, uint32_t port,
const struct spa_port_info *info)
{
if (this->callbacks && this->callbacks->port_info)
this->callbacks->port_info(this->user_data, direction, port, info);
}
static int fmt_input_port_info(void *data,
enum spa_direction direction, uint32_t port,
const struct spa_port_info *info)
@ -589,12 +570,12 @@ static int fmt_input_port_info(void *data,
if (direction != SPA_DIRECTION_INPUT)
return 0;
emit_port_info(this, direction, port, info);
spa_node_emit_port_info(&this->hooks, direction, port, info);
return 0;
}
static struct spa_node_callbacks fmt_input_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
static struct spa_node_events fmt_input_events = {
SPA_VERSION_NODE_EVENTS,
.port_info = fmt_input_port_info,
.result = on_node_result,
};
@ -608,40 +589,64 @@ static int fmt_output_port_info(void *data,
if (direction != SPA_DIRECTION_OUTPUT)
return 0;
emit_port_info(this, direction, port, info);
spa_node_emit_port_info(&this->hooks, direction, port, info);
return 0;
}
static struct spa_node_callbacks fmt_output_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
static struct spa_node_events fmt_output_events = {
SPA_VERSION_NODE_EVENTS,
.port_info = fmt_output_port_info,
.result = on_node_result,
};
static struct spa_node_callbacks node_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
static struct spa_node_events node_events = {
SPA_VERSION_NODE_EVENTS,
.result = on_node_result,
};
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
spa_log_debug(this->log, "%p: add listener %p", this, listener);
if (this->listening) {
spa_hook_remove(&this->listener[0]);
spa_hook_remove(&this->listener[1]);
spa_hook_remove(&this->listener[2]);
spa_hook_remove(&this->listener[3]);
}
spa_node_add_listener(this->fmt[SPA_DIRECTION_INPUT],
&this->listener[0], &fmt_input_events, this);
spa_node_add_listener(this->channelmix,
&this->listener[1], &node_events, this);
spa_node_add_listener(this->resample,
&this->listener[2], &node_events, this);
spa_node_add_listener(this->fmt[SPA_DIRECTION_OUTPUT],
&this->listener[3], &fmt_output_events, this);
this->listening = true;
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
spa_node_set_callbacks(this->fmt[SPA_DIRECTION_INPUT], &fmt_input_callbacks, this);
spa_node_set_callbacks(this->channelmix, &node_callbacks, this);
spa_node_set_callbacks(this->resample, &node_callbacks, this);
spa_node_set_callbacks(this->fmt[SPA_DIRECTION_OUTPUT], &fmt_output_callbacks, this);
return 0;
}
@ -681,13 +686,11 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -742,9 +745,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
spa_log_debug(this->log, "%p: %d callback %u", this, seq, count);
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -908,11 +909,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -1010,7 +1012,7 @@ impl_init(const struct spa_handle_factory *factory,
this->log = support[i].data;
}
this->node = impl_node;
spa_pending_queue_init(&this->pending);
spa_hook_list_init(&this->hooks);
if (info == NULL || (str = spa_dict_lookup(info, "factory.mode")) == NULL)
str = "convert";

View file

@ -74,11 +74,13 @@ struct port {
uint32_t direction;
uint32_t id;
struct spa_io_buffers *io;
struct spa_io_sequence *control;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[8];
struct spa_io_buffers *io;
struct spa_io_sequence *control;
bool have_format;
struct spa_audio_info format;
uint32_t stride;
@ -100,9 +102,9 @@ struct impl {
struct spa_log *log;
struct spa_cpu *cpu;
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
uint64_t info_all;
struct spa_node_info info;
struct props props;
struct spa_param_info params[8];
@ -445,13 +447,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -508,8 +508,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -583,40 +582,55 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_info(struct impl *this)
static void emit_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->user_data, port->direction, port->id, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_info(this, true);
emit_port_info(this, GET_IN_PORT(this, 0), true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
emit_info(this);
emit_port_info(this, GET_IN_PORT(this, 0));
emit_port_info(this, GET_OUT_PORT(this, 0));
return 0;
}
@ -689,7 +703,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -786,8 +799,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -852,6 +864,8 @@ static int port_set_format(struct spa_node *node,
spa_log_debug(this->log, NAME " %p: set format on port %d %d", this, port_id, res);
}
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
@ -859,7 +873,7 @@ static int port_set_format(struct spa_node *node,
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return res;
}
@ -1118,11 +1132,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -1196,9 +1211,12 @@ impl_init(const struct spa_handle_factory *factory,
if (this->cpu)
this->cpu_flags = spa_cpu_get_flags(this->cpu);
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.change_mask = SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
this->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
@ -1209,8 +1227,9 @@ impl_init(const struct spa_handle_factory *factory,
port = GET_OUT_PORT(this, 0);
port->direction = SPA_DIRECTION_OUTPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
@ -1224,8 +1243,9 @@ impl_init(const struct spa_handle_factory *factory,
port = GET_IN_PORT(this, 0);
port->direction = SPA_DIRECTION_INPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);

View file

@ -79,6 +79,7 @@ struct port {
struct spa_io_buffers *io;
struct spa_io_range *ctrl;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[8];
@ -103,12 +104,12 @@ struct impl {
struct spa_log *log;
struct spa_cpu *cpu;
uint64_t info_all;
struct spa_node_info info;
struct props props;
struct spa_param_info params[8];
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
struct port ports[2][1];
@ -229,45 +230,60 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_info(struct impl *this)
static void emit_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
struct spa_dict_item items[1];
items[0] = SPA_DICT_ITEM_INIT("port.dsp", "32 bit float mono audio");
port->info.props = &SPA_DICT_INIT_ARRAY(items);
this->callbacks->port_info(this->user_data, port->direction, port->id, &port->info);
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_info(this, true);
emit_port_info(this, GET_IN_PORT(this, 0), true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
emit_info(this);
emit_port_info(this, GET_IN_PORT(this, 0));
emit_port_info(this, GET_OUT_PORT(this, 0));
return 0;
}
@ -483,8 +499,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -861,11 +876,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -908,8 +924,8 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
port->id = port_id;
spa_list_init(&port->queue);
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_PROPS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS | SPA_PORT_CHANGE_MASK_PROPS;
port->info.flags = flags;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
@ -919,7 +935,6 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
port->info.params = port->params;
port->info.n_params = 5;
port->have_format = false;
emit_port_info(this, port);
return 0;
}
@ -960,12 +975,13 @@ impl_init(const struct spa_handle_factory *factory,
}
}
this->node = impl_node;
spa_hook_list_init(&this->hooks);
if (this->cpu)
this->cpu_flags = spa_cpu_get_flags(this->cpu);
this->info_all = SPA_PORT_CHANGE_MASK_FLAGS;
this->info = SPA_NODE_INFO_INIT();
this->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.params = this->params;
this->info.n_params = 0;

View file

@ -37,6 +37,7 @@
#include <spa/pod/filter.h>
#include <spa/debug/types.h>
#include <spa/debug/mem.h>
#include <spa/debug/pod.h>
#define NAME "merger"
@ -62,6 +63,7 @@ struct port {
struct spa_io_buffers *io;
struct spa_io_range *ctrl;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[8];
char position[16];
@ -86,11 +88,11 @@ struct impl {
struct spa_log *log;
struct spa_cpu *cpu;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[8];
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
uint32_t port_count;
struct port in_ports[MAX_PORTS];
@ -107,8 +109,6 @@ struct impl {
float empty[MAX_SAMPLES + 15];
};
#define emit_callback(this,name,...) this->callbacks->name(this->user_data, __VA_ARGS__)
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < this->port_count)
#define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) <= this->monitor_count)
#define CHECK_PORT(this,d,p) (CHECK_OUT_PORT(this,d,p) || CHECK_IN_PORT (this,d,p))
@ -118,27 +118,33 @@ struct impl {
#define PORT_IS_DSP(d,p) (p != 0 || d != SPA_DIRECTION_OUTPUT)
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
struct spa_dict_item items[3];
uint32_t n_items = 0;
if (port->info.change_mask & SPA_PORT_CHANGE_MASK_PROPS) {
if (PORT_IS_DSP(port->direction, port->id)) {
items[n_items++] = SPA_DICT_ITEM_INIT("port.dsp", "32 bit float mono audio");
items[n_items++] = SPA_DICT_ITEM_INIT("port.channel", port->position);
if (port->direction == SPA_DIRECTION_OUTPUT)
items[n_items++] = SPA_DICT_ITEM_INIT("port.monitor", "1");
port->info.props = &SPA_DICT_INIT(items, n_items);
}
this->callbacks->port_info(this->user_data, port->direction, port->id, &port->info);
port->info.props = &SPA_DICT_INIT(items, n_items);
spa_node_emit_port_info(&this->hooks, port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
@ -153,11 +159,11 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
snprintf(port->position, 16, "%s", rindex(spa_type_audio_channel[position].name, ':')+1);
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PROPS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PROPS;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -177,7 +183,7 @@ static int init_port(struct impl *this, enum spa_direction direction, uint32_t p
spa_list_init(&port->queue);
spa_log_debug(this->log, NAME " %p: add port %d", this, port_id);
emit_port_info(this, port);
emit_port_info(this, port, true);
return 0;
}
@ -192,12 +198,10 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -216,8 +220,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = emit_callback(this, result, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -273,12 +276,12 @@ static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flag
spa_log_debug(this->log, NAME " %p: profile %d/%d", this,
info.info.raw.rate, info.info.raw.channels);
if (this->callbacks && this->callbacks->port_info) {
for (i = 0; i < this->port_count; i++) {
this->callbacks->port_info(this->user_data, SPA_DIRECTION_INPUT, i, NULL);
if (this->monitor)
this->callbacks->port_info(this->user_data, SPA_DIRECTION_OUTPUT, i+1, NULL);
}
for (i = 0; i < this->port_count; i++) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_INPUT, i, NULL);
if (this->monitor)
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_OUTPUT, i+1, NULL);
}
port->have_format = true;
@ -325,25 +328,37 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
uint32_t i;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
spa_log_debug(this->log, NAME" %p: add listener %p", node, listener);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this);
emit_port_info(this, GET_OUT_PORT(this, 0));
emit_node_info(this, true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
for (i = 0; i < this->port_count; i++)
emit_port_info(this, GET_IN_PORT(this, i));
emit_port_info(this, GET_IN_PORT(this, i), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
return 0;
}
@ -426,13 +441,12 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
port = GET_PORT(this, direction, port_id);
spa_log_debug(this->log, "%p: enum params %d %u", this, seq, id);
spa_log_debug(this->log, "%p: enum params %d %d %u %u", this, seq, direction, port_id, id);
result.id = id;
result.next = start;
@ -499,11 +513,13 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
return -ENOENT;
}
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
if (spa_pod_filter(&b, &result.param, param, filter) < 0) {
spa_debug_pod(2, NULL, param);
spa_debug_pod(2, NULL, filter);
goto next;
}
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -652,6 +668,8 @@ static int port_set_format(struct spa_node *node,
port->have_format = true;
}
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
@ -659,7 +677,7 @@ static int port_set_format(struct spa_node *node,
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -973,11 +991,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -1056,13 +1075,14 @@ impl_init(const struct spa_handle_factory *factory,
this->monitor = atoi(str);
this->node = impl_node;
spa_hook_list_init(&this->hooks);
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = MAX_PORTS;
this->info.max_output_ports = MAX_PORTS+1;
this->info.change_mask = SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_Profile, SPA_PARAM_INFO_WRITE);
this->info.params = this->params;
this->info.n_params = 1;
@ -1070,10 +1090,10 @@ impl_init(const struct spa_handle_factory *factory,
port = GET_OUT_PORT(this, 0);
port->direction = SPA_DIRECTION_OUTPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -72,11 +72,13 @@ struct port {
uint32_t direction;
uint32_t id;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[8];
struct spa_io_buffers *io;
struct spa_io_range *io_range;
struct spa_io_sequence *io_control;
struct spa_port_info info;
struct spa_param_info params[8];
bool have_format;
struct spa_audio_info format;
@ -98,11 +100,11 @@ struct impl {
struct spa_log *log;
struct spa_cpu *cpu;
uint64_t info_all;
struct spa_node_info info;
struct props props;
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
struct port in_port;
struct port out_port;
@ -233,40 +235,56 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->user_data, port->direction, port->id, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, GET_IN_PORT(this, 0), true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
emit_node_info(this);
emit_port_info(this, GET_IN_PORT(this, 0));
emit_port_info(this, GET_OUT_PORT(this, 0));
return 0;
}
@ -346,7 +364,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -441,8 +458,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -507,6 +523,7 @@ static int port_set_format(struct spa_node *node,
spa_log_debug(this->log, NAME " %p: set format on port %d %d", this, port_id, res);
}
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
@ -514,7 +531,7 @@ static int port_set_format(struct spa_node *node,
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return res;
}
@ -799,11 +816,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -891,17 +909,19 @@ impl_init(const struct spa_handle_factory *factory,
this->node = impl_node;
spa_hook_list_init(&this->hooks);
this->info = SPA_NODE_INFO_INIT();
this->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
port = GET_OUT_PORT(this, 0);
port->direction = SPA_DIRECTION_OUTPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -914,10 +934,10 @@ impl_init(const struct spa_handle_factory *factory,
port = GET_IN_PORT(this, 0);
port->direction = SPA_DIRECTION_INPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -63,6 +63,7 @@ struct port {
struct spa_io_buffers *io;
struct spa_io_range *ctrl;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[8];
@ -90,11 +91,11 @@ struct impl {
struct spa_log *log;
struct spa_cpu *cpu;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[8];
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
struct port in_ports[1];
struct port out_ports[MAX_PORTS];
@ -116,17 +117,22 @@ struct impl {
#define GET_OUT_PORT(this,p) (&this->out_ports[p])
#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p))
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->user_data, port->direction, port->id, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
@ -141,18 +147,17 @@ static int init_port(struct impl *this, enum spa_direction direction,
snprintf(port->position, 7, "%s", rindex(spa_type_audio_channel[position].name, ':')+1);
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PROPS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PROPS;
port->info_props_items[0] = SPA_DICT_ITEM_INIT("port.dsp", "32 bit float mono audio");
port->info_props_items[1] = SPA_DICT_ITEM_INIT("port.channel", port->position);
port->info_props = SPA_DICT_INIT(port->info_props_items, 2);
port->info.props = &port->info_props;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -173,7 +178,7 @@ static int init_port(struct impl *this, enum spa_direction direction,
port->format.info.raw.position[0] = position;
spa_log_debug(this->log, NAME " %p: init port %d %s", this, port_id, port->position);
emit_port_info(this, port);
emit_port_info(this, port, true);
return 0;
}
@ -188,13 +193,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -211,8 +214,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -267,10 +269,10 @@ static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flag
spa_log_debug(this->log, NAME " %p: profile %d", this, info.info.raw.channels);
for (i = 0; i < this->port_count; i++) {
if (this->callbacks && this->callbacks->port_info)
this->callbacks->port_info(this->user_data, SPA_DIRECTION_OUTPUT, i, NULL);
}
for (i = 0; i < this->port_count; i++)
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_OUTPUT, i, NULL);
this->have_profile = true;
port->have_format = true;
port->format = info;
@ -311,25 +313,35 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
uint32_t i;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
this->callbacks = callbacks;
this->user_data = user_data;
emit_node_info(this);
emit_port_info(this, GET_IN_PORT(this, 0));
emit_node_info(this, true);
emit_port_info(this, GET_IN_PORT(this, 0), true);
for (i = 0; i < this->port_count; i++)
emit_port_info(this, GET_OUT_PORT(this, i));
emit_port_info(this, GET_OUT_PORT(this, i), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
return 0;
}
@ -417,7 +429,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -495,8 +506,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -628,6 +638,7 @@ static int port_set_format(struct spa_node *node,
port->have_format = true;
}
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
@ -635,7 +646,7 @@ static int port_set_format(struct spa_node *node,
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -906,11 +917,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -983,24 +995,26 @@ impl_init(const struct spa_handle_factory *factory,
if (this->cpu)
this->cpu_flags = spa_cpu_get_flags(this->cpu);
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = 1;
this->info.max_output_ports = MAX_PORTS;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_Profile, SPA_PARAM_INFO_WRITE);
this->info.params = this->params;
this->info.n_params = 1;
port = GET_IN_PORT(this, 0);
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->direction = SPA_DIRECTION_INPUT;
port->id = 0;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -76,6 +76,7 @@ struct port {
double *io_volume;
int32_t *io_mute;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[5];
@ -97,11 +98,11 @@ struct impl {
struct spa_audiomixer_ops ops;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[8];
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
uint32_t port_count;
uint32_t last_port;
@ -170,44 +171,58 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->user_data, port->direction, port->id, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
static int impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
uint32_t i;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
for (i = 0; i < this->last_port; i++) {
if (this->in_ports[i].valid)
emit_port_info(this, GET_IN_PORT(this, i), true);
}
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
struct impl *this;
uint32_t i;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
emit_node_info(this);
emit_port_info(this, GET_OUT_PORT(this, 0));
for (i = 0; i < this->last_port; i++) {
if (this->in_ports[i].valid)
emit_port_info(this, GET_IN_PORT(this, i));
}
return 0;
}
@ -233,13 +248,13 @@ static int impl_node_add_port(struct spa_node *node, enum spa_direction directio
port->io_mute = &port->props.mute;
spa_list_init(&port->queue);
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_REMOVABLE |
SPA_PORT_FLAG_OPTIONAL |
SPA_PORT_FLAG_IN_PLACE;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -253,7 +268,7 @@ static int impl_node_add_port(struct spa_node *node, enum spa_direction directio
this->last_port = port_id + 1;
spa_log_info(this->log, NAME " %p: add port %d", this, port_id);
emit_port_info(this, port);
emit_port_info(this, port, true);
return 0;
}
@ -289,8 +304,7 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
this->last_port = i + 1;
}
spa_log_info(this->log, NAME " %p: remove port %d", this, port_id);
if (this->callbacks && this->callbacks->port_info)
this->callbacks->port_info(this->user_data, direction, port_id, NULL);
spa_node_emit_port_info(&this->hooks, direction, port_id, NULL);
return 0;
}
@ -437,8 +451,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -520,6 +533,7 @@ static int port_set_format(struct spa_node *node,
spa_log_info(this->log, NAME " %p: set format on port %d", this, port_id);
}
}
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
@ -527,7 +541,7 @@ static int port_set_format(struct spa_node *node,
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -868,11 +882,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -937,6 +952,8 @@ impl_init(const struct spa_handle_factory *factory,
this->log = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = MAX_PORTS;

View file

@ -86,6 +86,7 @@ struct impl;
typedef int (*render_func_t) (struct impl *this, void *samples, size_t n_samples);
struct port {
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[5];
@ -112,10 +113,12 @@ struct impl {
struct spa_log *log;
struct spa_loop *data_loop;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[2];
struct props props;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
@ -144,13 +147,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -233,8 +234,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -456,23 +456,50 @@ static const struct spa_dict_item node_info_items[] = {
{ "media.class", "Audio/Source" },
};
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
this->info.props = &SPA_DICT_INIT_ARRAY(node_info_items);
this->callbacks->info(this->callbacks_data, &this->info);
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->callbacks_data, SPA_DIRECTION_OUTPUT, 0, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_OUTPUT, 0, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, &this->port, true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
@ -487,9 +514,6 @@ impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this, &this->port);
return 0;
}
@ -552,7 +576,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -641,8 +664,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -713,18 +735,17 @@ port_set_format(struct impl *this,
port->render_func = sine_funcs[idx];
}
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->info.change_mask |= SPA_PORT_CHANGE_MASK_RATE;
port->info.rate = port->current_format.info.raw.rate;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->info.rate = SPA_FRACTION(1, port->current_format.info.raw.rate);
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
} else {
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -944,11 +965,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -1025,13 +1047,15 @@ impl_init(const struct spa_handle_factory *factory,
this->data_loop = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all |= SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PROPS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_output_ports = 1;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PROPS;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
this->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
@ -1052,12 +1076,12 @@ impl_init(const struct spa_handle_factory *factory,
spa_loop_add_source(this->data_loop, &this->timer_source);
port = &this->port;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS | SPA_PORT_FLAG_NO_REF;
if (this->props.live)
this->info.flags |= SPA_PORT_FLAG_LIVE;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -68,6 +68,7 @@ struct port {
struct spa_audio_info current_format;
int frame_size;
uint64_t info_all;
struct spa_port_info info;
struct spa_io_buffers *io;
struct spa_io_range *range;
@ -92,9 +93,11 @@ struct impl {
struct spa_loop *main_loop;
struct spa_loop *data_loop;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[8];
struct props props;
@ -162,13 +165,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -225,8 +226,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -857,23 +857,50 @@ static const struct spa_dict_item node_info_items[] = {
{ "node.driver", "true" },
};
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
this->info.props = &SPA_DICT_INIT_ARRAY(node_info_items);
this->callbacks->info(this->callbacks_data, &this->info);
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->callbacks_data, SPA_DIRECTION_INPUT, 0, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_INPUT, 0, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, &this->port, true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
@ -888,9 +915,6 @@ impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this, &this->port);
return 0;
}
@ -919,13 +943,11 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
port = &this->port;
@ -1029,8 +1051,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -1077,20 +1098,19 @@ static int port_set_format(struct impl *this, struct port *port,
this->threshold = this->props.min_latency;
}
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS | SPA_PORT_FLAG_LIVE;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_RATE;
port->info.rate = port->current_format.info.raw.rate;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->info.rate = SPA_FRACTION(1, port->current_format.info.raw.rate);
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
} else {
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -1267,11 +1287,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -1349,22 +1370,24 @@ impl_init(const struct spa_handle_factory *factory,
}
this->node = impl_node;
spa_hook_list_init(&this->hooks);
reset_props(&this->props);
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
this->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
this->info.n_params = 2;
port = &this->port;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -62,8 +62,7 @@ struct impl {
struct spa_log *log;
struct spa_loop *main_loop;
const struct spa_device_callbacks *callbacks;
void *callbacks_data;
struct spa_hook_list hooks;
struct props props;
@ -103,7 +102,7 @@ static int emit_nodes(struct impl *this)
info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
info.props = &SPA_DICT_INIT_ARRAY(items);
this->callbacks->object_info(this->callbacks_data, 0, &info);
spa_device_emit_object_info(&this->hooks, 0, &info);
break;
}
}
@ -115,39 +114,40 @@ static const struct spa_dict_item info_items[] = {
{ "media.class", "Audio/Device" },
};
static int impl_set_callbacks(struct spa_device *device,
const struct spa_device_callbacks *callbacks,
void *data)
static int impl_add_listener(struct spa_device *device,
struct spa_hook *listener,
const struct spa_device_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(device != NULL, -EINVAL);
spa_return_val_if_fail(events != NULL, -EINVAL);
this = SPA_CONTAINER_OF(device, struct impl, device);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
this->callbacks = callbacks;
this->callbacks_data = data;
if (events->info) {
struct spa_device_info info;
if (callbacks) {
if (callbacks->info) {
struct spa_device_info info;
info = SPA_DEVICE_INFO_INIT();
info = SPA_DEVICE_INFO_INIT();
info.change_mask = SPA_DEVICE_CHANGE_MASK_PROPS;
info.props = &SPA_DICT_INIT_ARRAY(info_items);
info.change_mask = SPA_DEVICE_CHANGE_MASK_PROPS;
info.props = &SPA_DICT_INIT_ARRAY(info_items);
info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
info.n_params = 0;
info.params = NULL;
info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
info.n_params = 0;
info.params = NULL;
callbacks->info(data, &info);
}
if (this->callbacks->object_info)
emit_nodes(this);
spa_device_emit_info(&this->hooks, &info);
}
if (events->object_info)
emit_nodes(this);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
@ -168,7 +168,7 @@ static int impl_set_param(struct spa_device *device,
static const struct spa_device impl_device = {
SPA_VERSION_DEVICE,
impl_set_callbacks,
impl_add_listener,
impl_enum_params,
impl_set_param,
};
@ -241,6 +241,8 @@ impl_init(const struct spa_handle_factory *factory,
}
this->device = impl_device;
spa_hook_list_init(&this->hooks);
reset_props(&this->props);
return 0;

View file

@ -50,6 +50,10 @@ struct buffer {
};
struct port {
enum spa_direction direction;
uint32_t id;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[8];
@ -71,11 +75,11 @@ struct impl {
struct spa_log *log;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[2];
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
struct port in_ports[1];
struct port out_ports[1];
@ -124,43 +128,55 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, enum spa_direction direction, uint32_t id)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
struct port *port = GET_PORT(this, direction, id);
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->user_data, direction, id, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, GET_IN_PORT(this, 0), true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
struct impl *this;
if (node == NULL)
return -EINVAL;
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
emit_node_info(this);
emit_port_info(this, SPA_DIRECTION_INPUT, 0);
emit_port_info(this, SPA_DIRECTION_OUTPUT, 0);
return 0;
}
@ -267,8 +283,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -426,11 +441,12 @@ impl_node_port_reuse_buffer(struct spa_node *node, uint32_t port_id, uint32_t bu
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -479,29 +495,35 @@ spa_ffmpeg_dec_init(struct spa_handle *handle,
this->log = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = 1;
this->info.max_output_ports = 1;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.params = this->params;
port = GET_IN_PORT(this, 0);
port->direction = SPA_DIRECTION_INPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = 0;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->info.params = port->params;
port->info.n_params = 2;
port = GET_OUT_PORT(this, 0);
port->direction = SPA_DIRECTION_OUTPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = 0;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->info.params = port->params;

View file

@ -49,6 +49,10 @@ struct buffer {
};
struct port {
enum spa_direction direction;
uint32_t id;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[8];
@ -70,11 +74,11 @@ struct impl {
struct spa_log *log;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[2];
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
struct port in_ports[1];
struct port out_ports[1];
@ -122,43 +126,55 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, enum spa_direction direction, uint32_t id)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
struct port *port = GET_PORT(this, direction, id);
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->user_data, direction, id, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, GET_IN_PORT(this, 0), true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
struct impl *this;
if (node == NULL)
return -EINVAL;
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
emit_node_info(this);
emit_port_info(this, SPA_DIRECTION_INPUT, 0);
emit_port_info(this, SPA_DIRECTION_OUTPUT, 0);
return 0;
}
@ -252,8 +268,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -401,11 +416,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -453,29 +469,35 @@ spa_ffmpeg_enc_init(struct spa_handle *handle,
this->log = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = 1;
this->info.max_output_ports = 1;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.params = this->params;
port = GET_IN_PORT(this, 0);
port->direction = SPA_DIRECTION_INPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = 0;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->info.params = port->params;
port->info.n_params = 2;
port = GET_OUT_PORT(this, 0);
port->direction = SPA_DIRECTION_OUTPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = 0;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->info.params = port->params;

View file

@ -57,6 +57,7 @@ struct buffer {
};
struct port {
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[5];
@ -78,10 +79,12 @@ struct impl {
struct spa_log *log;
struct spa_loop *data_loop;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[1];
struct props props;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
@ -116,13 +119,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
struct spa_pod *param;
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -147,8 +148,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -337,22 +337,49 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->callbacks_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->callbacks_data, SPA_DIRECTION_INPUT, 0, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_INPUT, 0, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, &this->port, true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
@ -371,9 +398,6 @@ impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this, &this->port);
return 0;
}
@ -487,8 +511,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -685,11 +708,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -766,13 +790,15 @@ impl_init(const struct spa_handle_factory *factory,
this->data_loop = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = 1;
this->info.max_output_ports = 0;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
this->info.n_params = 1;
@ -793,12 +819,12 @@ impl_init(const struct spa_handle_factory *factory,
spa_loop_add_source(this->data_loop, &this->timer_source);
port = &this->port;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS | SPA_PORT_FLAG_NO_REF;
if (this->props.live)
port->info.flags |= SPA_PORT_FLAG_LIVE;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, 0);

View file

@ -58,6 +58,7 @@ struct buffer {
};
struct port {
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[5];
@ -79,10 +80,12 @@ struct impl {
struct spa_log *log;
struct spa_loop *data_loop;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[1];
struct props props;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
@ -120,13 +123,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
struct spa_pod *param;
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -156,8 +157,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -351,22 +351,48 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->callbacks_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->callbacks_data, SPA_DIRECTION_OUTPUT, 0, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_OUTPUT, 0, &port->info);
port->info.change_mask = 0;
}
}
static int impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, &this->port, true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
@ -385,9 +411,6 @@ impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this, &this->port);
return 0;
}
@ -447,7 +470,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(node, direction, port_id), -EINVAL);
port = &this->port;
@ -504,8 +526,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -725,11 +746,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -806,13 +828,15 @@ impl_init(const struct spa_handle_factory *factory,
this->data_loop = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = 0;
this->info.max_output_ports = 1;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
this->info.n_params = 1;
@ -832,12 +856,12 @@ impl_init(const struct spa_handle_factory *factory,
spa_loop_add_source(this->data_loop, &this->timer_source);
port = &this->port;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS | SPA_PORT_FLAG_NO_REF;
if (this->props.live)
port->info.flags |= SPA_PORT_FLAG_LIVE;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, 0);

View file

@ -63,13 +63,12 @@ struct impl {
struct props props;
const struct spa_device_callbacks *callbacks;
void *callbacks_data;
struct spa_hook_list hooks;
struct spa_v4l2_device dev;
};
static int emit_info(struct impl *this)
static int emit_info(struct impl *this, bool full)
{
int res;
struct spa_dict_item items[6];
@ -96,22 +95,18 @@ static int emit_info(struct impl *this)
info.n_params = SPA_N_ELEMENTS(params);
info.params = params;
if (this->callbacks->info)
this->callbacks->info(this->callbacks_data, &info);
spa_device_emit_info(&this->hooks, &info);
if (this->callbacks->object_info) {
if (spa_v4l2_is_capture(&this->dev)) {
struct spa_device_object_info oinfo;
if (spa_v4l2_is_capture(&this->dev)) {
struct spa_device_object_info oinfo;
oinfo = SPA_DEVICE_OBJECT_INFO_INIT();
oinfo.type = SPA_TYPE_INTERFACE_Node;
oinfo.factory = &spa_v4l2_source_factory;
oinfo.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
oinfo.props = &SPA_DICT_INIT(items, 6);
oinfo = SPA_DEVICE_OBJECT_INFO_INIT();
oinfo.type = SPA_TYPE_INTERFACE_Node;
oinfo.factory = &spa_v4l2_source_factory;
oinfo.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
oinfo.props = &SPA_DICT_INIT(items, 6);
this->callbacks->object_info(this->callbacks_data, 0, &oinfo);
}
spa_device_emit_object_info(&this->hooks, 0, &oinfo);
}
spa_v4l2_close(&this->dev);
@ -119,23 +114,26 @@ static int emit_info(struct impl *this)
return 0;
}
static int impl_set_callbacks(struct spa_device *device,
const struct spa_device_callbacks *callbacks,
void *data)
static int impl_add_listener(struct spa_device *device,
struct spa_hook *listener,
const struct spa_device_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
int res = 0;
spa_return_val_if_fail(device != NULL, -EINVAL);
spa_return_val_if_fail(events != NULL, -EINVAL);
this = SPA_CONTAINER_OF(device, struct impl, device);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
this->callbacks = callbacks;
this->callbacks_data = data;
if (events->info || events->object_info)
res = emit_info(this, true);
spa_hook_list_join(&this->hooks, &save);
if (callbacks) {
res = emit_info(this);
}
return res;
}
@ -155,7 +153,7 @@ static int impl_set_param(struct spa_device *device,
static const struct spa_device impl_device = {
SPA_VERSION_DEVICE,
impl_set_callbacks,
impl_add_listener,
impl_enum_params,
impl_set_param,
};
@ -217,6 +215,8 @@ impl_init(const struct spa_handle_factory *factory,
return -EINVAL;
}
spa_hook_list_init(&this->hooks);
this->device = impl_device;
this->dev.log = this->log;
this->dev.fd = -1;

View file

@ -113,6 +113,7 @@ struct port {
struct spa_source source;
uint64_t info_all;
struct spa_port_info info;
struct spa_io_buffers *io;
struct spa_io_sequence *control;
@ -127,10 +128,12 @@ struct impl {
struct spa_loop *main_loop;
struct spa_loop *data_loop;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[8];
struct props props;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
@ -157,13 +160,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -228,8 +229,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -329,23 +329,50 @@ static const struct spa_dict_item info_items[] = {
{ "node.driver", "true" },
};
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
this->info.props = &SPA_DICT_INIT_ARRAY(info_items);
this->callbacks->info(this->callbacks_data, &this->info);
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->callbacks_data, SPA_DIRECTION_OUTPUT, 0, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_OUTPUT, 0, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *data)
@ -359,9 +386,6 @@ static int impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this, GET_OUT_PORT(this, 0));
return 0;
}
@ -451,7 +475,6 @@ static int impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -534,8 +557,7 @@ static int impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -624,6 +646,7 @@ static int port_set_format(struct spa_node *node,
}
done:
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[5] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
@ -631,7 +654,7 @@ static int port_set_format(struct spa_node *node,
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[5] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -879,6 +902,7 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
@ -963,10 +987,14 @@ impl_init(const struct spa_handle_factory *factory,
}
this->node = impl_node;
spa_hook_list_init(&this->hooks);
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PROPS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_output_ports = 1;
this->info.change_mask = SPA_NODE_CHANGE_MASK_PROPS;
this->info.flags = SPA_NODE_FLAG_RT;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
this->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
@ -975,8 +1003,9 @@ impl_init(const struct spa_handle_factory *factory,
port = GET_OUT_PORT(this, 0);
spa_list_init(&port->queue);
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_LIVE |
SPA_PORT_FLAG_PHYSICAL |
SPA_PORT_FLAG_TERMINAL;

View file

@ -813,8 +813,7 @@ spa_v4l2_enum_format(struct impl *this, int seq,
spa_pod_builder_pop(&b, &f[1]);
result.param = spa_pod_builder_pop(&b, &f[0]);
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
goto exit;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -927,9 +926,10 @@ static int spa_v4l2_set_format(struct impl *this, struct spa_video_info *format,
SPA_PORT_FLAG_LIVE |
SPA_PORT_FLAG_PHYSICAL |
SPA_PORT_FLAG_TERMINAL;
port->info.rate = streamparm.parm.capture.timeperframe.denominator;
if (this->callbacks && this->callbacks->port_info)
this->callbacks->port_info(this->callbacks_data, SPA_DIRECTION_OUTPUT, 0, &port->info);
port->info.rate = SPA_FRACTION(port->rate.num, port->rate.denom);
spa_node_emit_port_info(&this->hooks, SPA_DIRECTION_OUTPUT, 0, &port->info);
port->info.change_mask = 0;
return 0;
}
@ -1143,15 +1143,13 @@ spa_v4l2_enum_controls(struct impl *this, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
goto exit;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
enum_end:
res = 0;
exit:
spa_v4l2_close(dev);
return res;
}

View file

@ -74,6 +74,7 @@ struct buffer {
};
struct port {
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[5];
@ -97,10 +98,12 @@ struct impl {
struct spa_log *log;
struct spa_loop *data_loop;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[2];
struct props props;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
@ -129,13 +132,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -202,8 +203,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -401,23 +401,50 @@ static const struct spa_dict_item node_info_items[] = {
{ "media.class", "Video/Source" },
};
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
this->info.props = &SPA_DICT_INIT_ARRAY(node_info_items);
this->callbacks->info(this->callbacks_data, &this->info);
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->callbacks_data, SPA_DIRECTION_OUTPUT, 0, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
SPA_DIRECTION_OUTPUT, 0, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, &this->port, true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
@ -432,9 +459,6 @@ impl_node_set_callbacks(struct spa_node *node,
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this, &this->port);
return 0;
}
@ -501,7 +525,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
port = &this->port;
@ -567,8 +590,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -631,7 +653,7 @@ static int port_set_format(struct impl *this, struct port *port,
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -816,11 +838,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -897,13 +920,15 @@ impl_init(const struct spa_handle_factory *factory,
this->data_loop = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PROPS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_output_ports = 1;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
this->info.flags = SPA_NODE_FLAG_RT;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PROPS;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
this->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
@ -924,12 +949,12 @@ impl_init(const struct spa_handle_factory *factory,
spa_loop_add_source(this->data_loop, &this->timer_source);
port = &this->port;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS | SPA_PORT_FLAG_NO_REF;
if (this->props.live)
this->info.flags |= SPA_PORT_FLAG_LIVE;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -69,6 +69,7 @@ struct port {
bool have_format;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[5];
@ -87,12 +88,12 @@ struct impl {
struct spa_log *log;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[5];
struct props props;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
struct spa_hook_list hooks;
struct spa_audio_info current_format;
int bpf;
@ -121,13 +122,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
struct props *p;
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
p = &this->props;
result.id = id;
@ -177,8 +176,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -244,40 +242,55 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->callbacks_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->callbacks_data, port->direction, port->id, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
static int
impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, GET_IN_PORT(this, 0), true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *data)
{
struct impl *this;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
emit_port_info(this, GET_IN_PORT(this, 0));
emit_port_info(this, GET_OUT_PORT(this, 0));
return 0;
}
@ -338,7 +351,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -421,8 +433,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -480,7 +491,7 @@ static int port_set_format(struct spa_node *node,
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -752,11 +763,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -821,11 +833,15 @@ impl_init(const struct spa_handle_factory *factory,
this->log = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info_all = SPA_NODE_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = 1;
this->info.max_output_ports = 1;
this->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
this->info.flags = SPA_NODE_FLAG_RT;
this->params[0] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ);
this->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
this->info.params = this->params;
@ -835,11 +851,11 @@ impl_init(const struct spa_handle_factory *factory,
port = GET_IN_PORT(this, 0);
port->direction = SPA_DIRECTION_INPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_IN_PLACE;
port->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -852,11 +868,11 @@ impl_init(const struct spa_handle_factory *factory,
port = GET_OUT_PORT(this, 0);
port->direction = SPA_DIRECTION_OUTPUT;
port->id = 0;
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_NODE_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_NO_REF;
port->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);

View file

@ -49,10 +49,10 @@ struct data {
struct spa_log *log;
struct spa_loop loop;
struct spa_node *node;
struct spa_pending_queue pending;
struct spa_hook listener;
};
static int print_param(struct spa_pending *pending, const void *result)
static int print_param(void *data, int seq, int res, const void *result)
{
const struct spa_result_node_params *r = result;
@ -69,7 +69,11 @@ inspect_node_params(struct data *data, struct spa_node *node,
{
int res;
uint32_t i;
struct spa_pending pending;
struct spa_hook listener;
static const struct spa_node_events node_events = {
SPA_VERSION_NODE_EVENTS,
.result = print_param,
};
for (i = 0; i < n_params; i++) {
printf("enumerating: %s:\n", spa_debug_type_find_name(spa_type_param, params[i].id));
@ -77,9 +81,9 @@ inspect_node_params(struct data *data, struct spa_node *node,
if (!SPA_FLAG_CHECK(params[i].flags, SPA_PARAM_INFO_READ))
continue;
spa_pending_queue_add(&data->pending, 0, &pending, print_param, data);
spa_node_add_listener(node, &listener, &node_events, data);
res = spa_node_enum_params(node, 0, params[i].id, 0, UINT32_MAX, NULL);
spa_pending_remove(&pending);
spa_hook_remove(&listener);
if (res != 0) {
error(0, -res, "enum_params %d", params[i].id);
@ -95,7 +99,11 @@ inspect_port_params(struct data *data, struct spa_node *node,
{
int res;
uint32_t i;
struct spa_pending pending;
struct spa_hook listener;
static const struct spa_node_events node_events = {
SPA_VERSION_NODE_EVENTS,
.result = print_param,
};
for (i = 0; i < n_params; i++) {
printf("param: %s: flags %c%c\n",
@ -107,12 +115,12 @@ inspect_port_params(struct data *data, struct spa_node *node,
continue;
printf("values:\n");
spa_pending_queue_add(&data->pending, 0, &pending, print_param, data);
spa_node_add_listener(node, &listener, &node_events, data);
res = spa_node_port_enum_params(node, 0,
direction, port_id,
params[i].id, 0, UINT32_MAX,
NULL);
spa_pending_remove(&pending);
spa_hook_remove(&listener);
if (res != 0) {
error(0, -res, "port_enum_params %d", params[i].id);
@ -165,24 +173,18 @@ static int node_port_info(void *_data, enum spa_direction direction, uint32_t id
return 0;
}
static int node_result(void *_data, int seq, int res, const void *result)
static const struct spa_node_events node_events =
{
struct data *data = _data;
return spa_pending_queue_complete(&data->pending, seq, res, result);
}
static const struct spa_node_callbacks node_callbacks =
{
SPA_VERSION_NODE_CALLBACKS,
SPA_VERSION_NODE_EVENTS,
.info = node_info,
.port_info = node_port_info,
.result = node_result,
};
static void inspect_node(struct data *data, struct spa_node *node)
{
data->node = node;
spa_node_set_callbacks(node, &node_callbacks, data);
spa_node_add_listener(node, &data->listener, &node_events, data);
spa_hook_remove(&data->listener);
}
static void inspect_factory(struct data *data, const struct spa_handle_factory *factory)
@ -283,8 +285,6 @@ int main(int argc, char *argv[])
data.support[2] = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_DataLoop, &data.loop);
data.n_support = 3;
spa_pending_queue_init(&data.pending);
if ((handle = dlopen(argv[1], RTLD_NOW)) == NULL) {
printf("can't load %s\n", argv[1]);
return -1;

View file

@ -74,8 +74,7 @@ struct data {
struct spa_hook remote_listener;
struct spa_node impl_node;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
struct spa_hook_list hooks;
struct spa_io_buffers *io;
struct spa_io_sequence *io_notify;
uint32_t io_notify_size;
@ -132,32 +131,40 @@ static int impl_send_command(struct spa_node *node, const struct spa_command *co
return 0;
}
static int impl_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct spa_port_info info;
struct spa_param_info params[5];
struct spa_hook_list save;
spa_hook_list_isolate(&d->hooks, &save, listener, events, data);
info = SPA_PORT_INFO_INIT();
info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
params[4] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
info.params = params;
info.n_params = 5;
spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_INPUT, 0, &info);
spa_hook_list_join(&d->hooks, &save);
return 0;
}
static int impl_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks, void *data)
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
d->callbacks = callbacks;
d->callbacks_data = data;
if (d->callbacks && d->callbacks->port_info) {
struct spa_port_info info;
struct spa_param_info params[5];
info = SPA_PORT_INFO_INIT();
info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
info.change_mask = SPA_PORT_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
params[4] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
info.params = params;
info.n_params = 5;
d->callbacks->port_info(d->callbacks_data, SPA_DIRECTION_INPUT, 0, &info);
}
return 0;
}
@ -198,7 +205,6 @@ static int impl_port_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
result.id = id;
result.next = start;
@ -282,8 +288,7 @@ static int impl_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = d->callbacks->result(d->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&d->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -437,6 +442,7 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_add_listener,
.set_callbacks = impl_set_callbacks,
.set_io = impl_set_io,
.send_command = impl_send_command,
@ -513,6 +519,8 @@ int main(int argc, char *argv[])
data.remote = pw_remote_new(data.core, NULL, 0);
data.path = argc > 1 ? argv[1] : NULL;
spa_hook_list_init(&data.hooks);
reset_props(&data.props);
if (SDL_Init(SDL_INIT_VIDEO) < 0) {

View file

@ -58,8 +58,7 @@ struct data {
struct spa_hook remote_listener;
struct spa_node impl_node;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
struct spa_hook_list hooks;
struct spa_io_buffers *io;
struct spa_io_control *io_notify;
uint32_t io_notify_size;
@ -101,35 +100,43 @@ static int impl_send_command(struct spa_node *node, const struct spa_command *co
return 0;
}
static int impl_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct spa_port_info info;
struct spa_dict_item items[1];
struct spa_param_info params[5];
struct spa_hook_list save;
spa_hook_list_isolate(&d->hooks, &save, listener, events, data);
info = SPA_PORT_INFO_INIT();
info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
info.change_mask |= SPA_PORT_CHANGE_MASK_PROPS;
items[0] = SPA_DICT_ITEM_INIT("port.dsp", "32 bit float mono audio");
info.props = &SPA_DICT_INIT_ARRAY(items);
info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
params[4] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
info.params = params;
info.n_params = 5;
spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_OUTPUT, 0, &info);
spa_hook_list_join(&d->hooks, &save);
return 0;
}
static int impl_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks, void *data)
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
d->callbacks = callbacks;
d->callbacks_data = data;
if (d->callbacks && d->callbacks->port_info) {
struct spa_port_info info;
struct spa_dict_item items[1];
struct spa_param_info params[5];
info = SPA_PORT_INFO_INIT();
info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
info.change_mask |= SPA_PORT_CHANGE_MASK_PROPS;
items[0] = SPA_DICT_ITEM_INIT("port.dsp", "32 bit float mono audio");
info.props = &SPA_DICT_INIT_ARRAY(items);
info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
params[4] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
info.params = params;
info.n_params = 5;
d->callbacks->port_info(d->callbacks_data, SPA_DIRECTION_OUTPUT, 0, &info);
}
return 0;
}
@ -169,7 +176,6 @@ static int impl_port_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
result.id = id;
result.next = start;
@ -255,8 +261,7 @@ static int impl_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = d->callbacks->result(d->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&d->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -444,6 +449,7 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_add_listener,
.set_callbacks = impl_set_callbacks,
.set_io = impl_set_io,
.send_command = impl_send_command,
@ -510,6 +516,7 @@ int main(int argc, char *argv[])
data.path = argc > 1 ? argv[1] : NULL;
spa_list_init(&data.empty);
spa_hook_list_init(&data.hooks);
pw_remote_add_listener(data.remote, &data.remote_listener, &remote_events, &data);

View file

@ -58,8 +58,7 @@ struct data {
struct spa_node impl_node;
struct spa_io_buffers *io;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
struct spa_hook_list hooks;
struct spa_video_info_raw format;
int32_t stride;
@ -90,22 +89,31 @@ static int impl_send_command(struct spa_node *node, const struct spa_command *co
return 0;
}
static int impl_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
struct spa_port_info info;
struct spa_hook_list save;
spa_hook_list_isolate(&d->hooks, &save, listener, events, data);
info = SPA_PORT_INFO_INIT();
info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
spa_node_emit_port_info(&d->hooks, SPA_DIRECTION_INPUT, 0, &info);
spa_hook_list_join(&d->hooks, &save);
return 0;
}
static int impl_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks, void *data)
{
struct data *d = SPA_CONTAINER_OF(node, struct data, impl_node);
d->callbacks = callbacks;
d->callbacks_data = data;
if (d->callbacks && d->callbacks->port_info) {
struct spa_port_info info;
info = SPA_PORT_INFO_INIT();
info.change_mask = SPA_PORT_CHANGE_MASK_FLAGS;
info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
d->callbacks->port_info(d->callbacks_data, SPA_DIRECTION_INPUT, 0, &info);
}
return 0;
}
@ -133,7 +141,6 @@ static int impl_port_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_result_node_params result;
uint32_t count = 0;
int res;
result.id = id;
result.next = start;
@ -184,8 +191,7 @@ static int impl_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = d->callbacks->result(d->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&d->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -315,9 +321,10 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
NULL,
.add_listener = impl_add_listener,
.set_callbacks = impl_set_callbacks,
.set_io = impl_set_io,
.send_command = impl_send_command,
.set_callbacks = impl_set_callbacks,
.port_set_io = impl_port_set_io,
.port_enum_params = impl_port_enum_params,
.port_set_param = impl_port_set_param,
@ -367,6 +374,8 @@ int main(int argc, char *argv[])
data.loop = pw_main_loop_new(NULL);
data.core = pw_core_new(pw_main_loop_get_loop(data.loop), NULL, 0);
spa_hook_list_init(&data.hooks);
pw_module_load(data.core, "libpipewire-module-spa-node-factory", NULL, NULL, NULL, NULL);
if (SDL_Init(SDL_INIT_VIDEO) < 0) {

View file

@ -76,6 +76,7 @@ struct port {
struct spa_io_buffers *io;
struct spa_io_range *range;
uint64_t info_all;
struct spa_port_info info;
struct spa_param_info params[8];
@ -95,11 +96,11 @@ struct impl {
struct spa_log *log;
uint64_t info_all;
struct spa_node_info info;
struct spa_param_info params[8];
const struct spa_node_callbacks *callbacks;
void *user_data;
struct spa_hook_list hooks;
uint32_t port_count;
uint32_t last_port;
@ -163,43 +164,58 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
return 0;
}
static void emit_node_info(struct impl *this)
static void emit_node_info(struct impl *this, bool full)
{
if (this->callbacks && this->callbacks->info && this->info.change_mask) {
this->callbacks->info(this->user_data, &this->info);
if (full)
this->info.change_mask = this->info_all;
if (this->info.change_mask) {
spa_node_emit_info(&this->hooks, &this->info);
this->info.change_mask = 0;
}
}
static void emit_port_info(struct impl *this, struct port *port)
static void emit_port_info(struct impl *this, struct port *port, bool full)
{
if (this->callbacks && this->callbacks->port_info && port->info.change_mask) {
this->callbacks->port_info(this->user_data, port->direction, port->id, &port->info);
if (full)
port->info.change_mask = port->info_all;
if (port->info.change_mask) {
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
port->info.change_mask = 0;
}
}
static int impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct impl *this;
struct spa_hook_list save;
uint32_t i;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this, true);
emit_port_info(this, GET_OUT_PORT(this, 0), true);
for (i = 0; i < this->last_port; i++) {
if (this->in_ports[i].valid)
emit_port_info(this, GET_IN_PORT(this, i), true);
}
spa_hook_list_join(&this->hooks, &save);
return 0;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *user_data)
{
struct impl *this;
uint32_t i;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
this->callbacks = callbacks;
this->user_data = user_data;
emit_node_info(this);
emit_port_info(this, GET_OUT_PORT(this, 0));
for (i = 0; i < this->last_port; i++) {
if (this->in_ports[i].valid)
emit_port_info(this, GET_IN_PORT(this, i));
}
return 0;
}
@ -222,13 +238,13 @@ static int impl_node_add_port(struct spa_node *node, enum spa_direction directio
port_props_reset(&port->props);
spa_list_init(&port->queue);
port->info_all = SPA_PORT_CHANGE_MASK_FLAGS |
SPA_PORT_CHANGE_MASK_PARAMS;
port->info = SPA_PORT_INFO_INIT();
port->info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
port->info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS |
SPA_PORT_FLAG_REMOVABLE |
SPA_PORT_FLAG_OPTIONAL |
SPA_PORT_FLAG_IN_PLACE;
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
port->params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
port->params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
@ -243,7 +259,7 @@ static int impl_node_add_port(struct spa_node *node, enum spa_direction directio
port->valid = true;
spa_log_info(this->log, NAME " %p: add port %d %d", this, port_id, this->last_port);
emit_port_info(this, port);
emit_port_info(this, port, true);
return 0;
}
@ -281,8 +297,7 @@ impl_node_remove_port(struct spa_node *node, enum spa_direction direction, uint3
}
spa_log_info(this->log, NAME " %p: remove port %d %d", this, port_id, this->last_port);
if (this->callbacks && this->callbacks->port_info)
this->callbacks->port_info(this->user_data, direction, port_id, NULL);
spa_node_emit_port_info(&this->hooks, direction, port_id, NULL);
return 0;
}
@ -335,7 +350,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct impl, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -425,8 +439,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->user_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -521,16 +534,15 @@ static int port_set_format(struct spa_node *node,
this, direction, port_id);
}
}
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
if (port->have_format) {
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READWRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, SPA_PARAM_INFO_READ);
} else {
port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
port->params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
port->params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
}
emit_port_info(this, port);
emit_port_info(this, port, false);
return 0;
}
@ -830,11 +842,12 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.enum_params = impl_node_enum_params,
.set_param = impl_node_set_param,
.set_io = impl_node_set_io,
.send_command = impl_node_send_command,
.set_callbacks = impl_node_set_callbacks,
.add_port = impl_node_add_port,
.remove_port = impl_node_remove_port,
.port_enum_params = impl_node_port_enum_params,
@ -899,6 +912,8 @@ impl_init(const struct spa_handle_factory *factory,
this->log = support[i].data;
}
spa_hook_list_init(&this->hooks);
this->node = impl_node;
this->info = SPA_NODE_INFO_INIT();
this->info.max_input_ports = MAX_PORTS;

View file

@ -126,6 +126,7 @@ struct node {
struct spa_log *log;
struct spa_loop *data_loop;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
struct io ios[MAX_IO];
@ -363,13 +364,11 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
struct spa_pod_builder b = { 0 };
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
result.id = id;
result.next = start;
@ -391,8 +390,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
continue;
pw_log_debug("client-node %p: %d param %u", this, seq, result.index);
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count == num)
break;
@ -481,27 +479,24 @@ static int impl_node_send_command(struct spa_node *node, const struct spa_comman
static void emit_port_info(struct node *this, struct port *port)
{
if (this->callbacks && this->callbacks->port_info)
this->callbacks->port_info(this->callbacks_data,
spa_node_emit_port_info(&this->hooks,
port->direction, port->id, &port->info);
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *data)
static int impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct node *this;
struct spa_hook_list save;
uint32_t i;
int res = 0;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
this->callbacks = callbacks;
this->callbacks_data = data;
pw_log_debug("client-node %p: callbacks %p", this, callbacks);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
for (i = 0; i < MAX_INPUTS; i++) {
if (this->in_ports[i])
@ -511,12 +506,30 @@ impl_node_set_callbacks(struct spa_node *node,
if (this->out_ports[i])
emit_port_info(this, this->out_ports[i]);
}
if (callbacks && this->resource)
if (this->resource)
res = pw_resource_sync(this->resource, 0);
spa_hook_list_join(&this->hooks, &save);
return res;
}
static int
impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *data)
{
struct node *this;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
this->callbacks = callbacks;
this->callbacks_data = data;
return 0;
}
static int
impl_node_sync(struct spa_node *node, int seq)
{
@ -561,6 +574,8 @@ do_update_port(struct node *this,
pw_properties_free(port->properties);
port->properties = NULL;
port->info.props = NULL;
port->info.n_params = 0;
port->info.params = NULL;
if (info) {
port->info = *info;
@ -603,8 +618,7 @@ clear_port(struct node *this, struct port *port)
this->n_outputs--;
}
}
if (this->callbacks && this->callbacks->port_info)
this->callbacks->port_info(this->callbacks_data, port->direction, port->id, NULL);
spa_node_emit_port_info(&this->hooks, port->direction, port->id, NULL);
}
static int
@ -646,13 +660,11 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
struct spa_pod_builder b = { 0 };
struct spa_result_node_params result;
uint32_t count = 0;
int res;
spa_return_val_if_fail(node != NULL, -EINVAL);
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL);
@ -681,8 +693,7 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
continue;
pw_log_debug("client-node %p: %d param %u", this, seq, result.index);
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count == num)
break;
@ -1056,9 +1067,8 @@ client_node_port_update(void *data,
n_params, params,
info);
if (this->callbacks && this->callbacks->port_info &&
info && (change_mask & PW_CLIENT_NODE_PORT_UPDATE_INFO))
this->callbacks->port_info(this->callbacks_data, direction, port_id, info);
if (info && (change_mask & PW_CLIENT_NODE_PORT_UPDATE_INFO))
spa_node_emit_port_info(&this->hooks, direction, port_id, info);
}
return 0;
}
@ -1073,8 +1083,7 @@ static int client_node_event(void *data, struct spa_event *event)
{
struct impl *impl = data;
struct node *this = &impl->node;
if (this->callbacks && this->callbacks->event)
this->callbacks->event(this->callbacks_data, event);
spa_node_emit_event(&this->hooks, event);
return 0;
}
@ -1110,6 +1119,7 @@ static void node_on_data_fd_events(struct spa_source *source)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
NULL,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.sync = impl_node_sync,
.enum_params = impl_node_enum_params,
@ -1153,6 +1163,7 @@ node_init(struct node *this,
}
this->node = impl_node;
spa_hook_list_init(&this->hooks);
spa_list_init(&this->pending_list);
init_ios(this->ios);
@ -1222,7 +1233,7 @@ static void client_node_resource_error(void *data, int seq, int res, const char
pw_log_error("client-node %p: error seq:%d %d (%s)", this, seq, res, message);
result.message = message;
this->callbacks->result(this->callbacks_data, seq, res, &result);
spa_node_emit_result(&this->hooks, seq, res, &result);
}
static void client_node_resource_done(void *data, int seq)
@ -1231,7 +1242,7 @@ static void client_node_resource_done(void *data, int seq)
struct node *this = &impl->node;
pw_log_debug("client-node %p: emit result %d", this, seq);
this->callbacks->result(this->callbacks_data, seq, 0, NULL);
spa_node_emit_result(&this->hooks, seq, 0, NULL);
}
void pw_client_node_registered(struct pw_client_node *this, uint32_t node_id)

View file

@ -67,8 +67,7 @@ struct node {
struct spa_log *log;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
struct spa_hook_list hooks;
};
struct impl {
@ -87,6 +86,7 @@ struct impl {
struct spa_node *cnode;
struct spa_node *adapter;
struct spa_hook adapter_listener;
struct spa_node *adapter_mix;
uint32_t adapter_mix_flags;
uint32_t adapter_mix_port;
@ -103,8 +103,6 @@ struct impl {
struct spa_buffer **buffers;
uint32_t n_buffers;
struct pw_memblock *mem;
struct spa_pending client_node_pending;
};
/** \endcond */
@ -126,7 +124,6 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
impl = this->impl;
result.id = id;
@ -142,8 +139,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
return 0;
if ((res = spa_node_enum_params_sync(impl->adapter,
id, &start, filter, &param, &b,
impl->this.node->pending)) != 1)
id, &start, filter, &param, &b)) != 1)
return res;
break;
@ -151,8 +147,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
case SPA_PARAM_Format:
if ((res = spa_node_port_enum_params_sync(impl->cnode,
impl->direction, 0,
id, &start, filter, &param, &b,
impl->client_node->node->pending)) != 1)
id, &start, filter, &param, &b)) != 1)
return res;
break;
@ -163,8 +158,7 @@ static int impl_node_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) < 0)
goto next;
if ((res = this->callbacks->result(this->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&this->hooks, seq, 0, &result);
if (++count != num)
goto next;
@ -221,7 +215,7 @@ static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flag
if (impl->started)
return -EIO;
pw_log_debug("set profile %d", id);
if (impl->adapter != impl->cnode) {
if (impl->adapter && impl->adapter != impl->cnode) {
if ((res = spa_node_set_param(impl->adapter, id, flags, param)) < 0)
return res;
@ -229,7 +223,7 @@ static int impl_node_set_param(struct spa_node *node, uint32_t id, uint32_t flag
}
break;
case SPA_PARAM_Props:
if (impl->adapter != impl->cnode) {
if (impl->adapter && impl->adapter != impl->cnode) {
if ((res = spa_node_set_param(impl->adapter, id, flags, param)) < 0)
return res;
}
@ -292,44 +286,73 @@ static int adapter_port_info(void *data,
struct impl *impl = data;
struct node *this = &impl->node;
if (this->callbacks && this->callbacks->port_info) {
if (direction == impl->direction) {
this->callbacks->port_info(this->callbacks_data, direction, port_id, info);
}
}
if (direction == impl->direction)
spa_node_emit_port_info(&this->hooks, direction, port_id, info);
return 0;
}
static int adapter_result(void *data, int seq, int res, const void *result)
{
struct impl *impl = data;
struct node *this = &impl->node;
return this->callbacks->result(this->callbacks_data, seq, res, result);
pw_log_debug("%p: result %d %d", this, seq, res);
spa_node_emit_result(&this->hooks, seq, res, result);
return 0;
}
static const struct spa_node_callbacks adapter_node_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
static const struct spa_node_events adapter_node_events = {
SPA_VERSION_NODE_EVENTS,
.port_info = adapter_port_info,
.result = adapter_result,
};
static void emit_node_info(struct node *this)
{
if (this->callbacks && this->callbacks->info) {
struct spa_node_info info;
struct spa_param_info params[4];
struct spa_node_info info;
struct spa_param_info params[4];
info = SPA_NODE_INFO_INIT();
info.max_input_ports = 0;
info.max_output_ports = 0;
info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
params[2] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Profile, SPA_PARAM_INFO_WRITE);
info.params = params;
info.n_params = 4;
this->callbacks->info(this->callbacks_data, &info);
info = SPA_NODE_INFO_INIT();
info.max_input_ports = 0;
info.max_output_ports = 0;
info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
params[2] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Profile, SPA_PARAM_INFO_WRITE);
info.params = params;
info.n_params = 4;
spa_node_emit_info(&this->hooks, &info);
}
static int impl_node_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct node *this;
struct impl *impl;
struct spa_hook l;
struct spa_hook_list save;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
impl = this->impl;
pw_log_debug("%p: add listener %p", this, listener);
spa_hook_list_isolate(&this->hooks, &save, listener, events, data);
emit_node_info(this);
if (impl->adapter && impl->adapter != impl->cnode) {
spa_zero(l);
spa_node_add_listener(impl->adapter, &l, &adapter_node_events, impl);
spa_hook_remove(&l);
}
spa_hook_list_join(&this->hooks, &save);
return spa_node_sync(impl->cnode, 0);
}
static int
@ -337,23 +360,7 @@ impl_node_set_callbacks(struct spa_node *node,
const struct spa_node_callbacks *callbacks,
void *data)
{
struct node *this;
struct impl *impl;
spa_return_val_if_fail(node != NULL, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
impl = this->impl;
this->callbacks = callbacks;
this->callbacks_data = data;
emit_node_info(this);
if (this->callbacks && impl->adapter && impl->adapter != impl->cnode)
spa_node_set_callbacks(impl->adapter, &adapter_node_callbacks, impl);
return spa_node_sync(impl->cnode, 0);
return 0;
}
static int
@ -429,7 +436,6 @@ impl_node_port_enum_params(struct spa_node *node, int seq,
spa_return_val_if_fail(num != 0, -EINVAL);
this = SPA_CONTAINER_OF(node, struct node, node);
spa_return_val_if_fail(this->callbacks && this->callbacks->result, -EIO);
impl = this->impl;
if (direction != impl->direction)
@ -459,8 +465,7 @@ static int debug_params(struct impl *impl, struct spa_node *node,
res = spa_node_port_enum_params_sync(node,
direction, port_id,
id, &state,
NULL, &param, &b,
impl->this.node->pending);
NULL, &param, &b);
if (res != 1) {
if (res < 0)
spa_log_error(this->log, " error: %s", spa_strerror(res));
@ -495,8 +500,7 @@ static int negotiate_format(struct impl *impl)
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
SPA_PARAM_EnumFormat, &state,
NULL, &format, &b,
impl->this.node->pending)) != 1) {
NULL, &format, &b)) != 1) {
debug_params(impl, impl->adapter_mix,
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
@ -508,8 +512,7 @@ static int negotiate_format(struct impl *impl)
if ((res = spa_node_port_enum_params_sync(impl->cnode,
impl->direction, 0,
SPA_PARAM_EnumFormat, &state,
format, &format, &b,
impl->client_node->node->pending)) != 1) {
format, &format, &b)) != 1) {
debug_params(impl, impl->cnode, impl->direction, 0,
SPA_PARAM_EnumFormat, format);
return -ENOTSUP;
@ -561,8 +564,7 @@ static int negotiate_buffers(struct impl *impl)
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
SPA_PARAM_Buffers, &state,
param, &param, &b,
impl->this.node->pending)) != 1) {
param, &param, &b)) != 1) {
debug_params(impl, impl->adapter_mix,
SPA_DIRECTION_REVERSE(impl->direction),
impl->adapter_mix_port,
@ -576,8 +578,7 @@ static int negotiate_buffers(struct impl *impl)
if ((res = spa_node_port_enum_params_sync(impl->cnode,
impl->direction, 0,
SPA_PARAM_Buffers, &state,
param, &param, &b,
impl->client_node->node->pending)) < 0) {
param, &param, &b)) < 0) {
debug_params(impl, impl->cnode, impl->direction, 0,
SPA_PARAM_Buffers, param);
return res;
@ -866,6 +867,7 @@ static int impl_node_process(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_node_add_listener,
.set_callbacks = impl_node_set_callbacks,
.sync = impl_node_sync,
.enum_params = impl_node_enum_params,
@ -896,6 +898,8 @@ node_init(struct node *this,
this->log = support[i].data;
}
this->node = impl_node;
spa_hook_list_init(&this->hooks);
return 0;
}
@ -910,21 +914,16 @@ static int do_port_info(void *data, struct pw_port *port)
info.flags = port->spa_flags;
info.props = &port->properties->dict;
node->callbacks->port_info(node->callbacks_data,
spa_node_emit_port_info(&node->hooks,
impl->direction, port->port_id, &info);
return 0;
}
static void emit_port_info(struct impl *impl)
{
struct node *node = &impl->node;
if (node->callbacks && node->callbacks->port_info) {
pw_node_for_each_port(impl->client_node->node,
impl->direction,
do_port_info,
impl);
}
pw_node_for_each_port(impl->client_node->node,
impl->direction,
do_port_info, impl);
}
static void client_node_initialized(void *data)
@ -992,8 +991,7 @@ static void client_node_initialized(void *data)
if ((res = spa_node_port_enum_params_sync(impl->cnode,
impl->direction, 0,
SPA_PARAM_EnumFormat, &state,
NULL, &format, &b,
impl->client_node->node->pending)) != 1) {
NULL, &format, &b)) != 1) {
pw_log_warn("client-stream %p: no format given", &impl->this);
impl->adapter = impl->cnode;
impl->adapter_mix = impl->client_port->mix;
@ -1038,8 +1036,8 @@ static void client_node_initialized(void *data)
impl->adapter_mix = impl->adapter;
impl->adapter_mix_port = 0;
impl->use_converter = true;
if (impl->node.callbacks != NULL)
spa_node_set_callbacks(impl->adapter, &adapter_node_callbacks, impl);
spa_node_add_listener(impl->adapter, &impl->adapter_listener,
&adapter_node_events, impl);
}
else {
impl->adapter = impl->cnode;
@ -1116,7 +1114,7 @@ static void client_node_result(void *data, int seq, int res, const void *result)
struct impl *impl = data;
struct node *node = &impl->node;
pw_log_debug("client-stream %p: result %d %d", &impl->this, seq, res);
node->callbacks->result(node->callbacks_data, seq, res, result);
spa_node_emit_result(&node->hooks, seq, res, result);
}
static void client_node_active_changed(void *data, bool active)

View file

@ -420,8 +420,7 @@ static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_
if (spa_node_port_enum_params_sync(port->node->node,
port->direction, port->port_id,
id, &idx2,
NULL, &param, &b,
port->node->pending) != 1)
NULL, &param, &b) != 1)
break;
params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1));
@ -434,7 +433,7 @@ static int add_port_update(struct pw_proxy *proxy, struct pw_port *port, uint32_
SPA_PORT_CHANGE_MASK_RATE |
SPA_PORT_CHANGE_MASK_PROPS;
pi.flags = port->spa_flags;
pi.rate = 0;
pi.rate = SPA_FRACTION(0, 1);
pi.props = &port->properties->dict;
pi.flags &= ~SPA_PORT_FLAG_CAN_ALLOC_BUFFERS;
}

View file

@ -170,17 +170,6 @@ void *pw_spa_node_get_user_data(struct pw_node *node)
return impl->user_data;
}
static int on_node_result(void *data, int seq, int res, const void *result)
{
struct spa_pending_queue *pending = data;
return spa_pending_queue_complete(pending, seq, res, result);
}
static const struct spa_node_callbacks node_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
.result = on_node_result,
};
static int
setup_props(struct pw_core *core, struct spa_node *spa_node, struct pw_properties *pw_props)
{
@ -192,15 +181,11 @@ setup_props(struct pw_core *core, struct spa_node *spa_node, struct pw_propertie
uint8_t buf[2048];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
const struct spa_pod_prop *prop = NULL;
struct spa_pending_queue pending;
spa_pending_queue_init(&pending);
spa_node_set_callbacks(spa_node, &node_callbacks, &pending);
if ((res = spa_node_enum_params_sync(spa_node,
res = spa_node_enum_params_sync(spa_node,
SPA_PARAM_Props, &index, NULL, &props,
&b, &pending)) != 1) {
&b);
if (res != 1) {
if (res < 0)
pw_log_debug("spa_node_get_props failed: %d", res);
return res;

View file

@ -836,8 +836,7 @@ int pw_core_find_format(struct pw_core *core,
if ((res = spa_node_port_enum_params_sync(output->node->node,
output->direction, output->port_id,
SPA_PARAM_Format, &oidx,
NULL, format, builder,
output->node->pending)) != 1) {
NULL, format, builder)) != 1) {
if (res == 0)
res = -EBADF;
asprintf(error, "error get output format: %s", spa_strerror(res));
@ -851,8 +850,7 @@ int pw_core_find_format(struct pw_core *core,
if ((res = spa_node_port_enum_params_sync(input->node->node,
input->direction, input->port_id,
SPA_PARAM_Format, &iidx,
NULL, format, builder,
input->node->pending)) != 1) {
NULL, format, builder)) != 1) {
if (res == 0)
res = -EBADF;
asprintf(error, "error get input format: %s", spa_strerror(res));
@ -872,8 +870,7 @@ int pw_core_find_format(struct pw_core *core,
if ((res = spa_node_port_enum_params_sync(input->node->node,
input->direction, input->port_id,
SPA_PARAM_EnumFormat, &iidx,
NULL, &filter, &fb,
input->node->pending)) != 1) {
NULL, &filter, &fb)) != 1) {
if (res == 0 && iidx == 0) {
asprintf(error, "error input enum formats: %s", spa_strerror(res));
goto error;
@ -888,8 +885,7 @@ int pw_core_find_format(struct pw_core *core,
if ((res = spa_node_port_enum_params_sync(output->node->node,
output->direction, output->port_id,
SPA_PARAM_EnumFormat, &oidx,
filter, format, builder,
output->node->pending)) != 1) {
filter, format, builder)) != 1) {
if (res == 0) {
oidx = 0;
goto again;

View file

@ -34,8 +34,6 @@
struct impl {
struct pw_device this;
struct spa_pending_queue pending;
};
struct resource_data {
@ -65,8 +63,6 @@ struct pw_device *pw_device_new(struct pw_core *core,
if (impl == NULL)
return NULL;
spa_pending_queue_init(&impl->pending);
this = &impl->this;
if (properties == NULL)
@ -138,12 +134,12 @@ struct result_device_params_data {
struct spa_pod *param);
};
static int result_device_params(struct spa_pending *pending, const void *result)
static int result_device_params(void *data, int seq, int res, const void *result)
{
struct result_device_params_data *d = pending->data;
struct result_device_params_data *d = data;
const struct spa_result_device_params *r =
(const struct spa_result_device_params *)result;
d->callback(d->data, pending->seq, r->id, r->index, r->next, r->param);
d->callback(d->data, seq, r->id, r->index, r->next, r->param);
return 0;
}
@ -157,21 +153,27 @@ int pw_device_for_each_param(struct pw_device *device,
struct spa_pod *param),
void *data)
{
struct impl *impl = SPA_CONTAINER_OF(device, struct impl, this);
int res;
struct result_device_params_data user_data = { data, callback };
struct spa_pending pending;
struct spa_hook listener;
static const struct spa_device_events device_events = {
SPA_VERSION_DEVICE_EVENTS,
.result = result_device_params,
};
if (max == 0)
max = UINT32_MAX;
spa_pending_queue_add(&impl->pending, seq, &pending,
result_device_params, &user_data);
pw_log_debug("device %p: params %s %u %u", device,
spa_debug_type_find_name(spa_type_param, param_id),
index, max);
spa_zero(listener);
spa_node_add_listener(device->implementation, &listener,
&device_events, &user_data);
res = spa_device_enum_params(device->implementation, seq,
param_id, index, max, filter);
spa_pending_remove(&pending);
spa_hook_remove(&listener);
return res;
}
@ -274,6 +276,7 @@ int pw_device_register(struct pw_device *device,
struct pw_properties *properties)
{
struct pw_core *core = device->core;
struct node_data *nd;
const char *str;
if (properties == NULL)
@ -296,10 +299,14 @@ int pw_device_register(struct pw_device *device,
if (device->global == NULL)
return -ENOMEM;
device->info.id = device->global->id;
pw_global_add_listener(device->global, &device->global_listener, &global_events, device);
pw_global_register(device->global, owner, parent);
device->info.id = device->global->id;
spa_list_for_each(nd, &device->node_list, link) {
pw_node_register(nd->node, NULL, device->global, NULL);
pw_node_set_active(nd->node, true);
}
return 0;
}
@ -412,9 +419,11 @@ static void device_add(struct pw_device *device, uint32_t id,
}
pw_node_set_implementation(node, iface);
pw_node_register(node, NULL, device->global, NULL);
pw_node_set_active(node, true);
if (device->global) {
pw_node_register(node, NULL, device->global, NULL);
pw_node_set_active(node, true);
}
return;
error:
@ -459,25 +468,27 @@ static int device_object_info(void *data, uint32_t id,
return 0;
}
static int device_result(void *data, int seq, int res, const void *result)
{
struct pw_device *device = data;
struct impl *impl = SPA_CONTAINER_OF(device, struct impl, this);
return spa_pending_queue_complete(&impl->pending, seq, res, result);
}
static const struct spa_device_callbacks device_callbacks = {
SPA_VERSION_DEVICE_CALLBACKS,
static const struct spa_device_events device_events = {
SPA_VERSION_DEVICE_EVENTS,
.info = device_info,
.object_info = device_object_info,
.result = device_result,
};
SPA_EXPORT
void pw_device_set_implementation(struct pw_device *device, struct spa_device *spa_device)
int pw_device_set_implementation(struct pw_device *device, struct spa_device *spa_device)
{
pw_log_debug("device %p: implementation %p", device, spa_device);
if (device->implementation) {
pw_log_error("device %p: implementation existed %p",
device, device->implementation);
return -EEXIST;
}
device->implementation = spa_device;
spa_device_set_callbacks(device->implementation, &device_callbacks, device);
spa_device_add_listener(device->implementation,
&device->listener, &device_events, device);
return 0;
}
SPA_EXPORT

View file

@ -76,7 +76,7 @@ void pw_device_destroy(struct pw_device *device);
void *pw_device_get_user_data(struct pw_device *device);
/** Set the device implementation */
void pw_device_set_implementation(struct pw_device *device, struct spa_device *spa_device);
int pw_device_set_implementation(struct pw_device *device, struct spa_device *spa_device);
/** Get the device implementation */
struct spa_device *pw_device_get_implementation(struct pw_device *device);

View file

@ -385,11 +385,22 @@ struct pw_device_info *pw_device_info_update(struct pw_device_info *info,
info->name = update->name ? strdup(update->name) : NULL;
info->change_mask = update->change_mask;
if (update->change_mask & PW_CLIENT_CHANGE_MASK_PROPS) {
if (update->change_mask & PW_DEVICE_CHANGE_MASK_PROPS) {
if (info->props)
pw_spa_dict_destroy(info->props);
info->props = pw_spa_dict_copy(update->props);
}
if (update->change_mask & PW_DEVICE_CHANGE_MASK_PARAMS) {
info->n_params = update->n_params;
free((void *) info->params);
if (update->params) {
size_t size = info->n_params * sizeof(struct spa_param_info);
info->params = malloc(size);
memcpy(info->params, update->params, size);
}
else
info->params = NULL;
}
return info;
}
@ -399,6 +410,7 @@ void pw_device_info_free(struct pw_device_info *info)
free((void *) info->name);
if (info->props)
pw_spa_dict_destroy(info->props);
free((void *) info->params);
free(info);
}

View file

@ -225,8 +225,7 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st
res = spa_node_port_enum_params_sync(output->node->node,
output->direction, output->port_id,
SPA_PARAM_Format, &index,
NULL, &current, &b,
output->node->pending);
NULL, &current, &b);
switch (res) {
case -EIO:
current = NULL;
@ -261,8 +260,7 @@ static int do_negotiate(struct pw_link *this, uint32_t in_state, uint32_t out_st
res = spa_node_port_enum_params_sync(input->node->node,
input->direction, input->port_id,
SPA_PARAM_Format, &index,
NULL, &current, &b,
input->node->pending);
NULL, &current, &b);
switch (res) {
case -EIO:
current = NULL;
@ -458,8 +456,7 @@ param_filter(struct pw_link *this,
pw_log_debug("iparam %d", iidx);
if ((res = spa_node_port_enum_params_sync(in_port->node->node,
in_port->direction, in_port->port_id,
id, &iidx, NULL, &iparam, &ib,
in_port->node->pending)) < 0)
id, &iidx, NULL, &iparam, &ib)) < 0)
break;
if (res != 1) {
@ -475,8 +472,7 @@ param_filter(struct pw_link *this,
pw_log_debug("oparam %d", oidx);
if (spa_node_port_enum_params_sync(out_port->node->node,
out_port->direction, out_port->port_id,
id, &oidx, iparam, &oparam, result,
out_port->node->pending) != 1) {
id, &oidx, iparam, &oparam, result) != 1) {
break;
}

View file

@ -63,7 +63,6 @@ struct impl {
uint32_t next_position;
int last_error;
struct spa_pending_queue pending;
int pause_on_idle:1;
};
@ -373,22 +372,8 @@ static void global_destroy(void *data)
pw_node_destroy(this);
}
static void global_registering(void *data)
{
struct pw_node *this = data;
struct pw_port *port;
spa_list_for_each(port, &this->input_ports, link)
pw_port_register(port, this->global->owner, this->global,
pw_properties_copy(port->properties));
spa_list_for_each(port, &this->output_ports, link)
pw_port_register(port, this->global->owner, this->global,
pw_properties_copy(port->properties));
}
static const struct pw_global_events global_events = {
PW_VERSION_GLOBAL_EVENTS,
.registering = global_registering,
.destroy = global_destroy,
};
@ -399,6 +384,7 @@ int pw_node_register(struct pw_node *this,
struct pw_properties *properties)
{
struct pw_core *core = this->core;
struct pw_port *port;
const char *str;
pw_log_debug("node %p: register", this);
@ -437,6 +423,13 @@ int pw_node_register(struct pw_node *this,
pw_global_add_listener(this->global, &this->global_listener, &global_events, this);
pw_global_register(this->global, owner, parent);
spa_list_for_each(port, &this->input_ports, link)
pw_port_register(port, this->global->owner, this->global,
pw_properties_copy(port->properties));
spa_list_for_each(port, &this->output_ports, link)
pw_port_register(port, this->global->owner, this->global,
pw_properties_copy(port->properties));
return 0;
}
@ -688,9 +681,6 @@ struct pw_node *pw_node_new(struct pw_core *core,
&this->activation) < 0)
goto clean_impl;
spa_pending_queue_init(&impl->pending);
this->pending = &impl->pending;
impl->work = pw_work_queue_new(this->core->main_loop);
if (impl->work == NULL)
goto clean_impl;
@ -810,6 +800,10 @@ static int node_info(void *data, const struct spa_node_info *info)
node->info.max_input_ports = info->max_input_ports;
node->info.max_output_ports = info->max_output_ports;
pw_log_debug("node %p: change_mask %08lx max_in:%u max_out:%u",
node, info->change_mask, info->max_input_ports,
info->max_output_ports);
if (info->change_mask & SPA_NODE_CHANGE_MASK_PROPS) {
update_properties(node, info->props);
}
@ -868,7 +862,6 @@ static int node_result(void *data, int seq, int res, const void *result)
pw_log_trace("node %p: result seq:%d res:%d", node, seq, res);
impl->last_error = res;
spa_pending_queue_complete(&impl->pending, seq, res, result);
if (SPA_RESULT_IS_ASYNC(seq))
pw_work_queue_complete(impl->work, &impl->this, SPA_RESULT_ASYNC_SEQ(seq), res);
@ -933,12 +926,16 @@ static int node_reuse_buffer(void *data, uint32_t port_id, uint32_t buffer_id)
return 0;
}
static const struct spa_node_callbacks node_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
static const struct spa_node_events node_events = {
SPA_VERSION_NODE_EVENTS,
.info = node_info,
.port_info = node_port_info,
.result = node_result,
.event = node_event,
};
static const struct spa_node_callbacks node_callbacks = {
SPA_VERSION_NODE_CALLBACKS,
.ready = node_ready,
.reuse_buffer = node_reuse_buffer,
};
@ -949,10 +946,17 @@ int pw_node_set_implementation(struct pw_node *node,
{
int res;
node->node = spa_node;
pw_log_debug("node %p: implementation %p", node, spa_node);
if (node->node) {
pw_log_error("node %p: implementation existed %p", node, node->node);
return -EEXIST;
}
node->node = spa_node;
spa_graph_node_set_callbacks(&node->rt.node, &spa_graph_node_impl_default, spa_node);
res = spa_node_set_callbacks(node->node, &node_callbacks, node);
spa_node_set_callbacks(node->node, &node_callbacks, node);
res = spa_node_add_listener(node->node, &node->listener, &node_events, node);
if (spa_node_set_io(node->node,
SPA_IO_Position,
@ -1086,12 +1090,11 @@ struct result_node_params_data {
struct spa_pod *param);
};
static int result_node_params(struct spa_pending *pending, const void *result)
static int result_node_params(void *data, int seq, int res, const void *result)
{
struct result_node_params_data *d = pending->data;
const struct spa_result_node_params *r =
(const struct spa_result_node_params *)result;
d->callback(d->data, pending->seq, r->id, r->index, r->next, r->param);
struct result_node_params_data *d = data;
const struct spa_result_node_params *r = result;
d->callback(d->data, seq, r->id, r->index, r->next, r->param);
return 0;
}
@ -1105,24 +1108,27 @@ int pw_node_for_each_param(struct pw_node *node,
struct spa_pod *param),
void *data)
{
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
int res;
struct result_node_params_data user_data = { data, callback };
struct spa_pending pending;
struct spa_hook listener;
static const struct spa_node_events node_events = {
SPA_VERSION_NODE_EVENTS,
.result = result_node_params,
};
if (max == 0)
max = UINT32_MAX;
pw_log_debug("node %p: params %s %u %u", impl,
pw_log_debug("node %p: params %s %u %u", node,
spa_debug_type_find_name(spa_type_param, param_id),
index, max);
spa_pending_queue_add(&impl->pending, seq, &pending,
result_node_params, &user_data);
spa_zero(listener);
spa_node_add_listener(node->node, &listener, &node_events, &user_data);
res = spa_node_enum_params(node->node, seq,
param_id, index, max,
filter);
spa_pending_remove(&pending);
spa_hook_remove(&listener);
return res;
}

View file

@ -798,12 +798,11 @@ struct result_port_params_data {
struct spa_pod *param);
};
static int result_port_params(struct spa_pending *pending, const void *result)
static int result_port_params(void *data, int seq, int res, const void *result)
{
struct result_port_params_data *d = pending->data;
const struct spa_result_node_params *r =
(const struct spa_result_node_params *)result;
d->callback(d->data, pending->seq, r->id, r->index, r->next, r->param);
struct result_port_params_data *d = data;
const struct spa_result_node_params *r = result;
d->callback(d->data, seq, r->id, r->index, r->next, r->param);
return 0;
}
@ -820,7 +819,11 @@ int pw_port_for_each_param(struct pw_port *port,
int res;
struct pw_node *node = port->node;
struct result_port_params_data user_data = { data, callback };
struct spa_pending pending;
struct spa_hook listener;
static const struct spa_node_events node_events = {
SPA_VERSION_NODE_EVENTS,
.result = result_port_params,
};
if (max == 0)
max = UINT32_MAX;
@ -829,14 +832,13 @@ int pw_port_for_each_param(struct pw_port *port,
spa_debug_type_find_name(spa_type_param, param_id),
index, max);
spa_pending_queue_add(node->pending, seq, &pending,
result_port_params, &user_data);
spa_zero(listener);
spa_node_add_listener(node->node, &listener, &node_events, &user_data);
res = spa_node_port_enum_params(node->node, seq,
port->direction, port->port_id,
param_id, index, max,
filter);
spa_pending_remove(&pending);
spa_hook_remove(&listener);
pw_log_debug("port %p: res %d: (%s)", port, res, spa_strerror(res));
return res;

View file

@ -265,6 +265,7 @@ struct pw_device {
struct spa_param_info params[32];
struct spa_device *implementation; /**< implementation */
struct spa_hook listener;
struct spa_hook_list listener_list;
struct spa_list node_list;
@ -353,6 +354,7 @@ struct pw_node {
struct spa_list driver_link;
struct spa_node *node; /**< SPA node implementation */
struct spa_hook listener;
struct spa_list input_ports; /**< list of input ports */
struct pw_map input_port_map; /**< map from port_id to port */
@ -371,8 +373,6 @@ struct pw_node {
struct pw_loop *data_loop; /**< the data loop for this node */
struct spa_pending_queue *pending;
uint32_t quantum_size; /**< desired quantum */
struct spa_source source; /**< source to remotely trigger this node */
struct pw_memblock *activation;

View file

@ -107,6 +107,7 @@ struct stream {
struct spa_port_info port_info;
struct spa_node impl_node;
struct spa_hook_list hooks;
const struct spa_node_callbacks *callbacks;
void *callbacks_data;
struct spa_io_buffers *io;
@ -315,40 +316,56 @@ static int impl_send_command(struct spa_node *node, const struct spa_command *co
static void emit_node_info(struct stream *d)
{
if (d->callbacks && d->callbacks->info) {
struct spa_node_info info;
info = SPA_NODE_INFO_INIT();
if (d->direction == SPA_DIRECTION_INPUT) {
info.max_input_ports = 1;
info.max_output_ports = 0;
} else {
info.max_input_ports = 0;
info.max_output_ports = 1;
}
info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
info.flags = SPA_NODE_FLAG_RT;
d->callbacks->info(d->callbacks_data, &info);
struct spa_node_info info;
info = SPA_NODE_INFO_INIT();
if (d->direction == SPA_DIRECTION_INPUT) {
info.max_input_ports = 1;
info.max_output_ports = 0;
} else {
info.max_input_ports = 0;
info.max_output_ports = 1;
}
info.change_mask |= SPA_NODE_CHANGE_MASK_FLAGS;
info.flags = SPA_NODE_FLAG_RT;
spa_node_emit_info(&d->hooks, &info);
}
static void emit_port_info(struct stream *d)
{
if (d->callbacks && d->callbacks->port_info) {
struct spa_port_info info;
struct spa_param_info params[5];
struct spa_port_info info;
struct spa_param_info params[5];
info = SPA_PORT_INFO_INIT();
info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
info.params = params;
info.n_params = 5;
d->callbacks->port_info(d->callbacks_data, d->direction, 0, &info);
}
info = SPA_PORT_INFO_INIT();
info.change_mask |= SPA_PORT_CHANGE_MASK_FLAGS;
info.flags = SPA_PORT_FLAG_CAN_USE_BUFFERS;
info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS;
params[0] = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, SPA_PARAM_INFO_READ);
params[1] = SPA_PARAM_INFO(SPA_PARAM_Meta, SPA_PARAM_INFO_READ);
params[2] = SPA_PARAM_INFO(SPA_PARAM_IO, SPA_PARAM_INFO_READ);
params[3] = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE);
params[4] = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0);
info.params = params;
info.n_params = 5;
spa_node_emit_port_info(&d->hooks, d->direction, 0, &info);
}
static int impl_add_listener(struct spa_node *node,
struct spa_hook *listener,
const struct spa_node_events *events,
void *data)
{
struct stream *d = SPA_CONTAINER_OF(node, struct stream, impl_node);
struct spa_hook_list save;
spa_hook_list_isolate(&d->hooks, &save, listener, events, data);
emit_node_info(d);
emit_port_info(d);
spa_hook_list_join(&d->hooks, &save);
return 0;
}
static int impl_set_callbacks(struct spa_node *node,
@ -359,9 +376,6 @@ static int impl_set_callbacks(struct spa_node *node,
d->callbacks = callbacks;
d->callbacks_data = data;
emit_node_info(d);
emit_port_info(d);
return 0;
}
@ -415,7 +429,6 @@ static int impl_port_enum_params(struct spa_node *node, int seq,
uint8_t buffer[1024];
struct spa_pod_builder b = { 0 };
uint32_t count = 0;
int res;
spa_return_val_if_fail(num != 0, -EINVAL);
@ -439,8 +452,7 @@ static int impl_port_enum_params(struct spa_node *node, int seq,
if (spa_pod_filter(&b, &result.param, param, filter) != 0)
continue;
if ((res = d->callbacks->result(d->callbacks_data, seq, 0, &result)) != 0)
return res;
spa_node_emit_result(&d->hooks, seq, 0, &result);
if (++count == num)
break;
@ -781,9 +793,10 @@ static int impl_node_process_output(struct spa_node *node)
static const struct spa_node impl_node = {
SPA_VERSION_NODE,
.add_listener = impl_add_listener,
.set_callbacks = impl_set_callbacks,
.set_io = impl_set_io,
.send_command = impl_send_command,
.set_callbacks = impl_set_callbacks,
.port_set_io = impl_port_set_io,
.port_enum_params = impl_port_enum_params,
.port_set_param = impl_port_set_param,
@ -928,6 +941,7 @@ struct pw_stream * pw_stream_new(struct pw_remote *remote, const char *name,
pw_properties_set(props, "node.name", name);
}
spa_hook_list_init(&impl->hooks);
this->properties = props;
this->remote = remote;

View file

@ -164,6 +164,25 @@ static void print_properties(struct spa_dict *props, char mark, bool header)
}
}
static void print_params(struct spa_param_info *params, uint32_t n_params, char mark, bool header)
{
uint32_t i;
if (header)
fprintf(stdout, "%c\tparams: (%u)\n", mark, n_params);
if (params == NULL || n_params == 0) {
if (header)
fprintf(stdout, "\t\tnone\n");
return;
}
for (i = 0; i < n_params; i++) {
fprintf(stdout, "%c\t %d (%s) %c%c\n", mark, params[i].id,
spa_debug_type_find_name(spa_type_param, params[i].id),
params[i].flags & SPA_PARAM_INFO_READ ? 'r' : '-',
params[i].flags & SPA_PARAM_INFO_WRITE ? 'w' : '-');
}
}
static bool do_not_implemented(struct data *data, const char *cmd, char *args, char **error)
{
asprintf(error, "Command \"%s\" not yet implemented", cmd);
@ -182,8 +201,7 @@ static bool do_create_node(struct data *data, const char *cmd, char *args, char
static bool do_destroy(struct data *data, const char *cmd, char *args, char **error);
static bool do_create_link(struct data *data, const char *cmd, char *args, char **error);
static bool do_export_node(struct data *data, const char *cmd, char *args, char **error);
static bool do_node_params(struct data *data, const char *cmd, char *args, char **error);
static bool do_port_params(struct data *data, const char *cmd, char *args, char **error);
static bool do_enum_params(struct data *data, const char *cmd, char *args, char **error);
static bool do_permissions(struct data *data, const char *cmd, char *args, char **error);
static bool do_get_permissions(struct data *data, const char *cmd, char *args, char **error);
@ -201,8 +219,7 @@ static struct command command_list[] = {
{ "destroy", "Destroy a global object. <object-id>", do_destroy },
{ "create-link", "Create a link between nodes. <node-id> <port-id> <node-id> <port-id> [<properties>]", do_create_link },
{ "export-node", "Export a local node to the current remote. <node-id> [remote-var]", do_export_node },
{ "node-params", "Enumerate params of a node <node-id> [<param-id-name>]", do_node_params },
{ "port-params", "Enumerate params of a port <port-id> [<param-id-name>]", do_port_params },
{ "enum-params", "Enumerate params of an object <object-id> [<param-id-name>]", do_enum_params },
{ "permissions", "Set permissions for a client <client-id> <permissions>", do_permissions },
{ "get-permissions", "Get permissions of a client <client-id>", do_get_permissions },
};
@ -553,7 +570,6 @@ static void info_module(struct proxy_data *pd)
static void info_node(struct proxy_data *pd)
{
struct pw_node_info *info = pd->info;
uint32_t i;
info_global(pd);
fprintf(stdout, "%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
@ -567,26 +583,17 @@ static void info_node(struct proxy_data *pd)
else
fprintf(stdout, "\n");
print_properties(info->props, MARK_CHANGE(4), true);
fprintf(stdout, "%c\tparams\n", MARK_CHANGE(5));
for (i = 0; i < info->n_params; i++) {
fprintf(stdout, "%c\t %d (%s)\n", MARK_CHANGE(5), info->params[i].id,
spa_debug_type_find_name(spa_type_param, info->params[i].id));
}
print_params(info->params, info->n_params, MARK_CHANGE(5), true);
info->change_mask = 0;
}
static void info_port(struct proxy_data *pd)
{
struct pw_port_info *info = pd->info;
uint32_t i;
info_global(pd);
print_properties(info->props, MARK_CHANGE(0), true);
fprintf(stdout, "%c\tparams\n", MARK_CHANGE(1));
for (i = 0; i < info->n_params; i++) {
fprintf(stdout, "%c\t %d (%s)\n", MARK_CHANGE(1), info->params[i].id,
spa_debug_type_find_name(spa_type_param, info->params[i].id));
}
print_params(info->params, info->n_params, MARK_CHANGE(1), true);
info->change_mask = 0;
}
@ -635,6 +642,7 @@ static void info_device(struct proxy_data *pd)
info_global(pd);
fprintf(stdout, "\tname: \"%s\"\n", info->name);
print_properties(info->props, MARK_CHANGE(0), true);
print_params(info->params, info->n_params, MARK_CHANGE(1), true);
info->change_mask = 0;
}
@ -697,13 +705,13 @@ static int node_event_info(void *object, const struct pw_node_info *info)
return 0;
}
static int node_event_param(void *object, int seq, uint32_t id,
static int event_param(void *object, int seq, uint32_t id,
uint32_t index, uint32_t next, const struct spa_pod *param)
{
struct proxy_data *data = object;
struct remote_data *rd = data->rd;
fprintf(stdout, "remote %d node %d param %d index %d\n",
fprintf(stdout, "remote %d object %d param %d index %d\n",
rd->id, data->global->id, id, index);
if (spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Format))
@ -716,7 +724,7 @@ static int node_event_param(void *object, int seq, uint32_t id,
static const struct pw_node_proxy_events node_events = {
PW_VERSION_NODE_PROXY_EVENTS,
.info = node_event_info,
.param = node_event_param
.param = event_param
};
@ -736,26 +744,10 @@ static int port_event_info(void *object, const struct pw_port_info *info)
return 0;
}
static int port_event_param(void *object, int seq, uint32_t id,
uint32_t index, uint32_t next, const struct spa_pod *param)
{
struct proxy_data *data = object;
struct remote_data *rd = data->rd;
fprintf(stdout, "remote %d port %d param %d index %d\n",
rd->id, data->global->id, id, index);
if (spa_pod_is_object_type(param, SPA_TYPE_OBJECT_Format))
spa_debug_format(2, NULL, param);
else
spa_debug_pod(2, NULL, param);
return 0;
}
static const struct pw_port_proxy_events port_events = {
PW_VERSION_PORT_PROXY_EVENTS,
.info = port_event_info,
.param = port_event_param
.param = event_param
};
static int factory_event_info(void *object, const struct pw_factory_info *info)
@ -861,7 +853,8 @@ static int device_event_info(void *object, const struct pw_device_info *info)
static const struct pw_device_proxy_events device_events = {
PW_VERSION_DEVICE_PROXY_EVENTS,
.info = device_event_info
.info = device_event_info,
.param = event_param
};
static void
@ -1183,7 +1176,7 @@ static bool do_export_node(struct data *data, const char *cmd, char *args, char
return false;
}
static bool do_node_params(struct data *data, const char *cmd, char *args, char **error)
static bool do_enum_params(struct data *data, const char *cmd, char *args, char **error)
{
struct remote_data *rd = data->current;
char *a[2];
@ -1205,55 +1198,28 @@ static bool do_node_params(struct data *data, const char *cmd, char *args, char
asprintf(error, "%s: unknown global %d", cmd, id);
return false;
}
if (global->type != PW_TYPE_INTERFACE_Node) {
asprintf(error, "object %d is not a node", atoi(a[0]));
return false;
}
if (global->proxy == NULL) {
if (!bind_global(rd, global, error))
return false;
}
pw_node_proxy_enum_params((struct pw_node_proxy*)global->proxy, 0,
switch (global->type) {
case PW_TYPE_INTERFACE_Node:
pw_node_proxy_enum_params((struct pw_node_proxy*)global->proxy, 0,
param_id, 0, 0, NULL);
return true;
}
static bool do_port_params(struct data *data, const char *cmd, char *args, char **error)
{
struct remote_data *rd = data->current;
char *a[2];
int n;
uint32_t id, param_id;
struct global *global;
n = pw_split_ip(args, WHITESPACE, 2, a);
if (n < 2) {
asprintf(error, "%s <object-id> <param-id>", cmd);
return false;
}
id = atoi(a[0]);
param_id = atoi(a[1]);
global = pw_map_lookup(&rd->globals, id);
if (global == NULL) {
asprintf(error, "%s: unknown global %d", cmd, id);
return false;
}
if (global->type != PW_TYPE_INTERFACE_Port) {
asprintf(error, "object %d is not a port", atoi(a[0]));
return false;
}
if (global->proxy == NULL) {
if (!bind_global(rd, global, error))
return false;
}
pw_port_proxy_enum_params((struct pw_port_proxy*)global->proxy, 0,
break;
case PW_TYPE_INTERFACE_Port:
pw_port_proxy_enum_params((struct pw_port_proxy*)global->proxy, 0,
param_id, 0, 0, NULL);
break;
case PW_TYPE_INTERFACE_Device:
pw_device_proxy_enum_params((struct pw_device_proxy*)global->proxy, 0,
param_id, 0, 0, NULL);
break;
default:
asprintf(error, "enum-params not implemented on object %d", atoi(a[0]));
return false;
}
return true;
}

View file

@ -147,6 +147,13 @@ static int add_param(struct proxy_data *data, uint32_t id, const struct spa_pod
return 0;
}
static int event_param(void *object, int seq, uint32_t id,
uint32_t index, uint32_t next, const struct spa_pod *param)
{
struct proxy_data *data = object;
return add_param(data, id, param);
}
static void print_params(struct proxy_data *data, char mark)
{
struct param *p;
@ -300,17 +307,10 @@ static int node_event_info(void *object, const struct pw_node_info *info)
return 0;
}
static int node_event_param(void *object, int seq, uint32_t id,
uint32_t index, uint32_t next, const struct spa_pod *param)
{
struct proxy_data *data = object;
return add_param(data, id, param);
}
static const struct pw_node_proxy_events node_events = {
PW_VERSION_NODE_PROXY_EVENTS,
.info = node_event_info,
.param = node_event_param
.param = event_param
};
static void print_port(struct proxy_data *data)
@ -369,17 +369,10 @@ static int port_event_info(void *object, const struct pw_port_info *info)
return 0;
}
static int port_event_param(void *object, int seq, uint32_t id,
uint32_t index, uint32_t next, const struct spa_pod *param)
{
struct proxy_data *data = object;
return add_param(data, id, param);
}
static const struct pw_port_proxy_events port_events = {
PW_VERSION_PORT_PROXY_EVENTS,
.info = port_event_info,
.param = port_event_param
.param = event_param
};
static int factory_event_info(void *object, const struct pw_factory_info *info)
@ -503,23 +496,22 @@ static const struct pw_link_proxy_events link_events = {
.info = link_event_info
};
static int device_event_info(void *object, const struct pw_device_info *info)
static void print_device(struct proxy_data *data)
{
struct proxy_data *data = object;
struct pw_device_info *info = data->info;
bool print_all, print_mark;
print_all = true;
if (data->info == NULL) {
if (data->first) {
printf("added:\n");
print_mark = false;
data->first = false;
}
else {
printf("changed:\n");
print_mark = true;
}
info = data->info = pw_device_info_update(data->info, info);
printf("\tid: %d\n", data->id);
printf("\tparent_id: %d\n", data->parent_id);
printf("\tpermissions: %c%c%c\n", data->permissions & PW_PERM_R ? 'r' : '-',
@ -528,14 +520,43 @@ static int device_event_info(void *object, const struct pw_device_info *info)
printf("\ttype: %s (version %d)\n",
spa_debug_type_find_name(pw_type_info(), data->type), data->version);
if (print_all) {
print_params(data, MARK_CHANGE(1));
print_properties(info->props, MARK_CHANGE(0));
}
}
static int device_event_info(void *object, const struct pw_device_info *info)
{
struct proxy_data *data = object;
struct pw_device_info *old = data->info;
uint32_t i;
if (info->change_mask & PW_DEVICE_CHANGE_MASK_PARAMS) {
for (i = 0; i < info->n_params; i++) {
if (old != NULL && info->params[i].flags == old->params[i].flags)
continue;
remove_params(data, info->params[i].id);
if (!SPA_FLAG_CHECK(info->params[i].flags, SPA_PARAM_INFO_READ))
continue;
pw_device_proxy_enum_params((struct pw_device_proxy*)data->proxy,
0, info->params[i].id, 0, 0, NULL);
}
add_pending(data);
}
data->info = pw_device_info_update(data->info, info);
if (data->pending_seq == 0)
data->print_func(data);
return 0;
}
static const struct pw_device_proxy_events device_events = {
PW_VERSION_DEVICE_PROXY_EVENTS,
.info = device_event_info
.info = device_event_info,
.param = event_param
};
static void
@ -593,6 +614,7 @@ static int registry_event_global(void *data, uint32_t id, uint32_t parent_id,
events = &device_events;
client_version = PW_VERSION_DEVICE;
destroy = (pw_destroy_t) pw_device_info_free;
print_func = print_device;
break;
case PW_TYPE_INTERFACE_Factory:
events = &factory_events;