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 const char *pa_encoding_to_string(pa_encoding_t e) {
45 static const char* const 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_ANY] = "any",
54 if (e < 0 || e >= PA_ENCODING_MAX)
60 pa_format_info* pa_format_info_new(void) {
61 pa_format_info *f = pa_xnew(pa_format_info, 1);
63 f->encoding = PA_ENCODING_INVALID;
64 f->plist = pa_proplist_new();
69 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
74 dest = pa_xnew(pa_format_info, 1);
76 dest->encoding = src->encoding;
79 dest->plist = pa_proplist_copy(src->plist);
86 void pa_format_info_free(pa_format_info *f) {
89 pa_proplist_free(f->plist);
93 void pa_format_info_free2(pa_format_info *f, void *userdata) {
94 pa_format_info_free(f);
97 int pa_format_info_valid(const pa_format_info *f) {
98 return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
101 int pa_format_info_is_pcm(const pa_format_info *f) {
102 return f->encoding == PA_ENCODING_PCM;
105 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
114 if (!pa_format_info_valid(f))
115 pa_snprintf(s, l, _("(invalid)"));
117 tmp = pa_proplist_to_string_sep(f->plist, " ");
119 pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
121 pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
128 int pa_format_info_is_compatible(pa_format_info *first, pa_format_info *second) {
135 if (first->encoding != second->encoding)
138 while ((key = pa_proplist_iterate(first->plist, &state))) {
139 const char *value_one, *value_two;
141 value_one = pa_proplist_gets(first->plist, key);
142 value_two = pa_proplist_gets(second->plist, key);
144 if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
151 pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map) {
152 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
155 pa_assert(ss && pa_sample_spec_valid(ss));
156 pa_assert(!map || pa_channel_map_valid(map));
158 f = pa_format_info_new();
159 f->encoding = PA_ENCODING_PCM;
161 pa_format_info_set_sample_format(f, ss->format);
162 pa_format_info_set_rate(f, ss->rate);
163 pa_format_info_set_channels(f, ss->channels);
166 pa_channel_map_snprint(cm, sizeof(cm), map);
167 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
173 /* For PCM streams */
174 pa_bool_t pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
175 char *sf = NULL, *m = NULL;
177 pa_bool_t ret = FALSE;
181 pa_return_val_if_fail(f->encoding == PA_ENCODING_PCM, FALSE);
183 if (!pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
185 if (!pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate))
187 if (!pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels))
190 if ((ss->format = pa_parse_sample_format(sf)) == PA_SAMPLE_INVALID)
193 ss->rate = (uint32_t) rate;
194 ss->channels = (uint8_t) channels;
197 pa_channel_map_init(map);
199 if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &m))
200 if (pa_channel_map_parse(map, m) == NULL)
215 /* For compressed streams */
216 pa_bool_t pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
221 pa_return_val_if_fail(f->encoding != PA_ENCODING_PCM, FALSE);
223 ss->format = PA_SAMPLE_S16LE;
226 pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate), FALSE);
227 ss->rate = (uint32_t) rate;
229 if (f->encoding == PA_ENCODING_EAC3_IEC61937)
235 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
236 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
239 void pa_format_info_set_rate(pa_format_info *f, int rate) {
240 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
243 void pa_format_info_set_channels(pa_format_info *f, int channels) {
244 pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
247 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
248 char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
250 pa_channel_map_snprint(map_str, sizeof(map_str), map);
252 pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
255 pa_bool_t pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
263 pa_return_val_if_fail(str = pa_proplist_gets(f->plist, key), FALSE);
264 o = json_tokener_parse(str);
265 pa_return_val_if_fail(!is_error(o), FALSE);
266 if (json_object_get_type(o) != json_type_int) {
271 *v = json_object_get_int(o);
277 pa_bool_t pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
278 const char *str = NULL;
285 str = pa_proplist_gets(f->plist, key), FALSE;
289 o = json_tokener_parse(str);
290 pa_return_val_if_fail(!is_error(o), FALSE);
291 if (json_object_get_type(o) != json_type_string) {
296 *v = pa_xstrdup(json_object_get_string(o));
302 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
308 o = json_object_new_int(value);
310 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
315 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
322 o = json_object_new_array();
324 for (i = 0; i < n_values; i++)
325 json_object_array_add(o, json_object_new_int(values[i]));
327 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
332 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
338 o = json_object_new_object();
340 json_object_object_add(o, PA_JSON_MIN_KEY, json_object_new_int(min));
341 json_object_object_add(o, PA_JSON_MAX_KEY, json_object_new_int(max));
343 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
348 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
354 o = json_object_new_string(value);
356 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
361 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
368 o = json_object_new_array();
370 for (i = 0; i < n_values; i++)
371 json_object_array_add(o, json_object_new_string(values[i]));
373 pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
378 static pa_bool_t pa_json_is_fixed_type(json_object *o)
380 switch(json_object_get_type(o)) {
381 case json_type_object:
382 case json_type_array:
390 static int pa_json_value_equal(json_object *o1, json_object *o2) {
391 return (json_object_get_type(o1) == json_object_get_type(o2)) &&
392 pa_streq(json_object_to_json_string(o1), json_object_to_json_string(o2));
395 static int pa_format_info_prop_compatible(const char *one, const char *two) {
396 json_object *o1 = NULL, *o2 = NULL;
399 o1 = json_tokener_parse(one);
403 o2 = json_tokener_parse(two);
407 /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
408 pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), FALSE);
410 if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
411 ret = pa_json_value_equal(o1, o2);
415 if (pa_json_is_fixed_type(o1)) {
416 json_object *tmp = o2;
421 /* o2 is now a fixed type, and o1 is not */
423 if (json_object_get_type(o1) == json_type_array) {
424 for (i = 0; i < json_object_array_length(o1); i++) {
425 if (pa_json_value_equal(json_object_array_get_idx(o1, i), o2)) {
430 } else if (json_object_get_type(o1) == json_type_object) {
431 /* o1 should be a range type */
433 json_object *o_min = NULL, *o_max = NULL;
435 if (json_object_get_type(o2) != json_type_int) {
436 /* We don't support non-integer ranges */
440 o_min = json_object_object_get(o1, PA_JSON_MIN_KEY);
441 if (!o_min || json_object_get_type(o_min) != json_type_int)
444 o_max = json_object_object_get(o1, PA_JSON_MAX_KEY);
445 if (!o_max || json_object_get_type(o_max) != json_type_int)
448 v = json_object_get_int(o2);
449 min = json_object_get_int(o_min);
450 max = json_object_get_int(o_max);
452 ret = v >= min && v <= max;
454 pa_log_warn("Got a format type that we don't support");