mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-08 13:30:08 -05:00
pulse-server: Fix missing subscription events on device port changes
When a device profile changes (e.g., Bluetooth headset switching from a2dp-sink to headset-head-unit), the active port information changes but PulseAudio compatibility layer clients don't receive the expected PA_SUBSCRIPTION_EVENT_SOURCE or PA_SUBSCRIPTION_EVENT_SINK change events. Root cause: The collect_device_info() function updates the active_port index from SPA_PARAM_Route parameters, but doesn't update the corresponding active_port_name field. When update_device_info() uses memcmp() to detect changes in the device_info structure, it compares the entire structure including active_port_name. If the pointer value doesn't change (even though the actual port changed), no change is detected, and the change_mask flag (PW_MANAGER_OBJECT_FLAG_SOURCE/SINK) is not set, preventing subscription events from being sent. Solution: After setting active_port in collect_device_info(), look up the corresponding port name from SPA_PARAM_EnumRoute parameters by matching both the port index and direction. Initialize active_port_name to NULL at the start to ensure it's always recalculated. This fix applies to all device types (Bluetooth, USB, PCI sound cards) and all profile switching scenarios, ensuring applications using the PulseAudio compatibility layer receive proper device change notifications. Tested with: - Bluetooth headset profile switching (a2dp-sink ↔ headset-head-unit) - Applications subscribing to PA_SUBSCRIPTION_MASK_SOURCE/SINK events - Verified no regression in audio initialization
This commit is contained in:
parent
fa8b0ba018
commit
23f0acfd1d
1 changed files with 25 additions and 0 deletions
|
|
@ -233,6 +233,7 @@ static void collect_device_info(struct pw_manager_object *device, struct pw_mana
|
||||||
struct device_info *dev_info, bool monitor, struct defs *defs)
|
struct device_info *dev_info, bool monitor, struct defs *defs)
|
||||||
{
|
{
|
||||||
struct pw_manager_param *p;
|
struct pw_manager_param *p;
|
||||||
|
dev_info->active_port_name = NULL;
|
||||||
|
|
||||||
if (card) {
|
if (card) {
|
||||||
spa_list_for_each(p, &card->param_list, link) {
|
spa_list_for_each(p, &card->param_list, link) {
|
||||||
|
|
@ -256,6 +257,30 @@ static void collect_device_info(struct pw_manager_object *device, struct pw_mana
|
||||||
dev_info->have_volume = true;
|
dev_info->have_volume = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Look up the port name for the active port */
|
||||||
|
if (dev_info->active_port != SPA_ID_INVALID) {
|
||||||
|
spa_list_for_each(p, &card->param_list, link) {
|
||||||
|
uint32_t index, direction;
|
||||||
|
const char *name = NULL;
|
||||||
|
|
||||||
|
if (p->id != SPA_PARAM_EnumRoute)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (spa_pod_parse_object(p->param,
|
||||||
|
SPA_TYPE_OBJECT_ParamRoute, NULL,
|
||||||
|
SPA_PARAM_ROUTE_index, SPA_POD_Int(&index),
|
||||||
|
SPA_PARAM_ROUTE_direction, SPA_POD_Id(&direction),
|
||||||
|
SPA_PARAM_ROUTE_name, SPA_POD_String(&name)) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (index == dev_info->active_port &&
|
||||||
|
direction == dev_info->direction) {
|
||||||
|
dev_info->active_port_name = name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_list_for_each(p, &device->param_list, link) {
|
spa_list_for_each(p, &device->param_list, link) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue