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_ANY] = "any",
53 const char *pa_encoding_to_string(pa_encoding_t e) {
54 if (e < 0 || e >= PA_ENCODING_MAX)
57 return _encoding_str_table[e];
60 pa_encoding_t pa_encoding_from_string(const char *encoding) {
63 for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
64 if (pa_streq(_encoding_str_table[e], encoding))
67 return PA_ENCODING_INVALID;
70 pa_format_info* pa_format_info_new(void) {
71 pa_format_info *f = pa_xnew(pa_format_info, 1);
73 f->encoding = PA_ENCODING_INVALID;
74 f->plist = pa_proplist_new();
79 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
84 dest = pa_xnew(pa_format_info, 1);
86 dest->encoding = src->encoding;
89 dest->plist = pa_proplist_copy(src->plist);
96 void pa_format_info_free(pa_format_info *f) {
99 pa_proplist_free(f->plist);
103 void pa_format_info_free2(pa_format_info *f, void *userdata) {
104 pa_format_info_free(f);
107 int pa_format_info_valid(const pa_format_info *f) {
108 return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
111 int pa_format_info_is_pcm(const pa_format_info *f) {
112 return f->encoding == PA_ENCODING_PCM;
115 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
124 if (!pa_format_info_valid(f))
125 pa_snprintf(s, l, _("(invalid)"));
127 tmp = pa_proplist_to_string_sep(f->plist, " ");
129 pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
131 pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
138 pa_format_info* pa_format_info_from_string(const char *str) {
139 pa_format_info *f = pa_format_info_new();
140 char *encoding = NULL, *properties = NULL;
143 pos = strcspn(str, ",");
145 encoding = pa_xstrndup(str, pos);
146 f->encoding = pa_encoding_from_string(pa_strip(encoding));
147 if (f->encoding == PA_ENCODING_INVALID)
150 if (pos != strlen(str)) {
153 properties = pa_xstrdup(&str[pos+1]);
154 plist = pa_proplist_from_string(properties);
159 pa_proplist_free(f->plist);
167 pa_xfree(properties);
171 pa_format_info_free(f);
176 int pa_format_info_is_compatible(pa_format_info *first, pa_format_info *second) {
183 if (first->encoding != second->encoding)
186 while ((key = pa_proplist_iterate(first->plist, &state))) {
187 const char *value_one, *value_two;
189 value_one = pa_proplist_gets(first->plist, key);
190 value_two = pa_proplist_gets(second->plist, key);
192 if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
199 pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map) {
200 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
203 pa_assert(ss && pa_sample_spec_valid(ss));
204 pa_assert(!map || pa_channel_map_valid(map));
206 f = pa_format_info_new();
207 f->encoding = PA_ENCODING_PCM;
209 pa_format_info_set_sample_format(f, ss->format);
210 pa_format_info_set_rate(f, ss->rate);
211 pa_format_info_set_channels(f, ss->channels);
214 pa_channel_map_snprint(cm, sizeof(cm), map);
215 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
221 /* For compressed streams */
222 static int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
228 /* Note: When we add support for non-IEC61937 encapsulated compressed
229 * formats, this function should return a non-zero values for these. */
231 ss->format = PA_SAMPLE_S16LE;
234 pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
235 ss->rate = (uint32_t) rate;
237 if (f->encoding == PA_ENCODING_EAC3_IEC61937)
243 /* For PCM streams */
244 int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
245 char *sf = NULL, *m = NULL;
247 int ret = -PA_ERR_INVALID;
252 if (!pa_format_info_is_pcm(f))
253 return pa_format_info_to_sample_spec_fake(f, ss);
255 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
257 if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate))
259 if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels))
262 if ((ss->format = pa_parse_sample_format(sf)) == PA_SAMPLE_INVALID)
265 ss->rate = (uint32_t) rate;
266 ss->channels = (uint8_t) channels;
269 pa_channel_map_init(map);
271 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &m) == 0)
272 if (pa_channel_map_parse(map, m) == NULL)
287 pa_prop_type_t pa_format_info_get_prop_type(pa_format_info *f, const char *key) {
295 str = pa_proplist_gets(f->plist, key);
297 return PA_PROP_TYPE_INVALID;
299 o = json_tokener_parse(str);
301 return PA_PROP_TYPE_INVALID;
303 switch (json_object_get_type(o)) {
305 type = PA_PROP_TYPE_INT;
308 case json_type_string:
309 type = PA_PROP_TYPE_STRING;
312 case json_type_array:
313 if (json_object_array_length(o) == 0) {
314 /* Unlikely, but let's account for this anyway. We need at
315 * least one element to figure out the array type. */
316 type = PA_PROP_TYPE_INVALID;
320 o1 = json_object_array_get_idx(o, 1);
322 if (json_object_get_type(o1) == json_type_int)
323 type = PA_PROP_TYPE_INT_ARRAY;
324 else if (json_object_get_type(o1) == json_type_string)
325 type = PA_PROP_TYPE_STRING_ARRAY;
327 type = PA_PROP_TYPE_INVALID;
332 case json_type_object:
333 /* We actually know at this point that it's a int range, but let's
335 o1 = json_object_object_get(o, PA_JSON_MIN_KEY);
337 type = PA_PROP_TYPE_INVALID;
342 o1 = json_object_object_get(o, PA_JSON_MAX_KEY);
344 type = PA_PROP_TYPE_INVALID;
349 type = PA_PROP_TYPE_INT_RANGE;
353 type = PA_PROP_TYPE_INVALID;
361 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
369 str = pa_proplist_gets(f->plist, key);
371 return -PA_ERR_NOENTITY;
373 o = json_tokener_parse(str);
375 return -PA_ERR_INVALID;
377 if (json_object_get_type(o) != json_type_int) {
379 return -PA_ERR_INVALID;
382 *v = json_object_get_int(o);
388 int pa_format_info_get_prop_int_range(pa_format_info *f, const char *key, int *min, int *max) {
391 int ret = -PA_ERR_INVALID;
398 str = pa_proplist_gets(f->plist, key);
400 return -PA_ERR_NOENTITY;
402 o = json_tokener_parse(str);
404 return -PA_ERR_INVALID;
406 if (json_object_get_type(o) != json_type_object)
409 if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
412 *min = json_object_get_int(o1);
415 if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
418 *max = json_object_get_int(o1);
428 int pa_format_info_get_prop_int_array(pa_format_info *f, const char *key, int **values, int *n_values)
432 int i, ret = -PA_ERR_INVALID;
439 str = pa_proplist_gets(f->plist, key);
441 return -PA_ERR_NOENTITY;
443 o = json_tokener_parse(str);
445 return -PA_ERR_INVALID;
447 if (json_object_get_type(o) != json_type_array)
450 *n_values = json_object_array_length(o);
451 *values = pa_xnew(int, *n_values);
453 for (i = 0; i < *n_values; i++) {
454 o1 = json_object_array_get_idx(o, i);
456 if (json_object_get_type(o1) != json_type_int) {
461 (*values)[i] = json_object_get_int(o1);
472 int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
473 const char *str = NULL;
480 str = pa_proplist_gets(f->plist, key);
482 return -PA_ERR_NOENTITY;
484 o = json_tokener_parse(str);
486 return -PA_ERR_INVALID;
488 if (json_object_get_type(o) != json_type_string) {
490 return -PA_ERR_INVALID;
493 *v = pa_xstrdup(json_object_get_string(o));
499 int pa_format_info_get_prop_string_array(pa_format_info *f, const char *key, char ***values, int *n_values)
503 int i, ret = -PA_ERR_INVALID;
510 str = pa_proplist_gets(f->plist, key);
512 return -PA_ERR_NOENTITY;
514 o = json_tokener_parse(str);
516 return -PA_ERR_INVALID;
518 if (json_object_get_type(o) != json_type_array)
521 *n_values = json_object_array_length(o);
522 *values = pa_xnew(char *, *n_values);
524 for (i = 0; i < *n_values; i++) {
525 o1 = json_object_array_get_idx(o, i);
527 if (json_object_get_type(o1) != json_type_string) {
532 (*values)[i] = pa_xstrdup(json_object_get_string(o1));
543 void pa_format_info_free_string_array(char **values, int n_values) {
546 for (i = 0; i < n_values; i++)
552 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
553 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
556 void pa_format_info_set_rate(pa_format_info *f, int rate) {
557 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
560 void pa_format_info_set_channels(pa_format_info *f, int channels) {
561 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
564 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
565 char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
567 pa_channel_map_snprint(map_str, sizeof(map_str), map);
569 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
572 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
578 o = json_object_new_int(value);
580 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
585 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
592 o = json_object_new_array();
594 for (i = 0; i < n_values; i++)
595 json_object_array_add(o, json_object_new_int(values[i]));
597 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
602 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
608 o = json_object_new_object();
610 json_object_object_add(o, PA_JSON_MIN_KEY, json_object_new_int(min));
611 json_object_object_add(o, PA_JSON_MAX_KEY, json_object_new_int(max));
613 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
618 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
624 o = json_object_new_string(value);
626 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
631 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
638 o = json_object_new_array();
640 for (i = 0; i < n_values; i++)
641 json_object_array_add(o, json_object_new_string(values[i]));
643 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
648 static pa_bool_t pa_json_is_fixed_type(json_object *o)
650 switch(json_object_get_type(o)) {
651 case json_type_object:
652 case json_type_array:
660 static int pa_json_value_equal(json_object *o1, json_object *o2) {
661 return (json_object_get_type(o1) == json_object_get_type(o2)) &&
662 pa_streq(json_object_to_json_string(o1), json_object_to_json_string(o2));
665 static int pa_format_info_prop_compatible(const char *one, const char *two) {
666 json_object *o1 = NULL, *o2 = NULL;
669 o1 = json_tokener_parse(one);
673 o2 = json_tokener_parse(two);
677 /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
678 pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), FALSE);
680 if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
681 ret = pa_json_value_equal(o1, o2);
685 if (pa_json_is_fixed_type(o1)) {
686 json_object *tmp = o2;
691 /* o2 is now a fixed type, and o1 is not */
693 if (json_object_get_type(o1) == json_type_array) {
694 for (i = 0; i < json_object_array_length(o1); i++) {
695 if (pa_json_value_equal(json_object_array_get_idx(o1, i), o2)) {
700 } else if (json_object_get_type(o1) == json_type_object) {
701 /* o1 should be a range type */
703 json_object *o_min = NULL, *o_max = NULL;
705 if (json_object_get_type(o2) != json_type_int) {
706 /* We don't support non-integer ranges */
710 o_min = json_object_object_get(o1, PA_JSON_MIN_KEY);
711 if (!o_min || json_object_get_type(o_min) != json_type_int)
714 o_max = json_object_object_get(o1, PA_JSON_MAX_KEY);
715 if (!o_max || json_object_get_type(o_max) != json_type_int)
718 v = json_object_get_int(o2);
719 min = json_object_get_int(o_min);
720 max = json_object_get_int(o_max);
722 ret = v >= min && v <= max;
724 pa_log_warn("Got a format type that we don't support");