mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-12-22 08:56:59 -05:00
media-session: move profile selection to media-session
Disable automatic profile selection in the acp device Implement selection of profiles in the default-profile module
This commit is contained in:
parent
3312757706
commit
585f533d27
2 changed files with 132 additions and 59 deletions
|
|
@ -24,8 +24,8 @@ rules = [
|
||||||
#api.alsa.ignore-dB = false
|
#api.alsa.ignore-dB = false
|
||||||
#device.profile-set = "profileset-name"
|
#device.profile-set = "profileset-name"
|
||||||
#device.profile = "default profile name"
|
#device.profile = "default profile name"
|
||||||
|
api.acp.auto-profile = false
|
||||||
#api.acp.auto-port = true
|
#api.acp.auto-port = true
|
||||||
#api.acp.auto-profile = true
|
|
||||||
#device.nick = "My Device"
|
#device.nick = "My Device"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -118,38 +118,99 @@ static void add_idle_timeout(struct impl *impl)
|
||||||
pw_loop_update_timer(main_loop, impl->idle_timeout, &value, NULL, false);
|
pw_loop_update_timer(main_loop, impl->idle_timeout, &value, NULL, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t find_profile_id(struct device *dev, const char *name)
|
struct profile {
|
||||||
|
struct sm_param *p;
|
||||||
|
uint32_t index;
|
||||||
|
const char *name;
|
||||||
|
uint32_t prio;
|
||||||
|
uint32_t available;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int parse_profile(struct sm_param *p, struct profile *pr)
|
||||||
|
{
|
||||||
|
pr->p = p;
|
||||||
|
pr->prio = 0;
|
||||||
|
pr->available = SPA_PARAM_AVAILABILITY_unknown;
|
||||||
|
return spa_pod_parse_object(p->param,
|
||||||
|
SPA_TYPE_OBJECT_ParamProfile, NULL,
|
||||||
|
SPA_PARAM_PROFILE_index, SPA_POD_Int(&pr->index),
|
||||||
|
SPA_PARAM_PROFILE_name, SPA_POD_String(&pr->name),
|
||||||
|
SPA_PARAM_PROFILE_priority, SPA_POD_OPT_Int(&pr->prio),
|
||||||
|
SPA_PARAM_PROFILE_available, SPA_POD_OPT_Id(&pr->available));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_profile(struct device *dev, uint32_t index, struct profile *pr)
|
||||||
{
|
{
|
||||||
struct sm_param *p;
|
struct sm_param *p;
|
||||||
spa_list_for_each(p, &dev->obj->param_list, link) {
|
spa_list_for_each(p, &dev->obj->param_list, link) {
|
||||||
const char *n;
|
if (p->id != SPA_PARAM_EnumProfile ||
|
||||||
uint32_t id, available = SPA_PARAM_AVAILABILITY_unknown;
|
parse_profile(p, pr) < 0)
|
||||||
|
continue;
|
||||||
|
if (index == pr->index)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_current_profile(struct device *dev, struct profile *pr)
|
||||||
|
{
|
||||||
|
struct sm_param *p;
|
||||||
|
spa_list_for_each(p, &dev->obj->param_list, link) {
|
||||||
|
if (p->id == SPA_PARAM_Profile &&
|
||||||
|
parse_profile(p, pr) >= 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_best_profile(struct device *dev, struct profile *pr)
|
||||||
|
{
|
||||||
|
struct sm_param *p;
|
||||||
|
struct profile best, best_avail, best_unk, off;
|
||||||
|
|
||||||
|
spa_zero(best);
|
||||||
|
spa_zero(best_avail);
|
||||||
|
spa_zero(best_unk);
|
||||||
|
spa_zero(off);
|
||||||
|
|
||||||
|
spa_list_for_each(p, &dev->obj->param_list, link) {
|
||||||
|
struct profile t;
|
||||||
|
|
||||||
if (p->id != SPA_PARAM_EnumProfile ||
|
if (p->id != SPA_PARAM_EnumProfile ||
|
||||||
spa_pod_parse_object(p->param,
|
parse_profile(p, &t) < 0)
|
||||||
SPA_TYPE_OBJECT_ParamProfile, NULL,
|
|
||||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(&id),
|
|
||||||
SPA_PARAM_PROFILE_name, SPA_POD_String(&n),
|
|
||||||
SPA_PARAM_PROFILE_available, SPA_POD_OPT_Id(&available)) < 0) {
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (t.name && strcmp(t.name, "off") == 0) {
|
||||||
|
off = t;
|
||||||
}
|
}
|
||||||
if (available == SPA_PARAM_AVAILABILITY_no)
|
else if (t.available == SPA_PARAM_AVAILABILITY_yes) {
|
||||||
continue;
|
if (best_avail.name == NULL || t.prio > best_avail.prio)
|
||||||
if (strcmp(n, name) == 0)
|
best_avail = t;
|
||||||
return id;
|
|
||||||
}
|
}
|
||||||
return SPA_ID_INVALID;
|
else if (t.available != SPA_PARAM_AVAILABILITY_no) {
|
||||||
|
if (best_unk.name == NULL || t.prio > best_unk.prio)
|
||||||
|
best_unk = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
best = best_avail;
|
||||||
|
if (best.name == NULL)
|
||||||
|
best = best_unk;
|
||||||
|
if (best.name == NULL)
|
||||||
|
best = off;
|
||||||
|
if (best.name == NULL)
|
||||||
|
return -ENOENT;
|
||||||
|
*pr = best;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int restore_profile(struct device *dev)
|
static int find_saved_profile(struct device *dev, struct profile *pr)
|
||||||
{
|
{
|
||||||
struct spa_json it[2];
|
struct spa_json it[2];
|
||||||
struct impl *impl = dev->impl;
|
struct impl *impl = dev->impl;
|
||||||
const char *json, *value;
|
const char *json, *value;
|
||||||
int len;
|
int len;
|
||||||
uint32_t index = SPA_ID_INVALID;
|
char name[1024] = "\0";
|
||||||
char buf[1024], name[1024] = "\0";
|
struct sm_param *p;
|
||||||
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
|
|
||||||
|
|
||||||
json = pw_properties_get(impl->properties, dev->key);
|
json = pw_properties_get(impl->properties, dev->key);
|
||||||
if (json == NULL)
|
if (json == NULL)
|
||||||
|
|
@ -169,44 +230,71 @@ static int restore_profile(struct device *dev)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pw_log_debug("device %d: find profile '%s'", dev->id, name);
|
pw_log_debug("device %d: find profile '%s'", dev->id, name);
|
||||||
index = find_profile_id(dev, name);
|
|
||||||
if (index == SPA_ID_INVALID)
|
|
||||||
return -ENOENT;
|
|
||||||
|
|
||||||
pw_log_info("device %d: restore profile '%s' index %d", dev->id, name, index);
|
spa_list_for_each(p, &dev->obj->param_list, link) {
|
||||||
|
if (p->id != SPA_PARAM_EnumProfile ||
|
||||||
|
parse_profile(p, pr) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (strcmp(pr->name, name) == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_profile(struct device *dev, struct profile *pr)
|
||||||
|
{
|
||||||
|
char buf[1024];
|
||||||
|
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
|
||||||
|
|
||||||
|
pw_log_info("device %d: restore profile '%s' index %d",
|
||||||
|
dev->id, pr->name, pr->index);
|
||||||
|
|
||||||
pw_device_set_param((struct pw_device*)dev->obj->obj.proxy,
|
pw_device_set_param((struct pw_device*)dev->obj->obj.proxy,
|
||||||
SPA_PARAM_Profile, 0,
|
SPA_PARAM_Profile, 0,
|
||||||
spa_pod_builder_add_object(&b,
|
spa_pod_builder_add_object(&b,
|
||||||
SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
|
SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
|
||||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(index)));
|
SPA_PARAM_PROFILE_index, SPA_POD_Int(pr->index)));
|
||||||
dev->active_profile = index;
|
|
||||||
|
dev->active_profile = pr->index;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_profile(struct device *dev, struct sm_param *p)
|
static int handle_profile(struct device *dev)
|
||||||
{
|
{
|
||||||
struct impl *impl = dev->impl;
|
struct impl *impl = dev->impl;
|
||||||
uint32_t index;
|
struct profile pr;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
if (!dev->restored) {
|
if (dev->active_profile != SPA_ID_INVALID) {
|
||||||
restore_profile(dev);
|
/* we had a profile but it is now gone or not available,
|
||||||
dev->restored = true;
|
* try to restore a new profile */
|
||||||
} else {
|
res = find_profile(dev, dev->active_profile, &pr);
|
||||||
const char *name;
|
if (res < 0 || pr.available == SPA_PARAM_AVAILABILITY_no)
|
||||||
if ((res = spa_pod_parse_object(p->param,
|
dev->restored = false;
|
||||||
SPA_TYPE_OBJECT_ParamProfile, NULL,
|
|
||||||
SPA_PARAM_PROFILE_index, SPA_POD_Int(&index),
|
|
||||||
SPA_PARAM_PROFILE_name, SPA_POD_String(&name))) < 0) {
|
|
||||||
pw_log_warn("device %d: can't parse profile: %s", dev->id, spa_strerror(res));
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
if (dev->active_profile == index)
|
if (!dev->restored) {
|
||||||
|
/* first try to restore our saved profile */
|
||||||
|
res = find_saved_profile(dev, &pr);
|
||||||
|
if (res < 0 || pr.available == SPA_PARAM_AVAILABILITY_no)
|
||||||
|
/* it's not found or not available, try to find
|
||||||
|
* the next best profile */
|
||||||
|
res = find_best_profile(dev, &pr);
|
||||||
|
if (res >= 0) {
|
||||||
|
if (set_profile(dev, &pr) >= 0)
|
||||||
|
dev->restored = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if ((res = find_current_profile(dev, &pr)) < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (dev->active_profile == pr.index)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dev->active_profile = index;
|
dev->active_profile = pr.index;
|
||||||
pw_log_debug("device %d: current profile %d %s", dev->id, index, name);
|
pw_log_info("device %d: current profile %d %s", dev->id, pr.index, pr.name);
|
||||||
pw_properties_setf(impl->properties, dev->key, "{ \"name\": \"%s\" }", name);
|
pw_properties_setf(impl->properties, dev->key, "{ \"name\": \"%s\" }", pr.name);
|
||||||
add_idle_timeout(impl);
|
add_idle_timeout(impl);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -226,23 +314,8 @@ static void object_update(void *data)
|
||||||
strcmp(str, "bluetooth") == 0)
|
strcmp(str, "bluetooth") == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (dev->obj->obj.changed & SM_DEVICE_CHANGE_MASK_PARAMS) {
|
if (dev->obj->obj.changed & SM_DEVICE_CHANGE_MASK_PARAMS)
|
||||||
struct sm_param *p;
|
handle_profile(dev);
|
||||||
spa_list_for_each(p, &dev->obj->param_list, link) {
|
|
||||||
if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG))
|
|
||||||
spa_debug_pod(2, NULL, p->param);
|
|
||||||
|
|
||||||
switch (p->id) {
|
|
||||||
case SPA_PARAM_EnumProfile:
|
|
||||||
break;
|
|
||||||
case SPA_PARAM_Profile:
|
|
||||||
handle_profile(dev, p);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct sm_object_events object_events = {
|
static const struct sm_object_events object_events = {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue