format: Add support for Dolby TrueHD and DTS-HD HBR passthrough
[platform/upstream/pulseaudio.git] / src / pulse / format.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2011 Intel Corporation
5   Copyright 2011 Collabora Multimedia
6   Copyright 2011 Arun Raghavan <arun.raghavan@collabora.co.uk>
7
8   PulseAudio is free software; you can redistribute it and/or modify
9   it under the terms of the GNU Lesser General Public License as published
10   by the Free Software Foundation; either version 2.1 of the License,
11   or (at your option) any later version.
12
13   PulseAudio is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <pulse/json.h>
27 #include <pulse/internal.h>
28 #include <pulse/xmalloc.h>
29
30 #include <pulsecore/core-format.h>
31 #include <pulsecore/core-util.h>
32 #include <pulsecore/i18n.h>
33 #include <pulsecore/macro.h>
34 #include <pulsecore/strbuf.h>
35
36 #include "format.h"
37
38 #define PA_JSON_MIN_KEY "min"
39 #define PA_JSON_MAX_KEY "max"
40
41 static int pa_format_info_prop_compatible(const char *one, const char *two);
42
43 static const char* const _encoding_str_table[]= {
44     [PA_ENCODING_PCM] = "pcm",
45     [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
46     [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
47     [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
48     [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
49     [PA_ENCODING_MPEG2_AAC_IEC61937] = "mpeg2-aac-iec61937",
50     [PA_ENCODING_TRUEHD_IEC61937] = "truehd-iec61937",
51     [PA_ENCODING_DTSHD_IEC61937] = "dtshd-iec61937",
52     [PA_ENCODING_ANY] = "any",
53 };
54
55 const char *pa_encoding_to_string(pa_encoding_t e) {
56     if (e < 0 || e >= PA_ENCODING_MAX)
57         return NULL;
58
59     return _encoding_str_table[e];
60 }
61
62 pa_encoding_t pa_encoding_from_string(const char *encoding) {
63     pa_encoding_t e;
64
65     for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
66         if (pa_streq(_encoding_str_table[e], encoding))
67             return e;
68
69     return PA_ENCODING_INVALID;
70 }
71
72 pa_format_info* pa_format_info_new(void) {
73     pa_format_info *f = pa_xnew(pa_format_info, 1);
74
75     f->encoding = PA_ENCODING_INVALID;
76     f->plist = pa_proplist_new();
77
78     return f;
79 }
80
81 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
82     pa_format_info *dest;
83
84     pa_assert(src);
85
86     dest = pa_xnew(pa_format_info, 1);
87
88     dest->encoding = src->encoding;
89
90     if (src->plist)
91         dest->plist = pa_proplist_copy(src->plist);
92     else
93         dest->plist = NULL;
94
95     return dest;
96 }
97
98 void pa_format_info_free(pa_format_info *f) {
99     pa_assert(f);
100
101     pa_proplist_free(f->plist);
102     pa_xfree(f);
103 }
104
105 int pa_format_info_valid(const pa_format_info *f) {
106     return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
107 }
108
109 int pa_format_info_is_pcm(const pa_format_info *f) {
110     return f->encoding == PA_ENCODING_PCM;
111 }
112
113 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
114     char *tmp;
115
116     pa_assert(s);
117     pa_assert(l > 0);
118     pa_assert(f);
119
120     pa_init_i18n();
121
122     if (!pa_format_info_valid(f))
123         pa_snprintf(s, l, _("(invalid)"));
124     else {
125         tmp = pa_proplist_to_string_sep(f->plist, "  ");
126         if (tmp[0])
127             pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
128         else
129             pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
130         pa_xfree(tmp);
131     }
132
133     return s;
134 }
135
136 pa_format_info* pa_format_info_from_string(const char *str) {
137     pa_format_info *f = pa_format_info_new();
138     char *encoding = NULL, *properties = NULL;
139     size_t pos;
140
141     pos = strcspn(str, ",");
142
143     encoding = pa_xstrndup(str, pos);
144     f->encoding = pa_encoding_from_string(pa_strip(encoding));
145     if (f->encoding == PA_ENCODING_INVALID)
146         goto error;
147
148     if (pos != strlen(str)) {
149         pa_proplist *plist;
150
151         properties = pa_xstrdup(&str[pos+1]);
152         plist = pa_proplist_from_string(properties);
153
154         if (!plist)
155             goto error;
156
157         pa_proplist_free(f->plist);
158         f->plist = plist;
159     }
160
161 out:
162     if (encoding)
163         pa_xfree(encoding);
164     if (properties)
165         pa_xfree(properties);
166     return f;
167
168 error:
169     pa_format_info_free(f);
170     f = NULL;
171     goto out;
172 }
173
174 int pa_format_info_is_compatible(const pa_format_info *first, const pa_format_info *second) {
175     const char *key;
176     void *state = NULL;
177
178     pa_assert(first);
179     pa_assert(second);
180
181     if (first->encoding != second->encoding)
182         return false;
183
184     while ((key = pa_proplist_iterate(first->plist, &state))) {
185         const char *value_one, *value_two;
186
187         value_one = pa_proplist_gets(first->plist, key);
188         value_two = pa_proplist_gets(second->plist, key);
189
190         if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
191             return false;
192     }
193
194     return true;
195 }
196
197 pa_format_info* pa_format_info_from_sample_spec(const pa_sample_spec *ss, const pa_channel_map *map) {
198     char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
199     pa_format_info *f;
200
201     pa_assert(ss && pa_sample_spec_valid(ss));
202     pa_assert(!map || pa_channel_map_valid(map));
203
204     f = pa_format_info_new();
205     f->encoding = PA_ENCODING_PCM;
206
207     pa_format_info_set_sample_format(f, ss->format);
208     pa_format_info_set_rate(f, ss->rate);
209     pa_format_info_set_channels(f, ss->channels);
210
211     if (map) {
212         pa_channel_map_snprint(cm, sizeof(cm), map);
213         pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
214     }
215
216     return f;
217 }
218
219 /* For PCM streams */
220 int pa_format_info_to_sample_spec(const pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
221     pa_assert(f);
222     pa_assert(ss);
223
224     if (!pa_format_info_is_pcm(f))
225         return pa_format_info_to_sample_spec_fake(f, ss, map);
226
227     if (pa_format_info_get_sample_format(f, &ss->format) < 0)
228         return -PA_ERR_INVALID;
229     if (pa_format_info_get_rate(f, &ss->rate) < 0)
230         return -PA_ERR_INVALID;
231     if (pa_format_info_get_channels(f, &ss->channels) < 0)
232         return -PA_ERR_INVALID;
233     if (map && pa_format_info_get_channel_map(f, map) < 0)
234         return -PA_ERR_INVALID;
235
236     return 0;
237 }
238
239 pa_prop_type_t pa_format_info_get_prop_type(const pa_format_info *f, const char *key) {
240     const char *str;
241     pa_json_object *o;
242     const pa_json_object *o1;
243     pa_prop_type_t type;
244
245     pa_assert(f);
246     pa_assert(key);
247
248     str = pa_proplist_gets(f->plist, key);
249     if (!str)
250         return PA_PROP_TYPE_INVALID;
251
252     o = pa_json_parse(str);
253     if (!o)
254         return PA_PROP_TYPE_INVALID;
255
256     switch (pa_json_object_get_type(o)) {
257         case PA_JSON_TYPE_INT:
258             type = PA_PROP_TYPE_INT;
259             break;
260
261         case PA_JSON_TYPE_STRING:
262             type = PA_PROP_TYPE_STRING;
263             break;
264
265         case PA_JSON_TYPE_ARRAY:
266             if (pa_json_object_get_array_length(o) == 0) {
267                 /* Unlikely, but let's account for this anyway. We need at
268                  * least one element to figure out the array type. */
269                 type = PA_PROP_TYPE_INVALID;
270                 break;
271             }
272
273             o1 = pa_json_object_get_array_member(o, 0);
274
275             if (pa_json_object_get_type(o1) == PA_JSON_TYPE_INT)
276                 type = PA_PROP_TYPE_INT_ARRAY;
277             else if (pa_json_object_get_type(o1) == PA_JSON_TYPE_STRING)
278                 type = PA_PROP_TYPE_STRING_ARRAY;
279             else
280                 type = PA_PROP_TYPE_INVALID;
281
282             break;
283
284         case PA_JSON_TYPE_OBJECT:
285             /* We actually know at this point that it's a int range, but let's
286              * confirm. */
287             if (!pa_json_object_get_object_member(o, PA_JSON_MIN_KEY)) {
288                 type = PA_PROP_TYPE_INVALID;
289                 break;
290             }
291
292             if (!pa_json_object_get_object_member(o, PA_JSON_MAX_KEY)) {
293                 type = PA_PROP_TYPE_INVALID;
294                 break;
295             }
296
297             type = PA_PROP_TYPE_INT_RANGE;
298             break;
299
300         default:
301             type = PA_PROP_TYPE_INVALID;
302             break;
303     }
304
305     pa_json_object_free(o);
306     return type;
307 }
308
309 int pa_format_info_get_prop_int(const pa_format_info *f, const char *key, int *v) {
310     const char *str;
311     pa_json_object *o;
312
313     pa_assert(f);
314     pa_assert(key);
315     pa_assert(v);
316
317     str = pa_proplist_gets(f->plist, key);
318     if (!str)
319         return -PA_ERR_NOENTITY;
320
321     o = pa_json_parse(str);
322     if (!o) {
323         pa_log_debug("Failed to parse format info property '%s'.", key);
324         return -PA_ERR_INVALID;
325     }
326
327     if (pa_json_object_get_type(o) != PA_JSON_TYPE_INT) {
328         pa_log_debug("Format info property '%s' type is not int.", key);
329         pa_json_object_free(o);
330         return -PA_ERR_INVALID;
331     }
332
333     *v = pa_json_object_get_int(o);
334     pa_json_object_free(o);
335
336     return 0;
337 }
338
339 int pa_format_info_get_prop_int_range(const pa_format_info *f, const char *key, int *min, int *max) {
340     const char *str;
341     pa_json_object *o;
342     const pa_json_object *o1;
343     int ret = -PA_ERR_INVALID;
344
345     pa_assert(f);
346     pa_assert(key);
347     pa_assert(min);
348     pa_assert(max);
349
350     str = pa_proplist_gets(f->plist, key);
351     if (!str)
352         return -PA_ERR_NOENTITY;
353
354     o = pa_json_parse(str);
355     if (!o) {
356         pa_log_debug("Failed to parse format info property '%s'.", key);
357         return -PA_ERR_INVALID;
358     }
359
360     if (pa_json_object_get_type(o) != PA_JSON_TYPE_OBJECT)
361         goto out;
362
363     if (!(o1 = pa_json_object_get_object_member(o, PA_JSON_MIN_KEY)) ||
364             (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT))
365         goto out;
366
367     *min = pa_json_object_get_int(o1);
368
369     if (!(o1 = pa_json_object_get_object_member(o, PA_JSON_MAX_KEY)) ||
370             (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT))
371         goto out;
372
373     *max = pa_json_object_get_int(o1);
374
375     ret = 0;
376
377 out:
378     if (ret < 0)
379         pa_log_debug("Format info property '%s' is not a valid int range.", key);
380
381     pa_json_object_free(o);
382     return ret;
383 }
384
385 int pa_format_info_get_prop_int_array(const pa_format_info *f, const char *key, int **values, int *n_values) {
386     const char *str;
387     pa_json_object *o;
388     const pa_json_object *o1;
389     int i, ret = -PA_ERR_INVALID;
390
391     pa_assert(f);
392     pa_assert(key);
393     pa_assert(values);
394     pa_assert(n_values);
395
396     str = pa_proplist_gets(f->plist, key);
397     if (!str)
398         return -PA_ERR_NOENTITY;
399
400     o = pa_json_parse(str);
401     if (!o) {
402         pa_log_debug("Failed to parse format info property '%s'.", key);
403         return -PA_ERR_INVALID;
404     }
405
406     if (pa_json_object_get_type(o) != PA_JSON_TYPE_ARRAY)
407         goto out;
408
409     *n_values = pa_json_object_get_array_length(o);
410     *values = pa_xnew(int, *n_values);
411
412     for (i = 0; i < *n_values; i++) {
413         o1 = pa_json_object_get_array_member(o, i);
414
415         if (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT) {
416             goto out;
417         }
418
419         (*values)[i] = pa_json_object_get_int(o1);
420     }
421
422     ret = 0;
423
424 out:
425     if (ret < 0)
426         pa_log_debug("Format info property '%s' is not a valid int array.", key);
427
428     pa_json_object_free(o);
429     return ret;
430 }
431
432 int pa_format_info_get_prop_string(const pa_format_info *f, const char *key, char **v) {
433     const char *str = NULL;
434     pa_json_object *o;
435
436     pa_assert(f);
437     pa_assert(key);
438     pa_assert(v);
439
440     str = pa_proplist_gets(f->plist, key);
441     if (!str)
442         return -PA_ERR_NOENTITY;
443
444     o = pa_json_parse(str);
445     if (!o) {
446         pa_log_debug("Failed to parse format info property '%s'.", key);
447         return -PA_ERR_INVALID;
448     }
449
450     if (pa_json_object_get_type(o) != PA_JSON_TYPE_STRING) {
451         pa_log_debug("Format info property '%s' type is not string.", key);
452         pa_json_object_free(o);
453         return -PA_ERR_INVALID;
454     }
455
456     *v = pa_xstrdup(pa_json_object_get_string(o));
457     pa_json_object_free(o);
458
459     return 0;
460 }
461
462 int pa_format_info_get_prop_string_array(const pa_format_info *f, const char *key, char ***values, int *n_values) {
463     const char *str;
464     pa_json_object *o;
465     const pa_json_object *o1;
466     int i, ret = -PA_ERR_INVALID;
467
468     pa_assert(f);
469     pa_assert(key);
470     pa_assert(values);
471     pa_assert(n_values);
472
473     str = pa_proplist_gets(f->plist, key);
474     if (!str)
475         return -PA_ERR_NOENTITY;
476
477     o = pa_json_parse(str);
478     if (!o) {
479         pa_log_debug("Failed to parse format info property '%s'.", key);
480         return -PA_ERR_INVALID;
481     }
482
483     if (pa_json_object_get_type(o) != PA_JSON_TYPE_ARRAY)
484         goto out;
485
486     *n_values = pa_json_object_get_array_length(o);
487     *values = pa_xnew(char *, *n_values);
488
489     for (i = 0; i < *n_values; i++) {
490         o1 = pa_json_object_get_array_member(o, i);
491
492         if (pa_json_object_get_type(o1) != PA_JSON_TYPE_STRING) {
493             goto out;
494         }
495
496         (*values)[i] = pa_xstrdup(pa_json_object_get_string(o1));
497     }
498
499     ret = 0;
500
501 out:
502     if (ret < 0)
503         pa_log_debug("Format info property '%s' is not a valid string array.", key);
504
505     pa_json_object_free(o);
506     return ret;
507 }
508
509 void pa_format_info_free_string_array(char **values, int n_values) {
510     int i;
511
512     for (i = 0; i < n_values; i++)
513         pa_xfree(values[i]);
514
515     pa_xfree(values);
516 }
517
518 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
519     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
520 }
521
522 void pa_format_info_set_rate(pa_format_info *f, int rate) {
523     pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
524 }
525
526 void pa_format_info_set_channels(pa_format_info *f, int channels) {
527     pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
528 }
529
530 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
531     char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
532
533     pa_channel_map_snprint(map_str, sizeof(map_str), map);
534
535     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
536 }
537
538 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
539     pa_assert(f);
540     pa_assert(key);
541
542     pa_proplist_setf(f->plist, key, "%d", value);
543 }
544
545 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
546     pa_strbuf *buf;
547     char *str;
548     int i;
549
550     pa_assert(f);
551     pa_assert(key);
552     pa_assert(n_values > 0);
553
554     buf = pa_strbuf_new();
555
556     pa_strbuf_printf(buf, "[ %d", values[0]);
557
558     for (i = 1; i < n_values; i++)
559         pa_strbuf_printf(buf, ", %d", values[i]);
560
561     pa_strbuf_printf(buf, " ]");
562     str = pa_strbuf_to_string_free(buf);
563
564     pa_proplist_sets(f->plist, key, str);
565     pa_xfree (str);
566 }
567
568 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
569     pa_assert(f);
570     pa_assert(key);
571
572     pa_proplist_setf(f->plist, key, "{ \"" PA_JSON_MIN_KEY "\": %d, \"" PA_JSON_MAX_KEY "\": %d }",
573             min, max);
574 }
575
576 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
577     pa_assert(f);
578     pa_assert(key);
579
580     pa_proplist_setf(f->plist, key, "\"%s\"", value);
581 }
582
583 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
584     pa_strbuf *buf;
585     char *str;
586     int i;
587
588     pa_assert(f);
589     pa_assert(key);
590
591     buf = pa_strbuf_new();
592
593     pa_strbuf_printf(buf, "[ \"%s\"", values[0]);
594
595     for (i = 1; i < n_values; i++)
596         pa_strbuf_printf(buf, ", \"%s\"", values[i]);
597
598     pa_strbuf_printf(buf, " ]");
599     str = pa_strbuf_to_string_free(buf);
600
601     pa_proplist_sets(f->plist, key, str);
602     pa_xfree (str);
603 }
604
605 static bool pa_json_is_fixed_type(pa_json_object *o) {
606     switch(pa_json_object_get_type(o)) {
607         case PA_JSON_TYPE_OBJECT:
608         case PA_JSON_TYPE_ARRAY:
609             return false;
610
611         default:
612             return true;
613     }
614 }
615
616 static int pa_format_info_prop_compatible(const char *one, const char *two) {
617     pa_json_object *o1 = NULL, *o2 = NULL;
618     int i, ret = 0;
619
620     o1 = pa_json_parse(one);
621     if (!o1)
622         goto out;
623
624     o2 = pa_json_parse(two);
625     if (!o2)
626         goto out;
627
628     /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
629     pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), false);
630
631     if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
632         ret = pa_json_object_equal(o1, o2);
633         goto out;
634     }
635
636     if (pa_json_is_fixed_type(o1)) {
637         pa_json_object *tmp = o2;
638         o2 = o1;
639         o1 = tmp;
640     }
641
642     /* o2 is now a fixed type, and o1 is not */
643
644     if (pa_json_object_get_type(o1) == PA_JSON_TYPE_ARRAY) {
645         for (i = 0; i < pa_json_object_get_array_length(o1); i++) {
646             if (pa_json_object_equal(pa_json_object_get_array_member(o1, i), o2)) {
647                 ret = 1;
648                 break;
649             }
650         }
651     } else if (pa_json_object_get_type(o1) == PA_JSON_TYPE_OBJECT) {
652         /* o1 should be a range type */
653         int min, max, v;
654         const pa_json_object *o_min = NULL, *o_max = NULL;
655
656         if (pa_json_object_get_type(o2) != PA_JSON_TYPE_INT) {
657             /* We don't support non-integer ranges */
658             goto out;
659         }
660
661         if (!(o_min = pa_json_object_get_object_member(o1, PA_JSON_MIN_KEY)) ||
662             pa_json_object_get_type(o_min) != PA_JSON_TYPE_INT)
663             goto out;
664
665         if (!(o_max = pa_json_object_get_object_member(o1, PA_JSON_MAX_KEY)) ||
666             pa_json_object_get_type(o_max) != PA_JSON_TYPE_INT)
667             goto out;
668
669         v = pa_json_object_get_int(o2);
670         min = pa_json_object_get_int(o_min);
671         max = pa_json_object_get_int(o_max);
672
673         ret = v >= min && v <= max;
674     } else {
675         pa_log_warn("Got a format type that we don't support");
676     }
677
678 out:
679     if (o1)
680         pa_json_object_free(o1);
681     if (o2)
682         pa_json_object_free(o2);
683
684     return ret;
685 }