From 5ab1d898caa6a88f2ee174086ad7ae6331919c93 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 2 Mar 2023 11:59:08 +0100 Subject: [PATCH] impl-port: improve port properties Move the port property logic from the adapter to the port itself. The port was already doing some of the same work as a fallback but can just as well do everything. This also makes things more unified when there is no adapter used. --- src/modules/module-adapter/adapter.c | 129 --------------------------- src/pipewire/impl-port.c | 124 ++++++++++++++++++++----- 2 files changed, 100 insertions(+), 153 deletions(-) diff --git a/src/modules/module-adapter/adapter.c b/src/modules/module-adapter/adapter.c index 69fc75fa4..9d52af531 100644 --- a/src/modules/module-adapter/adapter.c +++ b/src/modules/module-adapter/adapter.c @@ -65,138 +65,9 @@ static void node_free(void *data) pw_properties_free(n->props); } -static void node_port_init(void *data, struct pw_impl_port *port) -{ - struct node *n = data; - const struct pw_properties *old; - enum pw_direction direction; - struct pw_properties *new; - const char *str, *path, *desc, *nick, *name, *node_name, *media_class, *prop_port_names, *override_device_prefix; - char position[8], *prefix; - bool is_monitor, is_device, is_duplex, is_virtual, is_control = false, no_device_port_prefix; - - direction = pw_impl_port_get_direction(port); - - old = pw_impl_port_get_properties(port); - - is_monitor = pw_properties_get_bool(old, PW_KEY_PORT_MONITOR, false); - if (!is_monitor && direction != n->direction) - return; - - if ((str = pw_properties_get(old, PW_KEY_FORMAT_DSP)) != NULL) - is_control = spa_streq(str, "8 bit raw midi"); - - path = pw_properties_get(n->props, PW_KEY_OBJECT_PATH); - media_class = pw_properties_get(n->props, PW_KEY_MEDIA_CLASS); - - if (media_class != NULL && - (strstr(media_class, "Sink") != NULL || - strstr(media_class, "Source") != NULL)) - is_device = true; - else - is_device = false; - - is_duplex = media_class != NULL && strstr(media_class, "Duplex") != NULL; - is_virtual = media_class != NULL && strstr(media_class, "Virtual") != NULL; - - new = pw_properties_new(NULL, NULL); - - override_device_prefix = pw_properties_get(n->props, PW_KEY_NODE_DEVICE_PORT_NAME_PREFIX); - - if (is_control) - prefix = direction == PW_DIRECTION_INPUT ? - "control" : "notify"; - else if (is_duplex) - prefix = direction == PW_DIRECTION_INPUT ? - "playback" : "capture"; - else if (is_virtual) - prefix = direction == PW_DIRECTION_INPUT ? - "input" : "capture"; - else if (is_device) - prefix = direction == PW_DIRECTION_INPUT ? - override_device_prefix != NULL ? - strdup(override_device_prefix) : "playback" - : is_monitor ? "monitor" : override_device_prefix != NULL ? - strdup(override_device_prefix) : "capture"; - else - prefix = direction == PW_DIRECTION_INPUT ? - "input" : is_monitor ? "monitor" : "output"; - - if ((str = pw_properties_get(old, PW_KEY_AUDIO_CHANNEL)) == NULL || - spa_streq(str, "UNK")) { - snprintf(position, sizeof(position), "%d", pw_impl_port_get_id(port) + 1); - str = position; - } - if (direction == n->direction) { - if (is_device) { - pw_properties_set(new, PW_KEY_PORT_PHYSICAL, "true"); - pw_properties_set(new, PW_KEY_PORT_TERMINAL, "true"); - } - } - - desc = pw_properties_get(n->props, PW_KEY_NODE_DESCRIPTION); - nick = pw_properties_get(n->props, PW_KEY_NODE_NICK); - name = pw_properties_get(n->props, PW_KEY_NODE_NAME); - - if ((node_name = desc) == NULL && (node_name = nick) == NULL && - (node_name = name) == NULL) - node_name = "node"; - - pw_properties_setf(new, PW_KEY_OBJECT_PATH, "%s:%s_%d", - path ? path : node_name, prefix, pw_impl_port_get_id(port)); - - no_device_port_prefix = is_device && !is_monitor - && override_device_prefix != NULL && strlen(override_device_prefix) == 0; - - if (is_control) - pw_properties_setf(new, PW_KEY_PORT_NAME, "%s", prefix); - else if (no_device_port_prefix) - pw_properties_setf(new, PW_KEY_PORT_NAME, "%s", str); - else - pw_properties_setf(new, PW_KEY_PORT_NAME, "%s_%s", prefix, str); - - if ((node_name = nick) == NULL && (node_name = desc) == NULL && - (node_name = name) == NULL) - node_name = "node"; - - if (is_control) - pw_properties_setf(new, PW_KEY_PORT_ALIAS, "%s:%s", - node_name, prefix); - else - pw_properties_setf(new, PW_KEY_PORT_ALIAS, "%s:%s_%s", - node_name, prefix, str); - - prop_port_names = pw_properties_get(n->props, PW_KEY_NODE_CHANNELNAMES); - if (prop_port_names) { - struct spa_json it[2]; - char v[256]; - - spa_json_init(&it[0], prop_port_names, strlen(prop_port_names)); - if (spa_json_enter_array(&it[0], &it[1]) <= 0) - spa_json_init(&it[1], prop_port_names, strlen(prop_port_names)); - - uint32_t i; - for (i = 0; i < pw_impl_port_get_id(port) + 1; i++) - if (spa_json_get_string(&it[1], v, sizeof(v)) <= 0) - break; - - if (i == pw_impl_port_get_id(port) + 1 && strlen(v) > 0) { - if (no_device_port_prefix) { - pw_properties_setf(new, PW_KEY_PORT_NAME, "%s", v); - } else { - pw_properties_setf(new, PW_KEY_PORT_NAME, "%s_%s", prefix, v); - } - } - } - - pw_impl_port_update_properties(port, &new->dict); - pw_properties_free(new); -} - static const struct pw_impl_node_events node_events = { PW_VERSION_IMPL_NODE_EVENTS, .free = node_free, - .port_init = node_port_init, }; static int handle_node_param(struct pw_impl_node *node, const char *key, const char *value) diff --git a/src/pipewire/impl-port.c b/src/pipewire/impl-port.c index a131f9d63..249f11831 100644 --- a/src/pipewire/impl-port.c +++ b/src/pipewire/impl-port.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -953,8 +954,11 @@ int pw_impl_port_add(struct pw_impl_port *port, struct pw_impl_node *node) struct spa_list *ports; struct pw_map *portmap; struct pw_impl_port *find; - bool control; - const char *str, *dir; + bool is_control, is_network, is_monitor, is_device, is_duplex, is_virtual; + const char *media_class, *override_device_prefix, *channel_names; + const char *str, *dir, *prefix, *path, *desc, *nick, *name; + const struct pw_properties *nprops; + char position[256]; int res; if (port->node != NULL) @@ -982,43 +986,115 @@ int pw_impl_port_add(struct pw_impl_port *port, struct pw_impl_node *node) pw_impl_port_for_each_param(port, 0, SPA_PARAM_IO, 0, 0, NULL, check_param_io, port); pw_impl_port_for_each_param(port, 0, SPA_PARAM_Latency, 0, 0, NULL, process_latency_param, port); - control = PW_IMPL_PORT_IS_CONTROL(port); - if (control) { + nprops = pw_impl_node_get_properties(node); + media_class = pw_properties_get(nprops, PW_KEY_MEDIA_CLASS); + is_network = pw_properties_get_bool(nprops, PW_KEY_NODE_NETWORK, false); + + is_monitor = pw_properties_get_bool(port->properties, PW_KEY_PORT_MONITOR, false); + + is_control = PW_IMPL_PORT_IS_CONTROL(port); + if (is_control) { dir = port->direction == PW_DIRECTION_INPUT ? "control" : "notify"; pw_properties_set(port->properties, PW_KEY_PORT_CONTROL, "true"); } else { - dir = port->direction == PW_DIRECTION_INPUT ? "in" : "out"; + dir = port->direction == PW_DIRECTION_INPUT ? "in" : "out"; + } pw_properties_set(port->properties, PW_KEY_PORT_DIRECTION, dir); + if (media_class != NULL && + (strstr(media_class, "Sink") != NULL || + strstr(media_class, "Source") != NULL)) + is_device = true; + else + is_device = false; + + is_duplex = media_class != NULL && strstr(media_class, "Duplex") != NULL; + is_virtual = media_class != NULL && strstr(media_class, "Virtual") != NULL; + + override_device_prefix = pw_properties_get(nprops, PW_KEY_NODE_DEVICE_PORT_NAME_PREFIX); + + if (is_network) { + prefix = port->direction == PW_DIRECTION_INPUT ? + "send" : is_monitor ? "monitor" : "receive"; + } else if (is_duplex) { + prefix = port->direction == PW_DIRECTION_INPUT ? + "playback" : "capture"; + } else if (is_virtual) { + prefix = port->direction == PW_DIRECTION_INPUT ? + "input" : "capture"; + } else if (is_device) { + if (override_device_prefix != NULL) + prefix = is_monitor ? "monitor" : override_device_prefix; + else + prefix = port->direction == PW_DIRECTION_INPUT ? + "playback" : is_monitor ? "monitor" : "capture"; + } else { + prefix = port->direction == PW_DIRECTION_INPUT ? + "input" : is_monitor ? "monitor" : "output"; + } + + path = pw_properties_get(nprops, PW_KEY_OBJECT_PATH); + desc = pw_properties_get(nprops, PW_KEY_NODE_DESCRIPTION); + nick = pw_properties_get(nprops, PW_KEY_NODE_NICK); + name = pw_properties_get(nprops, PW_KEY_NODE_NAME); + + if (pw_properties_get(port->properties, PW_KEY_OBJECT_PATH) == NULL) { + if ((str = name) == NULL && (str = nick) == NULL && (str = desc) == NULL) + str = "node"; + + pw_properties_setf(port->properties, PW_KEY_OBJECT_PATH, "%s:%s_%d", + path ? path : str, prefix, pw_impl_port_get_id(port)); + } + + str = pw_properties_get(port->properties, PW_KEY_AUDIO_CHANNEL); + if (str == NULL || spa_streq(str, "UNK")) + snprintf(position, sizeof(position), "%d", port->port_id + 1); + else if (str != NULL) + snprintf(position, sizeof(position), "%s", str); + + channel_names = pw_properties_get(nprops, PW_KEY_NODE_CHANNELNAMES); + if (channel_names != NULL) { + struct spa_json it[2]; + char v[256]; + uint32_t i; + + spa_json_init(&it[0], channel_names, strlen(channel_names)); + if (spa_json_enter_array(&it[0], &it[1]) <= 0) + spa_json_init(&it[1], channel_names, strlen(channel_names)); + + for (i = 0; i < port->port_id + 1; i++) + if (spa_json_get_string(&it[1], v, sizeof(v)) <= 0) + break; + + if (i == port->port_id + 1 && strlen(v) > 0) + snprintf(position, sizeof(position), "%s", v); + } + if (pw_properties_get(port->properties, PW_KEY_PORT_NAME) == NULL) { - if ((str = pw_properties_get(port->properties, PW_KEY_AUDIO_CHANNEL)) != NULL && - !spa_streq(str, "UNK")) { - pw_properties_setf(port->properties, PW_KEY_PORT_NAME, "%s_%s", dir, str); - } - else { - pw_properties_setf(port->properties, PW_KEY_PORT_NAME, "%s_%d", dir, port->port_id); - } + if (is_control) + pw_properties_setf(port->properties, PW_KEY_PORT_NAME, "%s", prefix); + else if (prefix == NULL || strlen(prefix) == 0) + pw_properties_setf(port->properties, PW_KEY_PORT_NAME, "%s", position); + else + pw_properties_setf(port->properties, PW_KEY_PORT_NAME, "%s_%s", prefix, position); } if (pw_properties_get(port->properties, PW_KEY_PORT_ALIAS) == NULL) { - const struct pw_properties *nprops; - const char *node_name; + if ((str = nick) == NULL && (str = desc) == NULL && (str = name) == NULL) + str = "node"; - nprops = pw_impl_node_get_properties(node); - if ((node_name = pw_properties_get(nprops, PW_KEY_NODE_NICK)) == NULL && - (node_name = pw_properties_get(nprops, PW_KEY_NODE_DESCRIPTION)) == NULL && - (node_name = pw_properties_get(nprops, PW_KEY_NODE_NAME)) == NULL) - node_name = "node"; - - pw_properties_setf(port->properties, PW_KEY_PORT_ALIAS, "%s:%s", - node_name, - pw_properties_get(port->properties, PW_KEY_PORT_NAME)); + if (is_control) + pw_properties_setf(port->properties, PW_KEY_PORT_ALIAS, "%s:%s", + str, prefix); + else + pw_properties_setf(port->properties, PW_KEY_PORT_ALIAS, "%s:%s", + str, pw_properties_get(port->properties, PW_KEY_PORT_NAME)); } port->info.props = &port->properties->dict; - if (control) { + if (is_control) { pw_log_debug("%p: setting node control", port); } else { pw_log_debug("%p: setting mixer io", port);