pulse-server: handle special device names in play/record

@DEFAULT_MONITOR@ finds the default sink but returns is_monitor true.

Always lookup the device based on the name and index. This transform
the special device names like @DEFAULT_XXX@ to the default device.

Always use the found device name as the target. Make sure to set the
CAPTURE_SINK property when dealing with a monitor.

Fixes #3284
This commit is contained in:
Wim Taymans 2023-06-11 18:33:13 +02:00
parent b52be160ab
commit 8eb6c0ec33

View file

@ -1586,6 +1586,8 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
const struct spa_pod *params[MAX_FORMATS];
uint8_t buffer[4096];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
struct pw_manager_object *o;
bool is_monitor;
props = pw_properties_copy(client->props);
if (props == NULL)
@ -1632,15 +1634,11 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
TAG_INVALID) < 0)
goto error_protocol;
}
o = find_device(client, sink_index, sink_name, true, &is_monitor);
spa_zero(fix_ss);
spa_zero(fix_map);
if (fix_format || fix_rate || fix_channels) {
struct pw_manager_object *o;
bool is_monitor;
o = find_device(client, sink_index, sink_name, true, &is_monitor);
if (o != NULL) {
if ((fix_format || fix_rate || fix_channels) && o != NULL) {
struct device_info dev_info = DEVICE_INFO_INIT(PW_DIRECTION_OUTPUT);
collect_device_info(o, NULL, &dev_info, is_monitor, &impl->defs);
fix_ss.format = fix_format ? dev_info.ss.format : 0;
@ -1648,7 +1646,6 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
fix_ss.channels = fix_channels ? dev_info.ss.channels : 0;
fix_map = dev_info.map;
}
}
if (client->version >= 13) {
if (message_get(m,
@ -1772,6 +1769,9 @@ static int do_create_playback_stream(struct client *client, uint32_t command, ui
flags |= PW_STREAM_FLAG_DONT_RECONNECT;
if (sink_name != NULL) {
if (o != NULL)
sink_name = pw_properties_get(o->props,
PW_KEY_NODE_NAME);
pw_properties_set(props,
PW_KEY_TARGET_OBJECT, sink_name);
} else if (sink_index != SPA_ID_INVALID && sink_index != 0) {
@ -1858,6 +1858,8 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
const struct spa_pod *params[MAX_FORMATS];
uint8_t buffer[4096];
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
struct pw_manager_object *o;
bool is_monitor = false;
props = pw_properties_copy(client->props);
if (props == NULL)
@ -1922,15 +1924,11 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
TAG_INVALID) < 0)
goto error_protocol;
}
o = find_device(client, source_index, source_name, false, &is_monitor);
spa_zero(fix_ss);
spa_zero(fix_map);
if (fix_format || fix_rate || fix_channels) {
struct pw_manager_object *o;
bool is_monitor;
o = find_device(client, source_index, source_name, false, &is_monitor);
if (o != NULL) {
if ((fix_format || fix_rate || fix_channels) && o != NULL) {
struct device_info dev_info = DEVICE_INFO_INIT(PW_DIRECTION_INPUT);
collect_device_info(o, NULL, &dev_info, is_monitor, &impl->defs);
fix_ss.format = fix_format ? dev_info.ss.format : 0;
@ -1938,7 +1936,6 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
fix_ss.channels = fix_channels ? dev_info.ss.channels : 0;
fix_map = dev_info.map;
}
}
if (client->version >= 22) {
if (message_get(m,
@ -2048,16 +2045,21 @@ static int do_create_record_stream(struct client *client, uint32_t command, uint
pw_properties_setf(props,
PW_KEY_TARGET_OBJECT, "%u", source_index);
} else if (source_name != NULL) {
if (o != NULL)
source_name = pw_properties_get(o->props,
PW_KEY_NODE_NAME);
if (spa_strendswith(source_name, ".monitor")) {
is_monitor = true;
pw_properties_setf(props,
PW_KEY_TARGET_OBJECT,
"%.*s", (int)strlen(source_name)-8, source_name);
pw_properties_set(props,
PW_KEY_STREAM_CAPTURE_SINK, "true");
} else {
pw_properties_set(props,
PW_KEY_TARGET_OBJECT, source_name);
}
if (is_monitor)
pw_properties_set(props,
PW_KEY_STREAM_CAPTURE_SINK, "true");
}
stream->stream = pw_stream_new(client->core, name, props);
@ -2453,6 +2455,7 @@ static struct pw_manager_object *find_device(struct client *client,
return NULL;
sink = true;
find_default = true;
monitor = true;
} else if (spa_streq(name, DEFAULT_SOURCE)) {
if (sink)
return NULL;