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 PCM streams */
222 int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
223 char *sf = NULL, *m = NULL;
225 int ret = -PA_ERR_INVALID;
229 pa_return_val_if_fail(f->encoding == PA_ENCODING_PCM, FALSE);
231 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
233 if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate))
235 if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels))
238 if ((ss->format = pa_parse_sample_format(sf)) == PA_SAMPLE_INVALID)
241 ss->rate = (uint32_t) rate;
242 ss->channels = (uint8_t) channels;
245 pa_channel_map_init(map);
247 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &m) == 0)
248 if (pa_channel_map_parse(map, m) == NULL)
263 /* For compressed streams */
264 int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
269 pa_return_val_if_fail(f->encoding != PA_ENCODING_PCM, -PA_ERR_INVALID);
271 ss->format = PA_SAMPLE_S16LE;
274 pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
275 ss->rate = (uint32_t) rate;
277 if (f->encoding == PA_ENCODING_EAC3_IEC61937)
283 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
291 str = pa_proplist_gets(f->plist, key);
293 return -PA_ERR_NOENTITY;
295 o = json_tokener_parse(str);
297 return -PA_ERR_INVALID;
299 if (json_object_get_type(o) != json_type_int) {
301 return -PA_ERR_INVALID;
304 *v = json_object_get_int(o);
310 int pa_format_info_get_prop_int_range(pa_format_info *f, const char *key, int *min, int *max) {
313 int ret = -PA_ERR_INVALID;
320 str = pa_proplist_gets(f->plist, key);
322 return -PA_ERR_NOENTITY;
324 o = json_tokener_parse(str);
326 return -PA_ERR_INVALID;
328 if (json_object_get_type(o) != json_type_object)
331 if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
334 *min = json_object_get_int(o1);
337 if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
340 *max = json_object_get_int(o1);
350 int pa_format_info_get_prop_int_array(pa_format_info *f, const char *key, int **values, int *n_values)
354 int i, ret = -PA_ERR_INVALID;
361 str = pa_proplist_gets(f->plist, key);
363 return -PA_ERR_NOENTITY;
365 o = json_tokener_parse(str);
367 return -PA_ERR_INVALID;
369 if (json_object_get_type(o) != json_type_array)
372 *n_values = json_object_array_length(o);
373 *values = pa_xnew(int, *n_values);
375 for (i = 0; i < *n_values; i++) {
376 o1 = json_object_array_get_idx(o, i);
378 if (json_object_get_type(o1) != json_type_int) {
383 (*values)[i] = json_object_get_int(o1);
394 int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
395 const char *str = NULL;
402 str = pa_proplist_gets(f->plist, key);
404 return -PA_ERR_NOENTITY;
406 o = json_tokener_parse(str);
408 return -PA_ERR_INVALID;
410 if (json_object_get_type(o) != json_type_string) {
412 return -PA_ERR_INVALID;
415 *v = pa_xstrdup(json_object_get_string(o));
421 int pa_format_info_get_prop_string_array(pa_format_info *f, const char *key, char ***values, int *n_values)
425 int i, ret = -PA_ERR_INVALID;
432 str = pa_proplist_gets(f->plist, key);
434 return -PA_ERR_NOENTITY;
436 o = json_tokener_parse(str);
438 return -PA_ERR_INVALID;
440 if (json_object_get_type(o) != json_type_array)
443 *n_values = json_object_array_length(o);
444 *values = pa_xnew(char *, *n_values);
446 for (i = 0; i < *n_values; i++) {
447 o1 = json_object_array_get_idx(o, i);
449 if (json_object_get_type(o1) != json_type_string) {
454 (*values)[i] = pa_xstrdup(json_object_get_string(o1));
465 void pa_format_info_free_string_array(char **values, int n_values) {
468 for (i = 0; i < n_values; i++)
474 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
475 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
478 void pa_format_info_set_rate(pa_format_info *f, int rate) {
479 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
482 void pa_format_info_set_channels(pa_format_info *f, int channels) {
483 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
486 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
487 char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
489 pa_channel_map_snprint(map_str, sizeof(map_str), map);
491 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
494 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
500 o = json_object_new_int(value);
502 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
507 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
514 o = json_object_new_array();
516 for (i = 0; i < n_values; i++)
517 json_object_array_add(o, json_object_new_int(values[i]));
519 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
524 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
530 o = json_object_new_object();
532 json_object_object_add(o, PA_JSON_MIN_KEY, json_object_new_int(min));
533 json_object_object_add(o, PA_JSON_MAX_KEY, json_object_new_int(max));
535 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
540 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
546 o = json_object_new_string(value);
548 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
553 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
560 o = json_object_new_array();
562 for (i = 0; i < n_values; i++)
563 json_object_array_add(o, json_object_new_string(values[i]));
565 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
570 static pa_bool_t pa_json_is_fixed_type(json_object *o)
572 switch(json_object_get_type(o)) {
573 case json_type_object:
574 case json_type_array:
582 static int pa_json_value_equal(json_object *o1, json_object *o2) {
583 return (json_object_get_type(o1) == json_object_get_type(o2)) &&
584 pa_streq(json_object_to_json_string(o1), json_object_to_json_string(o2));
587 static int pa_format_info_prop_compatible(const char *one, const char *two) {
588 json_object *o1 = NULL, *o2 = NULL;
591 o1 = json_tokener_parse(one);
595 o2 = json_tokener_parse(two);
599 /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
600 pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), FALSE);
602 if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
603 ret = pa_json_value_equal(o1, o2);
607 if (pa_json_is_fixed_type(o1)) {
608 json_object *tmp = o2;
613 /* o2 is now a fixed type, and o1 is not */
615 if (json_object_get_type(o1) == json_type_array) {
616 for (i = 0; i < json_object_array_length(o1); i++) {
617 if (pa_json_value_equal(json_object_array_get_idx(o1, i), o2)) {
622 } else if (json_object_get_type(o1) == json_type_object) {
623 /* o1 should be a range type */
625 json_object *o_min = NULL, *o_max = NULL;
627 if (json_object_get_type(o2) != json_type_int) {
628 /* We don't support non-integer ranges */
632 o_min = json_object_object_get(o1, PA_JSON_MIN_KEY);
633 if (!o_min || json_object_get_type(o_min) != json_type_int)
636 o_max = json_object_object_get(o1, PA_JSON_MAX_KEY);
637 if (!o_max || json_object_get_type(o_max) != json_type_int)
640 v = json_object_get_int(o2);
641 min = json_object_get_int(o_min);
642 max = json_object_get_int(o_max);
644 ret = v >= min && v <= max;
646 pa_log_warn("Got a format type that we don't support");