2 This file is part of PulseAudio.
4 Copyright 2011 Intel Corporation
5 Copyright 2011 Collabora Multimedia
6 Copyright 2011 Arun Raghavan <arun.raghavan@collabora.co.uk>
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.
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.
18 You should have received a copy of the GNU Lesser General Public License
19 along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
30 #include <pulse/internal.h>
31 #include <pulse/xmalloc.h>
33 #include <pulsecore/core-util.h>
34 #include <pulsecore/i18n.h>
35 #include <pulsecore/macro.h>
39 #define PA_JSON_MIN_KEY "min"
40 #define PA_JSON_MAX_KEY "max"
42 static int pa_format_info_prop_compatible(const char *one, const char *two);
44 static const char* const _encoding_str_table[]= {
45 [PA_ENCODING_PCM] = "pcm",
46 [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
47 [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
48 [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
49 [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
50 [PA_ENCODING_MPEG2_AAC_IEC61937] = "mpeg2-aac-iec61937",
51 [PA_ENCODING_ANY] = "any",
54 const char *pa_encoding_to_string(pa_encoding_t e) {
55 if (e < 0 || e >= PA_ENCODING_MAX)
58 return _encoding_str_table[e];
61 pa_encoding_t pa_encoding_from_string(const char *encoding) {
64 for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
65 if (pa_streq(_encoding_str_table[e], encoding))
68 return PA_ENCODING_INVALID;
71 pa_format_info* pa_format_info_new(void) {
72 pa_format_info *f = pa_xnew(pa_format_info, 1);
74 f->encoding = PA_ENCODING_INVALID;
75 f->plist = pa_proplist_new();
80 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
85 dest = pa_xnew(pa_format_info, 1);
87 dest->encoding = src->encoding;
90 dest->plist = pa_proplist_copy(src->plist);
97 void pa_format_info_free(pa_format_info *f) {
100 pa_proplist_free(f->plist);
104 int pa_format_info_valid(const pa_format_info *f) {
105 return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
108 int pa_format_info_is_pcm(const pa_format_info *f) {
109 return f->encoding == PA_ENCODING_PCM;
112 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
121 if (!pa_format_info_valid(f))
122 pa_snprintf(s, l, _("(invalid)"));
124 tmp = pa_proplist_to_string_sep(f->plist, " ");
126 pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
128 pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
135 pa_format_info* pa_format_info_from_string(const char *str) {
136 pa_format_info *f = pa_format_info_new();
137 char *encoding = NULL, *properties = NULL;
140 pos = strcspn(str, ",");
142 encoding = pa_xstrndup(str, pos);
143 f->encoding = pa_encoding_from_string(pa_strip(encoding));
144 if (f->encoding == PA_ENCODING_INVALID)
147 if (pos != strlen(str)) {
150 properties = pa_xstrdup(&str[pos+1]);
151 plist = pa_proplist_from_string(properties);
156 pa_proplist_free(f->plist);
164 pa_xfree(properties);
168 pa_format_info_free(f);
173 int pa_format_info_is_compatible(pa_format_info *first, pa_format_info *second) {
180 if (first->encoding != second->encoding)
183 while ((key = pa_proplist_iterate(first->plist, &state))) {
184 const char *value_one, *value_two;
186 value_one = pa_proplist_gets(first->plist, key);
187 value_two = pa_proplist_gets(second->plist, key);
189 if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
196 pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map) {
197 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
200 pa_assert(ss && pa_sample_spec_valid(ss));
201 pa_assert(!map || pa_channel_map_valid(map));
203 f = pa_format_info_new();
204 f->encoding = PA_ENCODING_PCM;
206 pa_format_info_set_sample_format(f, ss->format);
207 pa_format_info_set_rate(f, ss->rate);
208 pa_format_info_set_channels(f, ss->channels);
211 pa_channel_map_snprint(cm, sizeof(cm), map);
212 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
218 /* For compressed streams */
219 static int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
225 /* Note: When we add support for non-IEC61937 encapsulated compressed
226 * formats, this function should return a non-zero values for these. */
228 ss->format = PA_SAMPLE_S16LE;
231 pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
232 ss->rate = (uint32_t) rate;
234 if (f->encoding == PA_ENCODING_EAC3_IEC61937)
240 /* For PCM streams */
241 int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
242 char *sf = NULL, *m = NULL;
244 int ret = -PA_ERR_INVALID;
249 if (!pa_format_info_is_pcm(f))
250 return pa_format_info_to_sample_spec_fake(f, ss);
252 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
254 if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate))
256 if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels))
259 if ((ss->format = pa_parse_sample_format(sf)) == PA_SAMPLE_INVALID)
262 ss->rate = (uint32_t) rate;
263 ss->channels = (uint8_t) channels;
266 pa_channel_map_init(map);
268 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &m) == 0)
269 if (pa_channel_map_parse(map, m) == NULL)
284 pa_prop_type_t pa_format_info_get_prop_type(pa_format_info *f, const char *key) {
292 str = pa_proplist_gets(f->plist, key);
294 return PA_PROP_TYPE_INVALID;
296 o = json_tokener_parse(str);
298 return PA_PROP_TYPE_INVALID;
300 switch (json_object_get_type(o)) {
302 type = PA_PROP_TYPE_INT;
305 case json_type_string:
306 type = PA_PROP_TYPE_STRING;
309 case json_type_array:
310 if (json_object_array_length(o) == 0) {
311 /* Unlikely, but let's account for this anyway. We need at
312 * least one element to figure out the array type. */
313 type = PA_PROP_TYPE_INVALID;
317 o1 = json_object_array_get_idx(o, 1);
319 if (json_object_get_type(o1) == json_type_int)
320 type = PA_PROP_TYPE_INT_ARRAY;
321 else if (json_object_get_type(o1) == json_type_string)
322 type = PA_PROP_TYPE_STRING_ARRAY;
324 type = PA_PROP_TYPE_INVALID;
329 case json_type_object:
330 /* We actually know at this point that it's a int range, but let's
332 o1 = json_object_object_get(o, PA_JSON_MIN_KEY);
334 type = PA_PROP_TYPE_INVALID;
339 o1 = json_object_object_get(o, PA_JSON_MAX_KEY);
341 type = PA_PROP_TYPE_INVALID;
346 type = PA_PROP_TYPE_INT_RANGE;
350 type = PA_PROP_TYPE_INVALID;
358 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
366 str = pa_proplist_gets(f->plist, key);
368 return -PA_ERR_NOENTITY;
370 o = json_tokener_parse(str);
372 return -PA_ERR_INVALID;
374 if (json_object_get_type(o) != json_type_int) {
376 return -PA_ERR_INVALID;
379 *v = json_object_get_int(o);
385 int pa_format_info_get_prop_int_range(pa_format_info *f, const char *key, int *min, int *max) {
388 int ret = -PA_ERR_INVALID;
395 str = pa_proplist_gets(f->plist, key);
397 return -PA_ERR_NOENTITY;
399 o = json_tokener_parse(str);
401 return -PA_ERR_INVALID;
403 if (json_object_get_type(o) != json_type_object)
406 if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
409 *min = json_object_get_int(o1);
412 if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
415 *max = json_object_get_int(o1);
425 int pa_format_info_get_prop_int_array(pa_format_info *f, const char *key, int **values, int *n_values) {
428 int i, ret = -PA_ERR_INVALID;
435 str = pa_proplist_gets(f->plist, key);
437 return -PA_ERR_NOENTITY;
439 o = json_tokener_parse(str);
441 return -PA_ERR_INVALID;
443 if (json_object_get_type(o) != json_type_array)
446 *n_values = json_object_array_length(o);
447 *values = pa_xnew(int, *n_values);
449 for (i = 0; i < *n_values; i++) {
450 o1 = json_object_array_get_idx(o, i);
452 if (json_object_get_type(o1) != json_type_int) {
457 (*values)[i] = json_object_get_int(o1);
468 int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
469 const char *str = NULL;
476 str = pa_proplist_gets(f->plist, key);
478 return -PA_ERR_NOENTITY;
480 o = json_tokener_parse(str);
482 return -PA_ERR_INVALID;
484 if (json_object_get_type(o) != json_type_string) {
486 return -PA_ERR_INVALID;
489 *v = pa_xstrdup(json_object_get_string(o));
495 int pa_format_info_get_prop_string_array(pa_format_info *f, const char *key, char ***values, int *n_values) {
498 int i, ret = -PA_ERR_INVALID;
505 str = pa_proplist_gets(f->plist, key);
507 return -PA_ERR_NOENTITY;
509 o = json_tokener_parse(str);
511 return -PA_ERR_INVALID;
513 if (json_object_get_type(o) != json_type_array)
516 *n_values = json_object_array_length(o);
517 *values = pa_xnew(char *, *n_values);
519 for (i = 0; i < *n_values; i++) {
520 o1 = json_object_array_get_idx(o, i);
522 if (json_object_get_type(o1) != json_type_string) {
527 (*values)[i] = pa_xstrdup(json_object_get_string(o1));
538 void pa_format_info_free_string_array(char **values, int n_values) {
541 for (i = 0; i < n_values; i++)
547 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
548 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
551 void pa_format_info_set_rate(pa_format_info *f, int rate) {
552 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
555 void pa_format_info_set_channels(pa_format_info *f, int channels) {
556 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
559 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
560 char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
562 pa_channel_map_snprint(map_str, sizeof(map_str), map);
564 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
567 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
573 o = json_object_new_int(value);
575 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
580 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
587 o = json_object_new_array();
589 for (i = 0; i < n_values; i++)
590 json_object_array_add(o, json_object_new_int(values[i]));
592 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
597 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
603 o = json_object_new_object();
605 json_object_object_add(o, PA_JSON_MIN_KEY, json_object_new_int(min));
606 json_object_object_add(o, PA_JSON_MAX_KEY, json_object_new_int(max));
608 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
613 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
619 o = json_object_new_string(value);
621 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
626 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
633 o = json_object_new_array();
635 for (i = 0; i < n_values; i++)
636 json_object_array_add(o, json_object_new_string(values[i]));
638 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
643 static pa_bool_t pa_json_is_fixed_type(json_object *o) {
644 switch(json_object_get_type(o)) {
645 case json_type_object:
646 case json_type_array:
654 static int pa_json_value_equal(json_object *o1, json_object *o2) {
655 return (json_object_get_type(o1) == json_object_get_type(o2)) &&
656 pa_streq(json_object_to_json_string(o1), json_object_to_json_string(o2));
659 static int pa_format_info_prop_compatible(const char *one, const char *two) {
660 json_object *o1 = NULL, *o2 = NULL;
663 o1 = json_tokener_parse(one);
667 o2 = json_tokener_parse(two);
671 /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
672 pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), FALSE);
674 if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
675 ret = pa_json_value_equal(o1, o2);
679 if (pa_json_is_fixed_type(o1)) {
680 json_object *tmp = o2;
685 /* o2 is now a fixed type, and o1 is not */
687 if (json_object_get_type(o1) == json_type_array) {
688 for (i = 0; i < json_object_array_length(o1); i++) {
689 if (pa_json_value_equal(json_object_array_get_idx(o1, i), o2)) {
694 } else if (json_object_get_type(o1) == json_type_object) {
695 /* o1 should be a range type */
697 json_object *o_min = NULL, *o_max = NULL;
699 if (json_object_get_type(o2) != json_type_int) {
700 /* We don't support non-integer ranges */
704 o_min = json_object_object_get(o1, PA_JSON_MIN_KEY);
705 if (!o_min || json_object_get_type(o_min) != json_type_int)
708 o_max = json_object_object_get(o1, PA_JSON_MAX_KEY);
709 if (!o_max || json_object_get_type(o_max) != json_type_int)
712 v = json_object_get_int(o2);
713 min = json_object_get_int(o_min);
714 max = json_object_get_int(o_max);
716 ret = v >= min && v <= max;
718 pa_log_warn("Got a format type that we don't support");