mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05: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_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_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_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;
 | 
					struct object;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -43,8 +43,6 @@ struct manager {
 | 
				
			||||||
	struct spa_hook registry_listener;
 | 
						struct spa_hook registry_listener;
 | 
				
			||||||
	int sync_seq;
 | 
						int sync_seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	struct object *metadata;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	struct spa_hook_list hooks;
 | 
						struct spa_hook_list hooks;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -412,7 +410,7 @@ static int metadata_property(void *object,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct object *o = object;
 | 
						struct object *o = object;
 | 
				
			||||||
	struct manager *m = o->manager;
 | 
						struct manager *m = o->manager;
 | 
				
			||||||
	manager_emit_metadata(m, subject, key, type, value);
 | 
						manager_emit_metadata(m, &o->this, subject, key, type, value);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -421,26 +419,10 @@ static const struct pw_metadata_events metadata_events = {
 | 
				
			||||||
	.property = metadata_property,
 | 
						.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 = {
 | 
					static const struct object_info metadata_info = {
 | 
				
			||||||
	.type = PW_TYPE_INTERFACE_Metadata,
 | 
						.type = PW_TYPE_INTERFACE_Metadata,
 | 
				
			||||||
	.version = PW_VERSION_METADATA,
 | 
						.version = PW_VERSION_METADATA,
 | 
				
			||||||
	.events = &metadata_events,
 | 
						.events = &metadata_events,
 | 
				
			||||||
	.init = metadata_init,
 | 
					 | 
				
			||||||
	.destroy = metadata_destroy,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const struct object_info *objects[] =
 | 
					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,
 | 
					int pw_manager_set_metadata(struct pw_manager *manager,
 | 
				
			||||||
 | 
							struct pw_manager_object *metadata,
 | 
				
			||||||
		uint32_t subject, const char *key, const char *type,
 | 
							uint32_t subject, const char *key, const char *type,
 | 
				
			||||||
		const char *format, ...)
 | 
							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))
 | 
						if (!SPA_FLAG_IS_SET(s->this.permissions, PW_PERM_M))
 | 
				
			||||||
		return -EACCES;
 | 
							return -EACCES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (m->metadata == NULL)
 | 
						if (metadata == NULL)
 | 
				
			||||||
		return -ENOTSUP;
 | 
							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;
 | 
							return -EACCES;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        va_start(args, format);
 | 
					        va_start(args, format);
 | 
				
			||||||
	vsnprintf(buf, sizeof(buf)-1, format, args);
 | 
						vsnprintf(buf, sizeof(buf)-1, format, args);
 | 
				
			||||||
        va_end(args);
 | 
					        va_end(args);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_metadata_set_property(m->metadata->this.proxy,
 | 
						pw_metadata_set_property(metadata->proxy,
 | 
				
			||||||
			subject, key, type, buf);
 | 
								subject, key, type, buf);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,8 @@ struct pw_manager_events {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void (*removed) (void *data, struct pw_manager_object *object);
 | 
						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);
 | 
								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);
 | 
					void pw_manager_destroy(struct pw_manager *manager);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int pw_manager_set_metadata(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,
 | 
							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 pw_manager_for_each_object(struct pw_manager *manager,
 | 
				
			||||||
		int (*callback) (void *data, struct pw_manager_object *object),
 | 
							int (*callback) (void *data, struct pw_manager_object *object),
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -63,6 +63,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pipewire/pipewire.h"
 | 
					#include "pipewire/pipewire.h"
 | 
				
			||||||
#include "pipewire/private.h"
 | 
					#include "pipewire/private.h"
 | 
				
			||||||
 | 
					#include "extensions/metadata.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "pulse-server.h"
 | 
					#include "pulse-server.h"
 | 
				
			||||||
#include "defs.h"
 | 
					#include "defs.h"
 | 
				
			||||||
| 
						 | 
					@ -110,8 +111,11 @@ struct client {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t subscribed;
 | 
						uint32_t subscribed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct pw_manager_object *metadata_default;
 | 
				
			||||||
	uint32_t default_sink;
 | 
						uint32_t default_sink;
 | 
				
			||||||
	uint32_t default_source;
 | 
						uint32_t default_source;
 | 
				
			||||||
 | 
						struct pw_manager_object *metadata_routes;
 | 
				
			||||||
 | 
						struct pw_properties *routes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	uint32_t connect_tag;
 | 
						uint32_t connect_tag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -685,11 +689,31 @@ static uint32_t get_event_and_id(struct client *client, struct pw_manager_object
 | 
				
			||||||
	return event;
 | 
						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)
 | 
					static void manager_added(void *data, struct pw_manager_object *o)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct client *client = data;
 | 
						struct client *client = data;
 | 
				
			||||||
	uint32_t event, id;
 | 
						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)
 | 
						if ((event = get_event_and_id(client, o, &id)) != SPA_ID_INVALID)
 | 
				
			||||||
		send_subscribe_event(client,
 | 
							send_subscribe_event(client,
 | 
				
			||||||
				event | SUBSCRIPTION_EVENT_NEW,
 | 
									event | SUBSCRIPTION_EVENT_NEW,
 | 
				
			||||||
| 
						 | 
					@ -718,15 +742,17 @@ static void manager_removed(void *data, struct pw_manager_object *o)
 | 
				
			||||||
				id);
 | 
									id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void manager_metadata(void *data, uint32_t subject, const char *key,
 | 
					static void manager_metadata(void *data, struct pw_manager_object *o,
 | 
				
			||||||
			const char *type, const char *value)
 | 
							uint32_t subject, const char *key, const char *type, const char *value)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct client *client = data;
 | 
						struct client *client = data;
 | 
				
			||||||
	uint32_t val;
 | 
						uint32_t val;
 | 
				
			||||||
	bool changed = false;
 | 
						bool changed = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug("meta %d %s %s %s", subject, key, type, value);
 | 
						pw_log_debug("meta id:%d subject:%d key:%s type:%s value:%s",
 | 
				
			||||||
	if (subject == PW_ID_CORE) {
 | 
								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;
 | 
							val = (key && value) ? (uint32_t)atoi(value) : SPA_ID_INVALID;
 | 
				
			||||||
		if (key == NULL || strcmp(key, "default.audio.sink") == 0) {
 | 
							if (key == NULL || strcmp(key, "default.audio.sink") == 0) {
 | 
				
			||||||
			changed = client->default_sink != val;
 | 
								changed = client->default_sink != val;
 | 
				
			||||||
| 
						 | 
					@ -736,7 +762,6 @@ static void manager_metadata(void *data, uint32_t subject, const char *key,
 | 
				
			||||||
			changed = client->default_source != val;
 | 
								changed = client->default_source != val;
 | 
				
			||||||
			client->default_source = val;
 | 
								client->default_source = val;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
		if (changed) {
 | 
							if (changed) {
 | 
				
			||||||
			if (client->subscribed & SUBSCRIPTION_MASK_SERVER) {
 | 
								if (client->subscribed & SUBSCRIPTION_MASK_SERVER) {
 | 
				
			||||||
				send_subscribe_event(client,
 | 
									send_subscribe_event(client,
 | 
				
			||||||
| 
						 | 
					@ -746,6 +771,13 @@ static void manager_metadata(void *data, uint32_t subject, const char *key,
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						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 = {
 | 
					static const struct pw_manager_events manager_events = {
 | 
				
			||||||
	PW_VERSION_MANAGER_EVENTS,
 | 
						PW_VERSION_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)
 | 
						if ((o = find_device(client, SPA_ID_INVALID, name, sink)) == NULL)
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((res = pw_manager_set_metadata(manager,
 | 
						if ((res = pw_manager_set_metadata(manager, client->metadata_default,
 | 
				
			||||||
			PW_ID_CORE,
 | 
								PW_ID_CORE,
 | 
				
			||||||
			sink ? METADATA_DEFAULT_SINK : METADATA_DEFAULT_SOURCE,
 | 
								sink ? METADATA_DEFAULT_SINK : METADATA_DEFAULT_SOURCE,
 | 
				
			||||||
			SPA_TYPE_INFO_BASE"Id", "%d", o->id)) < 0)
 | 
								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)
 | 
						if ((dev = find_device(client, id_device, name_device, sink)) == NULL)
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((res = pw_manager_set_metadata(manager,
 | 
						if ((res = pw_manager_set_metadata(manager, client->metadata_default,
 | 
				
			||||||
			o->id,
 | 
								o->id,
 | 
				
			||||||
			METADATA_TARGET_NODE,
 | 
								METADATA_TARGET_NODE,
 | 
				
			||||||
			SPA_TYPE_INFO_BASE"Id", "%d", dev->id)) < 0)
 | 
								SPA_TYPE_INFO_BASE"Id", "%d", dev->id)) < 0)
 | 
				
			||||||
| 
						 | 
					@ -4588,6 +4620,8 @@ static void client_free(struct client *client)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (client->props)
 | 
						if (client->props)
 | 
				
			||||||
		pw_properties_free(client->props);
 | 
							pw_properties_free(client->props);
 | 
				
			||||||
 | 
						if (client->routes)
 | 
				
			||||||
 | 
							pw_properties_free(client->routes);
 | 
				
			||||||
	if (client->source)
 | 
						if (client->source)
 | 
				
			||||||
		pw_loop_destroy_source(impl->loop, client->source);
 | 
							pw_loop_destroy_source(impl->loop, client->source);
 | 
				
			||||||
	if (client->cleanup)
 | 
						if (client->cleanup)
 | 
				
			||||||
| 
						 | 
					@ -4866,6 +4900,10 @@ on_connect(void *data, int fd, uint32_t mask)
 | 
				
			||||||
	if (client->props == NULL)
 | 
						if (client->props == NULL)
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client->routes = pw_properties_new(NULL, NULL);
 | 
				
			||||||
 | 
						if (client->routes == NULL)
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	length = sizeof(name);
 | 
						length = sizeof(name);
 | 
				
			||||||
	client_fd = accept4(fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC);
 | 
						client_fd = accept4(fd, (struct sockaddr *) &name, &length, SOCK_CLOEXEC);
 | 
				
			||||||
	if (client_fd < 0)
 | 
						if (client_fd < 0)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue