From 49073cf5277d73e3997d713dd9a6517ca78cb4dc Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Wed, 8 Apr 2026 13:57:55 +0200 Subject: [PATCH] port: improve parsing of passive modes Make a function to parse the passive mode and use that in ports and nodes. Improve the node passive mode parsing a little. Also make Duplex nodes follow-suspend. --- doc/dox/internals/running.dox | 13 ++++++++----- src/pipewire/impl-node.c | 28 +++++++++------------------- src/pipewire/impl-port.c | 7 +------ src/pipewire/private.h | 12 ++++++++++-- 4 files changed, 28 insertions(+), 32 deletions(-) diff --git a/doc/dox/internals/running.dox b/doc/dox/internals/running.dox index 1bf483f8a..e7ffe06db 100644 --- a/doc/dox/internals/running.dox +++ b/doc/dox/internals/running.dox @@ -44,7 +44,7 @@ wide range of use cases. # Node passive modes -A Node can have 8 passive modes, `node.passive` can be set to a comma separated list +A Node can have 10 passive modes, `node.passive` can be set to a comma separated list of the following values: - `false`, both input and output ports have `port.passive = false` @@ -56,10 +56,13 @@ of the following values: - `out-follow`, output ports have `port.passive = follow` - `follow`, input and output ports have `port.passive = follow`. This is the same as `in-follow,out-follow`. - - `follow-suspend`, input and output ports have `port.passive = follow-suspend` + - `in-follow-suspend`, input ports have `port.passive = follow-suspend` + - `out-follow-suspend`, output ports have `port.passive = follow-suspend` + - `follow-suspend`, input and output ports have `port.passive = follow-suspend`. + This is the same as `in-follow-suspend,out-follow-suspend`. -Node by default have the `false` mode but nodes with the `media.class` property -containing `Sink` or `Source` receive the `follow-suspend` mode by default. +Nodes by default have the `false` mode but nodes with the `media.class` property +containing `Sink`, `Source` or `Duplex` receive the `follow-suspend` mode by default. Unless explicitly configured, ports inherit the mode from their parent node. @@ -237,7 +240,7 @@ connected to the sink monitor ports. ``` We would like to keep the monitor stream and the ALSA sink suspended -unless something else activated the ALSA Sink: +unless something else activates the ALSA Sink: ``` diff --git a/src/pipewire/impl-node.c b/src/pipewire/impl-node.c index 12173f431..2cfb0c2c8 100644 --- a/src/pipewire/impl-node.c +++ b/src/pipewire/impl-node.c @@ -1251,36 +1251,26 @@ static void check_properties(struct pw_impl_node *node) if ((str = pw_properties_get(node->properties, PW_KEY_NODE_PASSIVE)) == NULL) { if ((str = pw_properties_get(node->properties, PW_KEY_MEDIA_CLASS)) != NULL && - (strstr(str, "/Sink") != NULL || strstr(str, "/Source") != NULL)) + (strstr(str, "/Duplex") || strstr(str, "/Sink") || strstr(str, "/Source"))) str = "follow-suspend"; else str = "false"; } while ((s = pw_split_walk(str, ",\0", &len, &state))) { - char v[16] = { 0 }; + char v[32] = { 0 }; snprintf(v, sizeof(v), "%.*s", (int)len, s); if (spa_streq(v, "out")) node->passive_mode[SPA_DIRECTION_OUTPUT] = PASSIVE_MODE_TRUE; - else if (spa_streq(v, "out-follow")) - node->passive_mode[SPA_DIRECTION_OUTPUT] = PASSIVE_MODE_FOLLOW; - else if (spa_streq(v, "in-follow")) - node->passive_mode[SPA_DIRECTION_INPUT] = PASSIVE_MODE_FOLLOW; else if (spa_streq(v, "in")) node->passive_mode[SPA_DIRECTION_INPUT] = PASSIVE_MODE_TRUE; - else if (spa_streq(v, "follow-suspend")) { - node->passive_mode[SPA_DIRECTION_INPUT] = PASSIVE_MODE_FOLLOW_SUSPEND; - node->passive_mode[SPA_DIRECTION_OUTPUT] = PASSIVE_MODE_FOLLOW_SUSPEND; - } - else if (spa_streq(v, "follow")) { - node->passive_mode[SPA_DIRECTION_INPUT] = PASSIVE_MODE_FOLLOW; - node->passive_mode[SPA_DIRECTION_OUTPUT] = PASSIVE_MODE_FOLLOW; - } - else { - node->passive_mode[SPA_DIRECTION_OUTPUT] = - node->passive_mode[SPA_DIRECTION_INPUT] = - spa_atob(v) ? PASSIVE_MODE_TRUE : PASSIVE_MODE_FALSE; - } + else if (spa_strstartswith(v, "out-")) + node->passive_mode[SPA_DIRECTION_OUTPUT] = passive_mode_from_string(v+4); + else if (spa_strstartswith(v, "in-")) + node->passive_mode[SPA_DIRECTION_INPUT] = passive_mode_from_string(v+3); + else + node->passive_mode[SPA_DIRECTION_INPUT] = + node->passive_mode[SPA_DIRECTION_OUTPUT] = passive_mode_from_string(v); } node->want_driver = pw_properties_get_bool(node->properties, PW_KEY_NODE_WANT_DRIVER, false); diff --git a/src/pipewire/impl-port.c b/src/pipewire/impl-port.c index 25dbdf718..c34060aee 100644 --- a/src/pipewire/impl-port.c +++ b/src/pipewire/impl-port.c @@ -541,12 +541,7 @@ static int check_properties(struct pw_impl_port *port) /* inherit passive state from parent node */ port->passive_mode = node->passive_mode[port->direction]; } else { - if (spa_streq(str, "follow")) { - port->passive_mode = PASSIVE_MODE_FOLLOW; - } else { - port->passive_mode = spa_atob(str) ? - PASSIVE_MODE_TRUE : PASSIVE_MODE_FALSE; - } + port->passive_mode = passive_mode_from_string(str); } if (media_class != NULL && diff --git a/src/pipewire/private.h b/src/pipewire/private.h index 612896861..dd81178ff 100644 --- a/src/pipewire/private.h +++ b/src/pipewire/private.h @@ -1000,9 +1000,17 @@ static inline const char* passive_mode_to_string(uint32_t passive_mode) return "follow"; case PASSIVE_MODE_FOLLOW_SUSPEND: return "follow"; - default: - return "unknown"; } + return "unknown"; +} + +static inline uint32_t passive_mode_from_string(const char *str) +{ + if (spa_streq(str, "follow")) + return PASSIVE_MODE_FOLLOW; + else if (spa_streq(str, "follow-suspend")) + return PASSIVE_MODE_FOLLOW_SUSPEND; + return spa_atob(str); } struct pw_control_link {