mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	session-manager: remove obsolte _set_id
media-session: Wait for devices to appear and be bound before setting the profile on the device. Then wait for all the nodes to appear before attempting the create endpoints on the device.
This commit is contained in:
		
							parent
							
								
									e1ef01c860
								
							
						
					
					
						commit
						125fcb5660
					
				
					 9 changed files with 748 additions and 490 deletions
				
			
		| 
						 | 
				
			
			@ -62,6 +62,7 @@ struct endpoint {
 | 
			
		|||
	struct spa_hook listener;
 | 
			
		||||
 | 
			
		||||
	struct pw_client_endpoint_proxy *client_endpoint;
 | 
			
		||||
	struct spa_hook proxy_listener;
 | 
			
		||||
	struct spa_hook client_endpoint_listener;
 | 
			
		||||
	struct pw_endpoint_info info;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +80,7 @@ struct endpoint {
 | 
			
		|||
 | 
			
		||||
struct stream {
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
	struct endpoint *endpoint;
 | 
			
		||||
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
	struct pw_endpoint_stream_info info;
 | 
			
		||||
| 
						 | 
				
			
			@ -89,17 +91,15 @@ struct stream {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
struct node {
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
	struct sm_node *node;
 | 
			
		||||
 | 
			
		||||
	struct device *device;
 | 
			
		||||
 | 
			
		||||
	struct endpoint *endpoint;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct device {
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
	struct sm_device *device;
 | 
			
		||||
| 
						 | 
				
			
			@ -113,13 +113,6 @@ struct impl {
 | 
			
		|||
	struct spa_hook listener;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int client_endpoint_set_id(void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = object;
 | 
			
		||||
	endpoint->info.id = id;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_endpoint_set_session_id(void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -228,7 +221,6 @@ exit:
 | 
			
		|||
 | 
			
		||||
static const struct pw_client_endpoint_proxy_events client_endpoint_events = {
 | 
			
		||||
	PW_VERSION_CLIENT_ENDPOINT_PROXY_EVENTS,
 | 
			
		||||
	.set_id = client_endpoint_set_id,
 | 
			
		||||
	.set_session_id = client_endpoint_set_session_id,
 | 
			
		||||
	.set_param = client_endpoint_set_param,
 | 
			
		||||
	.stream_set_param = client_endpoint_stream_set_param,
 | 
			
		||||
| 
						 | 
				
			
			@ -245,6 +237,8 @@ static struct stream *endpoint_add_stream(struct endpoint *endpoint)
 | 
			
		|||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	s->props = pw_properties_new(NULL, NULL);
 | 
			
		||||
	s->endpoint = endpoint;
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
| 
						 | 
				
			
			@ -279,6 +273,23 @@ static struct stream *endpoint_add_stream(struct endpoint *endpoint)
 | 
			
		|||
	return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void destroy_stream(struct stream *stream)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = stream->endpoint;
 | 
			
		||||
 | 
			
		||||
	pw_client_endpoint_proxy_stream_update(endpoint->client_endpoint,
 | 
			
		||||
			stream->info.id,
 | 
			
		||||
			PW_CLIENT_ENDPOINT_STREAM_UPDATE_DESTROYED,
 | 
			
		||||
			0, NULL,
 | 
			
		||||
			&stream->info);
 | 
			
		||||
 | 
			
		||||
	spa_list_remove(&stream->link);
 | 
			
		||||
	endpoint->info.n_streams--;
 | 
			
		||||
 | 
			
		||||
	pw_properties_free(stream->props);
 | 
			
		||||
	free(stream);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void update_params(void *data)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t n_params;
 | 
			
		||||
| 
						 | 
				
			
			@ -309,7 +320,7 @@ static void update_params(void *data)
 | 
			
		|||
			&endpoint->info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct endpoint *make_endpoint(struct node *node, struct endpoint *monitor);
 | 
			
		||||
static struct endpoint *create_endpoint(struct node *node, struct endpoint *monitor);
 | 
			
		||||
 | 
			
		||||
static void object_update(void *data)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -371,7 +382,7 @@ static void complete_endpoint(void *data)
 | 
			
		|||
		struct endpoint *monitor;
 | 
			
		||||
 | 
			
		||||
		/* make monitor for sinks */
 | 
			
		||||
		monitor = make_endpoint(endpoint->node, endpoint);
 | 
			
		||||
		monitor = create_endpoint(endpoint->node, endpoint);
 | 
			
		||||
		if (monitor == NULL)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -382,42 +393,85 @@ static void complete_endpoint(void *data)
 | 
			
		|||
	sm_object_add_listener(&endpoint->node->node->obj, &endpoint->listener, &object_events, endpoint);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct endpoint *make_endpoint(struct node *node, struct endpoint *monitor)
 | 
			
		||||
static void proxy_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = data;
 | 
			
		||||
	struct stream *s;
 | 
			
		||||
 | 
			
		||||
	spa_list_consume(s, &endpoint->stream_list, link)
 | 
			
		||||
		destroy_stream(s);
 | 
			
		||||
 | 
			
		||||
	pw_properties_free(endpoint->props);
 | 
			
		||||
	spa_list_remove(&endpoint->link);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void proxy_bound(void *data, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = data;
 | 
			
		||||
	endpoint->info.id = id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_proxy_events proxy_events = {
 | 
			
		||||
	PW_VERSION_PROXY_EVENTS,
 | 
			
		||||
	.destroy = proxy_destroy,
 | 
			
		||||
	.bound = proxy_bound,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct endpoint *create_endpoint(struct node *node, struct endpoint *monitor)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = node->impl;
 | 
			
		||||
	struct device *device = node->device;
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
	struct endpoint *endpoint;
 | 
			
		||||
	struct pw_proxy *proxy;
 | 
			
		||||
	const char *str, *media_class = NULL, *name = NULL;
 | 
			
		||||
	uint32_t subscribe[4], n_subscribe = 0;
 | 
			
		||||
	struct pw_properties *pr = node->node->obj.props;
 | 
			
		||||
	enum pw_direction direction;
 | 
			
		||||
 | 
			
		||||
	if (pr == NULL) {
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((media_class = pw_properties_get(pr, PW_KEY_MEDIA_CLASS)) == NULL) {
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	props = pw_properties_new(NULL, NULL);
 | 
			
		||||
	if (props == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	if (pr) {
 | 
			
		||||
		if ((media_class = pw_properties_get(pr, PW_KEY_MEDIA_CLASS)) != NULL) {
 | 
			
		||||
			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(pr, PW_KEY_PRIORITY_SESSION)) != NULL)
 | 
			
		||||
			pw_properties_set(props, PW_KEY_PRIORITY_SESSION, str);
 | 
			
		||||
		if ((name = pw_properties_get(pr, PW_KEY_NODE_DESCRIPTION)) != NULL) {
 | 
			
		||||
			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 ((str = pw_properties_get(pr, PW_KEY_DEVICE_ICON_NAME)) != NULL)
 | 
			
		||||
			pw_properties_set(props, PW_KEY_ENDPOINT_ICON_NAME, str);
 | 
			
		||||
	if (strstr(media_class, "Source") != NULL) {
 | 
			
		||||
		direction = PW_DIRECTION_OUTPUT;
 | 
			
		||||
	} else if (strstr(media_class, "Sink") != NULL) {
 | 
			
		||||
		direction = PW_DIRECTION_INPUT;
 | 
			
		||||
	} else {
 | 
			
		||||
		errno = EINVAL;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (monitor != NULL) {
 | 
			
		||||
		pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Source");
 | 
			
		||||
		direction = PW_DIRECTION_OUTPUT;
 | 
			
		||||
	} else {
 | 
			
		||||
		pw_properties_set(props, PW_KEY_MEDIA_CLASS, media_class);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if ((str = pw_properties_get(pr, PW_KEY_PRIORITY_SESSION)) != NULL)
 | 
			
		||||
		pw_properties_set(props, PW_KEY_PRIORITY_SESSION, str);
 | 
			
		||||
	if ((name = pw_properties_get(pr, PW_KEY_NODE_DESCRIPTION)) != NULL) {
 | 
			
		||||
		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 ((str = pw_properties_get(pr, PW_KEY_DEVICE_ICON_NAME)) != NULL)
 | 
			
		||||
		pw_properties_set(props, PW_KEY_ENDPOINT_ICON_NAME, str);
 | 
			
		||||
 | 
			
		||||
	proxy = sm_media_session_create_object(impl->session,
 | 
			
		||||
						"client-endpoint",
 | 
			
		||||
						PW_TYPE_INTERFACE_ClientEndpoint,
 | 
			
		||||
| 
						 | 
				
			
			@ -429,6 +483,7 @@ static struct endpoint *make_endpoint(struct node *node, struct endpoint *monito
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	endpoint = pw_proxy_get_user_data(proxy);
 | 
			
		||||
	endpoint->impl = impl;
 | 
			
		||||
	endpoint->node = node;
 | 
			
		||||
	endpoint->monitor = monitor;
 | 
			
		||||
	endpoint->props = props;
 | 
			
		||||
| 
						 | 
				
			
			@ -437,7 +492,7 @@ static struct endpoint *make_endpoint(struct node *node, struct endpoint *monito
 | 
			
		|||
	endpoint->info.name = (char*)pw_properties_get(endpoint->props, PW_KEY_ENDPOINT_NAME);
 | 
			
		||||
	endpoint->info.media_class = (char*)pw_properties_get(endpoint->props, PW_KEY_MEDIA_CLASS);
 | 
			
		||||
	endpoint->info.session_id = impl->session->session->obj.id;
 | 
			
		||||
	endpoint->info.direction = monitor != NULL ? PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT;
 | 
			
		||||
	endpoint->info.direction = direction;
 | 
			
		||||
	endpoint->info.flags = 0;
 | 
			
		||||
	endpoint->info.change_mask =
 | 
			
		||||
		PW_ENDPOINT_CHANGE_MASK_STREAMS |
 | 
			
		||||
| 
						 | 
				
			
			@ -453,6 +508,9 @@ static struct endpoint *make_endpoint(struct node *node, struct endpoint *monito
 | 
			
		|||
	spa_list_init(&endpoint->stream_list);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME" %p: new endpoint %p for alsa node %p", impl, endpoint, node);
 | 
			
		||||
	pw_proxy_add_listener(proxy,
 | 
			
		||||
			&endpoint->proxy_listener,
 | 
			
		||||
			&proxy_events, endpoint);
 | 
			
		||||
 | 
			
		||||
	pw_client_endpoint_proxy_add_listener(endpoint->client_endpoint,
 | 
			
		||||
			&endpoint->client_endpoint_listener,
 | 
			
		||||
| 
						 | 
				
			
			@ -467,12 +525,19 @@ static struct endpoint *make_endpoint(struct node *node, struct endpoint *monito
 | 
			
		|||
	pw_node_proxy_subscribe_params((struct pw_node_proxy*)node->node->obj.proxy,
 | 
			
		||||
				subscribe, n_subscribe);
 | 
			
		||||
 | 
			
		||||
	spa_list_append(&device->endpoint_list, &endpoint->link);
 | 
			
		||||
 | 
			
		||||
	if (monitor == NULL)
 | 
			
		||||
		sm_media_session_sync(impl->session, complete_endpoint, endpoint);
 | 
			
		||||
 | 
			
		||||
	return endpoint;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void destroy_endpoint(struct endpoint *endpoint)
 | 
			
		||||
{
 | 
			
		||||
	pw_proxy_destroy((struct pw_proxy*)endpoint->client_endpoint);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** fallback, one stream for each node */
 | 
			
		||||
static int setup_alsa_fallback_endpoint(struct device *device)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -488,9 +553,10 @@ static int setup_alsa_fallback_endpoint(struct device *device)
 | 
			
		|||
		pw_log_debug(NAME" %p: device %p has node %p", impl, d, n);
 | 
			
		||||
 | 
			
		||||
		node = sm_object_add_data(&n->obj, SESSION_KEY, sizeof(struct node));
 | 
			
		||||
		node->device = device;
 | 
			
		||||
		node->node = n;
 | 
			
		||||
		node->impl = impl;
 | 
			
		||||
		node->endpoint = make_endpoint(node, NULL);
 | 
			
		||||
		node->endpoint = create_endpoint(node, NULL);
 | 
			
		||||
		if (node->endpoint == NULL)
 | 
			
		||||
			return -errno;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -550,7 +616,7 @@ exit:
 | 
			
		|||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int setup_alsa_endpoint(struct device *device)
 | 
			
		||||
static int activate_device(struct device *device)
 | 
			
		||||
{
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -560,6 +626,14 @@ static int setup_alsa_endpoint(struct device *device)
 | 
			
		|||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int deactivate_device(struct device *device)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *e;
 | 
			
		||||
	spa_list_consume(e, &device->endpoint_list, link)
 | 
			
		||||
		destroy_endpoint(e);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void device_update(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct device *device = data;
 | 
			
		||||
| 
						 | 
				
			
			@ -567,11 +641,13 @@ static void device_update(void *data)
 | 
			
		|||
 | 
			
		||||
	pw_log_debug(NAME" %p: device %p %08x %08x", impl, device,
 | 
			
		||||
			device->device->obj.avail, device->device->obj.changed);
 | 
			
		||||
	if (!(device->device->obj.avail & SM_DEVICE_CHANGE_MASK_INFO))
 | 
			
		||||
 | 
			
		||||
	if (!SPA_FLAG_IS_SET(device->device->obj.avail,
 | 
			
		||||
			SM_DEVICE_CHANGE_MASK_INFO | SM_DEVICE_CHANGE_MASK_PARAMS))
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (device->device->obj.changed & SM_DEVICE_CHANGE_MASK_PARAMS) {
 | 
			
		||||
		setup_alsa_endpoint(device);
 | 
			
		||||
		activate_device(device);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -603,6 +679,7 @@ handle_device(struct impl *impl, struct sm_object *obj)
 | 
			
		|||
	device->impl = impl;
 | 
			
		||||
	device->id = obj->id;
 | 
			
		||||
	device->device = (struct sm_device*)obj;
 | 
			
		||||
	spa_list_init(&device->endpoint_list);
 | 
			
		||||
	pw_log_debug(NAME" %p: found alsa device %d media_class %s", impl, obj->id, media_class);
 | 
			
		||||
 | 
			
		||||
	sm_object_add_listener(obj, &device->listener, &device_events, device);
 | 
			
		||||
| 
						 | 
				
			
			@ -610,6 +687,12 @@ handle_device(struct impl *impl, struct sm_object *obj)
 | 
			
		|||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void destroy_device(struct device *device)
 | 
			
		||||
{
 | 
			
		||||
	deactivate_device(device);
 | 
			
		||||
	spa_hook_remove(&device->listener);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void session_create(void *data, struct sm_object *object)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
| 
						 | 
				
			
			@ -634,7 +717,12 @@ static void session_remove(void *data, struct sm_object *object)
 | 
			
		|||
{
 | 
			
		||||
	switch (object->type) {
 | 
			
		||||
	case PW_TYPE_INTERFACE_Device:
 | 
			
		||||
	{
 | 
			
		||||
		struct device *device;
 | 
			
		||||
		if ((device = sm_object_get_data(object, SESSION_KEY)) != NULL)
 | 
			
		||||
			destroy_device(device);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,7 +55,7 @@
 | 
			
		|||
struct node {
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
	enum pw_direction direction;
 | 
			
		||||
	struct device *object;
 | 
			
		||||
	struct device *device;
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -77,14 +77,19 @@ struct device {
 | 
			
		|||
	int seq;
 | 
			
		||||
	int priority;
 | 
			
		||||
 | 
			
		||||
	int profile;
 | 
			
		||||
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
 | 
			
		||||
	struct spa_handle *handle;
 | 
			
		||||
	struct pw_proxy *proxy;
 | 
			
		||||
	struct spa_device *device;
 | 
			
		||||
	struct spa_hook device_listener;
 | 
			
		||||
 | 
			
		||||
	struct sm_device *sdevice;
 | 
			
		||||
	struct spa_hook listener;
 | 
			
		||||
 | 
			
		||||
	unsigned int first:1;
 | 
			
		||||
	unsigned int appeared:1;
 | 
			
		||||
	struct spa_list node_list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -107,18 +112,18 @@ struct impl {
 | 
			
		|||
#undef NAME
 | 
			
		||||
#define NAME "alsa-monitor"
 | 
			
		||||
 | 
			
		||||
static struct node *alsa_find_node(struct device *obj, uint32_t id)
 | 
			
		||||
static struct node *alsa_find_node(struct device *device, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct node *node;
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(node, &obj->node_list, link) {
 | 
			
		||||
	spa_list_for_each(node, &device->node_list, link) {
 | 
			
		||||
		if (node->id == id)
 | 
			
		||||
			return node;
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void alsa_update_node(struct device *obj, struct node *node,
 | 
			
		||||
static void alsa_update_node(struct device *device, struct node *node,
 | 
			
		||||
		const struct spa_device_object_info *info)
 | 
			
		||||
{
 | 
			
		||||
	pw_log_debug("update node %u", node->id);
 | 
			
		||||
| 
						 | 
				
			
			@ -129,11 +134,11 @@ static void alsa_update_node(struct device *obj, struct node *node,
 | 
			
		|||
	pw_properties_update(node->props, info->props);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct node *alsa_create_node(struct device *obj, uint32_t id,
 | 
			
		||||
static struct node *alsa_create_node(struct device *device, uint32_t id,
 | 
			
		||||
		const struct spa_device_object_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct node *node;
 | 
			
		||||
	struct impl *impl = obj->impl;
 | 
			
		||||
	struct impl *impl = device->impl;
 | 
			
		||||
	int res;
 | 
			
		||||
	const char *dev, *subdev, *stream;
 | 
			
		||||
	int priority;
 | 
			
		||||
| 
						 | 
				
			
			@ -152,8 +157,7 @@ static struct node *alsa_create_node(struct device *obj, uint32_t id,
 | 
			
		|||
 | 
			
		||||
	node->props = pw_properties_new_dict(info->props);
 | 
			
		||||
 | 
			
		||||
	if (obj->device_id != 0)
 | 
			
		||||
		pw_properties_setf(node->props, PW_KEY_DEVICE_ID, "%d", obj->device_id);
 | 
			
		||||
	pw_properties_setf(node->props, PW_KEY_DEVICE_ID, "%d", device->device_id);
 | 
			
		||||
 | 
			
		||||
	pw_properties_set(node->props, "factory.name", info->factory_name);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -169,13 +173,13 @@ static struct node *alsa_create_node(struct device *obj, uint32_t id,
 | 
			
		|||
	else
 | 
			
		||||
		node->direction = PW_DIRECTION_INPUT;
 | 
			
		||||
 | 
			
		||||
	if (obj->first) {
 | 
			
		||||
	if (device->first) {
 | 
			
		||||
		if (atol(dev) != 0)
 | 
			
		||||
			obj->priority -= 256;
 | 
			
		||||
		obj->first = false;
 | 
			
		||||
			device->priority -= 256;
 | 
			
		||||
		device->first = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	priority = obj->priority;
 | 
			
		||||
	priority = device->priority;
 | 
			
		||||
	if (!strcmp(stream, "capture"))
 | 
			
		||||
		priority += 1000;
 | 
			
		||||
	priority -= atol(dev) * 16;
 | 
			
		||||
| 
						 | 
				
			
			@ -194,7 +198,7 @@ static struct node *alsa_create_node(struct device *obj, uint32_t id,
 | 
			
		|||
	}
 | 
			
		||||
	if (pw_properties_get(node->props, SPA_KEY_NODE_NAME) == NULL) {
 | 
			
		||||
		const char *devname;
 | 
			
		||||
		if ((devname = pw_properties_get(obj->props, SPA_KEY_DEVICE_NAME)) == NULL)
 | 
			
		||||
		if ((devname = pw_properties_get(device->props, SPA_KEY_DEVICE_NAME)) == NULL)
 | 
			
		||||
			devname = "unknown";
 | 
			
		||||
		pw_properties_setf(node->props, SPA_KEY_NODE_NAME, "%s.%s.%s.%s",
 | 
			
		||||
				devname, stream, dev, subdev);
 | 
			
		||||
| 
						 | 
				
			
			@ -202,7 +206,7 @@ static struct node *alsa_create_node(struct device *obj, uint32_t id,
 | 
			
		|||
	if (pw_properties_get(node->props, PW_KEY_NODE_DESCRIPTION) == NULL) {
 | 
			
		||||
		const char *desc, *name = NULL;
 | 
			
		||||
 | 
			
		||||
		if ((desc = pw_properties_get(obj->props, SPA_KEY_DEVICE_DESCRIPTION)) == NULL)
 | 
			
		||||
		if ((desc = pw_properties_get(device->props, SPA_KEY_DEVICE_DESCRIPTION)) == NULL)
 | 
			
		||||
			desc = "unknown";
 | 
			
		||||
 | 
			
		||||
		name = pw_properties_get(node->props, SPA_KEY_API_ALSA_PCM_NAME);
 | 
			
		||||
| 
						 | 
				
			
			@ -224,17 +228,16 @@ static struct node *alsa_create_node(struct device *obj, uint32_t id,
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	node->impl = impl;
 | 
			
		||||
	node->object = obj;
 | 
			
		||||
	node->device = device;
 | 
			
		||||
	node->id = id;
 | 
			
		||||
	node->snode = sm_media_session_create_node(impl->session,
 | 
			
		||||
				"adapter",
 | 
			
		||||
				&node->props->dict,
 | 
			
		||||
                                0);
 | 
			
		||||
				&node->props->dict);
 | 
			
		||||
	if (node->snode == NULL) {
 | 
			
		||||
		res = -errno;
 | 
			
		||||
		goto clean_node;
 | 
			
		||||
	}
 | 
			
		||||
	spa_list_append(&obj->node_list, &node->link);
 | 
			
		||||
	spa_list_append(&device->node_list, &node->link);
 | 
			
		||||
 | 
			
		||||
	return node;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -246,7 +249,7 @@ exit:
 | 
			
		|||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void alsa_remove_node(struct device *obj, struct node *node)
 | 
			
		||||
static void alsa_remove_node(struct device *device, struct node *node)
 | 
			
		||||
{
 | 
			
		||||
	pw_log_debug("remove node %u", node->id);
 | 
			
		||||
	spa_list_remove(&node->link);
 | 
			
		||||
| 
						 | 
				
			
			@ -256,36 +259,32 @@ static void alsa_remove_node(struct device *obj, struct node *node)
 | 
			
		|||
 | 
			
		||||
static void alsa_device_info(void *data, const struct spa_device_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct device *obj = data;
 | 
			
		||||
	const char *str;
 | 
			
		||||
	struct device *device = data;
 | 
			
		||||
 | 
			
		||||
	if (pw_log_level_enabled(SPA_LOG_LEVEL_DEBUG))
 | 
			
		||||
		spa_debug_dict(0, info->props);
 | 
			
		||||
 | 
			
		||||
	pw_properties_update(obj->props, info->props);
 | 
			
		||||
 | 
			
		||||
	if ((str = pw_properties_get(obj->props, PW_KEY_DEVICE_ID)) != NULL)
 | 
			
		||||
		obj->device_id = pw_properties_parse_int(str);
 | 
			
		||||
	pw_properties_update(device->props, info->props);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void alsa_device_object_info(void *data, uint32_t id,
 | 
			
		||||
                const struct spa_device_object_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct device *obj = data;
 | 
			
		||||
	struct device *device = data;
 | 
			
		||||
	struct node *node;
 | 
			
		||||
 | 
			
		||||
	node = alsa_find_node(obj, id);
 | 
			
		||||
	node = alsa_find_node(device, id);
 | 
			
		||||
 | 
			
		||||
	if (info == NULL) {
 | 
			
		||||
		if (node == NULL) {
 | 
			
		||||
			pw_log_warn("object %p: unknown node %u", obj, id);
 | 
			
		||||
			pw_log_warn("device %p: unknown node %u", device, id);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		alsa_remove_node(obj, node);
 | 
			
		||||
		alsa_remove_node(device, node);
 | 
			
		||||
	} else if (node == NULL) {
 | 
			
		||||
		alsa_create_node(obj, id, info);
 | 
			
		||||
		alsa_create_node(device, id, info);
 | 
			
		||||
	} else {
 | 
			
		||||
		alsa_update_node(obj, node, info);
 | 
			
		||||
		alsa_update_node(device, node, info);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -297,11 +296,11 @@ static const struct spa_device_events alsa_device_events = {
 | 
			
		|||
 | 
			
		||||
static struct device *alsa_find_device(struct impl *impl, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct device *obj;
 | 
			
		||||
	struct device *device;
 | 
			
		||||
 | 
			
		||||
	spa_list_for_each(obj, &impl->device_list, link) {
 | 
			
		||||
		if (obj->id == id)
 | 
			
		||||
			return obj;
 | 
			
		||||
	spa_list_for_each(device, &impl->device_list, link) {
 | 
			
		||||
		if (device->id == id)
 | 
			
		||||
			return device;
 | 
			
		||||
	}
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -412,11 +411,17 @@ static void set_profile(struct device *device, int index)
 | 
			
		|||
{
 | 
			
		||||
	char buf[1024];
 | 
			
		||||
	struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
 | 
			
		||||
	spa_device_set_param(device->device,
 | 
			
		||||
			SPA_PARAM_Profile, 0,
 | 
			
		||||
			spa_pod_builder_add_object(&b,
 | 
			
		||||
				SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
 | 
			
		||||
				SPA_PARAM_PROFILE_index,   SPA_POD_Int(index)));
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("%p: set profile %d", device, device->device_id);
 | 
			
		||||
 | 
			
		||||
	device->profile = index;
 | 
			
		||||
	if (device->device_id != 0) {
 | 
			
		||||
		spa_device_set_param(device->device,
 | 
			
		||||
				SPA_PARAM_Profile, 0,
 | 
			
		||||
				spa_pod_builder_add_object(&b,
 | 
			
		||||
					SPA_TYPE_OBJECT_ParamProfile, SPA_PARAM_Profile,
 | 
			
		||||
					SPA_PARAM_PROFILE_index,   SPA_POD_Int(index)));
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void remove_jack_timeout(struct impl *impl)
 | 
			
		||||
| 
						 | 
				
			
			@ -459,8 +464,6 @@ static void reserve_acquired(void *data, struct rd_device *d)
 | 
			
		|||
	remove_jack_timeout(impl);
 | 
			
		||||
	set_jack_profile(impl, 0);
 | 
			
		||||
	set_profile(device, 1);
 | 
			
		||||
 | 
			
		||||
//	setup_alsa_endpoint(device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void sync_complete_done(void *data, int seq)
 | 
			
		||||
| 
						 | 
				
			
			@ -496,10 +499,10 @@ static void reserve_release(void *data, struct rd_device *d, int forced)
 | 
			
		|||
	set_profile(device, 0);
 | 
			
		||||
 | 
			
		||||
	if (device->seq == 0)
 | 
			
		||||
		pw_proxy_add_listener(device->proxy,
 | 
			
		||||
		pw_proxy_add_listener(device->sdevice->obj.proxy,
 | 
			
		||||
				&device->sync_listener,
 | 
			
		||||
				&sync_complete_release, device);
 | 
			
		||||
	device->seq = pw_proxy_sync(device->proxy, 0);
 | 
			
		||||
	device->seq = pw_proxy_sync(device->sdevice->obj.proxy, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct rd_device_callbacks reserve_callbacks = {
 | 
			
		||||
| 
						 | 
				
			
			@ -507,6 +510,32 @@ static const struct rd_device_callbacks reserve_callbacks = {
 | 
			
		|||
	.release = reserve_release,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static void device_update(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct device *device = data;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("device %p appeared %d %d", device, device->appeared, device->profile);
 | 
			
		||||
 | 
			
		||||
	if (device->appeared)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	device->device_id = device->sdevice->obj.id;
 | 
			
		||||
	device->appeared = true;
 | 
			
		||||
 | 
			
		||||
	spa_device_add_listener(device->device,
 | 
			
		||||
		&device->device_listener,
 | 
			
		||||
		&alsa_device_events, device);
 | 
			
		||||
 | 
			
		||||
	set_profile(device, device->profile);
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct sm_object_events device_events = {
 | 
			
		||||
	SM_VERSION_OBJECT_EVENTS,
 | 
			
		||||
        .update = device_update,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct device *alsa_create_device(struct impl *impl, uint32_t id,
 | 
			
		||||
		const struct spa_device_object_info *info)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -552,15 +581,18 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id,
 | 
			
		|||
	device->priority = 1000;
 | 
			
		||||
	update_device_props(device);
 | 
			
		||||
 | 
			
		||||
	device->proxy = sm_media_session_export(impl->session,
 | 
			
		||||
			info->type,
 | 
			
		||||
	device->sdevice = sm_media_session_export_device(impl->session,
 | 
			
		||||
			pw_properties_copy(device->props),
 | 
			
		||||
			device->device, 0);
 | 
			
		||||
	if (device->proxy == NULL) {
 | 
			
		||||
			device->device);
 | 
			
		||||
	if (device->sdevice == NULL) {
 | 
			
		||||
		res = -errno;
 | 
			
		||||
		goto clean_device;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sm_object_add_listener(&device->sdevice->obj,
 | 
			
		||||
			&device->listener,
 | 
			
		||||
			&device_events, device);
 | 
			
		||||
 | 
			
		||||
	if ((card = spa_dict_lookup(info->props, SPA_KEY_API_ALSA_CARD)) != NULL) {
 | 
			
		||||
		const char *reserve;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -586,10 +618,6 @@ static struct device *alsa_create_device(struct impl *impl, uint32_t id,
 | 
			
		|||
 | 
			
		||||
	device->first = true;
 | 
			
		||||
	spa_list_init(&device->node_list);
 | 
			
		||||
 | 
			
		||||
	spa_device_add_listener(device->device,
 | 
			
		||||
			&device->device_listener, &alsa_device_events, device);
 | 
			
		||||
 | 
			
		||||
	spa_list_append(&impl->device_list, &device->link);
 | 
			
		||||
 | 
			
		||||
	return device;
 | 
			
		||||
| 
						 | 
				
			
			@ -603,37 +631,39 @@ exit:
 | 
			
		|||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void alsa_remove_device(struct impl *impl, struct device *obj)
 | 
			
		||||
static void alsa_remove_device(struct impl *impl, struct device *device)
 | 
			
		||||
{
 | 
			
		||||
	pw_log_debug("remove device %u", obj->id);
 | 
			
		||||
	spa_list_remove(&obj->link);
 | 
			
		||||
	spa_hook_remove(&obj->device_listener);
 | 
			
		||||
	if (obj->seq != 0)
 | 
			
		||||
		spa_hook_remove(&obj->sync_listener);
 | 
			
		||||
	if (obj->reserve)
 | 
			
		||||
		rd_device_destroy(obj->reserve);
 | 
			
		||||
	pw_proxy_destroy(obj->proxy);
 | 
			
		||||
	pw_unload_spa_handle(obj->handle);
 | 
			
		||||
	free(obj);
 | 
			
		||||
	pw_log_debug("remove device %u", device->id);
 | 
			
		||||
	spa_list_remove(&device->link);
 | 
			
		||||
	spa_hook_remove(&device->listener);
 | 
			
		||||
	spa_hook_remove(&device->device_listener);
 | 
			
		||||
	if (device->seq != 0)
 | 
			
		||||
		spa_hook_remove(&device->sync_listener);
 | 
			
		||||
	if (device->reserve)
 | 
			
		||||
		rd_device_destroy(device->reserve);
 | 
			
		||||
	if (device->sdevice)
 | 
			
		||||
		sm_object_destroy(&device->sdevice->obj);
 | 
			
		||||
	pw_unload_spa_handle(device->handle);
 | 
			
		||||
	free(device);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void alsa_udev_object_info(void *data, uint32_t id,
 | 
			
		||||
                const struct spa_device_object_info *info)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
	struct device *obj;
 | 
			
		||||
	struct device *device;
 | 
			
		||||
 | 
			
		||||
	obj = alsa_find_device(impl, id);
 | 
			
		||||
	device = alsa_find_device(impl, id);
 | 
			
		||||
 | 
			
		||||
	if (info == NULL) {
 | 
			
		||||
		if (obj == NULL)
 | 
			
		||||
		if (device == NULL)
 | 
			
		||||
			return;
 | 
			
		||||
		alsa_remove_device(impl, obj);
 | 
			
		||||
	} else if (obj == NULL) {
 | 
			
		||||
		if ((obj = alsa_create_device(impl, id, info)) == NULL)
 | 
			
		||||
		alsa_remove_device(impl, device);
 | 
			
		||||
	} else if (device == NULL) {
 | 
			
		||||
		if ((device = alsa_create_device(impl, id, info)) == NULL)
 | 
			
		||||
			return;
 | 
			
		||||
	} else {
 | 
			
		||||
		alsa_update_device(impl, obj, info);
 | 
			
		||||
		alsa_update_device(impl, device, info);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -663,6 +693,8 @@ static int alsa_start_jack_device(struct impl *impl)
 | 
			
		|||
	if (impl->jack_device == NULL)
 | 
			
		||||
		res = -errno;
 | 
			
		||||
 | 
			
		||||
	pw_properties_free(props);
 | 
			
		||||
 | 
			
		||||
	return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -109,6 +109,7 @@ struct impl {
 | 
			
		|||
	struct spa_hook_list hooks;
 | 
			
		||||
 | 
			
		||||
	struct pw_client_session_proxy *client_session;
 | 
			
		||||
	struct spa_hook client_session_proxy_listener;
 | 
			
		||||
	struct spa_hook client_session_listener;
 | 
			
		||||
 | 
			
		||||
	struct spa_list endpoint_link_list;	/** list of struct endpoint_link */
 | 
			
		||||
| 
						 | 
				
			
			@ -143,6 +144,15 @@ struct link {
 | 
			
		|||
	struct spa_list link;		/**< link in struct endpoint_link link_list */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct object_info {
 | 
			
		||||
	uint32_t type;
 | 
			
		||||
	uint32_t version;
 | 
			
		||||
	const void *events;
 | 
			
		||||
	size_t size;
 | 
			
		||||
	int (*init) (void *object);
 | 
			
		||||
	void (*destroy) (void *object);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void add_object(struct impl *impl, struct sm_object *obj)
 | 
			
		||||
{
 | 
			
		||||
	size_t size = pw_map_get_size(&impl->globals);
 | 
			
		||||
| 
						 | 
				
			
			@ -291,6 +301,15 @@ static void client_destroy(void *object)
 | 
			
		|||
		pw_client_info_free(client->info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct object_info client_info = {
 | 
			
		||||
	.type = PW_TYPE_INTERFACE_Client,
 | 
			
		||||
	.version = PW_VERSION_CLIENT_PROXY,
 | 
			
		||||
	.events = &client_events,
 | 
			
		||||
	.size = sizeof(struct sm_client),
 | 
			
		||||
	.init = NULL,
 | 
			
		||||
	.destroy = client_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Device
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -335,6 +354,14 @@ static const struct pw_device_proxy_events device_events = {
 | 
			
		|||
	.param = device_event_param,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int device_init(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_device *device = object;
 | 
			
		||||
	spa_list_init(&device->node_list);
 | 
			
		||||
	spa_list_init(&device->param_list);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void device_destroy(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_device *device = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -351,6 +378,23 @@ static void device_destroy(void *object)
 | 
			
		|||
		pw_device_info_free(device->info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct object_info device_info = {
 | 
			
		||||
	.type = PW_TYPE_INTERFACE_Device,
 | 
			
		||||
	.version = PW_VERSION_DEVICE_PROXY,
 | 
			
		||||
	.events = &device_events,
 | 
			
		||||
	.size = sizeof(struct sm_device),
 | 
			
		||||
	.init = device_init,
 | 
			
		||||
	.destroy = device_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static const struct object_info spa_device_info = {
 | 
			
		||||
	.type = SPA_TYPE_INTERFACE_Device,
 | 
			
		||||
	.version = SPA_VERSION_DEVICE,
 | 
			
		||||
	.size = sizeof(struct sm_device),
 | 
			
		||||
	.init = device_init,
 | 
			
		||||
	.destroy = device_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Node
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -363,12 +407,6 @@ static void node_event_info(void *object, const struct pw_node_info *info)
 | 
			
		|||
	pw_log_debug(NAME" %p: node %d info", impl, node->obj.id);
 | 
			
		||||
	node->info = pw_node_info_update(node->info, info);
 | 
			
		||||
 | 
			
		||||
	if (node->obj.id == SPA_ID_INVALID) {
 | 
			
		||||
		node->obj.id = info->id;
 | 
			
		||||
		pw_log_debug(NAME" %p: node %d added", impl, node->obj.id);
 | 
			
		||||
		add_object(impl, &node->obj);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	node->obj.avail |= SM_NODE_CHANGE_MASK_INFO;
 | 
			
		||||
	node->obj.changed |= SM_NODE_CHANGE_MASK_INFO;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -428,6 +466,28 @@ static const struct pw_node_proxy_events node_events = {
 | 
			
		|||
	.param = node_event_param,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int node_init(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_node *node = object;
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(node->obj.session, struct impl, this);
 | 
			
		||||
	struct pw_properties *props = node->obj.props;
 | 
			
		||||
	const char *str;
 | 
			
		||||
 | 
			
		||||
	spa_list_init(&node->port_list);
 | 
			
		||||
	spa_list_init(&node->param_list);
 | 
			
		||||
 | 
			
		||||
	if (props) {
 | 
			
		||||
		if ((str = pw_properties_get(props, PW_KEY_DEVICE_ID)) != NULL)
 | 
			
		||||
			node->device = find_object(impl, atoi(str));
 | 
			
		||||
		pw_log_debug(NAME" %p: node %d parent device %s", impl, node->obj.id, str);
 | 
			
		||||
		if (node->device) {
 | 
			
		||||
			spa_list_append(&node->device->node_list, &node->link);
 | 
			
		||||
			node->device->obj.changed |= SM_DEVICE_CHANGE_MASK_NODES;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void node_destroy(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_node *node = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -448,6 +508,15 @@ static void node_destroy(void *object)
 | 
			
		|||
		pw_node_info_free(node->info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct object_info node_info = {
 | 
			
		||||
	.type = PW_TYPE_INTERFACE_Node,
 | 
			
		||||
	.version = PW_VERSION_NODE_PROXY,
 | 
			
		||||
	.events = &node_events,
 | 
			
		||||
	.size = sizeof(struct sm_node),
 | 
			
		||||
	.init = node_init,
 | 
			
		||||
	.destroy = node_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Port
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -469,6 +538,30 @@ static const struct pw_port_proxy_events port_events = {
 | 
			
		|||
	.info = port_event_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int port_init(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_port *port = object;
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(port->obj.session, struct impl, this);
 | 
			
		||||
	struct pw_properties *props = port->obj.props;
 | 
			
		||||
	const char *str;
 | 
			
		||||
 | 
			
		||||
	if (props) {
 | 
			
		||||
		if ((str = pw_properties_get(props, PW_KEY_PORT_DIRECTION)) != NULL)
 | 
			
		||||
			port->direction = strcmp(str, "out") == 0 ?
 | 
			
		||||
				PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT;
 | 
			
		||||
		if ((str = pw_properties_get(props, PW_KEY_NODE_ID)) != NULL)
 | 
			
		||||
			port->node = find_object(impl, atoi(str));
 | 
			
		||||
 | 
			
		||||
		pw_log_debug(NAME" %p: port %d parent node %s direction:%d", impl,
 | 
			
		||||
				port->obj.id, str, port->direction);
 | 
			
		||||
		if (port->node) {
 | 
			
		||||
			spa_list_append(&port->node->port_list, &port->link);
 | 
			
		||||
			port->node->obj.changed |= SM_NODE_CHANGE_MASK_PORTS;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void port_destroy(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_port *port = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -480,6 +573,15 @@ static void port_destroy(void *object)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct object_info port_info = {
 | 
			
		||||
	.type = PW_TYPE_INTERFACE_Port,
 | 
			
		||||
	.version = PW_VERSION_PORT_PROXY,
 | 
			
		||||
	.events = &port_events,
 | 
			
		||||
	.size = sizeof(struct sm_port),
 | 
			
		||||
	.init = port_init,
 | 
			
		||||
	.destroy = port_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Session
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -512,6 +614,18 @@ static const struct pw_session_proxy_events session_events = {
 | 
			
		|||
	.info = session_event_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int session_init(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_session *sess = object;
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(sess->obj.session, struct impl, this);
 | 
			
		||||
 | 
			
		||||
	if (sess->obj.id == impl->session_id)
 | 
			
		||||
		impl->this.session = sess;
 | 
			
		||||
 | 
			
		||||
	spa_list_init(&sess->endpoint_list);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void session_destroy(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_session *sess = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -527,6 +641,15 @@ static void session_destroy(void *object)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct object_info session_info = {
 | 
			
		||||
	.type = PW_TYPE_INTERFACE_Session,
 | 
			
		||||
	.version = PW_VERSION_SESSION_PROXY,
 | 
			
		||||
	.events = &session_events,
 | 
			
		||||
	.size = sizeof(struct sm_session),
 | 
			
		||||
	.init = session_init,
 | 
			
		||||
	.destroy = session_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Endpoint
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -568,6 +691,28 @@ static const struct pw_endpoint_proxy_events endpoint_events = {
 | 
			
		|||
	.info = endpoint_event_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int endpoint_init(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_endpoint *endpoint = object;
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(endpoint->obj.session, struct impl, this);
 | 
			
		||||
	struct pw_properties *props = endpoint->obj.props;
 | 
			
		||||
	const char *str;
 | 
			
		||||
 | 
			
		||||
	if (props) {
 | 
			
		||||
		if ((str = pw_properties_get(props, PW_KEY_SESSION_ID)) != NULL)
 | 
			
		||||
			endpoint->session = find_object(impl, atoi(str));
 | 
			
		||||
		pw_log_debug(NAME" %p: endpoint %d parent session %s", impl,
 | 
			
		||||
				endpoint->obj.id, str);
 | 
			
		||||
		if (endpoint->session) {
 | 
			
		||||
			spa_list_append(&endpoint->session->endpoint_list, &endpoint->link);
 | 
			
		||||
			endpoint->session->obj.changed |= SM_SESSION_CHANGE_MASK_ENDPOINTS;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	spa_list_init(&endpoint->stream_list);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void endpoint_destroy(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_endpoint *endpoint = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -589,6 +734,16 @@ static void endpoint_destroy(void *object)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct object_info endpoint_info = {
 | 
			
		||||
	.type = PW_TYPE_INTERFACE_Endpoint,
 | 
			
		||||
	.version = PW_VERSION_ENDPOINT_PROXY,
 | 
			
		||||
	.events = &endpoint_events,
 | 
			
		||||
	.size = sizeof(struct sm_endpoint),
 | 
			
		||||
	.init = endpoint_init,
 | 
			
		||||
	.destroy = endpoint_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Endpoint Stream
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -617,6 +772,28 @@ static const struct pw_endpoint_stream_proxy_events endpoint_stream_events = {
 | 
			
		|||
	.info = endpoint_stream_event_info,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int endpoint_stream_init(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_endpoint_stream *stream = object;
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(stream->obj.session, struct impl, this);
 | 
			
		||||
	struct pw_properties *props = stream->obj.props;
 | 
			
		||||
	const char *str;
 | 
			
		||||
 | 
			
		||||
	if (props) {
 | 
			
		||||
		if ((str = pw_properties_get(props, PW_KEY_ENDPOINT_ID)) != NULL)
 | 
			
		||||
			stream->endpoint = find_object(impl, atoi(str));
 | 
			
		||||
		pw_log_debug(NAME" %p: stream %d parent endpoint %s", impl,
 | 
			
		||||
				stream->obj.id, str);
 | 
			
		||||
		if (stream->endpoint) {
 | 
			
		||||
			spa_list_append(&stream->endpoint->stream_list, &stream->link);
 | 
			
		||||
			stream->endpoint->obj.changed |= SM_ENDPOINT_CHANGE_MASK_STREAMS;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	spa_list_init(&stream->link_list);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void endpoint_stream_destroy(void *object)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_endpoint_stream *stream = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -630,6 +807,16 @@ static void endpoint_stream_destroy(void *object)
 | 
			
		|||
		spa_list_remove(&stream->link);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct object_info endpoint_stream_info = {
 | 
			
		||||
	.type = PW_TYPE_INTERFACE_EndpointStream,
 | 
			
		||||
	.version = PW_VERSION_ENDPOINT_STREAM_PROXY,
 | 
			
		||||
	.events = &endpoint_stream_events,
 | 
			
		||||
	.size = sizeof(struct sm_endpoint_stream),
 | 
			
		||||
	.init = endpoint_stream_init,
 | 
			
		||||
	.destroy = endpoint_stream_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Endpoint Link
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -679,6 +866,15 @@ static void endpoint_link_destroy(void *object)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct object_info endpoint_link_info = {
 | 
			
		||||
	.type = PW_TYPE_INTERFACE_EndpointLink,
 | 
			
		||||
	.version = PW_VERSION_ENDPOINT_STREAM_PROXY,
 | 
			
		||||
	.events = &endpoint_link_events,
 | 
			
		||||
	.size = sizeof(struct sm_endpoint_link),
 | 
			
		||||
	.init = NULL,
 | 
			
		||||
	.destroy = endpoint_link_destroy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Proxy
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -705,210 +901,177 @@ static void done_proxy(void *data, int seq)
 | 
			
		|||
	obj->changed = 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void bound_proxy(void *data, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_object *obj = data;
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("bound %p proxy %p id:%d", obj, obj->proxy, id);
 | 
			
		||||
 | 
			
		||||
	if (obj->id == SPA_ID_INVALID) {
 | 
			
		||||
		obj->id = id;
 | 
			
		||||
		pw_log_debug("bound %p proxy %p id:%d", obj, obj->proxy, id);
 | 
			
		||||
		add_object(impl, obj);
 | 
			
		||||
		sm_media_session_emit_create(impl, obj);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_proxy_events proxy_events = {
 | 
			
		||||
        PW_VERSION_PROXY_EVENTS,
 | 
			
		||||
        .destroy = destroy_proxy,
 | 
			
		||||
        .done = done_proxy,
 | 
			
		||||
        .bound = bound_proxy,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
init_object(struct impl *impl, struct sm_object *obj, uint32_t id,
 | 
			
		||||
static const struct object_info *get_object_info(struct impl *impl, uint32_t type)
 | 
			
		||||
{
 | 
			
		||||
	const struct object_info *info;
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case PW_TYPE_INTERFACE_Client:
 | 
			
		||||
		info = &client_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case SPA_TYPE_INTERFACE_Device:
 | 
			
		||||
		info = &spa_device_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_TYPE_INTERFACE_Device:
 | 
			
		||||
		info = &device_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_TYPE_INTERFACE_Node:
 | 
			
		||||
		info = &node_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_TYPE_INTERFACE_Port:
 | 
			
		||||
		info = &port_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_TYPE_INTERFACE_Session:
 | 
			
		||||
		info = &session_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_TYPE_INTERFACE_Endpoint:
 | 
			
		||||
		info = &endpoint_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_TYPE_INTERFACE_EndpointStream:
 | 
			
		||||
		info = &endpoint_stream_info;
 | 
			
		||||
		break;
 | 
			
		||||
	case PW_TYPE_INTERFACE_EndpointLink:
 | 
			
		||||
		info = &endpoint_link_info;
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
		info = NULL;
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	return info;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct sm_object *init_object(struct impl *impl, const struct object_info *info,
 | 
			
		||||
		struct pw_proxy *proxy, uint32_t id,
 | 
			
		||||
		const struct spa_dict *props)
 | 
			
		||||
{
 | 
			
		||||
	struct sm_object *obj;
 | 
			
		||||
 | 
			
		||||
	obj = pw_proxy_get_user_data(proxy);
 | 
			
		||||
	obj->session = &impl->this;
 | 
			
		||||
	obj->id = id;
 | 
			
		||||
	obj->type = info->type;
 | 
			
		||||
	obj->props = props ? pw_properties_new_dict(props) : pw_properties_new(NULL, NULL);
 | 
			
		||||
	obj->proxy = proxy;
 | 
			
		||||
	obj->destroy = info->destroy;
 | 
			
		||||
	obj->mask |= SM_OBJECT_CHANGE_MASK_PROPERTIES | SM_OBJECT_CHANGE_MASK_BIND;
 | 
			
		||||
	obj->avail |= obj->mask;
 | 
			
		||||
	spa_hook_list_init(&obj->hooks);
 | 
			
		||||
	spa_list_init(&obj->data);
 | 
			
		||||
 | 
			
		||||
	pw_proxy_add_listener(obj->proxy, &obj->proxy_listener, &proxy_events, obj);
 | 
			
		||||
	if (info->events != NULL)
 | 
			
		||||
		pw_proxy_add_object_listener(obj->proxy, &obj->object_listener, info->events, obj);
 | 
			
		||||
	SPA_FLAG_UPDATE(obj->mask, SM_OBJECT_CHANGE_MASK_LISTENER, info->events != NULL);
 | 
			
		||||
 | 
			
		||||
	if (info->init)
 | 
			
		||||
		info->init(obj);
 | 
			
		||||
 | 
			
		||||
	if (id != SPA_ID_INVALID) {
 | 
			
		||||
		add_object(impl, obj);
 | 
			
		||||
		sm_media_session_emit_create(impl, obj);
 | 
			
		||||
	}
 | 
			
		||||
	return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct sm_object *
 | 
			
		||||
create_object(struct impl *impl, struct pw_proxy *proxy,
 | 
			
		||||
		const struct spa_dict *props)
 | 
			
		||||
{
 | 
			
		||||
	uint32_t type;
 | 
			
		||||
	const struct object_info *info;
 | 
			
		||||
	struct sm_object *obj;
 | 
			
		||||
 | 
			
		||||
	type = pw_proxy_get_type(proxy, NULL);
 | 
			
		||||
 | 
			
		||||
	info = get_object_info(impl, type);
 | 
			
		||||
	if (info == NULL) {
 | 
			
		||||
		pw_log_error(NAME" %p: unknown object type %d", impl, type);
 | 
			
		||||
		errno = ENOTSUP;
 | 
			
		||||
		return NULL;
 | 
			
		||||
	}
 | 
			
		||||
	obj = init_object(impl, info, proxy, SPA_ID_INVALID, props);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME" %p: created new object %p proxy %p", impl, obj, obj->proxy);
 | 
			
		||||
 | 
			
		||||
	return obj;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct sm_object *
 | 
			
		||||
bind_object(struct impl *impl, const struct object_info *info, uint32_t id,
 | 
			
		||||
		uint32_t permissions, uint32_t type, uint32_t version,
 | 
			
		||||
		const struct spa_dict *props)
 | 
			
		||||
{
 | 
			
		||||
	int res;
 | 
			
		||||
	const void *events;
 | 
			
		||||
        uint32_t client_version;
 | 
			
		||||
        pw_destroy_t destroy;
 | 
			
		||||
	size_t user_data_size;
 | 
			
		||||
	const char *str;
 | 
			
		||||
	struct pw_proxy *proxy;
 | 
			
		||||
	struct sm_object *obj;
 | 
			
		||||
 | 
			
		||||
	proxy = obj ? obj->proxy : NULL;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: init '%d' %d", impl, id, type);
 | 
			
		||||
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case PW_TYPE_INTERFACE_Client:
 | 
			
		||||
		events = &client_events;
 | 
			
		||||
                client_version = PW_VERSION_CLIENT_PROXY;
 | 
			
		||||
                destroy = (pw_destroy_t) client_destroy;
 | 
			
		||||
		user_data_size = sizeof(struct sm_client);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case PW_TYPE_INTERFACE_Device:
 | 
			
		||||
		events = &device_events;
 | 
			
		||||
                client_version = PW_VERSION_DEVICE_PROXY;
 | 
			
		||||
                destroy = (pw_destroy_t) device_destroy;
 | 
			
		||||
		user_data_size = sizeof(struct sm_device);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case PW_TYPE_INTERFACE_Node:
 | 
			
		||||
		events = &node_events;
 | 
			
		||||
                client_version = PW_VERSION_NODE_PROXY;
 | 
			
		||||
                destroy = (pw_destroy_t) node_destroy;
 | 
			
		||||
		user_data_size = sizeof(struct sm_node);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case PW_TYPE_INTERFACE_Port:
 | 
			
		||||
		events = &port_events;
 | 
			
		||||
                client_version = PW_VERSION_PORT_PROXY;
 | 
			
		||||
                destroy = (pw_destroy_t) port_destroy;
 | 
			
		||||
		user_data_size = sizeof(struct sm_port);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case PW_TYPE_INTERFACE_Session:
 | 
			
		||||
		events = &session_events;
 | 
			
		||||
                client_version = PW_VERSION_SESSION_PROXY;
 | 
			
		||||
                destroy = (pw_destroy_t) session_destroy;
 | 
			
		||||
		user_data_size = sizeof(struct sm_session);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case PW_TYPE_INTERFACE_Endpoint:
 | 
			
		||||
		events = &endpoint_events;
 | 
			
		||||
                client_version = PW_VERSION_ENDPOINT_PROXY;
 | 
			
		||||
                destroy = (pw_destroy_t) endpoint_destroy;
 | 
			
		||||
		user_data_size = sizeof(struct sm_endpoint);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case PW_TYPE_INTERFACE_EndpointStream:
 | 
			
		||||
		events = &endpoint_stream_events;
 | 
			
		||||
                client_version = PW_VERSION_ENDPOINT_STREAM_PROXY;
 | 
			
		||||
                destroy = (pw_destroy_t) endpoint_stream_destroy;
 | 
			
		||||
		user_data_size = sizeof(struct sm_endpoint_stream);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case PW_TYPE_INTERFACE_EndpointLink:
 | 
			
		||||
		events = &endpoint_link_events;
 | 
			
		||||
		client_version = PW_VERSION_ENDPOINT_LINK_PROXY;
 | 
			
		||||
		destroy = (pw_destroy_t) endpoint_link_destroy;
 | 
			
		||||
		user_data_size = sizeof(struct sm_endpoint_link);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	proxy = pw_registry_proxy_bind(impl->registry_proxy,
 | 
			
		||||
			id, type, info->version, info->size);
 | 
			
		||||
	if (proxy == NULL) {
 | 
			
		||||
		proxy = pw_registry_proxy_bind(impl->registry_proxy,
 | 
			
		||||
				id, type, client_version, user_data_size);
 | 
			
		||||
		if (proxy == NULL) {
 | 
			
		||||
			res = -errno;
 | 
			
		||||
			goto error;
 | 
			
		||||
		}
 | 
			
		||||
		res = -errno;
 | 
			
		||||
		goto error;
 | 
			
		||||
	}
 | 
			
		||||
	if (obj == NULL)
 | 
			
		||||
		obj = pw_proxy_get_user_data(proxy);
 | 
			
		||||
	obj->session = &impl->this;
 | 
			
		||||
	obj->id = id;
 | 
			
		||||
	obj->type = type;
 | 
			
		||||
	obj->props = props ? pw_properties_new_dict(props) : pw_properties_new(NULL, NULL);
 | 
			
		||||
	obj->proxy = proxy;
 | 
			
		||||
	obj->destroy = destroy;
 | 
			
		||||
	obj->mask = SM_OBJECT_CHANGE_MASK_PROPERTIES | SM_OBJECT_CHANGE_MASK_BIND;
 | 
			
		||||
	obj->avail = obj->mask;
 | 
			
		||||
	spa_hook_list_init(&obj->hooks);
 | 
			
		||||
	spa_list_init(&obj->data);
 | 
			
		||||
	if (id != SPA_ID_INVALID)
 | 
			
		||||
		add_object(impl, obj);
 | 
			
		||||
	obj = init_object(impl, info, proxy, id, props);
 | 
			
		||||
 | 
			
		||||
	pw_proxy_add_listener(proxy, &obj->proxy_listener, &proxy_events, obj);
 | 
			
		||||
	pw_log_debug(NAME" %p: bound new object %p proxy %p id:%d", impl, obj, obj->proxy, obj->id);
 | 
			
		||||
 | 
			
		||||
	switch (type) {
 | 
			
		||||
	case PW_TYPE_INTERFACE_Device:
 | 
			
		||||
	{
 | 
			
		||||
		struct sm_device *device = (struct sm_device*) obj;
 | 
			
		||||
		spa_list_init(&device->node_list);
 | 
			
		||||
		spa_list_init(&device->param_list);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	case PW_TYPE_INTERFACE_Node:
 | 
			
		||||
	{
 | 
			
		||||
		struct sm_node *node = (struct sm_node*) obj;
 | 
			
		||||
		spa_list_init(&node->port_list);
 | 
			
		||||
		spa_list_init(&node->param_list);
 | 
			
		||||
 | 
			
		||||
		if (props) {
 | 
			
		||||
			if ((str = spa_dict_lookup(props, PW_KEY_DEVICE_ID)) != NULL)
 | 
			
		||||
				node->device = find_object(impl, atoi(str));
 | 
			
		||||
			pw_log_debug(NAME" %p: node %d parent device %s", impl, id, str);
 | 
			
		||||
			if (node->device) {
 | 
			
		||||
				spa_list_append(&node->device->node_list, &node->link);
 | 
			
		||||
				node->device->obj.changed |= SM_DEVICE_CHANGE_MASK_NODES;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	case PW_TYPE_INTERFACE_Port:
 | 
			
		||||
	{
 | 
			
		||||
		struct sm_port *port = (struct sm_port*) obj;
 | 
			
		||||
 | 
			
		||||
		if (props) {
 | 
			
		||||
			if ((str = spa_dict_lookup(props, PW_KEY_PORT_DIRECTION)) != NULL)
 | 
			
		||||
				port->direction = strcmp(str, "out") == 0 ?
 | 
			
		||||
					PW_DIRECTION_OUTPUT : PW_DIRECTION_INPUT;
 | 
			
		||||
			if ((str = spa_dict_lookup(props, PW_KEY_NODE_ID)) != NULL)
 | 
			
		||||
				port->node = find_object(impl, atoi(str));
 | 
			
		||||
 | 
			
		||||
			pw_log_debug(NAME" %p: port %d parent node %s direction:%d", impl, id, str,
 | 
			
		||||
					port->direction);
 | 
			
		||||
			if (port->node) {
 | 
			
		||||
				spa_list_append(&port->node->port_list, &port->link);
 | 
			
		||||
				port->node->obj.changed |= SM_NODE_CHANGE_MASK_PORTS;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	case PW_TYPE_INTERFACE_Session:
 | 
			
		||||
	{
 | 
			
		||||
		struct sm_session *sess = (struct sm_session*) obj;
 | 
			
		||||
		if (id == impl->session_id)
 | 
			
		||||
			impl->this.session = sess;
 | 
			
		||||
		spa_list_init(&sess->endpoint_list);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	case PW_TYPE_INTERFACE_Endpoint:
 | 
			
		||||
	{
 | 
			
		||||
		struct sm_endpoint *endpoint = (struct sm_endpoint*) obj;
 | 
			
		||||
		if (props) {
 | 
			
		||||
			if ((str = spa_dict_lookup(props, PW_KEY_SESSION_ID)) != NULL)
 | 
			
		||||
				endpoint->session = find_object(impl, atoi(str));
 | 
			
		||||
			pw_log_debug(NAME" %p: endpoint %d parent session %s", impl, id, str);
 | 
			
		||||
			if (endpoint->session)
 | 
			
		||||
				spa_list_append(&endpoint->session->endpoint_list, &endpoint->link);
 | 
			
		||||
		}
 | 
			
		||||
		spa_list_init(&endpoint->stream_list);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	case PW_TYPE_INTERFACE_EndpointStream:
 | 
			
		||||
	{
 | 
			
		||||
		struct sm_endpoint_stream *stream = (struct sm_endpoint_stream*) obj;
 | 
			
		||||
 | 
			
		||||
		if (props) {
 | 
			
		||||
			if ((str = spa_dict_lookup(props, PW_KEY_ENDPOINT_ID)) != NULL)
 | 
			
		||||
				stream->endpoint = find_object(impl, atoi(str));
 | 
			
		||||
			pw_log_debug(NAME" %p: stream %d parent endpoint %s", impl, id, str);
 | 
			
		||||
			if (stream->endpoint) {
 | 
			
		||||
				spa_list_append(&stream->endpoint->stream_list, &stream->link);
 | 
			
		||||
				stream->endpoint->obj.changed |= SM_ENDPOINT_CHANGE_MASK_STREAMS;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		spa_list_init(&stream->link_list);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	default:
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME" %p: created new object %p id:%d", impl, obj, obj->id);
 | 
			
		||||
	sm_media_session_emit_create(impl, obj);
 | 
			
		||||
	pw_proxy_add_object_listener(proxy, &obj->object_listener, events, obj);
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
	return obj;
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	pw_log_warn(NAME" %p: can't handle global %d: %s", impl, id, spa_strerror(res));
 | 
			
		||||
	errno = -res;
 | 
			
		||||
	return NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
update_object(struct impl *impl, const struct object_info *info,
 | 
			
		||||
		struct sm_object *obj, uint32_t id,
 | 
			
		||||
		uint32_t permissions, uint32_t type, uint32_t version,
 | 
			
		||||
		const struct spa_dict *props)
 | 
			
		||||
{
 | 
			
		||||
	pw_properties_update(obj->props, props);
 | 
			
		||||
 | 
			
		||||
	if (obj->type == type)
 | 
			
		||||
		return 0;
 | 
			
		||||
 | 
			
		||||
	spa_hook_remove(&obj->proxy_listener);
 | 
			
		||||
	if (SPA_FLAG_IS_SET(obj->mask, SM_OBJECT_CHANGE_MASK_LISTENER))
 | 
			
		||||
		spa_hook_remove(&obj->object_listener);
 | 
			
		||||
 | 
			
		||||
	obj->proxy = pw_registry_proxy_bind(impl->registry_proxy,
 | 
			
		||||
			id, info->type, info->version, 0);
 | 
			
		||||
	obj->type = type;
 | 
			
		||||
 | 
			
		||||
	pw_proxy_add_listener(obj->proxy, &obj->proxy_listener, &proxy_events, obj);
 | 
			
		||||
	if (info->events)
 | 
			
		||||
		pw_proxy_add_object_listener(obj->proxy, &obj->object_listener, info->events, obj);
 | 
			
		||||
 | 
			
		||||
	SPA_FLAG_UPDATE(obj->mask, SM_OBJECT_CHANGE_MASK_LISTENER, info->events != NULL);
 | 
			
		||||
 | 
			
		||||
	sm_media_session_emit_create(impl, obj);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
| 
						 | 
				
			
			@ -918,14 +1081,22 @@ registry_global(void *data, uint32_t id,
 | 
			
		|||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
        struct sm_object *obj;
 | 
			
		||||
	const struct object_info *info;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: new global '%d' %d", impl, id, type);
 | 
			
		||||
	pw_log_debug(NAME " %p: new global '%d' %s/%d", impl, id,
 | 
			
		||||
			spa_debug_type_find_name(pw_type_info(), type), version);
 | 
			
		||||
 | 
			
		||||
	info = get_object_info(impl, type);
 | 
			
		||||
	if (info == NULL)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	obj = find_object(impl, id);
 | 
			
		||||
	if (obj == NULL) {
 | 
			
		||||
		init_object(impl, obj, id, permissions, type, version, props);
 | 
			
		||||
		bind_object(impl, info, id, permissions, type, version, props);
 | 
			
		||||
	} else {
 | 
			
		||||
		pw_log_debug(NAME " %p: our object %d appeared", impl, id);
 | 
			
		||||
		pw_log_debug(NAME " %p: our object %d appeared %d/%d",
 | 
			
		||||
				impl, id, obj->type, type);
 | 
			
		||||
		update_object(impl, info, obj, id, permissions, type, version, props);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1049,6 +1220,23 @@ struct pw_proxy *sm_media_session_export(struct sm_media_session *sess,
 | 
			
		|||
			properties, object, user_data_size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct sm_device *sm_media_session_export_device(struct sm_media_session *sess,
 | 
			
		||||
		struct pw_properties *properties, struct spa_device *object)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(sess, struct impl, this);
 | 
			
		||||
	struct sm_device *device;
 | 
			
		||||
	struct pw_proxy *proxy;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug(NAME " %p: device %p", impl, object);
 | 
			
		||||
 | 
			
		||||
	proxy = pw_remote_export(impl->monitor_remote, SPA_TYPE_INTERFACE_Device,
 | 
			
		||||
			properties, object, sizeof(struct sm_device));
 | 
			
		||||
 | 
			
		||||
	device = (struct sm_device *) create_object(impl, proxy, &properties->dict);
 | 
			
		||||
 | 
			
		||||
	return device;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct pw_proxy *sm_media_session_create_object(struct sm_media_session *sess,
 | 
			
		||||
		const char *factory_name, uint32_t type, uint32_t version,
 | 
			
		||||
		const struct spa_dict *props, size_t user_data_size)
 | 
			
		||||
| 
						 | 
				
			
			@ -1059,8 +1247,7 @@ struct pw_proxy *sm_media_session_create_object(struct sm_media_session *sess,
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
struct sm_node *sm_media_session_create_node(struct sm_media_session *sess,
 | 
			
		||||
		const char *factory_name, const struct spa_dict *props,
 | 
			
		||||
		size_t user_data_size)
 | 
			
		||||
		const char *factory_name, const struct spa_dict *props)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = SPA_CONTAINER_OF(sess, struct impl, this);
 | 
			
		||||
	struct sm_node *node;
 | 
			
		||||
| 
						 | 
				
			
			@ -1073,13 +1260,9 @@ struct sm_node *sm_media_session_create_node(struct sm_media_session *sess,
 | 
			
		|||
				PW_TYPE_INTERFACE_Node,
 | 
			
		||||
				PW_VERSION_NODE_PROXY,
 | 
			
		||||
				props,
 | 
			
		||||
				sizeof(struct sm_node) + user_data_size);
 | 
			
		||||
				sizeof(struct sm_node));
 | 
			
		||||
 | 
			
		||||
	node = pw_proxy_get_user_data(proxy);
 | 
			
		||||
	node->obj.proxy = proxy;
 | 
			
		||||
	init_object(impl, &node->obj, SPA_ID_INVALID,
 | 
			
		||||
			PW_PERM_RWX, PW_TYPE_INTERFACE_Node,
 | 
			
		||||
			PW_VERSION_NODE_PROXY, props);
 | 
			
		||||
	node = (struct sm_node *)create_object(impl, proxy, props);
 | 
			
		||||
 | 
			
		||||
	return node;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1278,35 +1461,6 @@ int sm_media_session_create_links(struct sm_media_session *sess,
 | 
			
		|||
/**
 | 
			
		||||
 * Session implementation
 | 
			
		||||
 */
 | 
			
		||||
static int client_session_set_id(void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = object;
 | 
			
		||||
	struct pw_session_info info;
 | 
			
		||||
 | 
			
		||||
	impl->session_id = id;
 | 
			
		||||
 | 
			
		||||
	spa_zero(info);
 | 
			
		||||
	info.version = PW_VERSION_SESSION_INFO;
 | 
			
		||||
	info.id = id;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("got sesssion id:%d", id);
 | 
			
		||||
 | 
			
		||||
	pw_client_session_proxy_update(impl->client_session,
 | 
			
		||||
			PW_CLIENT_SESSION_UPDATE_INFO,
 | 
			
		||||
			0, NULL,
 | 
			
		||||
			&info);
 | 
			
		||||
 | 
			
		||||
	/* start monitors */
 | 
			
		||||
	sm_metadata_start(&impl->this);
 | 
			
		||||
	sm_alsa_midi_start(&impl->this);
 | 
			
		||||
	sm_bluez5_monitor_start(&impl->this);
 | 
			
		||||
	sm_alsa_monitor_start(&impl->this);
 | 
			
		||||
	sm_alsa_endpoint_start(&impl->this);
 | 
			
		||||
	sm_v4l2_monitor_start(&impl->this);
 | 
			
		||||
	sm_stream_monitor_start(&impl->this);
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_session_set_param(void *object, uint32_t id, uint32_t flags,
 | 
			
		||||
			const struct spa_pod *param)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -1332,12 +1486,44 @@ static int client_session_link_request_state(void *object, uint32_t link_id, uin
 | 
			
		|||
 | 
			
		||||
static const struct pw_client_session_proxy_events client_session_events = {
 | 
			
		||||
	PW_VERSION_CLIENT_SESSION_PROXY_METHODS,
 | 
			
		||||
	.set_id = client_session_set_id,
 | 
			
		||||
	.set_param = client_session_set_param,
 | 
			
		||||
	.link_set_param = client_session_link_set_param,
 | 
			
		||||
	.link_request_state = client_session_link_request_state,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void client_session_proxy_bound(void *data, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
	struct pw_session_info info;
 | 
			
		||||
 | 
			
		||||
	impl->session_id = id;
 | 
			
		||||
 | 
			
		||||
	spa_zero(info);
 | 
			
		||||
	info.version = PW_VERSION_SESSION_INFO;
 | 
			
		||||
	info.id = id;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("got sesssion id:%d", id);
 | 
			
		||||
 | 
			
		||||
	pw_client_session_proxy_update(impl->client_session,
 | 
			
		||||
			PW_CLIENT_SESSION_UPDATE_INFO,
 | 
			
		||||
			0, NULL,
 | 
			
		||||
			&info);
 | 
			
		||||
 | 
			
		||||
	/* start monitors */
 | 
			
		||||
	sm_metadata_start(&impl->this);
 | 
			
		||||
	sm_alsa_midi_start(&impl->this);
 | 
			
		||||
	sm_bluez5_monitor_start(&impl->this);
 | 
			
		||||
	sm_alsa_monitor_start(&impl->this);
 | 
			
		||||
	sm_alsa_endpoint_start(&impl->this);
 | 
			
		||||
	sm_v4l2_monitor_start(&impl->this);
 | 
			
		||||
	sm_stream_monitor_start(&impl->this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_proxy_events client_session_proxy_events = {
 | 
			
		||||
	PW_VERSION_PROXY_EVENTS,
 | 
			
		||||
	.bound = client_session_proxy_bound,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int start_session(struct impl *impl)
 | 
			
		||||
{
 | 
			
		||||
	impl->client_session = pw_core_proxy_create_object(impl->monitor_core,
 | 
			
		||||
| 
						 | 
				
			
			@ -1346,10 +1532,13 @@ static int start_session(struct impl *impl)
 | 
			
		|||
                                            PW_VERSION_CLIENT_SESSION_PROXY,
 | 
			
		||||
                                            NULL, 0);
 | 
			
		||||
 | 
			
		||||
	pw_proxy_add_listener((struct pw_proxy*)impl->client_session,
 | 
			
		||||
			&impl->client_session_proxy_listener,
 | 
			
		||||
			&client_session_proxy_events, impl);
 | 
			
		||||
 | 
			
		||||
	pw_client_session_proxy_add_listener(impl->client_session,
 | 
			
		||||
			&impl->client_session_listener,
 | 
			
		||||
			&client_session_events,
 | 
			
		||||
			impl);
 | 
			
		||||
			&client_session_events, impl);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -47,8 +47,9 @@ struct sm_object {
 | 
			
		|||
	struct spa_list link;
 | 
			
		||||
	struct sm_media_session *session;
 | 
			
		||||
 | 
			
		||||
#define SM_OBJECT_CHANGE_MASK_PROPERTIES	(1<<0)
 | 
			
		||||
#define SM_OBJECT_CHANGE_MASK_BIND		(1<<1)
 | 
			
		||||
#define SM_OBJECT_CHANGE_MASK_LISTENER		(1<<1)
 | 
			
		||||
#define SM_OBJECT_CHANGE_MASK_PROPERTIES	(1<<2)
 | 
			
		||||
#define SM_OBJECT_CHANGE_MASK_BIND		(1<<3)
 | 
			
		||||
#define SM_OBJECT_CHANGE_MASK_LAST		(1<<8)
 | 
			
		||||
	uint32_t mask;			/**< monitored info */
 | 
			
		||||
	uint32_t avail;			/**< available info */
 | 
			
		||||
| 
						 | 
				
			
			@ -135,7 +136,8 @@ struct sm_port {
 | 
			
		|||
struct sm_session {
 | 
			
		||||
	struct sm_object obj;
 | 
			
		||||
 | 
			
		||||
#define SM_SESSION_CHANGE_MASK_INFO	(SM_OBJECT_CHANGE_MASK_LAST<<0)
 | 
			
		||||
#define SM_SESSION_CHANGE_MASK_INFO		(SM_OBJECT_CHANGE_MASK_LAST<<0)
 | 
			
		||||
#define SM_SESSION_CHANGE_MASK_ENDPOINTS	(SM_OBJECT_CHANGE_MASK_LAST<<1)
 | 
			
		||||
	struct pw_session_info *info;
 | 
			
		||||
	struct spa_list endpoint_list;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -217,13 +219,15 @@ struct pw_proxy *sm_media_session_export(struct sm_media_session *sess,
 | 
			
		|||
		uint32_t type, struct pw_properties *properties,
 | 
			
		||||
		void *object, size_t user_data_size);
 | 
			
		||||
 | 
			
		||||
struct sm_device *sm_media_session_export_device(struct sm_media_session *sess,
 | 
			
		||||
		struct pw_properties *properties, struct spa_device *device);
 | 
			
		||||
 | 
			
		||||
struct pw_proxy *sm_media_session_create_object(struct sm_media_session *sess,
 | 
			
		||||
		const char *factory_name, uint32_t type, uint32_t version,
 | 
			
		||||
		const struct spa_dict *props, size_t user_data_size);
 | 
			
		||||
 | 
			
		||||
struct sm_node *sm_media_session_create_node(struct sm_media_session *sess,
 | 
			
		||||
		const char *factory_name, const struct spa_dict *props,
 | 
			
		||||
		size_t user_data_size);
 | 
			
		||||
		const char *factory_name, const struct spa_dict *props);
 | 
			
		||||
 | 
			
		||||
int sm_media_session_create_links(struct sm_media_session *sess,
 | 
			
		||||
		const struct spa_dict *dict);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,18 +52,14 @@ struct endpoint;
 | 
			
		|||
struct impl {
 | 
			
		||||
	struct sm_media_session *session;
 | 
			
		||||
	struct spa_hook listener;
 | 
			
		||||
 | 
			
		||||
	int seq;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct node {
 | 
			
		||||
	struct sm_node *obj;
 | 
			
		||||
	struct spa_hook listener;
 | 
			
		||||
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
 | 
			
		||||
	struct spa_hook proxy_listener;
 | 
			
		||||
	struct spa_hook listener;
 | 
			
		||||
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
	enum pw_direction direction;
 | 
			
		||||
	char *media;
 | 
			
		||||
| 
						 | 
				
			
			@ -74,6 +70,9 @@ struct node {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
struct stream {
 | 
			
		||||
	struct endpoint *endpoint;
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
	struct pw_endpoint_stream_info info;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -83,8 +82,6 @@ struct stream {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
struct endpoint {
 | 
			
		||||
	struct spa_list link;
 | 
			
		||||
 | 
			
		||||
	struct impl *impl;
 | 
			
		||||
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
| 
						 | 
				
			
			@ -92,21 +89,14 @@ struct endpoint {
 | 
			
		|||
 | 
			
		||||
	struct pw_client_endpoint_proxy *client_endpoint;
 | 
			
		||||
	struct spa_hook client_endpoint_listener;
 | 
			
		||||
	struct spa_hook proxy_listener;
 | 
			
		||||
	struct pw_endpoint_info info;
 | 
			
		||||
 | 
			
		||||
	struct spa_param_info params[5];
 | 
			
		||||
 | 
			
		||||
	struct stream stream;
 | 
			
		||||
	uint32_t pending_config;
 | 
			
		||||
	struct spa_list stream_list;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static int client_endpoint_set_id(void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = object;
 | 
			
		||||
	endpoint->info.id = id;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_endpoint_set_session_id(void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -133,8 +123,9 @@ static int client_endpoint_stream_set_param(void *object, uint32_t stream_id,
 | 
			
		|||
	return -ENOTSUP;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int stream_set_active(struct endpoint *endpoint, struct stream *stream, bool active)
 | 
			
		||||
static int stream_set_active(struct stream *stream, bool active)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = stream->endpoint;
 | 
			
		||||
	struct node *node = endpoint->node;
 | 
			
		||||
	char buf[1024];
 | 
			
		||||
	struct spa_pod_builder b = { 0, };
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +162,7 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
			
		|||
	struct endpoint *endpoint = object;
 | 
			
		||||
	struct impl *impl = endpoint->impl;
 | 
			
		||||
	struct pw_properties *p;
 | 
			
		||||
	struct stream *stream;
 | 
			
		||||
	int res;
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("create link");
 | 
			
		||||
| 
						 | 
				
			
			@ -178,7 +170,12 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
			
		|||
	if (props == NULL)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	stream_set_active(endpoint, &endpoint->stream, true);
 | 
			
		||||
	if (spa_list_is_empty(&endpoint->stream_list))
 | 
			
		||||
		return -EIO;
 | 
			
		||||
 | 
			
		||||
	/* FIXME take first stream */
 | 
			
		||||
	stream = spa_list_first(&endpoint->stream_list, struct stream, link);
 | 
			
		||||
	stream_set_active(stream, true);
 | 
			
		||||
 | 
			
		||||
	p = pw_properties_new_dict(props);
 | 
			
		||||
	if (p == NULL)
 | 
			
		||||
| 
						 | 
				
			
			@ -221,7 +218,6 @@ exit:
 | 
			
		|||
 | 
			
		||||
static const struct pw_client_endpoint_proxy_events client_endpoint_events = {
 | 
			
		||||
	PW_VERSION_CLIENT_ENDPOINT_PROXY_EVENTS,
 | 
			
		||||
	.set_id = client_endpoint_set_id,
 | 
			
		||||
	.set_session_id = client_endpoint_set_session_id,
 | 
			
		||||
	.set_param = client_endpoint_set_param,
 | 
			
		||||
	.stream_set_param = client_endpoint_stream_set_param,
 | 
			
		||||
| 
						 | 
				
			
			@ -235,9 +231,13 @@ static struct stream *endpoint_add_stream(struct endpoint *endpoint)
 | 
			
		|||
	struct node *node = endpoint->node;
 | 
			
		||||
	const char *str;
 | 
			
		||||
 | 
			
		||||
	s = &endpoint->stream;
 | 
			
		||||
	s = calloc(1, sizeof(*s));
 | 
			
		||||
	if (s == NULL)
 | 
			
		||||
		return NULL;
 | 
			
		||||
 | 
			
		||||
	s->endpoint = endpoint;
 | 
			
		||||
	s->props = pw_properties_new(NULL, NULL);
 | 
			
		||||
 | 
			
		||||
	if ((str = pw_properties_get(props, PW_KEY_MEDIA_CLASS)) != NULL)
 | 
			
		||||
		pw_properties_set(s->props, PW_KEY_MEDIA_CLASS, str);
 | 
			
		||||
	if (node->direction == PW_DIRECTION_OUTPUT)
 | 
			
		||||
| 
						 | 
				
			
			@ -251,6 +251,7 @@ static struct stream *endpoint_add_stream(struct endpoint *endpoint)
 | 
			
		|||
	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;
 | 
			
		||||
	spa_list_append(&endpoint->stream_list, &s->link);
 | 
			
		||||
 | 
			
		||||
	pw_log_debug("stream %d", node->id);
 | 
			
		||||
	pw_client_endpoint_proxy_stream_update(endpoint->client_endpoint,
 | 
			
		||||
| 
						 | 
				
			
			@ -261,6 +262,21 @@ static struct stream *endpoint_add_stream(struct endpoint *endpoint)
 | 
			
		|||
	return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void destroy_stream(struct stream *stream)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = stream->endpoint;
 | 
			
		||||
 | 
			
		||||
	pw_client_endpoint_proxy_stream_update(endpoint->client_endpoint,
 | 
			
		||||
			stream->info.id,
 | 
			
		||||
			PW_CLIENT_ENDPOINT_STREAM_UPDATE_DESTROYED,
 | 
			
		||||
			0, NULL,
 | 
			
		||||
			&stream->info);
 | 
			
		||||
 | 
			
		||||
	pw_properties_free(stream->props);
 | 
			
		||||
	spa_list_remove(&stream->link);
 | 
			
		||||
	free(stream);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void complete_endpoint(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = data;
 | 
			
		||||
| 
						 | 
				
			
			@ -335,7 +351,30 @@ static void update_params(void *data)
 | 
			
		|||
			&endpoint->info);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct endpoint *make_endpoint(struct node *node)
 | 
			
		||||
static void proxy_destroy(void *data)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = data;
 | 
			
		||||
	struct stream *s;
 | 
			
		||||
 | 
			
		||||
	spa_list_consume(s, &endpoint->stream_list, link)
 | 
			
		||||
		destroy_stream(s);
 | 
			
		||||
 | 
			
		||||
	pw_properties_free(endpoint->props);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void proxy_bound(void *data, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct endpoint *endpoint = data;
 | 
			
		||||
	endpoint->info.id = id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static const struct pw_proxy_events proxy_events = {
 | 
			
		||||
	PW_VERSION_PROXY_EVENTS,
 | 
			
		||||
	.destroy = proxy_destroy,
 | 
			
		||||
	.bound = proxy_bound,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static struct endpoint *create_endpoint(struct node *node)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = node->impl;
 | 
			
		||||
	struct pw_properties *props;
 | 
			
		||||
| 
						 | 
				
			
			@ -396,6 +435,11 @@ static struct endpoint *make_endpoint(struct node *node)
 | 
			
		|||
	endpoint->params[1] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE);
 | 
			
		||||
	endpoint->info.params = endpoint->params;
 | 
			
		||||
	endpoint->info.n_params = 2;
 | 
			
		||||
	spa_list_init(&endpoint->stream_list);
 | 
			
		||||
 | 
			
		||||
	pw_proxy_add_listener(proxy,
 | 
			
		||||
			&endpoint->proxy_listener,
 | 
			
		||||
			&proxy_events, endpoint);
 | 
			
		||||
 | 
			
		||||
	pw_client_endpoint_proxy_add_listener(endpoint->client_endpoint,
 | 
			
		||||
			&endpoint->client_endpoint_listener,
 | 
			
		||||
| 
						 | 
				
			
			@ -429,7 +473,7 @@ static void object_update(void *data)
 | 
			
		|||
 | 
			
		||||
	if (node->endpoint == NULL &&
 | 
			
		||||
	    node->obj->obj.avail & SM_OBJECT_CHANGE_MASK_PROPERTIES)
 | 
			
		||||
		node->endpoint = make_endpoint(node);
 | 
			
		||||
		node->endpoint = create_endpoint(node);
 | 
			
		||||
 | 
			
		||||
	if (node->obj->obj.changed & SM_NODE_CHANGE_MASK_PARAMS)
 | 
			
		||||
		update_params(node->endpoint);
 | 
			
		||||
| 
						 | 
				
			
			@ -484,6 +528,14 @@ handle_node(struct impl *impl, struct sm_object *obj)
 | 
			
		|||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void destroy_node(struct node *node)
 | 
			
		||||
{
 | 
			
		||||
	if (node->endpoint)
 | 
			
		||||
		destroy_endpoint(node->endpoint);
 | 
			
		||||
	free(node->media);
 | 
			
		||||
	spa_hook_remove(&node->listener);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void session_create(void *data, struct sm_object *object)
 | 
			
		||||
{
 | 
			
		||||
	struct impl *impl = data;
 | 
			
		||||
| 
						 | 
				
			
			@ -510,11 +562,8 @@ static void session_remove(void *data, struct sm_object *object)
 | 
			
		|||
	case PW_TYPE_INTERFACE_Node:
 | 
			
		||||
	{
 | 
			
		||||
		struct node *node;
 | 
			
		||||
		if ((node = sm_object_get_data(object, SESSION_KEY)) != NULL) {
 | 
			
		||||
			if (node->endpoint)
 | 
			
		||||
				destroy_endpoint(node->endpoint);
 | 
			
		||||
			free(node->media);
 | 
			
		||||
		}
 | 
			
		||||
		if ((node = sm_object_get_data(object, SESSION_KEY)) != NULL)
 | 
			
		||||
			destroy_node(node);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
	default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -39,35 +39,16 @@ extern "C" {
 | 
			
		|||
#define PW_VERSION_CLIENT_ENDPOINT_PROXY 0
 | 
			
		||||
struct pw_client_endpoint_proxy { struct spa_interface iface; };
 | 
			
		||||
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_ID			0
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_SESSION_ID		1
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_PARAM		2
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_STREAM_SET_PARAM		3
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_CREATE_LINK		4
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_NUM			5
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_SESSION_ID		0
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_PARAM		1
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_STREAM_SET_PARAM		2
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_CREATE_LINK		3
 | 
			
		||||
#define PW_CLIENT_ENDPOINT_PROXY_EVENT_NUM			4
 | 
			
		||||
 | 
			
		||||
struct pw_client_endpoint_proxy_events {
 | 
			
		||||
#define PW_VERSION_CLIENT_ENDPOINT_PROXY_EVENTS		0
 | 
			
		||||
	uint32_t version;		/**< version of this structure */
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Sets the id of the \a endpoint.
 | 
			
		||||
	 *
 | 
			
		||||
	 * On endpoint implementations, this is called by the server to notify
 | 
			
		||||
	 * the implementation of the assigned global id of the endpoint. The
 | 
			
		||||
	 * implementation is obliged to set this id in the
 | 
			
		||||
	 * #struct pw_endpoint_info \a id field. The implementation should also
 | 
			
		||||
	 * not emit the info() event before this method is called.
 | 
			
		||||
	 *
 | 
			
		||||
	 * \param endpoint a #pw_endpoint
 | 
			
		||||
	 * \param id the global id assigned to this endpoint
 | 
			
		||||
	 *
 | 
			
		||||
	 * \return 0 on success
 | 
			
		||||
	 *         -EINVAL when the id has already been set
 | 
			
		||||
	 *         -ENOTSUP on the server-side endpoint implementation
 | 
			
		||||
	 */
 | 
			
		||||
	int (*set_id) (void *object, uint32_t id);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Sets the session id of the \a endpoint.
 | 
			
		||||
	 *
 | 
			
		||||
| 
						 | 
				
			
			@ -190,34 +171,15 @@ struct pw_client_endpoint_proxy_methods {
 | 
			
		|||
#define PW_VERSION_CLIENT_SESSION_PROXY 0
 | 
			
		||||
struct pw_client_session_proxy { struct spa_interface iface; };
 | 
			
		||||
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_SET_ID			0
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_SET_PARAM			1
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_LINK_SET_PARAM		2
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_LINK_REQUEST_STATE	3
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_NUM			4
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_SET_PARAM			0
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_LINK_SET_PARAM		1
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_LINK_REQUEST_STATE	2
 | 
			
		||||
#define PW_CLIENT_SESSION_PROXY_EVENT_NUM			3
 | 
			
		||||
 | 
			
		||||
struct pw_client_session_proxy_events {
 | 
			
		||||
#define PW_VERSION_CLIENT_SESSION_PROXY_EVENTS		0
 | 
			
		||||
	uint32_t version;		/**< version of this structure */
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Sets the id of the \a session.
 | 
			
		||||
	 *
 | 
			
		||||
	 * On session implementations, this is called by the server to notify
 | 
			
		||||
	 * the implementation of the assigned global id of the session. The
 | 
			
		||||
	 * implementation is obliged to set this id in the
 | 
			
		||||
	 * #struct pw_session_info \a id field. The implementation should also
 | 
			
		||||
	 * not emit the info() event before this method is called.
 | 
			
		||||
	 *
 | 
			
		||||
	 * \param session a #pw_session
 | 
			
		||||
	 * \param id the global id assigned to this session
 | 
			
		||||
	 *
 | 
			
		||||
	 * \return 0 on success
 | 
			
		||||
	 *         -EINVAL when the id has already been set
 | 
			
		||||
	 *         -ENOTSUP on the server-side session implementation
 | 
			
		||||
	 */
 | 
			
		||||
	int (*set_id) (void *object, uint32_t id);
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * Set the configurable parameter in \a session.
 | 
			
		||||
	 *
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -340,7 +340,6 @@ int endpoint_init(struct endpoint *this,
 | 
			
		|||
	this->info.props = &this->props->dict;
 | 
			
		||||
 | 
			
		||||
	pw_resource_bound_id(client_ep->resource, this->global->id);
 | 
			
		||||
	pw_client_endpoint_resource_set_id(client_ep->resource, this->global->id);
 | 
			
		||||
 | 
			
		||||
	return pw_global_register(this->global);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -308,20 +308,6 @@ do { \
 | 
			
		|||
 *              CLIENT ENDPOINT
 | 
			
		||||
 ***********************************************/
 | 
			
		||||
 | 
			
		||||
static int client_endpoint_marshal_set_id (void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
	struct spa_pod_builder *b;
 | 
			
		||||
 | 
			
		||||
	b = pw_protocol_native_begin_resource(resource,
 | 
			
		||||
		PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_ID, NULL);
 | 
			
		||||
 | 
			
		||||
	spa_pod_builder_add_struct(b,
 | 
			
		||||
			SPA_POD_Int(id));
 | 
			
		||||
 | 
			
		||||
	return pw_protocol_native_end_resource(resource, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_endpoint_marshal_set_session_id (void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
| 
						 | 
				
			
			@ -465,22 +451,6 @@ static int client_endpoint_marshal_stream_update(void *object,
 | 
			
		|||
	return pw_protocol_native_end_proxy(proxy, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_endpoint_demarshal_set_id(void *object,
 | 
			
		||||
				const struct pw_protocol_native_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_proxy *proxy = object;
 | 
			
		||||
	struct spa_pod_parser prs;
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
 | 
			
		||||
	spa_pod_parser_init(&prs, msg->data, msg->size);
 | 
			
		||||
	if (spa_pod_parser_get_struct(&prs,
 | 
			
		||||
			SPA_POD_Int(&id)) < 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	return pw_proxy_notify(proxy, struct pw_client_endpoint_proxy_events,
 | 
			
		||||
				set_id, 0, id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_endpoint_demarshal_set_session_id(void *object,
 | 
			
		||||
				const struct pw_protocol_native_message *msg)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -633,7 +603,6 @@ static int client_endpoint_demarshal_stream_update(void *object,
 | 
			
		|||
 | 
			
		||||
static const struct pw_client_endpoint_proxy_events pw_protocol_native_client_endpoint_event_marshal = {
 | 
			
		||||
	PW_VERSION_CLIENT_ENDPOINT_PROXY_EVENTS,
 | 
			
		||||
	.set_id = client_endpoint_marshal_set_id,
 | 
			
		||||
	.set_session_id = client_endpoint_marshal_set_session_id,
 | 
			
		||||
	.set_param = client_endpoint_marshal_set_param,
 | 
			
		||||
	.stream_set_param = client_endpoint_marshal_stream_set_param,
 | 
			
		||||
| 
						 | 
				
			
			@ -643,7 +612,6 @@ static const struct pw_client_endpoint_proxy_events pw_protocol_native_client_en
 | 
			
		|||
static const struct pw_protocol_native_demarshal
 | 
			
		||||
pw_protocol_native_client_endpoint_event_demarshal[PW_CLIENT_ENDPOINT_PROXY_EVENT_NUM] =
 | 
			
		||||
{
 | 
			
		||||
	[PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_ID] = { client_endpoint_demarshal_set_id, 0 },
 | 
			
		||||
	[PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_SESSION_ID] = { client_endpoint_demarshal_set_session_id, 0 },
 | 
			
		||||
	[PW_CLIENT_ENDPOINT_PROXY_EVENT_SET_PARAM] = { client_endpoint_demarshal_set_param, 0 },
 | 
			
		||||
	[PW_CLIENT_ENDPOINT_PROXY_EVENT_STREAM_SET_PARAM] = { client_endpoint_demarshal_stream_set_param, 0 },
 | 
			
		||||
| 
						 | 
				
			
			@ -681,20 +649,6 @@ static const struct pw_protocol_marshal pw_protocol_native_client_endpoint_marsh
 | 
			
		|||
 *              CLIENT SESSION
 | 
			
		||||
 ***********************************************/
 | 
			
		||||
 | 
			
		||||
static int client_session_marshal_set_id (void *object, uint32_t id)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_resource *resource = object;
 | 
			
		||||
	struct spa_pod_builder *b;
 | 
			
		||||
 | 
			
		||||
	b = pw_protocol_native_begin_resource(resource,
 | 
			
		||||
		PW_CLIENT_SESSION_PROXY_EVENT_SET_ID, NULL);
 | 
			
		||||
 | 
			
		||||
	spa_pod_builder_add_struct(b,
 | 
			
		||||
			SPA_POD_Int(id));
 | 
			
		||||
 | 
			
		||||
	return pw_protocol_native_end_resource(resource, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_session_marshal_set_param (void *object,
 | 
			
		||||
					uint32_t id, uint32_t flags,
 | 
			
		||||
					const struct spa_pod *param)
 | 
			
		||||
| 
						 | 
				
			
			@ -826,22 +780,6 @@ static int client_session_marshal_link_update(void *object,
 | 
			
		|||
	return pw_protocol_native_end_proxy(proxy, b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_session_demarshal_set_id(void *object,
 | 
			
		||||
				const struct pw_protocol_native_message *msg)
 | 
			
		||||
{
 | 
			
		||||
	struct pw_proxy *proxy = object;
 | 
			
		||||
	struct spa_pod_parser prs;
 | 
			
		||||
	uint32_t id;
 | 
			
		||||
 | 
			
		||||
	spa_pod_parser_init(&prs, msg->data, msg->size);
 | 
			
		||||
	if (spa_pod_parser_get_struct(&prs,
 | 
			
		||||
			SPA_POD_Int(&id)) < 0)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	return pw_proxy_notify(proxy, struct pw_client_session_proxy_events,
 | 
			
		||||
				set_id, 0, id);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int client_session_demarshal_set_param(void *object,
 | 
			
		||||
				const struct pw_protocol_native_message *msg)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -979,7 +917,6 @@ static int client_session_demarshal_link_update(void *object,
 | 
			
		|||
 | 
			
		||||
static const struct pw_client_session_proxy_events pw_protocol_native_client_session_event_marshal = {
 | 
			
		||||
	PW_VERSION_CLIENT_SESSION_PROXY_EVENTS,
 | 
			
		||||
	.set_id = client_session_marshal_set_id,
 | 
			
		||||
	.set_param = client_session_marshal_set_param,
 | 
			
		||||
	.link_set_param = client_session_marshal_link_set_param,
 | 
			
		||||
	.link_request_state = client_session_marshal_link_request_state,
 | 
			
		||||
| 
						 | 
				
			
			@ -988,7 +925,6 @@ static const struct pw_client_session_proxy_events pw_protocol_native_client_ses
 | 
			
		|||
static const struct pw_protocol_native_demarshal
 | 
			
		||||
pw_protocol_native_client_session_event_demarshal[PW_CLIENT_SESSION_PROXY_EVENT_NUM] =
 | 
			
		||||
{
 | 
			
		||||
	[PW_CLIENT_SESSION_PROXY_EVENT_SET_ID] = { client_session_demarshal_set_id, 0 },
 | 
			
		||||
	[PW_CLIENT_SESSION_PROXY_EVENT_SET_PARAM] = { client_session_demarshal_set_param, 0 },
 | 
			
		||||
	[PW_CLIENT_SESSION_PROXY_EVENT_LINK_SET_PARAM] = { client_session_demarshal_link_set_param, 0 },
 | 
			
		||||
	[PW_CLIENT_SESSION_PROXY_EVENT_LINK_REQUEST_STATE] = { client_session_demarshal_link_request_state, 0 },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -301,7 +301,6 @@ int session_init(struct session *this,
 | 
			
		|||
	this->info.props = &this->props->dict;
 | 
			
		||||
 | 
			
		||||
	pw_resource_bound_id(client_sess->resource, this->global->id);
 | 
			
		||||
	pw_client_session_resource_set_id(client_sess->resource, this->global->id);
 | 
			
		||||
 | 
			
		||||
	return pw_global_register(this->global);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue