pulse-server: add more introspection

Add default nodes support and subscription events when it changes.
Fix stream id.
Fix node lookup.
Fix node volume.
This commit is contained in:
Wim Taymans 2020-10-26 13:28:45 +01:00
parent f75acc31d3
commit a372e4e90e
4 changed files with 552 additions and 224 deletions

View file

@ -23,24 +23,22 @@
*/
#include "manager.h"
#include <extensions/metadata.h>
#define manager_emit_sync(m) spa_hook_list_call(&m->hooks, struct pw_manager_events, sync, 0)
#define manager_emit_added(m,o) spa_hook_list_call(&m->hooks, struct pw_manager_events, added, 0, o)
#define manager_emit_updated(m,o) spa_hook_list_call(&m->hooks, struct pw_manager_events, updated, 0, o)
#define manager_emit_removed(m,o) spa_hook_list_call(&m->hooks, struct pw_manager_events, removed, 0, o)
#define manager_emit_metadata(m,s,k,t,v) spa_hook_list_call(&m->hooks, struct pw_manager_events, metadata,0,s,k,t,v)
struct manager {
struct pw_core *core;
struct pw_manager this;
struct spa_hook core_listener;
struct spa_hook registry_listener;
int sync_seq;
struct pw_registry *registry;
struct spa_hook registry_listener;
struct spa_hook_list hooks;
uint32_t n_objects;
struct spa_list object_list;
};
struct object_info {
@ -54,7 +52,6 @@ struct object {
struct pw_manager_object this;
struct manager *manager;
struct spa_list link;
const struct object_info *info;
@ -66,13 +63,13 @@ struct object {
static void core_sync(struct manager *m)
{
m->sync_seq = pw_core_sync(m->core, PW_ID_CORE, m->sync_seq);
m->sync_seq = pw_core_sync(m->this.core, PW_ID_CORE, m->sync_seq);
}
static struct object *find_object(struct manager *m, uint32_t id)
{
struct object *o;
spa_list_for_each(o, &m->object_list, link) {
spa_list_for_each(o, &m->this.object_list, this.link) {
if (o->this.id == id)
return o;
}
@ -87,8 +84,8 @@ static void object_destroy(struct object *o)
free(o->this.type);
if (o->this.props)
pw_properties_free(o->this.props);
spa_list_remove(&o->link);
m->n_objects--;
spa_list_remove(&o->this.link);
m->this.n_objects--;
free(o);
}
@ -112,7 +109,7 @@ static void client_destroy(void *data)
pw_client_info_free(o->this.info);
}
struct object_info client_info = {
static const struct object_info client_info = {
.type = PW_TYPE_INTERFACE_Client,
.version = PW_VERSION_CLIENT,
.events = &client_events,
@ -139,7 +136,7 @@ static void module_destroy(void *data)
pw_module_info_free(o->this.info);
}
struct object_info module_info = {
static const struct object_info module_info = {
.type = PW_TYPE_INTERFACE_Module,
.version = PW_VERSION_MODULE,
.events = &module_events,
@ -166,7 +163,7 @@ static void device_destroy(void *data)
pw_device_info_free(o->this.info);
}
struct object_info device_info = {
static const struct object_info device_info = {
.type = PW_TYPE_INTERFACE_Device,
.version = PW_VERSION_DEVICE,
.events = &device_events,
@ -176,9 +173,9 @@ struct object_info device_info = {
/* node */
static void node_event_info(void *object, const struct pw_node_info *info)
{
struct object *o = object;
pw_log_debug("object %p: id:%d change-mask:%"PRIu64, o, o->this.id, info->change_mask);
info = o->this.info = pw_node_info_update(o->this.info, info);
struct object *o = object;
pw_log_debug("object %p: id:%d change-mask:%"PRIu64, o, o->this.id, info->change_mask);
info = o->this.info = pw_node_info_update(o->this.info, info);
}
static const struct pw_node_events node_events = {
@ -193,19 +190,51 @@ static void node_destroy(void *data)
pw_node_info_free(o->this.info);
}
struct object_info node_info = {
static const struct object_info node_info = {
.type = PW_TYPE_INTERFACE_Node,
.version = PW_VERSION_NODE,
.events = &node_events,
.destroy = node_destroy,
};
/* link */
static const struct object_info link_info = {
.type = PW_TYPE_INTERFACE_Link,
.version = PW_VERSION_LINK,
};
/* metadata */
static int metadata_property(void *object,
uint32_t subject,
const char *key,
const char *type,
const char *value)
{
struct object *o = object;
struct manager *m = o->manager;
manager_emit_metadata(m, subject, key, type, value);
return 0;
}
static const struct pw_metadata_events metadata_events = {
PW_VERSION_METADATA_EVENTS,
.property = metadata_property,
};
static const struct object_info metadata_info = {
.type = PW_TYPE_INTERFACE_Metadata,
.version = PW_VERSION_METADATA,
.events = &metadata_events,
};
static const struct object_info *objects[] =
{
&module_info,
&client_info,
&device_info,
&node_info,
&link_info,
&metadata_info,
};
static const struct object_info *find_info(const char *type, uint32_t version)
@ -273,7 +302,7 @@ static void registry_event_global(void *data, uint32_t id,
if (info == NULL)
return;
proxy = pw_registry_bind(m->registry,
proxy = pw_registry_bind(m->this.registry,
id, type, info->version, 0);
if (proxy == NULL)
return;
@ -295,12 +324,13 @@ static void registry_event_global(void *data, uint32_t id,
o->manager = m;
o->info = info;
o->new = true;
spa_list_append(&m->object_list, &o->link);
m->n_objects++;
spa_list_append(&m->this.object_list, &o->this.link);
m->this.n_objects++;
pw_proxy_add_object_listener(proxy,
&o->object_listener,
o->info->events, o);
if (info->events)
pw_proxy_add_object_listener(proxy,
&o->object_listener,
o->info->events, o);
pw_proxy_add_listener(proxy,
&o->proxy_listener,
&proxy_events, o);
@ -331,9 +361,8 @@ static void on_core_done(void *data, uint32_t id, int seq)
{
struct manager *m = data;
if (id == PW_ID_CORE) {
if (m->sync_seq == seq) {
if (m->sync_seq == seq)
manager_emit_sync(m);
}
}
}
@ -344,44 +373,46 @@ static const struct pw_core_events core_events = {
struct pw_manager *pw_manager_new(struct pw_core *core)
{
struct manager *this;
struct manager *m;
this = calloc(1, sizeof(*this));
if (this == NULL)
m = calloc(1, sizeof(*m));
if (m == NULL)
return NULL;
this->core = core;
spa_hook_list_init(&this->hooks);
m->this.core = core;
spa_hook_list_init(&m->hooks);
spa_list_init(&this->object_list);
spa_list_init(&m->this.object_list);
pw_core_add_listener(this->core,
&this->core_listener,
&core_events, this);
this->registry = pw_core_get_registry(this->core,
pw_core_add_listener(m->this.core,
&m->core_listener,
&core_events, m);
m->this.registry = pw_core_get_registry(m->this.core,
PW_VERSION_REGISTRY, 0);
pw_registry_add_listener(this->registry,
&this->registry_listener,
&registry_events, this);
pw_registry_add_listener(m->this.registry,
&m->registry_listener,
&registry_events, m);
return (struct pw_manager*)this;
core_sync(m);
return &m->this;
}
void pw_manager_add_listener(struct pw_manager *manager,
struct spa_hook *listener,
const struct pw_manager_events *events, void *data)
{
struct manager *this = (struct manager*)manager;
spa_hook_list_append(&this->hooks, listener, events, data);
struct manager *m = SPA_CONTAINER_OF(manager, struct manager, this);
spa_hook_list_append(&m->hooks, listener, events, data);
}
struct pw_manager_object *pw_manager_find_object(struct pw_manager *manager,
uint32_t id)
{
struct manager *this = (struct manager*)manager;
struct manager *m = SPA_CONTAINER_OF(manager, struct manager, this);
struct object *o;
o = find_object(this, id);
o = find_object(m, id);
if (o == NULL)
return NULL;
return (struct pw_manager_object*)o;
@ -391,11 +422,11 @@ int pw_manager_for_each_object(struct pw_manager *manager,
int (*callback) (void *data, struct pw_manager_object *object),
void *data)
{
struct manager *this = (struct manager*)manager;
struct manager *m = SPA_CONTAINER_OF(manager, struct manager, this);
struct object *o;
int res;
spa_list_for_each(o, &this->object_list, link) {
spa_list_for_each(o, &m->this.object_list, this.link) {
if ((res = callback(data, &o->this)) != 0)
return res;
}
@ -404,17 +435,17 @@ int pw_manager_for_each_object(struct pw_manager *manager,
void pw_manager_destroy(struct pw_manager *manager)
{
struct manager *this = (struct manager*)manager;
struct manager *m = SPA_CONTAINER_OF(manager, struct manager, this);
struct object *o;
spa_hook_remove(&this->core_listener);
spa_hook_remove(&m->core_listener);
spa_list_consume(o, &this->object_list, link)
spa_list_consume(o, &m->this.object_list, this.link)
object_destroy(o);
if (this->registry) {
spa_hook_remove(&this->registry_listener);
pw_proxy_destroy((struct pw_proxy*)this->registry);
if (m->this.registry) {
spa_hook_remove(&m->registry_listener);
pw_proxy_destroy((struct pw_proxy*)m->this.registry);
}
free(this);
free(m);
}