mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-03 09:01:54 -05:00
media-session: improve routing
First check all the routes to see if anything changed. If there is a change check if we need a profile switch. Then check all the active routes and restore state when they changed.
This commit is contained in:
parent
3b0fcdd525
commit
ab45b16a05
1 changed files with 72 additions and 46 deletions
|
|
@ -140,9 +140,9 @@ struct route_info {
|
||||||
uint32_t available;
|
uint32_t available;
|
||||||
enum spa_direction direction;
|
enum spa_direction direction;
|
||||||
char name[64];
|
char name[64];
|
||||||
unsigned int restore:1;
|
|
||||||
unsigned int save:1;
|
unsigned int save:1;
|
||||||
unsigned int valid:1;
|
unsigned int prev_active:1;
|
||||||
|
unsigned int active:1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct route {
|
struct route {
|
||||||
|
|
@ -175,13 +175,12 @@ static struct route_info *find_route_info(struct device *dev, struct route *r)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
pw_log_info("device %d: new route %d '%s' found", dev->id, r->index, r->name);
|
pw_log_info("device %d: new route %d '%s' found", dev->id, r->index, r->name);
|
||||||
|
spa_zero(*i);
|
||||||
i->index = r->index;
|
i->index = r->index;
|
||||||
snprintf(i->name, sizeof(i->name), "%s", r->name);
|
snprintf(i->name, sizeof(i->name), "%s", r->name);
|
||||||
i->direction = r->direction;
|
i->direction = r->direction;
|
||||||
i->generation = dev->generation;
|
i->generation = dev->generation;
|
||||||
i->available = r->available;
|
i->available = r->available;
|
||||||
i->restore = true;
|
|
||||||
i->valid = true;
|
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
@ -233,7 +232,7 @@ static int parse_enum_route(struct sm_param *p, uint32_t device_id, struct route
|
||||||
SPA_PARAM_ROUTE_devices, SPA_POD_OPT_Pod(&devices))) < 0)
|
SPA_PARAM_ROUTE_devices, SPA_POD_OPT_Pod(&devices))) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
if (!array_contains(devices, device_id))
|
if (device_id != SPA_ID_INVALID && !array_contains(devices, device_id))
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
r->device_id = device_id;
|
r->device_id = device_id;
|
||||||
|
|
@ -518,8 +517,10 @@ static int restore_route(struct device *dev, struct route *r)
|
||||||
pw_log_info("device %d: restore route %d '%s' to %s", dev->id, r->index, key, val);
|
pw_log_info("device %d: restore route %d '%s' to %s", dev->id, r->index, key, val);
|
||||||
|
|
||||||
restore_route_params(dev, val, r);
|
restore_route_params(dev, val, r);
|
||||||
|
ri->prev_active = true;
|
||||||
|
ri->active = true;
|
||||||
ri->generation = dev->generation;
|
ri->generation = dev->generation;
|
||||||
ri->restore = false;
|
ri->available = r->available;
|
||||||
ri->save = r->save;
|
ri->save = r->save;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -787,63 +788,88 @@ static int handle_route(struct device *dev, struct route *r)
|
||||||
struct route_info *ri;
|
struct route_info *ri;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
pw_log_info("device %d: port '%s'", dev->id, r->name);
|
||||||
if ((ri = find_route_info(dev, r)) == NULL)
|
if ((ri = find_route_info(dev, r)) == NULL)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
if (ri->restore) {
|
ri->active = true;
|
||||||
|
|
||||||
|
if (!ri->prev_active) {
|
||||||
/* a new port has been found, restore the volume and make sure we
|
/* a new port has been found, restore the volume and make sure we
|
||||||
* save this as a prefered port */
|
* save this as a prefered port */
|
||||||
pw_log_info("device %d: new port found '%s'", dev->id, r->name);
|
pw_log_info("device %d: new active port found '%s'", dev->id, r->name);
|
||||||
restore_route(dev, r);
|
restore_route(dev, r);
|
||||||
} else if (ri->available != r->available) {
|
} else if (ri->available != r->available && r->available != SPA_PARAM_AVAILABILITY_yes) {
|
||||||
struct profile best;
|
struct route t;
|
||||||
|
/* an existing port has changed to unavailable */
|
||||||
/* port availability changed, find new best profile and switch
|
pw_log_info("device %d: route '%s' not available", dev->id, r->name);
|
||||||
* to it when needed. */
|
/* try to find a new best port */
|
||||||
pw_log_info("device %d: route %s available changed %d -> %d",
|
res = find_best_route(dev, r->device_id, &t);
|
||||||
dev->id, r->name, ri->available, r->available);
|
if (res < 0) {
|
||||||
|
pw_log_info("device %d: can't find best route", dev->id);
|
||||||
ri->available = r->available;
|
} else {
|
||||||
|
pw_log_info("device %d: found best route '%s'", dev->id,
|
||||||
if ((res = find_best_profile(dev, &best)) < 0) {
|
t.name);
|
||||||
pw_log_info("device %d: can't find best profile", dev->id);
|
restore_route(dev, &t);
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
} else if (ri->prev_active && r->props) {
|
||||||
if (dev->active_profile != best.index) {
|
|
||||||
pw_log_info("device %d: activating best profile %s",
|
|
||||||
dev->id, best.name);
|
|
||||||
/* we need to switch profiles */
|
|
||||||
set_profile(dev, &best);
|
|
||||||
ri->valid = false;
|
|
||||||
} else if (r->available != SPA_PARAM_AVAILABILITY_yes) {
|
|
||||||
struct route t;
|
|
||||||
|
|
||||||
/* an existing port has changed to unavailable */
|
|
||||||
pw_log_info("device %d: route '%s' not available", dev->id, r->name);
|
|
||||||
/* try to find a new best port */
|
|
||||||
res = find_best_route(dev, r->device_id, &t);
|
|
||||||
if (res < 0) {
|
|
||||||
pw_log_info("device %d: can't find best route", dev->id);
|
|
||||||
} else {
|
|
||||||
pw_log_info("device %d: found best route '%s'", dev->id,
|
|
||||||
t.name);
|
|
||||||
restore_route(dev, &t);
|
|
||||||
ri->valid = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (ri->valid && r->props) {
|
|
||||||
/* just save port properties */
|
/* just save port properties */
|
||||||
save_route(dev, r);
|
save_route(dev, r);
|
||||||
}
|
}
|
||||||
ri->generation = dev->generation;
|
ri->available = r->available;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_routes(struct device *dev)
|
static int handle_routes(struct device *dev)
|
||||||
{
|
{
|
||||||
struct sm_param *p;
|
struct sm_param *p;
|
||||||
|
bool changed = false;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
/* first look at all routes and see if something changed */
|
||||||
|
spa_list_for_each(p, &dev->obj->param_list, link) {
|
||||||
|
struct route r;
|
||||||
|
struct route_info *ri;
|
||||||
|
|
||||||
|
if (p->id != SPA_PARAM_EnumRoute ||
|
||||||
|
parse_enum_route(p, SPA_ID_INVALID, &r) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((ri = find_route_info(dev, &r)) == NULL)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ri->available != r.available) {
|
||||||
|
pw_log_info("device %d: route %s available changed %d -> %d",
|
||||||
|
dev->id, r.name, ri->available, r.available);
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
ri->generation = dev->generation;
|
||||||
|
ri->prev_active = ri->active;
|
||||||
|
ri->active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
struct profile best;
|
||||||
|
|
||||||
|
pw_log_info("device %d: find best profile", dev->id);
|
||||||
|
/* port availability changed, find new best profile and switch
|
||||||
|
* to it when needed. */
|
||||||
|
if ((res = find_best_profile(dev, &best)) < 0) {
|
||||||
|
pw_log_info("device %d: can't find best profile", dev->id);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (dev->active_profile != best.index) {
|
||||||
|
pw_log_info("device %d: activating best profile %s",
|
||||||
|
dev->id, best.name);
|
||||||
|
/* we need to switch profiles */
|
||||||
|
set_profile(dev, &best);
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
pw_log_info("device %d: best profile %s already active",
|
||||||
|
dev->id, best.name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* then check for changes in the active ports */
|
||||||
spa_list_for_each(p, &dev->obj->param_list, link) {
|
spa_list_for_each(p, &dev->obj->param_list, link) {
|
||||||
struct route r;
|
struct route r;
|
||||||
if (p->id != SPA_PARAM_Route ||
|
if (p->id != SPA_PARAM_Route ||
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue