mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	media-session: add log topics to all modules
Media-session itself uses ms.core, there are only two files that could have a sub-topic but right now they don't use it (match-rules and metadata). The modules use the ms.mod.* namespace, so it's trivial to filter on those.
This commit is contained in:
		
							parent
							
								
									52a96bb602
								
							
						
					
					
						commit
						e3b216c026
					
				
					 26 changed files with 346 additions and 218 deletions
				
			
		| 
						 | 
					@ -151,6 +151,9 @@ PipeWire uses a "category.topic" naming scheme, with the following categories:
 | 
				
			||||||
- `pw.*`: pipewire-internal topics
 | 
					- `pw.*`: pipewire-internal topics
 | 
				
			||||||
- `mod.*`: module topics, for example `mod.foo` would usually refer to the
 | 
					- `mod.*`: module topics, for example `mod.foo` would usually refer to the
 | 
				
			||||||
  "foo" module
 | 
					  "foo" module
 | 
				
			||||||
 | 
					- `ms.*`: media session topics
 | 
				
			||||||
 | 
					- `ms.mod.*`: media session modules, for example `ms.foo` would usually refer
 | 
				
			||||||
 | 
					   to the "media-session-foo" module
 | 
				
			||||||
- `conn.*`: connection-specific topics such as printing raw messages sent over
 | 
					- `conn.*`: connection-specific topics such as printing raw messages sent over
 | 
				
			||||||
  a communication socket. These are in a separate namespace as they are
 | 
					  a communication socket. These are in a separate namespace as they are
 | 
				
			||||||
  usually vastly more verbose than the normal debugging topics.
 | 
					  usually vastly more verbose than the normal debugging topics.
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -57,6 +57,9 @@
 | 
				
			||||||
#define NAME		"access-flatpak"
 | 
					#define NAME		"access-flatpak"
 | 
				
			||||||
#define SESSION_KEY	"access-flatpak"
 | 
					#define SESSION_KEY	"access-flatpak"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	struct sm_media_session *session;
 | 
						struct sm_media_session *session;
 | 
				
			||||||
	struct spa_hook listener;
 | 
						struct spa_hook listener;
 | 
				
			||||||
| 
						 | 
					@ -82,7 +85,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct impl *impl = client->impl;
 | 
						struct impl *impl = client->impl;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: client %p %08x", impl, client, client->obj->obj.changed);
 | 
						pw_log_debug("%p: client %p %08x", impl, client, client->obj->obj.changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (client->obj->obj.avail & SM_CLIENT_CHANGE_MASK_INFO &&
 | 
						if (client->obj->obj.avail & SM_CLIENT_CHANGE_MASK_INFO &&
 | 
				
			||||||
	    !client->active) {
 | 
						    !client->active) {
 | 
				
			||||||
| 
						 | 
					@ -104,7 +107,7 @@ static void object_update(void *data)
 | 
				
			||||||
			perms = PW_PERM_R | PW_PERM_X;
 | 
								perms = PW_PERM_R | PW_PERM_X;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_info(NAME" %p: flatpak client %d granted 0x%08x permissions"
 | 
							pw_log_info("%p: flatpak client %d granted 0x%08x permissions"
 | 
				
			||||||
				, impl, client->id, perms);
 | 
									, impl, client->id, perms);
 | 
				
			||||||
		permissions[0] = PW_PERMISSION_INIT(PW_ID_ANY, perms);
 | 
							permissions[0] = PW_PERMISSION_INIT(PW_ID_ANY, perms);
 | 
				
			||||||
		pw_client_update_permissions(client->obj->obj.proxy,
 | 
							pw_client_update_permissions(client->obj->obj.proxy,
 | 
				
			||||||
| 
						 | 
					@ -123,7 +126,7 @@ handle_client(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct client *client;
 | 
						struct client *client;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: client", impl);
 | 
						pw_log_debug("%p: client", impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	client = sm_object_add_data(object, SESSION_KEY, sizeof(struct client));
 | 
						client = sm_object_add_data(object, SESSION_KEY, sizeof(struct client));
 | 
				
			||||||
	client->obj = (struct sm_client*)object;
 | 
						client->obj = (struct sm_client*)object;
 | 
				
			||||||
| 
						 | 
					@ -149,7 +152,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: create global '%d'", impl, object->id);
 | 
						pw_log_debug("%p: create global '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_streq(object->type, PW_TYPE_INTERFACE_Client))
 | 
						if (spa_streq(object->type, PW_TYPE_INTERFACE_Client))
 | 
				
			||||||
		res = handle_client(impl, object);
 | 
							res = handle_client(impl, object);
 | 
				
			||||||
| 
						 | 
					@ -157,13 +160,13 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
		res = 0;
 | 
							res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res < 0)
 | 
						if (res < 0)
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d", impl, object->id);
 | 
							pw_log_warn("%p: can't handle global %d", impl, object->id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void session_remove(void *data, struct sm_object *object)
 | 
					static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: remove global '%d'", impl, object->id);
 | 
						pw_log_debug("%p: remove global '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_streq(object->type, PW_TYPE_INTERFACE_Client)) {
 | 
						if (spa_streq(object->type, PW_TYPE_INTERFACE_Client)) {
 | 
				
			||||||
		struct client *client;
 | 
							struct client *client;
 | 
				
			||||||
| 
						 | 
					@ -196,6 +199,8 @@ int sm_access_flatpak_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -79,6 +79,9 @@
 | 
				
			||||||
#define NAME		"access-portal"
 | 
					#define NAME		"access-portal"
 | 
				
			||||||
#define SESSION_KEY	"access-portal"
 | 
					#define SESSION_KEY	"access-portal"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
enum media_role {
 | 
					enum media_role {
 | 
				
			||||||
	MEDIA_ROLE_INVALID = -1,
 | 
						MEDIA_ROLE_INVALID = -1,
 | 
				
			||||||
	MEDIA_ROLE_NONE = 0,
 | 
						MEDIA_ROLE_NONE = 0,
 | 
				
			||||||
| 
						 | 
					@ -178,7 +181,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct client *client = data;
 | 
						struct client *client = data;
 | 
				
			||||||
	struct impl *impl = client->impl;
 | 
						struct impl *impl = client->impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: client %p %08x", impl, client, client->obj->obj.changed);
 | 
						pw_log_debug("%p: client %p %08x", impl, client, client->obj->obj.changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (client->obj->obj.avail & SM_CLIENT_CHANGE_MASK_INFO)
 | 
						if (client->obj->obj.avail & SM_CLIENT_CHANGE_MASK_INFO)
 | 
				
			||||||
		client_info_changed(client, client->obj->info);
 | 
							client_info_changed(client, client->obj->info);
 | 
				
			||||||
| 
						 | 
					@ -195,7 +198,7 @@ handle_client(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
	struct client *client;
 | 
						struct client *client;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: client %u", impl, object->id);
 | 
						pw_log_debug("%p: client %u", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	client = sm_object_add_data(object, SESSION_KEY, sizeof(struct client));
 | 
						client = sm_object_add_data(object, SESSION_KEY, sizeof(struct client));
 | 
				
			||||||
	client->obj = (struct sm_client*)object;
 | 
						client->obj = (struct sm_client*)object;
 | 
				
			||||||
| 
						 | 
					@ -210,7 +213,7 @@ handle_client(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
	    (str = pw_properties_get(client->obj->obj.props, PW_KEY_CLIENT_ACCESS)) != NULL) &&
 | 
						    (str = pw_properties_get(client->obj->obj.props, PW_KEY_CLIENT_ACCESS)) != NULL) &&
 | 
				
			||||||
	    spa_streq(str, "portal")) {
 | 
						    spa_streq(str, "portal")) {
 | 
				
			||||||
		client->portal_managed = true;
 | 
							client->portal_managed = true;
 | 
				
			||||||
		pw_log_info(NAME " %p: portal managed client %d added",
 | 
							pw_log_info("%p: portal managed client %d added",
 | 
				
			||||||
			     impl, client->id);
 | 
								     impl, client->id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
| 
						 | 
					@ -230,7 +233,7 @@ set_global_permissions(void *data, struct sm_object *object)
 | 
				
			||||||
	if ((props = object->props) == NULL)
 | 
						if ((props = object->props) == NULL)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: object %d type:%s", impl, object->id, object->type);
 | 
						pw_log_debug("%p: object %d type:%s", impl, object->id, object->type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_streq(object->type, PW_TYPE_INTERFACE_Client)) {
 | 
						if (spa_streq(object->type, PW_TYPE_INTERFACE_Client)) {
 | 
				
			||||||
		set_permission = allowed = object->id == client->id;
 | 
							set_permission = allowed = object->id == client->id;
 | 
				
			||||||
| 
						 | 
					@ -261,7 +264,7 @@ set_global_permissions(void *data, struct sm_object *object)
 | 
				
			||||||
	if (set_permission) {
 | 
						if (set_permission) {
 | 
				
			||||||
		permissions[n_permissions++] =
 | 
							permissions[n_permissions++] =
 | 
				
			||||||
			PW_PERMISSION_INIT(object->id, allowed ? PW_PERM_ALL : 0);
 | 
								PW_PERMISSION_INIT(object->id, allowed ? PW_PERM_ALL : 0);
 | 
				
			||||||
		pw_log_info(NAME" %p: object %d allowed:%d", impl, object->id, allowed);
 | 
							pw_log_info("%p: object %d allowed:%d", impl, object->id, allowed);
 | 
				
			||||||
		pw_client_update_permissions(client->obj->obj.proxy,
 | 
							pw_client_update_permissions(client->obj->obj.proxy,
 | 
				
			||||||
				n_permissions, permissions);
 | 
									n_permissions, permissions);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -274,7 +277,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: create global '%d'", impl, object->id);
 | 
						pw_log_debug("%p: create global '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_streq(object->type, PW_TYPE_INTERFACE_Client)) {
 | 
						if (spa_streq(object->type, PW_TYPE_INTERFACE_Client)) {
 | 
				
			||||||
		handle_client(impl, object);
 | 
							handle_client(impl, object);
 | 
				
			||||||
| 
						 | 
					@ -300,7 +303,7 @@ static void destroy_client(struct impl *impl, struct client *client)
 | 
				
			||||||
static void session_remove(void *data, struct sm_object *object)
 | 
					static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: remove global '%d'", impl, object->id);
 | 
						pw_log_debug("%p: remove global '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_streq(object->type, PW_TYPE_INTERFACE_Client)) {
 | 
						if (spa_streq(object->type, PW_TYPE_INTERFACE_Client)) {
 | 
				
			||||||
		struct client *client;
 | 
							struct client *client;
 | 
				
			||||||
| 
						 | 
					@ -491,7 +494,7 @@ static void client_info_changed(struct client *client, const struct pw_client_in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	is_portal = spa_dict_lookup(props, "pipewire.access.portal.is_portal");
 | 
						is_portal = spa_dict_lookup(props, "pipewire.access.portal.is_portal");
 | 
				
			||||||
	if (spa_streq(is_portal, "yes") || pw_properties_parse_bool(is_portal)) {
 | 
						if (spa_streq(is_portal, "yes") || pw_properties_parse_bool(is_portal)) {
 | 
				
			||||||
		pw_log_info(NAME " %p: client %d is the portal itself",
 | 
							pw_log_info("%p: client %d is the portal itself",
 | 
				
			||||||
			     impl, client->id);
 | 
								     impl, client->id);
 | 
				
			||||||
		client->is_portal = true;
 | 
							client->is_portal = true;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
| 
						 | 
					@ -499,13 +502,13 @@ static void client_info_changed(struct client *client, const struct pw_client_in
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	app_id = spa_dict_lookup(props, "pipewire.access.portal.app_id");
 | 
						app_id = spa_dict_lookup(props, "pipewire.access.portal.app_id");
 | 
				
			||||||
	if (app_id == NULL) {
 | 
						if (app_id == NULL) {
 | 
				
			||||||
		pw_log_error(NAME" %p: Portal managed client %d didn't set app_id",
 | 
							pw_log_error("%p: Portal managed client %d didn't set app_id",
 | 
				
			||||||
				impl, client->id);
 | 
									impl, client->id);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	media_roles = spa_dict_lookup(props, "pipewire.access.portal.media_roles");
 | 
						media_roles = spa_dict_lookup(props, "pipewire.access.portal.media_roles");
 | 
				
			||||||
	if (media_roles == NULL) {
 | 
						if (media_roles == NULL) {
 | 
				
			||||||
		pw_log_error(NAME" %p: Portal managed client %d didn't set media_roles",
 | 
							pw_log_error("%p: Portal managed client %d didn't set media_roles",
 | 
				
			||||||
				impl, client->id);
 | 
									impl, client->id);
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -513,7 +516,7 @@ static void client_info_changed(struct client *client, const struct pw_client_in
 | 
				
			||||||
	client->app_id = strdup(app_id);
 | 
						client->app_id = strdup(app_id);
 | 
				
			||||||
	client->media_roles = parse_media_roles(media_roles);
 | 
						client->media_roles = parse_media_roles(media_roles);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info(NAME" %p: client %d with app_id '%s' set to portal access",
 | 
						pw_log_info("%p: client %d with app_id '%s' set to portal access",
 | 
				
			||||||
			impl, client->id, client->app_id);
 | 
								impl, client->id, client->app_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	do_permission_store_check(client);
 | 
						do_permission_store_check(client);
 | 
				
			||||||
| 
						 | 
					@ -647,6 +650,8 @@ int sm_access_portal_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -61,6 +61,9 @@
 | 
				
			||||||
#define NAME		"alsa-endpoint"
 | 
					#define NAME		"alsa-endpoint"
 | 
				
			||||||
#define SESSION_KEY	"alsa-endpoint"
 | 
					#define SESSION_KEY	"alsa-endpoint"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct endpoint {
 | 
					struct endpoint {
 | 
				
			||||||
	struct spa_list link;
 | 
						struct spa_list link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -135,7 +138,7 @@ static int client_endpoint_set_param(void *object,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct endpoint *endpoint = object;
 | 
						struct endpoint *endpoint = object;
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	pw_log_debug(NAME " %p: endpoint %p set param %d", impl, endpoint, id);
 | 
						pw_log_debug("%p: endpoint %p set param %d", impl, endpoint, id);
 | 
				
			||||||
	return pw_node_set_param((struct pw_node*)endpoint->node->node->obj.proxy,
 | 
						return pw_node_set_param((struct pw_node*)endpoint->node->node->obj.proxy,
 | 
				
			||||||
				id, flags, param);
 | 
									id, flags, param);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -185,7 +188,7 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
				
			||||||
	struct pw_properties *p;
 | 
						struct pw_properties *p;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
 | 
						pw_log_debug("%p: endpoint %p", impl, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (props == NULL)
 | 
						if (props == NULL)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -200,13 +203,13 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
 | 
							str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
 | 
				
			||||||
		if (str == NULL) {
 | 
							if (str == NULL) {
 | 
				
			||||||
			pw_log_warn(NAME" %p: no target endpoint given", impl);
 | 
								pw_log_warn("%p: no target endpoint given", impl);
 | 
				
			||||||
			res = -EINVAL;
 | 
								res = -EINVAL;
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		obj = sm_media_session_find_object(impl->session, atoi(str));
 | 
							obj = sm_media_session_find_object(impl->session, atoi(str));
 | 
				
			||||||
		if (obj == NULL || !spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
							if (obj == NULL || !spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
				
			||||||
			pw_log_warn(NAME" %p: could not find endpoint %s (%p)", impl, str, obj);
 | 
								pw_log_warn("%p: could not find endpoint %s (%p)", impl, str, obj);
 | 
				
			||||||
			res = -EINVAL;
 | 
								res = -EINVAL;
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -308,7 +311,7 @@ static void update_params(void *data)
 | 
				
			||||||
	struct sm_node *node = endpoint->node->node;
 | 
						struct sm_node *node = endpoint->node->node;
 | 
				
			||||||
	struct sm_param *p;
 | 
						struct sm_param *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint", endpoint);
 | 
						pw_log_debug("%p: endpoint", endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params = alloca(sizeof(struct spa_pod *) * node->n_params);
 | 
						params = alloca(sizeof(struct spa_pod *) * node->n_params);
 | 
				
			||||||
	n_params = 0;
 | 
						n_params = 0;
 | 
				
			||||||
| 
						 | 
					@ -338,7 +341,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	struct sm_node *node = endpoint->node->node;
 | 
						struct sm_node *node = endpoint->node->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
 | 
						pw_log_debug("%p: endpoint %p", impl, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->obj.changed & SM_NODE_CHANGE_MASK_PARAMS)
 | 
						if (node->obj.changed & SM_NODE_CHANGE_MASK_PARAMS)
 | 
				
			||||||
		update_params(endpoint);
 | 
							update_params(endpoint);
 | 
				
			||||||
| 
						 | 
					@ -520,7 +523,7 @@ static struct endpoint *create_endpoint(struct node *node, struct endpoint *moni
 | 
				
			||||||
	endpoint->info.n_params = 2;
 | 
						endpoint->info.n_params = 2;
 | 
				
			||||||
	spa_list_init(&endpoint->stream_list);
 | 
						spa_list_init(&endpoint->stream_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: new endpoint %p for alsa node %p", impl, endpoint, node);
 | 
						pw_log_debug("%p: new endpoint %p for alsa node %p", impl, endpoint, node);
 | 
				
			||||||
	pw_proxy_add_listener(proxy,
 | 
						pw_proxy_add_listener(proxy,
 | 
				
			||||||
			&endpoint->proxy_listener,
 | 
								&endpoint->proxy_listener,
 | 
				
			||||||
			&proxy_events, endpoint);
 | 
								&proxy_events, endpoint);
 | 
				
			||||||
| 
						 | 
					@ -533,7 +536,7 @@ static struct endpoint *create_endpoint(struct node *node, struct endpoint *moni
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_EnumFormat;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_EnumFormat;
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_Props;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_Props;
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_PropInfo;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_PropInfo;
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p proxy %p subscribe %d params", impl,
 | 
						pw_log_debug("%p: endpoint %p proxy %p subscribe %d params", impl,
 | 
				
			||||||
				endpoint, node->node->obj.proxy, n_subscribe);
 | 
									endpoint, node->node->obj.proxy, n_subscribe);
 | 
				
			||||||
	pw_node_subscribe_params((struct pw_node*)node->node->obj.proxy,
 | 
						pw_node_subscribe_params((struct pw_node*)node->node->obj.proxy,
 | 
				
			||||||
				subscribe, n_subscribe);
 | 
									subscribe, n_subscribe);
 | 
				
			||||||
| 
						 | 
					@ -559,12 +562,12 @@ static int setup_alsa_fallback_endpoint(struct device *device)
 | 
				
			||||||
	struct sm_node *n;
 | 
						struct sm_node *n;
 | 
				
			||||||
	struct sm_device *d = device->device;
 | 
						struct sm_device *d = device->device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p fallback", impl, d);
 | 
						pw_log_debug("%p: device %p fallback", impl, d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(n, &d->node_list, link) {
 | 
						spa_list_for_each(n, &d->node_list, link) {
 | 
				
			||||||
		struct node *node;
 | 
							struct node *node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: device %p has node %p", impl, d, n);
 | 
							pw_log_debug("%p: device %p has node %p", impl, d, n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		node = sm_object_add_data(&n->obj, SESSION_KEY, sizeof(struct node));
 | 
							node = sm_object_add_data(&n->obj, SESSION_KEY, sizeof(struct node));
 | 
				
			||||||
		node->device = device;
 | 
							node->device = device;
 | 
				
			||||||
| 
						 | 
					@ -655,7 +658,7 @@ static void device_update(void *data)
 | 
				
			||||||
	struct device *device = data;
 | 
						struct device *device = data;
 | 
				
			||||||
	struct impl *impl = device->impl;
 | 
						struct impl *impl = device->impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p %08x %08x", impl, device,
 | 
						pw_log_debug("%p: device %p %08x %08x", impl, device,
 | 
				
			||||||
			device->device->obj.avail, device->device->obj.changed);
 | 
								device->device->obj.avail, device->device->obj.changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!SPA_FLAG_IS_SET(device->device->obj.avail,
 | 
						if (!SPA_FLAG_IS_SET(device->device->obj.avail,
 | 
				
			||||||
| 
						 | 
					@ -688,7 +691,7 @@ handle_device(struct impl *impl, struct sm_object *obj)
 | 
				
			||||||
	media_class = pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS);
 | 
						media_class = pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS);
 | 
				
			||||||
	str = pw_properties_get(obj->props, PW_KEY_DEVICE_API);
 | 
						str = pw_properties_get(obj->props, PW_KEY_DEVICE_API);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device "PW_KEY_MEDIA_CLASS":%s api:%s", impl, media_class, str);
 | 
						pw_log_debug("%p: device "PW_KEY_MEDIA_CLASS":%s api:%s", impl, media_class, str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!spa_strstartswith(media_class, "Audio/"))
 | 
						if (!spa_strstartswith(media_class, "Audio/"))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -700,7 +703,7 @@ handle_device(struct impl *impl, struct sm_object *obj)
 | 
				
			||||||
	device->id = obj->id;
 | 
						device->id = obj->id;
 | 
				
			||||||
	device->device = (struct sm_device*)obj;
 | 
						device->device = (struct sm_device*)obj;
 | 
				
			||||||
	spa_list_init(&device->endpoint_list);
 | 
						spa_list_init(&device->endpoint_list);
 | 
				
			||||||
	pw_log_debug(NAME" %p: found alsa device %d media_class %s", impl, obj->id, media_class);
 | 
						pw_log_debug("%p: found alsa device %d media_class %s", impl, obj->id, media_class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sm_object_add_listener(obj, &device->listener, &device_events, device);
 | 
						sm_object_add_listener(obj, &device->listener, &device_events, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -725,7 +728,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
		res = 0;
 | 
							res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res < 0) {
 | 
						if (res < 0) {
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d: %s", impl,
 | 
							pw_log_warn("%p: can't handle global %d: %s", impl,
 | 
				
			||||||
				object->id, spa_strerror(res));
 | 
									object->id, spa_strerror(res));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -759,6 +762,8 @@ int sm_alsa_endpoint_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,6 +46,11 @@
 | 
				
			||||||
/** \page page_media_session_module_alsa_midi Media Session Module: ALSA MIDI
 | 
					/** \page page_media_session_module_alsa_midi Media Session Module: ALSA MIDI
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NAME "alsa-midi"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFAULT_NAME	"Midi-Bridge"
 | 
					#define DEFAULT_NAME	"Midi-Bridge"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
| 
						 | 
					@ -175,6 +180,8 @@ int sm_alsa_midi_start(struct sm_media_session *session)
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	const char *name;
 | 
						const char *name;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -56,9 +56,6 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "media-session.h"
 | 
					#include "media-session.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NAME "alsa-monitor"
 | 
					 | 
				
			||||||
#include "reserve.c"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/** \page page_media_session_module_alsa_monitor Media Session Module: ALSA Monitor
 | 
					/** \page page_media_session_module_alsa_monitor Media Session Module: ALSA Monitor
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This module monitors udev for ALSA devices and creates the required
 | 
					 * This module monitors udev for ALSA devices and creates the required
 | 
				
			||||||
| 
						 | 
					@ -122,6 +119,14 @@
 | 
				
			||||||
 * See the `alsa-monitor.conf` provided by your installation for details on
 | 
					 * See the `alsa-monitor.conf` provided by your installation for details on
 | 
				
			||||||
 * possible actions and matches.
 | 
					 * possible actions and matches.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NAME "alsa-monitor"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "reserve.c"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SESSION_CONF	"alsa-monitor.conf"
 | 
					#define SESSION_CONF	"alsa-monitor.conf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFAULT_JACK_SECONDS	1
 | 
					#define DEFAULT_JACK_SECONDS	1
 | 
				
			||||||
| 
						 | 
					@ -1174,6 +1179,8 @@ int sm_alsa_monitor_start(struct sm_media_session *session)
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,6 +53,9 @@
 | 
				
			||||||
#define NAME		"bluez-autoswitch"
 | 
					#define NAME		"bluez-autoswitch"
 | 
				
			||||||
#define SESSION_KEY	"bluez-autoswitch"
 | 
					#define SESSION_KEY	"bluez-autoswitch"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define RESTORE_DELAY_SEC		3
 | 
					#define RESTORE_DELAY_SEC		3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFAULT_AUDIO_SINK_KEY		"default.audio.sink"
 | 
					#define DEFAULT_AUDIO_SINK_KEY		"default.audio.sink"
 | 
				
			||||||
| 
						 | 
					@ -201,7 +204,7 @@ static int set_profile(struct sm_device *dev, const char *profile_name)
 | 
				
			||||||
       if ((ret = find_profile(dev, -1, profile_name, &index, NULL, NULL)) < 0)
 | 
					       if ((ret = find_profile(dev, -1, profile_name, &index, NULL, NULL)) < 0)
 | 
				
			||||||
	       return ret;
 | 
						       return ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       pw_log_info(NAME ": switching device %d to profile %s", dev->obj.id, profile_name);
 | 
					       pw_log_info("switching device %d to profile %s", dev->obj.id, profile_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       return pw_device_set_param((struct pw_device *)dev->obj.proxy,
 | 
					       return pw_device_set_param((struct pw_device *)dev->obj.proxy,
 | 
				
			||||||
		       SPA_PARAM_Profile, 0,
 | 
							       SPA_PARAM_Profile, 0,
 | 
				
			||||||
| 
						 | 
					@ -357,7 +360,7 @@ static void switch_profile_if_needed(struct impl *impl)
 | 
				
			||||||
	if (impl->record_count == 0)
 | 
						if (impl->record_count == 0)
 | 
				
			||||||
		goto inactive;
 | 
							goto inactive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME ": considering switching device profiles");
 | 
						pw_log_debug("considering switching device profiles");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((dev = find_default_output_device(impl)) == NULL)
 | 
						if ((dev = find_default_output_device(impl)) == NULL)
 | 
				
			||||||
		goto inactive;
 | 
							goto inactive;
 | 
				
			||||||
| 
						 | 
					@ -566,7 +569,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
	if (!spa_streq(pw_properties_get(object->props, PW_KEY_MEDIA_CLASS), "Stream/Input/Audio"))
 | 
						if (!spa_streq(pw_properties_get(object->props, PW_KEY_MEDIA_CLASS), "Stream/Input/Audio"))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME ": input stream %d added", object->id);
 | 
						pw_log_debug("input stream %d added", object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	node = sm_object_add_data(object, SESSION_KEY, sizeof(struct node));
 | 
						node = sm_object_add_data(object, SESSION_KEY, sizeof(struct node));
 | 
				
			||||||
	if (!node->obj) {
 | 
						if (!node->obj) {
 | 
				
			||||||
| 
						 | 
					@ -591,7 +594,7 @@ static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
	change_node_state(node, false, false);
 | 
						change_node_state(node, false, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->obj) {
 | 
						if (node->obj) {
 | 
				
			||||||
		pw_log_debug(NAME ": input stream %d removed", object->id);
 | 
							pw_log_debug("input stream %d removed", object->id);
 | 
				
			||||||
		spa_hook_remove(&node->listener);
 | 
							spa_hook_remove(&node->listener);
 | 
				
			||||||
		node->obj = NULL;
 | 
							node->obj = NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -670,6 +673,8 @@ int sm_bluez5_autoswitch_start(struct sm_media_session *session)
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +52,9 @@
 | 
				
			||||||
#define NAME		"bluez-endpoint"
 | 
					#define NAME		"bluez-endpoint"
 | 
				
			||||||
#define SESSION_KEY	"bluez-endpoint"
 | 
					#define SESSION_KEY	"bluez-endpoint"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct endpoint {
 | 
					struct endpoint {
 | 
				
			||||||
	struct spa_list link;
 | 
						struct spa_list link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -123,7 +126,7 @@ static int client_endpoint_set_param(void *object,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct endpoint *endpoint = object;
 | 
						struct endpoint *endpoint = object;
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	pw_log_debug(NAME " %p: endpoint %p set param %d", impl, endpoint, id);
 | 
						pw_log_debug("%p: endpoint %p set param %d", impl, endpoint, id);
 | 
				
			||||||
	return pw_node_set_param((struct pw_node*)endpoint->node->node->obj.proxy,
 | 
						return pw_node_set_param((struct pw_node*)endpoint->node->node->obj.proxy,
 | 
				
			||||||
				id, flags, param);
 | 
									id, flags, param);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -173,7 +176,7 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
				
			||||||
	struct pw_properties *p;
 | 
						struct pw_properties *p;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
 | 
						pw_log_debug("%p: endpoint %p", impl, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (props == NULL)
 | 
						if (props == NULL)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -188,13 +191,13 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
 | 
							str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
 | 
				
			||||||
		if (str == NULL) {
 | 
							if (str == NULL) {
 | 
				
			||||||
			pw_log_warn(NAME" %p: no target endpoint given", impl);
 | 
								pw_log_warn("%p: no target endpoint given", impl);
 | 
				
			||||||
			res = -EINVAL;
 | 
								res = -EINVAL;
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		obj = sm_media_session_find_object(impl->session, atoi(str));
 | 
							obj = sm_media_session_find_object(impl->session, atoi(str));
 | 
				
			||||||
		if (obj == NULL || !spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
							if (obj == NULL || !spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
				
			||||||
			pw_log_warn(NAME" %p: could not find endpoint %s (%p)", impl, str, obj);
 | 
								pw_log_warn("%p: could not find endpoint %s (%p)", impl, str, obj);
 | 
				
			||||||
			res = -EINVAL;
 | 
								res = -EINVAL;
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -296,7 +299,7 @@ static void update_params(void *data)
 | 
				
			||||||
	struct sm_node *node = endpoint->node->node;
 | 
						struct sm_node *node = endpoint->node->node;
 | 
				
			||||||
	struct sm_param *p;
 | 
						struct sm_param *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint", endpoint);
 | 
						pw_log_debug("%p: endpoint", endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params = alloca(sizeof(struct spa_pod *) * node->n_params);
 | 
						params = alloca(sizeof(struct spa_pod *) * node->n_params);
 | 
				
			||||||
	n_params = 0;
 | 
						n_params = 0;
 | 
				
			||||||
| 
						 | 
					@ -326,7 +329,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	struct sm_node *node = endpoint->node->node;
 | 
						struct sm_node *node = endpoint->node->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
 | 
						pw_log_debug("%p: endpoint %p", impl, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->obj.changed & SM_NODE_CHANGE_MASK_PARAMS)
 | 
						if (node->obj.changed & SM_NODE_CHANGE_MASK_PARAMS)
 | 
				
			||||||
		update_params(endpoint);
 | 
							update_params(endpoint);
 | 
				
			||||||
| 
						 | 
					@ -508,7 +511,7 @@ static struct endpoint *create_endpoint(struct node *node, struct endpoint *moni
 | 
				
			||||||
	endpoint->info.n_params = 2;
 | 
						endpoint->info.n_params = 2;
 | 
				
			||||||
	spa_list_init(&endpoint->stream_list);
 | 
						spa_list_init(&endpoint->stream_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: new endpoint %p for bluez node %p", impl, endpoint, node);
 | 
						pw_log_debug("%p: new endpoint %p for bluez node %p", impl, endpoint, node);
 | 
				
			||||||
	pw_proxy_add_listener(proxy,
 | 
						pw_proxy_add_listener(proxy,
 | 
				
			||||||
			&endpoint->proxy_listener,
 | 
								&endpoint->proxy_listener,
 | 
				
			||||||
			&proxy_events, endpoint);
 | 
								&proxy_events, endpoint);
 | 
				
			||||||
| 
						 | 
					@ -521,7 +524,7 @@ static struct endpoint *create_endpoint(struct node *node, struct endpoint *moni
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_EnumFormat;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_EnumFormat;
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_Props;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_Props;
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_PropInfo;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_PropInfo;
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p proxy %p subscribe %d params", impl,
 | 
						pw_log_debug("%p: endpoint %p proxy %p subscribe %d params", impl,
 | 
				
			||||||
				endpoint, node->node->obj.proxy, n_subscribe);
 | 
									endpoint, node->node->obj.proxy, n_subscribe);
 | 
				
			||||||
	pw_node_subscribe_params((struct pw_node*)node->node->obj.proxy,
 | 
						pw_node_subscribe_params((struct pw_node*)node->node->obj.proxy,
 | 
				
			||||||
				subscribe, n_subscribe);
 | 
									subscribe, n_subscribe);
 | 
				
			||||||
| 
						 | 
					@ -547,12 +550,12 @@ static int setup_bluez_endpoint(struct device *device)
 | 
				
			||||||
	struct sm_node *n;
 | 
						struct sm_node *n;
 | 
				
			||||||
	struct sm_device *d = device->device;
 | 
						struct sm_device *d = device->device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p fallback", impl, d);
 | 
						pw_log_debug("%p: device %p fallback", impl, d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(n, &d->node_list, link) {
 | 
						spa_list_for_each(n, &d->node_list, link) {
 | 
				
			||||||
		struct node *node;
 | 
							struct node *node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: device %p has node %p", impl, d, n);
 | 
							pw_log_debug("%p: device %p has node %p", impl, d, n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		node = sm_object_add_data(&n->obj, SESSION_KEY, sizeof(struct node));
 | 
							node = sm_object_add_data(&n->obj, SESSION_KEY, sizeof(struct node));
 | 
				
			||||||
		node->device = device;
 | 
							node->device = device;
 | 
				
			||||||
| 
						 | 
					@ -583,7 +586,7 @@ static void device_update(void *data)
 | 
				
			||||||
	struct device *device = data;
 | 
						struct device *device = data;
 | 
				
			||||||
	struct impl *impl = device->impl;
 | 
						struct impl *impl = device->impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p %08x %08x", impl, device,
 | 
						pw_log_debug("%p: device %p %08x %08x", impl, device,
 | 
				
			||||||
			device->device->obj.avail, device->device->obj.changed);
 | 
								device->device->obj.avail, device->device->obj.changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!SPA_FLAG_IS_SET(device->device->obj.avail,
 | 
						if (!SPA_FLAG_IS_SET(device->device->obj.avail,
 | 
				
			||||||
| 
						 | 
					@ -616,7 +619,7 @@ handle_device(struct impl *impl, struct sm_object *obj)
 | 
				
			||||||
	media_class = pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS);
 | 
						media_class = pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS);
 | 
				
			||||||
	str = pw_properties_get(obj->props, PW_KEY_DEVICE_API);
 | 
						str = pw_properties_get(obj->props, PW_KEY_DEVICE_API);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device "PW_KEY_MEDIA_CLASS":%s api:%s", impl, media_class, str);
 | 
						pw_log_debug("%p: device "PW_KEY_MEDIA_CLASS":%s api:%s", impl, media_class, str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!spa_strstartswith(media_class, "Audio/"))
 | 
						if (!spa_strstartswith(media_class, "Audio/"))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -628,7 +631,7 @@ handle_device(struct impl *impl, struct sm_object *obj)
 | 
				
			||||||
	device->id = obj->id;
 | 
						device->id = obj->id;
 | 
				
			||||||
	device->device = (struct sm_device*)obj;
 | 
						device->device = (struct sm_device*)obj;
 | 
				
			||||||
	spa_list_init(&device->endpoint_list);
 | 
						spa_list_init(&device->endpoint_list);
 | 
				
			||||||
	pw_log_debug(NAME" %p: found bluez device %d media_class %s", impl, obj->id, media_class);
 | 
						pw_log_debug("%p: found bluez device %d media_class %s", impl, obj->id, media_class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sm_object_add_listener(obj, &device->listener, &device_events, device);
 | 
						sm_object_add_listener(obj, &device->listener, &device_events, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -653,7 +656,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
		res = 0;
 | 
							res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res < 0) {
 | 
						if (res < 0) {
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d: %s", impl,
 | 
							pw_log_warn("%p: can't handle global %d: %s", impl,
 | 
				
			||||||
				object->id, spa_strerror(res));
 | 
									object->id, spa_strerror(res));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -687,6 +690,8 @@ int sm_bluez5_endpoint_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -54,6 +54,9 @@
 | 
				
			||||||
#define SESSION_CONF	"bluez-monitor.conf"
 | 
					#define SESSION_CONF	"bluez-monitor.conf"
 | 
				
			||||||
#define FEATURES_CONF	"bluez-hardware.conf"
 | 
					#define FEATURES_CONF	"bluez-hardware.conf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct device;
 | 
					struct device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct node {
 | 
					struct node {
 | 
				
			||||||
| 
						 | 
					@ -700,10 +703,10 @@ static void seat_active(void *data, bool active)
 | 
				
			||||||
	impl->seat_active = active;
 | 
						impl->seat_active = active;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->seat_active) {
 | 
						if (impl->seat_active) {
 | 
				
			||||||
		pw_log_info(NAME ": seat active, starting bluetooth");
 | 
							pw_log_info("seat active, starting bluetooth");
 | 
				
			||||||
		load_bluez_handle(impl);
 | 
							load_bluez_handle(impl);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		pw_log_info(NAME ": seat not active, stopping bluetooth");
 | 
							pw_log_info("seat not active, stopping bluetooth");
 | 
				
			||||||
		unload_bluez_handle(impl);
 | 
							unload_bluez_handle(impl);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -721,6 +724,8 @@ int sm_bluez5_monitor_start(struct sm_media_session *session)
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL) {
 | 
						if (impl == NULL) {
 | 
				
			||||||
		res = -errno;
 | 
							res = -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,6 +53,9 @@
 | 
				
			||||||
#define DEFAULT_CONFIG_AUDIO_SOURCE_KEY	"default.configured.audio.source"
 | 
					#define DEFAULT_CONFIG_AUDIO_SOURCE_KEY	"default.configured.audio.source"
 | 
				
			||||||
#define DEFAULT_CONFIG_VIDEO_SOURCE_KEY	"default.configured.video.source"
 | 
					#define DEFAULT_CONFIG_VIDEO_SOURCE_KEY	"default.configured.video.source"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	struct sm_media_session *session;
 | 
						struct sm_media_session *session;
 | 
				
			||||||
	struct spa_hook listener;
 | 
						struct spa_hook listener;
 | 
				
			||||||
| 
						 | 
					@ -89,7 +92,7 @@ static void remove_idle_timeout(struct impl *impl)
 | 
				
			||||||
static void idle_timeout(void *data, uint64_t expirations)
 | 
					static void idle_timeout(void *data, uint64_t expirations)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: idle timeout", impl);
 | 
						pw_log_debug("%p: idle timeout", impl);
 | 
				
			||||||
	remove_idle_timeout(impl);
 | 
						remove_idle_timeout(impl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -171,6 +174,8 @@ int sm_default_nodes_start(struct sm_media_session *session)
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -83,6 +83,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SAVE_INTERVAL	1
 | 
					#define SAVE_INTERVAL	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	struct timespec now;
 | 
						struct timespec now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -131,7 +134,7 @@ static void remove_idle_timeout(struct impl *impl)
 | 
				
			||||||
static void idle_timeout(void *data, uint64_t expirations)
 | 
					static void idle_timeout(void *data, uint64_t expirations)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: idle timeout", impl);
 | 
						pw_log_debug("%p: idle timeout", impl);
 | 
				
			||||||
	remove_idle_timeout(impl);
 | 
						remove_idle_timeout(impl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -396,7 +399,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct impl *impl = dev->impl;
 | 
						struct impl *impl = dev->impl;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p %08x/%08x", impl, dev,
 | 
						pw_log_debug("%p: device %p %08x/%08x", impl, dev,
 | 
				
			||||||
			dev->obj->obj.changed, dev->obj->obj.avail);
 | 
								dev->obj->obj.changed, dev->obj->obj.avail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dev->obj->info && dev->obj->info->props &&
 | 
						if (dev->obj->info && dev->obj->info->props &&
 | 
				
			||||||
| 
						 | 
					@ -424,7 +427,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
	    (name = pw_properties_get(object->props, PW_KEY_DEVICE_NAME)) == NULL)
 | 
						    (name = pw_properties_get(object->props, PW_KEY_DEVICE_NAME)) == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: add device '%d' %s", impl, object->id, name);
 | 
						pw_log_debug("%p: add device '%d' %s", impl, object->id, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev = sm_object_add_data(object, SESSION_KEY, sizeof(struct device));
 | 
						dev = sm_object_add_data(object, SESSION_KEY, sizeof(struct device));
 | 
				
			||||||
	dev->obj = (struct sm_device*)object;
 | 
						dev->obj = (struct sm_device*)object;
 | 
				
			||||||
| 
						 | 
					@ -455,7 +458,7 @@ static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
	if (!spa_streq(object->type, PW_TYPE_INTERFACE_Device))
 | 
						if (!spa_streq(object->type, PW_TYPE_INTERFACE_Device))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: remove device '%d'", impl, object->id);
 | 
						pw_log_debug("%p: remove device '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((dev = sm_object_get_data(object, SESSION_KEY)) != NULL)
 | 
						if ((dev = sm_object_get_data(object, SESSION_KEY)) != NULL)
 | 
				
			||||||
		destroy_device(impl, dev);
 | 
							destroy_device(impl, dev);
 | 
				
			||||||
| 
						 | 
					@ -483,6 +486,8 @@ int sm_default_profile_start(struct sm_media_session *session)
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,6 +53,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SAVE_INTERVAL	1
 | 
					#define SAVE_INTERVAL	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	struct timespec now;
 | 
						struct timespec now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -99,7 +102,7 @@ static void remove_idle_timeout(struct impl *impl)
 | 
				
			||||||
static void idle_timeout(void *data, uint64_t expirations)
 | 
					static void idle_timeout(void *data, uint64_t expirations)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: idle timeout", impl);
 | 
						pw_log_debug("%p: idle timeout", impl);
 | 
				
			||||||
	remove_idle_timeout(impl);
 | 
						remove_idle_timeout(impl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -877,7 +880,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct device *dev = data;
 | 
						struct device *dev = data;
 | 
				
			||||||
	struct impl *impl = dev->impl;
 | 
						struct impl *impl = dev->impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p %08x/%08x", impl, dev,
 | 
						pw_log_debug("%p: device %p %08x/%08x", impl, dev,
 | 
				
			||||||
			dev->obj->obj.changed, dev->obj->obj.avail);
 | 
								dev->obj->obj.changed, dev->obj->obj.avail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (dev->obj->obj.changed & SM_DEVICE_CHANGE_MASK_PARAMS)
 | 
						if (dev->obj->obj.changed & SM_DEVICE_CHANGE_MASK_PARAMS)
 | 
				
			||||||
| 
						 | 
					@ -900,7 +903,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
	    (name = pw_properties_get(object->props, PW_KEY_DEVICE_NAME)) == NULL)
 | 
						    (name = pw_properties_get(object->props, PW_KEY_DEVICE_NAME)) == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: add device '%d' %s", impl, object->id, name);
 | 
						pw_log_debug("%p: add device '%d' %s", impl, object->id, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dev = sm_object_add_data(object, SESSION_KEY, sizeof(struct device));
 | 
						dev = sm_object_add_data(object, SESSION_KEY, sizeof(struct device));
 | 
				
			||||||
	dev->obj = (struct sm_device*)object;
 | 
						dev->obj = (struct sm_device*)object;
 | 
				
			||||||
| 
						 | 
					@ -931,7 +934,7 @@ static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
	if (!spa_streq(object->type, PW_TYPE_INTERFACE_Device))
 | 
						if (!spa_streq(object->type, PW_TYPE_INTERFACE_Device))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: remove device '%d'", impl, object->id);
 | 
						pw_log_debug("%p: remove device '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((dev = sm_object_get_data(object, SESSION_KEY)) != NULL)
 | 
						if ((dev = sm_object_get_data(object, SESSION_KEY)) != NULL)
 | 
				
			||||||
		destroy_device(impl, dev);
 | 
							destroy_device(impl, dev);
 | 
				
			||||||
| 
						 | 
					@ -958,6 +961,8 @@ int sm_default_routes_start(struct sm_media_session *session)
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,11 @@
 | 
				
			||||||
/** \page page_media_session_module_libcamera_monitor Media Session Module: libCamera Monitor
 | 
					/** \page page_media_session_module_libcamera_monitor Media Session Module: libCamera Monitor
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define NAME "libcamera-monitor"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct device;
 | 
					struct device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct node {
 | 
					struct node {
 | 
				
			||||||
| 
						 | 
					@ -469,6 +474,8 @@ int sm_libcamera_monitor_start(struct sm_media_session *sess)
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	void *iface;
 | 
						void *iface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +52,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NAME		"logind"
 | 
					#define NAME		"logind"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	struct sm_media_session *session;
 | 
						struct sm_media_session *session;
 | 
				
			||||||
	struct spa_hook listener;
 | 
						struct spa_hook listener;
 | 
				
			||||||
| 
						 | 
					@ -106,6 +109,8 @@ int sm_logind_start(struct sm_media_session *session)
 | 
				
			||||||
	struct pw_loop *main_loop;
 | 
						struct pw_loop *main_loop;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					@ -132,7 +137,7 @@ int sm_logind_start(struct sm_media_session *session)
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fail:
 | 
					fail:
 | 
				
			||||||
	pw_log_error(NAME ": failed to start systemd logind monitor: %d (%s)", res, spa_strerror(res));
 | 
						pw_log_error(": failed to start systemd logind monitor: %d (%s)", res, spa_strerror(res));
 | 
				
			||||||
	free(impl);
 | 
						free(impl);
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +37,9 @@
 | 
				
			||||||
#include <pipewire/pipewire.h>
 | 
					#include <pipewire/pipewire.h>
 | 
				
			||||||
#include "media-session.h"
 | 
					#include "media-session.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_EXTERN(mod_topic);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool find_match(struct spa_json *arr, struct pw_properties *props)
 | 
					static bool find_match(struct spa_json *arr, struct pw_properties *props)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct spa_json match_obj;
 | 
						struct spa_json match_obj;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +66,9 @@
 | 
				
			||||||
#define SESSION_PREFIX	"media-session.d"
 | 
					#define SESSION_PREFIX	"media-session.d"
 | 
				
			||||||
#define SESSION_CONF	"media-session.conf"
 | 
					#define SESSION_CONF	"media-session.conf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC(mod_topic, "ms.core");
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define sm_object_emit(o,m,v,...) spa_hook_list_call(&(o)->hooks, struct sm_object_events, m, v, ##__VA_ARGS__)
 | 
					#define sm_object_emit(o,m,v,...) spa_hook_list_call(&(o)->hooks, struct sm_object_events, m, v, ##__VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define sm_object_emit_update(s)		sm_object_emit(s, update, 0)
 | 
					#define sm_object_emit_update(s)		sm_object_emit(s, update, 0)
 | 
				
			||||||
| 
						 | 
					@ -304,7 +307,7 @@ static int sm_object_destroy_maybe_free(struct sm_object *obj)
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(obj->session, struct impl, this);
 | 
				
			||||||
	struct data *d;
 | 
						struct data *d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: destroy object %p id:%d proxy:%p handle:%p monitor:%d destroyed:%d discarded:%d", obj->session,
 | 
						pw_log_debug("%p: destroy object %p id:%d proxy:%p handle:%p monitor:%d destroyed:%d discarded:%d", obj->session,
 | 
				
			||||||
			obj, obj->id, obj->proxy, obj->handle, obj->monitor_global, obj->destroyed, obj->discarded);
 | 
								obj, obj->id, obj->proxy, obj->handle, obj->monitor_global, obj->destroyed, obj->discarded);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (obj->destroyed)
 | 
						if (obj->destroyed)
 | 
				
			||||||
| 
						 | 
					@ -376,13 +379,13 @@ static struct param *add_param(struct spa_list *param_list,
 | 
				
			||||||
		id = SPA_POD_OBJECT_ID(param);
 | 
							id = SPA_POD_OBJECT_ID(param);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (id >= SM_MAX_PARAMS) {
 | 
						if (id >= SM_MAX_PARAMS) {
 | 
				
			||||||
		pw_log_error(NAME": too big param id %d", id);
 | 
							pw_log_error("too big param id %d", id);
 | 
				
			||||||
		errno = EINVAL;
 | 
							errno = EINVAL;
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (seq != param_seq[id]) {
 | 
						if (seq != param_seq[id]) {
 | 
				
			||||||
		pw_log_debug(NAME": ignoring param %d, seq:%d != current_seq:%d",
 | 
							pw_log_debug("ignoring param %d, seq:%d != current_seq:%d",
 | 
				
			||||||
				id, seq, param_seq[id]);
 | 
									id, seq, param_seq[id]);
 | 
				
			||||||
		errno = EBUSY;
 | 
							errno = EBUSY;
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
| 
						 | 
					@ -455,7 +458,7 @@ static void client_event_info(void *object, const struct pw_client_info *info)
 | 
				
			||||||
	struct sm_client *client = object;
 | 
						struct sm_client *client = object;
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(client->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(client->obj.session, struct impl, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: client %d info", impl, client->obj.id);
 | 
						pw_log_debug("%p: client %d info", impl, client->obj.id);
 | 
				
			||||||
	client->info = pw_client_info_merge(client->info, info, client->obj.changed == 0);
 | 
						client->info = pw_client_info_merge(client->info, info, client->obj.changed == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	client->obj.avail |= SM_CLIENT_CHANGE_MASK_INFO;
 | 
						client->obj.avail |= SM_CLIENT_CHANGE_MASK_INFO;
 | 
				
			||||||
| 
						 | 
					@ -493,7 +496,7 @@ static void device_event_info(void *object, const struct pw_device_info *info)
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(device->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(device->obj.session, struct impl, this);
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %d info", impl, device->obj.id);
 | 
						pw_log_debug("%p: device %d info", impl, device->obj.id);
 | 
				
			||||||
	info = device->info = pw_device_info_merge(device->info, info, device->obj.changed == 0);
 | 
						info = device->info = pw_device_info_merge(device->info, info, device->obj.changed == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	device->obj.avail |= SM_DEVICE_CHANGE_MASK_INFO;
 | 
						device->obj.avail |= SM_DEVICE_CHANGE_MASK_INFO;
 | 
				
			||||||
| 
						 | 
					@ -507,7 +510,7 @@ static void device_event_info(void *object, const struct pw_device_info *info)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (id >= SM_MAX_PARAMS) {
 | 
								if (id >= SM_MAX_PARAMS) {
 | 
				
			||||||
				pw_log_error(NAME" %p: too big param id %d", impl, id);
 | 
									pw_log_error("%p: too big param id %d", impl, id);
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -519,7 +522,7 @@ static void device_event_info(void *object, const struct pw_device_info *info)
 | 
				
			||||||
						++device->param_seq[id], id, 0, UINT32_MAX, NULL);
 | 
											++device->param_seq[id], id, 0, UINT32_MAX, NULL);
 | 
				
			||||||
				if (SPA_RESULT_IS_ASYNC(res))
 | 
									if (SPA_RESULT_IS_ASYNC(res))
 | 
				
			||||||
					device->param_seq[id] = res;
 | 
										device->param_seq[id] = res;
 | 
				
			||||||
				pw_log_debug(NAME" %p: device %d enum params %d seq:%d", impl,
 | 
									pw_log_debug("%p: device %d enum params %d seq:%d", impl,
 | 
				
			||||||
						device->obj.id, id, device->param_seq[id]);
 | 
											device->obj.id, id, device->param_seq[id]);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			info->params[i].user = 0;
 | 
								info->params[i].user = 0;
 | 
				
			||||||
| 
						 | 
					@ -536,7 +539,7 @@ static void device_event_param(void *object, int seq,
 | 
				
			||||||
	struct sm_device *device = object;
 | 
						struct sm_device *device = object;
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(device->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(device->obj.session, struct impl, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p param %d index:%d seq:%d", impl, device, id, index, seq);
 | 
						pw_log_debug("%p: device %p param %d index:%d seq:%d", impl, device, id, index, seq);
 | 
				
			||||||
	if (add_param(&device->param_list, seq, device->param_seq, id, param) != NULL)
 | 
						if (add_param(&device->param_list, seq, device->param_seq, id, param) != NULL)
 | 
				
			||||||
		device->n_params++;
 | 
							device->n_params++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -601,7 +604,7 @@ static void node_event_info(void *object, const struct pw_node_info *info)
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(node->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(node->obj.session, struct impl, this);
 | 
				
			||||||
	uint32_t i;
 | 
						uint32_t i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: node %d info", impl, node->obj.id);
 | 
						pw_log_debug("%p: node %d info", impl, node->obj.id);
 | 
				
			||||||
	info = node->info = pw_node_info_merge(node->info, info, node->obj.changed == 0);
 | 
						info = node->info = pw_node_info_merge(node->info, info, node->obj.changed == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	node->obj.avail |= SM_NODE_CHANGE_MASK_INFO;
 | 
						node->obj.avail |= SM_NODE_CHANGE_MASK_INFO;
 | 
				
			||||||
| 
						 | 
					@ -616,7 +619,7 @@ static void node_event_info(void *object, const struct pw_node_info *info)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (id >= SM_MAX_PARAMS) {
 | 
								if (id >= SM_MAX_PARAMS) {
 | 
				
			||||||
				pw_log_error(NAME" %p: too big param id %d", impl, id);
 | 
									pw_log_error("%p: too big param id %d", impl, id);
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -628,7 +631,7 @@ static void node_event_info(void *object, const struct pw_node_info *info)
 | 
				
			||||||
						++node->param_seq[id], id, 0, UINT32_MAX, NULL);
 | 
											++node->param_seq[id], id, 0, UINT32_MAX, NULL);
 | 
				
			||||||
				if (SPA_RESULT_IS_ASYNC(res))
 | 
									if (SPA_RESULT_IS_ASYNC(res))
 | 
				
			||||||
					node->param_seq[id] = res;
 | 
										node->param_seq[id] = res;
 | 
				
			||||||
				pw_log_debug(NAME" %p: node %d enum params %d seq:%d", impl,
 | 
									pw_log_debug("%p: node %d enum params %d seq:%d", impl,
 | 
				
			||||||
						node->obj.id, id, node->param_seq[id]);
 | 
											node->obj.id, id, node->param_seq[id]);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			info->params[i].user = 0;
 | 
								info->params[i].user = 0;
 | 
				
			||||||
| 
						 | 
					@ -645,7 +648,7 @@ static void node_event_param(void *object, int seq,
 | 
				
			||||||
	struct sm_node *node = object;
 | 
						struct sm_node *node = object;
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(node->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(node->obj.session, struct impl, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: node %p param %d index:%d seq:%d", impl, node, id, index, seq);
 | 
						pw_log_debug("%p: node %p param %d index:%d seq:%d", impl, node, id, index, seq);
 | 
				
			||||||
	if (add_param(&node->param_list, seq, node->param_seq, id, param) != NULL)
 | 
						if (add_param(&node->param_list, seq, node->param_seq, id, param) != NULL)
 | 
				
			||||||
		node->n_params++;
 | 
							node->n_params++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -672,7 +675,7 @@ static int node_init(void *object)
 | 
				
			||||||
	if (props) {
 | 
						if (props) {
 | 
				
			||||||
		if ((str = pw_properties_get(props, PW_KEY_DEVICE_ID)) != NULL)
 | 
							if ((str = pw_properties_get(props, PW_KEY_DEVICE_ID)) != NULL)
 | 
				
			||||||
			node->device = find_object(impl, atoi(str), NULL);
 | 
								node->device = find_object(impl, atoi(str), NULL);
 | 
				
			||||||
		pw_log_debug(NAME" %p: node %d parent device %s (%p)", impl,
 | 
							pw_log_debug("%p: node %d parent device %s (%p)", impl,
 | 
				
			||||||
				node->obj.id, str, node->device);
 | 
									node->obj.id, str, node->device);
 | 
				
			||||||
		if (node->device) {
 | 
							if (node->device) {
 | 
				
			||||||
			spa_list_append(&node->device->node_list, &node->link);
 | 
								spa_list_append(&node->device->node_list, &node->link);
 | 
				
			||||||
| 
						 | 
					@ -724,7 +727,7 @@ static void port_event_info(void *object, const struct pw_port_info *info)
 | 
				
			||||||
	struct sm_port *port = object;
 | 
						struct sm_port *port = object;
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(port->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(port->obj.session, struct impl, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: port %d info", impl, port->obj.id);
 | 
						pw_log_debug("%p: port %d info", impl, port->obj.id);
 | 
				
			||||||
	port->info = pw_port_info_merge(port->info, info, port->obj.changed == 0);
 | 
						port->info = pw_port_info_merge(port->info, info, port->obj.changed == 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	port->obj.avail |= SM_PORT_CHANGE_MASK_INFO;
 | 
						port->obj.avail |= SM_PORT_CHANGE_MASK_INFO;
 | 
				
			||||||
| 
						 | 
					@ -769,7 +772,7 @@ static int port_init(void *object)
 | 
				
			||||||
		if ((str = pw_properties_get(props, PW_KEY_NODE_ID)) != NULL)
 | 
							if ((str = pw_properties_get(props, PW_KEY_NODE_ID)) != NULL)
 | 
				
			||||||
			port->node = find_object(impl, atoi(str), PW_TYPE_INTERFACE_Node);
 | 
								port->node = find_object(impl, atoi(str), PW_TYPE_INTERFACE_Node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: port %d parent node %s (%p) direction:%d type:%d", impl,
 | 
							pw_log_debug("%p: port %d parent node %s (%p) direction:%d type:%d", impl,
 | 
				
			||||||
				port->obj.id, str, port->node, port->direction, port->type);
 | 
									port->obj.id, str, port->node, port->direction, port->type);
 | 
				
			||||||
		if (port->node) {
 | 
							if (port->node) {
 | 
				
			||||||
			spa_list_append(&port->node->port_list, &port->link);
 | 
								spa_list_append(&port->node->port_list, &port->link);
 | 
				
			||||||
| 
						 | 
					@ -809,7 +812,7 @@ static void session_event_info(void *object, const struct pw_session_info *info)
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(sess->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(sess->obj.session, struct impl, this);
 | 
				
			||||||
	struct pw_session_info *i = sess->info;
 | 
						struct pw_session_info *i = sess->info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: session %d info", impl, sess->obj.id);
 | 
						pw_log_debug("%p: session %d info", impl, sess->obj.id);
 | 
				
			||||||
	if (i == NULL && info) {
 | 
						if (i == NULL && info) {
 | 
				
			||||||
		i = sess->info = calloc(1, sizeof(struct pw_session_info));
 | 
							i = sess->info = calloc(1, sizeof(struct pw_session_info));
 | 
				
			||||||
		i->version = PW_VERSION_SESSION_INFO;
 | 
							i->version = PW_VERSION_SESSION_INFO;
 | 
				
			||||||
| 
						 | 
					@ -881,7 +884,7 @@ static void endpoint_event_info(void *object, const struct pw_endpoint_info *inf
 | 
				
			||||||
	struct pw_endpoint_info *i = endpoint->info;
 | 
						struct pw_endpoint_info *i = endpoint->info;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %d info", impl, endpoint->obj.id);
 | 
						pw_log_debug("%p: endpoint %d info", impl, endpoint->obj.id);
 | 
				
			||||||
	if (i == NULL && info) {
 | 
						if (i == NULL && info) {
 | 
				
			||||||
		i = endpoint->info = calloc(1, sizeof(struct pw_endpoint_info));
 | 
							i = endpoint->info = calloc(1, sizeof(struct pw_endpoint_info));
 | 
				
			||||||
		i->id = info->id;
 | 
							i->id = info->id;
 | 
				
			||||||
| 
						 | 
					@ -923,7 +926,7 @@ static int endpoint_init(void *object)
 | 
				
			||||||
	if (props) {
 | 
						if (props) {
 | 
				
			||||||
		if ((str = pw_properties_get(props, PW_KEY_SESSION_ID)) != NULL)
 | 
							if ((str = pw_properties_get(props, PW_KEY_SESSION_ID)) != NULL)
 | 
				
			||||||
			endpoint->session = find_object(impl, atoi(str), PW_TYPE_INTERFACE_Session);
 | 
								endpoint->session = find_object(impl, atoi(str), PW_TYPE_INTERFACE_Session);
 | 
				
			||||||
		pw_log_debug(NAME" %p: endpoint %d parent session %s", impl,
 | 
							pw_log_debug("%p: endpoint %d parent session %s", impl,
 | 
				
			||||||
				endpoint->obj.id, str);
 | 
									endpoint->obj.id, str);
 | 
				
			||||||
		if (endpoint->session) {
 | 
							if (endpoint->session) {
 | 
				
			||||||
			spa_list_append(&endpoint->session->endpoint_list, &endpoint->link);
 | 
								spa_list_append(&endpoint->session->endpoint_list, &endpoint->link);
 | 
				
			||||||
| 
						 | 
					@ -976,7 +979,7 @@ static void endpoint_stream_event_info(void *object, const struct pw_endpoint_st
 | 
				
			||||||
	struct sm_endpoint_stream *stream = object;
 | 
						struct sm_endpoint_stream *stream = object;
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(stream->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(stream->obj.session, struct impl, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint stream %d info", impl, stream->obj.id);
 | 
						pw_log_debug("%p: endpoint stream %d info", impl, stream->obj.id);
 | 
				
			||||||
	if (stream->info == NULL && info) {
 | 
						if (stream->info == NULL && info) {
 | 
				
			||||||
		stream->info = calloc(1, sizeof(struct pw_endpoint_stream_info));
 | 
							stream->info = calloc(1, sizeof(struct pw_endpoint_stream_info));
 | 
				
			||||||
		stream->info->version = PW_VERSION_ENDPOINT_STREAM_INFO;
 | 
							stream->info->version = PW_VERSION_ENDPOINT_STREAM_INFO;
 | 
				
			||||||
| 
						 | 
					@ -1008,7 +1011,7 @@ static int endpoint_stream_init(void *object)
 | 
				
			||||||
	if (props) {
 | 
						if (props) {
 | 
				
			||||||
		if ((str = pw_properties_get(props, PW_KEY_ENDPOINT_ID)) != NULL)
 | 
							if ((str = pw_properties_get(props, PW_KEY_ENDPOINT_ID)) != NULL)
 | 
				
			||||||
			stream->endpoint = find_object(impl, atoi(str), PW_TYPE_INTERFACE_Endpoint);
 | 
								stream->endpoint = find_object(impl, atoi(str), PW_TYPE_INTERFACE_Endpoint);
 | 
				
			||||||
		pw_log_debug(NAME" %p: stream %d parent endpoint %s", impl,
 | 
							pw_log_debug("%p: stream %d parent endpoint %s", impl,
 | 
				
			||||||
				stream->obj.id, str);
 | 
									stream->obj.id, str);
 | 
				
			||||||
		if (stream->endpoint) {
 | 
							if (stream->endpoint) {
 | 
				
			||||||
			spa_list_append(&stream->endpoint->stream_list, &stream->link);
 | 
								spa_list_append(&stream->endpoint->stream_list, &stream->link);
 | 
				
			||||||
| 
						 | 
					@ -1052,7 +1055,7 @@ static void endpoint_link_event_info(void *object, const struct pw_endpoint_link
 | 
				
			||||||
	struct sm_endpoint_link *link = object;
 | 
						struct sm_endpoint_link *link = object;
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(link->obj.session, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(link->obj.session, struct impl, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint link %d info", impl, link->obj.id);
 | 
						pw_log_debug("%p: endpoint link %d info", impl, link->obj.id);
 | 
				
			||||||
	if (link->info == NULL && info) {
 | 
						if (link->info == NULL && info) {
 | 
				
			||||||
		link->info = calloc(1, sizeof(struct pw_endpoint_link_info));
 | 
							link->info = calloc(1, sizeof(struct pw_endpoint_link_info));
 | 
				
			||||||
		link->info->version = PW_VERSION_ENDPOINT_LINK_INFO;
 | 
							link->info->version = PW_VERSION_ENDPOINT_LINK_INFO;
 | 
				
			||||||
| 
						 | 
					@ -1253,13 +1256,13 @@ create_object(struct impl *impl, struct pw_proxy *proxy, struct pw_proxy *handle
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info = get_object_info(impl, type);
 | 
						info = get_object_info(impl, type);
 | 
				
			||||||
	if (info == NULL) {
 | 
						if (info == NULL) {
 | 
				
			||||||
		pw_log_error(NAME" %p: unknown object type %s", impl, type);
 | 
							pw_log_error("%p: unknown object type %s", impl, type);
 | 
				
			||||||
		errno = ENOTSUP;
 | 
							errno = ENOTSUP;
 | 
				
			||||||
		return NULL;
 | 
							return NULL;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	obj = init_object(impl, info, proxy, handle, SPA_ID_INVALID, props, monitor_global);
 | 
						obj = init_object(impl, info, proxy, handle, SPA_ID_INVALID, props, monitor_global);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: created new object %p proxy:%p handle:%p", impl,
 | 
						pw_log_debug("%p: created new object %p proxy:%p handle:%p", impl,
 | 
				
			||||||
			obj, obj->proxy, obj->handle);
 | 
								obj, obj->proxy, obj->handle);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return obj;
 | 
						return obj;
 | 
				
			||||||
| 
						 | 
					@ -1278,7 +1281,7 @@ bind_object(struct impl *impl, const struct object_info *info, struct registry_e
 | 
				
			||||||
	sm_object_discard(obj);
 | 
						sm_object_discard(obj);
 | 
				
			||||||
	add_object(impl, obj, re->id);
 | 
						add_object(impl, obj, re->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: bound new object %p proxy %p id:%d", impl, obj, obj->proxy, obj->id);
 | 
						pw_log_debug("%p: bound new object %p proxy %p id:%d", impl, obj, obj->proxy, obj->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return obj;
 | 
						return obj;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1294,7 +1297,7 @@ update_object(struct impl *impl, const struct object_info *info, struct sm_objec
 | 
				
			||||||
	if (obj->proxy != NULL)
 | 
						if (obj->proxy != NULL)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: update type:%s", impl, obj->type);
 | 
						pw_log_debug("%p: update type:%s", impl, obj->type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	proxy = re->proxy;
 | 
						proxy = re->proxy;
 | 
				
			||||||
	re->proxy = NULL;
 | 
						re->proxy = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1333,7 +1336,7 @@ static int handle_registry_event(struct impl *impl, struct registry_event *re)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	obj = find_object(impl, re->id, NULL);
 | 
						obj = find_object(impl, re->id, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: new global '%d' %s/%d obj:%p monitor:%d seq:%d",
 | 
						pw_log_debug("%p: new global '%d' %s/%d obj:%p monitor:%d seq:%d",
 | 
				
			||||||
			impl, re->id, re->type, re->version, obj, re->monitor, re->seq);
 | 
								impl, re->id, re->type, re->version, obj, re->monitor, re->seq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info = get_object_info(impl, re->type);
 | 
						info = get_object_info(impl, re->type);
 | 
				
			||||||
| 
						 | 
					@ -1377,7 +1380,7 @@ static int monitor_sync(struct impl *impl)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pw_core_set_paused(impl->policy_core, true);
 | 
						pw_core_set_paused(impl->policy_core, true);
 | 
				
			||||||
	impl->monitor_seq = pw_core_sync(impl->monitor_core, 0, impl->monitor_seq);
 | 
						impl->monitor_seq = pw_core_sync(impl->monitor_core, 0, impl->monitor_seq);
 | 
				
			||||||
	pw_log_debug(NAME " %p: monitor sync start %d", impl, impl->monitor_seq);
 | 
						pw_log_debug("%p: monitor sync start %d", impl, impl->monitor_seq);
 | 
				
			||||||
	sm_media_session_schedule_rescan(&impl->this);
 | 
						sm_media_session_schedule_rescan(&impl->this);
 | 
				
			||||||
	return impl->monitor_seq;
 | 
						return impl->monitor_seq;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1395,7 +1398,7 @@ registry_global(void *data, uint32_t id,
 | 
				
			||||||
	if (info == NULL)
 | 
						if (info == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: registry event (policy) for new global '%d'", impl, id);
 | 
						pw_log_debug("%p: registry event (policy) for new global '%d'", impl, id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Handle policy core events after monitor core ones.
 | 
						 * Handle policy core events after monitor core ones.
 | 
				
			||||||
| 
						 | 
					@ -1435,7 +1438,7 @@ registry_global(void *data, uint32_t id,
 | 
				
			||||||
error:
 | 
					error:
 | 
				
			||||||
	if (re)
 | 
						if (re)
 | 
				
			||||||
		registry_event_free(re);
 | 
							registry_event_free(re);
 | 
				
			||||||
	pw_log_warn(NAME" %p: can't handle global %d: %s", impl, id, spa_strerror(-errno));
 | 
						pw_log_warn("%p: can't handle global %d: %s", impl, id, spa_strerror(-errno));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
| 
						 | 
					@ -1447,7 +1450,7 @@ registry_global_remove(void *data, uint32_t id)
 | 
				
			||||||
	obj = find_object(impl, id, NULL);
 | 
						obj = find_object(impl, id, NULL);
 | 
				
			||||||
	obj = (obj && !obj->monitor_global) ? obj : NULL;
 | 
						obj = (obj && !obj->monitor_global) ? obj : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: registry event (policy) for remove global '%d' obj:%p",
 | 
						pw_log_debug("%p: registry event (policy) for remove global '%d' obj:%p",
 | 
				
			||||||
			impl, id, obj);
 | 
								impl, id, obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (obj)
 | 
						if (obj)
 | 
				
			||||||
| 
						 | 
					@ -1472,7 +1475,7 @@ monitor_registry_global(void *data, uint32_t id,
 | 
				
			||||||
		.props = props,	.monitor = true
 | 
							.props = props,	.monitor = true
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: registry event (monitor) for new global '%d'", impl, id);
 | 
						pw_log_debug("%p: registry event (monitor) for new global '%d'", impl, id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	info = get_object_info(impl, type);
 | 
						info = get_object_info(impl, type);
 | 
				
			||||||
	if (info == NULL)
 | 
						if (info == NULL)
 | 
				
			||||||
| 
						 | 
					@ -1483,7 +1486,7 @@ monitor_registry_global(void *data, uint32_t id,
 | 
				
			||||||
	if (re.proxy)
 | 
						if (re.proxy)
 | 
				
			||||||
		handle_registry_event(impl, &re);
 | 
							handle_registry_event(impl, &re);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d: %s", impl, id, spa_strerror(-errno));
 | 
							pw_log_warn("%p: can't handle global %d: %s", impl, id, spa_strerror(-errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	registry_event_free(&re);
 | 
						registry_event_free(&re);
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
| 
						 | 
					@ -1498,7 +1501,7 @@ monitor_registry_global_remove(void *data, uint32_t id)
 | 
				
			||||||
	obj = find_object(impl, id, NULL);
 | 
						obj = find_object(impl, id, NULL);
 | 
				
			||||||
	obj = (obj && obj->monitor_global) ? obj : NULL;
 | 
						obj = (obj && obj->monitor_global) ? obj : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: registry event (monitor) for remove global '%d' obj:%p", impl, id, obj);
 | 
						pw_log_debug("%p: registry event (monitor) for remove global '%d' obj:%p", impl, id, obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (obj)
 | 
						if (obj)
 | 
				
			||||||
		sm_object_destroy_maybe_free(obj);
 | 
							sm_object_destroy_maybe_free(obj);
 | 
				
			||||||
| 
						 | 
					@ -1616,21 +1619,21 @@ int sm_media_session_roundtrip(struct sm_media_session *sess)
 | 
				
			||||||
	if ((seq = sm_media_session_sync(sess, roundtrip_callback, &done)) < 0)
 | 
						if ((seq = sm_media_session_sync(sess, roundtrip_callback, &done)) < 0)
 | 
				
			||||||
		return seq;
 | 
							return seq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: roundtrip %d", impl, seq);
 | 
						pw_log_debug("%p: roundtrip %d", impl, seq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_loop_enter(loop);
 | 
						pw_loop_enter(loop);
 | 
				
			||||||
	while (!done) {
 | 
						while (!done) {
 | 
				
			||||||
		if ((res = pw_loop_iterate(loop, -1)) < 0) {
 | 
							if ((res = pw_loop_iterate(loop, -1)) < 0) {
 | 
				
			||||||
			if (res == -EINTR)
 | 
								if (res == -EINTR)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			pw_log_warn(NAME" %p: iterate error %d (%s)",
 | 
								pw_log_warn("%p: iterate error %d (%s)",
 | 
				
			||||||
				loop, res, spa_strerror(res));
 | 
									loop, res, spa_strerror(res));
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
        pw_loop_leave(loop);
 | 
					        pw_loop_leave(loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: roundtrip %d done", impl, seq);
 | 
						pw_log_debug("%p: roundtrip %d done", impl, seq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1642,7 +1645,7 @@ struct pw_proxy *sm_media_session_export(struct sm_media_session *sess,
 | 
				
			||||||
	struct impl *impl = SPA_CONTAINER_OF(sess, struct impl, this);
 | 
						struct impl *impl = SPA_CONTAINER_OF(sess, struct impl, this);
 | 
				
			||||||
	struct pw_proxy *handle;
 | 
						struct pw_proxy *handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: object %s %p", impl, type, object);
 | 
						pw_log_debug("%p: object %s %p", impl, type, object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	handle = pw_core_export(impl->monitor_core, type,
 | 
						handle = pw_core_export(impl->monitor_core, type,
 | 
				
			||||||
			props, object, user_data_size);
 | 
								props, object, user_data_size);
 | 
				
			||||||
| 
						 | 
					@ -1659,7 +1662,7 @@ struct sm_node *sm_media_session_export_node(struct sm_media_session *sess,
 | 
				
			||||||
	struct sm_node *node;
 | 
						struct sm_node *node;
 | 
				
			||||||
	struct pw_proxy *handle;
 | 
						struct pw_proxy *handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: node %p", impl, object);
 | 
						pw_log_debug("%p: node %p", impl, object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	handle = pw_core_export(impl->monitor_core, PW_TYPE_INTERFACE_Node,
 | 
						handle = pw_core_export(impl->monitor_core, PW_TYPE_INTERFACE_Node,
 | 
				
			||||||
			props, object, sizeof(struct sm_node));
 | 
								props, object, sizeof(struct sm_node));
 | 
				
			||||||
| 
						 | 
					@ -1678,7 +1681,7 @@ struct sm_device *sm_media_session_export_device(struct sm_media_session *sess,
 | 
				
			||||||
	struct sm_device *device;
 | 
						struct sm_device *device;
 | 
				
			||||||
	struct pw_proxy *handle;
 | 
						struct pw_proxy *handle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: device %p", impl, object);
 | 
						pw_log_debug("%p: device %p", impl, object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	handle = pw_core_export(impl->monitor_core, SPA_TYPE_INTERFACE_Device,
 | 
						handle = pw_core_export(impl->monitor_core, SPA_TYPE_INTERFACE_Device,
 | 
				
			||||||
			props, object, sizeof(struct sm_device));
 | 
								props, object, sizeof(struct sm_device));
 | 
				
			||||||
| 
						 | 
					@ -1706,7 +1709,7 @@ struct sm_node *sm_media_session_create_node(struct sm_media_session *sess,
 | 
				
			||||||
	struct sm_node *node;
 | 
						struct sm_node *node;
 | 
				
			||||||
	struct pw_proxy *proxy;
 | 
						struct pw_proxy *proxy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: node '%s'", impl, factory_name);
 | 
						pw_log_debug("%p: node '%s'", impl, factory_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	proxy = pw_core_create_object(impl->policy_core,
 | 
						proxy = pw_core_create_object(impl->policy_core,
 | 
				
			||||||
				factory_name,
 | 
									factory_name,
 | 
				
			||||||
| 
						 | 
					@ -1832,7 +1835,7 @@ static int link_nodes(struct impl *impl, struct endpoint_link *link,
 | 
				
			||||||
	bool passive = false;
 | 
						bool passive = false;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: linking %d -> %d", impl, outnode->obj.id, innode->obj.id);
 | 
						pw_log_debug("%p: linking %d -> %d", impl, outnode->obj.id, innode->obj.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = spa_dict_lookup(outnode->info->props, PW_KEY_NODE_PASSIVE)) != NULL)
 | 
						if ((str = spa_dict_lookup(outnode->info->props, PW_KEY_NODE_PASSIVE)) != NULL)
 | 
				
			||||||
		passive |= (pw_properties_parse_bool(str) || spa_streq(str, "out"));
 | 
							passive |= (pw_properties_parse_bool(str) || spa_streq(str, "out"));
 | 
				
			||||||
| 
						 | 
					@ -1856,13 +1859,13 @@ static int link_nodes(struct impl *impl, struct endpoint_link *link,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		inport = find_input_port(impl, outnode, outport, innode);
 | 
							inport = find_input_port(impl, outnode, outport, innode);
 | 
				
			||||||
		if (inport == NULL) {
 | 
							if (inport == NULL) {
 | 
				
			||||||
			pw_log_debug(NAME" %p: port %d:%d can't be linked", impl,
 | 
								pw_log_debug("%p: port %d:%d can't be linked", impl,
 | 
				
			||||||
				outport->direction, outport->obj.id);
 | 
									outport->direction, outport->obj.id);
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		inport->visited = true;
 | 
							inport->visited = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: port %d:%d -> %d:%d", impl,
 | 
							pw_log_debug("%p: port %d:%d -> %d:%d", impl,
 | 
				
			||||||
				outport->direction, outport->obj.id,
 | 
									outport->direction, outport->obj.id,
 | 
				
			||||||
				inport->direction, inport->obj.id);
 | 
									inport->direction, inport->obj.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2098,7 +2101,7 @@ static void monitor_core_done(void *data, uint32_t id, int seq)
 | 
				
			||||||
		handle_postponed_registry_events(impl, seq);
 | 
							handle_postponed_registry_events(impl, seq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (seq == impl->monitor_seq) {
 | 
						if (seq == impl->monitor_seq) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: monitor sync stop %d", impl, seq);
 | 
							pw_log_debug("%p: monitor sync stop %d", impl, seq);
 | 
				
			||||||
		pw_core_set_paused(impl->policy_core, false);
 | 
							pw_core_set_paused(impl->policy_core, false);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -2132,7 +2135,7 @@ static int start_session(struct impl *impl)
 | 
				
			||||||
static void core_info(void *data, const struct pw_core_info *info)
 | 
					static void core_info(void *data, const struct pw_core_info *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME" %p: info", impl);
 | 
						pw_log_debug("%p: info", impl);
 | 
				
			||||||
	impl->this.info = pw_core_info_merge(impl->this.info, info, true);
 | 
						impl->this.info = pw_core_info_merge(impl->this.info, info, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (impl->this.info->change_mask != 0)
 | 
						if (impl->this.info->change_mask != 0)
 | 
				
			||||||
| 
						 | 
					@ -2157,7 +2160,7 @@ static void core_done(void *data, uint32_t id, int seq)
 | 
				
			||||||
		struct sm_object *obj, *to;
 | 
							struct sm_object *obj, *to;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!impl->scanning) {
 | 
							if (!impl->scanning) {
 | 
				
			||||||
			pw_log_trace(NAME" %p: rescan %u %d", impl, id, seq);
 | 
								pw_log_trace("%p: rescan %u %d", impl, id, seq);
 | 
				
			||||||
			impl->scanning = true;
 | 
								impl->scanning = true;
 | 
				
			||||||
			sm_media_session_emit_rescan(impl, seq);
 | 
								sm_media_session_emit_rescan(impl, seq);
 | 
				
			||||||
			impl->scanning = false;
 | 
								impl->scanning = false;
 | 
				
			||||||
| 
						 | 
					@ -2170,7 +2173,7 @@ static void core_done(void *data, uint32_t id, int seq)
 | 
				
			||||||
		spa_list_for_each_safe(obj, to, &impl->object_list, link) {
 | 
							spa_list_for_each_safe(obj, to, &impl->object_list, link) {
 | 
				
			||||||
			if (obj->id == SPA_ID_INVALID)
 | 
								if (obj->id == SPA_ID_INVALID)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			pw_log_trace(NAME" %p: obj %p %08x", impl, obj, obj->changed);
 | 
								pw_log_trace("%p: obj %p %08x", impl, obj, obj->changed);
 | 
				
			||||||
			if (obj->changed)
 | 
								if (obj->changed)
 | 
				
			||||||
				sm_object_emit_update(obj);
 | 
									sm_object_emit_update(obj);
 | 
				
			||||||
			obj->changed = 0;
 | 
								obj->changed = 0;
 | 
				
			||||||
| 
						 | 
					@ -2203,7 +2206,7 @@ static const struct pw_core_events policy_core_events = {
 | 
				
			||||||
static void policy_core_destroy(void *data)
 | 
					static void policy_core_destroy(void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME" %p: policy core destroy", impl);
 | 
						pw_log_debug("%p: policy core destroy", impl);
 | 
				
			||||||
	impl->policy_core = NULL;
 | 
						impl->policy_core = NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2242,7 +2245,7 @@ static void session_shutdown(struct impl *impl)
 | 
				
			||||||
	struct registry_event *re;
 | 
						struct registry_event *re;
 | 
				
			||||||
	struct spa_list free_list;
 | 
						struct spa_list free_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info(NAME" %p", impl);
 | 
						pw_log_info("%p", impl);
 | 
				
			||||||
	sm_media_session_emit_shutdown(impl);
 | 
						sm_media_session_emit_shutdown(impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
| 
						 | 
					@ -2451,6 +2454,8 @@ int main(int argc, char *argv[])
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_init(&argc, &argv);
 | 
						pw_init(&argc, &argv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	while ((c = getopt_long(argc, argv, "hVc:v", long_options, NULL)) != -1) {
 | 
						while ((c = getopt_long(argc, argv, "hVc:v", long_options, NULL)) != -1) {
 | 
				
			||||||
		switch (c) {
 | 
							switch (c) {
 | 
				
			||||||
		case 'v':
 | 
							case 'v':
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define NAME "metadata"
 | 
					#define NAME "metadata"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct metadata {
 | 
					struct metadata {
 | 
				
			||||||
	struct pw_impl_metadata *impl;
 | 
						struct pw_impl_metadata *impl;
 | 
				
			||||||
	struct pw_metadata *metadata;
 | 
						struct pw_metadata *metadata;
 | 
				
			||||||
| 
						 | 
					@ -68,6 +71,8 @@ struct pw_metadata *sm_media_session_export_metadata(struct sm_media_session *se
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	struct spa_dict_item items[1];
 | 
						struct spa_dict_item items[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	this = calloc(1, sizeof(*this));
 | 
						this = calloc(1, sizeof(*this));
 | 
				
			||||||
	if (this == NULL)
 | 
						if (this == NULL)
 | 
				
			||||||
		goto error_errno;
 | 
							goto error_errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,6 +53,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFAULT_IDLE_SECONDS	3
 | 
					#define DEFAULT_IDLE_SECONDS	3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	struct timespec now;
 | 
						struct timespec now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -119,7 +122,7 @@ handle_endpoint(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	media_class = object->props ? pw_properties_get(object->props, PW_KEY_MEDIA_CLASS) : NULL;
 | 
						media_class = object->props ? pw_properties_get(object->props, PW_KEY_MEDIA_CLASS) : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint "PW_KEY_MEDIA_CLASS" %s", impl, media_class);
 | 
						pw_log_debug("%p: endpoint "PW_KEY_MEDIA_CLASS" %s", impl, media_class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (media_class == NULL)
 | 
						if (media_class == NULL)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -150,7 +153,7 @@ handle_endpoint(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
		ep->direction = direction;
 | 
							ep->direction = direction;
 | 
				
			||||||
		ep->type = ENDPOINT_TYPE_STREAM;
 | 
							ep->type = ENDPOINT_TYPE_STREAM;
 | 
				
			||||||
		ep->media = strdup(media_class);
 | 
							ep->media = strdup(media_class);
 | 
				
			||||||
		pw_log_debug(NAME "%p: endpoint %d is stream %s", impl, object->id, ep->media);
 | 
							pw_log_debug("%p: endpoint %d is stream %s", impl, object->id, ep->media);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		const char *media;
 | 
							const char *media;
 | 
				
			||||||
| 
						 | 
					@ -176,7 +179,7 @@ handle_endpoint(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
		ep->type = ENDPOINT_TYPE_DEVICE;
 | 
							ep->type = ENDPOINT_TYPE_DEVICE;
 | 
				
			||||||
		ep->media = strdup(media);
 | 
							ep->media = strdup(media);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: endpoint %d '%s' prio:%d", impl,
 | 
							pw_log_debug("%p: endpoint %d '%s' prio:%d", impl,
 | 
				
			||||||
				object->id, ep->media, ep->priority);
 | 
									object->id, ep->media, ep->priority);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return 1;
 | 
						return 1;
 | 
				
			||||||
| 
						 | 
					@ -230,7 +233,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
		res = 0;
 | 
							res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res < 0) {
 | 
						if (res < 0) {
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d", impl, object->id);
 | 
							pw_log_warn("%p: can't handle global %d", impl, object->id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		sm_media_session_schedule_rescan(impl->session);
 | 
							sm_media_session_schedule_rescan(impl->session);
 | 
				
			||||||
| 
						 | 
					@ -239,7 +242,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
static void session_remove(void *data, struct sm_object *object)
 | 
					static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: remove global '%d'", impl, object->id);
 | 
						pw_log_debug("%p: remove global '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_streq(object->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
						if (spa_streq(object->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
				
			||||||
		struct endpoint *ep;
 | 
							struct endpoint *ep;
 | 
				
			||||||
| 
						 | 
					@ -271,7 +274,7 @@ static int find_endpoint(void *data, struct endpoint *endpoint)
 | 
				
			||||||
	int priority = 0;
 | 
						int priority = 0;
 | 
				
			||||||
	uint64_t plugged = 0;
 | 
						uint64_t plugged = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: looking at endpoint '%d' enabled:%d busy:%d exclusive:%d",
 | 
						pw_log_debug("%p: looking at endpoint '%d' enabled:%d busy:%d exclusive:%d",
 | 
				
			||||||
			impl, endpoint->id, endpoint->enabled, endpoint->busy, endpoint->exclusive);
 | 
								impl, endpoint->id, endpoint->enabled, endpoint->busy, endpoint->exclusive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!endpoint->enabled)
 | 
						if (!endpoint->enabled)
 | 
				
			||||||
| 
						 | 
					@ -290,17 +293,17 @@ static int find_endpoint(void *data, struct endpoint *endpoint)
 | 
				
			||||||
	priority = endpoint->priority;
 | 
						priority = endpoint->priority;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((find->exclusive && endpoint->busy) || endpoint->exclusive) {
 | 
						if ((find->exclusive && endpoint->busy) || endpoint->exclusive) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: endpoint '%d' in use", impl, endpoint->id);
 | 
							pw_log_debug("%p: endpoint '%d' in use", impl, endpoint->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: found endpoint '%d' %"PRIu64" prio:%d", impl,
 | 
						pw_log_debug("%p: found endpoint '%d' %"PRIu64" prio:%d", impl,
 | 
				
			||||||
			endpoint->id, plugged, priority);
 | 
								endpoint->id, plugged, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (find->endpoint == NULL ||
 | 
						if (find->endpoint == NULL ||
 | 
				
			||||||
	    priority > find->priority ||
 | 
						    priority > find->priority ||
 | 
				
			||||||
	    (priority == find->priority && plugged > find->plugged)) {
 | 
						    (priority == find->priority && plugged > find->plugged)) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: new best %d %" PRIu64, impl, priority, plugged);
 | 
							pw_log_debug("%p: new best %d %" PRIu64, impl, priority, plugged);
 | 
				
			||||||
		find->endpoint = endpoint;
 | 
							find->endpoint = endpoint;
 | 
				
			||||||
		find->priority = priority;
 | 
							find->priority = priority;
 | 
				
			||||||
		find->plugged = plugged;
 | 
							find->plugged = plugged;
 | 
				
			||||||
| 
						 | 
					@ -313,7 +316,7 @@ static int link_endpoints(struct endpoint *endpoint, struct endpoint *peer)
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	struct pw_properties *props;
 | 
						struct pw_properties *props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: link endpoints %d %d", impl, endpoint->id, peer->id);
 | 
						pw_log_debug("%p: link endpoints %d %d", impl, endpoint->id, peer->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (endpoint->direction == PW_DIRECTION_INPUT) {
 | 
						if (endpoint->direction == PW_DIRECTION_INPUT) {
 | 
				
			||||||
		struct endpoint *t = endpoint;
 | 
							struct endpoint *t = endpoint;
 | 
				
			||||||
| 
						 | 
					@ -325,7 +328,7 @@ static int link_endpoints(struct endpoint *endpoint, struct endpoint *peer)
 | 
				
			||||||
	pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_OUTPUT_STREAM, "%d", -1);
 | 
						pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_OUTPUT_STREAM, "%d", -1);
 | 
				
			||||||
	pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT, "%d", peer->id);
 | 
						pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT, "%d", peer->id);
 | 
				
			||||||
	pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_STREAM, "%d", -1);
 | 
						pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_STREAM, "%d", -1);
 | 
				
			||||||
	pw_log_debug(NAME " %p: endpoint %d -> endpoint %d", impl,
 | 
						pw_log_debug("%p: endpoint %d -> endpoint %d", impl,
 | 
				
			||||||
			endpoint->id, peer->id);
 | 
								endpoint->id, peer->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_endpoint_create_link((struct pw_endpoint*)endpoint->obj->obj.proxy,
 | 
						pw_endpoint_create_link((struct pw_endpoint*)endpoint->obj->obj.proxy,
 | 
				
			||||||
| 
						 | 
					@ -344,7 +347,7 @@ static int link_node(struct endpoint *endpoint, struct sm_node *peer)
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	struct pw_properties *props;
 | 
						struct pw_properties *props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: link endpoint %d to node %d", impl, endpoint->id, peer->obj.id);
 | 
						pw_log_debug("%p: link endpoint %d to node %d", impl, endpoint->id, peer->obj.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	props = pw_properties_new(NULL, NULL);
 | 
						props = pw_properties_new(NULL, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -353,14 +356,14 @@ static int link_node(struct endpoint *endpoint, struct sm_node *peer)
 | 
				
			||||||
		pw_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", -1);
 | 
							pw_properties_setf(props, PW_KEY_LINK_OUTPUT_PORT, "%d", -1);
 | 
				
			||||||
		pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT, "%d", endpoint->id);
 | 
							pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT, "%d", endpoint->id);
 | 
				
			||||||
		pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_STREAM, "%d", -1);
 | 
							pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_INPUT_STREAM, "%d", -1);
 | 
				
			||||||
		pw_log_debug(NAME " %p: node %d -> endpoint %d", impl,
 | 
							pw_log_debug("%p: node %d -> endpoint %d", impl,
 | 
				
			||||||
				peer->obj.id, endpoint->id);
 | 
									peer->obj.id, endpoint->id);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_OUTPUT_ENDPOINT, "%d", endpoint->id);
 | 
							pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_OUTPUT_ENDPOINT, "%d", endpoint->id);
 | 
				
			||||||
		pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_OUTPUT_STREAM, "%d", -1);
 | 
							pw_properties_setf(props, PW_KEY_ENDPOINT_LINK_OUTPUT_STREAM, "%d", -1);
 | 
				
			||||||
		pw_properties_setf(props, PW_KEY_LINK_INPUT_NODE, "%d", peer->obj.id);
 | 
							pw_properties_setf(props, PW_KEY_LINK_INPUT_NODE, "%d", peer->obj.id);
 | 
				
			||||||
		pw_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", -1);
 | 
							pw_properties_setf(props, PW_KEY_LINK_INPUT_PORT, "%d", -1);
 | 
				
			||||||
		pw_log_debug(NAME " %p: endpoint %d -> node %d", impl,
 | 
							pw_log_debug("%p: endpoint %d -> node %d", impl,
 | 
				
			||||||
				endpoint->id, peer->obj.id);
 | 
									endpoint->id, peer->obj.id);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -389,12 +392,12 @@ static int rescan_endpoint(struct impl *impl, struct endpoint *ep)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ep->obj->info == NULL || ep->obj->info->props == NULL) {
 | 
						if (ep->obj->info == NULL || ep->obj->info->props == NULL) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: endpoint %d has no properties", impl, ep->id);
 | 
							pw_log_debug("%p: endpoint %d has no properties", impl, ep->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ep->linked > 0) {
 | 
						if (ep->linked > 0) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: endpoint %d is already linked", impl, ep->id);
 | 
							pw_log_debug("%p: endpoint %d is already linked", impl, ep->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -403,12 +406,12 @@ static int rescan_endpoint(struct impl *impl, struct endpoint *ep)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        str = spa_dict_lookup(props, PW_KEY_ENDPOINT_AUTOCONNECT);
 | 
					        str = spa_dict_lookup(props, PW_KEY_ENDPOINT_AUTOCONNECT);
 | 
				
			||||||
        if (str == NULL || !pw_properties_parse_bool(str)) {
 | 
					        if (str == NULL || !pw_properties_parse_bool(str)) {
 | 
				
			||||||
		pw_log_debug(NAME" %p: endpoint %d does not need autoconnect", impl, ep->id);
 | 
							pw_log_debug("%p: endpoint %d does not need autoconnect", impl, ep->id);
 | 
				
			||||||
                return 0;
 | 
					                return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ep->media == NULL) {
 | 
						if (ep->media == NULL) {
 | 
				
			||||||
		pw_log_debug(NAME" %p: endpoint %d has unknown media", impl, ep->id);
 | 
							pw_log_debug("%p: endpoint %d has unknown media", impl, ep->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -423,14 +426,14 @@ static int rescan_endpoint(struct impl *impl, struct endpoint *ep)
 | 
				
			||||||
	find.ep = ep;
 | 
						find.ep = ep;
 | 
				
			||||||
	find.exclusive = exclusive;
 | 
						find.exclusive = exclusive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: exclusive:%d", impl, exclusive);
 | 
						pw_log_debug("%p: exclusive:%d", impl, exclusive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	str = spa_dict_lookup(props, PW_KEY_ENDPOINT_TARGET);
 | 
						str = spa_dict_lookup(props, PW_KEY_ENDPOINT_TARGET);
 | 
				
			||||||
	if (str == NULL)
 | 
						if (str == NULL)
 | 
				
			||||||
		str = spa_dict_lookup(props, PW_KEY_NODE_TARGET);
 | 
							str = spa_dict_lookup(props, PW_KEY_NODE_TARGET);
 | 
				
			||||||
	if (str != NULL) {
 | 
						if (str != NULL) {
 | 
				
			||||||
		uint32_t path_id = atoi(str);
 | 
							uint32_t path_id = atoi(str);
 | 
				
			||||||
		pw_log_debug(NAME " %p: target:%d", impl, path_id);
 | 
							pw_log_debug("%p: target:%d", impl, path_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if ((obj = sm_media_session_find_object(impl->session, path_id)) != NULL) {
 | 
							if ((obj = sm_media_session_find_object(impl->session, path_id)) != NULL) {
 | 
				
			||||||
			if (spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
								if (spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
				
			||||||
| 
						 | 
					@ -450,7 +453,7 @@ static int rescan_endpoint(struct impl *impl, struct endpoint *ep)
 | 
				
			||||||
	if (find.endpoint == NULL) {
 | 
						if (find.endpoint == NULL) {
 | 
				
			||||||
		struct sm_object *obj;
 | 
							struct sm_object *obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_warn(NAME " %p: no endpoint found for %d", impl, ep->id);
 | 
							pw_log_warn("%p: no endpoint found for %d", impl, ep->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		str = spa_dict_lookup(props, PW_KEY_NODE_DONT_RECONNECT);
 | 
							str = spa_dict_lookup(props, PW_KEY_NODE_DONT_RECONNECT);
 | 
				
			||||||
		if (str != NULL && pw_properties_parse_bool(str)) {
 | 
							if (str != NULL && pw_properties_parse_bool(str)) {
 | 
				
			||||||
| 
						 | 
					@ -467,12 +470,12 @@ static int rescan_endpoint(struct impl *impl, struct endpoint *ep)
 | 
				
			||||||
	peer = find.endpoint;
 | 
						peer = find.endpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (exclusive && peer->busy) {
 | 
						if (exclusive && peer->busy) {
 | 
				
			||||||
		pw_log_warn(NAME" %p: endpoint %d busy, can't get exclusive access", impl, peer->id);
 | 
							pw_log_warn("%p: endpoint %d busy, can't get exclusive access", impl, peer->id);
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	peer->exclusive = exclusive;
 | 
						peer->exclusive = exclusive;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: linking to endpoint '%d'", impl, peer->id);
 | 
						pw_log_debug("%p: linking to endpoint '%d'", impl, peer->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        peer->busy = true;
 | 
					        peer->busy = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -490,7 +493,7 @@ static void session_rescan(void *data, int seq)
 | 
				
			||||||
	struct endpoint *ep;
 | 
						struct endpoint *ep;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	clock_gettime(CLOCK_MONOTONIC, &impl->now);
 | 
						clock_gettime(CLOCK_MONOTONIC, &impl->now);
 | 
				
			||||||
	pw_log_debug(NAME" %p: rescan", impl);
 | 
						pw_log_debug("%p: rescan", impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(ep, &impl->endpoint_list, link)
 | 
						spa_list_for_each(ep, &impl->endpoint_list, link)
 | 
				
			||||||
		rescan_endpoint(impl, ep);
 | 
							rescan_endpoint(impl, ep);
 | 
				
			||||||
| 
						 | 
					@ -515,6 +518,8 @@ int sm_policy_ep_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -65,6 +65,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_LINK_RETRY			5
 | 
					#define MAX_LINK_RETRY			5
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct default_node {
 | 
					struct default_node {
 | 
				
			||||||
	char *key;
 | 
						char *key;
 | 
				
			||||||
	char *key_config;
 | 
						char *key_config;
 | 
				
			||||||
| 
						 | 
					@ -360,7 +363,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct impl *impl = node->impl;
 | 
						struct impl *impl = node->impl;
 | 
				
			||||||
	const char *str;
 | 
						const char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: node %d %08x", impl, node->id, node->obj->obj.changed);
 | 
						pw_log_debug("%p: node %d %08x", impl, node->id, node->obj->obj.changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->obj->obj.avail & SM_NODE_CHANGE_MASK_INFO &&
 | 
						if (node->obj->obj.avail & SM_NODE_CHANGE_MASK_INFO &&
 | 
				
			||||||
	    node->obj->info != NULL && node->obj->info->props != NULL) {
 | 
						    node->obj->info != NULL && node->obj->info->props != NULL) {
 | 
				
			||||||
| 
						 | 
					@ -371,7 +374,7 @@ static void object_update(void *data)
 | 
				
			||||||
	if (!node->active) {
 | 
						if (!node->active) {
 | 
				
			||||||
		if (node->obj->obj.avail & SM_NODE_CHANGE_MASK_PARAMS) {
 | 
							if (node->obj->obj.avail & SM_NODE_CHANGE_MASK_PARAMS) {
 | 
				
			||||||
			if (!find_format(node)) {
 | 
								if (!find_format(node)) {
 | 
				
			||||||
				pw_log_debug(NAME" %p: node %d can't find format", impl, node->id);
 | 
									pw_log_debug("%p: node %d can't find format", impl, node->id);
 | 
				
			||||||
				return;
 | 
									return;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			node->active = true;
 | 
								node->active = true;
 | 
				
			||||||
| 
						 | 
					@ -402,7 +405,7 @@ handle_node(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
		role = pw_properties_get(object->props, PW_KEY_MEDIA_ROLE);
 | 
							role = pw_properties_get(object->props, PW_KEY_MEDIA_ROLE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: node "PW_KEY_MEDIA_CLASS" %s", impl, media_class);
 | 
						pw_log_debug("%p: node "PW_KEY_MEDIA_CLASS" %s", impl, media_class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (media_class == NULL)
 | 
						if (media_class == NULL)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -449,7 +452,7 @@ handle_node(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
		node->direction = direction;
 | 
							node->direction = direction;
 | 
				
			||||||
		node->type = NODE_TYPE_STREAM;
 | 
							node->type = NODE_TYPE_STREAM;
 | 
				
			||||||
		node->media = strdup(media_class);
 | 
							node->media = strdup(media_class);
 | 
				
			||||||
		pw_log_debug(NAME" %p: node %d is stream %s", impl, object->id, node->media);
 | 
							pw_log_debug("%p: node %d is stream %s", impl, object->id, node->media);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else {
 | 
						else {
 | 
				
			||||||
		const char *media;
 | 
							const char *media;
 | 
				
			||||||
| 
						 | 
					@ -493,7 +496,7 @@ handle_node(struct impl *impl, struct sm_object *object)
 | 
				
			||||||
		node->type = NODE_TYPE_DEVICE;
 | 
							node->type = NODE_TYPE_DEVICE;
 | 
				
			||||||
		node->media = strdup(media);
 | 
							node->media = strdup(media);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: node %d '%s' prio:%d", impl,
 | 
							pw_log_debug("%p: node %d '%s' prio:%d", impl,
 | 
				
			||||||
				object->id, node->media, node->priority);
 | 
									object->id, node->media, node->priority);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -659,7 +662,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
		res = 0;
 | 
							res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res < 0) {
 | 
						if (res < 0) {
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d", impl, object->id);
 | 
							pw_log_warn("%p: can't handle global %d", impl, object->id);
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		sm_media_session_schedule_rescan(impl->session);
 | 
							sm_media_session_schedule_rescan(impl->session);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -667,7 +670,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
static void session_remove(void *data, struct sm_object *object)
 | 
					static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: remove global '%d'", impl, object->id);
 | 
						pw_log_debug("%p: remove global '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_streq(object->type, PW_TYPE_INTERFACE_Node)) {
 | 
						if (spa_streq(object->type, PW_TYPE_INTERFACE_Node)) {
 | 
				
			||||||
		struct node *n, *node;
 | 
							struct node *n, *node;
 | 
				
			||||||
| 
						 | 
					@ -791,11 +794,11 @@ static int find_node(void *data, struct node *node)
 | 
				
			||||||
	bool is_default = false, can_passthrough = false;
 | 
						bool is_default = false, can_passthrough = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->obj->info == NULL) {
 | 
						if (node->obj->info == NULL) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: skipping node '%d' with no node info", impl, node->id);
 | 
							pw_log_debug("%p: skipping node '%d' with no node info", impl, node->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: looking at node '%d' enabled:%d state:%d peer:%p exclusive:%d",
 | 
						pw_log_debug("%p: looking at node '%d' enabled:%d state:%d peer:%p exclusive:%d",
 | 
				
			||||||
			impl, node->id, node->enabled, node->obj->info->state, node->peer, node->exclusive);
 | 
								impl, node->id, node->enabled, node->obj->info->state, node->peer, node->exclusive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!node->enabled || node->type == NODE_TYPE_UNKNOWN)
 | 
						if (!node->enabled || node->type == NODE_TYPE_UNKNOWN)
 | 
				
			||||||
| 
						 | 
					@ -852,7 +855,7 @@ static int find_node(void *data, struct node *node)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if ((find->exclusive && node->obj->info->state == PW_NODE_STATE_RUNNING) ||
 | 
						if ((find->exclusive && node->obj->info->state == PW_NODE_STATE_RUNNING) ||
 | 
				
			||||||
	    (node->peer && node->peer->exclusive)) {
 | 
						    (node->peer && node->peer->exclusive)) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: node '%d' in use", impl, node->id);
 | 
							pw_log_debug("%p: node '%d' in use", impl, node->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (find->node && find->have_passthrough && node->have_passthrough)
 | 
						if (find->node && find->have_passthrough && node->have_passthrough)
 | 
				
			||||||
| 
						 | 
					@ -860,17 +863,17 @@ static int find_node(void *data, struct node *node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((find->passthrough_only || node->passthrough_only) &&
 | 
						if ((find->passthrough_only || node->passthrough_only) &&
 | 
				
			||||||
	    !can_passthrough) {
 | 
						    !can_passthrough) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: node '%d' passthrough required", impl, node->id);
 | 
							pw_log_debug("%p: node '%d' passthrough required", impl, node->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: found node '%d' %"PRIu64" prio:%d", impl,
 | 
						pw_log_debug("%p: found node '%d' %"PRIu64" prio:%d", impl,
 | 
				
			||||||
			node->id, plugged, priority);
 | 
								node->id, plugged, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (find->result == NULL ||
 | 
						if (find->result == NULL ||
 | 
				
			||||||
	    priority > find->priority ||
 | 
						    priority > find->priority ||
 | 
				
			||||||
	    (priority == find->priority && plugged > find->plugged)) {
 | 
						    (priority == find->priority && plugged > find->plugged)) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: new best %d %" PRIu64, impl, priority, plugged);
 | 
							pw_log_debug("%p: new best %d %" PRIu64, impl, priority, plugged);
 | 
				
			||||||
		find->result = node;
 | 
							find->result = node;
 | 
				
			||||||
		find->priority = priority;
 | 
							find->priority = priority;
 | 
				
			||||||
		find->plugged = plugged;
 | 
							find->plugged = plugged;
 | 
				
			||||||
| 
						 | 
					@ -916,7 +919,7 @@ static int link_nodes(struct node *node, struct node *peer)
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	uint32_t node_id = node->id;
 | 
						uint32_t node_id = node->id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: link nodes %d %d remix:%d", impl,
 | 
						pw_log_debug("%p: link nodes %d %d remix:%d", impl,
 | 
				
			||||||
			node->id, peer->id, !node->dont_remix);
 | 
								node->id, peer->id, !node->dont_remix);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->want_passthrough) {
 | 
						if (node->want_passthrough) {
 | 
				
			||||||
| 
						 | 
					@ -966,7 +969,7 @@ static int unlink_nodes(struct node *node, struct node *peer)
 | 
				
			||||||
	struct impl *impl = node->impl;
 | 
						struct impl *impl = node->impl;
 | 
				
			||||||
	struct pw_properties *props;
 | 
						struct pw_properties *props;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: unlink nodes %d %d", impl, node->id, peer->id);
 | 
						pw_log_debug("%p: unlink nodes %d %d", impl, node->id, peer->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (peer->peer == node)
 | 
						if (peer->peer == node)
 | 
				
			||||||
		peer->peer = NULL;
 | 
							peer->peer = NULL;
 | 
				
			||||||
| 
						 | 
					@ -995,7 +998,7 @@ static int relink_node(struct impl *impl, struct node *n, struct node *peer)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (peer == n->failed_peer && n->failed_count > MAX_LINK_RETRY) {
 | 
						if (peer == n->failed_peer && n->failed_count > MAX_LINK_RETRY) {
 | 
				
			||||||
		/* Break rescan -> failed link -> rescan loop. */
 | 
							/* Break rescan -> failed link -> rescan loop. */
 | 
				
			||||||
		pw_log_debug(NAME" %p: tried to link '%d' on last rescan, not retrying",
 | 
							pw_log_debug("%p: tried to link '%d' on last rescan, not retrying",
 | 
				
			||||||
				impl, peer->id);
 | 
									impl, peer->id);
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -1015,7 +1018,7 @@ static int relink_node(struct impl *impl, struct node *n, struct node *peer)
 | 
				
			||||||
		if ((res = unlink_nodes(n, n->peer)) < 0)
 | 
							if ((res = unlink_nodes(n, n->peer)) < 0)
 | 
				
			||||||
			return res;
 | 
								return res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: linking node %d to node %d", impl, n->id, peer->id);
 | 
						pw_log_debug("%p: linking node %d to node %d", impl, n->id, peer->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* NB. if link_nodes returns error, n may have been invalidated */
 | 
						/* NB. if link_nodes returns error, n may have been invalidated */
 | 
				
			||||||
	if ((res = link_nodes(n, peer)) > 0) {
 | 
						if ((res = link_nodes(n, peer)) > 0) {
 | 
				
			||||||
| 
						 | 
					@ -1036,7 +1039,7 @@ static int rescan_node(struct impl *impl, struct node *n)
 | 
				
			||||||
	uint32_t path_id;
 | 
						uint32_t path_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!n->active) {
 | 
						if (!n->active) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: node %d is not active", impl, n->id);
 | 
							pw_log_debug("%p: node %d is not active", impl, n->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1046,7 +1049,7 @@ static int rescan_node(struct impl *impl, struct node *n)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (n->obj->info == NULL || n->obj->info->props == NULL) {
 | 
						if (n->obj->info == NULL || n->obj->info->props == NULL) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: node %d has no properties", impl, n->id);
 | 
							pw_log_debug("%p: node %d has no properties", impl, n->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1075,17 +1078,17 @@ static int rescan_node(struct impl *impl, struct node *n)
 | 
				
			||||||
		autoconnect = true;
 | 
							autoconnect = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!autoconnect) {
 | 
						if (!autoconnect) {
 | 
				
			||||||
		pw_log_debug(NAME" %p: node %d does not need autoconnect", impl, n->id);
 | 
							pw_log_debug("%p: node %d does not need autoconnect", impl, n->id);
 | 
				
			||||||
		configure_node(n, NULL, false);
 | 
							configure_node(n, NULL, false);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (n->media == NULL) {
 | 
						if (n->media == NULL) {
 | 
				
			||||||
		pw_log_debug(NAME" %p: node %d has unknown media", impl, n->id);
 | 
							pw_log_debug("%p: node %d has unknown media", impl, n->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: exclusive:%d", impl, n->exclusive);
 | 
						pw_log_debug("%p: exclusive:%d", impl, n->exclusive);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* honor target node set by user or asked for by the client */
 | 
						/* honor target node set by user or asked for by the client */
 | 
				
			||||||
	path_id = SPA_ID_INVALID;
 | 
						path_id = SPA_ID_INVALID;
 | 
				
			||||||
| 
						 | 
					@ -1111,7 +1114,7 @@ static int rescan_node(struct impl *impl, struct node *n)
 | 
				
			||||||
		bool recheck = !peer_is_target && (follows_default || target_found) &&
 | 
							bool recheck = !peer_is_target && (follows_default || target_found) &&
 | 
				
			||||||
			reconnect && !n->passthrough;
 | 
								reconnect && !n->passthrough;
 | 
				
			||||||
		if (!recheck) {
 | 
							if (!recheck) {
 | 
				
			||||||
			pw_log_debug(NAME " %p: node %d is already linked, peer-is-target:%d "
 | 
								pw_log_debug("%p: node %d is already linked, peer-is-target:%d "
 | 
				
			||||||
					"follows-default:%d", impl, n->id, peer_is_target,
 | 
										"follows-default:%d", impl, n->id, peer_is_target,
 | 
				
			||||||
					follows_default);
 | 
										follows_default);
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
| 
						 | 
					@ -1122,7 +1125,7 @@ static int rescan_node(struct impl *impl, struct node *n)
 | 
				
			||||||
			n->id, n->exclusive, reconnect, path_id, n->peer);
 | 
								n->id, n->exclusive, reconnect, path_id, n->peer);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (path_id != SPA_ID_INVALID) {
 | 
						if (path_id != SPA_ID_INVALID) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: target:%d", impl, path_id);
 | 
							pw_log_debug("%p: target:%d", impl, path_id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!reconnect)
 | 
							if (!reconnect)
 | 
				
			||||||
			n->obj->target_node = NULL;
 | 
								n->obj->target_node = NULL;
 | 
				
			||||||
| 
						 | 
					@ -1139,12 +1142,12 @@ static int rescan_node(struct impl *impl, struct node *n)
 | 
				
			||||||
			goto fallback;
 | 
								goto fallback;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		peer = sm_object_get_data(obj, SESSION_KEY);
 | 
							peer = sm_object_get_data(obj, SESSION_KEY);
 | 
				
			||||||
		pw_log_debug(NAME " %p: found target:%d type:%s %d:%d", impl,
 | 
							pw_log_debug("%p: found target:%d type:%s %d:%d", impl,
 | 
				
			||||||
				peer->id, obj->type, n->passthrough_only, peer->have_passthrough);
 | 
									peer->id, obj->type, n->passthrough_only, peer->have_passthrough);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		can_passthrough = check_passthrough(n, peer);
 | 
							can_passthrough = check_passthrough(n, peer);
 | 
				
			||||||
		if (n->passthrough_only && !can_passthrough) {
 | 
							if (n->passthrough_only && !can_passthrough) {
 | 
				
			||||||
			pw_log_info(NAME " %p: peer has no passthrough", impl);
 | 
								pw_log_info("%p: peer has no passthrough", impl);
 | 
				
			||||||
			goto fallback;
 | 
								goto fallback;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1186,16 +1189,16 @@ do_link:
 | 
				
			||||||
			sm_media_session_destroy_object(impl->session, n->id);
 | 
								sm_media_session_destroy_object(impl->session, n->id);
 | 
				
			||||||
		} else if (reconnect && n->connect_count > 0) {
 | 
							} else if (reconnect && n->connect_count > 0) {
 | 
				
			||||||
			/* Don't error the stream on reconnects */
 | 
								/* Don't error the stream on reconnects */
 | 
				
			||||||
			pw_log_info(NAME " %p: no node found for %d, waiting reconnect", impl, n->id);
 | 
								pw_log_info("%p: no node found for %d, waiting reconnect", impl, n->id);
 | 
				
			||||||
			if (n->peer != NULL)
 | 
								if (n->peer != NULL)
 | 
				
			||||||
				unlink_nodes(n, n->peer);
 | 
									unlink_nodes(n, n->peer);
 | 
				
			||||||
			return 0;
 | 
								return 0;
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			pw_log_warn(NAME " %p: no node found for %d, stream error", impl, n->id);
 | 
								pw_log_warn("%p: no node found for %d, stream error", impl, n->id);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		obj = sm_media_session_find_object(impl->session, n->client_id);
 | 
							obj = sm_media_session_find_object(impl->session, n->client_id);
 | 
				
			||||||
		pw_log_debug(NAME " %p: client_id:%d object:%p type:%s", impl,
 | 
							pw_log_debug("%p: client_id:%d object:%p type:%s", impl,
 | 
				
			||||||
				n->client_id, obj, obj ? obj->type : "None");
 | 
									n->client_id, obj, obj ? obj->type : "None");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (obj && spa_streq(obj->type, PW_TYPE_INTERFACE_Client)) {
 | 
							if (obj && spa_streq(obj->type, PW_TYPE_INTERFACE_Client)) {
 | 
				
			||||||
| 
						 | 
					@ -1204,7 +1207,7 @@ do_link:
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
	} else if (peer == n->peer) {
 | 
						} else if (peer == n->peer) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: node %d already linked to %d (not changing)",
 | 
							pw_log_debug("%p: node %d already linked to %d (not changing)",
 | 
				
			||||||
				impl, n->id, peer->id);
 | 
									impl, n->id, peer->id);
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					@ -1230,7 +1233,7 @@ static void session_info(void *data, const struct pw_core_info *info)
 | 
				
			||||||
		if ((str = spa_dict_lookup(info->props, "default.clock.rate")) != NULL)
 | 
							if ((str = spa_dict_lookup(info->props, "default.clock.rate")) != NULL)
 | 
				
			||||||
			impl->sample_rate = atoi(str);
 | 
								impl->sample_rate = atoi(str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: props changed sample_rate:%d", impl, impl->sample_rate);
 | 
							pw_log_debug("%p: props changed sample_rate:%d", impl, impl->sample_rate);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1241,7 +1244,7 @@ static void refresh_auto_default_nodes(struct impl *impl)
 | 
				
			||||||
	if (impl->session->metadata == NULL)
 | 
						if (impl->session->metadata == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: refresh", impl);
 | 
						pw_log_debug("%p: refresh", impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Auto set default nodes */
 | 
						/* Auto set default nodes */
 | 
				
			||||||
	for (def = impl->defaults; def->key != NULL; ++def) {
 | 
						for (def = impl->defaults; def->key != NULL; ++def) {
 | 
				
			||||||
| 
						 | 
					@ -1274,7 +1277,7 @@ static void session_rescan(void *data, int seq)
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	struct node *node;
 | 
						struct node *node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: rescan", impl);
 | 
						pw_log_debug("%p: rescan", impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
again:
 | 
					again:
 | 
				
			||||||
	impl->node_list_changed = false;
 | 
						impl->node_list_changed = false;
 | 
				
			||||||
| 
						 | 
					@ -1395,6 +1398,8 @@ int sm_policy_node_start(struct sm_media_session *session)
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
	const char *flag;
 | 
						const char *flag;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -120,7 +120,7 @@ static DBusHandlerResult object_handler(DBusConnection *c, DBusMessage *m, void
 | 
				
			||||||
					DBUS_TYPE_INVALID))
 | 
										DBUS_TYPE_INVALID))
 | 
				
			||||||
			goto invalid;
 | 
								goto invalid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: request release priority:%d", d, priority);
 | 
							pw_log_debug("%p: request release priority:%d", d, priority);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!(reply = dbus_message_new_method_return(m)))
 | 
							if (!(reply = dbus_message_new_method_return(m)))
 | 
				
			||||||
			goto oom;
 | 
								goto oom;
 | 
				
			||||||
| 
						 | 
					@ -260,7 +260,7 @@ static DBusHandlerResult filter_handler(DBusConnection *c, DBusMessage *m, void
 | 
				
			||||||
		if (!spa_streq(name, d->service_name))
 | 
							if (!spa_streq(name, d->service_name))
 | 
				
			||||||
			goto invalid;
 | 
								goto invalid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: acquired %s, %s", d, name, d->service_name);
 | 
							pw_log_debug("%p: acquired %s, %s", d, name, d->service_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		d->owning = true;
 | 
							d->owning = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -288,7 +288,7 @@ static DBusHandlerResult filter_handler(DBusConnection *c, DBusMessage *m, void
 | 
				
			||||||
		if (!spa_streq(name, d->service_name))
 | 
							if (!spa_streq(name, d->service_name))
 | 
				
			||||||
			goto invalid;
 | 
								goto invalid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: lost %s", d, name);
 | 
							pw_log_debug("%p: lost %s", d, name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		d->owning = false;
 | 
							d->owning = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -310,7 +310,7 @@ static DBusHandlerResult filter_handler(DBusConnection *c, DBusMessage *m, void
 | 
				
			||||||
		if (!spa_streq(name, d->service_name) || d->owning)
 | 
							if (!spa_streq(name, d->service_name) || d->owning)
 | 
				
			||||||
			goto invalid;
 | 
								goto invalid;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: changed %s: %s -> %s", d, name, old, new);
 | 
							pw_log_debug("%p: changed %s: %s -> %s", d, name, old, new);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (old == NULL || *old == 0) {
 | 
							if (old == NULL || *old == 0) {
 | 
				
			||||||
			if (d->callbacks->busy && !d->acquiring)
 | 
								if (d->callbacks->busy && !d->acquiring)
 | 
				
			||||||
| 
						 | 
					@ -374,7 +374,7 @@ rd_device_new(DBusConnection *connection, const char *device_name, const char *a
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dbus_connection_ref(d->connection);
 | 
						dbus_connection_ref(d->connection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME"%p: new device %s", d, device_name);
 | 
						pw_log_debug("%p: new device %s", d, device_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return d;
 | 
						return d;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -393,7 +393,7 @@ int rd_device_acquire(struct rd_device *d)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	dbus_error_init(&error);
 | 
						dbus_error_init(&error);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME"%p: reserve %s", d, d->service_name);
 | 
						pw_log_debug("%p: reserve %s", d, d->service_name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	d->acquiring = true;
 | 
						d->acquiring = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -401,12 +401,12 @@ int rd_device_acquire(struct rd_device *d)
 | 
				
			||||||
					d->service_name,
 | 
										d->service_name,
 | 
				
			||||||
					(d->priority < INT32_MAX ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT : 0),
 | 
										(d->priority < INT32_MAX ? DBUS_NAME_FLAG_ALLOW_REPLACEMENT : 0),
 | 
				
			||||||
					&error)) < 0) {
 | 
										&error)) < 0) {
 | 
				
			||||||
			pw_log_warn(NAME"%p: reserve failed: %s", d, error.message);
 | 
								pw_log_warn("%p: reserve failed: %s", d, error.message);
 | 
				
			||||||
			dbus_error_free(&error);
 | 
								dbus_error_free(&error);
 | 
				
			||||||
			return -EIO;
 | 
								return -EIO;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME"%p: reserve result: %d", d, res);
 | 
						pw_log_debug("%p: reserve result: %d", d, res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ||
 | 
						if (res == DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER ||
 | 
				
			||||||
	    res == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER)
 | 
						    res == DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER)
 | 
				
			||||||
| 
						 | 
					@ -451,7 +451,7 @@ int rd_device_complete_release(struct rd_device *d, int res)
 | 
				
			||||||
	if (d->reply == NULL)
 | 
						if (d->reply == NULL)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: complete release %d", d, res);
 | 
						pw_log_debug("%p: complete release %d", d, res);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!dbus_message_append_args(d->reply,
 | 
						if (!dbus_message_append_args(d->reply,
 | 
				
			||||||
				DBUS_TYPE_BOOLEAN, &ret,
 | 
									DBUS_TYPE_BOOLEAN, &ret,
 | 
				
			||||||
| 
						 | 
					@ -473,7 +473,7 @@ exit:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void rd_device_release(struct rd_device *d)
 | 
					void rd_device_release(struct rd_device *d)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pw_log_debug(NAME" %p: release %d", d, d->owning);
 | 
						pw_log_debug("%p: release %d", d, d->owning);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (d->owning) {
 | 
						if (d->owning) {
 | 
				
			||||||
		DBusError error;
 | 
							DBusError error;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,6 +71,9 @@
 | 
				
			||||||
#define SESSION_KEY	"restore-stream"
 | 
					#define SESSION_KEY	"restore-stream"
 | 
				
			||||||
#define PREFIX		"restore.stream."
 | 
					#define PREFIX		"restore.stream."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define SAVE_INTERVAL	1
 | 
					#define SAVE_INTERVAL	1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
| 
						 | 
					@ -119,7 +122,7 @@ static void remove_idle_timeout(struct impl *impl)
 | 
				
			||||||
static void idle_timeout(void *data, uint64_t expirations)
 | 
					static void idle_timeout(void *data, uint64_t expirations)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: idle timeout", impl);
 | 
						pw_log_debug("%p: idle timeout", impl);
 | 
				
			||||||
	remove_idle_timeout(impl);
 | 
						remove_idle_timeout(impl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -321,7 +324,7 @@ static int restore_stream(struct stream *str)
 | 
				
			||||||
	if (val == NULL)
 | 
						if (val == NULL)
 | 
				
			||||||
		return -ENOENT;
 | 
							return -ENOENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info("stream %d: restore '%s' to %s", str->id, str->key, val);
 | 
						pw_log_info("stream %d: restoring '%s' to %s", str->id, str->key, val);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_json_init(&it[0], val, strlen(val));
 | 
						spa_json_init(&it[0], val, strlen(val));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -456,7 +459,7 @@ static void update_stream(struct stream *str)
 | 
				
			||||||
	if (key == NULL)
 | 
						if (key == NULL)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: stream %p key '%s'", impl, str, key);
 | 
						pw_log_debug("%p: stream %p key '%s'", impl, str, key);
 | 
				
			||||||
	free(str->key);
 | 
						free(str->key);
 | 
				
			||||||
	str->key = key;
 | 
						str->key = key;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -473,7 +476,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct stream *str = data;
 | 
						struct stream *str = data;
 | 
				
			||||||
	struct impl *impl = str->impl;
 | 
						struct impl *impl = str->impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info(NAME" %p: stream %p %08x/%08x", impl, str,
 | 
						pw_log_info("%p: stream %p %08x/%08x", impl, str,
 | 
				
			||||||
			str->obj->obj.changed, str->obj->obj.avail);
 | 
								str->obj->obj.changed, str->obj->obj.avail);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (str->obj->obj.changed & (SM_NODE_CHANGE_MASK_INFO | SM_NODE_CHANGE_MASK_PARAMS))
 | 
						if (str->obj->obj.changed & (SM_NODE_CHANGE_MASK_INFO | SM_NODE_CHANGE_MASK_PARAMS))
 | 
				
			||||||
| 
						 | 
					@ -498,11 +501,11 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_strstartswith(media_class, "Stream/")) {
 | 
						if (spa_strstartswith(media_class, "Stream/")) {
 | 
				
			||||||
		media_class += strlen("Stream/");
 | 
							media_class += strlen("Stream/");
 | 
				
			||||||
		pw_log_debug(NAME " %p: add stream '%d' %s", impl, object->id, media_class);
 | 
							pw_log_debug("%p: add stream '%d' %s", impl, object->id, media_class);
 | 
				
			||||||
	} else if (spa_strstartswith(media_class, "Audio/") &&
 | 
						} else if (spa_strstartswith(media_class, "Audio/") &&
 | 
				
			||||||
		   ((routes = pw_properties_get(object->props, "device.routes")) == NULL ||
 | 
							   ((routes = pw_properties_get(object->props, "device.routes")) == NULL ||
 | 
				
			||||||
		    atoi(routes) == 0)) {
 | 
							    atoi(routes) == 0)) {
 | 
				
			||||||
		pw_log_debug(NAME " %p: add node '%d' %s", impl, object->id, media_class);
 | 
							pw_log_debug("%p: add node '%d' %s", impl, object->id, media_class);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -534,7 +537,7 @@ static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
	if (!spa_streq(object->type, PW_TYPE_INTERFACE_Node))
 | 
						if (!spa_streq(object->type, PW_TYPE_INTERFACE_Node))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: remove node '%d'", impl, object->id);
 | 
						pw_log_debug("%p: remove node '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((str = sm_object_get_data(object, SESSION_KEY)) != NULL)
 | 
						if ((str = sm_object_get_data(object, SESSION_KEY)) != NULL)
 | 
				
			||||||
		destroy_stream(impl, str);
 | 
							destroy_stream(impl, str);
 | 
				
			||||||
| 
						 | 
					@ -552,6 +555,8 @@ int sm_restore_stream_start(struct sm_media_session *session)
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -47,6 +47,9 @@
 | 
				
			||||||
#define NAME		"session-manager"
 | 
					#define NAME		"session-manager"
 | 
				
			||||||
#define SESSION_KEY	"session-manager"
 | 
					#define SESSION_KEY	"session-manager"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int sm_stream_endpoint_start(struct sm_media_session *sess);
 | 
					int sm_stream_endpoint_start(struct sm_media_session *sess);
 | 
				
			||||||
int sm_v4l2_endpoint_start(struct sm_media_session *sess);
 | 
					int sm_v4l2_endpoint_start(struct sm_media_session *sess);
 | 
				
			||||||
int sm_bluez5_endpoint_start(struct sm_media_session *sess);
 | 
					int sm_bluez5_endpoint_start(struct sm_media_session *sess);
 | 
				
			||||||
| 
						 | 
					@ -146,6 +149,8 @@ int sm_session_manager_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +52,9 @@
 | 
				
			||||||
#define DEFAULT_CHANNELS	2
 | 
					#define DEFAULT_CHANNELS	2
 | 
				
			||||||
#define DEFAULT_SAMPLERATE	48000
 | 
					#define DEFAULT_SAMPLERATE	48000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct endpoint;
 | 
					struct endpoint;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
| 
						 | 
					@ -116,7 +119,7 @@ static int client_endpoint_set_param(void *object,
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	struct node *node = endpoint->node;
 | 
						struct node *node = endpoint->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME " %p: node %d set param %d", impl, node->obj->obj.id, id);
 | 
						pw_log_debug("%p: node %d set param %d", impl, node->obj->obj.id, id);
 | 
				
			||||||
	return pw_node_set_param((struct pw_node*)node->obj->obj.proxy,
 | 
						return pw_node_set_param((struct pw_node*)node->obj->obj.proxy,
 | 
				
			||||||
			id, flags, param);
 | 
								id, flags, param);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -207,13 +210,13 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
 | 
							str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
 | 
				
			||||||
		if (str == NULL) {
 | 
							if (str == NULL) {
 | 
				
			||||||
			pw_log_warn(NAME" %p: no target endpoint given", impl);
 | 
								pw_log_warn("%p: no target endpoint given", impl);
 | 
				
			||||||
			res = -EINVAL;
 | 
								res = -EINVAL;
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		obj = sm_media_session_find_object(impl->session, atoi(str));
 | 
							obj = sm_media_session_find_object(impl->session, atoi(str));
 | 
				
			||||||
		if (obj == NULL || !spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
							if (obj == NULL || !spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
				
			||||||
			pw_log_warn(NAME" %p: could not find endpoint %s (%p)", impl, str, obj);
 | 
								pw_log_warn("%p: could not find endpoint %s (%p)", impl, str, obj);
 | 
				
			||||||
			res = -EINVAL;
 | 
								res = -EINVAL;
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -301,7 +304,7 @@ static void complete_endpoint(void *data)
 | 
				
			||||||
	struct node *node = endpoint->node;
 | 
						struct node *node = endpoint->node;
 | 
				
			||||||
	struct sm_param *p;
 | 
						struct sm_param *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
 | 
						pw_log_debug("%p: endpoint %p", impl, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(p, &node->obj->param_list, link) {
 | 
						spa_list_for_each(p, &node->obj->param_list, link) {
 | 
				
			||||||
		struct spa_audio_info info = { 0, };
 | 
							struct spa_audio_info info = { 0, };
 | 
				
			||||||
| 
						 | 
					@ -346,7 +349,7 @@ static void update_params(void *data)
 | 
				
			||||||
	struct node *node = endpoint->node;
 | 
						struct node *node = endpoint->node;
 | 
				
			||||||
	struct sm_param *p;
 | 
						struct sm_param *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
 | 
						pw_log_debug("%p: endpoint %p", impl, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params = alloca(sizeof(struct spa_pod *) * node->obj->n_params);
 | 
						params = alloca(sizeof(struct spa_pod *) * node->obj->n_params);
 | 
				
			||||||
	n_params = 0;
 | 
						n_params = 0;
 | 
				
			||||||
| 
						 | 
					@ -468,7 +471,7 @@ static struct endpoint *create_endpoint(struct node *node)
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_EnumFormat;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_EnumFormat;
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_Props;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_Props;
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_PropInfo;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_PropInfo;
 | 
				
			||||||
	pw_log_debug(NAME" %p: node %p proxy %p subscribe %d params", impl,
 | 
						pw_log_debug("%p: node %p proxy %p subscribe %d params", impl,
 | 
				
			||||||
				node->obj, node->obj->obj.proxy, n_subscribe);
 | 
									node->obj, node->obj->obj.proxy, n_subscribe);
 | 
				
			||||||
	pw_node_subscribe_params((struct pw_node*)node->obj->obj.proxy,
 | 
						pw_node_subscribe_params((struct pw_node*)node->obj->obj.proxy,
 | 
				
			||||||
				subscribe, n_subscribe);
 | 
									subscribe, n_subscribe);
 | 
				
			||||||
| 
						 | 
					@ -488,7 +491,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct node *node = data;
 | 
						struct node *node = data;
 | 
				
			||||||
	struct impl *impl = node->impl;
 | 
						struct impl *impl = node->impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: node %p endpoint %p %08x", impl, node, node->endpoint, node->obj->obj.changed);
 | 
						pw_log_debug("%p: node %p endpoint %p %08x", impl, node, node->endpoint, node->obj->obj.changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->endpoint == NULL &&
 | 
						if (node->endpoint == NULL &&
 | 
				
			||||||
	    node->obj->obj.avail & SM_OBJECT_CHANGE_MASK_PROPERTIES)
 | 
						    node->obj->obj.avail & SM_OBJECT_CHANGE_MASK_PROPERTIES)
 | 
				
			||||||
| 
						 | 
					@ -514,7 +517,7 @@ handle_node(struct impl *impl, struct sm_object *obj)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	media_class = obj->props ? pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS) : NULL;
 | 
						media_class = obj->props ? pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS) : NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: node "PW_KEY_MEDIA_CLASS" %s", impl, media_class);
 | 
						pw_log_debug("%p: node "PW_KEY_MEDIA_CLASS" %s", impl, media_class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (media_class == NULL)
 | 
						if (media_class == NULL)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -541,7 +544,7 @@ handle_node(struct impl *impl, struct sm_object *obj)
 | 
				
			||||||
	node->id = obj->id;
 | 
						node->id = obj->id;
 | 
				
			||||||
	node->direction = direction;
 | 
						node->direction = direction;
 | 
				
			||||||
	node->media = strdup(media_class);
 | 
						node->media = strdup(media_class);
 | 
				
			||||||
	pw_log_debug(NAME "%p: node %d is stream %d:%s", impl, node->id,
 | 
						pw_log_debug("%p: node %d is stream %d:%s", impl, node->id,
 | 
				
			||||||
			node->direction, node->media);
 | 
								node->direction, node->media);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sm_object_add_listener(obj, &node->listener, &object_events, node);
 | 
						sm_object_add_listener(obj, &node->listener, &object_events, node);
 | 
				
			||||||
| 
						 | 
					@ -569,7 +572,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
		res = 0;
 | 
							res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res < 0) {
 | 
						if (res < 0) {
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d: %s", impl,
 | 
							pw_log_warn("%p: can't handle global %d: %s", impl,
 | 
				
			||||||
				object->id, spa_strerror(res));
 | 
									object->id, spa_strerror(res));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -603,6 +606,8 @@ int sm_stream_endpoint_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,6 +48,9 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFAULT_IDLE_SECONDS	3
 | 
					#define DEFAULT_IDLE_SECONDS	3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct impl {
 | 
					struct impl {
 | 
				
			||||||
	struct timespec now;
 | 
						struct timespec now;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -91,7 +94,7 @@ static void idle_timeout(void *data, uint64_t expirations)
 | 
				
			||||||
	struct impl *impl = node->impl;
 | 
						struct impl *impl = node->impl;
 | 
				
			||||||
	struct spa_command *cmd = &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend);
 | 
						struct spa_command *cmd = &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info(NAME " %p: node %d suspend", impl, node->id);
 | 
						pw_log_info("%p: node %d suspend", impl, node->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	remove_idle_timeout(node);
 | 
						remove_idle_timeout(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -125,14 +128,14 @@ static void add_idle_timeout(struct node *node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int on_node_idle(struct impl *impl, struct node *node)
 | 
					static int on_node_idle(struct impl *impl, struct node *node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pw_log_debug(NAME" %p: node %d idle", impl, node->id);
 | 
						pw_log_debug("%p: node %d idle", impl, node->id);
 | 
				
			||||||
	add_idle_timeout(node);
 | 
						add_idle_timeout(node);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int on_node_running(struct impl *impl, struct node *node)
 | 
					static int on_node_running(struct impl *impl, struct node *node)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	pw_log_debug(NAME" %p: node %d running", impl, node->id);
 | 
						pw_log_debug("%p: node %d running", impl, node->id);
 | 
				
			||||||
	sm_object_acquire(&node->obj->obj);
 | 
						sm_object_acquire(&node->obj->obj);
 | 
				
			||||||
	remove_idle_timeout(node);
 | 
						remove_idle_timeout(node);
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
| 
						 | 
					@ -143,7 +146,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct node *node = data;
 | 
						struct node *node = data;
 | 
				
			||||||
	struct impl *impl = node->impl;
 | 
						struct impl *impl = node->impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: node %p %08x", impl, node, node->obj->obj.changed);
 | 
						pw_log_debug("%p: node %p %08x", impl, node, node->obj->obj.changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->obj->obj.changed & SM_NODE_CHANGE_MASK_INFO) {
 | 
						if (node->obj->obj.changed & SM_NODE_CHANGE_MASK_INFO) {
 | 
				
			||||||
		const struct pw_node_info *info = node->obj->info;
 | 
							const struct pw_node_info *info = node->obj->info;
 | 
				
			||||||
| 
						 | 
					@ -216,13 +219,13 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
		res = 0;
 | 
							res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res < 0)
 | 
						if (res < 0)
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d", impl, object->id);
 | 
							pw_log_warn("%p: can't handle global %d", impl, object->id);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void session_remove(void *data, struct sm_object *object)
 | 
					static void session_remove(void *data, struct sm_object *object)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl = data;
 | 
						struct impl *impl = data;
 | 
				
			||||||
	pw_log_debug(NAME " %p: remove global '%d'", impl, object->id);
 | 
						pw_log_debug("%p: remove global '%d'", impl, object->id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (spa_streq(object->type, PW_TYPE_INTERFACE_Node)) {
 | 
						if (spa_streq(object->type, PW_TYPE_INTERFACE_Node)) {
 | 
				
			||||||
		struct node *node;
 | 
							struct node *node;
 | 
				
			||||||
| 
						 | 
					@ -249,6 +252,8 @@ int sm_suspend_node_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,6 +52,9 @@
 | 
				
			||||||
#define NAME		"v4l2-endpoint"
 | 
					#define NAME		"v4l2-endpoint"
 | 
				
			||||||
#define SESSION_KEY	"v4l2-endpoint"
 | 
					#define SESSION_KEY	"v4l2-endpoint"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct endpoint {
 | 
					struct endpoint {
 | 
				
			||||||
	struct spa_list link;
 | 
						struct spa_list link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,7 +120,7 @@ static int client_endpoint_set_param(void *object,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct endpoint *endpoint = object;
 | 
						struct endpoint *endpoint = object;
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	pw_log_debug(NAME " %p: endpoint %p set param %d", impl, endpoint, id);
 | 
						pw_log_debug("%p: endpoint %p set param %d", impl, endpoint, id);
 | 
				
			||||||
	return pw_node_set_param((struct pw_node*)endpoint->node->node->obj.proxy,
 | 
						return pw_node_set_param((struct pw_node*)endpoint->node->node->obj.proxy,
 | 
				
			||||||
				id, flags, param);
 | 
									id, flags, param);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -145,7 +148,7 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
				
			||||||
	struct pw_properties *p;
 | 
						struct pw_properties *p;
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
 | 
						pw_log_debug("%p: endpoint %p", impl, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (props == NULL)
 | 
						if (props == NULL)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -160,13 +163,13 @@ static int client_endpoint_create_link(void *object, const struct spa_dict *prop
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
 | 
							str = spa_dict_lookup(props, PW_KEY_ENDPOINT_LINK_INPUT_ENDPOINT);
 | 
				
			||||||
		if (str == NULL) {
 | 
							if (str == NULL) {
 | 
				
			||||||
			pw_log_warn(NAME" %p: no target endpoint given", impl);
 | 
								pw_log_warn("%p: no target endpoint given", impl);
 | 
				
			||||||
			res = -EINVAL;
 | 
								res = -EINVAL;
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		obj = sm_media_session_find_object(impl->session, atoi(str));
 | 
							obj = sm_media_session_find_object(impl->session, atoi(str));
 | 
				
			||||||
		if (obj == NULL || !spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
							if (obj == NULL || !spa_streq(obj->type, PW_TYPE_INTERFACE_Endpoint)) {
 | 
				
			||||||
			pw_log_warn(NAME" %p: could not find endpoint %s (%p)", impl, str, obj);
 | 
								pw_log_warn("%p: could not find endpoint %s (%p)", impl, str, obj);
 | 
				
			||||||
			res = -EINVAL;
 | 
								res = -EINVAL;
 | 
				
			||||||
			goto exit;
 | 
								goto exit;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
| 
						 | 
					@ -264,7 +267,7 @@ static void update_params(void *data)
 | 
				
			||||||
	struct sm_node *node = endpoint->node->node;
 | 
						struct sm_node *node = endpoint->node->node;
 | 
				
			||||||
	struct sm_param *p;
 | 
						struct sm_param *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint", endpoint);
 | 
						pw_log_debug("%p: endpoint", endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	params = alloca(sizeof(struct spa_pod *) * node->n_params);
 | 
						params = alloca(sizeof(struct spa_pod *) * node->n_params);
 | 
				
			||||||
	n_params = 0;
 | 
						n_params = 0;
 | 
				
			||||||
| 
						 | 
					@ -294,7 +297,7 @@ static void object_update(void *data)
 | 
				
			||||||
	struct impl *impl = endpoint->impl;
 | 
						struct impl *impl = endpoint->impl;
 | 
				
			||||||
	struct sm_node *node = endpoint->node->node;
 | 
						struct sm_node *node = endpoint->node->node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p", impl, endpoint);
 | 
						pw_log_debug("%p: endpoint %p", impl, endpoint);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (node->obj.changed & SM_NODE_CHANGE_MASK_PARAMS)
 | 
						if (node->obj.changed & SM_NODE_CHANGE_MASK_PARAMS)
 | 
				
			||||||
		update_params(endpoint);
 | 
							update_params(endpoint);
 | 
				
			||||||
| 
						 | 
					@ -453,7 +456,7 @@ static struct endpoint *create_endpoint(struct node *node)
 | 
				
			||||||
	endpoint->info.n_params = 2;
 | 
						endpoint->info.n_params = 2;
 | 
				
			||||||
	spa_list_init(&endpoint->stream_list);
 | 
						spa_list_init(&endpoint->stream_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: new endpoint %p for v4l2 node %p", impl, endpoint, node);
 | 
						pw_log_debug("%p: new endpoint %p for v4l2 node %p", impl, endpoint, node);
 | 
				
			||||||
	pw_proxy_add_listener(proxy,
 | 
						pw_proxy_add_listener(proxy,
 | 
				
			||||||
			&endpoint->proxy_listener,
 | 
								&endpoint->proxy_listener,
 | 
				
			||||||
			&proxy_events, endpoint);
 | 
								&proxy_events, endpoint);
 | 
				
			||||||
| 
						 | 
					@ -466,7 +469,7 @@ static struct endpoint *create_endpoint(struct node *node)
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_EnumFormat;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_EnumFormat;
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_Props;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_Props;
 | 
				
			||||||
	subscribe[n_subscribe++] = SPA_PARAM_PropInfo;
 | 
						subscribe[n_subscribe++] = SPA_PARAM_PropInfo;
 | 
				
			||||||
	pw_log_debug(NAME" %p: endpoint %p proxy %p subscribe %d params", impl,
 | 
						pw_log_debug("%p: endpoint %p proxy %p subscribe %d params", impl,
 | 
				
			||||||
				endpoint, node->node->obj.proxy, n_subscribe);
 | 
									endpoint, node->node->obj.proxy, n_subscribe);
 | 
				
			||||||
	pw_node_subscribe_params((struct pw_node*)node->node->obj.proxy,
 | 
						pw_node_subscribe_params((struct pw_node*)node->node->obj.proxy,
 | 
				
			||||||
				subscribe, n_subscribe);
 | 
									subscribe, n_subscribe);
 | 
				
			||||||
| 
						 | 
					@ -493,12 +496,12 @@ static int setup_v4l2_endpoint(struct device *device)
 | 
				
			||||||
	struct sm_node *n;
 | 
						struct sm_node *n;
 | 
				
			||||||
	struct sm_device *d = device->device;
 | 
						struct sm_device *d = device->device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p setup", impl, d);
 | 
						pw_log_debug("%p: device %p setup", impl, d);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	spa_list_for_each(n, &d->node_list, link) {
 | 
						spa_list_for_each(n, &d->node_list, link) {
 | 
				
			||||||
		struct node *node;
 | 
							struct node *node;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		pw_log_debug(NAME" %p: device %p has node %p", impl, d, n);
 | 
							pw_log_debug("%p: device %p has node %p", impl, d, n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		node = sm_object_add_data(&n->obj, SESSION_KEY, sizeof(struct node));
 | 
							node = sm_object_add_data(&n->obj, SESSION_KEY, sizeof(struct node));
 | 
				
			||||||
		node->device = device;
 | 
							node->device = device;
 | 
				
			||||||
| 
						 | 
					@ -521,7 +524,7 @@ static int deactivate_device(struct device *device)
 | 
				
			||||||
	struct impl *impl = device->impl;
 | 
						struct impl *impl = device->impl;
 | 
				
			||||||
	struct endpoint *e;
 | 
						struct endpoint *e;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p deactivate", impl, device->device);
 | 
						pw_log_debug("%p: device %p deactivate", impl, device->device);
 | 
				
			||||||
	spa_list_consume(e, &device->endpoint_list, link)
 | 
						spa_list_consume(e, &device->endpoint_list, link)
 | 
				
			||||||
		destroy_endpoint(impl, e);
 | 
							destroy_endpoint(impl, e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -533,7 +536,7 @@ static void device_update(void *data)
 | 
				
			||||||
	struct device *device = data;
 | 
						struct device *device = data;
 | 
				
			||||||
	struct impl *impl = device->impl;
 | 
						struct impl *impl = device->impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device %p %08x %08x", impl, device,
 | 
						pw_log_debug("%p: device %p %08x %08x", impl, device,
 | 
				
			||||||
			device->device->obj.avail, device->device->obj.changed);
 | 
								device->device->obj.avail, device->device->obj.changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!SPA_FLAG_IS_SET(device->device->obj.avail,
 | 
						if (!SPA_FLAG_IS_SET(device->device->obj.avail,
 | 
				
			||||||
| 
						 | 
					@ -564,7 +567,7 @@ handle_device(struct impl *impl, struct sm_object *obj)
 | 
				
			||||||
	media_class = pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS);
 | 
						media_class = pw_properties_get(obj->props, PW_KEY_MEDIA_CLASS);
 | 
				
			||||||
	str = pw_properties_get(obj->props, PW_KEY_DEVICE_API);
 | 
						str = pw_properties_get(obj->props, PW_KEY_DEVICE_API);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_debug(NAME" %p: device "PW_KEY_MEDIA_CLASS":%s api:%s", impl, media_class, str);
 | 
						pw_log_debug("%p: device "PW_KEY_MEDIA_CLASS":%s api:%s", impl, media_class, str);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!spa_strstartswith(media_class, "Video/"))
 | 
						if (!spa_strstartswith(media_class, "Video/"))
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
| 
						 | 
					@ -576,7 +579,7 @@ handle_device(struct impl *impl, struct sm_object *obj)
 | 
				
			||||||
	device->id = obj->id;
 | 
						device->id = obj->id;
 | 
				
			||||||
	device->device = (struct sm_device*)obj;
 | 
						device->device = (struct sm_device*)obj;
 | 
				
			||||||
	spa_list_init(&device->endpoint_list);
 | 
						spa_list_init(&device->endpoint_list);
 | 
				
			||||||
	pw_log_debug(NAME" %p: found v4l2 device %d media_class %s", impl, obj->id, media_class);
 | 
						pw_log_debug("%p: found v4l2 device %d media_class %s", impl, obj->id, media_class);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sm_object_add_listener(obj, &device->listener, &device_events, device);
 | 
						sm_object_add_listener(obj, &device->listener, &device_events, device);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -601,7 +604,7 @@ static void session_create(void *data, struct sm_object *object)
 | 
				
			||||||
		res = 0;
 | 
							res = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (res < 0) {
 | 
						if (res < 0) {
 | 
				
			||||||
		pw_log_warn(NAME" %p: can't handle global %d: %s", impl,
 | 
							pw_log_warn("%p: can't handle global %d: %s", impl,
 | 
				
			||||||
				object->id, spa_strerror(res));
 | 
									object->id, spa_strerror(res));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -635,6 +638,8 @@ int sm_v4l2_endpoint_start(struct sm_media_session *session)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct impl *impl;
 | 
						struct impl *impl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -46,8 +46,12 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/** \page page_media_session_module_v4l2_monitor Media Session Module: V4L2 Monitor
 | 
					/** \page page_media_session_module_v4l2_monitor Media Session Module: V4L2 Monitor
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					#define NAME "v4l2-monitor"
 | 
				
			||||||
#define SESSION_CONF	"v4l2-monitor.conf"
 | 
					#define SESSION_CONF	"v4l2-monitor.conf"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					PW_LOG_TOPIC_STATIC(mod_topic, "ms.mod." NAME);
 | 
				
			||||||
 | 
					#define PW_LOG_TOPIC_DEFAULT mod_topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct device;
 | 
					struct device;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct node {
 | 
					struct node {
 | 
				
			||||||
| 
						 | 
					@ -539,6 +543,8 @@ int sm_v4l2_monitor_start(struct sm_media_session *sess)
 | 
				
			||||||
	int res;
 | 
						int res;
 | 
				
			||||||
	void *iface;
 | 
						void *iface;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						PW_LOG_TOPIC_INIT(mod_topic);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	impl = calloc(1, sizeof(struct impl));
 | 
						impl = calloc(1, sizeof(struct impl));
 | 
				
			||||||
	if (impl == NULL)
 | 
						if (impl == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue