acp: add min and max volume properties

This way, the min/max volume can be updated and saved in the same way as
the volume is updated.

Also add support for this in audioconvert channelmix.
This commit is contained in:
Wim Taymans 2026-06-08 16:23:10 +02:00
parent fb74ab9054
commit 1a534cd907
6 changed files with 71 additions and 0 deletions

View file

@ -2339,6 +2339,41 @@ int acp_device_set_port(struct acp_device *dev, uint32_t port_index, uint32_t fl
return res;
}
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;
if (min)
*min = volume_range[0];
if (max)
*max = volume_range[1];
return 0;
}
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;
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;
return 0;
}
int acp_device_set_volume(struct acp_device *dev, const float *volume, uint32_t n_volume)
{
pa_alsa_device *d = (pa_alsa_device*)dev;

View file

@ -303,6 +303,8 @@ int acp_device_get_soft_volume(struct acp_device *dev, float *volume, uint32_t n
int acp_device_get_volume(struct acp_device *dev, float *volume, uint32_t n_volume);
int acp_device_set_mute(struct acp_device *dev, bool mute);
int acp_device_get_mute(struct acp_device *dev, bool *mute);
int acp_device_get_volume_limit(struct acp_device *dev, float *min, float *max);
int acp_device_set_volume_limit(struct acp_device *dev, float min, float max);
typedef void (*acp_log_func) (void *data,
int level, const char *file, int line, const char *func,

View file

@ -710,6 +710,20 @@ static int apply_device_props(struct impl *this, struct acp_device *dev, struct
changed++;
}
break;
case SPA_PROP_volumeMin:
acp_device_get_volume_limit(dev, &volumes[0], &volumes[1]);
if (spa_pod_get_float(&prop->value, &volumes[0]) == 0) {
acp_device_set_volume_limit(dev, volumes[0], volumes[1]);
changed++;
}
break;
case SPA_PROP_volumeMax:
acp_device_get_volume_limit(dev, &volumes[0], &volumes[1]);
if (spa_pod_get_float(&prop->value, &volumes[1]) == 0) {
acp_device_set_volume_limit(dev, volumes[0], volumes[1]);
changed++;
}
break;
case SPA_PROP_latencyOffsetNsec:
{
int64_t latency_ns;

View file

@ -905,6 +905,8 @@ static int node_param_props(struct impl *this, uint32_t id, uint32_t index,
SPA_TYPE_Float,
p->monitor.n_volumes,
p->monitor.volumes),
SPA_PROP_volumeMin, SPA_POD_Float(p->min_volume),
SPA_PROP_volumeMax, SPA_POD_Float(p->max_volume),
0);
spa_pod_builder_prop(b, SPA_PROP_params, 0);
spa_pod_builder_push_struct(b, &f[1]);
@ -1867,6 +1869,20 @@ static int apply_props(struct impl *this, const struct spa_pod *param)
changed++;
}
break;
case SPA_PROP_volumeMin:
if (!p->lock_volumes &&
spa_pod_get_float(&prop->value, &p->min_volume) == 0) {
spa_log_debug(this->log, "%p new min-volume %f", this, p->min_volume);
changed++;
}
break;
case SPA_PROP_volumeMax:
if (!p->lock_volumes &&
spa_pod_get_float(&prop->value, &p->max_volume) == 0) {
spa_log_debug(this->log, "%p new max-volume %f", this, p->min_volume);
changed++;
}
break;
case SPA_PROP_rate:
if (spa_pod_get_double(&prop->value, &p->rate) == 0 &&
!this->rate_adjust && p->rate != 1.0) {