1 /* PipeWire
2  *
3  * Copyright © 2017 Wim Taymans <wim.taymans@gmail.com>
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 #include <stdio.h>
26 #include <errno.h>
27 
28 #include "spa/pod/parser.h"
29 #include "spa/pod/builder.h"
30 #include "spa/debug/pod.h"
31 #include "spa/utils/string.h"
32 
33 #include "pipewire/pipewire.h"
34 #include "pipewire/private.h"
35 #include "pipewire/protocol.h"
36 #include "pipewire/resource.h"
37 #include "pipewire/extensions/protocol-native.h"
38 #include "pipewire/extensions/metadata.h"
39 #include "pipewire/extensions/session-manager.h"
40 #include "pipewire/extensions/client-node.h"
41 
42 #include "interfaces.h"
43 #include "typemap.h"
44 
45 #include "../connection.h"
46 
47 PW_LOG_TOPIC_EXTERN(mod_topic);
48 #define PW_LOG_TOPIC_DEFAULT mod_topic
49 
50 #define PW_PROTOCOL_NATIVE_FLAG_REMAP        (1<<0)
51 
52 SPA_EXPORT
pw_protocol_native0_find_type(struct pw_impl_client * client,const char * type)53 uint32_t pw_protocol_native0_find_type(struct pw_impl_client *client, const char *type)
54 {
55 	uint32_t i;
56 	for (i = 0; i < SPA_N_ELEMENTS(type_map); i++) {
57 		if (spa_streq(type_map[i].type, type))
58 			return i;
59 	}
60 	return SPA_ID_INVALID;
61 }
62 
63 static void
update_types_server(struct pw_resource * resource)64 update_types_server(struct pw_resource *resource)
65 {
66 	struct spa_pod_builder *b;
67 	struct spa_pod_frame f;
68 	uint32_t i;
69 
70 	b = pw_protocol_native_begin_resource(resource, PW_CORE_V0_EVENT_UPDATE_TYPES, NULL);
71 
72         spa_pod_builder_push_struct(b, &f);
73 	spa_pod_builder_add(b,
74 			    "i", 0,
75 			    "i", SPA_N_ELEMENTS(type_map), NULL);
76 
77 	for (i = 0; i < SPA_N_ELEMENTS(type_map); i++) {
78 		spa_pod_builder_add(b, "s", type_map[i].type, NULL);
79 	}
80         spa_pod_builder_pop(b, &f);
81 
82 	pw_protocol_native_end_resource(resource, b);
83 }
84 
85 
core_marshal_info(void * object,const struct pw_core_info * info)86 static void core_marshal_info(void *object, const struct pw_core_info *info)
87 {
88 	struct pw_resource *resource = object;
89 	struct pw_impl_client *client = pw_resource_get_client(resource);
90 	struct protocol_compat_v2 *compat_v2 = client->compat_v2;
91 	struct spa_pod_builder *b;
92 	uint32_t i, n_items;
93 	uint64_t change_mask = 0;
94 	struct spa_pod_frame f;
95 	struct pw_protocol_native_message *msg;
96 
97 #define PW_CORE_V0_CHANGE_MASK_USER_NAME  (1 << 0)
98 #define PW_CORE_V0_CHANGE_MASK_HOST_NAME  (1 << 1)
99 #define PW_CORE_V0_CHANGE_MASK_VERSION    (1 << 2)
100 #define PW_CORE_V0_CHANGE_MASK_NAME       (1 << 3)
101 #define PW_CORE_V0_CHANGE_MASK_COOKIE     (1 << 4)
102 #define PW_CORE_V0_CHANGE_MASK_PROPS      (1 << 5)
103 
104 	if (compat_v2->send_types) {
105 		update_types_server(resource);
106 		change_mask |= PW_CORE_V0_CHANGE_MASK_USER_NAME |
107 			PW_CORE_V0_CHANGE_MASK_HOST_NAME |
108 			PW_CORE_V0_CHANGE_MASK_VERSION |
109 			PW_CORE_V0_CHANGE_MASK_NAME |
110 			PW_CORE_V0_CHANGE_MASK_COOKIE;
111 		compat_v2->send_types = false;
112 	}
113 	b = pw_protocol_native_begin_resource(resource, PW_CORE_V0_EVENT_INFO, &msg);
114 
115 	n_items = info->props ? info->props->n_items : 0;
116 
117 	if (info->change_mask & PW_CORE_CHANGE_MASK_PROPS)
118 		change_mask |= PW_CORE_V0_CHANGE_MASK_PROPS;
119 
120         spa_pod_builder_push_struct(b, &f);
121 	spa_pod_builder_add(b,
122 			    "i", info->id,
123 			    "l", change_mask,
124 			    "s", info->user_name,
125 			    "s", info->host_name,
126 			    "s", info->version,
127 			    "s", info->name,
128 			    "i", info->cookie,
129 			    "i", n_items, NULL);
130 
131 	for (i = 0; i < n_items; i++) {
132 		spa_pod_builder_add(b,
133 				    "s", info->props->items[i].key,
134 				    "s", info->props->items[i].value, NULL);
135 	}
136         spa_pod_builder_pop(b, &f);
137 
138 	pw_protocol_native_end_resource(resource, b);
139 }
140 
core_marshal_done(void * object,uint32_t id,int seq)141 static void core_marshal_done(void *object, uint32_t id, int seq)
142 {
143 	struct pw_resource *resource = object;
144 	struct spa_pod_builder *b;
145 
146 	b = pw_protocol_native_begin_resource(resource, PW_CORE_V0_EVENT_DONE, NULL);
147 
148 	spa_pod_builder_add_struct(b, "i", seq);
149 
150 	pw_protocol_native_end_resource(resource, b);
151 }
152 
core_marshal_error(void * object,uint32_t id,int seq,int res,const char * error)153 static void core_marshal_error(void *object, uint32_t id, int seq, int res, const char *error)
154 {
155 	struct pw_resource *resource = object;
156 	struct spa_pod_builder *b;
157 
158 	b = pw_protocol_native_begin_resource(resource, PW_CORE_V0_EVENT_ERROR, NULL);
159 
160 	spa_pod_builder_add_struct(b,
161 			       "i", id,
162 			       "i", res,
163 			       "s", error);
164 
165 	pw_protocol_native_end_resource(resource, b);
166 }
167 
core_marshal_remove_id(void * object,uint32_t id)168 static void core_marshal_remove_id(void *object, uint32_t id)
169 {
170 	struct pw_resource *resource = object;
171 	struct spa_pod_builder *b;
172 
173 	b = pw_protocol_native_begin_resource(resource, PW_CORE_V0_EVENT_REMOVE_ID, NULL);
174 
175 	spa_pod_builder_add_struct(b, "i", id);
176 
177 	pw_protocol_native_end_resource(resource, b);
178 }
179 
core_demarshal_client_update(void * object,const struct pw_protocol_native_message * msg)180 static int core_demarshal_client_update(void *object, const struct pw_protocol_native_message *msg)
181 {
182 	struct pw_resource *resource = object;
183 	struct pw_impl_client *client = pw_resource_get_client(resource);
184 	struct spa_dict props;
185 	struct spa_pod_parser prs;
186 	struct spa_pod_frame f;
187 	uint32_t i;
188 
189 	spa_pod_parser_init(&prs, msg->data, msg->size);
190 	if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
191 	    spa_pod_parser_get(&prs,
192 		    "i", &props.n_items, NULL) < 0)
193 		return -EINVAL;
194 
195 	props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
196 	for (i = 0; i < props.n_items; i++) {
197 		if (spa_pod_parser_get(&prs,
198 				"s", &props.items[i].key,
199 				"s", &props.items[i].value,
200 				NULL) < 0)
201 			return -EINVAL;
202 	}
203 	pw_impl_client_update_properties(client, &props);
204 	return 0;
205 }
206 
parse_perms(const char * str)207 static uint32_t parse_perms(const char *str)
208 {
209 	uint32_t perms = 0;
210 
211 	while (*str != '\0') {
212 		switch (*str++) {
213 		case 'r':
214 			perms |= PW_PERM_R;
215 			break;
216 		case 'w':
217 			perms |= PW_PERM_W;
218 			break;
219 		case 'x':
220 			perms |= PW_PERM_X;
221 			break;
222 		}
223 	}
224 	return perms;
225 }
226 
core_demarshal_permissions(void * object,const struct pw_protocol_native_message * msg)227 static int core_demarshal_permissions(void *object, const struct pw_protocol_native_message *msg)
228 {
229 	struct pw_resource *resource = object;
230 	struct spa_dict props;
231 	struct spa_pod_parser prs;
232 	struct spa_pod_frame f;
233 	uint32_t i, n_permissions;
234 	struct pw_permission *permissions, defperm = { 0, };
235 
236 	spa_pod_parser_init(&prs, msg->data, msg->size);
237 	if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
238 	    spa_pod_parser_get(&prs, "i", &props.n_items, NULL) < 0)
239 		return -EINVAL;
240 
241 	props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
242 
243 	n_permissions = 0;
244 	permissions = alloca(props.n_items * sizeof(struct pw_permission));
245 
246 	for (i = 0; i < props.n_items; i++) {
247 		uint32_t id, perms;
248 		const char *str;
249 
250 		if (spa_pod_parser_get(&prs,
251 				"s", &props.items[i].key,
252 				"s", &props.items[i].value,
253 				NULL) < 0)
254 			return -EINVAL;
255 
256 		str = props.items[i].value;
257 		/* first set global permissions */
258 		if (spa_streq(props.items[i].key, PW_CORE_PERMISSIONS_GLOBAL)) {
259 			size_t len;
260 
261                         /* <global-id>:[r][w][x] */
262 			len = strcspn(str, ":");
263 			if (len == 0)
264 				continue;
265 			id = atoi(str);
266 			perms = parse_perms(str + len);
267 			permissions[n_permissions++] = PW_PERMISSION_INIT(id, perms);
268 		} else if (spa_streq(props.items[i].key, PW_CORE_PERMISSIONS_DEFAULT)) {
269 			perms = parse_perms(str);
270 			defperm = PW_PERMISSION_INIT(PW_ID_ANY, perms);
271 		}
272 	}
273 	/* add default permission if set */
274 	if (defperm.id == PW_ID_ANY)
275 		permissions[n_permissions++] = defperm;
276 
277 	for (i = 0; i < n_permissions; i++) {
278 		pw_log_debug("%d: %d: %08x", i, permissions[i].id, permissions[i].permissions);
279 	}
280 
281 	return pw_impl_client_update_permissions(resource->client,
282 			n_permissions, permissions);
283 }
284 
core_demarshal_hello(void * object,const struct pw_protocol_native_message * msg)285 static int core_demarshal_hello(void *object, const struct pw_protocol_native_message *msg)
286 {
287 	struct pw_resource *resource = object;
288 	struct spa_pod_parser prs;
289 	void *ptr;
290 
291 	spa_pod_parser_init(&prs, msg->data, msg->size);
292 	if (spa_pod_parser_get_struct(&prs,
293 				"P", &ptr) < 0)
294 		return -EINVAL;
295 
296         return pw_resource_notify(resource, struct pw_core_methods, hello, 0, 2);
297 }
298 
core_demarshal_sync(void * object,const struct pw_protocol_native_message * msg)299 static int core_demarshal_sync(void *object, const struct pw_protocol_native_message *msg)
300 {
301 	struct pw_resource *resource = object;
302 	struct spa_pod_parser prs;
303 	uint32_t seq;
304 
305 	spa_pod_parser_init(&prs, msg->data, msg->size);
306 	if (spa_pod_parser_get_struct(&prs, "i", &seq) < 0)
307 		return -EINVAL;
308 
309         return pw_resource_notify(resource, struct pw_core_methods, sync, 0, 0, seq);
310 }
311 
core_demarshal_get_registry(void * object,const struct pw_protocol_native_message * msg)312 static int core_demarshal_get_registry(void *object, const struct pw_protocol_native_message *msg)
313 {
314 	struct pw_resource *resource = object;
315 	struct spa_pod_parser prs;
316 	int32_t version, new_id;
317 
318 	spa_pod_parser_init(&prs, msg->data, msg->size);
319 	if (spa_pod_parser_get_struct(&prs,
320 				"i", &version,
321 				"i", &new_id) < 0)
322 		return -EINVAL;
323 
324         return pw_resource_notify(resource, struct pw_core_methods, get_registry, 0, version, new_id);
325 }
326 
327 SPA_EXPORT
pw_protocol_native0_type_from_v2(struct pw_impl_client * client,uint32_t type)328 uint32_t pw_protocol_native0_type_from_v2(struct pw_impl_client *client, uint32_t type)
329 {
330 	void *t;
331 	uint32_t index;
332 	struct protocol_compat_v2 *compat_v2 = client->compat_v2;
333 
334 	if ((t = pw_map_lookup(&compat_v2->types, type)) == NULL)
335 		return SPA_ID_INVALID;
336 
337 	index = PW_MAP_PTR_TO_ID(t);
338 	if (index >= SPA_N_ELEMENTS(type_map))
339 		return SPA_ID_INVALID;
340 
341 	return type_map[index].id;
342 }
343 
344 SPA_EXPORT
pw_protocol_native0_name_from_v2(struct pw_impl_client * client,uint32_t type)345 const char * pw_protocol_native0_name_from_v2(struct pw_impl_client *client, uint32_t type)
346 {
347 	void *t;
348 	uint32_t index;
349 	struct protocol_compat_v2 *compat_v2 = client->compat_v2;
350 
351 	if ((t = pw_map_lookup(&compat_v2->types, type)) == NULL)
352 		return NULL;
353 
354 	index = PW_MAP_PTR_TO_ID(t);
355 	if (index >= SPA_N_ELEMENTS(type_map))
356 		return NULL;
357 
358 	return type_map[index].name;
359 }
360 
361 SPA_EXPORT
pw_protocol_native0_name_to_v2(struct pw_impl_client * client,const char * name)362 uint32_t pw_protocol_native0_name_to_v2(struct pw_impl_client *client, const char *name)
363 {
364 	uint32_t i;
365 	/* match name to type table and return index */
366 	for (i = 0; i < SPA_N_ELEMENTS(type_map); i++) {
367 		if (type_map[i].name != NULL && spa_streq(type_map[i].name, name))
368 			return i;
369 	}
370 	return SPA_ID_INVALID;
371 }
372 
373 SPA_EXPORT
pw_protocol_native0_type_to_v2(struct pw_impl_client * client,const struct spa_type_info * info,uint32_t type)374 uint32_t pw_protocol_native0_type_to_v2(struct pw_impl_client *client,
375 		const struct spa_type_info *info, uint32_t type)
376 {
377 	const char *name;
378 
379 	/** find full name of type in type_info */
380 	if ((name = spa_debug_type_find_name(info, type)) == NULL)
381 		return SPA_ID_INVALID;
382 
383 	return pw_protocol_native0_name_to_v2(client, name);
384 }
385 
386 struct spa_pod_prop_body0 {
387         uint32_t key;
388 #define SPA_POD_PROP0_RANGE_NONE         0       /**< no range */
389 #define SPA_POD_PROP0_RANGE_MIN_MAX      1       /**< property has range */
390 #define SPA_POD_PROP0_RANGE_STEP         2       /**< property has range with step */
391 #define SPA_POD_PROP0_RANGE_ENUM         3       /**< property has enumeration */
392 #define SPA_POD_PROP0_RANGE_FLAGS        4       /**< property has flags */
393 #define SPA_POD_PROP0_RANGE_MASK         0xf     /**< mask to select range type */
394 #define SPA_POD_PROP0_FLAG_UNSET         (1 << 4)        /**< property value is unset */
395 #define SPA_POD_PROP0_FLAG_OPTIONAL      (1 << 5)        /**< property value is optional */
396 #define SPA_POD_PROP0_FLAG_READONLY      (1 << 6)        /**< property is readonly */
397 #define SPA_POD_PROP0_FLAG_DEPRECATED    (1 << 7)        /**< property is deprecated */
398 #define SPA_POD_PROP0_FLAG_INFO          (1 << 8)        /**< property is informational and is not
399                                                           *  used when filtering */
400         uint32_t flags;
401         struct spa_pod value;
402         /* array with elements of value.size follows,
403          * first element is value/default, rest are alternatives */
404 };
405 
406 /* v2 iterates object as containing spa_pod */
407 #define SPA_POD_OBJECT_BODY_FOREACH0(body, size, iter)                                           \
408         for ((iter) = SPA_PTROFF((body), sizeof(struct spa_pod_object_body), struct spa_pod);   \
409              spa_pod_is_inside(body, size, iter);                                               \
410              (iter) = spa_pod_next(iter))
411 
412 #define SPA_POD_PROP_ALTERNATIVE_FOREACH0(body, _size, iter)                                     \
413         for ((iter) = SPA_PTROFF((body), (body)->value.size +                                   \
414                                 sizeof(struct spa_pod_prop_body0), __typeof__(*iter));           \
415              (iter) <= SPA_PTROFF((body), (_size)-(body)->value.size, __typeof__(*iter));       \
416              (iter) = SPA_PTROFF((iter), (body)->value.size, __typeof__(*iter)))
417 
418 #define SPA0_POD_PROP_N_VALUES(b,size)     ((size - sizeof(struct spa_pod_prop_body0)) / (b)->value.size)
419 
remap_from_v2(uint32_t type,void * body,uint32_t size,struct pw_impl_client * client,struct spa_pod_builder * builder)420 static int remap_from_v2(uint32_t type, void *body, uint32_t size, struct pw_impl_client *client,
421 		struct spa_pod_builder *builder)
422 {
423 	int res;
424 
425 	switch (type) {
426 	case SPA_TYPE_Id:
427 		spa_pod_builder_id(builder, pw_protocol_native0_type_from_v2(client, *(int32_t*) body));
428 		break;
429 
430 	/** choice was props in v2 */
431 	case SPA_TYPE_Choice:
432 	{
433 		struct spa_pod_prop_body0 *b = body;
434 		struct spa_pod_frame f;
435 		void *alt;
436 		uint32_t key = pw_protocol_native0_type_from_v2(client, b->key);
437 		enum spa_choice_type type;
438 
439 		spa_pod_builder_prop(builder, key, 0);
440 
441 		switch (b->flags & SPA_POD_PROP0_RANGE_MASK) {
442 		default:
443 		case SPA_POD_PROP0_RANGE_NONE:
444 			type = SPA_CHOICE_None;
445 			break;
446 		case SPA_POD_PROP0_RANGE_MIN_MAX:
447 			type = SPA_CHOICE_Range;
448 			break;
449 		case SPA_POD_PROP0_RANGE_STEP:
450 			type = SPA_CHOICE_Step;
451 			break;
452 		case SPA_POD_PROP0_RANGE_ENUM:
453 			type = SPA_CHOICE_Enum;
454 			break;
455 		case SPA_POD_PROP0_RANGE_FLAGS:
456 			type = SPA_CHOICE_Flags;
457 			break;
458 		}
459 		if (!SPA_FLAG_IS_SET(b->flags, SPA_POD_PROP0_FLAG_UNSET) &&
460 		    SPA0_POD_PROP_N_VALUES(b, size) == 1)
461 			type = SPA_CHOICE_None;
462 
463 		spa_pod_builder_push_choice(builder, &f, type, 0);
464 
465 		if (b->value.type == SPA_TYPE_Id) {
466 			uint32_t id;
467 			if ((res = spa_pod_get_id(&b->value, &id)) < 0)
468 				return res;
469 			spa_pod_builder_id(builder, pw_protocol_native0_type_from_v2(client, id));
470 			SPA_POD_PROP_ALTERNATIVE_FOREACH0(b, size, alt)
471 				if ((res = remap_from_v2(b->value.type, alt, b->value.size, client, builder)) < 0)
472 					return res;
473 		} else {
474 			spa_pod_builder_raw(builder, &b->value, size - sizeof(struct spa_pod));
475 		}
476 
477 		spa_pod_builder_pop(builder, &f);
478 
479 		break;
480 	}
481 	case SPA_TYPE_Object:
482 	{
483 		struct spa_pod_object_body *b = body;
484 		struct spa_pod *p;
485 		struct spa_pod_frame f;
486 		uint32_t type, count = 0;
487 
488 		/* type and id are switched */
489 		type = pw_protocol_native0_type_from_v2(client, b->id),
490 		spa_pod_builder_push_object(builder, &f, type,
491 			pw_protocol_native0_type_from_v2(client, b->type));
492 
493 		/* object contained pods in v2 */
494 		SPA_POD_OBJECT_BODY_FOREACH0(b, size, p) {
495 			if (type == SPA_TYPE_OBJECT_Format && count < 2) {
496 				uint32_t id;
497 				if (spa_pod_get_id(p, &id) < 0)
498 					continue;
499 				id = pw_protocol_native0_type_from_v2(client, id);
500 
501 				if (count == 0) {
502 					spa_pod_builder_prop(builder, SPA_FORMAT_mediaType, 0);
503 					spa_pod_builder_id(builder, id);
504 				}
505 				if (count == 1) {
506 					spa_pod_builder_prop(builder, SPA_FORMAT_mediaSubtype, 0);
507 					spa_pod_builder_id(builder, id);
508 				}
509 				count++;
510 				continue;
511 			}
512 			if ((res = remap_from_v2(p->type,
513 						SPA_POD_BODY(p),
514 						p->size,
515 						client, builder)) < 0)
516 				return res;
517 		}
518 		spa_pod_builder_pop(builder, &f);
519 		break;
520 	}
521 	case SPA_TYPE_Struct:
522 	{
523 		struct spa_pod *b = body, *p;
524 		struct spa_pod_frame f;
525 
526 		spa_pod_builder_push_struct(builder, &f);
527 		SPA_POD_FOREACH(b, size, p)
528 			if ((res = remap_from_v2(p->type, SPA_POD_BODY(p), p->size, client, builder)) < 0)
529 				return res;
530 		spa_pod_builder_pop(builder, &f);
531 		break;
532 	}
533 	default:
534 		break;
535 	}
536 	return 0;
537 }
538 
remap_to_v2(struct pw_impl_client * client,const struct spa_type_info * info,uint32_t type,void * body,uint32_t size,struct spa_pod_builder * builder)539 static int remap_to_v2(struct pw_impl_client *client, const struct spa_type_info *info,
540 		uint32_t type, void *body, uint32_t size,
541 		struct spa_pod_builder *builder)
542 {
543 	int res;
544 
545 	switch (type) {
546 	case SPA_TYPE_Id:
547 		spa_pod_builder_id(builder, pw_protocol_native0_type_to_v2(client, info, *(int32_t*) body));
548 		break;
549 
550 	case SPA_TYPE_Object:
551 	{
552 		struct spa_pod_object_body *b = body;
553 		struct spa_pod_prop *p;
554 		struct spa_pod_frame f[2];
555 		uint32_t type;
556                 const struct spa_type_info *ti, *ii;
557 
558 		ti = spa_debug_type_find(info, b->type);
559 		ii = ti ? spa_debug_type_find(ti->values, 0) : NULL;
560 
561 		if (b->type == SPA_TYPE_COMMAND_Node ||
562 		    b->type == SPA_TYPE_EVENT_Node) {
563 			spa_pod_builder_push_object(builder, &f[0], 0,
564 				pw_protocol_native0_type_to_v2(client, ii ? ii->values : NULL, b->id));
565 		} else {
566 			ii = ii ? spa_debug_type_find(ii->values, b->id) : NULL;
567 			/* type and id are switched */
568 			type = pw_protocol_native0_type_to_v2(client, info, b->type),
569 			spa_pod_builder_push_object(builder, &f[0],
570 				pw_protocol_native0_type_to_v2(client, ii ? ii->values : NULL, b->id), type);
571 		}
572 
573 
574 		info = ti ? ti->values : info;
575 
576 		SPA_POD_OBJECT_BODY_FOREACH(b, size, p) {
577 			uint32_t key, flags;
578 			uint32_t n_vals, choice;
579 			struct spa_pod *values;
580 
581                         ii = spa_debug_type_find(info, p->key);
582 
583 			values = spa_pod_get_values(&p->value, &n_vals, &choice);
584 
585 			if (b->type == SPA_TYPE_OBJECT_Format &&
586 			    (p->key == SPA_FORMAT_mediaType ||
587 			     p->key == SPA_FORMAT_mediaSubtype)) {
588 				uint32_t val;
589 
590 				if (spa_pod_get_id(values, &val) < 0)
591 					continue;
592 				spa_pod_builder_id(builder,
593 						pw_protocol_native0_type_to_v2(client, ii ? ii->values : NULL, val));
594 				continue;
595 			}
596 
597 			flags = 0;
598 			switch(choice) {
599 			case SPA_CHOICE_None:
600 				flags |= SPA_POD_PROP0_RANGE_NONE;
601 				break;
602 			case SPA_CHOICE_Range:
603 				flags |= SPA_POD_PROP0_RANGE_MIN_MAX | SPA_POD_PROP0_FLAG_UNSET;
604 				break;
605 			case SPA_CHOICE_Step:
606 				flags |= SPA_POD_PROP0_RANGE_STEP | SPA_POD_PROP0_FLAG_UNSET;
607 				break;
608 			case SPA_CHOICE_Enum:
609 				flags |= SPA_POD_PROP0_RANGE_ENUM | SPA_POD_PROP0_FLAG_UNSET;
610 				break;
611 			case SPA_CHOICE_Flags:
612 				flags |= SPA_POD_PROP0_RANGE_FLAGS | SPA_POD_PROP0_FLAG_UNSET;
613 				break;
614 			}
615 
616 			key = pw_protocol_native0_type_to_v2(client, info, p->key);
617 
618 			spa_pod_builder_push_choice(builder, &f[1], key, flags);
619 
620 			if (values->type == SPA_TYPE_Id) {
621 				uint32_t i, *id = SPA_POD_BODY(values);
622 
623 				for (i = 0; i < n_vals; i++) {
624 					spa_pod_builder_id(builder,
625 						pw_protocol_native0_type_to_v2(client, ii ? ii->values : NULL, id[i]));
626 				}
627 
628 			} else {
629 				spa_pod_builder_raw(builder, values, sizeof(struct spa_pod) + n_vals * values->size);
630 			}
631 			spa_pod_builder_pop(builder, &f[1]);
632 		}
633 		spa_pod_builder_pop(builder, &f[0]);
634 		break;
635 	}
636 	case SPA_TYPE_Struct:
637 	{
638 		struct spa_pod *b = body, *p;
639 		struct spa_pod_frame f;
640 
641 		spa_pod_builder_push_struct(builder, &f);
642 		SPA_POD_FOREACH(b, size, p)
643 			if ((res = remap_to_v2(client, info, p->type, SPA_POD_BODY(p), p->size, builder)) < 0)
644 				return res;
645 		spa_pod_builder_pop(builder, &f);
646 		break;
647 	}
648 	default:
649 		break;
650 	}
651 	return 0;
652 }
653 
654 
655 
656 
657 SPA_EXPORT
pw_protocol_native0_pod_from_v2(struct pw_impl_client * client,const struct spa_pod * pod)658 struct spa_pod * pw_protocol_native0_pod_from_v2(struct pw_impl_client *client, const struct spa_pod *pod)
659 {
660 	uint8_t buffer[4096];
661 	struct spa_pod *copy;
662 	struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, 4096);
663 	int res;
664 
665 	if (pod == NULL)
666 		return NULL;
667 
668 	if ((res = remap_from_v2(SPA_POD_TYPE(pod),
669 					SPA_POD_BODY(pod),
670 					SPA_POD_BODY_SIZE(pod),
671 					client, &b)) < 0) {
672 		errno = -res;
673 		return NULL;
674 	}
675 	copy = spa_pod_copy(b.data);
676 	return copy;
677 }
678 
679 SPA_EXPORT
pw_protocol_native0_pod_to_v2(struct pw_impl_client * client,const struct spa_pod * pod,struct spa_pod_builder * b)680 int pw_protocol_native0_pod_to_v2(struct pw_impl_client *client, const struct spa_pod *pod,
681 		struct spa_pod_builder *b)
682 {
683 	int res;
684 
685 	if (pod == NULL) {
686 		spa_pod_builder_none(b);
687 		return 0;
688 	}
689 
690 	if ((res = remap_to_v2(client, pw_type_info(),
691 				SPA_POD_TYPE(pod),
692 				SPA_POD_BODY(pod),
693 				SPA_POD_BODY_SIZE(pod),
694 				b)) < 0) {
695 		return -res;
696 	}
697 	return 0;
698 }
699 
core_demarshal_create_object(void * object,const struct pw_protocol_native_message * msg)700 static int core_demarshal_create_object(void *object, const struct pw_protocol_native_message *msg)
701 {
702 	struct pw_resource *resource = object;
703 	struct pw_impl_client *client = pw_resource_get_client(resource);
704 	struct spa_pod_parser prs;
705 	struct spa_pod_frame f;
706 	uint32_t version, type, new_id, i;
707 	const char *factory_name, *type_name;
708 	struct spa_dict props;
709 
710 	spa_pod_parser_init(&prs, msg->data, msg->size);
711 	if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
712 	    spa_pod_parser_get(&prs,
713 			"s", &factory_name,
714 			"I", &type,
715 			"i", &version,
716 			"i", &props.n_items, NULL) < 0)
717 		return -EINVAL;
718 
719 	props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
720 	for (i = 0; i < props.n_items; i++) {
721 		if (spa_pod_parser_get(&prs,
722 					"s", &props.items[i].key,
723 					"s", &props.items[i].value, NULL) < 0)
724 			return -EINVAL;
725 	}
726 	if (spa_pod_parser_get(&prs, "i", &new_id, NULL) < 0)
727 		return -EINVAL;
728 
729 	type_name = pw_protocol_native0_name_from_v2(client, type);
730 	if (type_name == NULL)
731 		return -EINVAL;
732 
733 	return pw_resource_notify(resource, struct pw_core_methods, create_object, 0, factory_name,
734                                                                       type_name, version,
735                                                                       &props, new_id);
736 }
737 
core_demarshal_destroy(void * object,const struct pw_protocol_native_message * msg)738 static int core_demarshal_destroy(void *object, const struct pw_protocol_native_message *msg)
739 {
740 	struct pw_resource *resource = object, *r;
741 	struct pw_impl_client *client = pw_resource_get_client(resource);
742 	struct spa_pod_parser prs;
743 	uint32_t id;
744 
745 	spa_pod_parser_init(&prs, msg->data, msg->size);
746 	if (spa_pod_parser_get_struct(&prs,
747 				"i", &id, NULL) < 0)
748 		return -EINVAL;
749 
750 	pw_log_debug("client %p: destroy resource %u", client, id);
751 
752 	if ((r = pw_impl_client_find_resource(client, id)) == NULL)
753 		goto no_resource;
754 
755 	return pw_resource_notify(resource, struct pw_core_methods, destroy, 0, r);
756 
757 no_resource:
758 	pw_log_error("client %p: unknown resource %u op:%u", client, id, msg->opcode);
759 	pw_resource_errorf(resource, -ENOENT, "unknown resource %d op:%u", id, msg->opcode);
760 	return 0;
761 }
762 
core_demarshal_update_types_server(void * object,const struct pw_protocol_native_message * msg)763 static int core_demarshal_update_types_server(void *object, const struct pw_protocol_native_message *msg)
764 {
765 	struct pw_resource *resource = object;
766 	struct pw_impl_client *client = pw_resource_get_client(resource);
767 	struct protocol_compat_v2 *compat_v2 = client->compat_v2;
768 	struct spa_pod_parser prs;
769 	uint32_t first_id, n_types;
770 	struct spa_pod_frame f;
771 	const char **types;
772 	uint32_t i;
773 
774 	spa_pod_parser_init(&prs, msg->data, msg->size);
775 	if (spa_pod_parser_push_struct(&prs, &f) < 0 ||
776 	    spa_pod_parser_get(&prs,
777 			"i", &first_id,
778 			"i", &n_types,
779 			NULL) < 0)
780 		return -EINVAL;
781 
782 	if (first_id == 0)
783 		compat_v2->send_types = true;
784 
785 	types = alloca(n_types * sizeof(char *));
786 	for (i = 0; i < n_types; i++) {
787 		if (spa_pod_parser_get(&prs, "s", &types[i], NULL) < 0)
788 			return -EINVAL;
789 	}
790 
791 	for (i = 0; i < n_types; i++, first_id++) {
792 		uint32_t type_id = pw_protocol_native0_find_type(client, types[i]);
793 		if (type_id == SPA_ID_INVALID)
794 			continue;
795 		if (pw_map_insert_at(&compat_v2->types, first_id, PW_MAP_ID_TO_PTR(type_id)) < 0)
796 			pw_log_error("can't add type %d->%d for client", first_id, type_id);
797         }
798 	return 0;
799 }
800 
registry_marshal_global(void * object,uint32_t id,uint32_t permissions,const char * type,uint32_t version,const struct spa_dict * props)801 static void registry_marshal_global(void *object, uint32_t id, uint32_t permissions,
802 				    const char *type, uint32_t version, const struct spa_dict *props)
803 {
804 	struct pw_resource *resource = object;
805 	struct pw_impl_client *client = pw_resource_get_client(resource);
806 	struct spa_pod_builder *b;
807 	struct spa_pod_frame f;
808 	uint32_t i, n_items, parent_id;
809 	uint32_t type_id;
810 	const char *str;
811 
812 	type_id = pw_protocol_native0_find_type(client, type);
813 	if (type_id == SPA_ID_INVALID)
814 		return;
815 
816 	b = pw_protocol_native_begin_resource(resource, PW_REGISTRY_V0_EVENT_GLOBAL, NULL);
817 
818 	n_items = props ? props->n_items : 0;
819 
820 	parent_id = 0;
821 	if (props) {
822 		if (spa_streq(type, PW_TYPE_INTERFACE_Port)) {
823 			if ((str = spa_dict_lookup(props, "node.id")) != NULL)
824 				parent_id = atoi(str);
825 		} else if (spa_streq(type, PW_TYPE_INTERFACE_Node)) {
826 			if ((str = spa_dict_lookup(props, "device.id")) != NULL)
827 				parent_id = atoi(str);
828 		} else if (spa_streq(type, PW_TYPE_INTERFACE_Client) ||
829 		    spa_streq(type, PW_TYPE_INTERFACE_Device) ||
830 		    spa_streq(type, PW_TYPE_INTERFACE_Factory)) {
831 			if ((str = spa_dict_lookup(props, "module.id")) != NULL)
832 				parent_id = atoi(str);
833 		}
834 	}
835 
836 	version = 0;
837 
838         spa_pod_builder_push_struct(b, &f);
839 	spa_pod_builder_add(b,
840 			    "i", id,
841 			    "i", parent_id,
842 			    "i", permissions,
843 			    "I", type_id,
844 			    "i", version,
845 			    "i", n_items, NULL);
846 
847 	for (i = 0; i < n_items; i++) {
848 		spa_pod_builder_add(b,
849 				    "s", props->items[i].key,
850 				    "s", props->items[i].value, NULL);
851 	}
852         spa_pod_builder_pop(b, &f);
853 
854 	pw_protocol_native_end_resource(resource, b);
855 }
856 
registry_marshal_global_remove(void * object,uint32_t id)857 static void registry_marshal_global_remove(void *object, uint32_t id)
858 {
859 	struct pw_resource *resource = object;
860 	struct spa_pod_builder *b;
861 
862 	b = pw_protocol_native_begin_resource(resource, PW_REGISTRY_V0_EVENT_GLOBAL_REMOVE, NULL);
863 
864 	spa_pod_builder_add_struct(b, "i", id);
865 
866 	pw_protocol_native_end_resource(resource, b);
867 }
868 
registry_demarshal_bind(void * object,const struct pw_protocol_native_message * msg)869 static int registry_demarshal_bind(void *object, const struct pw_protocol_native_message *msg)
870 {
871 	struct pw_resource *resource = object;
872 	struct pw_impl_client *client = pw_resource_get_client(resource);
873 	struct spa_pod_parser prs;
874 	uint32_t id, version, type, new_id;
875 	const char *type_name;
876 
877 	spa_pod_parser_init(&prs, msg->data, msg->size);
878 	if (spa_pod_parser_get_struct(&prs,
879 			"i", &id,
880 			"I", &type,
881 			"i", &version,
882 			"i", &new_id) < 0)
883 		return -EINVAL;
884 
885 	type_name = pw_protocol_native0_name_from_v2(client, type);
886 	if (type_name == NULL)
887 		return -EINVAL;
888 
889 	return pw_resource_notify(resource, struct pw_registry_methods, bind, 0, id, type_name, version, new_id);
890 }
891 
module_marshal_info(void * object,const struct pw_module_info * info)892 static void module_marshal_info(void *object, const struct pw_module_info *info)
893 {
894 	struct pw_resource *resource = object;
895 	struct spa_pod_builder *b;
896 	struct spa_pod_frame f;
897 	uint32_t i, n_items;
898 
899 	b = pw_protocol_native_begin_resource(resource, PW_MODULE_V0_EVENT_INFO, NULL);
900 
901 	n_items = info->props ? info->props->n_items : 0;
902 
903         spa_pod_builder_push_struct(b, &f);
904 	spa_pod_builder_add(b,
905 			    "i", info->id,
906 			    "l", info->change_mask,
907 			    "s", info->name,
908 			    "s", info->filename,
909 			    "s", info->args,
910 			    "i", n_items, NULL);
911 
912 	for (i = 0; i < n_items; i++) {
913 		spa_pod_builder_add(b,
914 				    "s", info->props->items[i].key,
915 				    "s", info->props->items[i].value, NULL);
916 	}
917         spa_pod_builder_pop(b, &f);
918 
919 	pw_protocol_native_end_resource(resource, b);
920 }
921 
factory_marshal_info(void * object,const struct pw_factory_info * info)922 static void factory_marshal_info(void *object, const struct pw_factory_info *info)
923 {
924 	struct pw_resource *resource = object;
925 	struct pw_impl_client *client = pw_resource_get_client(resource);
926 	struct spa_pod_builder *b;
927 	struct spa_pod_frame f;
928 	uint32_t i, n_items, type, version;
929 
930 	type = pw_protocol_native0_find_type(client, info->type);
931 	if (type == SPA_ID_INVALID)
932 		return;
933 
934 	b = pw_protocol_native_begin_resource(resource, PW_FACTORY_V0_EVENT_INFO, NULL);
935 
936 	n_items = info->props ? info->props->n_items : 0;
937 
938 	version = 0;
939 
940         spa_pod_builder_push_struct(b, &f);
941 	spa_pod_builder_add(b,
942 			    "i", info->id,
943 			    "l", info->change_mask,
944 			    "s", info->name,
945 			    "I", type,
946 			    "i", version,
947 			    "i", n_items, NULL);
948 
949 	for (i = 0; i < n_items; i++) {
950 		spa_pod_builder_add(b,
951 				    "s", info->props->items[i].key,
952 				    "s", info->props->items[i].value, NULL);
953 	}
954         spa_pod_builder_pop(b, &f);
955 
956 	pw_protocol_native_end_resource(resource, b);
957 }
958 
node_marshal_info(void * object,const struct pw_node_info * info)959 static void node_marshal_info(void *object, const struct pw_node_info *info)
960 {
961 	struct pw_resource *resource = object;
962 	struct spa_pod_builder *b;
963 	struct spa_pod_frame f;
964 	uint32_t i, n_items;
965 
966 	b = pw_protocol_native_begin_resource(resource, PW_NODE_V0_EVENT_INFO, NULL);
967 
968 	n_items = info->props ? info->props->n_items : 0;
969 
970         spa_pod_builder_push_struct(b, &f);
971 	spa_pod_builder_add(b,
972 			    "i", info->id,
973 			    "l", info->change_mask,
974 			    "s", "node.name",
975 			    "i", info->max_input_ports,
976 			    "i", info->n_input_ports,
977 			    "i", info->max_output_ports,
978 			    "i", info->n_output_ports,
979 			    "i", info->state,
980 			    "s", info->error,
981 			    "i", n_items, NULL);
982 
983 	for (i = 0; i < n_items; i++) {
984 		spa_pod_builder_add(b,
985 				    "s", info->props->items[i].key,
986 				    "s", info->props->items[i].value, NULL);
987 	}
988         spa_pod_builder_pop(b, &f);
989 
990 	pw_protocol_native_end_resource(resource, b);
991 }
992 
node_marshal_param(void * object,int seq,uint32_t id,uint32_t index,uint32_t next,const struct spa_pod * param)993 static void node_marshal_param(void *object, int seq, uint32_t id, uint32_t index, uint32_t next,
994 		const struct spa_pod *param)
995 {
996 	struct pw_resource *resource = object;
997 	struct pw_impl_client *client = pw_resource_get_client(resource);
998 	struct spa_pod_builder *b;
999 	struct spa_pod_frame f;
1000 
1001 	b = pw_protocol_native_begin_resource(resource, PW_NODE_V0_EVENT_PARAM, NULL);
1002 
1003 	id = pw_protocol_native0_type_to_v2(client, spa_type_param, id),
1004 
1005 	spa_pod_builder_push_struct(b, &f);
1006 	spa_pod_builder_add(b,
1007 			"I", id,
1008 			"i", index,
1009 			"i", next,
1010 			NULL);
1011 	pw_protocol_native0_pod_to_v2(client, (struct spa_pod *)param, b);
1012 	spa_pod_builder_pop(b, &f);
1013 
1014 	pw_protocol_native_end_resource(resource, b);
1015 }
1016 
node_demarshal_enum_params(void * object,const struct pw_protocol_native_message * msg)1017 static int node_demarshal_enum_params(void *object, const struct pw_protocol_native_message *msg)
1018 {
1019 	struct pw_resource *resource = object;
1020 	struct pw_impl_client *client = pw_resource_get_client(resource);
1021 	struct spa_pod_parser prs;
1022 	uint32_t id, index, num;
1023 	struct spa_pod *filter;
1024 
1025 	spa_pod_parser_init(&prs, msg->data, msg->size);
1026 	if (spa_pod_parser_get_struct(&prs,
1027 				"I", &id,
1028 				"i", &index,
1029 				"i", &num,
1030 				"P", &filter) < 0)
1031 		return -EINVAL;
1032 
1033 	id = pw_protocol_native0_type_from_v2(client, id);
1034 	filter = NULL;
1035 
1036         return pw_resource_notify(resource, struct pw_node_methods, enum_params, 0,
1037                         0, id, index, num, filter);
1038 }
1039 
port_marshal_info(void * object,const struct pw_port_info * info)1040 static void port_marshal_info(void *object, const struct pw_port_info *info)
1041 {
1042 	struct pw_resource *resource = object;
1043 	struct spa_pod_builder *b;
1044 	struct spa_pod_frame f;
1045 	uint32_t i, n_items;
1046 	uint64_t change_mask = 0;
1047 	const char *port_name;
1048 
1049 	b = pw_protocol_native_begin_resource(resource, PW_PORT_V0_EVENT_INFO, NULL);
1050 
1051 	n_items = info->props ? info->props->n_items : 0;
1052 
1053 #define PW_PORT_V0_CHANGE_MASK_NAME                (1 << 0)
1054 #define PW_PORT_V0_CHANGE_MASK_PROPS               (1 << 1)
1055 #define PW_PORT_V0_CHANGE_MASK_ENUM_PARAMS         (1 << 2)
1056 
1057 	change_mask |= PW_PORT_V0_CHANGE_MASK_NAME;
1058 	if (info->change_mask & PW_PORT_CHANGE_MASK_PROPS)
1059 		change_mask |= PW_PORT_V0_CHANGE_MASK_PROPS;
1060 	if (info->change_mask & PW_PORT_CHANGE_MASK_PARAMS)
1061 		change_mask |= PW_PORT_V0_CHANGE_MASK_ENUM_PARAMS;
1062 
1063 	port_name = NULL;
1064 	if (info->props != NULL)
1065 		port_name = spa_dict_lookup(info->props, "port.name");
1066 	if (port_name == NULL)
1067 		port_name = "port.name";
1068 
1069         spa_pod_builder_push_struct(b, &f);
1070 	spa_pod_builder_add(b,
1071 			    "i", info->id,
1072 			    "l", change_mask,
1073 			    "s", port_name,
1074 			    "i", n_items, NULL);
1075 
1076 	for (i = 0; i < n_items; i++) {
1077 		spa_pod_builder_add(b,
1078 				    "s", info->props->items[i].key,
1079 				    "s", info->props->items[i].value, NULL);
1080 	}
1081         spa_pod_builder_pop(b, &f);
1082 
1083 	pw_protocol_native_end_resource(resource, b);
1084 }
1085 
port_marshal_param(void * object,int seq,uint32_t id,uint32_t index,uint32_t next,const struct spa_pod * param)1086 static void port_marshal_param(void *object, int seq, uint32_t id, uint32_t index, uint32_t next,
1087 		const struct spa_pod *param)
1088 {
1089 	struct pw_resource *resource = object;
1090 	struct pw_impl_client *client = pw_resource_get_client(resource);
1091 	struct spa_pod_builder *b;
1092 	struct spa_pod_frame f;
1093 
1094 	b = pw_protocol_native_begin_resource(resource, PW_PORT_V0_EVENT_PARAM, NULL);
1095 
1096 	id = pw_protocol_native0_type_to_v2(client, spa_type_param, id),
1097 
1098 	spa_pod_builder_push_struct(b, &f);
1099 	spa_pod_builder_add(b,
1100 			"I", id,
1101 			"i", index,
1102 			"i", next,
1103 			NULL);
1104 	pw_protocol_native0_pod_to_v2(client, (struct spa_pod *)param, b);
1105 	spa_pod_builder_pop(b, &f);
1106 
1107 	pw_protocol_native_end_resource(resource, b);
1108 }
1109 
port_demarshal_enum_params(void * object,const struct pw_protocol_native_message * msg)1110 static int port_demarshal_enum_params(void *object, const struct pw_protocol_native_message *msg)
1111 {
1112 	struct pw_resource *resource = object;
1113 	struct pw_impl_client *client = pw_resource_get_client(resource);
1114 	struct spa_pod_parser prs;
1115 	uint32_t id, index, num;
1116 	struct spa_pod *filter;
1117 
1118 	spa_pod_parser_init(&prs, msg->data, msg->size);
1119 	if (spa_pod_parser_get_struct(&prs,
1120 				"I", &id,
1121 				"i", &index,
1122 				"i", &num,
1123 				"P", &filter) < 0)
1124 		return -EINVAL;
1125 
1126 	id = pw_protocol_native0_type_from_v2(client, id);
1127 	filter = NULL;
1128 
1129         return pw_resource_notify(resource, struct pw_port_methods, enum_params, 0,
1130                         0, id, index, num, filter);
1131 }
1132 
client_marshal_info(void * object,const struct pw_client_info * info)1133 static void client_marshal_info(void *object, const struct pw_client_info *info)
1134 {
1135 	struct pw_resource *resource = object;
1136 	struct spa_pod_builder *b;
1137 	struct spa_pod_frame f;
1138 	uint32_t i, n_items;
1139 
1140 	b = pw_protocol_native_begin_resource(resource, PW_CLIENT_V0_EVENT_INFO, NULL);
1141 
1142 	n_items = info->props ? info->props->n_items : 0;
1143 
1144         spa_pod_builder_push_struct(b, &f);
1145 	spa_pod_builder_add(b,
1146 			    "i", info->id,
1147 			    "l", info->change_mask,
1148 			    "i", n_items, NULL);
1149 
1150 	for (i = 0; i < n_items; i++) {
1151 		spa_pod_builder_add(b,
1152 				    "s", info->props->items[i].key,
1153 				    "s", info->props->items[i].value, NULL);
1154 	}
1155         spa_pod_builder_pop(b, &f);
1156 
1157 	pw_protocol_native_end_resource(resource, b);
1158 }
1159 
client_marshal_permissions(void * object,uint32_t index,uint32_t n_permissions,const struct pw_permission * permissions)1160 static void client_marshal_permissions(void *object, uint32_t index, uint32_t n_permissions,
1161                 const struct pw_permission *permissions)
1162 {
1163 }
1164 
1165 
link_marshal_info(void * object,const struct pw_link_info * info)1166 static void link_marshal_info(void *object, const struct pw_link_info *info)
1167 {
1168 	struct pw_resource *resource = object;
1169 	struct spa_pod_builder *b;
1170 	struct spa_pod_frame f;
1171 	uint32_t i, n_items;
1172 
1173 	b = pw_protocol_native_begin_resource(resource, PW_LINK_V0_EVENT_INFO, NULL);
1174 
1175 	n_items = info->props ? info->props->n_items : 0;
1176 
1177         spa_pod_builder_push_struct(b, &f);
1178 	spa_pod_builder_add(b,
1179 			    "i", info->id,
1180 			    "l", info->change_mask,
1181 			    "i", info->output_node_id,
1182 			    "i", info->output_port_id,
1183 			    "i", info->input_node_id,
1184 			    "i", info->input_port_id,
1185 			    "P", info->format,
1186 			    "i", n_items, NULL);
1187 
1188 	for (i = 0; i < n_items; i++) {
1189 		spa_pod_builder_add(b,
1190 				    "s", info->props->items[i].key,
1191 				    "s", info->props->items[i].value, NULL);
1192 	}
1193         spa_pod_builder_pop(b, &f);
1194 
1195 	pw_protocol_native_end_resource(resource, b);
1196 }
1197 
1198 static const struct pw_protocol_native_demarshal pw_protocol_native_core_method_demarshal[PW_CORE_V0_METHOD_NUM] = {
1199 	[PW_CORE_V0_METHOD_HELLO] = { &core_demarshal_hello, 0, },
1200 	[PW_CORE_V0_METHOD_UPDATE_TYPES] = { &core_demarshal_update_types_server, 0, },
1201 	[PW_CORE_V0_METHOD_SYNC] = { &core_demarshal_sync, 0, },
1202 	[PW_CORE_V0_METHOD_GET_REGISTRY] = { &core_demarshal_get_registry, 0, },
1203 	[PW_CORE_V0_METHOD_CLIENT_UPDATE] = { &core_demarshal_client_update, 0, },
1204 	[PW_CORE_V0_METHOD_PERMISSIONS] = { &core_demarshal_permissions, 0, },
1205 	[PW_CORE_V0_METHOD_CREATE_OBJECT] = { &core_demarshal_create_object, 0, PW_PROTOCOL_NATIVE_FLAG_REMAP, },
1206 	[PW_CORE_V0_METHOD_DESTROY] = { &core_demarshal_destroy, 0, }
1207 };
1208 
1209 static const struct pw_core_events pw_protocol_native_core_event_marshal = {
1210 	PW_VERSION_CORE_EVENTS,
1211 	.info = &core_marshal_info,
1212 	.done = &core_marshal_done,
1213 	.error = &core_marshal_error,
1214 	.remove_id = &core_marshal_remove_id,
1215 };
1216 
1217 static const struct pw_protocol_marshal pw_protocol_native_core_marshal = {
1218 	PW_TYPE_INTERFACE_Core,
1219 	PW_VERSION_CORE_V0,
1220 	PW_CORE_V0_METHOD_NUM,
1221 	PW_CORE_EVENT_NUM,
1222 	0,
1223 	NULL,
1224 	pw_protocol_native_core_method_demarshal,
1225 	&pw_protocol_native_core_event_marshal,
1226 	NULL
1227 };
1228 
1229 static const struct pw_protocol_native_demarshal pw_protocol_native_registry_method_demarshal[] = {
1230 	[PW_REGISTRY_V0_METHOD_BIND] = { &registry_demarshal_bind, 0, PW_PROTOCOL_NATIVE_FLAG_REMAP, },
1231 };
1232 
1233 static const struct pw_registry_events pw_protocol_native_registry_event_marshal = {
1234 	PW_VERSION_REGISTRY_EVENTS,
1235 	.global = &registry_marshal_global,
1236 	.global_remove = &registry_marshal_global_remove,
1237 };
1238 
1239 static const struct pw_protocol_marshal pw_protocol_native_registry_marshal = {
1240 	PW_TYPE_INTERFACE_Registry,
1241 	PW_VERSION_REGISTRY_V0,
1242 	PW_REGISTRY_V0_METHOD_NUM,
1243 	PW_REGISTRY_EVENT_NUM,
1244 	0,
1245 	NULL,
1246 	pw_protocol_native_registry_method_demarshal,
1247 	&pw_protocol_native_registry_event_marshal,
1248 	NULL
1249 };
1250 
1251 static const struct pw_module_events pw_protocol_native_module_event_marshal = {
1252 	PW_VERSION_MODULE_EVENTS,
1253 	.info = &module_marshal_info,
1254 };
1255 
1256 static const struct pw_protocol_marshal pw_protocol_native_module_marshal = {
1257 	PW_TYPE_INTERFACE_Module,
1258 	PW_VERSION_MODULE_V0,
1259 	0,
1260 	PW_MODULE_EVENT_NUM,
1261 	0,
1262 	NULL, NULL,
1263 	&pw_protocol_native_module_event_marshal,
1264 	NULL
1265 };
1266 
1267 static const struct pw_factory_events pw_protocol_native_factory_event_marshal = {
1268 	PW_VERSION_FACTORY_EVENTS,
1269 	.info = &factory_marshal_info,
1270 };
1271 
1272 static const struct pw_protocol_marshal pw_protocol_native_factory_marshal = {
1273 	PW_TYPE_INTERFACE_Factory,
1274 	PW_VERSION_FACTORY_V0,
1275 	0,
1276 	PW_FACTORY_EVENT_NUM,
1277 	0,
1278 	NULL, NULL,
1279 	&pw_protocol_native_factory_event_marshal,
1280 	NULL,
1281 };
1282 
1283 static const struct pw_protocol_native_demarshal pw_protocol_native_node_method_demarshal[] = {
1284 	[PW_NODE_V0_METHOD_ENUM_PARAMS] = { &node_demarshal_enum_params, 0, PW_PROTOCOL_NATIVE_FLAG_REMAP, },
1285 };
1286 
1287 static const struct pw_node_events pw_protocol_native_node_event_marshal = {
1288 	PW_VERSION_NODE_EVENTS,
1289 	.info = &node_marshal_info,
1290 	.param = &node_marshal_param,
1291 };
1292 
1293 static const struct pw_protocol_marshal pw_protocol_native_node_marshal = {
1294 	PW_TYPE_INTERFACE_Node,
1295 	PW_VERSION_NODE_V0,
1296 	PW_NODE_V0_METHOD_NUM,
1297 	PW_NODE_EVENT_NUM,
1298 	0,
1299 	NULL,
1300 	pw_protocol_native_node_method_demarshal,
1301 	&pw_protocol_native_node_event_marshal,
1302 	NULL
1303 };
1304 
1305 
1306 static const struct pw_protocol_native_demarshal pw_protocol_native_port_method_demarshal[] = {
1307 	[PW_PORT_V0_METHOD_ENUM_PARAMS] = { &port_demarshal_enum_params, 0, PW_PROTOCOL_NATIVE_FLAG_REMAP, },
1308 };
1309 
1310 static const struct pw_port_events pw_protocol_native_port_event_marshal = {
1311 	PW_VERSION_PORT_EVENTS,
1312 	.info = &port_marshal_info,
1313 	.param = &port_marshal_param,
1314 };
1315 
1316 static const struct pw_protocol_marshal pw_protocol_native_port_marshal = {
1317 	PW_TYPE_INTERFACE_Port,
1318 	PW_VERSION_PORT_V0,
1319 	PW_PORT_V0_METHOD_NUM,
1320 	PW_PORT_EVENT_NUM,
1321 	0,
1322 	NULL,
1323 	pw_protocol_native_port_method_demarshal,
1324 	&pw_protocol_native_port_event_marshal,
1325 	NULL
1326 };
1327 
1328 static const struct pw_client_events pw_protocol_native_client_event_marshal = {
1329 	PW_VERSION_CLIENT_EVENTS,
1330 	.info = &client_marshal_info,
1331 	.permissions = &client_marshal_permissions,
1332 };
1333 
1334 static const struct pw_protocol_marshal pw_protocol_native_client_marshal = {
1335 	PW_TYPE_INTERFACE_Client,
1336 	PW_VERSION_CLIENT_V0,
1337 	0,
1338 	PW_CLIENT_EVENT_NUM,
1339 	0,
1340 	NULL, NULL,
1341 	&pw_protocol_native_client_event_marshal,
1342 	NULL,
1343 };
1344 
1345 static const struct pw_link_events pw_protocol_native_link_event_marshal = {
1346 	PW_VERSION_LINK_EVENTS,
1347 	.info = &link_marshal_info,
1348 };
1349 
1350 static const struct pw_protocol_marshal pw_protocol_native_link_marshal = {
1351 	PW_TYPE_INTERFACE_Link,
1352 	PW_VERSION_LINK_V0,
1353 	0,
1354 	PW_LINK_EVENT_NUM,
1355 	0,
1356 	NULL, NULL,
1357 	&pw_protocol_native_link_event_marshal,
1358 	NULL
1359 };
1360 
pw_protocol_native0_init(struct pw_protocol * protocol)1361 void pw_protocol_native0_init(struct pw_protocol *protocol)
1362 {
1363 	pw_protocol_add_marshal(protocol, &pw_protocol_native_core_marshal);
1364 	pw_protocol_add_marshal(protocol, &pw_protocol_native_registry_marshal);
1365 	pw_protocol_add_marshal(protocol, &pw_protocol_native_module_marshal);
1366 	pw_protocol_add_marshal(protocol, &pw_protocol_native_node_marshal);
1367 	pw_protocol_add_marshal(protocol, &pw_protocol_native_port_marshal);
1368 	pw_protocol_add_marshal(protocol, &pw_protocol_native_factory_marshal);
1369 	pw_protocol_add_marshal(protocol, &pw_protocol_native_client_marshal);
1370 	pw_protocol_add_marshal(protocol, &pw_protocol_native_link_marshal);
1371 }
1372