acp: remove the soft volume/mute events

Remove the soft mute/volume events, add a new method to get the soft
volume and use the volume_changed event to emit the changed soft and
monitor (real) volumes event for the node.

Make sure the monitor ports always uses the monitor volume, which is the
real volume unaffected by the mixer volumes.

This configures the soft and real volume on the sink/source in all
cases and makes the monitor port follow the real volume of the sink.

See #897
This commit is contained in:
Wim Taymans 2021-03-21 16:19:57 +01:00
parent 3bce026d67
commit 5cddd61c6c
4 changed files with 42 additions and 54 deletions

View file

@ -1043,7 +1043,6 @@ static int read_volume(pa_alsa_device *dev)
static void set_volume(pa_alsa_device *dev, const pa_cvolume *v)
{
pa_card *impl = dev->card;
pa_cvolume r;
dev->real_volume = *v;
@ -1083,18 +1082,7 @@ static void set_volume(pa_alsa_device *dev, const pa_cvolume *v)
if (accurate_enough)
pa_cvolume_reset(&new_soft_volume, new_soft_volume.channels);
if (!pa_cvolume_equal(&dev->soft_volume, &new_soft_volume)) {
dev->soft_volume = new_soft_volume;
if (impl->events && impl->events->set_soft_volume) {
uint32_t i, n_volumes = new_soft_volume.channels;
float volumes[n_volumes];
for (i = 0; i < n_volumes; i++)
volumes[i] = pa_sw_volume_to_linear(new_soft_volume.values[i]);
impl->events->set_soft_volume(impl->user_data, &dev->device, volumes, n_volumes);
}
}
dev->soft_volume = new_soft_volume;
} else {
pa_log_debug("Wrote hardware volume: %d", pa_cvolume_max(&r));
/* We can't match exactly what the user requested, hence let's
@ -1823,8 +1811,6 @@ int acp_device_set_volume(struct acp_device *dev, const float *volume, uint32_t
} else {
d->real_volume = v;
d->soft_volume = v;
if (impl->events && impl->events->set_soft_volume)
impl->events->set_soft_volume(impl->user_data, dev, volume, n_volume);
}
if (!pa_cvolume_equal(&d->real_volume, &old_volume))
if (impl->events && impl->events->volume_changed)
@ -1832,17 +1818,26 @@ int acp_device_set_volume(struct acp_device *dev, const float *volume, uint32_t
return 0;
}
static int get_volume(pa_cvolume *v, float *volume, uint32_t n_volume)
{
uint32_t i;
if (v->channels == 0)
return -EIO;
for (i = 0; i < n_volume; i++)
volume[i] = pa_sw_volume_to_linear(v->values[i % v->channels]);
return 0;
}
int acp_device_get_soft_volume(struct acp_device *dev, float *volume, uint32_t n_volume)
{
pa_alsa_device *d = (pa_alsa_device*)dev;
return get_volume(&d->soft_volume, volume, n_volume);
}
int acp_device_get_volume(struct acp_device *dev, float *volume, uint32_t n_volume)
{
pa_alsa_device *d = (pa_alsa_device*)dev;
pa_cvolume v;
uint32_t i;
v = d->real_volume;
if (v.channels == 0)
return -EIO;
for (i = 0; i < n_volume; i++)
volume[i] = pa_sw_volume_to_linear(v.values[i % v.channels]);
return 0;
return get_volume(&d->real_volume, volume, n_volume);
}
int acp_device_set_mute(struct acp_device *dev, bool mute)
@ -1860,8 +1855,6 @@ int acp_device_set_mute(struct acp_device *dev, bool mute)
d->set_mute(d, mute);
} else {
d->muted = mute;
if (impl->events && impl->events->set_soft_mute)
impl->events->set_soft_mute(impl->user_data, dev, mute);
}
if (old_muted != mute)
if (impl->events && impl->events->mute_changed)

View file

@ -177,10 +177,6 @@ struct acp_card_events {
void (*volume_changed) (void *data, struct acp_device *dev);
void (*mute_changed) (void *data, struct acp_device *dev);
void (*set_soft_volume) (void *data, struct acp_device *dev,
const float *volume, uint32_t n_volume);
void (*set_soft_mute) (void *data, struct acp_device *dev, bool mute);
};
struct acp_port {
@ -282,6 +278,7 @@ uint32_t acp_device_find_best_port_index(struct acp_device *dev, const char *nam
int acp_device_set_port(struct acp_device *dev, uint32_t port_index, uint32_t flags);
int acp_device_set_volume(struct acp_device *dev, const float *volume, uint32_t n_volume);
int acp_device_get_soft_volume(struct acp_device *dev, float *volume, uint32_t n_volume);
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);

View file

@ -778,31 +778,24 @@ static void card_port_available(void *data, uint32_t index,
}
static void on_volume_changed(void *data, struct acp_device *dev)
{
struct impl *this = data;
spa_log_info(this->log, "device %s volume changed", dev->name);
this->info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
this->params[IDX_Route].user++;
}
static void on_mute_changed(void *data, struct acp_device *dev)
{
struct impl *this = data;
spa_log_info(this->log, "device %s mute changed", dev->name);
this->info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
this->params[IDX_Route].user++;
}
static void on_set_soft_volume(void *data, struct acp_device *dev,
const float *volume, uint32_t n_volume)
{
struct impl *this = data;
struct spa_event *event;
uint8_t buffer[4096];
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[1];
uint32_t n_volume = dev->format.channels;
float volume[n_volume];
float mon_volume[n_volume];
spa_log_info(this->log, "device %s soft volume %f", dev->name, volume[0]);
spa_log_info(this->log, "device %s volume changed", dev->name);
this->info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
this->params[IDX_Route].user++;
spa_zero(volume);
spa_zero(mon_volume);
acp_device_get_soft_volume(dev, volume, n_volume);
acp_device_get_volume(dev, mon_volume, n_volume);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_push_object(&b, &f[0],
@ -814,6 +807,8 @@ static void on_set_soft_volume(void *data, struct acp_device *dev,
SPA_TYPE_OBJECT_Props, SPA_EVENT_DEVICE_Props,
SPA_PROP_channelVolumes, SPA_POD_Array(sizeof(float),
SPA_TYPE_Float, n_volume, volume),
SPA_PROP_monitorVolumes, SPA_POD_Array(sizeof(float),
SPA_TYPE_Float, n_volume, mon_volume),
SPA_PROP_channelMap, SPA_POD_Array(sizeof(uint32_t),
SPA_TYPE_Id, dev->format.channels,
dev->format.map));
@ -822,16 +817,20 @@ static void on_set_soft_volume(void *data, struct acp_device *dev,
spa_device_emit_event(&this->hooks, event);
}
static void on_set_soft_mute(void *data, struct acp_device *dev,
bool mute)
static void on_mute_changed(void *data, struct acp_device *dev)
{
struct impl *this = data;
struct spa_event *event;
uint8_t buffer[4096];
struct spa_pod_builder b = { 0 };
struct spa_pod_frame f[1];
bool mute;
spa_log_info(this->log, "device %s soft mute %d", dev->name, mute);
spa_log_info(this->log, "device %s mute changed", dev->name);
this->info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS;
this->params[IDX_Route].user++;
acp_device_get_mute(dev, &mute);
spa_pod_builder_init(&b, buffer, sizeof(buffer));
spa_pod_builder_push_object(&b, &f[0],
@ -842,7 +841,8 @@ static void on_set_soft_mute(void *data, struct acp_device *dev,
spa_pod_builder_add_object(&b,
SPA_TYPE_OBJECT_Props, SPA_EVENT_DEVICE_Props,
SPA_PROP_mute, SPA_POD_Bool(mute));
SPA_PROP_mute, SPA_POD_Bool(mute),
SPA_PROP_monitorMute, SPA_POD_Bool(mute));
event = spa_pod_builder_pop(&b, &f[0]);
spa_device_emit_event(&this->hooks, event);
@ -857,8 +857,6 @@ struct acp_card_events card_events = {
.port_available = card_port_available,
.volume_changed = on_volume_changed,
.mute_changed = on_mute_changed,
.set_soft_volume = on_set_soft_volume,
.set_soft_mute = on_set_soft_mute,
};
static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface)

View file

@ -1344,7 +1344,7 @@ impl_init(const struct spa_handle_factory *factory,
if (this->cpu)
this->cpu_flags = spa_cpu_get_flags(this->cpu);
this->monitor_channel_volumes = true;
this->monitor_channel_volumes = false;
if (info) {
if ((str = spa_dict_lookup(info, "monitor.channel-volumes")) != NULL)
this->monitor_channel_volumes = strcmp(str, "true") == 0 || atoi(str) == 1;