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] = { ®istry_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 = ®istry_marshal_global,
1236 .global_remove = ®istry_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