diff --git a/src/modules/module-protocol-pulse/manager.c b/src/modules/module-protocol-pulse/manager.c index 258e60105..b98e3fd80 100644 --- a/src/modules/module-protocol-pulse/manager.c +++ b/src/modules/module-protocol-pulse/manager.c @@ -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; } diff --git a/src/modules/module-protocol-pulse/manager.h b/src/modules/module-protocol-pulse/manager.h index 51ac25654..f0a8785df 100644 --- a/src/modules/module-protocol-pulse/manager.h +++ b/src/modules/module-protocol-pulse/manager.h @@ -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), diff --git a/src/modules/module-protocol-pulse/pulse-server.c b/src/modules/module-protocol-pulse/pulse-server.c index 662b48f1c..bdb51225b 100644 --- a/src/modules/module-protocol-pulse/pulse-server.c +++ b/src/modules/module-protocol-pulse/pulse-server.c @@ -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)