Rework profile/route handling

Add save property to Profile and Route params to notify the session
manager that they should be saved. Let the session manager only save
the Profile and Routes with the save flag.
Make pulse-server set the save flag on Profile and Route changes.
The result is that we can make a difference between user requested
changes and automatical changes and only remember the user preferences.
When a port changes availability, first check if we need to perform
a profile switch, if not select the new best port.
This commit is contained in:
Wim Taymans 2021-02-22 16:42:29 +01:00
parent 5ae92fd643
commit 8414092763
9 changed files with 176 additions and 105 deletions

View file

@ -320,7 +320,7 @@ static int cmd_set_profile(struct data *data, const struct command *cmd, int arg
else
index = card->active_profile_index;
return acp_card_set_profile(card, index);
return acp_card_set_profile(card, index, 0);
}
static int cmd_list_ports(struct data *data, const struct command *cmd, int argc, char *argv[])
@ -355,7 +355,7 @@ static int cmd_set_port(struct data *data, const struct command *cmd, int argc,
if (dev_id >= card->n_devices)
return -EINVAL;
return acp_device_set_port(card->devices[dev_id], port_id);
return acp_device_set_port(card->devices[dev_id], port_id, 0);
}
static int cmd_list_devices(struct data *data, const struct command *cmd, int argc, char *argv[])

View file

@ -1328,7 +1328,7 @@ static int device_enable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_device
return 0;
}
int acp_card_set_profile(struct acp_card *card, uint32_t new_index)
int acp_card_set_profile(struct acp_card *card, uint32_t new_index, uint32_t flags)
{
pa_card *impl = (pa_card *)card;
pa_alsa_mapping *am;
@ -1397,8 +1397,8 @@ int acp_card_set_profile(struct acp_card *card, uint32_t new_index)
}
}
if (op)
op->profile.flags &= ~ACP_PROFILE_ACTIVE;
np->profile.flags |= ACP_PROFILE_ACTIVE;
op->profile.flags &= ~(ACP_PROFILE_ACTIVE | ACP_PROFILE_SAVE);
np->profile.flags |= ACP_PROFILE_ACTIVE | flags;
impl->card.active_profile_index = new_index;
if (impl->events && impl->events->profile_changed)
@ -1566,7 +1566,7 @@ struct acp_card *acp_card_new(uint32_t index, const struct acp_dict *props)
profile = "off";
profile_index = acp_card_find_best_profile_index(&impl->card, profile);
acp_card_set_profile(&impl->card, profile_index);
acp_card_set_profile(&impl->card, profile_index, 0);
init_eld_ctls(impl);
@ -1744,7 +1744,7 @@ uint32_t acp_device_find_best_port_index(struct acp_device *dev, const char *nam
return ACP_INVALID_INDEX;
}
int acp_device_set_port(struct acp_device *dev, uint32_t port_index)
int acp_device_set_port(struct acp_device *dev, uint32_t port_index, uint32_t flags)
{
pa_alsa_device *d = (pa_alsa_device*)dev;
pa_card *impl = d->card;
@ -1762,9 +1762,9 @@ int acp_device_set_port(struct acp_device *dev, uint32_t port_index)
return -EINVAL;
if (old)
old->port.flags &= ~ACP_PORT_ACTIVE;
old->port.flags &= ~(ACP_PORT_ACTIVE | ACP_PORT_SAVE);
d->active_port = p;
p->port.flags |= ACP_PORT_ACTIVE;
p->port.flags |= ACP_PORT_ACTIVE | flags;
if (impl->use_ucm) {
pa_alsa_ucm_port_data *data;

View file

@ -186,6 +186,7 @@ struct acp_card_events {
struct acp_port {
uint32_t index; /**< unique index for this port */
#define ACP_PORT_ACTIVE (1<<0)
#define ACP_PORT_SAVE (1<<1) /* if the port needs saving */
uint32_t flags; /**< extra port flags */
const char *name; /**< Name of this port */
@ -229,6 +230,7 @@ struct acp_card_profile {
uint32_t index;
#define ACP_PROFILE_ACTIVE (1<<0)
#define ACP_PROFILE_OFF (1<<1) /* the Off profile */
#define ACP_PROFILE_SAVE (1<<2) /* if the profile needs saving */
uint32_t flags;
const char *name;
@ -274,10 +276,10 @@ int acp_card_poll_descriptors_revents(struct acp_card *card, struct pollfd *pfds
int acp_card_handle_events(struct acp_card *card);
uint32_t acp_card_find_best_profile_index(struct acp_card *card, const char *name);
int acp_card_set_profile(struct acp_card *card, uint32_t profile_index);
int acp_card_set_profile(struct acp_card *card, uint32_t profile_index, uint32_t flags);
uint32_t acp_device_find_best_port_index(struct acp_device *dev, const char *name);
int acp_device_set_port(struct acp_device *dev, uint32_t port_index);
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_volume(struct acp_device *dev, float *volume, uint32_t n_volume);

View file

@ -294,7 +294,7 @@ static int impl_sync(void *object, int seq)
}
static struct spa_pod *build_profile(struct spa_pod_builder *b, uint32_t id,
struct acp_card_profile *pr)
struct acp_card_profile *pr, bool current)
{
struct spa_pod_frame f[2];
uint32_t i, n_classes, n_capture = 0, n_playback = 0;
@ -345,6 +345,11 @@ static struct spa_pod *build_profile(struct spa_pod_builder *b, uint32_t id,
n_playback, playback));
}
spa_pod_builder_pop(b, &f[1]);
if (current) {
spa_pod_builder_prop(b, SPA_PARAM_PROFILE_save, 0);
spa_pod_builder_bool(b, SPA_FLAG_IS_SET(pr->flags, ACP_PROFILE_SAVE));
}
return spa_pod_builder_pop(b, &f[0]);
}
@ -438,6 +443,8 @@ static struct spa_pod *build_route(struct spa_pod_builder *b, uint32_t id,
if (profile != SPA_ID_INVALID) {
spa_pod_builder_prop(b, SPA_PARAM_ROUTE_profile, 0);
spa_pod_builder_int(b, profile);
spa_pod_builder_prop(b, SPA_PARAM_ROUTE_save, 0);
spa_pod_builder_bool(b, SPA_FLAG_IS_SET(p->flags, ACP_PORT_SAVE));
}
return spa_pod_builder_pop(b, &f[0]);
}
@ -486,7 +493,7 @@ static int impl_enum_params(void *object, int seq,
return 0;
pr = card->profiles[result.index];
param = build_profile(&b, id, pr);
param = build_profile(&b, id, pr, false);
break;
case SPA_PARAM_Profile:
@ -494,7 +501,7 @@ static int impl_enum_params(void *object, int seq,
return 0;
pr = card->profiles[card->active_profile_index];
param = build_profile(&b, id, pr);
param = build_profile(&b, id, pr, true);
break;
case SPA_PARAM_EnumRoute:
@ -600,16 +607,18 @@ static int impl_set_param(void *object,
case SPA_PARAM_Profile:
{
uint32_t id;
bool save = false;
if ((res = spa_pod_parse_object(param,
SPA_TYPE_OBJECT_ParamProfile, NULL,
SPA_PARAM_PROFILE_index, SPA_POD_Int(&id))) < 0) {
SPA_PARAM_PROFILE_index, SPA_POD_Int(&id),
SPA_PARAM_PROFILE_save, SPA_POD_OPT_Bool(&save))) < 0) {
spa_log_warn(this->log, "can't parse profile");
spa_debug_pod(0, NULL, param);
return res;
}
res = acp_card_set_profile(this->card, id);
res = acp_card_set_profile(this->card, id, save ? ACP_PROFILE_SAVE : 0);
emit_info(this, false);
break;
}
@ -618,12 +627,14 @@ static int impl_set_param(void *object,
uint32_t id, device;
struct spa_pod *props = NULL;
struct acp_device *dev;
bool save = false;
if ((res = spa_pod_parse_object(param,
SPA_TYPE_OBJECT_ParamRoute, NULL,
SPA_PARAM_ROUTE_index, SPA_POD_Int(&id),
SPA_PARAM_ROUTE_device, SPA_POD_Int(&device),
SPA_PARAM_ROUTE_props, SPA_POD_OPT_Pod(&props))) < 0) {
SPA_PARAM_ROUTE_props, SPA_POD_OPT_Pod(&props),
SPA_PARAM_ROUTE_save, SPA_POD_OPT_Bool(&save))) < 0) {
spa_log_warn(this->log, "can't parse route");
spa_debug_pod(0, NULL, param);
return res;
@ -632,7 +643,7 @@ static int impl_set_param(void *object,
return -EINVAL;
dev = this->card->devices[device];
res = acp_device_set_port(dev, id);
res = acp_device_set_port(dev, id, save ? ACP_PORT_SAVE : 0);
if (props)
apply_device_props(this, dev, props);
emit_info(this, false);
@ -712,7 +723,7 @@ static void card_profile_available(void *data, uint32_t index,
if (this->props.auto_profile) {
uint32_t best = acp_card_find_best_profile_index(card, NULL);
acp_card_set_profile(card, best);
acp_card_set_profile(card, best, 0);
}
}
@ -755,7 +766,7 @@ static void card_port_available(void *data, uint32_t index,
continue;
best = acp_device_find_best_port_index(d, NULL);
acp_device_set_port(d, best);
acp_device_set_port(d, best, 0);
}
}
}