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.
This commit is contained in:
Wim Taymans 2026-04-08 13:57:55 +02:00
parent 446e36807f
commit 49073cf527
4 changed files with 28 additions and 32 deletions

View file

@ -44,7 +44,7 @@ wide range of use cases.
# Node passive modes # 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: of the following values:
- `false`, both input and output ports have `port.passive = false` - `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` - `out-follow`, output ports have `port.passive = follow`
- `follow`, input and output ports have `port.passive = follow`. This is the same - `follow`, input and output ports have `port.passive = follow`. This is the same
as `in-follow,out-follow`. 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 Nodes by default have the `false` mode but nodes with the `media.class` property
containing `Sink` or `Source` receive the `follow-suspend` mode by default. containing `Sink`, `Source` or `Duplex` receive the `follow-suspend` mode by default.
Unless explicitly configured, ports inherit the mode from their parent node. 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 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:
``` ```

View file

@ -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_NODE_PASSIVE)) == NULL) {
if ((str = pw_properties_get(node->properties, PW_KEY_MEDIA_CLASS)) != 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"; str = "follow-suspend";
else else
str = "false"; str = "false";
} }
while ((s = pw_split_walk(str, ",\0", &len, &state))) { 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); snprintf(v, sizeof(v), "%.*s", (int)len, s);
if (spa_streq(v, "out")) if (spa_streq(v, "out"))
node->passive_mode[SPA_DIRECTION_OUTPUT] = PASSIVE_MODE_TRUE; 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")) else if (spa_streq(v, "in"))
node->passive_mode[SPA_DIRECTION_INPUT] = PASSIVE_MODE_TRUE; node->passive_mode[SPA_DIRECTION_INPUT] = PASSIVE_MODE_TRUE;
else if (spa_streq(v, "follow-suspend")) { else if (spa_strstartswith(v, "out-"))
node->passive_mode[SPA_DIRECTION_INPUT] = PASSIVE_MODE_FOLLOW_SUSPEND; node->passive_mode[SPA_DIRECTION_OUTPUT] = passive_mode_from_string(v+4);
node->passive_mode[SPA_DIRECTION_OUTPUT] = PASSIVE_MODE_FOLLOW_SUSPEND; else if (spa_strstartswith(v, "in-"))
} node->passive_mode[SPA_DIRECTION_INPUT] = passive_mode_from_string(v+3);
else if (spa_streq(v, "follow")) { else
node->passive_mode[SPA_DIRECTION_INPUT] = PASSIVE_MODE_FOLLOW; node->passive_mode[SPA_DIRECTION_INPUT] =
node->passive_mode[SPA_DIRECTION_OUTPUT] = PASSIVE_MODE_FOLLOW; node->passive_mode[SPA_DIRECTION_OUTPUT] = passive_mode_from_string(v);
}
else {
node->passive_mode[SPA_DIRECTION_OUTPUT] =
node->passive_mode[SPA_DIRECTION_INPUT] =
spa_atob(v) ? PASSIVE_MODE_TRUE : PASSIVE_MODE_FALSE;
}
} }
node->want_driver = pw_properties_get_bool(node->properties, PW_KEY_NODE_WANT_DRIVER, false); node->want_driver = pw_properties_get_bool(node->properties, PW_KEY_NODE_WANT_DRIVER, false);

View file

@ -541,12 +541,7 @@ static int check_properties(struct pw_impl_port *port)
/* inherit passive state from parent node */ /* inherit passive state from parent node */
port->passive_mode = node->passive_mode[port->direction]; port->passive_mode = node->passive_mode[port->direction];
} else { } else {
if (spa_streq(str, "follow")) { port->passive_mode = passive_mode_from_string(str);
port->passive_mode = PASSIVE_MODE_FOLLOW;
} else {
port->passive_mode = spa_atob(str) ?
PASSIVE_MODE_TRUE : PASSIVE_MODE_FALSE;
}
} }
if (media_class != NULL && if (media_class != NULL &&

View file

@ -1000,9 +1000,17 @@ static inline const char* passive_mode_to_string(uint32_t passive_mode)
return "follow"; return "follow";
case PASSIVE_MODE_FOLLOW_SUSPEND: case PASSIVE_MODE_FOLLOW_SUSPEND:
return "follow"; 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 { struct pw_control_link {