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-format.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/i18n.h>
36 #include <pulsecore/macro.h>
40 #define PA_JSON_MIN_KEY "min"
41 #define PA_JSON_MAX_KEY "max"
43 static int pa_format_info_prop_compatible(const char *one, const char *two);
45 static const char* const _encoding_str_table[]= {
46 [PA_ENCODING_PCM] = "pcm",
47 [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
48 [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
49 [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
50 [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
51 [PA_ENCODING_MPEG2_AAC_IEC61937] = "mpeg2-aac-iec61937",
52 [PA_ENCODING_ANY] = "any",
55 const char *pa_encoding_to_string(pa_encoding_t e) {
56 if (e < 0 || e >= PA_ENCODING_MAX)
59 return _encoding_str_table[e];
62 pa_encoding_t pa_encoding_from_string(const char *encoding) {
65 for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
66 if (pa_streq(_encoding_str_table[e], encoding))
69 return PA_ENCODING_INVALID;
72 pa_format_info* pa_format_info_new(void) {
73 pa_format_info *f = pa_xnew(pa_format_info, 1);
75 f->encoding = PA_ENCODING_INVALID;
76 f->plist = pa_proplist_new();
81 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
86 dest = pa_xnew(pa_format_info, 1);
88 dest->encoding = src->encoding;
91 dest->plist = pa_proplist_copy(src->plist);
98 void pa_format_info_free(pa_format_info *f) {
101 pa_proplist_free(f->plist);
105 int pa_format_info_valid(const pa_format_info *f) {
106 return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
109 int pa_format_info_is_pcm(const pa_format_info *f) {
110 return f->encoding == PA_ENCODING_PCM;
113 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
122 if (!pa_format_info_valid(f))
123 pa_snprintf(s, l, _("(invalid)"));
125 tmp = pa_proplist_to_string_sep(f->plist, " ");
127 pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
129 pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
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;
141 pos = strcspn(str, ",");
143 encoding = pa_xstrndup(str, pos);
144 f->encoding = pa_encoding_from_string(pa_strip(encoding));
145 if (f->encoding == PA_ENCODING_INVALID)
148 if (pos != strlen(str)) {
151 properties = pa_xstrdup(&str[pos+1]);
152 plist = pa_proplist_from_string(properties);
157 pa_proplist_free(f->plist);
165 pa_xfree(properties);
169 pa_format_info_free(f);
174 int pa_format_info_is_compatible(const pa_format_info *first, const pa_format_info *second) {
181 if (first->encoding != second->encoding)
184 while ((key = pa_proplist_iterate(first->plist, &state))) {
185 const char *value_one, *value_two;
187 value_one = pa_proplist_gets(first->plist, key);
188 value_two = pa_proplist_gets(second->plist, key);
190 if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
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];
201 pa_assert(ss && pa_sample_spec_valid(ss));
202 pa_assert(!map || pa_channel_map_valid(map));
204 f = pa_format_info_new();
205 f->encoding = PA_ENCODING_PCM;
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);
212 pa_channel_map_snprint(cm, sizeof(cm), map);
213 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
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) {
224 if (!pa_format_info_is_pcm(f))
225 return pa_format_info_to_sample_spec_fake(f, ss, map);
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;
239 pa_prop_type_t pa_format_info_get_prop_type(const pa_format_info *f, const char *key) {
247 str = pa_proplist_gets(f->plist, key);
249 return PA_PROP_TYPE_INVALID;
251 o = json_tokener_parse(str);
253 return PA_PROP_TYPE_INVALID;
255 switch (json_object_get_type(o)) {
257 type = PA_PROP_TYPE_INT;
260 case json_type_string:
261 type = PA_PROP_TYPE_STRING;
264 case json_type_array:
265 if (json_object_array_length(o) == 0) {
266 /* Unlikely, but let's account for this anyway. We need at
267 * least one element to figure out the array type. */
268 type = PA_PROP_TYPE_INVALID;
272 o1 = json_object_array_get_idx(o, 1);
274 if (json_object_get_type(o1) == json_type_int)
275 type = PA_PROP_TYPE_INT_ARRAY;
276 else if (json_object_get_type(o1) == json_type_string)
277 type = PA_PROP_TYPE_STRING_ARRAY;
279 type = PA_PROP_TYPE_INVALID;
283 case json_type_object:
284 /* We actually know at this point that it's a int range, but let's
286 o1 = json_object_object_get(o, PA_JSON_MIN_KEY);
288 type = PA_PROP_TYPE_INVALID;
292 o1 = json_object_object_get(o, PA_JSON_MAX_KEY);
294 type = PA_PROP_TYPE_INVALID;
298 type = PA_PROP_TYPE_INT_RANGE;
302 type = PA_PROP_TYPE_INVALID;
310 int pa_format_info_get_prop_int(const pa_format_info *f, const char *key, int *v) {
318 str = pa_proplist_gets(f->plist, key);
320 return -PA_ERR_NOENTITY;
322 o = json_tokener_parse(str);
324 pa_log_debug("Failed to parse format info property '%s'.", key);
325 return -PA_ERR_INVALID;
328 if (json_object_get_type(o) != json_type_int) {
329 pa_log_debug("Format info property '%s' type is not int.", key);
331 return -PA_ERR_INVALID;
334 *v = json_object_get_int(o);
340 int pa_format_info_get_prop_int_range(const pa_format_info *f, const char *key, int *min, int *max) {
343 int ret = -PA_ERR_INVALID;
350 str = pa_proplist_gets(f->plist, key);
352 return -PA_ERR_NOENTITY;
354 o = json_tokener_parse(str);
356 pa_log_debug("Failed to parse format info property '%s'.", key);
357 return -PA_ERR_INVALID;
360 if (json_object_get_type(o) != json_type_object)
363 if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
366 *min = json_object_get_int(o1);
368 if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
371 *max = json_object_get_int(o1);
377 pa_log_debug("Format info property '%s' is not a valid int range.", key);
383 int pa_format_info_get_prop_int_array(const pa_format_info *f, const char *key, int **values, int *n_values) {
386 int i, ret = -PA_ERR_INVALID;
393 str = pa_proplist_gets(f->plist, key);
395 return -PA_ERR_NOENTITY;
397 o = json_tokener_parse(str);
399 pa_log_debug("Failed to parse format info property '%s'.", key);
400 return -PA_ERR_INVALID;
403 if (json_object_get_type(o) != json_type_array)
406 *n_values = json_object_array_length(o);
407 *values = pa_xnew(int, *n_values);
409 for (i = 0; i < *n_values; i++) {
410 o1 = json_object_array_get_idx(o, i);
412 if (json_object_get_type(o1) != json_type_int) {
416 (*values)[i] = json_object_get_int(o1);
423 pa_log_debug("Format info property '%s' is not a valid int array.", key);
429 int pa_format_info_get_prop_string(const pa_format_info *f, const char *key, char **v) {
430 const char *str = NULL;
437 str = pa_proplist_gets(f->plist, key);
439 return -PA_ERR_NOENTITY;
441 o = json_tokener_parse(str);
443 pa_log_debug("Failed to parse format info property '%s'.", key);
444 return -PA_ERR_INVALID;
447 if (json_object_get_type(o) != json_type_string) {
448 pa_log_debug("Format info property '%s' type is not string.", key);
450 return -PA_ERR_INVALID;
453 *v = pa_xstrdup(json_object_get_string(o));
459 int pa_format_info_get_prop_string_array(const pa_format_info *f, const char *key, char ***values, int *n_values) {
462 int i, ret = -PA_ERR_INVALID;
469 str = pa_proplist_gets(f->plist, key);
471 return -PA_ERR_NOENTITY;
473 o = json_tokener_parse(str);
475 pa_log_debug("Failed to parse format info property '%s'.", key);
476 return -PA_ERR_INVALID;
479 if (json_object_get_type(o) != json_type_array)
482 *n_values = json_object_array_length(o);
483 *values = pa_xnew(char *, *n_values);
485 for (i = 0; i < *n_values; i++) {
486 o1 = json_object_array_get_idx(o, i);
488 if (json_object_get_type(o1) != json_type_string) {
492 (*values)[i] = pa_xstrdup(json_object_get_string(o1));
499 pa_log_debug("Format info property '%s' is not a valid string array.", key);
505 void pa_format_info_free_string_array(char **values, int n_values) {
508 for (i = 0; i < n_values; i++)
514 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
515 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
518 void pa_format_info_set_rate(pa_format_info *f, int rate) {
519 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
522 void pa_format_info_set_channels(pa_format_info *f, int channels) {
523 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
526 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
527 char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
529 pa_channel_map_snprint(map_str, sizeof(map_str), map);
531 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
534 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
540 o = json_object_new_int(value);
542 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
547 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
554 o = json_object_new_array();
556 for (i = 0; i < n_values; i++)
557 json_object_array_add(o, json_object_new_int(values[i]));
559 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
564 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
570 o = json_object_new_object();
572 json_object_object_add(o, PA_JSON_MIN_KEY, json_object_new_int(min));
573 json_object_object_add(o, PA_JSON_MAX_KEY, json_object_new_int(max));
575 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
580 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
586 o = json_object_new_string(value);
588 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
593 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
600 o = json_object_new_array();
602 for (i = 0; i < n_values; i++)
603 json_object_array_add(o, json_object_new_string(values[i]));
605 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
610 static bool pa_json_is_fixed_type(json_object *o) {
611 switch(json_object_get_type(o)) {
612 case json_type_object:
613 case json_type_array:
621 static int pa_json_value_equal(json_object *o1, json_object *o2) {
622 return (json_object_get_type(o1) == json_object_get_type(o2)) &&
623 pa_streq(json_object_to_json_string(o1), json_object_to_json_string(o2));
626 static int pa_format_info_prop_compatible(const char *one, const char *two) {
627 json_object *o1 = NULL, *o2 = NULL;
630 o1 = json_tokener_parse(one);
634 o2 = json_tokener_parse(two);
638 /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
639 pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), false);
641 if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
642 ret = pa_json_value_equal(o1, o2);
646 if (pa_json_is_fixed_type(o1)) {
647 json_object *tmp = o2;
652 /* o2 is now a fixed type, and o1 is not */
654 if (json_object_get_type(o1) == json_type_array) {
655 for (i = 0; i < json_object_array_length(o1); i++) {
656 if (pa_json_value_equal(json_object_array_get_idx(o1, i), o2)) {
661 } else if (json_object_get_type(o1) == json_type_object) {
662 /* o1 should be a range type */
664 json_object *o_min = NULL, *o_max = NULL;
666 if (json_object_get_type(o2) != json_type_int) {
667 /* We don't support non-integer ranges */
671 o_min = json_object_object_get(o1, PA_JSON_MIN_KEY);
672 if (!o_min || json_object_get_type(o_min) != json_type_int)
675 o_max = json_object_object_get(o1, PA_JSON_MAX_KEY);
676 if (!o_max || json_object_get_type(o_max) != json_type_int)
679 v = json_object_get_int(o2);
680 min = json_object_get_int(o_min);
681 max = json_object_get_int(o_max);
683 ret = v >= min && v <= max;
685 pa_log_warn("Got a format type that we don't support");