mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	alsa-endpoint: make monitor endpoints as well
This commit is contained in:
		
							parent
							
								
									8d49964c4d
								
							
						
					
					
						commit
						aef04961aa
					
				
					 1 changed files with 88 additions and 42 deletions
				
			
		| 
						 | 
					@ -56,6 +56,8 @@ struct endpoint {
 | 
				
			||||||
	struct spa_hook client_endpoint_listener;
 | 
						struct spa_hook client_endpoint_listener;
 | 
				
			||||||
	struct pw_endpoint_info info;
 | 
						struct pw_endpoint_info info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						struct endpoint *monitor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	unsigned int use_ucm:1;
 | 
						unsigned int use_ucm:1;
 | 
				
			||||||
	snd_use_case_mgr_t *ucm;
 | 
						snd_use_case_mgr_t *ucm;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -193,6 +195,48 @@ static const struct pw_client_endpoint_proxy_events client_endpoint_events = {
 | 
				
			||||||
	.create_link = client_endpoint_create_link,
 | 
						.create_link = client_endpoint_create_link,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int endpoint_add_stream(struct endpoint *endpoint)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct stream *s;
 | 
				
			||||||
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s = calloc(1, sizeof(*s));
 | 
				
			||||||
 | 
						if (s == NULL)
 | 
				
			||||||
 | 
							return -errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s->props = pw_properties_new(NULL, NULL);
 | 
				
			||||||
 | 
						if ((str = pw_properties_get(endpoint->props, PW_KEY_MEDIA_CLASS)) != NULL)
 | 
				
			||||||
 | 
							pw_properties_set(s->props, PW_KEY_MEDIA_CLASS, str);
 | 
				
			||||||
 | 
						if ((str = pw_properties_get(endpoint->props, PW_KEY_PRIORITY_SESSION)) != NULL)
 | 
				
			||||||
 | 
							pw_properties_set(s->props, PW_KEY_PRIORITY_SESSION, str);
 | 
				
			||||||
 | 
						if (endpoint->info.direction == PW_DIRECTION_OUTPUT) {
 | 
				
			||||||
 | 
							if (endpoint->monitor != NULL)
 | 
				
			||||||
 | 
								pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Monitor");
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Playback");
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Capture");
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						s->info.version = PW_VERSION_ENDPOINT_STREAM_INFO;
 | 
				
			||||||
 | 
						s->info.id = endpoint->info.n_streams;
 | 
				
			||||||
 | 
						s->info.endpoint_id = endpoint->info.id;
 | 
				
			||||||
 | 
						s->info.name = (char*)pw_properties_get(s->props, PW_KEY_ENDPOINT_STREAM_NAME);
 | 
				
			||||||
 | 
						s->info.change_mask = PW_ENDPOINT_STREAM_CHANGE_MASK_PROPS;
 | 
				
			||||||
 | 
						s->info.props = &s->props->dict;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_log_debug("stream %d", s->info.id);
 | 
				
			||||||
 | 
						pw_client_endpoint_proxy_stream_update(endpoint->client_endpoint,
 | 
				
			||||||
 | 
								s->info.id,
 | 
				
			||||||
 | 
								PW_CLIENT_ENDPOINT_STREAM_UPDATE_INFO,
 | 
				
			||||||
 | 
								0, NULL,
 | 
				
			||||||
 | 
								&s->info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						spa_list_append(&endpoint->stream_list, &s->link);
 | 
				
			||||||
 | 
						endpoint->info.n_streams++;
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void node_event_param(void *object, int seq,
 | 
					static void node_event_param(void *object, int seq,
 | 
				
			||||||
                       uint32_t id, uint32_t index, uint32_t next,
 | 
					                       uint32_t id, uint32_t index, uint32_t next,
 | 
				
			||||||
                       const struct spa_pod *param)
 | 
					                       const struct spa_pod *param)
 | 
				
			||||||
| 
						 | 
					@ -223,6 +267,7 @@ static void node_event_param(void *object, int seq,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (endpoint->format.info.raw.channels < info.info.raw.channels)
 | 
						if (endpoint->format.info.raw.channels < info.info.raw.channels)
 | 
				
			||||||
		endpoint->format = info;
 | 
							endpoint->format = info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      error:
 | 
					      error:
 | 
				
			||||||
| 
						 | 
					@ -237,7 +282,27 @@ static const struct pw_node_proxy_events endpoint_node_events = {
 | 
				
			||||||
	.param = node_event_param,
 | 
						.param = node_event_param,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct endpoint *make_endpoint(struct alsa_node *obj)
 | 
					static struct endpoint *make_endpoint(struct alsa_node *obj, struct endpoint *monitor);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void complete_endpoint(void *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct endpoint *endpoint = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						endpoint_add_stream(endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (endpoint->info.direction == PW_DIRECTION_INPUT) {
 | 
				
			||||||
 | 
							struct endpoint *monitor;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* make monitor for sinks */
 | 
				
			||||||
 | 
							monitor = make_endpoint(endpoint->obj, endpoint);
 | 
				
			||||||
 | 
							if (monitor == NULL)
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							endpoint_add_stream(monitor);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static struct endpoint *make_endpoint(struct alsa_node *obj, struct endpoint *monitor)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = obj->monitor->impl;
 | 
						struct impl *impl = obj->monitor->impl;
 | 
				
			||||||
	struct pw_properties *props;
 | 
						struct pw_properties *props;
 | 
				
			||||||
| 
						 | 
					@ -250,12 +315,23 @@ static struct endpoint *make_endpoint(struct alsa_node *obj)
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (obj->props) {
 | 
						if (obj->props) {
 | 
				
			||||||
		if ((media_class = pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS)) != NULL)
 | 
							if ((media_class = pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS)) != NULL) {
 | 
				
			||||||
			pw_properties_set(props, PW_KEY_MEDIA_CLASS, media_class);
 | 
								if (monitor != NULL) {
 | 
				
			||||||
 | 
									pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Source");
 | 
				
			||||||
 | 
								 } else {
 | 
				
			||||||
 | 
									pw_properties_set(props, PW_KEY_MEDIA_CLASS, media_class);
 | 
				
			||||||
 | 
								 }
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		if ((str = pw_properties_get(obj->props, PW_KEY_PRIORITY_SESSION)) != NULL)
 | 
							if ((str = pw_properties_get(obj->props, PW_KEY_PRIORITY_SESSION)) != NULL)
 | 
				
			||||||
			pw_properties_set(props, PW_KEY_PRIORITY_SESSION, str);
 | 
								pw_properties_set(props, PW_KEY_PRIORITY_SESSION, str);
 | 
				
			||||||
		if ((name = pw_properties_get(obj->props, PW_KEY_NODE_DESCRIPTION)) != NULL)
 | 
							if ((name = pw_properties_get(obj->props, PW_KEY_NODE_DESCRIPTION)) != NULL) {
 | 
				
			||||||
			pw_properties_set(props, PW_KEY_ENDPOINT_NAME, name);
 | 
								if (monitor != NULL) {
 | 
				
			||||||
 | 
									pw_properties_setf(props, PW_KEY_ENDPOINT_NAME, "Monitor of %s", monitor->info.name);
 | 
				
			||||||
 | 
									pw_properties_setf(props, PW_KEY_ENDPOINT_MONITOR, "%d", monitor->info.id);
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									pw_properties_set(props, PW_KEY_ENDPOINT_NAME, name);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (obj->object && obj->object->props) {
 | 
						if (obj->object && obj->object->props) {
 | 
				
			||||||
		if ((str = pw_properties_get(obj->object->props, PW_KEY_DEVICE_ICON_NAME)) != NULL)
 | 
							if ((str = pw_properties_get(obj->object->props, PW_KEY_DEVICE_ICON_NAME)) != NULL)
 | 
				
			||||||
| 
						 | 
					@ -274,13 +350,14 @@ static struct endpoint *make_endpoint(struct alsa_node *obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	endpoint = pw_proxy_get_user_data(proxy);
 | 
						endpoint = pw_proxy_get_user_data(proxy);
 | 
				
			||||||
	endpoint->obj = obj;
 | 
						endpoint->obj = obj;
 | 
				
			||||||
 | 
						endpoint->monitor = monitor;
 | 
				
			||||||
	endpoint->props = props;
 | 
						endpoint->props = props;
 | 
				
			||||||
	endpoint->client_endpoint = (struct pw_client_endpoint_proxy *) proxy;
 | 
						endpoint->client_endpoint = (struct pw_client_endpoint_proxy *) proxy;
 | 
				
			||||||
	endpoint->info.version = PW_VERSION_ENDPOINT_INFO;
 | 
						endpoint->info.version = PW_VERSION_ENDPOINT_INFO;
 | 
				
			||||||
	endpoint->info.name = (char*)pw_properties_get(endpoint->props, PW_KEY_ENDPOINT_NAME);
 | 
						endpoint->info.name = (char*)pw_properties_get(endpoint->props, PW_KEY_ENDPOINT_NAME);
 | 
				
			||||||
	endpoint->info.media_class = (char*)pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS);
 | 
						endpoint->info.media_class = (char*)pw_properties_get(endpoint->props, PW_KEY_MEDIA_CLASS);
 | 
				
			||||||
	endpoint->info.session_id = impl->session->info.id;
 | 
						endpoint->info.session_id = impl->session->info.id;
 | 
				
			||||||
	endpoint->info.direction = obj->direction;
 | 
						endpoint->info.direction = monitor != NULL ? PW_DIRECTION_OUTPUT : obj->direction;
 | 
				
			||||||
	endpoint->info.flags = 0;
 | 
						endpoint->info.flags = 0;
 | 
				
			||||||
	endpoint->info.change_mask =
 | 
						endpoint->info.change_mask =
 | 
				
			||||||
		PW_ENDPOINT_CHANGE_MASK_STREAMS |
 | 
							PW_ENDPOINT_CHANGE_MASK_STREAMS |
 | 
				
			||||||
| 
						 | 
					@ -303,6 +380,9 @@ static struct endpoint *make_endpoint(struct alsa_node *obj)
 | 
				
			||||||
				0, SPA_PARAM_EnumFormat,
 | 
									0, SPA_PARAM_EnumFormat,
 | 
				
			||||||
				0, -1, NULL);
 | 
									0, -1, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (monitor == NULL)
 | 
				
			||||||
 | 
							sm_media_session_sync(impl->session, complete_endpoint, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return endpoint;
 | 
						return endpoint;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -310,47 +390,13 @@ static struct endpoint *make_endpoint(struct alsa_node *obj)
 | 
				
			||||||
static int setup_alsa_fallback_endpoint(struct alsa_object *obj)
 | 
					static int setup_alsa_fallback_endpoint(struct alsa_object *obj)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct alsa_node *n;
 | 
						struct alsa_node *n;
 | 
				
			||||||
	const char *str;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(n, &obj->node_list, link) {
 | 
						spa_list_for_each(n, &obj->node_list, link) {
 | 
				
			||||||
		struct stream *s;
 | 
					 | 
				
			||||||
		struct endpoint *endpoint;
 | 
							struct endpoint *endpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		endpoint = make_endpoint(n);
 | 
							endpoint = make_endpoint(n, NULL);
 | 
				
			||||||
		if (endpoint == NULL)
 | 
							if (endpoint == NULL)
 | 
				
			||||||
			return -errno;
 | 
								return -errno;
 | 
				
			||||||
 | 
					 | 
				
			||||||
		s = calloc(1, sizeof(*s));
 | 
					 | 
				
			||||||
		if (s == NULL)
 | 
					 | 
				
			||||||
			return -errno;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		s->props = pw_properties_new(NULL, NULL);
 | 
					 | 
				
			||||||
		if ((str = pw_properties_get(n->props, PW_KEY_MEDIA_CLASS)) != NULL)
 | 
					 | 
				
			||||||
			pw_properties_set(s->props, PW_KEY_MEDIA_CLASS, str);
 | 
					 | 
				
			||||||
		if ((str = pw_properties_get(n->props, PW_KEY_PRIORITY_SESSION)) != NULL)
 | 
					 | 
				
			||||||
			pw_properties_set(s->props, PW_KEY_PRIORITY_SESSION, str);
 | 
					 | 
				
			||||||
		if (n->direction == PW_DIRECTION_OUTPUT)
 | 
					 | 
				
			||||||
			pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Playback");
 | 
					 | 
				
			||||||
		else
 | 
					 | 
				
			||||||
			pw_properties_set(s->props, PW_KEY_ENDPOINT_STREAM_NAME, "Capture");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		s->info.version = PW_VERSION_ENDPOINT_STREAM_INFO;
 | 
					 | 
				
			||||||
		s->info.id = endpoint->info.n_streams;
 | 
					 | 
				
			||||||
		s->info.endpoint_id = endpoint->info.id;
 | 
					 | 
				
			||||||
		s->info.name = (char*)pw_properties_get(s->props, PW_KEY_ENDPOINT_STREAM_NAME);
 | 
					 | 
				
			||||||
		s->info.change_mask = PW_ENDPOINT_STREAM_CHANGE_MASK_PROPS;
 | 
					 | 
				
			||||||
		s->info.props = &s->props->dict;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		pw_log_debug("stream %d", s->info.id);
 | 
					 | 
				
			||||||
		pw_client_endpoint_proxy_stream_update(endpoint->client_endpoint,
 | 
					 | 
				
			||||||
				n->id,
 | 
					 | 
				
			||||||
				PW_CLIENT_ENDPOINT_STREAM_UPDATE_INFO,
 | 
					 | 
				
			||||||
				0, NULL,
 | 
					 | 
				
			||||||
				&s->info);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		spa_list_append(&endpoint->stream_list, &s->link);
 | 
					 | 
				
			||||||
		endpoint->info.n_streams++;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue