mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
params: make method on node and port to enum params
Do not pass the params of the node in the node_info, instead, make a method to enumerate the params. This makes it possible for clients to only enumerate what they need and when they need it. Improve introspection of a port, add the name and properties. Add an enum_param method on the port that can be used to enumerate port formats. Change -monitor and -cli and add support for enum_params on the node and port.
This commit is contained in:
parent
a9a95a4205
commit
58667d6ced
14 changed files with 977 additions and 259 deletions
|
|
@ -200,30 +200,24 @@ new_node (GstPipeWireDeviceProvider *self, const struct pw_node_info *info, uint
|
|||
const gchar *klass = NULL;
|
||||
const struct spa_dict_item *item;
|
||||
GstPipeWireDeviceType type;
|
||||
int i;
|
||||
struct pw_type *t = self->type;
|
||||
|
||||
caps = gst_caps_new_empty ();
|
||||
#if 0
|
||||
int i;
|
||||
struct pw_type *t = self->type;
|
||||
for (i = 0; i < info->n_params; i++) {
|
||||
if (!spa_pod_is_object_id(info->params[i], t->param.idEnumFormat))
|
||||
continue;
|
||||
GstCaps *c1 = gst_caps_from_format (info->params[i], t->map);
|
||||
if (c1)
|
||||
gst_caps_append (caps, c1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (info->max_input_ports > 0 && info->max_output_ports == 0) {
|
||||
type = GST_PIPEWIRE_DEVICE_TYPE_SINK;
|
||||
|
||||
for (i = 0; i < info->n_input_params; i++) {
|
||||
if (!spa_pod_is_object_id(info->input_params[i], t->param.idEnumFormat))
|
||||
continue;
|
||||
GstCaps *c1 = gst_caps_from_format (info->input_params[i], t->map);
|
||||
if (c1)
|
||||
gst_caps_append (caps, c1);
|
||||
}
|
||||
}
|
||||
else if (info->max_output_ports > 0 && info->max_input_ports == 0) {
|
||||
} else if (info->max_output_ports > 0 && info->max_input_ports == 0) {
|
||||
type = GST_PIPEWIRE_DEVICE_TYPE_SOURCE;
|
||||
for (i = 0; i < info->n_output_params; i++) {
|
||||
if (!spa_pod_is_object_id(info->output_params[i], t->param.idEnumFormat))
|
||||
continue;
|
||||
GstCaps *c1 = gst_caps_from_format (info->output_params[i], t->map);
|
||||
if (c1)
|
||||
gst_caps_append (caps, c1);
|
||||
}
|
||||
} else {
|
||||
gst_caps_unref(caps);
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -740,7 +740,16 @@ static struct pw_node *make_node(struct impl *impl, const struct pw_properties *
|
|||
char node_name[128];
|
||||
int i;
|
||||
|
||||
snprintf(node_name, sizeof(node_name), "system%d", impl->node_count++);
|
||||
if ((alias = pw_properties_get(props, "alsa.device")) == NULL)
|
||||
goto error;
|
||||
|
||||
snprintf(node_name, sizeof(node_name), "system_%s", alias);
|
||||
for (i = 0; node_name[i]; i++) {
|
||||
if (node_name[i] == ':')
|
||||
node_name[i] = '_';
|
||||
}
|
||||
if ((alias = pw_properties_get(props, "alsa.card")) == NULL)
|
||||
goto error;
|
||||
|
||||
node = pw_node_new(impl->core, node_name, NULL, sizeof(struct node));
|
||||
if (node == NULL)
|
||||
|
|
@ -755,9 +764,6 @@ static struct pw_node *make_node(struct impl *impl, const struct pw_properties *
|
|||
n->buffer_size = 1024 / sizeof(float);
|
||||
pw_node_set_implementation(node, &n->node_impl);
|
||||
|
||||
if ((alias = pw_properties_get(props, "alsa.card")) == NULL)
|
||||
goto error;
|
||||
|
||||
p = make_port(n, direction, 0, 0, NULL);
|
||||
if (p == NULL)
|
||||
goto error_free_node;
|
||||
|
|
|
|||
|
|
@ -728,6 +728,8 @@ static void node_marshal_info(void *object, struct pw_node_info *info)
|
|||
|
||||
b = pw_protocol_native_begin_resource(resource, PW_NODE_PROXY_EVENT_INFO);
|
||||
|
||||
n_items = info->props ? info->props->n_items : 0;
|
||||
|
||||
spa_pod_builder_add(b,
|
||||
"[",
|
||||
"i", info->id,
|
||||
|
|
@ -735,24 +737,11 @@ static void node_marshal_info(void *object, struct pw_node_info *info)
|
|||
"s", info->name,
|
||||
"i", info->max_input_ports,
|
||||
"i", info->n_input_ports,
|
||||
"i", info->n_input_params, NULL);
|
||||
|
||||
for (i = 0; i < info->n_input_params; i++)
|
||||
spa_pod_builder_add(b, "P", info->input_params[i], NULL);
|
||||
|
||||
spa_pod_builder_add(b,
|
||||
"i", info->max_output_ports,
|
||||
"i", info->n_output_ports,
|
||||
"i", info->n_output_params, 0);
|
||||
|
||||
for (i = 0; i < info->n_output_params; i++)
|
||||
spa_pod_builder_add(b, "P", info->output_params[i], NULL);
|
||||
|
||||
n_items = info->props ? info->props->n_items : 0;
|
||||
|
||||
spa_pod_builder_add(b,
|
||||
"i", info->state,
|
||||
"s", info->error, "i", n_items, NULL);
|
||||
"s", info->error,
|
||||
"i", n_items, NULL);
|
||||
|
||||
for (i = 0; i < n_items; i++) {
|
||||
spa_pod_builder_add(b,
|
||||
|
|
@ -780,29 +769,11 @@ static int node_demarshal_info(void *object, void *data, size_t size)
|
|||
"s", &info.name,
|
||||
"i", &info.max_input_ports,
|
||||
"i", &info.n_input_ports,
|
||||
"i", &info.n_input_params, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
info.input_params = alloca(info.n_input_params * sizeof(struct spa_pod *));
|
||||
for (i = 0; i < info.n_input_params; i++)
|
||||
if (spa_pod_parser_get(&prs, "P", &info.input_params[i], NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"i", &info.max_output_ports,
|
||||
"i", &info.n_output_ports,
|
||||
"i", &info.n_output_params, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
info.output_params = alloca(info.n_output_params * sizeof(struct spa_pod *));
|
||||
for (i = 0; i < info.n_output_params; i++)
|
||||
if (spa_pod_parser_get(&prs, "P", &info.output_params[i], NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"i", &info.state,
|
||||
"s", &info.error,
|
||||
"i", &props.n_items, NULL) < 0)
|
||||
"i", &info.max_output_ports,
|
||||
"i", &info.n_output_ports,
|
||||
"i", &info.state,
|
||||
"s", &info.error,
|
||||
"i", &props.n_items, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
info.props = &props;
|
||||
|
|
@ -817,6 +788,198 @@ static int node_demarshal_info(void *object, void *data, size_t size)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void node_marshal_param(void *object, uint32_t id, uint32_t index, uint32_t next,
|
||||
const struct spa_pod *param)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_pod_builder *b;
|
||||
|
||||
b = pw_protocol_native_begin_resource(resource, PW_NODE_PROXY_EVENT_PARAM);
|
||||
|
||||
spa_pod_builder_struct(b, "I", id, "i", index, "i", next, "P", param);
|
||||
|
||||
pw_protocol_native_end_resource(resource, b);
|
||||
}
|
||||
|
||||
static int node_demarshal_param(void *object, void *data, size_t size)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t id, index, next;
|
||||
struct spa_pod *param;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"[ I", &id,
|
||||
"i", &index,
|
||||
"i", &next,
|
||||
"P", ¶m, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
pw_proxy_notify(proxy, struct pw_node_proxy_events, param, id, index, next, param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void node_marshal_enum_params(void *object, uint32_t id, uint32_t index, uint32_t num,
|
||||
const struct spa_pod *filter)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_builder *b;
|
||||
|
||||
b = pw_protocol_native_begin_proxy(proxy, PW_NODE_PROXY_METHOD_ENUM_PARAMS);
|
||||
|
||||
spa_pod_builder_struct(b,
|
||||
"I", id,
|
||||
"i", index,
|
||||
"i", num,
|
||||
"P", filter);
|
||||
|
||||
pw_protocol_native_end_proxy(proxy, b);
|
||||
}
|
||||
|
||||
static int node_demarshal_enum_params(void *object, void *data, size_t size)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t id, index, num;
|
||||
struct spa_pod *filter;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"[ I", &id,
|
||||
"i", &index,
|
||||
"i", &num,
|
||||
"P", &filter, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
pw_resource_do(resource, struct pw_node_proxy_methods, enum_params, id, index, num, filter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void port_marshal_info(void *object, struct pw_port_info *info)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_pod_builder *b;
|
||||
uint32_t i, n_items;
|
||||
|
||||
b = pw_protocol_native_begin_resource(resource, PW_PORT_PROXY_EVENT_INFO);
|
||||
|
||||
n_items = info->props ? info->props->n_items : 0;
|
||||
|
||||
spa_pod_builder_add(b,
|
||||
"[",
|
||||
"i", info->id,
|
||||
"l", info->change_mask,
|
||||
"s", info->name,
|
||||
"i", n_items, NULL);
|
||||
|
||||
for (i = 0; i < n_items; i++) {
|
||||
spa_pod_builder_add(b,
|
||||
"s", info->props->items[i].key,
|
||||
"s", info->props->items[i].value, NULL);
|
||||
}
|
||||
spa_pod_builder_add(b, "]", NULL);
|
||||
|
||||
pw_protocol_native_end_resource(resource, b);
|
||||
}
|
||||
|
||||
static int port_demarshal_info(void *object, void *data, size_t size)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_parser prs;
|
||||
struct spa_dict props;
|
||||
struct pw_port_info info;
|
||||
int i;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"["
|
||||
"i", &info.id,
|
||||
"l", &info.change_mask,
|
||||
"s", &info.name,
|
||||
"i", &props.n_items, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
info.props = &props;
|
||||
props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
|
||||
for (i = 0; i < props.n_items; i++) {
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"s", &props.items[i].key,
|
||||
"s", &props.items[i].value, NULL) < 0)
|
||||
return -EINVAL;
|
||||
}
|
||||
pw_proxy_notify(proxy, struct pw_port_proxy_events, info, &info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void port_marshal_param(void *object, uint32_t id, uint32_t index, uint32_t next,
|
||||
const struct spa_pod *param)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_pod_builder *b;
|
||||
|
||||
b = pw_protocol_native_begin_resource(resource, PW_PORT_PROXY_EVENT_PARAM);
|
||||
|
||||
spa_pod_builder_struct(b, "I", id, "i", index, "i", next, "P", param);
|
||||
|
||||
pw_protocol_native_end_resource(resource, b);
|
||||
}
|
||||
|
||||
static int port_demarshal_param(void *object, void *data, size_t size)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t id, index, next;
|
||||
struct spa_pod *param;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"[ I", &id,
|
||||
"i", &index,
|
||||
"i", &next,
|
||||
"P", ¶m, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
pw_proxy_notify(proxy, struct pw_port_proxy_events, param, id, index, next, param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void port_marshal_enum_params(void *object, uint32_t id, uint32_t index, uint32_t num,
|
||||
const struct spa_pod *filter)
|
||||
{
|
||||
struct pw_proxy *proxy = object;
|
||||
struct spa_pod_builder *b;
|
||||
|
||||
b = pw_protocol_native_begin_proxy(proxy, PW_PORT_PROXY_METHOD_ENUM_PARAMS);
|
||||
|
||||
spa_pod_builder_struct(b,
|
||||
"I", id,
|
||||
"i", index,
|
||||
"i", num,
|
||||
"P", filter);
|
||||
|
||||
pw_protocol_native_end_proxy(proxy, b);
|
||||
}
|
||||
|
||||
static int port_demarshal_enum_params(void *object, void *data, size_t size)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct spa_pod_parser prs;
|
||||
uint32_t id, index, num;
|
||||
struct spa_pod *filter;
|
||||
|
||||
spa_pod_parser_init(&prs, data, size, 0);
|
||||
if (spa_pod_parser_get(&prs,
|
||||
"[ I", &id,
|
||||
"i", &index,
|
||||
"i", &num,
|
||||
"P", &filter, NULL) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
pw_resource_do(resource, struct pw_port_proxy_methods, enum_params, id, index, num, filter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void client_marshal_info(void *object, struct pw_client_info *info)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
|
|
@ -1116,24 +1279,69 @@ const struct pw_protocol_marshal pw_protocol_native_factory_marshal = {
|
|||
PW_FACTORY_PROXY_EVENT_NUM,
|
||||
};
|
||||
|
||||
static const struct pw_node_proxy_methods pw_protocol_native_node_method_marshal = {
|
||||
PW_VERSION_NODE_PROXY_METHODS,
|
||||
&node_marshal_enum_params,
|
||||
};
|
||||
|
||||
static const struct pw_protocol_native_demarshal pw_protocol_native_node_method_demarshal[] = {
|
||||
{ &node_demarshal_enum_params, PW_PROTOCOL_NATIVE_REMAP, },
|
||||
};
|
||||
|
||||
static const struct pw_node_proxy_events pw_protocol_native_node_event_marshal = {
|
||||
PW_VERSION_NODE_PROXY_EVENTS,
|
||||
&node_marshal_info,
|
||||
&node_marshal_param,
|
||||
};
|
||||
|
||||
static const struct pw_protocol_native_demarshal pw_protocol_native_node_event_demarshal[] = {
|
||||
{ &node_demarshal_info, PW_PROTOCOL_NATIVE_REMAP, }
|
||||
{ &node_demarshal_info, PW_PROTOCOL_NATIVE_REMAP, },
|
||||
{ &node_demarshal_param, PW_PROTOCOL_NATIVE_REMAP, }
|
||||
};
|
||||
|
||||
static const struct pw_protocol_marshal pw_protocol_native_node_marshal = {
|
||||
PW_TYPE_INTERFACE__Node,
|
||||
PW_VERSION_NODE,
|
||||
NULL, NULL, 0,
|
||||
&pw_protocol_native_node_method_marshal,
|
||||
pw_protocol_native_node_method_demarshal,
|
||||
PW_NODE_PROXY_METHOD_NUM,
|
||||
&pw_protocol_native_node_event_marshal,
|
||||
pw_protocol_native_node_event_demarshal,
|
||||
PW_NODE_PROXY_EVENT_NUM,
|
||||
};
|
||||
|
||||
|
||||
static const struct pw_port_proxy_methods pw_protocol_native_port_method_marshal = {
|
||||
PW_VERSION_PORT_PROXY_METHODS,
|
||||
&port_marshal_enum_params,
|
||||
};
|
||||
|
||||
static const struct pw_protocol_native_demarshal pw_protocol_native_port_method_demarshal[] = {
|
||||
{ &port_demarshal_enum_params, PW_PROTOCOL_NATIVE_REMAP, },
|
||||
};
|
||||
|
||||
static const struct pw_port_proxy_events pw_protocol_native_port_event_marshal = {
|
||||
PW_VERSION_PORT_PROXY_EVENTS,
|
||||
&port_marshal_info,
|
||||
&port_marshal_param,
|
||||
};
|
||||
|
||||
static const struct pw_protocol_native_demarshal pw_protocol_native_port_event_demarshal[] = {
|
||||
{ &port_demarshal_info, PW_PROTOCOL_NATIVE_REMAP, },
|
||||
{ &port_demarshal_param, PW_PROTOCOL_NATIVE_REMAP, }
|
||||
};
|
||||
|
||||
static const struct pw_protocol_marshal pw_protocol_native_port_marshal = {
|
||||
PW_TYPE_INTERFACE__Port,
|
||||
PW_VERSION_PORT,
|
||||
&pw_protocol_native_port_method_marshal,
|
||||
pw_protocol_native_port_method_demarshal,
|
||||
PW_PORT_PROXY_METHOD_NUM,
|
||||
&pw_protocol_native_port_event_marshal,
|
||||
pw_protocol_native_port_event_demarshal,
|
||||
PW_PORT_PROXY_EVENT_NUM,
|
||||
};
|
||||
|
||||
static const struct pw_client_proxy_events pw_protocol_native_client_event_marshal = {
|
||||
PW_VERSION_CLIENT_PROXY_EVENTS,
|
||||
&client_marshal_info,
|
||||
|
|
@ -1176,6 +1384,7 @@ void pw_protocol_native_init(struct pw_protocol *protocol)
|
|||
pw_protocol_add_marshal(protocol, &pw_protocol_native_registry_marshal);
|
||||
pw_protocol_add_marshal(protocol, &pw_protocol_native_module_marshal);
|
||||
pw_protocol_add_marshal(protocol, &pw_protocol_native_node_marshal);
|
||||
pw_protocol_add_marshal(protocol, &pw_protocol_native_port_marshal);
|
||||
pw_protocol_add_marshal(protocol, &pw_protocol_native_factory_marshal);
|
||||
pw_protocol_add_marshal(protocol, &pw_protocol_native_client_marshal);
|
||||
pw_protocol_add_marshal(protocol, &pw_protocol_native_link_marshal);
|
||||
|
|
|
|||
|
|
@ -65,7 +65,8 @@ static void registry_bind(void *object, uint32_t id,
|
|||
pw_log_debug("global %p: bind global id %d, iface %s to %d", global, id,
|
||||
spa_type_map_get_type(core->type.map, type), new_id);
|
||||
|
||||
pw_global_bind(global, client, permissions, version, new_id);
|
||||
if (pw_global_bind(global, client, permissions, version, new_id) < 0)
|
||||
goto exit;
|
||||
|
||||
return;
|
||||
|
||||
|
|
|
|||
|
|
@ -484,7 +484,8 @@ pw_module_proxy_add_listener(struct pw_module_proxy *module,
|
|||
#define PW_VERSION_NODE 0
|
||||
|
||||
#define PW_NODE_PROXY_EVENT_INFO 0
|
||||
#define PW_NODE_PROXY_EVENT_NUM 1
|
||||
#define PW_NODE_PROXY_EVENT_PARAM 1
|
||||
#define PW_NODE_PROXY_EVENT_NUM 2
|
||||
|
||||
/** Node events */
|
||||
struct pw_node_proxy_events {
|
||||
|
|
@ -496,6 +497,19 @@ struct pw_node_proxy_events {
|
|||
* \param info info about the node
|
||||
*/
|
||||
void (*info) (void *object, struct pw_node_info *info);
|
||||
/**
|
||||
* Notify a node param
|
||||
*
|
||||
* Event emited as a result of the enum_params method.
|
||||
*
|
||||
* \param id the param id
|
||||
* \param index the param index
|
||||
* \param next the param index of the next param
|
||||
* \param param the parameter
|
||||
*/
|
||||
void (*param) (void *object,
|
||||
uint32_t id, uint32_t index, uint32_t next,
|
||||
const struct spa_pod *param);
|
||||
};
|
||||
|
||||
static inline void
|
||||
|
|
@ -508,12 +522,44 @@ pw_node_proxy_add_listener(struct pw_node_proxy *node,
|
|||
}
|
||||
|
||||
#define pw_node_resource_info(r,...) pw_resource_notify(r,struct pw_node_proxy_events,info,__VA_ARGS__)
|
||||
#define pw_node_resource_param(r,...) pw_resource_notify(r,struct pw_node_proxy_events,param,__VA_ARGS__)
|
||||
|
||||
#define PW_NODE_PROXY_METHOD_ENUM_PARAMS 0
|
||||
#define PW_NODE_PROXY_METHOD_NUM 1
|
||||
|
||||
/** Node methods */
|
||||
struct pw_node_proxy_methods {
|
||||
#define PW_VERSION_NODE_PROXY_METHODS 0
|
||||
uint32_t version;
|
||||
/**
|
||||
* Enumerate node parameters
|
||||
*
|
||||
* Start enumeration of node parameters. For each param, a
|
||||
* param event will be emited.
|
||||
*
|
||||
* \param id the parameter id to enum or SPA_ID_INVALID for all
|
||||
* \param start the start index or 0 for the first param
|
||||
* \param num the maximum number of params to retrieve
|
||||
* \param filter a param filter or NULL
|
||||
*/
|
||||
void (*enum_params) (void *object, uint32_t id, uint32_t start, uint32_t num,
|
||||
const struct spa_pod *filter);
|
||||
};
|
||||
|
||||
/** Registry */
|
||||
static inline void
|
||||
pw_node_proxy_enum_params(struct pw_node_proxy *node, uint32_t id, uint32_t index,
|
||||
uint32_t num, const struct spa_pod *filter)
|
||||
{
|
||||
pw_proxy_do((struct pw_proxy*)node, struct pw_node_proxy_methods, enum_params,
|
||||
id, index, num, filter);
|
||||
}
|
||||
|
||||
#define PW_VERSION_PORT 0
|
||||
|
||||
#define PW_PORT_PROXY_EVENT_INFO 0
|
||||
#define PW_PORT_PROXY_EVENT_NUM 1
|
||||
#define PW_PORT_PROXY_EVENT_PARAM 1
|
||||
#define PW_PORT_PROXY_EVENT_NUM 2
|
||||
|
||||
/** Port events */
|
||||
struct pw_port_proxy_events {
|
||||
|
|
@ -525,6 +571,19 @@ struct pw_port_proxy_events {
|
|||
* \param info info about the port
|
||||
*/
|
||||
void (*info) (void *object, struct pw_port_info *info);
|
||||
/**
|
||||
* Notify a port param
|
||||
*
|
||||
* Event emited as a result of the enum_params method.
|
||||
*
|
||||
* \param id the param id
|
||||
* \param index the param index
|
||||
* \param next the param index of the next param
|
||||
* \param param the parameter
|
||||
*/
|
||||
void (*param) (void *object,
|
||||
uint32_t id, uint32_t index, uint32_t next,
|
||||
const struct spa_pod *param);
|
||||
};
|
||||
|
||||
static inline void
|
||||
|
|
@ -537,6 +596,38 @@ pw_port_proxy_add_listener(struct pw_port_proxy *port,
|
|||
}
|
||||
|
||||
#define pw_port_resource_info(r,...) pw_resource_notify(r,struct pw_port_proxy_events,info,__VA_ARGS__)
|
||||
#define pw_port_resource_param(r,...) pw_resource_notify(r,struct pw_port_proxy_events,param,__VA_ARGS__)
|
||||
|
||||
#define PW_PORT_PROXY_METHOD_ENUM_PARAMS 0
|
||||
#define PW_PORT_PROXY_METHOD_NUM 1
|
||||
|
||||
/** Port methods */
|
||||
struct pw_port_proxy_methods {
|
||||
#define PW_VERSION_PORT_PROXY_METHODS 0
|
||||
uint32_t version;
|
||||
/**
|
||||
* Enumerate port parameters
|
||||
*
|
||||
* Start enumeration of port parameters. For each param, a
|
||||
* param event will be emited.
|
||||
*
|
||||
* \param id the parameter id to enumerate
|
||||
* \param start the start index or 0 for the first param
|
||||
* \param num the maximum number of params to retrieve
|
||||
* \param filter a param filter or NULL
|
||||
*/
|
||||
void (*enum_params) (void *object, uint32_t id, uint32_t start, uint32_t num,
|
||||
const struct spa_pod *filter);
|
||||
};
|
||||
|
||||
/** Registry */
|
||||
static inline void
|
||||
pw_port_proxy_enum_params(struct pw_port_proxy *port, uint32_t id, uint32_t index,
|
||||
uint32_t num, const struct spa_pod *filter)
|
||||
{
|
||||
pw_proxy_do((struct pw_proxy*)port, struct pw_port_proxy_methods, enum_params,
|
||||
id, index, num, filter);
|
||||
}
|
||||
|
||||
#define PW_VERSION_FACTORY 0
|
||||
|
||||
|
|
|
|||
|
|
@ -177,7 +177,6 @@ void pw_core_info_free(struct pw_core_info *info)
|
|||
struct pw_node_info *pw_node_info_update(struct pw_node_info *info,
|
||||
const struct pw_node_info *update)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (update == NULL)
|
||||
return info;
|
||||
|
|
@ -199,42 +198,10 @@ struct pw_node_info *pw_node_info_update(struct pw_node_info *info,
|
|||
info->max_input_ports = update->max_input_ports;
|
||||
info->n_input_ports = update->n_input_ports;
|
||||
}
|
||||
if (update->change_mask & PW_NODE_CHANGE_MASK_INPUT_PARAMS) {
|
||||
for (i = 0; i < info->n_input_params; i++)
|
||||
free(info->input_params[i]);
|
||||
info->n_input_params = update->n_input_params;
|
||||
if (info->n_input_params)
|
||||
info->input_params =
|
||||
realloc(info->input_params,
|
||||
info->n_input_params * sizeof(struct spa_pod *));
|
||||
else {
|
||||
free(info->input_params);
|
||||
info->input_params = NULL;
|
||||
}
|
||||
for (i = 0; i < info->n_input_params; i++) {
|
||||
info->input_params[i] = pw_spa_pod_copy(update->input_params[i]);
|
||||
}
|
||||
}
|
||||
if (update->change_mask & PW_NODE_CHANGE_MASK_OUTPUT_PORTS) {
|
||||
info->max_output_ports = update->max_output_ports;
|
||||
info->n_output_ports = update->n_output_ports;
|
||||
}
|
||||
if (update->change_mask & PW_NODE_CHANGE_MASK_OUTPUT_PARAMS) {
|
||||
for (i = 0; i < info->n_output_params; i++)
|
||||
free(info->output_params[i]);
|
||||
info->n_output_params = update->n_output_params;
|
||||
if (info->n_output_params)
|
||||
info->output_params =
|
||||
realloc(info->output_params,
|
||||
info->n_output_params * sizeof(struct spa_pod *));
|
||||
else {
|
||||
free(info->output_params);
|
||||
info->output_params = NULL;
|
||||
}
|
||||
for (i = 0; i < info->n_output_params; i++) {
|
||||
info->output_params[i] = pw_spa_pod_copy(update->output_params[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (update->change_mask & PW_NODE_CHANGE_MASK_STATE) {
|
||||
info->state = update->state;
|
||||
|
|
@ -252,20 +219,9 @@ struct pw_node_info *pw_node_info_update(struct pw_node_info *info,
|
|||
|
||||
void pw_node_info_free(struct pw_node_info *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
if (info->input_params) {
|
||||
for (i = 0; i < info->n_input_params; i++)
|
||||
free(info->input_params[i]);
|
||||
free(info->input_params);
|
||||
}
|
||||
if (info->output_params) {
|
||||
for (i = 0; i < info->n_output_params; i++)
|
||||
free(info->output_params[i]);
|
||||
free(info->output_params);
|
||||
}
|
||||
if (info->error)
|
||||
free((void *) info->error);
|
||||
if (info->props)
|
||||
|
|
@ -273,6 +229,44 @@ void pw_node_info_free(struct pw_node_info *info)
|
|||
free(info);
|
||||
}
|
||||
|
||||
struct pw_port_info *pw_port_info_update(struct pw_port_info *info,
|
||||
const struct pw_port_info *update)
|
||||
{
|
||||
|
||||
if (update == NULL)
|
||||
return info;
|
||||
|
||||
if (info == NULL) {
|
||||
info = calloc(1, sizeof(struct pw_port_info));
|
||||
if (info == NULL)
|
||||
return NULL;
|
||||
}
|
||||
info->id = update->id;
|
||||
info->change_mask = update->change_mask;
|
||||
|
||||
if (update->change_mask & PW_PORT_CHANGE_MASK_NAME) {
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
info->name = update->name ? strdup(update->name) : NULL;
|
||||
}
|
||||
if (update->change_mask & PW_PORT_CHANGE_MASK_PROPS) {
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
info->props = pw_spa_dict_copy(update->props);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
void pw_port_info_free(struct pw_port_info *info)
|
||||
{
|
||||
|
||||
if (info->name)
|
||||
free((void *) info->name);
|
||||
if (info->props)
|
||||
pw_spa_dict_destroy(info->props);
|
||||
free(info);
|
||||
}
|
||||
|
||||
struct pw_factory_info *pw_factory_info_update(struct pw_factory_info *info,
|
||||
const struct pw_factory_info *update)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -143,21 +143,16 @@ struct pw_node_info {
|
|||
uint32_t id; /**< id of the global */
|
||||
#define PW_NODE_CHANGE_MASK_NAME (1 << 0)
|
||||
#define PW_NODE_CHANGE_MASK_INPUT_PORTS (1 << 1)
|
||||
#define PW_NODE_CHANGE_MASK_INPUT_PARAMS (1 << 2)
|
||||
#define PW_NODE_CHANGE_MASK_OUTPUT_PORTS (1 << 3)
|
||||
#define PW_NODE_CHANGE_MASK_OUTPUT_PARAMS (1 << 4)
|
||||
#define PW_NODE_CHANGE_MASK_STATE (1 << 5)
|
||||
#define PW_NODE_CHANGE_MASK_PROPS (1 << 6)
|
||||
#define PW_NODE_CHANGE_MASK_OUTPUT_PORTS (1 << 2)
|
||||
#define PW_NODE_CHANGE_MASK_STATE (1 << 3)
|
||||
#define PW_NODE_CHANGE_MASK_PROPS (1 << 4)
|
||||
#define PW_NODE_CHANGE_MASK_ENUM_PARAMS (1 << 5)
|
||||
uint64_t change_mask; /**< bitfield of changed fields since last call */
|
||||
const char *name; /**< name the node, suitable for display */
|
||||
uint32_t max_input_ports; /**< maximum number of inputs */
|
||||
uint32_t n_input_ports; /**< number of inputs */
|
||||
struct spa_pod **input_params; /**< array of input params */
|
||||
uint32_t n_input_params; /**< number of input params */
|
||||
uint32_t max_output_ports; /**< maximum number of outputs */
|
||||
uint32_t n_output_ports; /**< number of outputs */
|
||||
struct spa_pod **output_params; /**< array of output params */
|
||||
uint32_t n_output_params; /**< number of output params */
|
||||
enum pw_node_state state; /**< the current state of the node */
|
||||
const char *error; /**< an error reason if \a state is error */
|
||||
struct spa_dict *props; /**< the properties of the node */
|
||||
|
|
@ -172,8 +167,21 @@ pw_node_info_free(struct pw_node_info *info);
|
|||
|
||||
struct pw_port_info {
|
||||
uint32_t id; /**< id of the global */
|
||||
#define PW_PORT_CHANGE_MASK_NAME (1 << 0)
|
||||
#define PW_PORT_CHANGE_MASK_PROPS (1 << 1)
|
||||
#define PW_PORT_CHANGE_MASK_ENUM_PARAMS (1 << 2)
|
||||
uint64_t change_mask; /**< bitfield of changed fields since last call */
|
||||
const char *name; /**< name the port, suitable for display */
|
||||
struct spa_dict *props; /**< the properties of the port */
|
||||
};
|
||||
|
||||
struct pw_port_info *
|
||||
pw_port_info_update(struct pw_port_info *info,
|
||||
const struct pw_port_info *update);
|
||||
|
||||
void
|
||||
pw_port_info_free(struct pw_port_info *info);
|
||||
|
||||
/** The factory information. Extra information can be added in later versions \memberof pw_introspect */
|
||||
struct pw_factory_info {
|
||||
uint32_t id; /**< id of the global */
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
#include <spa/clock/clock.h>
|
||||
#include <spa/lib/debug.h>
|
||||
#include <spa/pod/parser.h>
|
||||
|
||||
#include "pipewire/pipewire.h"
|
||||
#include "pipewire/interfaces.h"
|
||||
|
|
@ -43,6 +44,7 @@ struct impl {
|
|||
|
||||
struct resource_data {
|
||||
struct spa_hook resource_listener;
|
||||
struct pw_node *node;
|
||||
};
|
||||
|
||||
/** \endcond */
|
||||
|
|
@ -223,64 +225,11 @@ static int update_port_ids(struct pw_node *node)
|
|||
return 0;
|
||||
}
|
||||
|
||||
struct param_array {
|
||||
struct spa_pod **params;
|
||||
uint32_t n_params;
|
||||
};
|
||||
|
||||
static int add_param(void *data, struct spa_pod *param)
|
||||
{
|
||||
struct param_array *arr = data;
|
||||
uint32_t idx = arr->n_params++;
|
||||
|
||||
arr->params = realloc(arr->params, sizeof(struct spa_pod *) * arr->n_params);
|
||||
arr->params[idx] = pw_spa_pod_copy(param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
update_info(struct pw_node *this)
|
||||
{
|
||||
struct pw_type *t = &this->core->type;
|
||||
struct param_array params;
|
||||
struct pw_port *port;
|
||||
|
||||
params = (struct param_array) { NULL };
|
||||
if (!spa_list_is_empty(&this->input_ports)) {
|
||||
port = spa_list_first(&this->input_ports, struct pw_port, link);
|
||||
pw_port_for_each_param(port, t->param.idEnumFormat, NULL, add_param, ¶ms);
|
||||
}
|
||||
this->info.input_params = params.params;
|
||||
this->info.n_input_params = params.n_params;
|
||||
|
||||
params = (struct param_array) { NULL };
|
||||
if (!spa_list_is_empty(&this->output_ports)) {
|
||||
port = spa_list_first(&this->output_ports, struct pw_port, link);
|
||||
pw_port_for_each_param(port, t->param.idEnumFormat, NULL, add_param, ¶ms);
|
||||
}
|
||||
this->info.output_params = params.params;
|
||||
this->info.n_output_params = params.n_params;
|
||||
}
|
||||
|
||||
static void
|
||||
clear_info(struct pw_node *this)
|
||||
{
|
||||
int i;
|
||||
|
||||
free((char*)this->info.name);
|
||||
if (this->info.input_params) {
|
||||
for (i = 0; i < this->info.n_input_params; i++)
|
||||
free(this->info.input_params[i]);
|
||||
free(this->info.input_params);
|
||||
}
|
||||
|
||||
if (this->info.output_params) {
|
||||
for (i = 0; i < this->info.n_output_params; i++)
|
||||
free(this->info.output_params[i]);
|
||||
free(this->info.output_params);
|
||||
}
|
||||
free((char*)this->info.error);
|
||||
|
||||
}
|
||||
|
||||
static const struct pw_resource_events resource_events = {
|
||||
|
|
@ -288,6 +237,28 @@ static const struct pw_resource_events resource_events = {
|
|||
.destroy = node_unbind_func,
|
||||
};
|
||||
|
||||
static int reply_param(void *data, uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param)
|
||||
{
|
||||
struct pw_resource *resource = data;
|
||||
pw_node_resource_param(resource, id, index, next, param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void node_enum_params(void *object, uint32_t id, uint32_t index, uint32_t num,
|
||||
const struct spa_pod *filter)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct resource_data *data = pw_resource_get_user_data(resource);
|
||||
struct pw_node *node = data->node;
|
||||
|
||||
pw_node_for_each_param(node, id, index, num, filter, reply_param, resource);
|
||||
}
|
||||
|
||||
static const struct pw_node_proxy_methods node_methods = {
|
||||
PW_VERSION_NODE_PROXY_METHODS,
|
||||
.enum_params = node_enum_params
|
||||
};
|
||||
|
||||
static void
|
||||
global_bind(void *_data, struct pw_client *client, uint32_t permissions,
|
||||
uint32_t version, uint32_t id)
|
||||
|
|
@ -302,8 +273,11 @@ global_bind(void *_data, struct pw_client *client, uint32_t permissions,
|
|||
goto no_mem;
|
||||
|
||||
data = pw_resource_get_user_data(resource);
|
||||
data->node = this;
|
||||
pw_resource_add_listener(resource, &data->resource_listener, &resource_events, resource);
|
||||
|
||||
pw_resource_set_implementation(resource, &node_methods, resource);
|
||||
|
||||
pw_log_debug("node %p: bound to %d", this, resource->id);
|
||||
|
||||
spa_list_append(&this->resource_list, &resource->link);
|
||||
|
|
@ -362,7 +336,6 @@ int pw_node_register(struct pw_node *this,
|
|||
return -ENOMEM;
|
||||
|
||||
update_port_ids(this);
|
||||
update_info(this);
|
||||
|
||||
pw_loop_invoke(this->data_loop, do_node_add, 1, NULL, 0, false, this);
|
||||
|
||||
|
|
@ -386,9 +359,11 @@ int pw_node_register(struct pw_node *this,
|
|||
this->info.id = this->global->id;
|
||||
|
||||
spa_list_for_each(port, &this->input_ports, link)
|
||||
pw_port_register(port, owner, this->global, pw_properties_copy(port->properties));
|
||||
pw_port_register(port, owner, this->global,
|
||||
pw_properties_copy(port->properties));
|
||||
spa_list_for_each(port, &this->output_ports, link)
|
||||
pw_port_register(port, owner, this->global, pw_properties_copy(port->properties));
|
||||
pw_port_register(port, owner, this->global,
|
||||
pw_properties_copy(port->properties));
|
||||
|
||||
spa_hook_list_call(&this->listener_list, struct pw_node_events, initialized);
|
||||
|
||||
|
|
@ -487,7 +462,7 @@ int pw_node_update_properties(struct pw_node *node, const struct spa_dict *dict)
|
|||
|
||||
node->info.props = &node->properties->dict;
|
||||
|
||||
node->info.change_mask = PW_NODE_CHANGE_MASK_PROPS;
|
||||
node->info.change_mask |= PW_NODE_CHANGE_MASK_PROPS;
|
||||
spa_hook_list_call(&node->listener_list, struct pw_node_events,
|
||||
info_changed, &node->info);
|
||||
|
||||
|
|
@ -504,7 +479,7 @@ static void node_done(void *data, int seq, int res)
|
|||
struct pw_node *node = data;
|
||||
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
|
||||
|
||||
pw_log_debug("node %p: async complete event %d %d", node, seq, res);
|
||||
pw_log_debug("node %p: async complete event %d %d %s", node, seq, res, spa_strerror(res));
|
||||
pw_work_queue_complete(impl->work, node, seq, res);
|
||||
spa_hook_list_call(&node->listener_list, struct pw_node_events, async_complete, seq, res);
|
||||
}
|
||||
|
|
@ -680,6 +655,39 @@ int pw_node_for_each_port(struct pw_node *node,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int pw_node_for_each_param(struct pw_node *node,
|
||||
uint32_t param_id,
|
||||
uint32_t index, uint32_t max,
|
||||
const struct spa_pod *filter,
|
||||
int (*callback) (void *data,
|
||||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param),
|
||||
void *data)
|
||||
{
|
||||
int res = 0;
|
||||
uint32_t idx, count;
|
||||
uint8_t buf[4096];
|
||||
struct spa_pod_builder b = { 0 };
|
||||
struct spa_pod *param;
|
||||
|
||||
if (max == 0)
|
||||
max = UINT32_MAX;
|
||||
|
||||
for (count = 0; count < max; count++) {
|
||||
spa_pod_builder_init(&b, buf, sizeof(buf));
|
||||
|
||||
idx = index;
|
||||
if ((res = spa_node_enum_params(node->node,
|
||||
param_id, &index,
|
||||
filter, ¶m, &b)) <= 0)
|
||||
break;
|
||||
|
||||
if ((res = callback(data, param_id, idx, index, param)) != 0)
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
struct pw_port *
|
||||
pw_node_find_port(struct pw_node *node, enum pw_direction direction, uint32_t port_id)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -150,6 +150,14 @@ int pw_node_for_each_port(struct pw_node *node,
|
|||
int (*callback) (void *data, struct pw_port *port),
|
||||
void *data);
|
||||
|
||||
int pw_node_for_each_param(struct pw_node *node,
|
||||
uint32_t param_id,
|
||||
uint32_t index, uint32_t max,
|
||||
const struct spa_pod *filter,
|
||||
int (*callback) (void *data,
|
||||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param),
|
||||
void *data);
|
||||
|
||||
/** Find the port with direction and port_id or NULL when not found */
|
||||
struct pw_port *
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <spa/pod/parser.h>
|
||||
|
||||
#include "pipewire/pipewire.h"
|
||||
#include "pipewire/private.h"
|
||||
#include "pipewire/port.h"
|
||||
|
|
@ -31,6 +33,12 @@ struct impl {
|
|||
|
||||
struct spa_node mix_node;
|
||||
};
|
||||
|
||||
struct resource_data {
|
||||
struct spa_hook resource_listener;
|
||||
struct pw_port *port;
|
||||
};
|
||||
|
||||
/** \endcond */
|
||||
|
||||
|
||||
|
|
@ -128,7 +136,8 @@ static int schedule_mix_output(struct spa_node *data)
|
|||
*p->io = *io;
|
||||
}
|
||||
else {
|
||||
io->status = SPA_STATUS_OK;
|
||||
io->status = SPA_STATUS_HAVE_BUFFER;
|
||||
io->buffer_id = SPA_ID_INVALID;
|
||||
}
|
||||
pw_log_trace("mix output %d %d", io->status, io->buffer_id);
|
||||
return io->status;
|
||||
|
|
@ -187,10 +196,14 @@ struct pw_port *pw_port_new(enum pw_direction direction,
|
|||
if (user_data_size > 0)
|
||||
this->user_data = SPA_MEMBER(impl, sizeof(struct impl), void);
|
||||
|
||||
this->info.props = &this->properties->dict;
|
||||
|
||||
spa_list_init(&this->links);
|
||||
spa_list_init(&this->control_list[0]);
|
||||
spa_list_init(&this->control_list[1]);
|
||||
|
||||
spa_list_init(&this->resource_list);
|
||||
|
||||
spa_hook_list_init(&this->listener_list);
|
||||
|
||||
spa_graph_port_init(&this->rt.port,
|
||||
|
|
@ -235,12 +248,22 @@ const struct pw_properties *pw_port_get_properties(struct pw_port *port)
|
|||
|
||||
int pw_port_update_properties(struct pw_port *port, const struct spa_dict *dict)
|
||||
{
|
||||
struct pw_resource *resource;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < dict->n_items; i++)
|
||||
pw_properties_set(port->properties, dict->items[i].key, dict->items[i].value);
|
||||
|
||||
port->info.props = &port->properties->dict;
|
||||
|
||||
port->info.change_mask |= PW_PORT_CHANGE_MASK_PROPS;
|
||||
spa_hook_list_call(&port->listener_list, struct pw_port_events,
|
||||
properties_changed, port->properties);
|
||||
info_changed, &port->info);
|
||||
|
||||
spa_list_for_each(resource, &port->resource_list, link)
|
||||
pw_port_resource_info(resource, &port->info);
|
||||
|
||||
port->info.change_mask = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -268,6 +291,7 @@ static int do_add_port(struct spa_loop *loop,
|
|||
{
|
||||
struct pw_port *this = user_data;
|
||||
|
||||
this->rt.port.flags = this->spa_info->flags;
|
||||
spa_graph_port_add(&this->node->rt.node, &this->rt.port);
|
||||
spa_graph_node_add(this->rt.graph, &this->rt.mix_node);
|
||||
spa_graph_port_add(&this->rt.mix_node, &this->rt.mix_port);
|
||||
|
|
@ -276,7 +300,7 @@ static int do_add_port(struct spa_loop *loop,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int make_control(void *data, struct spa_pod *param)
|
||||
static int make_control(void *data, uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param)
|
||||
{
|
||||
struct pw_port *port = data;
|
||||
struct pw_node *node = port->node;
|
||||
|
|
@ -284,10 +308,72 @@ static int make_control(void *data, struct spa_pod *param)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void port_unbind_func(void *data)
|
||||
{
|
||||
struct pw_resource *resource = data;
|
||||
spa_list_remove(&resource->link);
|
||||
}
|
||||
|
||||
static const struct pw_resource_events resource_events = {
|
||||
PW_VERSION_RESOURCE_EVENTS,
|
||||
.destroy = port_unbind_func,
|
||||
};
|
||||
|
||||
static int reply_param(void *data, uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param)
|
||||
{
|
||||
struct pw_resource *resource = data;
|
||||
pw_port_resource_param(resource, id, index, next, param);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void port_enum_params(void *object, uint32_t id, uint32_t index, uint32_t num,
|
||||
const struct spa_pod *filter)
|
||||
{
|
||||
struct pw_resource *resource = object;
|
||||
struct resource_data *data = pw_resource_get_user_data(resource);
|
||||
struct pw_port *port = data->port;
|
||||
|
||||
pw_port_for_each_param(port, id, index, num, filter,
|
||||
reply_param, resource);
|
||||
}
|
||||
|
||||
static const struct pw_port_proxy_methods port_methods = {
|
||||
PW_VERSION_NODE_PROXY_METHODS,
|
||||
.enum_params = port_enum_params
|
||||
};
|
||||
|
||||
static void
|
||||
global_bind(void *_data, struct pw_client *client, uint32_t permissions,
|
||||
uint32_t version, uint32_t id)
|
||||
{
|
||||
struct pw_port *this = _data;
|
||||
struct pw_global *global = this->global;
|
||||
struct pw_resource *resource;
|
||||
struct resource_data *data;
|
||||
|
||||
resource = pw_resource_new(client, id, permissions, global->type, version, sizeof(*data));
|
||||
if (resource == NULL)
|
||||
goto no_mem;
|
||||
|
||||
data = pw_resource_get_user_data(resource);
|
||||
data->port = this;
|
||||
pw_resource_add_listener(resource, &data->resource_listener, &resource_events, resource);
|
||||
|
||||
pw_resource_set_implementation(resource, &port_methods, resource);
|
||||
|
||||
pw_log_debug("port %p: bound to %d", this, resource->id);
|
||||
|
||||
spa_list_append(&this->resource_list, &resource->link);
|
||||
|
||||
this->info.change_mask = ~0;
|
||||
pw_port_resource_info(resource, &this->info);
|
||||
this->info.change_mask = 0;
|
||||
return;
|
||||
|
||||
no_mem:
|
||||
pw_log_error("can't create port resource");
|
||||
pw_core_resource_error(client->core_resource,
|
||||
client->core_resource->id, -ENOMEM, "no memory");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -336,10 +422,10 @@ int pw_port_add(struct pw_port *port, struct pw_node *node)
|
|||
|
||||
spa_node_port_get_info(node->node,
|
||||
port->direction, port_id,
|
||||
&port->info);
|
||||
&port->spa_info);
|
||||
|
||||
if (port->info->props)
|
||||
pw_port_update_properties(port, port->info->props);
|
||||
if (port->spa_info->props)
|
||||
pw_port_update_properties(port, port->spa_info->props);
|
||||
|
||||
dir = port->direction == PW_DIRECTION_INPUT ? "in" : "out";
|
||||
|
||||
|
|
@ -348,12 +434,12 @@ int pw_port_add(struct pw_port *port, struct pw_node *node)
|
|||
}
|
||||
pw_properties_set(port->properties, "port.direction", dir);
|
||||
|
||||
if (SPA_FLAG_CHECK(port->info->flags, SPA_PORT_INFO_FLAG_PHYSICAL))
|
||||
if (SPA_FLAG_CHECK(port->spa_info->flags, SPA_PORT_INFO_FLAG_PHYSICAL))
|
||||
pw_properties_set(port->properties, "port.physical", "1");
|
||||
if (SPA_FLAG_CHECK(port->info->flags, SPA_PORT_INFO_FLAG_TERMINAL))
|
||||
if (SPA_FLAG_CHECK(port->spa_info->flags, SPA_PORT_INFO_FLAG_TERMINAL))
|
||||
pw_properties_set(port->properties, "port.terminal", "1");
|
||||
|
||||
pw_log_debug("port %p: add to node %p %08x", port, node, port->info->flags);
|
||||
pw_log_debug("port %p: add to node %p %08x", port, node, port->spa_info->flags);
|
||||
if (port->direction == PW_DIRECTION_INPUT) {
|
||||
spa_list_append(&node->input_ports, &port->link);
|
||||
pw_map_insert_at(&node->input_port_map, port_id, port);
|
||||
|
|
@ -367,8 +453,8 @@ int pw_port_add(struct pw_port *port, struct pw_node *node)
|
|||
node->info.change_mask |= PW_NODE_CHANGE_MASK_OUTPUT_PORTS;
|
||||
}
|
||||
|
||||
pw_port_for_each_param(port, t->param_io.idPropsOut, NULL, make_control, port);
|
||||
pw_port_for_each_param(port, t->param_io.idPropsIn, NULL, make_control, port);
|
||||
pw_port_for_each_param(port, t->param_io.idPropsOut, 0, 0, NULL, make_control, port);
|
||||
pw_port_for_each_param(port, t->param_io.idPropsIn, 0, 0, NULL, make_control, port);
|
||||
|
||||
pw_log_debug("port %p: setting node io", port);
|
||||
spa_node_port_set_io(node->node,
|
||||
|
|
@ -498,26 +584,33 @@ int pw_port_send_command(struct pw_port *port, bool block, const struct spa_comm
|
|||
|
||||
int pw_port_for_each_param(struct pw_port *port,
|
||||
uint32_t param_id,
|
||||
uint32_t index, uint32_t max,
|
||||
const struct spa_pod *filter,
|
||||
int (*callback) (void *data, struct spa_pod *param),
|
||||
int (*callback) (void *data,
|
||||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param),
|
||||
void *data)
|
||||
{
|
||||
int res;
|
||||
uint8_t buffer[4096];
|
||||
int res = 0;
|
||||
uint8_t buf[4096];
|
||||
struct spa_pod_builder b = { 0 };
|
||||
uint32_t state;
|
||||
uint32_t idx, count;
|
||||
struct pw_node *node = port->node;
|
||||
struct spa_pod *param;
|
||||
|
||||
for (state = 0;;) {
|
||||
spa_pod_builder_init(&b, buffer, sizeof(buffer));
|
||||
if ((res = spa_node_port_enum_params(port->node->node,
|
||||
port->direction,
|
||||
port->port_id,
|
||||
param_id, &state,
|
||||
if (max == 0)
|
||||
max = UINT32_MAX;
|
||||
|
||||
for (count = 0; count < max; count++) {
|
||||
spa_pod_builder_init(&b, buf, sizeof(buf));
|
||||
idx = index;
|
||||
if ((res = spa_node_port_enum_params(node->node,
|
||||
port->direction, port->port_id,
|
||||
param_id, &index,
|
||||
filter, ¶m, &b)) <= 0)
|
||||
break;
|
||||
|
||||
if ((res = callback(data, param)) != 0)
|
||||
if ((res = callback(data, param_id, idx, index, param)) != 0)
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
|
|
@ -528,33 +621,35 @@ struct param_filter {
|
|||
struct pw_port *out_port;
|
||||
uint32_t in_param_id;
|
||||
uint32_t out_param_id;
|
||||
int (*callback) (void *data, struct spa_pod *param);
|
||||
int (*callback) (void *data, uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param);
|
||||
void *data;
|
||||
uint32_t n_params;
|
||||
};
|
||||
|
||||
static int do_filter(void *data, struct spa_pod *param)
|
||||
static int do_filter(void *data, uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param)
|
||||
{
|
||||
struct param_filter *f = data;
|
||||
f->n_params++;
|
||||
return pw_port_for_each_param(f->out_port, f->out_param_id, param, f->callback, f->data);
|
||||
return pw_port_for_each_param(f->out_port, f->out_param_id, 0, 0, param, f->callback, f->data);
|
||||
}
|
||||
|
||||
int pw_port_for_each_filtered_param(struct pw_port *in_port,
|
||||
struct pw_port *out_port,
|
||||
uint32_t in_param_id,
|
||||
uint32_t out_param_id,
|
||||
int (*callback) (void *data, struct spa_pod *param),
|
||||
int (*callback) (void *data,
|
||||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param),
|
||||
void *data)
|
||||
{
|
||||
int res;
|
||||
struct param_filter filter = { in_port, out_port, in_param_id, out_param_id, callback, data, 0 };
|
||||
|
||||
if ((res = pw_port_for_each_param(in_port, in_param_id, NULL, do_filter, &filter)) < 0)
|
||||
if ((res = pw_port_for_each_param(in_port, in_param_id, 0, 0, NULL, do_filter, &filter)) < 0)
|
||||
return res;
|
||||
|
||||
if (filter.n_params == 0)
|
||||
res = do_filter(&filter, NULL);
|
||||
res = do_filter(&filter, 0, 0, 0, NULL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
@ -632,8 +727,8 @@ int pw_port_alloc_buffers(struct pw_port *port,
|
|||
return -EIO;
|
||||
|
||||
res = spa_node_port_alloc_buffers(node->node, port->direction, port->port_id,
|
||||
params, n_params,
|
||||
buffers, n_buffers);
|
||||
params, n_params,
|
||||
buffers, n_buffers);
|
||||
pw_log_debug("port %p: alloc %d buffers: %d (%s)", port, *n_buffers, res, spa_strerror(res));
|
||||
|
||||
if (port->allocated) {
|
||||
|
|
|
|||
|
|
@ -67,6 +67,9 @@ struct pw_port_events {
|
|||
/** The port is freed */
|
||||
void (*free) (void *data);
|
||||
|
||||
/** the port info changed */
|
||||
void (*info_changed) (void *data, struct pw_port_info *info);
|
||||
|
||||
/** a new link is added on this port */
|
||||
void (*link_added) (void *data, struct pw_link *link);
|
||||
|
||||
|
|
@ -76,9 +79,6 @@ struct pw_port_events {
|
|||
/** the state of the port changed */
|
||||
void (*state_changed) (void *data, enum pw_port_state state);
|
||||
|
||||
/** the properties of the port changed */
|
||||
void (*properties_changed) (void *data, const struct pw_properties *properties);
|
||||
|
||||
/** a control was added to the port */
|
||||
void (*control_added) (void *data, struct pw_control *control);
|
||||
|
||||
|
|
|
|||
|
|
@ -292,8 +292,12 @@ struct pw_port {
|
|||
|
||||
enum pw_direction direction; /**< port direction */
|
||||
uint32_t port_id; /**< port id */
|
||||
struct pw_properties *properties;
|
||||
const struct spa_port_info *info;
|
||||
const struct spa_port_info *spa_info;
|
||||
|
||||
struct pw_properties *properties; /**< properties of the port */
|
||||
struct pw_port_info info;
|
||||
|
||||
struct spa_list resource_list; /**< list of resources for this port */
|
||||
|
||||
enum pw_port_state state; /**< state of the port */
|
||||
|
||||
|
|
@ -498,15 +502,20 @@ void pw_port_destroy(struct pw_port *port);
|
|||
* The function returns 0 on success or the error returned by the callback. */
|
||||
int pw_port_for_each_param(struct pw_port *port,
|
||||
uint32_t param_id,
|
||||
uint32_t index, uint32_t max,
|
||||
const struct spa_pod *filter,
|
||||
int (*callback) (void *data, struct spa_pod *param),
|
||||
int (*callback) (void *data,
|
||||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param),
|
||||
void *data);
|
||||
|
||||
int pw_port_for_each_filtered_param(struct pw_port *in_port,
|
||||
struct pw_port *out_port,
|
||||
uint32_t in_param_id,
|
||||
uint32_t out_param_id,
|
||||
int (*callback) (void *data, struct spa_pod *param),
|
||||
int (*callback) (void *data,
|
||||
uint32_t id, uint32_t index, uint32_t next,
|
||||
struct spa_pod *param),
|
||||
void *data);
|
||||
|
||||
/** Set a param on a port \memberof pw_port */
|
||||
|
|
|
|||
|
|
@ -175,6 +175,8 @@ static bool do_create_node(struct data *data, const char *cmd, char *args, char
|
|||
static bool do_destroy(struct data *data, const char *cmd, char *args, char **error);
|
||||
static bool do_create_link(struct data *data, const char *cmd, char *args, char **error);
|
||||
static bool do_export_node(struct data *data, const char *cmd, char *args, char **error);
|
||||
static bool do_node_params(struct data *data, const char *cmd, char *args, char **error);
|
||||
static bool do_port_params(struct data *data, const char *cmd, char *args, char **error);
|
||||
|
||||
static struct command command_list[] = {
|
||||
{ "help", "Show this help", do_help },
|
||||
|
|
@ -190,6 +192,8 @@ static struct command command_list[] = {
|
|||
{ "destroy", "Destroy a global object. <object-id>", do_destroy },
|
||||
{ "create-link", "Create a link between nodes. <node-id> <port-id> <node-id> <port-id> [<properties>]", do_create_link },
|
||||
{ "export-node", "Export a local node to the current remote. <node-id> [remote-var]", do_export_node },
|
||||
{ "node-params", "Enumerate params of a node <node-id> [<param-id-name>]", do_node_params },
|
||||
{ "port-params", "Enumerate params of a port <port-id> [<param-id-name>]", do_port_params },
|
||||
};
|
||||
|
||||
static bool do_help(struct data *data, const char *cmd, char *args, char **error)
|
||||
|
|
@ -532,34 +536,31 @@ static void info_module(struct proxy_data *pd)
|
|||
static void info_node(struct proxy_data *pd)
|
||||
{
|
||||
struct pw_node_info *info = pd->info;
|
||||
struct pw_type *t = pd->rd->data->t;
|
||||
int i;
|
||||
|
||||
info_global(pd);
|
||||
fprintf(stdout, "%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
|
||||
fprintf(stdout, "%c\tinput ports: %u/%u\n", MARK_CHANGE(1), info->n_input_ports, info->max_input_ports);
|
||||
fprintf(stdout, "%c\tinput params:\n", MARK_CHANGE(2));
|
||||
for (i = 0; i < info->n_input_params; i++) {
|
||||
uint32_t flags = 0;
|
||||
if (spa_pod_is_object_type(info->input_params[i], t->spa_format))
|
||||
flags |= SPA_DEBUG_FLAG_FORMAT;
|
||||
spa_debug_pod(info->input_params[i], flags);
|
||||
}
|
||||
|
||||
fprintf(stdout, "%c\toutput ports: %u/%u\n", MARK_CHANGE(3), info->n_output_ports, info->max_output_ports);
|
||||
fprintf(stdout, "%c\toutput params:\n", MARK_CHANGE(4));
|
||||
for (i = 0; i < info->n_output_params; i++) {
|
||||
uint32_t flags = 0;
|
||||
if (spa_pod_is_object_type(info->output_params[i], t->spa_format))
|
||||
flags |= SPA_DEBUG_FLAG_FORMAT;
|
||||
spa_debug_pod(info->output_params[i], flags);
|
||||
}
|
||||
fprintf(stdout, "%c\tstate: \"%s\"", MARK_CHANGE(5), pw_node_state_as_string(info->state));
|
||||
fprintf(stdout, "%c\tinput ports: %u/%u\n", MARK_CHANGE(1),
|
||||
info->n_input_ports, info->max_input_ports);
|
||||
fprintf(stdout, "%c\toutput ports: %u/%u\n", MARK_CHANGE(2),
|
||||
info->n_output_ports, info->max_output_ports);
|
||||
fprintf(stdout, "%c\tstate: \"%s\"", MARK_CHANGE(3), pw_node_state_as_string(info->state));
|
||||
if (info->state == PW_NODE_STATE_ERROR && info->error)
|
||||
fprintf(stdout, " \"%s\"\n", info->error);
|
||||
else
|
||||
fprintf(stdout, "\n");
|
||||
print_properties(info->props, MARK_CHANGE(6), true);
|
||||
print_properties(info->props, MARK_CHANGE(4), true);
|
||||
fprintf(stdout, "%c\tenum_params\n", MARK_CHANGE(5));
|
||||
info->change_mask = 0;
|
||||
}
|
||||
|
||||
static void info_port(struct proxy_data *pd)
|
||||
{
|
||||
struct pw_port_info *info = pd->info;
|
||||
|
||||
info_global(pd);
|
||||
fprintf(stdout, "%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
|
||||
print_properties(info->props, MARK_CHANGE(1), true);
|
||||
fprintf(stdout, "%c\tenum_params\n", MARK_CHANGE(2));
|
||||
info->change_mask = 0;
|
||||
}
|
||||
|
||||
|
|
@ -659,9 +660,64 @@ static void node_event_info(void *object, struct pw_node_info *info)
|
|||
}
|
||||
}
|
||||
|
||||
static void node_event_param(void *object, uint32_t id, uint32_t index, uint32_t next,
|
||||
const struct spa_pod *param)
|
||||
{
|
||||
struct proxy_data *data = object;
|
||||
struct remote_data *rd = data->rd;
|
||||
struct pw_type *t = rd->data->t;
|
||||
uint32_t flags = 0;
|
||||
|
||||
fprintf(stdout, "remote %d node %d param %d index %d\n",
|
||||
rd->id, data->global->id, id, index);
|
||||
|
||||
if (spa_pod_is_object_type(param, t->spa_format))
|
||||
flags |= SPA_DEBUG_FLAG_FORMAT;
|
||||
spa_debug_pod(param, flags);
|
||||
}
|
||||
|
||||
static const struct pw_node_proxy_events node_events = {
|
||||
PW_VERSION_NODE_PROXY_EVENTS,
|
||||
.info = node_event_info
|
||||
.info = node_event_info,
|
||||
.param = node_event_param
|
||||
};
|
||||
|
||||
|
||||
static void port_event_info(void *object, struct pw_port_info *info)
|
||||
{
|
||||
struct proxy_data *pd = object;
|
||||
struct remote_data *rd = pd->rd;
|
||||
if (pd->info)
|
||||
fprintf(stdout, "remote %d port %d changed\n", rd->id, info->id);
|
||||
pd->info = pw_port_info_update(pd->info, info);
|
||||
if (pd->global == NULL)
|
||||
pd->global = pw_map_lookup(&rd->globals, info->id);
|
||||
if (pd->global && pd->global->info_pending) {
|
||||
info_port(pd);
|
||||
pd->global->info_pending = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void port_event_param(void *object, uint32_t id, uint32_t index, uint32_t next,
|
||||
const struct spa_pod *param)
|
||||
{
|
||||
struct proxy_data *data = object;
|
||||
struct remote_data *rd = data->rd;
|
||||
struct pw_type *t = rd->data->t;
|
||||
uint32_t flags = 0;
|
||||
|
||||
fprintf(stdout, "remote %d port %d param %d index %d\n",
|
||||
rd->id, data->global->id, id, index);
|
||||
|
||||
if (spa_pod_is_object_type(param, t->spa_format))
|
||||
flags |= SPA_DEBUG_FLAG_FORMAT;
|
||||
spa_debug_pod(param, flags);
|
||||
}
|
||||
|
||||
static const struct pw_port_proxy_events port_events = {
|
||||
PW_VERSION_PORT_PROXY_EVENTS,
|
||||
.info = port_event_info,
|
||||
.param = port_event_param
|
||||
};
|
||||
|
||||
static void factory_event_info(void *object, struct pw_factory_info *info)
|
||||
|
|
@ -780,6 +836,12 @@ static bool bind_global(struct remote_data *rd, struct global *global, char **er
|
|||
destroy = (pw_destroy_t) pw_node_info_free;
|
||||
info_func = info_node;
|
||||
}
|
||||
else if (global->type == t->port) {
|
||||
events = &port_events;
|
||||
client_version = PW_VERSION_PORT;
|
||||
destroy = (pw_destroy_t) pw_port_info_free;
|
||||
info_func = info_port;
|
||||
}
|
||||
else if (global->type == t->factory) {
|
||||
events = &factory_events;
|
||||
client_version = PW_VERSION_FACTORY;
|
||||
|
|
@ -1033,6 +1095,81 @@ static bool do_export_node(struct data *data, const char *cmd, char *args, char
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool do_node_params(struct data *data, const char *cmd, char *args, char **error)
|
||||
{
|
||||
struct pw_type *t = data->t;
|
||||
struct remote_data *rd = data->current;
|
||||
char *a[2];
|
||||
int n;
|
||||
uint32_t id, param_id;
|
||||
struct global *global;
|
||||
|
||||
n = pw_split_ip(args, WHITESPACE, 2, a);
|
||||
if (n < 1) {
|
||||
asprintf(error, "%s <object-id> [<param-id-name>]", cmd);
|
||||
return false;
|
||||
}
|
||||
if (n == 2)
|
||||
param_id = spa_type_map_get_id(t->map, a[1]);
|
||||
else
|
||||
param_id = t->param.idList;
|
||||
|
||||
id = atoi(a[0]);
|
||||
global = pw_map_lookup(&rd->globals, id);
|
||||
if (global == NULL) {
|
||||
asprintf(error, "%s: unknown global %d", cmd, id);
|
||||
return false;
|
||||
}
|
||||
if (global->type != t->node) {
|
||||
asprintf(error, "object %d is not a node", atoi(a[0]));
|
||||
return false;
|
||||
}
|
||||
pw_node_proxy_enum_params((struct pw_node_proxy*)global->proxy,
|
||||
param_id, 0, 0, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool do_port_params(struct data *data, const char *cmd, char *args, char **error)
|
||||
{
|
||||
struct pw_type *t = data->t;
|
||||
struct remote_data *rd = data->current;
|
||||
char *a[2];
|
||||
int n;
|
||||
uint32_t id, param_id;
|
||||
struct global *global;
|
||||
|
||||
n = pw_split_ip(args, WHITESPACE, 2, a);
|
||||
if (n < 1) {
|
||||
asprintf(error, "%s <object-id> [<param-id-name>]", cmd);
|
||||
return false;
|
||||
}
|
||||
if (n == 2)
|
||||
param_id = spa_type_map_get_id(t->map, a[1]);
|
||||
else
|
||||
param_id = t->param.idList;
|
||||
|
||||
id = atoi(a[0]);
|
||||
global = pw_map_lookup(&rd->globals, id);
|
||||
if (global == NULL) {
|
||||
asprintf(error, "%s: unknown global %d", cmd, id);
|
||||
return false;
|
||||
}
|
||||
if (global->type != t->port) {
|
||||
asprintf(error, "object %d is not a port", atoi(a[0]));
|
||||
return false;
|
||||
}
|
||||
if (global->proxy == NULL) {
|
||||
if (!bind_global(rd, global, error))
|
||||
return false;
|
||||
}
|
||||
|
||||
pw_port_proxy_enum_params((struct pw_port_proxy*)global->proxy,
|
||||
param_id, 0, 0, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool parse(struct data *data, char *buf, size_t size, char **error)
|
||||
{
|
||||
char *a[2];
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@
|
|||
#include <pipewire/interfaces.h>
|
||||
#include <pipewire/type.h>
|
||||
|
||||
struct proxy_data;
|
||||
|
||||
typedef void (*print_func_t) (struct proxy_data *data);
|
||||
|
||||
struct data {
|
||||
struct pw_main_loop *loop;
|
||||
struct pw_core *core;
|
||||
|
|
@ -37,10 +41,14 @@ struct data {
|
|||
|
||||
struct pw_registry_proxy *registry_proxy;
|
||||
struct spa_hook registry_listener;
|
||||
|
||||
uint32_t seq;
|
||||
struct spa_list pending_list;
|
||||
};
|
||||
|
||||
struct proxy_data {
|
||||
struct data *data;
|
||||
bool first;
|
||||
struct pw_proxy *proxy;
|
||||
uint32_t id;
|
||||
uint32_t parent_id;
|
||||
|
|
@ -51,8 +59,56 @@ struct proxy_data {
|
|||
pw_destroy_t destroy;
|
||||
struct spa_hook proxy_listener;
|
||||
struct spa_hook proxy_proxy_listener;
|
||||
uint32_t pending_seq;
|
||||
struct spa_list pending_link;
|
||||
print_func_t print_func;
|
||||
uint32_t n_params;
|
||||
struct spa_pod **params;
|
||||
};
|
||||
|
||||
static void add_pending(struct proxy_data *pd)
|
||||
{
|
||||
struct data *d = pd->data;
|
||||
|
||||
spa_list_append(&d->pending_list, &pd->pending_link);
|
||||
pd->pending_seq = ++d->seq;
|
||||
pw_core_proxy_sync(d->core_proxy, pd->pending_seq);
|
||||
}
|
||||
|
||||
static void on_sync_reply(void *data, uint32_t seq)
|
||||
{
|
||||
struct data *d = data;
|
||||
struct proxy_data *pd;
|
||||
|
||||
spa_list_for_each(pd, &d->pending_list, pending_link) {
|
||||
if (pd->pending_seq == seq) {
|
||||
spa_list_remove(&pd->pending_link);
|
||||
pd->pending_seq = SPA_ID_INVALID;
|
||||
pd->print_func(pd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void clear_params(struct proxy_data *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < data->n_params; i++)
|
||||
free(data->params[i]);
|
||||
free(data->params);
|
||||
|
||||
data->n_params = 0;
|
||||
data->params = NULL;
|
||||
}
|
||||
|
||||
static void add_param(struct proxy_data *data, const struct spa_pod *param)
|
||||
{
|
||||
uint32_t idx = data->n_params++;
|
||||
|
||||
data->params = realloc(data->params, sizeof(struct spa_pod *) * data->n_params);
|
||||
data->params[idx] = pw_spa_pod_copy(param);
|
||||
}
|
||||
|
||||
static void print_properties(const struct spa_dict *props, char mark)
|
||||
{
|
||||
const struct spa_dict_item *item;
|
||||
|
|
@ -124,24 +180,23 @@ static const struct pw_module_proxy_events module_events = {
|
|||
.info = module_event_info,
|
||||
};
|
||||
|
||||
static void node_event_info(void *object, struct pw_node_info *info)
|
||||
static void print_node(struct proxy_data *data)
|
||||
{
|
||||
struct proxy_data *data = object;
|
||||
struct pw_node_info *info = data->info;
|
||||
bool print_all, print_mark;
|
||||
struct pw_type *t = pw_core_get_type(data->data->core);
|
||||
|
||||
print_all = true;
|
||||
if (data->info == NULL) {
|
||||
if (data->first) {
|
||||
printf("added:\n");
|
||||
print_mark = false;
|
||||
data->first = false;
|
||||
}
|
||||
else {
|
||||
printf("changed:\n");
|
||||
print_mark = true;
|
||||
}
|
||||
|
||||
info = data->info = pw_node_info_update(data->info, info);
|
||||
|
||||
printf("\tid: %d\n", data->id);
|
||||
printf("\tparent_id: %d\n", data->parent_id);
|
||||
printf("\tpermissions: %c%c%c\n", data->permissions & PW_PERM_R ? 'r' : '-',
|
||||
|
|
@ -152,36 +207,122 @@ static void node_event_info(void *object, struct pw_node_info *info)
|
|||
int i;
|
||||
|
||||
printf("%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
|
||||
printf("%c\tinput ports: %u/%u\n", MARK_CHANGE(1), info->n_input_ports, info->max_input_ports);
|
||||
printf("%c\tinput params:\n", MARK_CHANGE(2));
|
||||
for (i = 0; i < info->n_input_params; i++) {
|
||||
printf("%c\tparams:\n", MARK_CHANGE(5));
|
||||
for (i = 0; i < data->n_params; i++) {
|
||||
uint32_t flags = 0;
|
||||
if (spa_pod_is_object_type(info->input_params[i], t->spa_format))
|
||||
if (spa_pod_is_object_type(data->params[i], t->spa_format))
|
||||
flags |= SPA_DEBUG_FLAG_FORMAT;
|
||||
spa_debug_pod(info->input_params[i], flags);
|
||||
spa_debug_pod(data->params[i], flags);
|
||||
}
|
||||
|
||||
printf("%c\toutput ports: %u/%u\n", MARK_CHANGE(3), info->n_output_ports, info->max_output_ports);
|
||||
printf("%c\toutput params:\n", MARK_CHANGE(4));
|
||||
for (i = 0; i < info->n_output_params; i++) {
|
||||
uint32_t flags = 0;
|
||||
if (spa_pod_is_object_type(info->output_params[i], t->spa_format))
|
||||
flags |= SPA_DEBUG_FLAG_FORMAT;
|
||||
spa_debug_pod(info->output_params[i], flags);
|
||||
}
|
||||
|
||||
printf("%c\tstate: \"%s\"", MARK_CHANGE(5), pw_node_state_as_string(info->state));
|
||||
printf("%c\tinput ports: %u/%u\n", MARK_CHANGE(1),
|
||||
info->n_input_ports, info->max_input_ports);
|
||||
printf("%c\toutput ports: %u/%u\n", MARK_CHANGE(2),
|
||||
info->n_output_ports, info->max_output_ports);
|
||||
printf("%c\tstate: \"%s\"", MARK_CHANGE(3), pw_node_state_as_string(info->state));
|
||||
if (info->state == PW_NODE_STATE_ERROR && info->error)
|
||||
printf(" \"%s\"\n", info->error);
|
||||
else
|
||||
printf("\n");
|
||||
print_properties(info->props, MARK_CHANGE(6));
|
||||
print_properties(info->props, MARK_CHANGE(4));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void node_event_info(void *object, struct pw_node_info *info)
|
||||
{
|
||||
struct proxy_data *data = object;
|
||||
struct pw_type *t = pw_core_get_type(data->data->core);
|
||||
|
||||
data->info = pw_node_info_update(data->info, info);
|
||||
|
||||
if (info->change_mask & PW_NODE_CHANGE_MASK_ENUM_PARAMS) {
|
||||
pw_node_proxy_enum_params((struct pw_node_proxy*)data->proxy,
|
||||
t->param.idList, 0, 0, NULL);
|
||||
add_pending(data);
|
||||
}
|
||||
if (data->pending_seq == SPA_ID_INVALID)
|
||||
data->print_func(data);
|
||||
}
|
||||
|
||||
static void node_event_param(void *object, uint32_t id, uint32_t index, uint32_t next,
|
||||
const struct spa_pod *param)
|
||||
{
|
||||
struct proxy_data *data = object;
|
||||
add_param(data, param);
|
||||
}
|
||||
|
||||
static const struct pw_node_proxy_events node_events = {
|
||||
PW_VERSION_NODE_PROXY_EVENTS,
|
||||
.info = node_event_info
|
||||
.info = node_event_info,
|
||||
.param = node_event_param
|
||||
};
|
||||
|
||||
static void print_port(struct proxy_data *data)
|
||||
{
|
||||
struct pw_port_info *info = data->info;
|
||||
bool print_all, print_mark;
|
||||
struct pw_type *t = pw_core_get_type(data->data->core);
|
||||
|
||||
print_all = true;
|
||||
if (data->first) {
|
||||
printf("added:\n");
|
||||
print_mark = false;
|
||||
data->first = false;
|
||||
}
|
||||
else {
|
||||
printf("changed:\n");
|
||||
print_mark = true;
|
||||
}
|
||||
|
||||
printf("\tid: %d\n", data->id);
|
||||
printf("\tparent_id: %d\n", data->parent_id);
|
||||
printf("\tpermissions: %c%c%c\n", data->permissions & PW_PERM_R ? 'r' : '-',
|
||||
data->permissions & PW_PERM_W ? 'w' : '-',
|
||||
data->permissions & PW_PERM_X ? 'x' : '-');
|
||||
printf("\ttype: %s (version %d)\n", PW_TYPE_INTERFACE__Port, data->version);
|
||||
if (print_all) {
|
||||
int i;
|
||||
printf("%c\tname: \"%s\"\n", MARK_CHANGE(0), info->name);
|
||||
printf("%c\tparams:\n", MARK_CHANGE(2));
|
||||
for (i = 0; i < data->n_params; i++) {
|
||||
uint32_t flags = 0;
|
||||
if (spa_pod_is_object_type(data->params[i], t->spa_format))
|
||||
flags |= SPA_DEBUG_FLAG_FORMAT;
|
||||
spa_debug_pod(data->params[i], flags);
|
||||
}
|
||||
print_properties(info->props, MARK_CHANGE(1));
|
||||
}
|
||||
}
|
||||
|
||||
static void port_event_info(void *object, struct pw_port_info *info)
|
||||
{
|
||||
|
||||
struct proxy_data *data = object;
|
||||
struct pw_type *t = pw_core_get_type(data->data->core);
|
||||
|
||||
data->info = pw_port_info_update(data->info, info);
|
||||
|
||||
if (info->change_mask & PW_PORT_CHANGE_MASK_ENUM_PARAMS) {
|
||||
pw_port_proxy_enum_params((struct pw_port_proxy*)data->proxy,
|
||||
t->param.idEnumFormat, 0, 0, NULL);
|
||||
add_pending(data);
|
||||
}
|
||||
if (data->pending_seq == SPA_ID_INVALID)
|
||||
data->print_func(data);
|
||||
}
|
||||
|
||||
static void port_event_param(void *object, uint32_t id, uint32_t index, uint32_t next,
|
||||
const struct spa_pod *param)
|
||||
{
|
||||
struct proxy_data *data = object;
|
||||
add_param(data, param);
|
||||
}
|
||||
|
||||
static const struct pw_port_proxy_events port_events = {
|
||||
PW_VERSION_PORT_PROXY_EVENTS,
|
||||
.info = port_event_info,
|
||||
.param = port_event_param
|
||||
};
|
||||
|
||||
static void factory_event_info(void *object, struct pw_factory_info *info)
|
||||
|
|
@ -300,6 +441,8 @@ destroy_proxy (void *data)
|
|||
{
|
||||
struct proxy_data *user_data = data;
|
||||
|
||||
clear_params(user_data);
|
||||
|
||||
if (user_data->info == NULL)
|
||||
return;
|
||||
|
||||
|
|
@ -325,11 +468,19 @@ static void registry_event_global(void *data, uint32_t id, uint32_t parent_id,
|
|||
struct pw_type *t = pw_core_get_type(core);
|
||||
struct proxy_data *pd;
|
||||
pw_destroy_t destroy;
|
||||
print_func_t print_func = NULL;
|
||||
|
||||
if (type == t->node) {
|
||||
events = &node_events;
|
||||
client_version = PW_VERSION_NODE;
|
||||
destroy = (pw_destroy_t) pw_node_info_free;
|
||||
print_func = print_node;
|
||||
}
|
||||
else if (type == t->port) {
|
||||
events = &port_events;
|
||||
client_version = PW_VERSION_PORT;
|
||||
destroy = (pw_destroy_t) pw_port_info_free;
|
||||
print_func = print_port;
|
||||
}
|
||||
else if (type == t->module) {
|
||||
events = &module_events;
|
||||
|
|
@ -371,12 +522,15 @@ static void registry_event_global(void *data, uint32_t id, uint32_t parent_id,
|
|||
|
||||
pd = pw_proxy_get_user_data(proxy);
|
||||
pd->data = d;
|
||||
pd->first = true;
|
||||
pd->proxy = proxy;
|
||||
pd->id = id;
|
||||
pd->parent_id = parent_id;
|
||||
pd->permissions = permissions;
|
||||
pd->version = version;
|
||||
pd->destroy = destroy;
|
||||
pd->pending_seq = SPA_ID_INVALID;
|
||||
pd->print_func = print_func;
|
||||
pw_proxy_add_proxy_listener(proxy, &pd->proxy_proxy_listener, events, pd);
|
||||
pw_proxy_add_listener(proxy, &pd->proxy_listener, &proxy_events, pd);
|
||||
|
||||
|
|
@ -433,6 +587,7 @@ static const struct pw_remote_events remote_events = {
|
|||
PW_VERSION_REMOTE_EVENTS,
|
||||
.info_changed = on_info_changed,
|
||||
.state_changed = on_state_changed,
|
||||
.sync_reply = on_sync_reply,
|
||||
};
|
||||
|
||||
static void do_quit(void *data, int signal_number)
|
||||
|
|
@ -472,6 +627,9 @@ int main(int argc, char *argv[])
|
|||
if (pw_remote_connect(data.remote) < 0)
|
||||
return -1;
|
||||
|
||||
data.seq = 1;
|
||||
spa_list_init(&data.pending_list);
|
||||
|
||||
pw_main_loop_run(data.loop);
|
||||
|
||||
pw_remote_destroy(data.remote);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue