mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	pulse-server: find the target device in play_sample
Use the regular logic to find the target device for play sample so that it supports @DEFAULT_SINK@ etc. See #612
This commit is contained in:
		
							parent
							
								
									1eb9d73814
								
							
						
					
					
						commit
						14dcfb8a28
					
				
					 1 changed files with 82 additions and 82 deletions
				
			
		| 
						 | 
				
			
			@ -2359,6 +2359,80 @@ error:
 | 
			
		|||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *get_default(struct client *client, bool sink)
 | 
			
		||||
{
 | 
			
		||||
	struct selector sel;
 | 
			
		||||
	struct pw_manager *manager = client->manager;
 | 
			
		||||
	struct pw_manager_object *o;
 | 
			
		||||
	const char *def, *str, *mon;
 | 
			
		||||
 | 
			
		||||
	spa_zero(sel);
 | 
			
		||||
	if (sink) {
 | 
			
		||||
		sel.type = object_is_sink;
 | 
			
		||||
		sel.id = client->default_sink;
 | 
			
		||||
		def = DEFAULT_SINK;
 | 
			
		||||
	} else {
 | 
			
		||||
		sel.type = object_is_source_or_monitor;
 | 
			
		||||
		sel.id = client->default_source;
 | 
			
		||||
		def = DEFAULT_SOURCE;
 | 
			
		||||
	}
 | 
			
		||||
	sel.accumulate = select_best;
 | 
			
		||||
 | 
			
		||||
	o = select_object(manager, &sel);
 | 
			
		||||
	if (o == NULL || o->props == NULL)
 | 
			
		||||
		return def;
 | 
			
		||||
	str = pw_properties_get(o->props, PW_KEY_NODE_NAME);
 | 
			
		||||
 | 
			
		||||
	if (!sink && object_is_monitor(o)) {
 | 
			
		||||
		def = DEFAULT_MONITOR;
 | 
			
		||||
		if (str != NULL &&
 | 
			
		||||
		    (mon = pw_properties_get(o->props, PW_KEY_NODE_NAME".monitor")) == NULL) {
 | 
			
		||||
			pw_properties_setf(o->props,
 | 
			
		||||
					PW_KEY_NODE_NAME".monitor",
 | 
			
		||||
					"%s.monitor", str);
 | 
			
		||||
		}
 | 
			
		||||
		str = pw_properties_get(o->props, PW_KEY_NODE_NAME".monitor");
 | 
			
		||||
	}
 | 
			
		||||
	if (str == NULL)
 | 
			
		||||
		str = def;
 | 
			
		||||
	return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct pw_manager_object *find_device(struct client *client,
 | 
			
		||||
		uint32_t id, const char *name, bool sink)
 | 
			
		||||
{
 | 
			
		||||
	struct selector sel;
 | 
			
		||||
	const char *def;
 | 
			
		||||
 | 
			
		||||
	if (name != NULL && !sink) {
 | 
			
		||||
		if (pw_endswith(name, ".monitor")) {
 | 
			
		||||
			name = strndupa(name, strlen(name)-8);
 | 
			
		||||
			sink = true;
 | 
			
		||||
		} else if (strcmp(name, DEFAULT_MONITOR) == 0) {
 | 
			
		||||
			name = NULL;
 | 
			
		||||
			sink = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spa_zero(sel);
 | 
			
		||||
	sel.id = id;
 | 
			
		||||
	sel.key = PW_KEY_NODE_NAME;
 | 
			
		||||
	sel.value = name;
 | 
			
		||||
 | 
			
		||||
	if (sink) {
 | 
			
		||||
		sel.type = object_is_sink;
 | 
			
		||||
		def = DEFAULT_SINK;
 | 
			
		||||
	} else {
 | 
			
		||||
		sel.type = object_is_source;
 | 
			
		||||
		def = DEFAULT_SOURCE;
 | 
			
		||||
	}
 | 
			
		||||
	if (id == SPA_ID_INVALID &&
 | 
			
		||||
	    (sel.value == NULL || strcmp(sel.value, def) == 0))
 | 
			
		||||
		sel.value = get_default(client, sink);
 | 
			
		||||
 | 
			
		||||
	return select_object(client->manager, &sel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pending_sample {
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
	struct client *client;
 | 
			
		||||
| 
						 | 
				
			
			@ -2425,6 +2499,7 @@ static int do_play_sample(struct client *client, uint32_t command, uint32_t tag,
 | 
			
		|||
	const char *sink_name, *name;
 | 
			
		||||
	struct pw_properties *props = NULL;
 | 
			
		||||
	struct pending_sample *ps;
 | 
			
		||||
	struct pw_manager_object *o;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	if ((props = pw_properties_new(NULL, NULL)) == NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -2449,22 +2524,21 @@ static int do_play_sample(struct client *client, uint32_t command, uint32_t tag,
 | 
			
		|||
			impl, client->name, commands[command].name, tag,
 | 
			
		||||
			sink_index, sink_name, name);
 | 
			
		||||
 | 
			
		||||
	pw_properties_update(props, &client->props->dict);
 | 
			
		||||
 | 
			
		||||
	if (sink_index != SPA_ID_INVALID && sink_name != NULL)
 | 
			
		||||
		goto error_inval;
 | 
			
		||||
 | 
			
		||||
	if (sink_name != NULL)
 | 
			
		||||
		pw_properties_set(props,
 | 
			
		||||
				PW_KEY_NODE_TARGET, sink_name);
 | 
			
		||||
	else if (sink_index != SPA_ID_INVALID)
 | 
			
		||||
		pw_properties_setf(props,
 | 
			
		||||
				PW_KEY_NODE_TARGET, "%u", sink_index);
 | 
			
		||||
 | 
			
		||||
	pw_properties_update(props, &client->props->dict);
 | 
			
		||||
	o = find_device(client, sink_index, sink_name, PW_DIRECTION_OUTPUT);
 | 
			
		||||
	if (o == NULL)
 | 
			
		||||
		goto error_noent;
 | 
			
		||||
 | 
			
		||||
	sample = find_sample(impl, SPA_ID_INVALID, name);
 | 
			
		||||
	if (sample == NULL)
 | 
			
		||||
		goto error_noent;
 | 
			
		||||
 | 
			
		||||
	pw_properties_setf(props, PW_KEY_NODE_TARGET, "%u", o->id);
 | 
			
		||||
 | 
			
		||||
	play = sample_play_new(client->core, sample, props, sizeof(struct pending_sample));
 | 
			
		||||
	props = NULL;
 | 
			
		||||
	if (play == NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -2803,80 +2877,6 @@ static int do_set_stream_mute(struct client *client, uint32_t command, uint32_t
 | 
			
		|||
	return reply_simple_ack(client, tag);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const char *get_default(struct client *client, bool sink)
 | 
			
		||||
{
 | 
			
		||||
	struct selector sel;
 | 
			
		||||
	struct pw_manager *manager = client->manager;
 | 
			
		||||
	struct pw_manager_object *o;
 | 
			
		||||
	const char *def, *str, *mon;
 | 
			
		||||
 | 
			
		||||
	spa_zero(sel);
 | 
			
		||||
	if (sink) {
 | 
			
		||||
		sel.type = object_is_sink;
 | 
			
		||||
		sel.id = client->default_sink;
 | 
			
		||||
		def = DEFAULT_SINK;
 | 
			
		||||
	} else {
 | 
			
		||||
		sel.type = object_is_source_or_monitor;
 | 
			
		||||
		sel.id = client->default_source;
 | 
			
		||||
		def = DEFAULT_SOURCE;
 | 
			
		||||
	}
 | 
			
		||||
	sel.accumulate = select_best;
 | 
			
		||||
 | 
			
		||||
	o = select_object(manager, &sel);
 | 
			
		||||
	if (o == NULL || o->props == NULL)
 | 
			
		||||
		return def;
 | 
			
		||||
	str = pw_properties_get(o->props, PW_KEY_NODE_NAME);
 | 
			
		||||
 | 
			
		||||
	if (!sink && object_is_monitor(o)) {
 | 
			
		||||
		def = DEFAULT_MONITOR;
 | 
			
		||||
		if (str != NULL &&
 | 
			
		||||
		    (mon = pw_properties_get(o->props, PW_KEY_NODE_NAME".monitor")) == NULL) {
 | 
			
		||||
			pw_properties_setf(o->props,
 | 
			
		||||
					PW_KEY_NODE_NAME".monitor",
 | 
			
		||||
					"%s.monitor", str);
 | 
			
		||||
		}
 | 
			
		||||
		str = pw_properties_get(o->props, PW_KEY_NODE_NAME".monitor");
 | 
			
		||||
	}
 | 
			
		||||
	if (str == NULL)
 | 
			
		||||
		str = def;
 | 
			
		||||
	return str;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct pw_manager_object *find_device(struct client *client,
 | 
			
		||||
		uint32_t id, const char *name, bool sink)
 | 
			
		||||
{
 | 
			
		||||
	struct selector sel;
 | 
			
		||||
	const char *def;
 | 
			
		||||
 | 
			
		||||
	if (name != NULL && !sink) {
 | 
			
		||||
		if (pw_endswith(name, ".monitor")) {
 | 
			
		||||
			name = strndupa(name, strlen(name)-8);
 | 
			
		||||
			sink = true;
 | 
			
		||||
		} else if (strcmp(name, DEFAULT_MONITOR) == 0) {
 | 
			
		||||
			name = NULL;
 | 
			
		||||
			sink = true;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	spa_zero(sel);
 | 
			
		||||
	sel.id = id;
 | 
			
		||||
	sel.key = PW_KEY_NODE_NAME;
 | 
			
		||||
	sel.value = name;
 | 
			
		||||
 | 
			
		||||
	if (sink) {
 | 
			
		||||
		sel.type = object_is_sink;
 | 
			
		||||
		def = DEFAULT_SINK;
 | 
			
		||||
	} else {
 | 
			
		||||
		sel.type = object_is_source;
 | 
			
		||||
		def = DEFAULT_SOURCE;
 | 
			
		||||
	}
 | 
			
		||||
	if (id == SPA_ID_INVALID &&
 | 
			
		||||
	    (sel.value == NULL || strcmp(sel.value, def) == 0))
 | 
			
		||||
		sel.value = get_default(client, sink);
 | 
			
		||||
 | 
			
		||||
	return select_object(client->manager, &sel);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int do_set_volume(struct client *client, uint32_t command, uint32_t tag, struct message *m)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = client->impl;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue