mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-02-12 04:28:02 -05:00
bluez5: handle BAP device set volume change notifications
Update volume state on device set volume notifications. When one device sends volume notification, CAP specifies volume on other devices shall be synchronized too.
This commit is contained in:
parent
260e8261d5
commit
c96e58af01
2 changed files with 54 additions and 1 deletions
|
|
@ -3813,7 +3813,8 @@ static int transport_update_props(struct spa_bt_transport *transport,
|
|||
t_volume->active = true;
|
||||
t_volume->new_hw_volume = value;
|
||||
|
||||
if (transport->profile & SPA_BT_PROFILE_A2DP_SINK)
|
||||
if ((transport->profile & SPA_BT_PROFILE_A2DP_SINK) ||
|
||||
((transport->profile & SPA_BT_PROFILE_BAP_DUPLEX) && transport->bap_initiator))
|
||||
spa_bt_transport_start_volume_timer(transport);
|
||||
else
|
||||
spa_bt_transport_volume_changed(transport);
|
||||
|
|
|
|||
|
|
@ -910,6 +910,55 @@ static void device_set_clear(struct impl *impl, struct device_set *set)
|
|||
set->source[i].impl = impl;
|
||||
}
|
||||
|
||||
static void device_set_volume_changed(void *data)
|
||||
{
|
||||
struct device_set_member *member = data;
|
||||
struct impl *impl = member->impl;
|
||||
struct device_set *dset = &impl->device_set;
|
||||
bool sink = (member->id & SINK_ID_FLAG);
|
||||
int id = sink ? DEVICE_ID_SINK_SET : DEVICE_ID_SOURCE_SET;
|
||||
struct node *node = &impl->nodes[id];
|
||||
int volume_id = get_volume_id(member->id);
|
||||
struct device_set_member *members = sink ? dset->sink : dset->source;
|
||||
uint32_t n_members = sink ? dset->sinks : dset->sources;
|
||||
struct spa_bt_transport_volume *t_volume;
|
||||
float prev_hw_volume;
|
||||
unsigned int i;
|
||||
|
||||
if (!node->active || !spa_bt_transport_volume_enabled(member->transport))
|
||||
return;
|
||||
|
||||
t_volume = &member->transport->volumes[volume_id];
|
||||
if (!t_volume->active)
|
||||
return;
|
||||
|
||||
spa_log_debug(impl->log, "%p device set changed hw volume %d %f", impl, volume_id, t_volume->volume);
|
||||
|
||||
prev_hw_volume = node_get_hw_volume(node);
|
||||
|
||||
for (uint32_t i = 0; i < node->n_channels; ++i) {
|
||||
node->volumes[i] = prev_hw_volume > 0.0f
|
||||
? node->volumes[i] * t_volume->volume / prev_hw_volume
|
||||
: t_volume->volume;
|
||||
}
|
||||
|
||||
/* CAP v1.0.1 7.3.2.2: spread hw volume to other devices in set */
|
||||
if (member->transport->bap_initiator) {
|
||||
for (i = 0; i < n_members; ++i)
|
||||
spa_bt_transport_set_volume(members[i].transport, volume_id, t_volume->volume);
|
||||
}
|
||||
|
||||
node_update_soft_volumes(node, t_volume->volume);
|
||||
|
||||
node->save = true;
|
||||
|
||||
emit_volume(impl, node);
|
||||
|
||||
impl->info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
|
||||
impl->params[IDX_Route].flags ^= SPA_PARAM_INFO_SERIAL;
|
||||
emit_info(impl, false);
|
||||
}
|
||||
|
||||
static void device_set_transport_destroy(void *data)
|
||||
{
|
||||
struct device_set_member *member = data;
|
||||
|
|
@ -921,6 +970,7 @@ static void device_set_transport_destroy(void *data)
|
|||
static const struct spa_bt_transport_events device_set_transport_events = {
|
||||
SPA_VERSION_BT_DEVICE_EVENTS,
|
||||
.destroy = device_set_transport_destroy,
|
||||
.volume_changed = device_set_volume_changed,
|
||||
};
|
||||
|
||||
static void device_set_update_asha(struct impl *this, struct device_set *dset)
|
||||
|
|
@ -2840,6 +2890,8 @@ static void device_set_update_volumes(struct node *node)
|
|||
goto soft_volume;
|
||||
}
|
||||
|
||||
spa_log_info(impl->log, "%p device set set hw volume %d %f", impl, volume_id, hw_volume);
|
||||
|
||||
node_update_soft_volumes(node, hw_volume);
|
||||
for (i = 0; i < n_members; ++i)
|
||||
spa_bt_transport_set_volume(members[i].transport, volume_id, hw_volume);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue