mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	media-session: move profile switch to default-profile
Move the profile switching from default-route to the default-profile module. This makes more sense and it also allows us to restore the saved profile when it becomes available. Make default-profile always check if the saved profile can be restored before attempting to switch to the best profile. Default-route now just monitors profile changes and restores the routes associated with it. See #466
This commit is contained in:
		
							parent
							
								
									3e2d897f97
								
							
						
					
					
						commit
						59f86df9f3
					
				
					 2 changed files with 74 additions and 136 deletions
				
			
		| 
						 | 
				
			
			@ -74,8 +74,6 @@ struct device {
 | 
			
		|||
 | 
			
		||||
	struct spa_hook listener;
 | 
			
		||||
 | 
			
		||||
	unsigned int restored:1;
 | 
			
		||||
 | 
			
		||||
	uint32_t saved_profile;
 | 
			
		||||
	uint32_t active_profile;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -250,70 +248,98 @@ static int set_profile(struct device *dev, struct profile *pr)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int handle_profile(struct device *dev)
 | 
			
		||||
static int handle_active_profile(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = dev->impl;
 | 
			
		||||
	struct profile pr;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
			/* no saved profile found or it is not available */
 | 
			
		||||
			if (res < 0)
 | 
			
		||||
				pw_log_info("device '%s': no saved profile: %s",
 | 
			
		||||
					dev->name, spa_strerror(res));
 | 
			
		||||
			else
 | 
			
		||||
				pw_log_info("device '%s': saved profile '%s' unavailable",
 | 
			
		||||
					dev->name, pr.name);
 | 
			
		||||
	/* check if current profile changed */
 | 
			
		||||
	if ((res = find_current_profile(dev, &pr)) < 0)
 | 
			
		||||
		return res;
 | 
			
		||||
 | 
			
		||||
			/* try to find the next best profile */
 | 
			
		||||
			res = find_best_profile(dev, &pr);
 | 
			
		||||
			if (res < 0)
 | 
			
		||||
				pw_log_info("device '%s': can't find best profile: %s",
 | 
			
		||||
						dev->name, spa_strerror(res));
 | 
			
		||||
			else
 | 
			
		||||
				pw_log_info("device '%s': found best profile '%s'",
 | 
			
		||||
						dev->name, pr.name);
 | 
			
		||||
	if (dev->active_profile == pr.index) {
 | 
			
		||||
		/* no change, we're done */
 | 
			
		||||
		pw_log_info("device '%s': active profile '%s'", dev->name, pr.name);
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* we get here when we had configured a profile but something
 | 
			
		||||
	 * else changed it, in that case, save it when asked. */
 | 
			
		||||
	pw_log_info("device '%s': active profile changed to '%s'", dev->name, pr.name);
 | 
			
		||||
	dev->active_profile = pr.index;
 | 
			
		||||
 | 
			
		||||
	if (!pr.save)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	dev->saved_profile = pr.index;
 | 
			
		||||
	if (pw_properties_setf(impl->properties, dev->key, "{ \"name\": \"%s\" }", pr.name)) {
 | 
			
		||||
		pw_log_info("device '%s': active profile saved as '%s'", dev->name, pr.name);
 | 
			
		||||
		add_idle_timeout(impl);
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int handle_profile_switch(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct profile pr;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	/* try to restore our saved profile */
 | 
			
		||||
	res = find_saved_profile(dev, &pr);
 | 
			
		||||
	if (res >= 0) {
 | 
			
		||||
		/* we found a saved profile */
 | 
			
		||||
		if (pr.available == SPA_PARAM_AVAILABILITY_no) {
 | 
			
		||||
			pw_log_info("device '%s': saved profile '%s' unavailable",
 | 
			
		||||
				dev->name, pr.name);
 | 
			
		||||
			res = -ENOENT;
 | 
			
		||||
		} else {
 | 
			
		||||
			pw_log_info("device '%s': found saved profile '%s'",
 | 
			
		||||
						dev->name, pr.name);
 | 
			
		||||
			dev->saved_profile = pr.index;
 | 
			
		||||
			/* make sure we save again */
 | 
			
		||||
			pr.save = true;
 | 
			
		||||
		}
 | 
			
		||||
		if (res >= 0) {
 | 
			
		||||
			pw_log_info("device '%s': restore profile '%s' index %d",
 | 
			
		||||
					dev->name, pr.name, pr.index);
 | 
			
		||||
			if (set_profile(dev, &pr) >= 0)
 | 
			
		||||
				dev->restored = true;
 | 
			
		||||
	} else {
 | 
			
		||||
		pw_log_info("device '%s': no saved profile: %s",
 | 
			
		||||
			dev->name, spa_strerror(res));
 | 
			
		||||
	}
 | 
			
		||||
	if (res < 0) {
 | 
			
		||||
		/* try to find the next best profile */
 | 
			
		||||
		res = find_best_profile(dev, &pr);
 | 
			
		||||
		if (res < 0)
 | 
			
		||||
			pw_log_info("device '%s': can't find best profile: %s",
 | 
			
		||||
					dev->name, spa_strerror(res));
 | 
			
		||||
		else
 | 
			
		||||
			pw_log_info("device '%s': found best profile '%s'",
 | 
			
		||||
					dev->name, pr.name);
 | 
			
		||||
	}
 | 
			
		||||
	if (res >= 0) {
 | 
			
		||||
		if (dev->active_profile == pr.index) {
 | 
			
		||||
			pw_log_info("device '%s': best profile '%s' is already active",
 | 
			
		||||
					dev->name, pr.name);
 | 
			
		||||
		} else {
 | 
			
		||||
			pw_log_warn("device '%s': can't restore profile", dev->name);
 | 
			
		||||
			pw_log_info("device '%s': restore best profile '%s' index %d",
 | 
			
		||||
					dev->name, pr.name, pr.index);
 | 
			
		||||
			set_profile(dev, &pr);
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if ((res = find_current_profile(dev, &pr)) < 0)
 | 
			
		||||
			return res;
 | 
			
		||||
 | 
			
		||||
		if (dev->active_profile == pr.index)
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		/* we get here when we had configured a profile but something
 | 
			
		||||
		 * else changed it, in that case, save it when asked. */
 | 
			
		||||
		dev->active_profile = pr.index;
 | 
			
		||||
 | 
			
		||||
		if (!pr.save)
 | 
			
		||||
			return 0;
 | 
			
		||||
 | 
			
		||||
		dev->saved_profile = pr.index;
 | 
			
		||||
		if (pw_properties_setf(impl->properties, dev->key, "{ \"name\": \"%s\" }", pr.name)) {
 | 
			
		||||
			pw_log_info("device '%s': active profile changed to '%s'", dev->name, pr.name);
 | 
			
		||||
			add_idle_timeout(impl);
 | 
			
		||||
		}
 | 
			
		||||
		pw_log_warn("device '%s': can't restore profile: %s", dev->name,
 | 
			
		||||
				spa_strerror(res));
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int handle_profile(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	/* check if current profile changed */
 | 
			
		||||
	handle_active_profile(dev);
 | 
			
		||||
 | 
			
		||||
	/* check if we need to switch profile */
 | 
			
		||||
	handle_profile_switch(dev);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void object_update(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct device *dev = data;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -454,49 +454,6 @@ static int find_current_profile(struct device *dev, struct profile *pr)
 | 
			
		|||
	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 ||
 | 
			
		||||
		    parse_profile(p, &t) < 0)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (t.name && strcmp(t.name, "pro-audio") == 0)
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		if (t.name && strcmp(t.name, "off") == 0) {
 | 
			
		||||
			off = t;
 | 
			
		||||
		}
 | 
			
		||||
		else if (t.available == SPA_PARAM_AVAILABILITY_yes) {
 | 
			
		||||
			if (best_avail.name == NULL || t.prio > best_avail.prio)
 | 
			
		||||
				best_avail = t;
 | 
			
		||||
		}
 | 
			
		||||
		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_route(struct device *dev, struct route *r)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = dev->impl;
 | 
			
		||||
| 
						 | 
				
			
			@ -768,26 +725,6 @@ static void prune_route_info(struct device *dev)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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));
 | 
			
		||||
 | 
			
		||||
	if (dev->active_profile == pr->index)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	pw_device_set_param((struct pw_device*)dev->obj->obj.proxy,
 | 
			
		||||
			SPA_PARAM_Profile, 0,
 | 
			
		||||
			spa_pod_builder_add_object(&b,
 | 
			
		||||
				SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
 | 
			
		||||
				SPA_PARAM_PROFILE_index, SPA_POD_Int(pr->index),
 | 
			
		||||
				SPA_PARAM_PROFILE_save, SPA_POD_Bool(false)));
 | 
			
		||||
 | 
			
		||||
	dev->active_profile = pr->index;
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int handle_route(struct device *dev, struct route *r)
 | 
			
		||||
{
 | 
			
		||||
	struct route_info *ri;
 | 
			
		||||
| 
						 | 
				
			
			@ -814,10 +751,8 @@ static int handle_route(struct device *dev, struct route *r)
 | 
			
		|||
static int handle_routes(struct device *dev)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_param *p;
 | 
			
		||||
	bool changed = false;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	/* first look at all routes and see if something changed */
 | 
			
		||||
	/* first look at all routes */
 | 
			
		||||
	spa_list_for_each(p, &dev->obj->param_list, link) {
 | 
			
		||||
		struct route r;
 | 
			
		||||
		struct route_info *ri;
 | 
			
		||||
| 
						 | 
				
			
			@ -832,7 +767,6 @@ static int handle_routes(struct device *dev)
 | 
			
		|||
		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;
 | 
			
		||||
| 
						 | 
				
			
			@ -846,28 +780,6 @@ static int handle_routes(struct device *dev)
 | 
			
		|||
			continue;
 | 
			
		||||
		handle_route(dev, &r);
 | 
			
		||||
	}
 | 
			
		||||
	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);
 | 
			
		||||
			reconfigure_profile(dev, &best);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	prune_route_info(dev);
 | 
			
		||||
 | 
			
		||||
	save_profile(dev);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue