1 /* PipeWire
2  *
3  * Copyright © 2020 Wim Taymans
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 <arpa/inet.h>
26 #include <math.h>
27 
28 #include <spa/debug/buffer.h>
29 #include <spa/utils/defs.h>
30 #include <spa/utils/string.h>
31 #include <pipewire/keys.h>
32 #include <pipewire/log.h>
33 
34 #include "defs.h"
35 #include "format.h"
36 #include "internal.h"
37 #include "log.h"
38 #include "media-roles.h"
39 #include "message.h"
40 #include "volume.h"
41 
42 #define MAX_SIZE	(256*1024)
43 #define MAX_ALLOCATED	(16*1024 *1024)
44 
45 #define VOLUME_MUTED ((uint32_t) 0U)
46 #define VOLUME_NORM ((uint32_t) 0x10000U)
47 #define VOLUME_MAX ((uint32_t) UINT32_MAX/2)
48 
49 #define PA_CHANNELS_MAX	(32u)
50 
volume_from_linear(float vol)51 static inline uint32_t volume_from_linear(float vol)
52 {
53 	uint32_t v;
54 	if (vol <= 0.0f)
55 		v = VOLUME_MUTED;
56 	else
57 		v = SPA_CLAMP((uint64_t) lround(cbrt(vol) * VOLUME_NORM),
58 				VOLUME_MUTED, VOLUME_MAX);
59 	return v;
60 }
61 
volume_to_linear(uint32_t vol)62 static inline float volume_to_linear(uint32_t vol)
63 {
64 	float v = ((float)vol) / VOLUME_NORM;
65 	return v * v * v;
66 }
67 
68 static const struct str_map key_table[] = {
69 	{ PW_KEY_DEVICE_BUS_PATH, "device.bus_path" },
70 	{ PW_KEY_DEVICE_FORM_FACTOR, "device.form_factor" },
71 	{ PW_KEY_DEVICE_ICON_NAME, "device.icon_name" },
72 	{ PW_KEY_DEVICE_INTENDED_ROLES, "device.intended_roles" },
73 	{ PW_KEY_NODE_DESCRIPTION, "device.description" },
74 	{ PW_KEY_MEDIA_ICON_NAME, "media.icon_name" },
75 	{ PW_KEY_APP_ICON_NAME, "application.icon_name" },
76 	{ PW_KEY_APP_PROCESS_MACHINE_ID, "application.process.machine_id" },
77 	{ PW_KEY_APP_PROCESS_SESSION_ID, "application.process.session_id" },
78 	{ PW_KEY_MEDIA_ROLE, "media.role", media_role_map },
79 	{ NULL, NULL },
80 };
81 
read_u8(struct message * m,uint8_t * val)82 static int read_u8(struct message *m, uint8_t *val)
83 {
84 	if (m->offset + 1 > m->length)
85 		return -ENOSPC;
86 	*val = m->data[m->offset];
87 	m->offset++;
88 	return 0;
89 }
90 
read_u32(struct message * m,uint32_t * val)91 static int read_u32(struct message *m, uint32_t *val)
92 {
93 	if (m->offset + 4 > m->length)
94 		return -ENOSPC;
95 	memcpy(val, &m->data[m->offset], 4);
96 	*val = ntohl(*val);
97 	m->offset += 4;
98 	return 0;
99 }
read_u64(struct message * m,uint64_t * val)100 static int read_u64(struct message *m, uint64_t *val)
101 {
102 	uint32_t tmp;
103 	int res;
104 	if ((res = read_u32(m, &tmp)) < 0)
105 		return res;
106 	*val = ((uint64_t)tmp) << 32;
107 	if ((res = read_u32(m, &tmp)) < 0)
108 		return res;
109 	*val |= tmp;
110 	return 0;
111 }
112 
read_sample_spec(struct message * m,struct sample_spec * ss)113 static int read_sample_spec(struct message *m, struct sample_spec *ss)
114 {
115 	int res;
116 	uint8_t tmp;
117 	if ((res = read_u8(m, &tmp)) < 0)
118 		return res;
119 	ss->format = format_pa2id(tmp);
120 	if ((res = read_u8(m, &ss->channels)) < 0)
121 		return res;
122 	return read_u32(m, &ss->rate);
123 }
124 
read_props(struct message * m,struct pw_properties * props,bool remap)125 static int read_props(struct message *m, struct pw_properties *props, bool remap)
126 {
127 	int res;
128 
129 	while (true) {
130 		const char *key;
131 		const void *data;
132 		uint32_t length;
133 		size_t size;
134 		const struct str_map *map;
135 
136 		if ((res = message_get(m,
137 				TAG_STRING, &key,
138 				TAG_INVALID)) < 0)
139 			return res;
140 
141 		if (key == NULL)
142 			break;
143 
144 		if ((res = message_get(m,
145 				TAG_U32, &length,
146 				TAG_INVALID)) < 0)
147 			return res;
148 		if (length > MAX_TAG_SIZE)
149 			return -EINVAL;
150 
151 		if ((res = message_get(m,
152 				TAG_ARBITRARY, &data, &size,
153 				TAG_INVALID)) < 0)
154 			return res;
155 
156 		if (remap && (map = str_map_find(key_table, NULL, key)) != NULL) {
157 			key = map->pw_str;
158 			if (map->child != NULL &&
159 			    (map = str_map_find(map->child, NULL, data)) != NULL)
160 				data = map->pw_str;
161 		}
162 		pw_properties_set(props, key, data);
163 	}
164 	return 0;
165 }
166 
read_arbitrary(struct message * m,const void ** val,size_t * length)167 static int read_arbitrary(struct message *m, const void **val, size_t *length)
168 {
169 	uint32_t len;
170 	int res;
171 	if ((res = read_u32(m, &len)) < 0)
172 		return res;
173 	if (m->offset + len > m->length)
174 		return -ENOSPC;
175 	*val = m->data + m->offset;
176 	m->offset += len;
177 	if (length)
178 		*length = len;
179 	return 0;
180 }
181 
read_string(struct message * m,char ** str)182 static int read_string(struct message *m, char **str)
183 {
184 	uint32_t n, maxlen;
185 	if (m->offset + 1 > m->length)
186 		return -ENOSPC;
187 	maxlen = m->length - m->offset;
188 	n = strnlen(SPA_PTROFF(m->data, m->offset, char), maxlen);
189 	if (n == maxlen)
190 		return -EINVAL;
191 	*str = SPA_PTROFF(m->data, m->offset, char);
192 	m->offset += n + 1;
193 	return 0;
194 }
195 
read_timeval(struct message * m,struct timeval * tv)196 static int read_timeval(struct message *m, struct timeval *tv)
197 {
198 	int res;
199 	uint32_t tmp;
200 
201 	if ((res = read_u32(m, &tmp)) < 0)
202 		return res;
203 	tv->tv_sec = tmp;
204 	if ((res = read_u32(m, &tmp)) < 0)
205 		return res;
206 	tv->tv_usec = tmp;
207 	return 0;
208 }
209 
read_channel_map(struct message * m,struct channel_map * map)210 static int read_channel_map(struct message *m, struct channel_map *map)
211 {
212 	int res;
213 	uint8_t i, tmp;
214 
215 	if ((res = read_u8(m, &map->channels)) < 0)
216 		return res;
217 	if (map->channels > CHANNELS_MAX)
218 		return -EINVAL;
219 	for (i = 0; i < map->channels; i ++) {
220 		if ((res = read_u8(m, &tmp)) < 0)
221 			return res;
222 		map->map[i] = channel_pa2id(tmp);
223 	}
224 	return 0;
225 }
read_volume(struct message * m,float * vol)226 static int read_volume(struct message *m, float *vol)
227 {
228 	int res;
229 	uint32_t v;
230 	if ((res = read_u32(m, &v)) < 0)
231 		return res;
232 	*vol = volume_to_linear(v);
233 	return 0;
234 }
235 
read_cvolume(struct message * m,struct volume * vol)236 static int read_cvolume(struct message *m, struct volume *vol)
237 {
238 	int res;
239 	uint8_t i;
240 
241 	if ((res = read_u8(m, &vol->channels)) < 0)
242 		return res;
243 	if (vol->channels > CHANNELS_MAX)
244 		return -EINVAL;
245 	for (i = 0; i < vol->channels; i ++) {
246 		if ((res = read_volume(m, &vol->values[i])) < 0)
247 			return res;
248 	}
249 	return 0;
250 }
251 
read_format_info(struct message * m,struct format_info * info)252 static int read_format_info(struct message *m, struct format_info *info)
253 {
254 	int res;
255 	uint8_t tag, encoding;
256 
257 	spa_zero(*info);
258 	if ((res = read_u8(m, &tag)) < 0)
259 		return res;
260 	if (tag != TAG_U8)
261 		return -EPROTO;
262 	if ((res = read_u8(m, &encoding)) < 0)
263 		return res;
264 	info->encoding = encoding;
265 
266 	if ((res = read_u8(m, &tag)) < 0)
267 		return res;
268 	if (tag != TAG_PROPLIST)
269 		return -EPROTO;
270 
271 	info->props = pw_properties_new(NULL, NULL);
272 	if (info->props == NULL)
273 		return -errno;
274 	if ((res = read_props(m, info->props, false)) < 0)
275 		format_info_clear(info);
276 	return res;
277 }
278 
message_get(struct message * m,...)279 int message_get(struct message *m, ...)
280 {
281 	va_list va;
282 	int res = 0;
283 
284 	va_start(va, m);
285 
286 	while (true) {
287 		int tag = va_arg(va, int);
288 		uint8_t dtag;
289 		if (tag == TAG_INVALID)
290 			break;
291 
292 		if ((res = read_u8(m, &dtag)) < 0)
293 			goto done;
294 
295 		switch (dtag) {
296 		case TAG_STRING:
297 			if (tag != TAG_STRING)
298 				goto invalid;
299 			if ((res = read_string(m, va_arg(va, char**))) < 0)
300 				goto done;
301 			break;
302 		case TAG_STRING_NULL:
303 			if (tag != TAG_STRING)
304 				goto invalid;
305 			*va_arg(va, char**) = NULL;
306 			break;
307 		case TAG_U8:
308 			if (dtag != tag)
309 				goto invalid;
310 			if ((res = read_u8(m, va_arg(va, uint8_t*))) < 0)
311 				goto done;
312 			break;
313 		case TAG_U32:
314 			if (dtag != tag)
315 				goto invalid;
316 			if ((res = read_u32(m, va_arg(va, uint32_t*))) < 0)
317 				goto done;
318 			break;
319 		case TAG_S64:
320 		case TAG_U64:
321 		case TAG_USEC:
322 			if (dtag != tag)
323 				goto invalid;
324 			if ((res = read_u64(m, va_arg(va, uint64_t*))) < 0)
325 				goto done;
326 			break;
327 		case TAG_SAMPLE_SPEC:
328 			if (dtag != tag)
329 				goto invalid;
330 			if ((res = read_sample_spec(m, va_arg(va, struct sample_spec*))) < 0)
331 				goto done;
332 			break;
333 		case TAG_ARBITRARY:
334 		{
335 			const void **val = va_arg(va, const void**);
336 			size_t *len = va_arg(va, size_t*);
337 			if (dtag != tag)
338 				goto invalid;
339 			if ((res = read_arbitrary(m, val, len)) < 0)
340 				goto done;
341 			break;
342 		}
343 		case TAG_BOOLEAN_TRUE:
344 			if (tag != TAG_BOOLEAN)
345 				goto invalid;
346 			*va_arg(va, bool*) = true;
347 			break;
348 		case TAG_BOOLEAN_FALSE:
349 			if (tag != TAG_BOOLEAN)
350 				goto invalid;
351 			*va_arg(va, bool*) = false;
352 			break;
353 		case TAG_TIMEVAL:
354 			if (dtag != tag)
355 				goto invalid;
356 			if ((res = read_timeval(m, va_arg(va, struct timeval*))) < 0)
357 				goto done;
358 			break;
359 		case TAG_CHANNEL_MAP:
360 			if (dtag != tag)
361 				goto invalid;
362 			if ((res = read_channel_map(m, va_arg(va, struct channel_map*))) < 0)
363 				goto done;
364 			break;
365 		case TAG_CVOLUME:
366 			if (dtag != tag)
367 				goto invalid;
368 			if ((res = read_cvolume(m, va_arg(va, struct volume*))) < 0)
369 				goto done;
370 			break;
371 		case TAG_PROPLIST:
372 			if (dtag != tag)
373 				goto invalid;
374 			if ((res = read_props(m, va_arg(va, struct pw_properties*), true)) < 0)
375 				goto done;
376 			break;
377 		case TAG_VOLUME:
378 			if (dtag != tag)
379 				goto invalid;
380 			if ((res = read_volume(m, va_arg(va, float*))) < 0)
381 				goto done;
382 			break;
383 		case TAG_FORMAT_INFO:
384 			if (dtag != tag)
385 				goto invalid;
386 			if ((res = read_format_info(m, va_arg(va, struct format_info*))) < 0)
387 				goto done;
388 			break;
389 		}
390 	}
391 	res = 0;
392 	goto done;
393 
394 invalid:
395 	res = -EINVAL;
396 
397 done:
398 	va_end(va);
399 
400 	return res;
401 }
402 
ensure_size(struct message * m,uint32_t size)403 static int ensure_size(struct message *m, uint32_t size)
404 {
405 	uint32_t alloc, diff;
406 	void *data;
407 
408 	if (m->length + size <= m->allocated)
409 		return size;
410 
411 	alloc = SPA_ROUND_UP_N(SPA_MAX(m->allocated + size, 4096u), 4096u);
412 	diff = alloc - m->allocated;
413 	if ((data = realloc(m->data, alloc)) == NULL)
414 		return -errno;
415 	m->stat->allocated += diff;
416 	m->stat->accumulated += diff;
417 	m->data = data;
418 	m->allocated = alloc;
419 	return size;
420 }
421 
write_8(struct message * m,uint8_t val)422 static void write_8(struct message *m, uint8_t val)
423 {
424 	if (ensure_size(m, 1) > 0)
425 		m->data[m->length] = val;
426 	m->length++;
427 }
428 
write_32(struct message * m,uint32_t val)429 static void write_32(struct message *m, uint32_t val)
430 {
431 	val = htonl(val);
432 	if (ensure_size(m, 4) > 0)
433 		memcpy(m->data + m->length, &val, 4);
434 	m->length += 4;
435 }
436 
write_string(struct message * m,const char * s)437 static void write_string(struct message *m, const char *s)
438 {
439 	write_8(m, s ? TAG_STRING : TAG_STRING_NULL);
440 	if (s != NULL) {
441 		int len = strlen(s) + 1;
442 		if (ensure_size(m, len) > 0)
443 			strcpy(SPA_PTROFF(m->data, m->length, char), s);
444 		m->length += len;
445 	}
446 }
write_u8(struct message * m,uint8_t val)447 static void write_u8(struct message *m, uint8_t val)
448 {
449 	write_8(m, TAG_U8);
450 	write_8(m, val);
451 }
452 
write_u32(struct message * m,uint32_t val)453 static void write_u32(struct message *m, uint32_t val)
454 {
455 	write_8(m, TAG_U32);
456 	write_32(m, val);
457 }
458 
write_64(struct message * m,uint8_t tag,uint64_t val)459 static void write_64(struct message *m, uint8_t tag, uint64_t val)
460 {
461 	write_8(m, tag);
462 	write_32(m, val >> 32);
463 	write_32(m, val);
464 }
465 
write_sample_spec(struct message * m,struct sample_spec * ss)466 static void write_sample_spec(struct message *m, struct sample_spec *ss)
467 {
468 	uint32_t channels = SPA_MIN(ss->channels, PA_CHANNELS_MAX);
469 	write_8(m, TAG_SAMPLE_SPEC);
470 	write_8(m, format_id2pa(ss->format));
471 	write_8(m, channels);
472 	write_32(m, ss->rate);
473 }
474 
write_arbitrary(struct message * m,const void * p,size_t length)475 static void write_arbitrary(struct message *m, const void *p, size_t length)
476 {
477 	write_8(m, TAG_ARBITRARY);
478 	write_32(m, length);
479 	if (ensure_size(m, length) > 0)
480 		memcpy(m->data + m->length, p, length);
481 	m->length += length;
482 }
483 
write_boolean(struct message * m,bool val)484 static void write_boolean(struct message *m, bool val)
485 {
486 	write_8(m, val ? TAG_BOOLEAN_TRUE : TAG_BOOLEAN_FALSE);
487 }
488 
write_timeval(struct message * m,struct timeval * tv)489 static void write_timeval(struct message *m, struct timeval *tv)
490 {
491 	write_8(m, TAG_TIMEVAL);
492 	write_32(m, tv->tv_sec);
493 	write_32(m, tv->tv_usec);
494 }
495 
write_channel_map(struct message * m,struct channel_map * map)496 static void write_channel_map(struct message *m, struct channel_map *map)
497 {
498 	uint8_t i;
499 	uint32_t aux = 0, channels = SPA_MIN(map->channels, PA_CHANNELS_MAX);
500 	write_8(m, TAG_CHANNEL_MAP);
501 	write_8(m, channels);
502 	for (i = 0; i < channels; i ++)
503 		write_8(m, channel_id2pa(map->map[i], &aux));
504 }
505 
write_volume(struct message * m,float vol)506 static void write_volume(struct message *m, float vol)
507 {
508 	write_8(m, TAG_VOLUME);
509 	write_32(m, volume_from_linear(vol));
510 }
511 
write_cvolume(struct message * m,struct volume * vol)512 static void write_cvolume(struct message *m, struct volume *vol)
513 {
514 	uint8_t i;
515 	uint32_t channels = SPA_MIN(vol->channels, PA_CHANNELS_MAX);
516 	write_8(m, TAG_CVOLUME);
517 	write_8(m, channels);
518 	for (i = 0; i < channels; i ++)
519 		write_32(m, volume_from_linear(vol->values[i]));
520 }
521 
add_stream_group(struct message * m,struct spa_dict * dict,const char * key,const char * media_class,const char * media_role)522 static void add_stream_group(struct message *m, struct spa_dict *dict, const char *key,
523 		const char *media_class, const char *media_role)
524 {
525 	const char *str, *id, *prefix;
526 	char *b;
527 	int l;
528 
529 	if (media_class == NULL)
530 		return;
531 	if (spa_streq(media_class, "Stream/Output/Audio"))
532 		prefix = "sink-input";
533 	else if (spa_streq(media_class, "Stream/Input/Audio"))
534 		prefix = "source-output";
535 	else
536 		return;
537 
538 	if ((str = media_role) != NULL)
539 		id = "media-role";
540 	else if ((str = spa_dict_lookup(dict, PW_KEY_APP_ID)) != NULL)
541 		id = "application-id";
542 	else if ((str = spa_dict_lookup(dict, PW_KEY_APP_NAME)) != NULL)
543 		id = "application-name";
544 	else if ((str = spa_dict_lookup(dict, PW_KEY_MEDIA_NAME)) != NULL)
545 		id = "media-name";
546 	else
547 		return;
548 
549 	write_string(m, key);
550 	l = strlen(prefix) + strlen(id) + strlen(str) + 6; /* "-by-" , ":" and \0 */
551 	b = alloca(l);
552 	snprintf(b, l, "%s-by-%s:%s", prefix, id, str);
553 	write_u32(m, l);
554 	write_arbitrary(m, b, l);
555 }
556 
write_dict(struct message * m,struct spa_dict * dict,bool remap)557 static void write_dict(struct message *m, struct spa_dict *dict, bool remap)
558 {
559 	const struct spa_dict_item *it;
560 
561 	write_8(m, TAG_PROPLIST);
562 	if (dict != NULL) {
563 		const char *media_class = NULL, *media_role = NULL;
564 		spa_dict_for_each(it, dict) {
565 			const char *key = it->key;
566 			const char *val = it->value;
567 			int l;
568 			const struct str_map *map;
569 
570 			if (remap && (map = str_map_find(key_table, key, NULL)) != NULL) {
571 				key = map->pa_str;
572 				if (map->child != NULL &&
573 				    (map = str_map_find(map->child, val, NULL)) != NULL)
574 					val = map->pa_str;
575 			}
576 			if (spa_streq(key, "media.class"))
577 				media_class = val;
578 			if (spa_streq(key, "media.role"))
579 				media_role = val;
580 
581 			write_string(m, key);
582 			l = strlen(val) + 1;
583 			write_u32(m, l);
584 			write_arbitrary(m, val, l);
585 
586 		}
587 		if (remap)
588 			add_stream_group(m, dict, "module-stream-restore.id",
589 					media_class, media_role);
590 	}
591 	write_string(m, NULL);
592 }
593 
write_format_info(struct message * m,struct format_info * info)594 static void write_format_info(struct message *m, struct format_info *info)
595 {
596 	write_8(m, TAG_FORMAT_INFO);
597 	write_u8(m, (uint8_t) info->encoding);
598 	write_dict(m, info->props ? &info->props->dict : NULL, false);
599 }
600 
message_put(struct message * m,...)601 int message_put(struct message *m, ...)
602 {
603 	va_list va;
604 
605 	if (m == NULL)
606 		return -EINVAL;
607 
608 	va_start(va, m);
609 
610 	while (true) {
611 		int tag = va_arg(va, int);
612 		if (tag == TAG_INVALID)
613 			break;
614 
615 		switch (tag) {
616 		case TAG_STRING:
617 			write_string(m, va_arg(va, const char *));
618 			break;
619 		case TAG_U8:
620 			write_u8(m, (uint8_t)va_arg(va, int));
621 			break;
622 		case TAG_U32:
623 			write_u32(m, (uint32_t)va_arg(va, uint32_t));
624 			break;
625 		case TAG_S64:
626 		case TAG_U64:
627 		case TAG_USEC:
628 			write_64(m, tag, va_arg(va, uint64_t));
629 			break;
630 		case TAG_SAMPLE_SPEC:
631 			write_sample_spec(m, va_arg(va, struct sample_spec*));
632 			break;
633 		case TAG_ARBITRARY:
634 		{
635 			const void *p = va_arg(va, const void*);
636 			size_t length = va_arg(va, size_t);
637 			write_arbitrary(m, p, length);
638 			break;
639 		}
640 		case TAG_BOOLEAN:
641 			write_boolean(m, va_arg(va, int));
642 			break;
643 		case TAG_TIMEVAL:
644 			write_timeval(m, va_arg(va, struct timeval*));
645 			break;
646 		case TAG_CHANNEL_MAP:
647 			write_channel_map(m, va_arg(va, struct channel_map*));
648 			break;
649 		case TAG_CVOLUME:
650 			write_cvolume(m, va_arg(va, struct volume*));
651 			break;
652 		case TAG_PROPLIST:
653 			write_dict(m, va_arg(va, struct spa_dict*), true);
654 			break;
655 		case TAG_VOLUME:
656 			write_volume(m, va_arg(va, double));
657 			break;
658 		case TAG_FORMAT_INFO:
659 			write_format_info(m, va_arg(va, struct format_info*));
660 			break;
661 		}
662 	}
663 	va_end(va);
664 
665 	if (m->length > m->allocated)
666 		return -ENOMEM;
667 
668 	return 0;
669 }
670 
message_dump(enum spa_log_level level,struct message * m)671 int message_dump(enum spa_log_level level, struct message *m)
672 {
673 	int res;
674 	uint32_t i, offset = m->offset, o;
675 
676 	pw_log(level, "message: len:%d alloc:%u", m->length, m->allocated);
677 	while (true) {
678 		uint8_t tag;
679 
680 		o = m->offset;
681 		if (read_u8(m, &tag) < 0)
682 			break;
683 
684 		switch (tag) {
685 		case TAG_STRING:
686 		{
687 			char *val;
688 			if ((res = read_string(m, &val)) < 0)
689 				return res;
690 			pw_log(level, "%u: string: '%s'", o, val);
691 			break;
692 			}
693 		case TAG_STRING_NULL:
694 			pw_log(level, "%u: string: NULL", o);
695 			break;
696 		case TAG_U8:
697 		{
698 			uint8_t val;
699 			if ((res = read_u8(m, &val)) < 0)
700 				return res;
701 			pw_log(level, "%u: u8: %u", o, val);
702 			break;
703 		}
704 		case TAG_U32:
705 		{
706 			uint32_t val;
707 			if ((res = read_u32(m, &val)) < 0)
708 				return res;
709 			pw_log(level, "%u: u32: %u", o, val);
710 			break;
711 		}
712 		case TAG_S64:
713 		{
714 			uint64_t val;
715 			if ((res = read_u64(m, &val)) < 0)
716 				return res;
717 			pw_log(level, "%u: s64: %"PRIi64"", o, (int64_t)val);
718 			break;
719 		}
720 		case TAG_U64:
721 		{
722 			uint64_t val;
723 			if ((res = read_u64(m, &val)) < 0)
724 				return res;
725 			pw_log(level, "%u: u64: %"PRIu64"", o, val);
726 			break;
727 		}
728 		case TAG_USEC:
729 		{
730 			uint64_t val;
731 			if ((res = read_u64(m, &val)) < 0)
732 				return res;
733 			pw_log(level, "%u: u64: %"PRIu64"", o, val);
734 			break;
735 		}
736 		case TAG_SAMPLE_SPEC:
737 		{
738 			struct sample_spec ss;
739 			if ((res = read_sample_spec(m, &ss)) < 0)
740 				return res;
741 			pw_log(level, "%u: ss: format:%s rate:%d channels:%u", o,
742 					format_id2name(ss.format), ss.rate,
743 					ss.channels);
744 			break;
745 		}
746 		case TAG_ARBITRARY:
747 		{
748 			const void *mem;
749 			size_t len;
750 			if ((res = read_arbitrary(m, &mem, &len)) < 0)
751 				return res;
752 			spa_debug_mem(0, mem, len);
753 			break;
754 		}
755 		case TAG_BOOLEAN_TRUE:
756 			pw_log(level, "%u: bool: true", o);
757 			break;
758 		case TAG_BOOLEAN_FALSE:
759 			pw_log(level, "%u: bool: false", o);
760 			break;
761 		case TAG_TIMEVAL:
762 		{
763 			struct timeval tv;
764 			if ((res = read_timeval(m, &tv)) < 0)
765 				return res;
766 			pw_log(level, "%u: timeval: %lu:%lu", o, tv.tv_sec, tv.tv_usec);
767 			break;
768 		}
769 		case TAG_CHANNEL_MAP:
770 		{
771 			struct channel_map map;
772 			if ((res = read_channel_map(m, &map)) < 0)
773 				return res;
774 			pw_log(level, "%u: channelmap: channels:%u", o, map.channels);
775 			for (i = 0; i < map.channels; i++)
776 				pw_log(level, "    %d: %s", i, channel_id2name(map.map[i]));
777 			break;
778 		}
779 		case TAG_CVOLUME:
780 		{
781 			struct volume vol;
782 			if ((res = read_cvolume(m, &vol)) < 0)
783 				return res;
784 			pw_log(level, "%u: cvolume: channels:%u", o, vol.channels);
785 			for (i = 0; i < vol.channels; i++)
786 				pw_log(level, "    %d: %f", i, vol.values[i]);
787 			break;
788 		}
789 		case TAG_PROPLIST:
790 		{
791 			struct pw_properties *props = pw_properties_new(NULL, NULL);
792 			const struct spa_dict_item *it;
793 			res = read_props(m, props, false);
794 			if (res >= 0) {
795 				pw_log(level, "%u: props: n_items:%u", o, props->dict.n_items);
796 				spa_dict_for_each(it, &props->dict)
797 					pw_log(level, "     '%s': '%s'", it->key, it->value);
798 			}
799 			pw_properties_free(props);
800 			if (res < 0)
801 				return res;
802 			break;
803 		}
804 		case TAG_VOLUME:
805 		{
806 			float vol;
807 			if ((res = read_volume(m, &vol)) < 0)
808 				return res;
809 			pw_log(level, "%u: volume: %f", o, vol);
810 			break;
811 		}
812 		case TAG_FORMAT_INFO:
813 		{
814 			struct format_info info;
815 			const struct spa_dict_item *it;
816 			if ((res = read_format_info(m, &info)) < 0)
817 				return res;
818 			pw_log(level, "%u: format-info: enc:%s n_items:%u",
819 					o, format_encoding2name(info.encoding),
820 					info.props->dict.n_items);
821 			spa_dict_for_each(it, &info.props->dict)
822 				pw_log(level, "     '%s': '%s'", it->key, it->value);
823 			break;
824 		}
825 		}
826 	}
827 	m->offset = offset;
828 
829 	return 0;
830 }
831 
message_alloc(struct impl * impl,uint32_t channel,uint32_t size)832 struct message *message_alloc(struct impl *impl, uint32_t channel, uint32_t size)
833 {
834 	struct message *msg;
835 
836 	if (!spa_list_is_empty(&impl->free_messages)) {
837 		msg = spa_list_first(&impl->free_messages, struct message, link);
838 		spa_list_remove(&msg->link);
839 		pw_log_trace("using recycled message %p", msg);
840 	} else {
841 		if ((msg = calloc(1, sizeof(*msg))) == NULL)
842 			return NULL;
843 
844 		pw_log_trace("new message %p", msg);
845 		msg->stat = &impl->stat;
846 		msg->stat->n_allocated++;
847 		msg->stat->n_accumulated++;
848 	}
849 
850 	if (ensure_size(msg, size) < 0) {
851 		message_free(impl, msg, false, true);
852 		return NULL;
853 	}
854 
855 	spa_zero(msg->extra);
856 	msg->channel = channel;
857 	msg->offset = 0;
858 	msg->length = size;
859 
860 	return msg;
861 }
862 
message_free(struct impl * impl,struct message * msg,bool dequeue,bool destroy)863 void message_free(struct impl *impl, struct message *msg, bool dequeue, bool destroy)
864 {
865 	if (dequeue)
866 		spa_list_remove(&msg->link);
867 
868 	if (msg->stat->allocated > MAX_ALLOCATED || msg->allocated > MAX_SIZE)
869 		destroy = true;
870 
871 	if (destroy) {
872 		pw_log_trace("destroy message %p size:%d", msg, msg->allocated);
873 		msg->stat->n_allocated--;
874 		msg->stat->allocated -= msg->allocated;
875 		free(msg->data);
876 		free(msg);
877 	} else {
878 		pw_log_trace("recycle message %p size:%d", msg, msg->allocated);
879 		spa_list_append(&impl->free_messages, &msg->link);
880 	}
881 }
882