mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-01 22:58:50 -04:00
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:
parent
f75acc31d3
commit
a372e4e90e
4 changed files with 552 additions and 224 deletions
|
|
@ -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,
|
||||
®istry_events, this);
|
||||
pw_registry_add_listener(m->this.registry,
|
||||
&m->registry_listener,
|
||||
®istry_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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue