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(pa_format_info
*first
, 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(pa_sample_spec
*ss
, 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(pa_format_info
*f
, pa_sample_spec
*ss
, pa_channel_map
*map
) {
223 int ret
= -PA_ERR_INVALID
;
228 if (!pa_format_info_is_pcm(f
))
229 return pa_format_info_to_sample_spec_fake(f
, ss
, map
);
231 if (pa_format_info_get_sample_format(f
, &ss
->format
) < 0)
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 ss
->rate
= (uint32_t) rate
;
239 ss
->channels
= (uint8_t) channels
;
242 pa_channel_map_init(map
);
244 if (pa_format_info_get_prop_string(f
, PA_PROP_FORMAT_CHANNEL_MAP
, &m
) == 0)
245 if (pa_channel_map_parse(map
, m
) == NULL
)
258 pa_prop_type_t
pa_format_info_get_prop_type(pa_format_info
*f
, const char *key
) {
266 str
= pa_proplist_gets(f
->plist
, key
);
268 return PA_PROP_TYPE_INVALID
;
270 o
= json_tokener_parse(str
);
272 return PA_PROP_TYPE_INVALID
;
274 switch (json_object_get_type(o
)) {
276 type
= PA_PROP_TYPE_INT
;
279 case json_type_string
:
280 type
= PA_PROP_TYPE_STRING
;
283 case json_type_array
:
284 if (json_object_array_length(o
) == 0) {
285 /* Unlikely, but let's account for this anyway. We need at
286 * least one element to figure out the array type. */
287 type
= PA_PROP_TYPE_INVALID
;
291 o1
= json_object_array_get_idx(o
, 1);
293 if (json_object_get_type(o1
) == json_type_int
)
294 type
= PA_PROP_TYPE_INT_ARRAY
;
295 else if (json_object_get_type(o1
) == json_type_string
)
296 type
= PA_PROP_TYPE_STRING_ARRAY
;
298 type
= PA_PROP_TYPE_INVALID
;
303 case json_type_object
:
304 /* We actually know at this point that it's a int range, but let's
306 o1
= json_object_object_get(o
, PA_JSON_MIN_KEY
);
308 type
= PA_PROP_TYPE_INVALID
;
313 o1
= json_object_object_get(o
, PA_JSON_MAX_KEY
);
315 type
= PA_PROP_TYPE_INVALID
;
320 type
= PA_PROP_TYPE_INT_RANGE
;
324 type
= PA_PROP_TYPE_INVALID
;
332 int pa_format_info_get_prop_int(pa_format_info
*f
, const char *key
, int *v
) {
340 str
= pa_proplist_gets(f
->plist
, key
);
342 return -PA_ERR_NOENTITY
;
344 o
= json_tokener_parse(str
);
346 return -PA_ERR_INVALID
;
348 if (json_object_get_type(o
) != json_type_int
) {
350 return -PA_ERR_INVALID
;
353 *v
= json_object_get_int(o
);
359 int pa_format_info_get_prop_int_range(pa_format_info
*f
, const char *key
, int *min
, int *max
) {
362 int ret
= -PA_ERR_INVALID
;
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_object
)
380 if (!(o1
= json_object_object_get(o
, PA_JSON_MIN_KEY
)))
383 *min
= json_object_get_int(o1
);
386 if (!(o1
= json_object_object_get(o
, PA_JSON_MAX_KEY
)))
389 *max
= json_object_get_int(o1
);
399 int pa_format_info_get_prop_int_array(pa_format_info
*f
, const char *key
, int **values
, int *n_values
) {
402 int i
, ret
= -PA_ERR_INVALID
;
409 str
= pa_proplist_gets(f
->plist
, key
);
411 return -PA_ERR_NOENTITY
;
413 o
= json_tokener_parse(str
);
415 return -PA_ERR_INVALID
;
417 if (json_object_get_type(o
) != json_type_array
)
420 *n_values
= json_object_array_length(o
);
421 *values
= pa_xnew(int, *n_values
);
423 for (i
= 0; i
< *n_values
; i
++) {
424 o1
= json_object_array_get_idx(o
, i
);
426 if (json_object_get_type(o1
) != json_type_int
) {
431 (*values
)[i
] = json_object_get_int(o1
);
442 int pa_format_info_get_prop_string(pa_format_info
*f
, const char *key
, char **v
) {
443 const char *str
= NULL
;
450 str
= pa_proplist_gets(f
->plist
, key
);
452 return -PA_ERR_NOENTITY
;
454 o
= json_tokener_parse(str
);
456 return -PA_ERR_INVALID
;
458 if (json_object_get_type(o
) != json_type_string
) {
460 return -PA_ERR_INVALID
;
463 *v
= pa_xstrdup(json_object_get_string(o
));
469 int pa_format_info_get_prop_string_array(pa_format_info
*f
, const char *key
, char ***values
, int *n_values
) {
472 int i
, ret
= -PA_ERR_INVALID
;
479 str
= pa_proplist_gets(f
->plist
, key
);
481 return -PA_ERR_NOENTITY
;
483 o
= json_tokener_parse(str
);
485 return -PA_ERR_INVALID
;
487 if (json_object_get_type(o
) != json_type_array
)
490 *n_values
= json_object_array_length(o
);
491 *values
= pa_xnew(char *, *n_values
);
493 for (i
= 0; i
< *n_values
; i
++) {
494 o1
= json_object_array_get_idx(o
, i
);
496 if (json_object_get_type(o1
) != json_type_string
) {
501 (*values
)[i
] = pa_xstrdup(json_object_get_string(o1
));
512 void pa_format_info_free_string_array(char **values
, int n_values
) {
515 for (i
= 0; i
< n_values
; i
++)
521 void pa_format_info_set_sample_format(pa_format_info
*f
, pa_sample_format_t sf
) {
522 pa_format_info_set_prop_string(f
, PA_PROP_FORMAT_SAMPLE_FORMAT
, pa_sample_format_to_string(sf
));
525 void pa_format_info_set_rate(pa_format_info
*f
, int rate
) {
526 pa_format_info_set_prop_int(f
, PA_PROP_FORMAT_RATE
, rate
);
529 void pa_format_info_set_channels(pa_format_info
*f
, int channels
) {
530 pa_format_info_set_prop_int(f
, PA_PROP_FORMAT_CHANNELS
, channels
);
533 void pa_format_info_set_channel_map(pa_format_info
*f
, const pa_channel_map
*map
) {
534 char map_str
[PA_CHANNEL_MAP_SNPRINT_MAX
];
536 pa_channel_map_snprint(map_str
, sizeof(map_str
), map
);
538 pa_format_info_set_prop_string(f
, PA_PROP_FORMAT_CHANNEL_MAP
, map_str
);
541 void pa_format_info_set_prop_int(pa_format_info
*f
, const char *key
, int value
) {
547 o
= json_object_new_int(value
);
549 pa_proplist_sets(f
->plist
, key
, json_object_to_json_string(o
));
554 void pa_format_info_set_prop_int_array(pa_format_info
*f
, const char *key
, const int *values
, int n_values
) {
561 o
= json_object_new_array();
563 for (i
= 0; i
< n_values
; i
++)
564 json_object_array_add(o
, json_object_new_int(values
[i
]));
566 pa_proplist_sets(f
->plist
, key
, json_object_to_json_string(o
));
571 void pa_format_info_set_prop_int_range(pa_format_info
*f
, const char *key
, int min
, int max
) {
577 o
= json_object_new_object();
579 json_object_object_add(o
, PA_JSON_MIN_KEY
, json_object_new_int(min
));
580 json_object_object_add(o
, PA_JSON_MAX_KEY
, json_object_new_int(max
));
582 pa_proplist_sets(f
->plist
, key
, json_object_to_json_string(o
));
587 void pa_format_info_set_prop_string(pa_format_info
*f
, const char *key
, const char *value
) {
593 o
= json_object_new_string(value
);
595 pa_proplist_sets(f
->plist
, key
, json_object_to_json_string(o
));
600 void pa_format_info_set_prop_string_array(pa_format_info
*f
, const char *key
, const char **values
, int n_values
) {
607 o
= json_object_new_array();
609 for (i
= 0; i
< n_values
; i
++)
610 json_object_array_add(o
, json_object_new_string(values
[i
]));
612 pa_proplist_sets(f
->plist
, key
, json_object_to_json_string(o
));
617 static bool pa_json_is_fixed_type(json_object
*o
) {
618 switch(json_object_get_type(o
)) {
619 case json_type_object
:
620 case json_type_array
:
628 static int pa_json_value_equal(json_object
*o1
, json_object
*o2
) {
629 return (json_object_get_type(o1
) == json_object_get_type(o2
)) &&
630 pa_streq(json_object_to_json_string(o1
), json_object_to_json_string(o2
));
633 static int pa_format_info_prop_compatible(const char *one
, const char *two
) {
634 json_object
*o1
= NULL
, *o2
= NULL
;
637 o1
= json_tokener_parse(one
);
641 o2
= json_tokener_parse(two
);
645 /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
646 pa_return_val_if_fail(pa_json_is_fixed_type(o1
) || pa_json_is_fixed_type(o2
), false);
648 if (pa_json_is_fixed_type(o1
) && pa_json_is_fixed_type(o2
)) {
649 ret
= pa_json_value_equal(o1
, o2
);
653 if (pa_json_is_fixed_type(o1
)) {
654 json_object
*tmp
= o2
;
659 /* o2 is now a fixed type, and o1 is not */
661 if (json_object_get_type(o1
) == json_type_array
) {
662 for (i
= 0; i
< json_object_array_length(o1
); i
++) {
663 if (pa_json_value_equal(json_object_array_get_idx(o1
, i
), o2
)) {
668 } else if (json_object_get_type(o1
) == json_type_object
) {
669 /* o1 should be a range type */
671 json_object
*o_min
= NULL
, *o_max
= NULL
;
673 if (json_object_get_type(o2
) != json_type_int
) {
674 /* We don't support non-integer ranges */
678 o_min
= json_object_object_get(o1
, PA_JSON_MIN_KEY
);
679 if (!o_min
|| json_object_get_type(o_min
) != json_type_int
)
682 o_max
= json_object_object_get(o1
, PA_JSON_MAX_KEY
);
683 if (!o_max
|| json_object_get_type(o_max
) != json_type_int
)
686 v
= json_object_get_int(o2
);
687 min
= json_object_get_int(o_min
);
688 max
= json_object_get_int(o_max
);
690 ret
= v
>= min
&& v
<= max
;
692 pa_log_warn("Got a format type that we don't support");