mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-10-31 22:25:38 -04:00
pulse-server: keep metadata for the routes
Pass all metadata objects to the pulse-server and keep track of some. Keep route restore info in properties.
This commit is contained in:
parent
1f73280c52
commit
4f0f5fccc9
3 changed files with 62 additions and 39 deletions
|
|
@ -32,7 +32,7 @@
|
|||
#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)
|
||||
#define manager_emit_metadata(m,o,s,k,t,v) spa_hook_list_call(&m->hooks, struct pw_manager_events, metadata,0,o,s,k,t,v)
|
||||
|
||||
struct object;
|
||||
|
||||
|
|
@ -43,8 +43,6 @@ struct manager {
|
|||
struct spa_hook registry_listener;
|
||||
int sync_seq;
|
||||
|
||||
struct object *metadata;
|
||||
|
||||
struct spa_hook_list hooks;
|
||||
};
|
||||
|
||||
|
|
@ -412,8 +410,8 @@ static int metadata_property(void *object,
|
|||
{
|
||||
struct object *o = object;
|
||||
struct manager *m = o->manager;
|
||||
manager_emit_metadata(m, subject, key, type, value);
|
||||
return 0;
|
||||
manager_emit_metadata(m, &o->this, subject, key, type, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct pw_metadata_events metadata_events = {
|
||||
|
|
@ -421,26 +419,10 @@ static const struct pw_metadata_events metadata_events = {
|
|||
.property = metadata_property,
|
||||
};
|
||||
|
||||
static void metadata_init(struct object *o)
|
||||
{
|
||||
struct manager *m = o->manager;
|
||||
if (m->metadata == NULL)
|
||||
m->metadata = o;
|
||||
}
|
||||
|
||||
static void metadata_destroy(struct object *o)
|
||||
{
|
||||
struct manager *m = o->manager;
|
||||
if (m->metadata == o)
|
||||
m->metadata = NULL;
|
||||
}
|
||||
|
||||
static const struct object_info metadata_info = {
|
||||
.type = PW_TYPE_INTERFACE_Metadata,
|
||||
.version = PW_VERSION_METADATA,
|
||||
.events = &metadata_events,
|
||||
.init = metadata_init,
|
||||
.destroy = metadata_destroy,
|
||||
};
|
||||
|
||||
static const struct object_info *objects[] =
|
||||
|
|
@ -637,6 +619,7 @@ void pw_manager_add_listener(struct pw_manager *manager,
|
|||
}
|
||||
|
||||
int pw_manager_set_metadata(struct pw_manager *manager,
|
||||
struct pw_manager_object *metadata,
|
||||
uint32_t subject, const char *key, const char *type,
|
||||
const char *format, ...)
|
||||
{
|
||||
|
|
@ -650,16 +633,16 @@ int pw_manager_set_metadata(struct pw_manager *manager,
|
|||
if (!SPA_FLAG_IS_SET(s->this.permissions, PW_PERM_M))
|
||||
return -EACCES;
|
||||
|
||||
if (m->metadata == NULL)
|
||||
if (metadata == NULL)
|
||||
return -ENOTSUP;
|
||||
if (!SPA_FLAG_IS_SET(m->metadata->this.permissions, PW_PERM_W|PW_PERM_X))
|
||||
if (!SPA_FLAG_IS_SET(metadata->permissions, PW_PERM_W|PW_PERM_X))
|
||||
return -EACCES;
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(buf, sizeof(buf)-1, format, args);
|
||||
va_end(args);
|
||||
|
||||
pw_metadata_set_property(m->metadata->this.proxy,
|
||||
pw_metadata_set_property(metadata->proxy,
|
||||
subject, key, type, buf);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,7 +50,8 @@ struct pw_manager_events {
|
|||
|
||||
void (*removed) (void *data, struct pw_manager_object *object);
|
||||
|
||||
void (*metadata) (void *data, uint32_t subject, const char *key,
|
||||
void (*metadata) (void *data, struct pw_manager_object *object,
|
||||
uint32_t subject, const char *key,
|
||||
const char *type, const char *value);
|
||||
};
|
||||
|
||||
|
|
@ -94,8 +95,9 @@ void pw_manager_add_listener(struct pw_manager *manager,
|
|||
void pw_manager_destroy(struct pw_manager *manager);
|
||||
|
||||
int pw_manager_set_metadata(struct pw_manager *manager,
|
||||
struct pw_manager_object *metdata,
|
||||
uint32_t subject, const char *key, const char *type,
|
||||
const char *format, ...) SPA_PRINTF_FUNC(5,6);
|
||||
const char *format, ...) SPA_PRINTF_FUNC(6,7);
|
||||
|
||||
int pw_manager_for_each_object(struct pw_manager *manager,
|
||||
int (*callback) (void *data, struct pw_manager_object *object),
|
||||
|
|
|
|||
|
|
@ -63,6 +63,7 @@
|
|||
|
||||
#include "pipewire/pipewire.h"
|
||||
#include "pipewire/private.h"
|
||||
#include "extensions/metadata.h"
|
||||
|
||||
#include "pulse-server.h"
|
||||
#include "defs.h"
|
||||
|
|
@ -110,8 +111,11 @@ struct client {
|
|||
|
||||
uint32_t subscribed;
|
||||
|
||||
struct pw_manager_object *metadata_default;
|
||||
uint32_t default_sink;
|
||||
uint32_t default_source;
|
||||
struct pw_manager_object *metadata_routes;
|
||||
struct pw_properties *routes;
|
||||
|
||||
uint32_t connect_tag;
|
||||
|
||||
|
|
@ -685,11 +689,31 @@ static uint32_t get_event_and_id(struct client *client, struct pw_manager_object
|
|||
return event;
|
||||
}
|
||||
|
||||
static void handle_metadata_added(struct client *client, struct pw_manager_object *o,
|
||||
const char *name)
|
||||
{
|
||||
if (strcmp(name, "default") == 0) {
|
||||
if (client->metadata_default == NULL)
|
||||
client->metadata_default = o;
|
||||
}
|
||||
else if (strcmp(name, "route-settings") == 0) {
|
||||
if (client->metadata_routes == NULL) {
|
||||
client->metadata_routes = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void manager_added(void *data, struct pw_manager_object *o)
|
||||
{
|
||||
struct client *client = data;
|
||||
uint32_t event, id;
|
||||
const char *str;
|
||||
|
||||
if (strcmp(o->type, PW_TYPE_INTERFACE_Metadata) == 0) {
|
||||
if (o->props != NULL &&
|
||||
(str = pw_properties_get(o->props, PW_KEY_METADATA_NAME)) != NULL)
|
||||
handle_metadata_added(client, o, str);
|
||||
}
|
||||
if ((event = get_event_and_id(client, o, &id)) != SPA_ID_INVALID)
|
||||
send_subscribe_event(client,
|
||||
event | SUBSCRIPTION_EVENT_NEW,
|
||||
|
|
@ -718,15 +742,17 @@ static void manager_removed(void *data, struct pw_manager_object *o)
|
|||
id);
|
||||
}
|
||||
|
||||
static void manager_metadata(void *data, uint32_t subject, const char *key,
|
||||
const char *type, const char *value)
|
||||
static void manager_metadata(void *data, struct pw_manager_object *o,
|
||||
uint32_t subject, const char *key, const char *type, const char *value)
|
||||
{
|
||||
struct client *client = data;
|
||||
uint32_t val;
|
||||
bool changed = false;
|
||||
|
||||
pw_log_debug("meta %d %s %s %s", subject, key, type, value);
|
||||
if (subject == PW_ID_CORE) {
|
||||
pw_log_debug("meta id:%d subject:%d key:%s type:%s value:%s",
|
||||
o->id, subject, key, type, value);
|
||||
|
||||
if (subject == PW_ID_CORE && o == client->metadata_default) {
|
||||
val = (key && value) ? (uint32_t)atoi(value) : SPA_ID_INVALID;
|
||||
if (key == NULL || strcmp(key, "default.audio.sink") == 0) {
|
||||
changed = client->default_sink != val;
|
||||
|
|
@ -736,15 +762,21 @@ static void manager_metadata(void *data, uint32_t subject, const char *key,
|
|||
changed = client->default_source != val;
|
||||
client->default_source = val;
|
||||
}
|
||||
}
|
||||
if (changed) {
|
||||
if (client->subscribed & SUBSCRIPTION_MASK_SERVER) {
|
||||
send_subscribe_event(client,
|
||||
SUBSCRIPTION_EVENT_CHANGE |
|
||||
SUBSCRIPTION_EVENT_SERVER,
|
||||
-1);
|
||||
if (changed) {
|
||||
if (client->subscribed & SUBSCRIPTION_MASK_SERVER) {
|
||||
send_subscribe_event(client,
|
||||
SUBSCRIPTION_EVENT_CHANGE |
|
||||
SUBSCRIPTION_EVENT_SERVER,
|
||||
-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (subject == PW_ID_CORE && o == client->metadata_routes) {
|
||||
if (key == NULL)
|
||||
pw_properties_clear(client->routes);
|
||||
else
|
||||
pw_properties_set(client->routes, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct pw_manager_events manager_events = {
|
||||
|
|
@ -4173,7 +4205,7 @@ static int do_set_default(struct client *client, uint32_t command, uint32_t tag,
|
|||
if ((o = find_device(client, SPA_ID_INVALID, name, sink)) == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
if ((res = pw_manager_set_metadata(manager,
|
||||
if ((res = pw_manager_set_metadata(manager, client->metadata_default,
|
||||
PW_ID_CORE,
|
||||
sink ? METADATA_DEFAULT_SINK : METADATA_DEFAULT_SOURCE,
|
||||
SPA_TYPE_INFO_BASE"Id", "%d", o->id)) < 0)
|
||||
|
|
@ -4218,7 +4250,7 @@ static int do_move_stream(struct client *client, uint32_t command, uint32_t tag,
|
|||
if ((dev = find_device(client, id_device, name_device, sink)) == NULL)
|
||||
return -ENOENT;
|
||||
|
||||
if ((res = pw_manager_set_metadata(manager,
|
||||
if ((res = pw_manager_set_metadata(manager, client->metadata_default,
|
||||
o->id,
|
||||
METADATA_TARGET_NODE,
|
||||
SPA_TYPE_INFO_BASE"Id", "%d", dev->id)) < 0)
|
||||
|
|
@ -4588,6 +4620,8 @@ static void client_free(struct client *client)
|
|||
}
|
||||
if (client->props)
|
||||
pw_properties_free(client->props);
|
||||
if (client->routes)
|
||||
pw_properties_free(client->routes);
|
||||
if (client->source)
|
||||
pw_loop_destroy_source(impl->loop, client->source);
|
||||
if (client->cleanup)
|
||||
|
|
@ -4866,6 +4900,10 @@ on_connect(void *data, int fd, uint32_t mask)
|
|||
if (client->props == NULL)
|
||||
goto error;
|
||||
|
||||
client->routes = pw_properties_new(NULL, NULL);
|
||||
if (client->routes == NULL)
|
||||
goto error;
|
||||
|
||||
length = sizeof(name);
|
||||
client_fd = accept4(fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC);
|
||||
if (client_fd < 0)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue