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
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:
```

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_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);

View file

@ -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 &&

View file

@ -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 {