factory: add introspection

This commit is contained in:
Wim Taymans 2017-09-18 09:35:00 +02:00
parent 7f20e04803
commit 67d4dd8656
10 changed files with 220 additions and 22 deletions

View file

@ -92,7 +92,7 @@ core_marshal_create_object(void *object,
struct spa_pod_frame f;
uint32_t i, n_items;
b = pw_protocol_native_begin_proxy(proxy, PW_CORE_PROXY_METHOD_CREATE_NODE);
b = pw_protocol_native_begin_proxy(proxy, PW_CORE_PROXY_METHOD_CREATE_OBJECT);
n_items = props ? props->n_items : 0;
@ -630,6 +630,66 @@ static bool module_demarshal_info(void *object, void *data, size_t size)
return true;
}
static void factory_marshal_info(void *object, struct pw_factory_info *info)
{
struct pw_resource *resource = object;
struct spa_pod_builder *b;
struct spa_pod_frame f;
uint32_t i, n_items;
b = pw_protocol_native_begin_resource(resource, PW_FACTORY_PROXY_EVENT_INFO);
n_items = info->props ? info->props->n_items : 0;
spa_pod_builder_add(b,
SPA_POD_TYPE_STRUCT, &f,
SPA_POD_TYPE_INT, info->id,
SPA_POD_TYPE_LONG, info->change_mask,
SPA_POD_TYPE_STRING, info->name,
SPA_POD_TYPE_ID, info->type,
SPA_POD_TYPE_INT, info->version,
SPA_POD_TYPE_INT, n_items, 0);
for (i = 0; i < n_items; i++) {
spa_pod_builder_add(b,
SPA_POD_TYPE_STRING, info->props->items[i].key,
SPA_POD_TYPE_STRING, info->props->items[i].value, 0);
}
spa_pod_builder_add(b, -SPA_POD_TYPE_STRUCT, &f, 0);
pw_protocol_native_end_resource(resource, b);
}
static bool factory_demarshal_info(void *object, void *data, size_t size)
{
struct pw_proxy *proxy = object;
struct spa_pod_iter it;
struct spa_dict props;
struct pw_factory_info info;
int i;
if (!spa_pod_iter_struct(&it, data, size) ||
!spa_pod_iter_get(&it,
SPA_POD_TYPE_INT, &info.id,
SPA_POD_TYPE_LONG, &info.change_mask,
SPA_POD_TYPE_STRING, &info.name,
SPA_POD_TYPE_ID, &info.type,
SPA_POD_TYPE_INT, &info.version,
SPA_POD_TYPE_INT, &props.n_items, 0))
return false;
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_iter_get(&it,
SPA_POD_TYPE_STRING, &props.items[i].key,
SPA_POD_TYPE_STRING, &props.items[i].value, 0))
return false;
}
pw_proxy_notify(proxy, struct pw_factory_proxy_events, info, &info);
return true;
}
static void node_marshal_info(void *object, struct pw_node_info *info)
{
struct pw_resource *resource = object;
@ -992,6 +1052,24 @@ const struct pw_protocol_marshal pw_protocol_native_module_marshal = {
pw_protocol_native_module_event_demarshal,
};
static const struct pw_factory_proxy_events pw_protocol_native_factory_event_marshal = {
PW_VERSION_FACTORY_PROXY_EVENTS,
&factory_marshal_info,
};
static const struct pw_protocol_native_demarshal pw_protocol_native_factory_event_demarshal[] = {
{ &factory_demarshal_info, PW_PROTOCOL_NATIVE_REMAP, },
};
const struct pw_protocol_marshal pw_protocol_native_factory_marshal = {
PW_TYPE_INTERFACE__Factory,
PW_VERSION_FACTORY,
0, NULL, NULL,
PW_FACTORY_PROXY_EVENT_NUM,
&pw_protocol_native_factory_event_marshal,
pw_protocol_native_factory_event_demarshal,
};
static const struct pw_node_proxy_events pw_protocol_native_node_event_marshal = {
PW_VERSION_NODE_PROXY_EVENTS,
&node_marshal_info,
@ -1052,6 +1130,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_factory_marshal);
pw_protocol_add_marshal(protocol, &pw_protocol_native_client_marshal);
pw_protocol_add_marshal(protocol, &pw_protocol_native_link_marshal);
}

View file

@ -63,7 +63,7 @@ static void *create_object(void *_data,
node = pw_spa_node_load(data->core,
NULL,
NULL,
pw_factory_get_global(data->this),
lib,
factory_name,
name,

View file

@ -181,10 +181,10 @@ core_create_object(void *object,
if (factory == NULL)
goto no_factory;
if (factory->type != type)
if (factory->info.type != type)
goto wrong_type;
if (factory->version < version)
if (factory->info.version < version)
goto wrong_version;
if (props) {
@ -795,7 +795,7 @@ struct pw_factory *pw_core_find_factory(struct pw_core *core, const char *name)
struct pw_factory *factory;
spa_list_for_each(factory, &core->factory_list, link) {
if (strcmp(factory->name, name) == 0)
if (strcmp(factory->info.name, name) == 0)
return factory;
}
return NULL;

View file

@ -36,12 +36,14 @@ struct pw_factory *pw_factory_new(struct pw_core *core,
this = calloc(1, sizeof(*this) + user_data_size);
this->core = core;
this->name = strdup(name);
this->type = type;
this->version = version;
this->properties = properties;
spa_list_init(&this->resource_list);
this->info.name = strdup(name);
this->info.type = type;
this->info.version = version;
this->info.props = properties ? &properties->dict : NULL;
if (user_data_size > 0)
this->user_data = SPA_MEMBER(this, sizeof(*this), void);
@ -58,8 +60,10 @@ void pw_factory_destroy(struct pw_factory *factory)
spa_list_remove(&factory->link);
pw_global_destroy(factory->global);
}
if (factory->name)
free((char *)factory->name);
if (factory->info.name)
free((char *)factory->info.name);
if (factory->properties)
pw_properties_free(factory->properties);
free(factory);
}
@ -123,6 +127,11 @@ void *pw_factory_get_user_data(struct pw_factory *factory)
return factory->user_data;
}
struct pw_global *pw_factory_get_global(struct pw_factory *factory)
{
return factory->global;
}
void pw_factory_set_implementation(struct pw_factory *factory,
const struct pw_factory_implementation *implementation,
void *data)

View file

@ -69,6 +69,9 @@ void pw_factory_destroy(struct pw_factory *factory);
void *pw_factory_get_user_data(struct pw_factory *factory);
/** Get the global of this factory */
struct pw_global *pw_factory_get_global(struct pw_factory *factory);
void pw_factory_set_implementation(struct pw_factory *factory,
const struct pw_factory_implementation *implementation,
void *data);

View file

@ -72,7 +72,7 @@ struct pw_link_proxy;
#define PW_CORE_PROXY_METHOD_SYNC 1
#define PW_CORE_PROXY_METHOD_GET_REGISTRY 2
#define PW_CORE_PROXY_METHOD_CLIENT_UPDATE 3
#define PW_CORE_PROXY_METHOD_CREATE_NODE 4
#define PW_CORE_PROXY_METHOD_CREATE_OBJECT 4
#define PW_CORE_PROXY_METHOD_CREATE_LINK 5
#define PW_CORE_PROXY_METHOD_NUM 6

View file

@ -273,6 +273,42 @@ void pw_node_info_free(struct pw_node_info *info)
free(info);
}
struct pw_factory_info *pw_factory_info_update(struct pw_factory_info *info,
const struct pw_factory_info *update)
{
if (update == NULL)
return info;
if (info == NULL) {
info = calloc(1, sizeof(struct pw_factory_info));
if (info == NULL)
return NULL;
}
info->id = update->id;
if (info->name)
free((void *) info->name);
info->name = update->name ? strdup(update->name) : NULL;
info->type = update->type;
info->version = update->version;
info->change_mask = update->change_mask;
if (update->change_mask & PW_FACTORY_CHANGE_MASK_PROPS) {
if (info->props)
pw_spa_dict_destroy(info->props);
info->props = pw_spa_dict_copy(update->props);
}
return info;
}
void pw_factory_info_free(struct pw_factory_info *info)
{
if (info->name)
free((void *) info->name);
if (info->props)
pw_spa_dict_destroy(info->props);
free(info);
}
struct pw_module_info *pw_module_info_update(struct pw_module_info *info,
const struct pw_module_info *update)
{

View file

@ -374,9 +374,6 @@ struct pw_factory {
struct pw_global *global; /**< global for this factory */
struct pw_factory_info info; /**< introspectable factory info */
const char *name; /**< the factory name */
uint32_t type; /**< the type produced by the factory*/
uint32_t version; /**< the version of the produced object */
struct pw_properties *properties; /**< properties of the factory */
const struct pw_factory_implementation *implementation;

View file

@ -543,6 +543,17 @@ static void info_node(struct proxy_data *pd)
print_properties(info->props, MARK_CHANGE(6));
}
static void info_factory(struct proxy_data *pd)
{
struct pw_factory_info *info = pd->info;
struct pw_type *t = pd->rd->data->t;
info_global(pd);
fprintf(stdout, "\tname: \"%s\"\n", info->name);
fprintf(stdout, "\tobject-type: %s/%d\n", spa_type_map_get_type(t->map, info->type), info->version);
print_properties(info->props, MARK_CHANGE(0));
}
static void info_client(struct proxy_data *pd)
{
struct pw_client_info *info = pd->info;
@ -624,6 +635,24 @@ static const struct pw_node_proxy_events node_events = {
.info = node_event_info
};
static void factory_event_info(void *object, struct pw_factory_info *info)
{
struct proxy_data *pd = object;
struct remote_data *rd = pd->rd;
pd->info = pw_factory_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_factory(pd);
pd->global->info_pending = false;
}
}
static const struct pw_factory_proxy_events factory_events = {
PW_VERSION_FACTORY_PROXY_EVENTS,
.info = factory_event_info
};
static void client_event_info(void *object, struct pw_client_info *info)
{
struct proxy_data *pd = object;
@ -716,6 +745,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->factory) {
events = &factory_events;
client_version = PW_VERSION_FACTORY;
destroy = (pw_destroy_t) pw_factory_info_free;
info_func = info_factory;
}
else if (global->type == t->client) {
events = &client_events;
client_version = PW_VERSION_CLIENT;

View file

@ -40,6 +40,7 @@ struct data {
};
struct proxy_data {
struct data *data;
struct pw_proxy *proxy;
uint32_t id;
uint32_t parent_id;
@ -86,8 +87,7 @@ static void on_info_changed(void *data, const struct pw_core_info *info)
static void module_event_info(void *object, struct pw_module_info *info)
{
struct pw_proxy *proxy = object;
struct proxy_data *data = pw_proxy_get_user_data(proxy);
struct proxy_data *data = object;
bool print_all, print_mark;
print_all = true;
@ -123,8 +123,7 @@ static const struct pw_module_proxy_events module_events = {
static void node_event_info(void *object, struct pw_node_info *info)
{
struct pw_proxy *proxy = object;
struct proxy_data *data = pw_proxy_get_user_data(proxy);
struct proxy_data *data = object;
bool print_all, print_mark;
print_all = true;
@ -173,10 +172,45 @@ static const struct pw_node_proxy_events node_events = {
.info = node_event_info
};
static void factory_event_info(void *object, struct pw_factory_info *info)
{
struct proxy_data *data = object;
struct pw_type *t = pw_core_get_type(data->data->core);
bool print_all, print_mark;
print_all = true;
if (data->info == NULL) {
printf("added:\n");
print_mark = false;
}
else {
printf("changed:\n");
print_mark = true;
}
info = data->info = pw_factory_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' : '-',
data->permissions & PW_PERM_W ? 'w' : '-',
data->permissions & PW_PERM_X ? 'x' : '-');
printf("\ttype: %s (version %d)\n", PW_TYPE_INTERFACE__Factory, data->version);
printf("\tname: \"%s\"\n", info->name);
printf("\tobject-type: %s/%d\n", spa_type_map_get_type(t->map, info->type), info->version);
if (print_all) {
print_properties(info->props, MARK_CHANGE(0));
}
}
static const struct pw_factory_proxy_events factory_events = {
PW_VERSION_FACTORY_PROXY_EVENTS,
.info = factory_event_info
};
static void client_event_info(void *object, struct pw_client_info *info)
{
struct pw_proxy *proxy = object;
struct proxy_data *data = pw_proxy_get_user_data(proxy);
struct proxy_data *data = object;
bool print_all, print_mark;
print_all = true;
@ -209,8 +243,7 @@ static const struct pw_client_proxy_events client_events = {
static void link_event_info(void *object, struct pw_link_info *info)
{
struct pw_proxy *proxy = object;
struct proxy_data *data = pw_proxy_get_user_data(proxy);
struct proxy_data *data = object;
bool print_all, print_mark;
print_all = true;
@ -290,6 +323,11 @@ static void registry_event_global(void *data, uint32_t id, uint32_t parent_id,
client_version = PW_VERSION_MODULE;
destroy = (pw_destroy_t) pw_module_info_free;
}
else if (type == t->factory) {
events = &factory_events;
client_version = PW_VERSION_FACTORY;
destroy = (pw_destroy_t) pw_factory_info_free;
}
else if (type == t->client) {
events = &client_events;
client_version = PW_VERSION_CLIENT;
@ -318,6 +356,7 @@ static void registry_event_global(void *data, uint32_t id, uint32_t parent_id,
goto no_mem;
pd = pw_proxy_get_user_data(proxy);
pd->data = d;
pd->proxy = proxy;
pd->id = id;
pd->parent_id = parent_id;