mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-06-09 03:01:53 -04:00
acp: make hard and soft volume limit
Make a hard volume limit property that is configured with the config and can never be changed. Make a soft volume limit property that can be changed at runtime. The used volume limit is a combination of the soft and hard limit.
This commit is contained in:
parent
1a534cd907
commit
64d3ed4710
4 changed files with 53 additions and 43 deletions
|
|
@ -644,51 +644,53 @@ static void add_profiles(pa_card *impl)
|
|||
|
||||
snprintf(name, sizeof(name), "api.acp.port.%s.min-volume", dp->name);
|
||||
if ((str = pa_proplist_gets(impl->proplist, name)))
|
||||
spa_atof(str, &dp->volume_range[0]);
|
||||
spa_atof(str, &dp->hard_volume_limit[0]);
|
||||
else
|
||||
dp->volume_range[0] = impl->volume_range[0];
|
||||
dp->hard_volume_limit[0] = impl->hard_volume_limit[0];
|
||||
|
||||
snprintf(name, sizeof(name), "api.acp.port.%s.max-volume", dp->name);
|
||||
if ((str = pa_proplist_gets(impl->proplist, name)))
|
||||
spa_atof(str, &dp->volume_range[1]);
|
||||
spa_atof(str, &dp->hard_volume_limit[1]);
|
||||
else
|
||||
dp->volume_range[1] = impl->volume_range[1];
|
||||
dp->hard_volume_limit[1] = impl->hard_volume_limit[1];
|
||||
|
||||
dp->soft_volume_limit[0] = dp->hard_volume_limit[0];
|
||||
dp->soft_volume_limit[1] = dp->hard_volume_limit[1];
|
||||
pa_proplist_setf(dp->proplist, "card.profile.port", "%u", dp->port.index);
|
||||
pa_proplist_as_dict(dp->proplist, &dp->port.props);
|
||||
pa_dynarray_append(&impl->out.ports, dp);
|
||||
}
|
||||
PA_DYNARRAY_FOREACH(dev, &impl->out.devices, idx) {
|
||||
float vol_range[2] = { 0.0f, FLT_MAX };
|
||||
float vol_limit[2] = { 0.0f, FLT_MAX };
|
||||
n_ports = 0;
|
||||
|
||||
snprintf(name, sizeof(name), "api.acp.device.%s.min-volume", dev->device.name);
|
||||
if ((str = pa_proplist_gets(impl->proplist, name)))
|
||||
spa_atof(str, &vol_range[0]);
|
||||
spa_atof(str, &vol_limit[0]);
|
||||
else
|
||||
vol_range[0] = impl->volume_range[0];
|
||||
vol_limit[0] = impl->hard_volume_limit[0];
|
||||
|
||||
snprintf(name, sizeof(name), "api.acp.device.%s.max-volume", dev->device.name);
|
||||
if ((str = pa_proplist_gets(impl->proplist, name)))
|
||||
spa_atof(str, &vol_range[1]);
|
||||
spa_atof(str, &vol_limit[1]);
|
||||
else
|
||||
vol_range[1] = impl->volume_range[1];
|
||||
vol_limit[1] = impl->hard_volume_limit[1];
|
||||
|
||||
PA_HASHMAP_FOREACH(dp, dev->ports, state) {
|
||||
if (n_ports == 0) {
|
||||
vol_range[0] = dp->volume_range[0];
|
||||
vol_range[1] = dp->volume_range[1];
|
||||
vol_limit[0] = dp->hard_volume_limit[0];
|
||||
vol_limit[1] = dp->hard_volume_limit[1];
|
||||
} else {
|
||||
vol_range[0] = fminf(vol_range[0], dp->volume_range[0]);
|
||||
vol_range[1] = fmaxf(vol_range[1], dp->volume_range[1]);
|
||||
vol_limit[0] = fminf(vol_limit[0], dp->hard_volume_limit[0]);
|
||||
vol_limit[1] = fmaxf(vol_limit[1], dp->hard_volume_limit[1]);
|
||||
}
|
||||
pa_dynarray_append(&dev->port_array, dp);
|
||||
pa_dynarray_append(&dp->devices, dev);
|
||||
n_ports++;
|
||||
}
|
||||
if (n_ports == 0) {
|
||||
pa_proplist_setf(dev->proplist, "channelmix.min-volume", "%f", vol_range[0]);
|
||||
pa_proplist_setf(dev->proplist, "channelmix.max-volume", "%f", vol_range[1]);
|
||||
pa_proplist_setf(dev->proplist, "channelmix.min-volume", "%f", vol_limit[0]);
|
||||
pa_proplist_setf(dev->proplist, "channelmix.max-volume", "%f", vol_limit[1]);
|
||||
}
|
||||
pa_proplist_as_dict(dev->proplist, &dev->device.props);
|
||||
|
||||
|
|
@ -1990,8 +1992,8 @@ struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props)
|
|||
impl->ignore_dB = false;
|
||||
impl->rate = DEFAULT_RATE;
|
||||
impl->pro_channels = DEFAULT_CHANNELS;
|
||||
impl->volume_range[0] = 0.0f;
|
||||
impl->volume_range[1] = FLT_MAX;
|
||||
impl->hard_volume_limit[0] = 0.0f;
|
||||
impl->hard_volume_limit[1] = FLT_MAX;
|
||||
|
||||
if (props) {
|
||||
if ((s = acp_dict_lookup(props, "api.alsa.use-ucm")) != NULL)
|
||||
|
|
@ -2021,9 +2023,9 @@ struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props)
|
|||
if ((s = acp_dict_lookup(props, "api.acp.use-eld-channels")) != NULL)
|
||||
impl->use_eld_channels = spa_atob(s);
|
||||
if ((s = acp_dict_lookup(props, "api.acp.min-volume")) != NULL)
|
||||
spa_atof(s, &impl->volume_range[0]);
|
||||
spa_atof(s, &impl->hard_volume_limit[0]);
|
||||
if ((s = acp_dict_lookup(props, "api.acp.max-volume")) != NULL)
|
||||
spa_atof(s, &impl->volume_range[1]);
|
||||
spa_atof(s, &impl->hard_volume_limit[1]);
|
||||
}
|
||||
|
||||
#if SND_LIB_VERSION < 0x10207
|
||||
|
|
@ -2344,17 +2346,19 @@ int acp_device_get_volume_limit(struct acp_device *dev, float *min, float *max)
|
|||
pa_alsa_device *d = (pa_alsa_device*)dev;
|
||||
pa_card *impl = d->card;
|
||||
pa_device_port *p;
|
||||
float *volume_range;
|
||||
|
||||
if ((p = d->active_port) != NULL)
|
||||
volume_range = p->volume_range;
|
||||
else
|
||||
volume_range = impl->volume_range;
|
||||
float *soft_volume_limit, *hard_volume_limit;
|
||||
|
||||
if ((p = d->active_port) != NULL) {
|
||||
soft_volume_limit = p->soft_volume_limit;
|
||||
hard_volume_limit = p->hard_volume_limit;
|
||||
} else {
|
||||
soft_volume_limit = impl->hard_volume_limit;
|
||||
hard_volume_limit = impl->hard_volume_limit;
|
||||
}
|
||||
if (min)
|
||||
*min = volume_range[0];
|
||||
*min = fmaxf(soft_volume_limit[0], hard_volume_limit[0]);
|
||||
if (max)
|
||||
*max = volume_range[1];
|
||||
*max = fminf(soft_volume_limit[1], hard_volume_limit[1]);
|
||||
return 0;
|
||||
}
|
||||
int acp_device_set_volume_limit(struct acp_device *dev, float min, float max)
|
||||
|
|
@ -2362,15 +2366,18 @@ int acp_device_set_volume_limit(struct acp_device *dev, float min, float max)
|
|||
pa_alsa_device *d = (pa_alsa_device*)dev;
|
||||
pa_card *impl = d->card;
|
||||
pa_device_port *p;
|
||||
float *volume_range;
|
||||
float *soft_volume_limit, *hard_volume_limit;
|
||||
|
||||
if ((p = d->active_port) != NULL)
|
||||
volume_range = p->volume_range;
|
||||
else
|
||||
volume_range = impl->volume_range;
|
||||
|
||||
volume_range[0] = min;
|
||||
volume_range[1] = max;
|
||||
if ((p = d->active_port) != NULL) {
|
||||
soft_volume_limit = p->soft_volume_limit;
|
||||
hard_volume_limit = p->hard_volume_limit;
|
||||
}
|
||||
else {
|
||||
soft_volume_limit = impl->hard_volume_limit;
|
||||
hard_volume_limit = impl->hard_volume_limit;
|
||||
}
|
||||
soft_volume_limit[0] = fmaxf(min, hard_volume_limit[0]);
|
||||
soft_volume_limit[1] = fminf(max, hard_volume_limit[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -2381,7 +2388,7 @@ int acp_device_set_volume(struct acp_device *dev, const float *volume, uint32_t
|
|||
uint32_t i;
|
||||
pa_cvolume v, old_volume;
|
||||
pa_device_port *p;
|
||||
float *volume_range;
|
||||
float *volume_limit;
|
||||
|
||||
if (n_volume == 0)
|
||||
return -EINVAL;
|
||||
|
|
@ -2389,14 +2396,14 @@ int acp_device_set_volume(struct acp_device *dev, const float *volume, uint32_t
|
|||
old_volume = d->real_volume;
|
||||
|
||||
if ((p = d->active_port) != NULL)
|
||||
volume_range = p->volume_range;
|
||||
volume_limit = p->soft_volume_limit;
|
||||
else
|
||||
volume_range = impl->volume_range;
|
||||
volume_limit = impl->hard_volume_limit;
|
||||
|
||||
v.channels = d->mapping->channel_map.channels;
|
||||
for (i = 0; i < v.channels; i++)
|
||||
v.values[i] = pa_sw_volume_from_linear(
|
||||
SPA_CLAMPF(volume[i % n_volume], volume_range[0], volume_range[1]));
|
||||
SPA_CLAMPF(volume[i % n_volume], volume_limit[0], volume_limit[1]));
|
||||
|
||||
pa_log_info("Set %s volume: min:%d max:%d",
|
||||
d->set_volume ? "hardware" : "software",
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ struct pa_card {
|
|||
bool use_eld_channels;
|
||||
uint32_t rate;
|
||||
uint32_t pro_channels;
|
||||
float volume_range[2];
|
||||
float hard_volume_limit[2];
|
||||
|
||||
pa_alsa_ucm_config ucm;
|
||||
pa_alsa_profile_set *profile_set;
|
||||
|
|
|
|||
|
|
@ -142,8 +142,10 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si
|
|||
p->port.direction = data->direction == PA_DIRECTION_OUTPUT ?
|
||||
ACP_DIRECTION_PLAYBACK : ACP_DIRECTION_CAPTURE;
|
||||
p->type = data->type;
|
||||
p->volume_range[0] = 0.0f;
|
||||
p->volume_range[1] = FLT_MAX;
|
||||
p->hard_volume_limit[0] = 0.0f;
|
||||
p->hard_volume_limit[1] = FLT_MAX;
|
||||
p->soft_volume_limit[0] = p->hard_volume_limit[0];
|
||||
p->soft_volume_limit[1] = p->hard_volume_limit[1];
|
||||
|
||||
p->proplist = pa_proplist_new();
|
||||
pa_proplist_sets(p->proplist, ACP_KEY_PORT_TYPE, str_port_type(data->type));
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ struct pa_device_port {
|
|||
|
||||
pa_direction_t direction;
|
||||
int64_t latency_offset;
|
||||
float volume_range[2];
|
||||
float hard_volume_limit[2];
|
||||
float soft_volume_limit[2];
|
||||
|
||||
pa_proplist *proplist;
|
||||
pa_hashmap *profiles;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue