diff --git a/pipewire-jack/src/pipewire-jack.c b/pipewire-jack/src/pipewire-jack.c index a5814d7db..c838c2f4a 100644 --- a/pipewire-jack/src/pipewire-jack.c +++ b/pipewire-jack/src/pipewire-jack.c @@ -56,7 +56,6 @@ #define JACK_DEFAULT_VIDEO_TYPE "32 bit float RGBA video" #define JACK_CLIENT_NAME_SIZE 64 -#define JACK_CLIENT_KEY_SIZE 256 #define JACK_PORT_NAME_SIZE 256 #define JACK_PORT_MAX 4096 #define JACK_PORT_TYPE_SIZE 32 @@ -70,7 +69,6 @@ #define MAX_BUFFER_DATAS 1u #define REAL_JACK_PORT_NAME_SIZE (JACK_CLIENT_NAME_SIZE + JACK_PORT_NAME_SIZE) -#define REAL_JACK_PORT_KEY_SIZE (JACK_CLIENT_KEY_SIZE + JACK_PORT_NAME_SIZE) #define NAME "jack-client" @@ -110,7 +108,6 @@ struct object { union { struct { char name[JACK_CLIENT_NAME_SIZE+1]; - char key[JACK_CLIENT_KEY_SIZE+1]; int32_t priority; uint32_t client_id; } node; @@ -123,7 +120,6 @@ struct object { char name[REAL_JACK_PORT_NAME_SIZE+1]; char alias1[REAL_JACK_PORT_NAME_SIZE+1]; char alias2[REAL_JACK_PORT_NAME_SIZE+1]; - char key[REAL_JACK_PORT_KEY_SIZE+1]; uint32_t type_id; uint32_t node_id; uint32_t port_id; @@ -236,8 +232,8 @@ struct metadata { struct pw_metadata *proxy; struct spa_hook listener; - char *default_audio_sink; - char *default_audio_source; + uint32_t default_audio_sink; + uint32_t default_audio_source; }; struct client { @@ -1955,12 +1951,10 @@ static int metadata_property(void *object, uint32_t id, uuid = jack_port_uuid_generate(id); update_property(c, uuid, key, type, value); - if (key && strcmp(key, "default.audio.sink.name") == 0) { - free(c->metadata->default_audio_sink); - c->metadata->default_audio_sink = value ? strdup(value) : NULL; - } else if (key && strcmp(key, "default.audio.source.name") == 0) { - free(c->metadata->default_audio_source); - c->metadata->default_audio_source = value ? strdup(value) : NULL; + if (key && strcmp(key, "default.audio.sink") == 0) { + c->metadata->default_audio_sink = value ? (uint32_t)atoi(value) : SPA_ID_INVALID; + } else if (key && strcmp(key, "default.audio.source") == 0) { + c->metadata->default_audio_source = value ? (uint32_t)atoi(value) : SPA_ID_INVALID; } return 0; } @@ -2008,10 +2002,6 @@ static void registry_event_global(void *data, uint32_t id, if (ot != NULL && o->node.client_id != ot->node.client_id) snprintf(o->node.name, sizeof(o->node.name), "%s-%d", str, id); - if ((str = spa_dict_lookup(props, PW_KEY_NODE_NAME)) == NULL) - str = o->node.name; - snprintf(o->node.key, sizeof(o->node.key), "%s", str); - if ((str = spa_dict_lookup(props, PW_KEY_PRIORITY_MASTER)) != NULL) o->node.priority = pw_properties_parse_int(str); @@ -2084,7 +2074,6 @@ static void registry_event_global(void *data, uint32_t id, goto exit_free; snprintf(o->port.name, sizeof(o->port.name), "%s:%s", ot->node.name, str); - snprintf(o->port.key, sizeof(o->port.key), "%s:%s", ot->node.key, str); o->port.port_id = SPA_ID_INVALID; o->port.priority = ot->node.priority; } @@ -2115,8 +2104,8 @@ static void registry_event_global(void *data, uint32_t id, snprintf(o->port.name, sizeof(o->port.name), "%.*s-%d", (int)(sizeof(op->port.name)-11), op->port.name, id); - pw_log_debug(NAME" %p: add port %d name:%s key:%s %d", c, id, - o->port.name, o->port.key, type_id); + pw_log_debug(NAME" %p: add port %d name:%s %d", c, id, + o->port.name, type_id); } else if (strcmp(type, PW_TYPE_INTERFACE_Link) == 0) { o = alloc_object(c); @@ -2148,6 +2137,8 @@ static void registry_event_global(void *data, uint32_t id, c->metadata = pw_proxy_get_user_data(proxy); c->metadata->proxy = (struct pw_metadata*)proxy; + c->metadata->default_audio_sink = SPA_ID_INVALID; + c->metadata->default_audio_source = SPA_ID_INVALID; pw_metadata_add_listener(proxy, &c->metadata->listener, @@ -2202,6 +2193,13 @@ static void registry_event_global_remove(void *object, uint32_t id) pw_log_debug(NAME" %p: removed: %u", c, id); + if (c->metadata) { + if (id == c->metadata->default_audio_sink) + c->metadata->default_audio_sink = SPA_ID_INVALID; + if (id == c->metadata->default_audio_source) + c->metadata->default_audio_source = SPA_ID_INVALID; + } + o = pw_map_lookup(&c->context.globals, id); if (o == NULL) return; @@ -2444,8 +2442,6 @@ int jack_client_close (jack_client_t *client) pw_proxy_destroy((struct pw_proxy*)c->registry); if (c->metadata && c->metadata->proxy) { pw_proxy_destroy((struct pw_proxy*)c->metadata->proxy); - free(c->metadata->default_audio_sink); - free(c->metadata->default_audio_source); } pw_core_disconnect(c->core); pw_context_destroy(c->context.context); @@ -3967,16 +3963,17 @@ static int port_compare_func(const void *v1, const void *v2, void *arg) is_cap1 = ((*o1)->port.flags & JackPortIsOutput) == JackPortIsOutput; is_cap2 = ((*o2)->port.flags & JackPortIsOutput) == JackPortIsOutput; - if (is_cap1 && c->metadata->default_audio_source != NULL) - is_def1 = strstr((*o1)->port.key, c->metadata->default_audio_source) == (*o1)->port.key; - else if (!is_cap1 && c->metadata->default_audio_sink != NULL) - is_def1 = strstr((*o1)->port.key, c->metadata->default_audio_sink) == (*o1)->port.key; - - if (is_cap2 && c->metadata->default_audio_source != NULL) - is_def2 = strstr((*o2)->port.key, c->metadata->default_audio_source) == (*o2)->port.key; - else if (!is_cap2 && c->metadata->default_audio_sink != NULL) - is_def2 = strstr((*o2)->port.key, c->metadata->default_audio_sink) == (*o2)->port.key; + if (c->metadata) { + if (is_cap1) + is_def1 = (*o1)->port.node_id == c->metadata->default_audio_source; + else if (!is_cap1) + is_def1 = (*o1)->port.node_id == c->metadata->default_audio_sink; + if (is_cap2) + is_def2 = (*o2)->port.node_id == c->metadata->default_audio_source; + else if (!is_cap2) + is_def2 = (*o2)->port.node_id == c->metadata->default_audio_sink; + } if ((*o1)->port.type_id != (*o2)->port.type_id) res = (*o1)->port.type_id - (*o2)->port.type_id; else if ((is_cap1 || is_cap2) && is_cap1 != is_cap2) @@ -3988,8 +3985,7 @@ static int port_compare_func(const void *v1, const void *v2, void *arg) else if ((res = strcmp((*o1)->port.alias1, (*o2)->port.alias1) == 0)) res = (*o1)->id - (*o2)->id; - pw_log_debug("port %s %s type:%d<->%d def:%d<->%d prio:%d<->%d id:%d<->%d res:%d", - (*o1)->port.key, (*o2)->port.key, + pw_log_debug("port type:%d<->%d def:%d<->%d prio:%d<->%d id:%d<->%d res:%d", (*o1)->port.type_id, (*o2)->port.type_id, is_def1, is_def2, (*o1)->port.priority, (*o2)->port.priority, diff --git a/pipewire-pulseaudio/src/context.c b/pipewire-pulseaudio/src/context.c index 754ff3818..2b208f4c3 100644 --- a/pipewire-pulseaudio/src/context.c +++ b/pipewire-pulseaudio/src/context.c @@ -1619,8 +1619,10 @@ static void do_default_node(pa_operation *o, void *userdata) if (g == NULL) { error = PA_ERR_NOENTITY; } else if (c->metadata) { + char buf[16]; + snprintf(buf, sizeof(buf), "%d", g->id); pw_metadata_set_property(c->metadata->proxy, - PW_ID_CORE, d->key, "text/plain", d->name); + PW_ID_CORE, d->key, SPA_TYPE_INFO_BASE"Id", buf); } else { error = PA_ERR_NOTIMPLEMENTED; } diff --git a/pipewire-pulseaudio/src/internal.h b/pipewire-pulseaudio/src/internal.h index 9d796e6fa..922bfb96a 100644 --- a/pipewire-pulseaudio/src/internal.h +++ b/pipewire-pulseaudio/src/internal.h @@ -481,8 +481,9 @@ pa_operation *pa_operation_new(pa_context *c, pa_stream *s, pa_operation_cb_t cb void pa_operation_done(pa_operation *o); int pa_operation_sync(pa_operation *o); -#define METADATA_DEFAULT_SINK "default.audio.sink.name" -#define METADATA_DEFAULT_SOURCE "default.audio.source.name" +#define METADATA_DEFAULT_SINK "default.audio.sink" +#define METADATA_DEFAULT_SOURCE "default.audio.source" +#define METADATA_TARGET_NODE "target.node" int pa_metadata_update(struct global *global, uint32_t subject, const char *key, const char *type, const char *value); diff --git a/pipewire-pulseaudio/src/introspect.c b/pipewire-pulseaudio/src/introspect.c index 7cb3a4bb8..497281536 100644 --- a/pipewire-pulseaudio/src/introspect.c +++ b/pipewire-pulseaudio/src/introspect.c @@ -1244,7 +1244,7 @@ struct server_data { static const char *get_default_name(pa_context *c, uint32_t mask) { struct global *g; - const char *str, *name = NULL, *type, *key; + const char *str, *id = NULL, *type, *key; if (c->metadata) { if (mask & PA_SUBSCRIPTION_MASK_SINK) @@ -1254,15 +1254,15 @@ static const char *get_default_name(pa_context *c, uint32_t mask) else return NULL; - if (pa_metadata_get(c->metadata, PW_ID_CORE, key, &type, &name) <= 0) - name = NULL; + if (pa_metadata_get(c->metadata, PW_ID_CORE, key, &type, &id) <= 0) + id = NULL; } spa_list_for_each(g, &c->globals, link) { if ((g->mask & mask) != mask) continue; if (g->props != NULL && (str = pw_properties_get(g->props, PW_KEY_NODE_NAME)) != NULL && - (name == NULL || strcmp(name, str) == 0)) + (id == NULL || (uint32_t)atoi(id) == g->id)) return str; } return "unknown"; @@ -2043,7 +2043,6 @@ struct target_node { pa_context_success_cb_t cb; void *userdata; const char *key; - const char *type; }; static void do_target_node(pa_operation *o, void *userdata) @@ -2067,15 +2066,14 @@ static void do_target_node(pa_operation *o, void *userdata) if ((g = pa_context_find_global(c, d->target_idx)) == NULL || !(g->mask & d->target_mask)) g = NULL; - else { - d->target_name = spa_aprintf("%d", g->id); - } } if (g == NULL) { error = PA_ERR_NOENTITY; } else if (c->metadata) { + char buf[16]; + snprintf(buf, sizeof(buf), "%d", g->id); pw_metadata_set_property(c->metadata->proxy, - d->idx, d->key, d->type, d->target_name); + d->idx, d->key, SPA_TYPE_INFO_BASE "Id", buf); } else { error = PA_ERR_NOTIMPLEMENTED; } @@ -2102,8 +2100,7 @@ pa_operation* pa_context_move_sink_input_by_name(pa_context *c, uint32_t idx, co d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT; d->target_name = pa_xstrdup(sink_name); d->target_mask = PA_SUBSCRIPTION_MASK_SINK; - d->key = "target.node.name"; - d->type = SPA_TYPE_INFO_BASE "String"; + d->key = METADATA_TARGET_NODE; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -2125,8 +2122,7 @@ pa_operation* pa_context_move_sink_input_by_index(pa_context *c, uint32_t idx, u d->mask = PA_SUBSCRIPTION_MASK_SINK_INPUT; d->target_idx = sink_idx; d->target_mask = PA_SUBSCRIPTION_MASK_SINK; - d->key = "target.node"; - d->type = SPA_TYPE_INFO_BASE "Id"; + d->key = METADATA_TARGET_NODE; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -2459,8 +2455,7 @@ pa_operation* pa_context_move_source_output_by_name(pa_context *c, uint32_t idx, d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT; d->target_name = pa_xstrdup(source_name); d->target_mask = PA_SUBSCRIPTION_MASK_SOURCE; - d->key = "target.node.name"; - d->type = SPA_TYPE_INFO_BASE "String"; + d->key = METADATA_TARGET_NODE; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); @@ -2482,8 +2477,7 @@ pa_operation* pa_context_move_source_output_by_index(pa_context *c, uint32_t idx d->mask = PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT; d->target_idx = source_idx; d->target_mask = PA_SUBSCRIPTION_MASK_SOURCE; - d->key = "target.node"; - d->type = SPA_TYPE_INFO_BASE "Id"; + d->key = METADATA_TARGET_NODE; d->cb = cb; d->userdata = userdata; pa_operation_sync(o); diff --git a/src/examples/media-session/policy-node.c b/src/examples/media-session/policy-node.c index 56783e6f1..c069acbff 100644 --- a/src/examples/media-session/policy-node.c +++ b/src/examples/media-session/policy-node.c @@ -61,8 +61,8 @@ struct impl { struct spa_list node_list; int seq; - char *default_audio_sink; - char *default_audio_source; + uint32_t default_audio_sink; + uint32_t default_audio_source; }; struct node { @@ -334,6 +334,10 @@ static void session_remove(void *data, struct sm_object *object) if (n->peer == node) n->peer = NULL; } + if (impl->default_audio_sink == object->id) + impl->default_audio_sink = SPA_ID_INVALID; + if (impl->default_audio_source == object->id) + impl->default_audio_source = SPA_ID_INVALID; } sm_media_session_schedule_rescan(impl->session); @@ -355,7 +359,6 @@ static int find_node(void *data, struct node *node) int priority = 0; uint64_t plugged = 0; struct sm_device *device = node->obj->device; - const char *name; bool is_default = false; pw_log_debug(NAME " %p: looking at node '%d' enabled:%d state:%d peer:%p exclusive:%d", @@ -377,15 +380,11 @@ static int find_node(void *data, struct node *node) pw_log_debug(".. incompatible media %s <-> %s", node->media, find->target->media); return 0; } - if ((name = pw_properties_get(node->obj->obj.props, PW_KEY_NODE_NAME)) != NULL) { - if (node->media && strcmp(node->media, "Audio") == 0) { - if (node->direction == PW_DIRECTION_INPUT && - impl->default_audio_sink != NULL) - is_default = strcmp(impl->default_audio_sink, name) == 0; - else if (node->direction == PW_DIRECTION_OUTPUT && - impl->default_audio_source != NULL) - is_default = strcmp(impl->default_audio_source, name) == 0; - } + if (node->media && strcmp(node->media, "Audio") == 0) { + if (node->direction == PW_DIRECTION_INPUT) + is_default = impl->default_audio_sink == node->id; + else if (node->direction == PW_DIRECTION_OUTPUT) + is_default = impl->default_audio_source == node->id; } plugged = node->plugged; @@ -640,28 +639,15 @@ static struct node *find_node_by_id(struct impl *impl, uint32_t id) return NULL; } -static struct node *find_node_by_name(struct impl *impl, const char *name) -{ - const char *str; - struct node *node; - - spa_list_for_each(node, &impl->node_list, link) { - str = pw_properties_get(node->obj->obj.props, "node.name"); - if (str && strcmp(str, name) == 0) - return node; - } - return NULL; -} - -static int move_node(struct impl *impl, const char *source, const char *target) +static int move_node(struct impl *impl, uint32_t source, uint32_t target) { struct node *n, *src_node, *dst_node; const char *str; /* find source and dest node */ - if ((src_node = find_node_by_name(impl, source)) == NULL) + if ((src_node = find_node_by_id(impl, source)) == NULL) return -ENOENT; - if ((dst_node = find_node_by_name(impl, target)) == NULL) + if ((dst_node = find_node_by_id(impl, target)) == NULL) return -ENOENT; if (src_node == dst_node) @@ -694,6 +680,8 @@ static int handle_move(struct impl *impl, struct node *src_node, struct node *ds const char *str; struct pw_node_info *info; + + if (src_node->peer == dst_node) return 0; @@ -722,21 +710,19 @@ static int metadata_property(void *object, uint32_t subject, { struct impl *impl = object; - if (key == NULL || type == NULL) + if (key == NULL) return 0; if (subject == PW_ID_CORE) { - if (strcmp(key, "default.audio.sink.name") == 0) { - if (impl->default_audio_sink && value) - move_node(impl, impl->default_audio_sink, value); - free(impl->default_audio_sink); - impl->default_audio_sink = value ? strdup(value) : NULL; + if (strcmp(key, "default.audio.sink") == 0) { + if (impl->default_audio_sink != SPA_ID_INVALID && value) + move_node(impl, impl->default_audio_sink, atoi(value)); + impl->default_audio_sink = value ? (uint32_t)atoi(value) : SPA_ID_INVALID; } - else if (strcmp(key, "default.audio.source.name") == 0) { - if (impl->default_audio_source && value) - move_node(impl, impl->default_audio_source, value); - free(impl->default_audio_source); - impl->default_audio_source = value ? strdup(value) : NULL; + else if (strcmp(key, "default.audio.source") == 0) { + if (impl->default_audio_source != SPA_ID_INVALID && value) + move_node(impl, impl->default_audio_source, atoi(value)); + impl->default_audio_source = value ? (uint32_t)atoi(value) : SPA_ID_INVALID; } } else { struct node *src_node, *dst_node = NULL; @@ -746,9 +732,6 @@ static int metadata_property(void *object, uint32_t subject, if (strcmp(key, "target.node") == 0 && value != NULL) { dst_node = find_node_by_id(impl, atoi(value)); } - else if (strcmp(key, "target.node.name") == 0 && value != NULL) { - dst_node = find_node_by_name(impl, value); - } if (src_node && dst_node) handle_move(impl, src_node, dst_node); } @@ -773,6 +756,8 @@ int sm_policy_node_start(struct sm_media_session *session) impl->context = session->context; impl->sample_rate = 48000; + impl->default_audio_sink = SPA_ID_INVALID; + impl->default_audio_source = SPA_ID_INVALID; spa_list_init(&impl->node_list);