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

@ -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);