153a5a1b3Sopenharmony_ci/*** 253a5a1b3Sopenharmony_ci This file is part of PulseAudio. 353a5a1b3Sopenharmony_ci 453a5a1b3Sopenharmony_ci Copyright 2011 Intel Corporation 553a5a1b3Sopenharmony_ci Copyright 2011 Collabora Multimedia 653a5a1b3Sopenharmony_ci Copyright 2011 Arun Raghavan <arun.raghavan@collabora.co.uk> 753a5a1b3Sopenharmony_ci 853a5a1b3Sopenharmony_ci PulseAudio is free software; you can redistribute it and/or modify 953a5a1b3Sopenharmony_ci it under the terms of the GNU Lesser General Public License as published 1053a5a1b3Sopenharmony_ci by the Free Software Foundation; either version 2.1 of the License, 1153a5a1b3Sopenharmony_ci or (at your option) any later version. 1253a5a1b3Sopenharmony_ci 1353a5a1b3Sopenharmony_ci PulseAudio is distributed in the hope that it will be useful, but 1453a5a1b3Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 1553a5a1b3Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1653a5a1b3Sopenharmony_ci General Public License for more details. 1753a5a1b3Sopenharmony_ci 1853a5a1b3Sopenharmony_ci You should have received a copy of the GNU Lesser General Public License 1953a5a1b3Sopenharmony_ci along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 2053a5a1b3Sopenharmony_ci***/ 2153a5a1b3Sopenharmony_ci 2253a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H 2353a5a1b3Sopenharmony_ci#include <config.h> 2453a5a1b3Sopenharmony_ci#endif 2553a5a1b3Sopenharmony_ci 2653a5a1b3Sopenharmony_ci#include <pulse/internal.h> 2753a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h> 2853a5a1b3Sopenharmony_ci 2953a5a1b3Sopenharmony_ci#include <pulsecore/core-format.h> 3053a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h> 3153a5a1b3Sopenharmony_ci#include <pulsecore/i18n.h> 3253a5a1b3Sopenharmony_ci#include <pulsecore/json.h> 3353a5a1b3Sopenharmony_ci#include <pulsecore/macro.h> 3453a5a1b3Sopenharmony_ci#include <pulsecore/strbuf.h> 3553a5a1b3Sopenharmony_ci 3653a5a1b3Sopenharmony_ci#include "format.h" 3753a5a1b3Sopenharmony_ci 3853a5a1b3Sopenharmony_ci#define PA_JSON_MIN_KEY "min" 3953a5a1b3Sopenharmony_ci#define PA_JSON_MAX_KEY "max" 4053a5a1b3Sopenharmony_ci 4153a5a1b3Sopenharmony_cistatic int pa_format_info_prop_compatible(const char *one, const char *two); 4253a5a1b3Sopenharmony_ci 4353a5a1b3Sopenharmony_cistatic const char* const _encoding_str_table[]= { 4453a5a1b3Sopenharmony_ci [PA_ENCODING_PCM] = "pcm", 4553a5a1b3Sopenharmony_ci [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937", 4653a5a1b3Sopenharmony_ci [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937", 4753a5a1b3Sopenharmony_ci [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937", 4853a5a1b3Sopenharmony_ci [PA_ENCODING_DTS_IEC61937] = "dts-iec61937", 4953a5a1b3Sopenharmony_ci [PA_ENCODING_MPEG2_AAC_IEC61937] = "mpeg2-aac-iec61937", 5053a5a1b3Sopenharmony_ci [PA_ENCODING_TRUEHD_IEC61937] = "truehd-iec61937", 5153a5a1b3Sopenharmony_ci [PA_ENCODING_DTSHD_IEC61937] = "dtshd-iec61937", 5253a5a1b3Sopenharmony_ci [PA_ENCODING_ANY] = "any", 5353a5a1b3Sopenharmony_ci}; 5453a5a1b3Sopenharmony_ci 5553a5a1b3Sopenharmony_ciconst char *pa_encoding_to_string(pa_encoding_t e) { 5653a5a1b3Sopenharmony_ci if (e < 0 || e >= PA_ENCODING_MAX) 5753a5a1b3Sopenharmony_ci return NULL; 5853a5a1b3Sopenharmony_ci 5953a5a1b3Sopenharmony_ci return _encoding_str_table[e]; 6053a5a1b3Sopenharmony_ci} 6153a5a1b3Sopenharmony_ci 6253a5a1b3Sopenharmony_cipa_encoding_t pa_encoding_from_string(const char *encoding) { 6353a5a1b3Sopenharmony_ci pa_encoding_t e; 6453a5a1b3Sopenharmony_ci 6553a5a1b3Sopenharmony_ci for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++) 6653a5a1b3Sopenharmony_ci if (pa_streq(_encoding_str_table[e], encoding)) 6753a5a1b3Sopenharmony_ci return e; 6853a5a1b3Sopenharmony_ci 6953a5a1b3Sopenharmony_ci return PA_ENCODING_INVALID; 7053a5a1b3Sopenharmony_ci} 7153a5a1b3Sopenharmony_ci 7253a5a1b3Sopenharmony_cipa_format_info* pa_format_info_new(void) { 7353a5a1b3Sopenharmony_ci pa_format_info *f = pa_xnew(pa_format_info, 1); 7453a5a1b3Sopenharmony_ci 7553a5a1b3Sopenharmony_ci f->encoding = PA_ENCODING_INVALID; 7653a5a1b3Sopenharmony_ci f->plist = pa_proplist_new(); 7753a5a1b3Sopenharmony_ci 7853a5a1b3Sopenharmony_ci return f; 7953a5a1b3Sopenharmony_ci} 8053a5a1b3Sopenharmony_ci 8153a5a1b3Sopenharmony_cipa_format_info* pa_format_info_copy(const pa_format_info *src) { 8253a5a1b3Sopenharmony_ci pa_format_info *dest; 8353a5a1b3Sopenharmony_ci 8453a5a1b3Sopenharmony_ci pa_assert(src); 8553a5a1b3Sopenharmony_ci 8653a5a1b3Sopenharmony_ci dest = pa_xnew(pa_format_info, 1); 8753a5a1b3Sopenharmony_ci 8853a5a1b3Sopenharmony_ci dest->encoding = src->encoding; 8953a5a1b3Sopenharmony_ci 9053a5a1b3Sopenharmony_ci if (src->plist) 9153a5a1b3Sopenharmony_ci dest->plist = pa_proplist_copy(src->plist); 9253a5a1b3Sopenharmony_ci else 9353a5a1b3Sopenharmony_ci dest->plist = NULL; 9453a5a1b3Sopenharmony_ci 9553a5a1b3Sopenharmony_ci return dest; 9653a5a1b3Sopenharmony_ci} 9753a5a1b3Sopenharmony_ci 9853a5a1b3Sopenharmony_civoid pa_format_info_free(pa_format_info *f) { 9953a5a1b3Sopenharmony_ci pa_assert(f); 10053a5a1b3Sopenharmony_ci 10153a5a1b3Sopenharmony_ci pa_proplist_free(f->plist); 10253a5a1b3Sopenharmony_ci pa_xfree(f); 10353a5a1b3Sopenharmony_ci} 10453a5a1b3Sopenharmony_ci 10553a5a1b3Sopenharmony_ciint pa_format_info_valid(const pa_format_info *f) { 10653a5a1b3Sopenharmony_ci return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL); 10753a5a1b3Sopenharmony_ci} 10853a5a1b3Sopenharmony_ci 10953a5a1b3Sopenharmony_ciint pa_format_info_is_pcm(const pa_format_info *f) { 11053a5a1b3Sopenharmony_ci return f->encoding == PA_ENCODING_PCM; 11153a5a1b3Sopenharmony_ci} 11253a5a1b3Sopenharmony_ci 11353a5a1b3Sopenharmony_cichar *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) { 11453a5a1b3Sopenharmony_ci char *tmp; 11553a5a1b3Sopenharmony_ci 11653a5a1b3Sopenharmony_ci pa_assert(s); 11753a5a1b3Sopenharmony_ci pa_assert(l > 0); 11853a5a1b3Sopenharmony_ci pa_assert(f); 11953a5a1b3Sopenharmony_ci 12053a5a1b3Sopenharmony_ci pa_init_i18n(); 12153a5a1b3Sopenharmony_ci 12253a5a1b3Sopenharmony_ci if (!pa_format_info_valid(f)) 12353a5a1b3Sopenharmony_ci pa_snprintf(s, l, _("(invalid)")); 12453a5a1b3Sopenharmony_ci else { 12553a5a1b3Sopenharmony_ci tmp = pa_proplist_to_string_sep(f->plist, " "); 12653a5a1b3Sopenharmony_ci if (tmp[0]) 12753a5a1b3Sopenharmony_ci pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp); 12853a5a1b3Sopenharmony_ci else 12953a5a1b3Sopenharmony_ci pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding)); 13053a5a1b3Sopenharmony_ci pa_xfree(tmp); 13153a5a1b3Sopenharmony_ci } 13253a5a1b3Sopenharmony_ci 13353a5a1b3Sopenharmony_ci return s; 13453a5a1b3Sopenharmony_ci} 13553a5a1b3Sopenharmony_ci 13653a5a1b3Sopenharmony_cipa_format_info* pa_format_info_from_string(const char *str) { 13753a5a1b3Sopenharmony_ci pa_format_info *f = pa_format_info_new(); 13853a5a1b3Sopenharmony_ci char *encoding = NULL, *properties = NULL; 13953a5a1b3Sopenharmony_ci size_t pos; 14053a5a1b3Sopenharmony_ci 14153a5a1b3Sopenharmony_ci pos = strcspn(str, ","); 14253a5a1b3Sopenharmony_ci 14353a5a1b3Sopenharmony_ci encoding = pa_xstrndup(str, pos); 14453a5a1b3Sopenharmony_ci f->encoding = pa_encoding_from_string(pa_strip(encoding)); 14553a5a1b3Sopenharmony_ci if (f->encoding == PA_ENCODING_INVALID) 14653a5a1b3Sopenharmony_ci goto error; 14753a5a1b3Sopenharmony_ci 14853a5a1b3Sopenharmony_ci if (pos != strlen(str)) { 14953a5a1b3Sopenharmony_ci pa_proplist *plist; 15053a5a1b3Sopenharmony_ci 15153a5a1b3Sopenharmony_ci properties = pa_xstrdup(&str[pos+1]); 15253a5a1b3Sopenharmony_ci plist = pa_proplist_from_string(properties); 15353a5a1b3Sopenharmony_ci 15453a5a1b3Sopenharmony_ci if (!plist) 15553a5a1b3Sopenharmony_ci goto error; 15653a5a1b3Sopenharmony_ci 15753a5a1b3Sopenharmony_ci pa_proplist_free(f->plist); 15853a5a1b3Sopenharmony_ci f->plist = plist; 15953a5a1b3Sopenharmony_ci } 16053a5a1b3Sopenharmony_ci 16153a5a1b3Sopenharmony_ciout: 16253a5a1b3Sopenharmony_ci if (encoding) 16353a5a1b3Sopenharmony_ci pa_xfree(encoding); 16453a5a1b3Sopenharmony_ci if (properties) 16553a5a1b3Sopenharmony_ci pa_xfree(properties); 16653a5a1b3Sopenharmony_ci return f; 16753a5a1b3Sopenharmony_ci 16853a5a1b3Sopenharmony_cierror: 16953a5a1b3Sopenharmony_ci pa_format_info_free(f); 17053a5a1b3Sopenharmony_ci f = NULL; 17153a5a1b3Sopenharmony_ci goto out; 17253a5a1b3Sopenharmony_ci} 17353a5a1b3Sopenharmony_ci 17453a5a1b3Sopenharmony_ciint pa_format_info_is_compatible(const pa_format_info *first, const pa_format_info *second) { 17553a5a1b3Sopenharmony_ci const char *key; 17653a5a1b3Sopenharmony_ci void *state = NULL; 17753a5a1b3Sopenharmony_ci 17853a5a1b3Sopenharmony_ci pa_assert(first); 17953a5a1b3Sopenharmony_ci pa_assert(second); 18053a5a1b3Sopenharmony_ci 18153a5a1b3Sopenharmony_ci if (first->encoding != second->encoding) 18253a5a1b3Sopenharmony_ci return false; 18353a5a1b3Sopenharmony_ci 18453a5a1b3Sopenharmony_ci while ((key = pa_proplist_iterate(first->plist, &state))) { 18553a5a1b3Sopenharmony_ci const char *value_one, *value_two; 18653a5a1b3Sopenharmony_ci 18753a5a1b3Sopenharmony_ci value_one = pa_proplist_gets(first->plist, key); 18853a5a1b3Sopenharmony_ci value_two = pa_proplist_gets(second->plist, key); 18953a5a1b3Sopenharmony_ci 19053a5a1b3Sopenharmony_ci if (!value_two || !pa_format_info_prop_compatible(value_one, value_two)) 19153a5a1b3Sopenharmony_ci return false; 19253a5a1b3Sopenharmony_ci } 19353a5a1b3Sopenharmony_ci 19453a5a1b3Sopenharmony_ci return true; 19553a5a1b3Sopenharmony_ci} 19653a5a1b3Sopenharmony_ci 19753a5a1b3Sopenharmony_cipa_format_info* pa_format_info_from_sample_spec(const pa_sample_spec *ss, const pa_channel_map *map) { 19853a5a1b3Sopenharmony_ci char cm[PA_CHANNEL_MAP_SNPRINT_MAX]; 19953a5a1b3Sopenharmony_ci pa_format_info *f; 20053a5a1b3Sopenharmony_ci 20153a5a1b3Sopenharmony_ci pa_assert(ss && pa_sample_spec_valid(ss)); 20253a5a1b3Sopenharmony_ci pa_assert(!map || pa_channel_map_valid(map)); 20353a5a1b3Sopenharmony_ci 20453a5a1b3Sopenharmony_ci f = pa_format_info_new(); 20553a5a1b3Sopenharmony_ci f->encoding = PA_ENCODING_PCM; 20653a5a1b3Sopenharmony_ci 20753a5a1b3Sopenharmony_ci pa_format_info_set_sample_format(f, ss->format); 20853a5a1b3Sopenharmony_ci pa_format_info_set_rate(f, ss->rate); 20953a5a1b3Sopenharmony_ci pa_format_info_set_channels(f, ss->channels); 21053a5a1b3Sopenharmony_ci 21153a5a1b3Sopenharmony_ci if (map) { 21253a5a1b3Sopenharmony_ci pa_channel_map_snprint(cm, sizeof(cm), map); 21353a5a1b3Sopenharmony_ci pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm); 21453a5a1b3Sopenharmony_ci } 21553a5a1b3Sopenharmony_ci 21653a5a1b3Sopenharmony_ci return f; 21753a5a1b3Sopenharmony_ci} 21853a5a1b3Sopenharmony_ci 21953a5a1b3Sopenharmony_ci/* For PCM streams */ 22053a5a1b3Sopenharmony_ciint pa_format_info_to_sample_spec(const pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) { 22153a5a1b3Sopenharmony_ci pa_assert(f); 22253a5a1b3Sopenharmony_ci pa_assert(ss); 22353a5a1b3Sopenharmony_ci 22453a5a1b3Sopenharmony_ci if (!pa_format_info_is_pcm(f)) 22553a5a1b3Sopenharmony_ci return pa_format_info_to_sample_spec_fake(f, ss, map); 22653a5a1b3Sopenharmony_ci 22753a5a1b3Sopenharmony_ci if (pa_format_info_get_sample_format(f, &ss->format) < 0) 22853a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 22953a5a1b3Sopenharmony_ci if (pa_format_info_get_rate(f, &ss->rate) < 0) 23053a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 23153a5a1b3Sopenharmony_ci if (pa_format_info_get_channels(f, &ss->channels) < 0) 23253a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 23353a5a1b3Sopenharmony_ci if (map && pa_format_info_get_channel_map(f, map) < 0) 23453a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 23553a5a1b3Sopenharmony_ci 23653a5a1b3Sopenharmony_ci return 0; 23753a5a1b3Sopenharmony_ci} 23853a5a1b3Sopenharmony_ci 23953a5a1b3Sopenharmony_cipa_prop_type_t pa_format_info_get_prop_type(const pa_format_info *f, const char *key) { 24053a5a1b3Sopenharmony_ci const char *str; 24153a5a1b3Sopenharmony_ci pa_json_object *o; 24253a5a1b3Sopenharmony_ci const pa_json_object *o1; 24353a5a1b3Sopenharmony_ci pa_prop_type_t type; 24453a5a1b3Sopenharmony_ci 24553a5a1b3Sopenharmony_ci pa_assert(f); 24653a5a1b3Sopenharmony_ci pa_assert(key); 24753a5a1b3Sopenharmony_ci 24853a5a1b3Sopenharmony_ci str = pa_proplist_gets(f->plist, key); 24953a5a1b3Sopenharmony_ci if (!str) 25053a5a1b3Sopenharmony_ci return PA_PROP_TYPE_INVALID; 25153a5a1b3Sopenharmony_ci 25253a5a1b3Sopenharmony_ci o = pa_json_parse(str); 25353a5a1b3Sopenharmony_ci if (!o) 25453a5a1b3Sopenharmony_ci return PA_PROP_TYPE_INVALID; 25553a5a1b3Sopenharmony_ci 25653a5a1b3Sopenharmony_ci switch (pa_json_object_get_type(o)) { 25753a5a1b3Sopenharmony_ci case PA_JSON_TYPE_INT: 25853a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_INT; 25953a5a1b3Sopenharmony_ci break; 26053a5a1b3Sopenharmony_ci 26153a5a1b3Sopenharmony_ci case PA_JSON_TYPE_STRING: 26253a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_STRING; 26353a5a1b3Sopenharmony_ci break; 26453a5a1b3Sopenharmony_ci 26553a5a1b3Sopenharmony_ci case PA_JSON_TYPE_ARRAY: 26653a5a1b3Sopenharmony_ci if (pa_json_object_get_array_length(o) == 0) { 26753a5a1b3Sopenharmony_ci /* Unlikely, but let's account for this anyway. We need at 26853a5a1b3Sopenharmony_ci * least one element to figure out the array type. */ 26953a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_INVALID; 27053a5a1b3Sopenharmony_ci break; 27153a5a1b3Sopenharmony_ci } 27253a5a1b3Sopenharmony_ci 27353a5a1b3Sopenharmony_ci o1 = pa_json_object_get_array_member(o, 0); 27453a5a1b3Sopenharmony_ci 27553a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o1) == PA_JSON_TYPE_INT) 27653a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_INT_ARRAY; 27753a5a1b3Sopenharmony_ci else if (pa_json_object_get_type(o1) == PA_JSON_TYPE_STRING) 27853a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_STRING_ARRAY; 27953a5a1b3Sopenharmony_ci else 28053a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_INVALID; 28153a5a1b3Sopenharmony_ci 28253a5a1b3Sopenharmony_ci break; 28353a5a1b3Sopenharmony_ci 28453a5a1b3Sopenharmony_ci case PA_JSON_TYPE_OBJECT: 28553a5a1b3Sopenharmony_ci /* We actually know at this point that it's a int range, but let's 28653a5a1b3Sopenharmony_ci * confirm. */ 28753a5a1b3Sopenharmony_ci if (!pa_json_object_get_object_member(o, PA_JSON_MIN_KEY)) { 28853a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_INVALID; 28953a5a1b3Sopenharmony_ci break; 29053a5a1b3Sopenharmony_ci } 29153a5a1b3Sopenharmony_ci 29253a5a1b3Sopenharmony_ci if (!pa_json_object_get_object_member(o, PA_JSON_MAX_KEY)) { 29353a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_INVALID; 29453a5a1b3Sopenharmony_ci break; 29553a5a1b3Sopenharmony_ci } 29653a5a1b3Sopenharmony_ci 29753a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_INT_RANGE; 29853a5a1b3Sopenharmony_ci break; 29953a5a1b3Sopenharmony_ci 30053a5a1b3Sopenharmony_ci default: 30153a5a1b3Sopenharmony_ci type = PA_PROP_TYPE_INVALID; 30253a5a1b3Sopenharmony_ci break; 30353a5a1b3Sopenharmony_ci } 30453a5a1b3Sopenharmony_ci 30553a5a1b3Sopenharmony_ci pa_json_object_free(o); 30653a5a1b3Sopenharmony_ci return type; 30753a5a1b3Sopenharmony_ci} 30853a5a1b3Sopenharmony_ci 30953a5a1b3Sopenharmony_ciint pa_format_info_get_prop_int(const pa_format_info *f, const char *key, int *v) { 31053a5a1b3Sopenharmony_ci const char *str; 31153a5a1b3Sopenharmony_ci pa_json_object *o; 31253a5a1b3Sopenharmony_ci 31353a5a1b3Sopenharmony_ci pa_assert(f); 31453a5a1b3Sopenharmony_ci pa_assert(key); 31553a5a1b3Sopenharmony_ci pa_assert(v); 31653a5a1b3Sopenharmony_ci 31753a5a1b3Sopenharmony_ci str = pa_proplist_gets(f->plist, key); 31853a5a1b3Sopenharmony_ci if (!str) 31953a5a1b3Sopenharmony_ci return -PA_ERR_NOENTITY; 32053a5a1b3Sopenharmony_ci 32153a5a1b3Sopenharmony_ci o = pa_json_parse(str); 32253a5a1b3Sopenharmony_ci if (!o) { 32353a5a1b3Sopenharmony_ci pa_log_debug("Failed to parse format info property '%s'.", key); 32453a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 32553a5a1b3Sopenharmony_ci } 32653a5a1b3Sopenharmony_ci 32753a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o) != PA_JSON_TYPE_INT) { 32853a5a1b3Sopenharmony_ci pa_log_debug("Format info property '%s' type is not int.", key); 32953a5a1b3Sopenharmony_ci pa_json_object_free(o); 33053a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 33153a5a1b3Sopenharmony_ci } 33253a5a1b3Sopenharmony_ci 33353a5a1b3Sopenharmony_ci *v = pa_json_object_get_int(o); 33453a5a1b3Sopenharmony_ci pa_json_object_free(o); 33553a5a1b3Sopenharmony_ci 33653a5a1b3Sopenharmony_ci return 0; 33753a5a1b3Sopenharmony_ci} 33853a5a1b3Sopenharmony_ci 33953a5a1b3Sopenharmony_ciint pa_format_info_get_prop_int_range(const pa_format_info *f, const char *key, int *min, int *max) { 34053a5a1b3Sopenharmony_ci const char *str; 34153a5a1b3Sopenharmony_ci pa_json_object *o; 34253a5a1b3Sopenharmony_ci const pa_json_object *o1; 34353a5a1b3Sopenharmony_ci int ret = -PA_ERR_INVALID; 34453a5a1b3Sopenharmony_ci 34553a5a1b3Sopenharmony_ci pa_assert(f); 34653a5a1b3Sopenharmony_ci pa_assert(key); 34753a5a1b3Sopenharmony_ci pa_assert(min); 34853a5a1b3Sopenharmony_ci pa_assert(max); 34953a5a1b3Sopenharmony_ci 35053a5a1b3Sopenharmony_ci str = pa_proplist_gets(f->plist, key); 35153a5a1b3Sopenharmony_ci if (!str) 35253a5a1b3Sopenharmony_ci return -PA_ERR_NOENTITY; 35353a5a1b3Sopenharmony_ci 35453a5a1b3Sopenharmony_ci o = pa_json_parse(str); 35553a5a1b3Sopenharmony_ci if (!o) { 35653a5a1b3Sopenharmony_ci pa_log_debug("Failed to parse format info property '%s'.", key); 35753a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 35853a5a1b3Sopenharmony_ci } 35953a5a1b3Sopenharmony_ci 36053a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o) != PA_JSON_TYPE_OBJECT) 36153a5a1b3Sopenharmony_ci goto out; 36253a5a1b3Sopenharmony_ci 36353a5a1b3Sopenharmony_ci if (!(o1 = pa_json_object_get_object_member(o, PA_JSON_MIN_KEY)) || 36453a5a1b3Sopenharmony_ci (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT)) 36553a5a1b3Sopenharmony_ci goto out; 36653a5a1b3Sopenharmony_ci 36753a5a1b3Sopenharmony_ci *min = pa_json_object_get_int(o1); 36853a5a1b3Sopenharmony_ci 36953a5a1b3Sopenharmony_ci if (!(o1 = pa_json_object_get_object_member(o, PA_JSON_MAX_KEY)) || 37053a5a1b3Sopenharmony_ci (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT)) 37153a5a1b3Sopenharmony_ci goto out; 37253a5a1b3Sopenharmony_ci 37353a5a1b3Sopenharmony_ci *max = pa_json_object_get_int(o1); 37453a5a1b3Sopenharmony_ci 37553a5a1b3Sopenharmony_ci ret = 0; 37653a5a1b3Sopenharmony_ci 37753a5a1b3Sopenharmony_ciout: 37853a5a1b3Sopenharmony_ci if (ret < 0) 37953a5a1b3Sopenharmony_ci pa_log_debug("Format info property '%s' is not a valid int range.", key); 38053a5a1b3Sopenharmony_ci 38153a5a1b3Sopenharmony_ci pa_json_object_free(o); 38253a5a1b3Sopenharmony_ci return ret; 38353a5a1b3Sopenharmony_ci} 38453a5a1b3Sopenharmony_ci 38553a5a1b3Sopenharmony_ciint pa_format_info_get_prop_int_array(const pa_format_info *f, const char *key, int **values, int *n_values) { 38653a5a1b3Sopenharmony_ci const char *str; 38753a5a1b3Sopenharmony_ci pa_json_object *o; 38853a5a1b3Sopenharmony_ci const pa_json_object *o1; 38953a5a1b3Sopenharmony_ci int i, ret = -PA_ERR_INVALID; 39053a5a1b3Sopenharmony_ci 39153a5a1b3Sopenharmony_ci pa_assert(f); 39253a5a1b3Sopenharmony_ci pa_assert(key); 39353a5a1b3Sopenharmony_ci pa_assert(values); 39453a5a1b3Sopenharmony_ci pa_assert(n_values); 39553a5a1b3Sopenharmony_ci 39653a5a1b3Sopenharmony_ci str = pa_proplist_gets(f->plist, key); 39753a5a1b3Sopenharmony_ci if (!str) 39853a5a1b3Sopenharmony_ci return -PA_ERR_NOENTITY; 39953a5a1b3Sopenharmony_ci 40053a5a1b3Sopenharmony_ci o = pa_json_parse(str); 40153a5a1b3Sopenharmony_ci if (!o) { 40253a5a1b3Sopenharmony_ci pa_log_debug("Failed to parse format info property '%s'.", key); 40353a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 40453a5a1b3Sopenharmony_ci } 40553a5a1b3Sopenharmony_ci 40653a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o) != PA_JSON_TYPE_ARRAY) 40753a5a1b3Sopenharmony_ci goto out; 40853a5a1b3Sopenharmony_ci 40953a5a1b3Sopenharmony_ci *n_values = pa_json_object_get_array_length(o); 41053a5a1b3Sopenharmony_ci *values = pa_xnew(int, *n_values); 41153a5a1b3Sopenharmony_ci 41253a5a1b3Sopenharmony_ci for (i = 0; i < *n_values; i++) { 41353a5a1b3Sopenharmony_ci o1 = pa_json_object_get_array_member(o, i); 41453a5a1b3Sopenharmony_ci 41553a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT) { 41653a5a1b3Sopenharmony_ci goto out; 41753a5a1b3Sopenharmony_ci } 41853a5a1b3Sopenharmony_ci 41953a5a1b3Sopenharmony_ci (*values)[i] = pa_json_object_get_int(o1); 42053a5a1b3Sopenharmony_ci } 42153a5a1b3Sopenharmony_ci 42253a5a1b3Sopenharmony_ci ret = 0; 42353a5a1b3Sopenharmony_ci 42453a5a1b3Sopenharmony_ciout: 42553a5a1b3Sopenharmony_ci if (ret < 0) 42653a5a1b3Sopenharmony_ci pa_log_debug("Format info property '%s' is not a valid int array.", key); 42753a5a1b3Sopenharmony_ci 42853a5a1b3Sopenharmony_ci pa_json_object_free(o); 42953a5a1b3Sopenharmony_ci return ret; 43053a5a1b3Sopenharmony_ci} 43153a5a1b3Sopenharmony_ci 43253a5a1b3Sopenharmony_ciint pa_format_info_get_prop_string(const pa_format_info *f, const char *key, char **v) { 43353a5a1b3Sopenharmony_ci const char *str = NULL; 43453a5a1b3Sopenharmony_ci pa_json_object *o; 43553a5a1b3Sopenharmony_ci 43653a5a1b3Sopenharmony_ci pa_assert(f); 43753a5a1b3Sopenharmony_ci pa_assert(key); 43853a5a1b3Sopenharmony_ci pa_assert(v); 43953a5a1b3Sopenharmony_ci 44053a5a1b3Sopenharmony_ci str = pa_proplist_gets(f->plist, key); 44153a5a1b3Sopenharmony_ci if (!str) 44253a5a1b3Sopenharmony_ci return -PA_ERR_NOENTITY; 44353a5a1b3Sopenharmony_ci 44453a5a1b3Sopenharmony_ci o = pa_json_parse(str); 44553a5a1b3Sopenharmony_ci if (!o) { 44653a5a1b3Sopenharmony_ci pa_log_debug("Failed to parse format info property '%s'.", key); 44753a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 44853a5a1b3Sopenharmony_ci } 44953a5a1b3Sopenharmony_ci 45053a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o) != PA_JSON_TYPE_STRING) { 45153a5a1b3Sopenharmony_ci pa_log_debug("Format info property '%s' type is not string.", key); 45253a5a1b3Sopenharmony_ci pa_json_object_free(o); 45353a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 45453a5a1b3Sopenharmony_ci } 45553a5a1b3Sopenharmony_ci 45653a5a1b3Sopenharmony_ci *v = pa_xstrdup(pa_json_object_get_string(o)); 45753a5a1b3Sopenharmony_ci pa_json_object_free(o); 45853a5a1b3Sopenharmony_ci 45953a5a1b3Sopenharmony_ci return 0; 46053a5a1b3Sopenharmony_ci} 46153a5a1b3Sopenharmony_ci 46253a5a1b3Sopenharmony_ciint pa_format_info_get_prop_string_array(const pa_format_info *f, const char *key, char ***values, int *n_values) { 46353a5a1b3Sopenharmony_ci const char *str; 46453a5a1b3Sopenharmony_ci pa_json_object *o; 46553a5a1b3Sopenharmony_ci const pa_json_object *o1; 46653a5a1b3Sopenharmony_ci int i, ret = -PA_ERR_INVALID; 46753a5a1b3Sopenharmony_ci 46853a5a1b3Sopenharmony_ci pa_assert(f); 46953a5a1b3Sopenharmony_ci pa_assert(key); 47053a5a1b3Sopenharmony_ci pa_assert(values); 47153a5a1b3Sopenharmony_ci pa_assert(n_values); 47253a5a1b3Sopenharmony_ci 47353a5a1b3Sopenharmony_ci str = pa_proplist_gets(f->plist, key); 47453a5a1b3Sopenharmony_ci if (!str) 47553a5a1b3Sopenharmony_ci return -PA_ERR_NOENTITY; 47653a5a1b3Sopenharmony_ci 47753a5a1b3Sopenharmony_ci o = pa_json_parse(str); 47853a5a1b3Sopenharmony_ci if (!o) { 47953a5a1b3Sopenharmony_ci pa_log_debug("Failed to parse format info property '%s'.", key); 48053a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 48153a5a1b3Sopenharmony_ci } 48253a5a1b3Sopenharmony_ci 48353a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o) != PA_JSON_TYPE_ARRAY) 48453a5a1b3Sopenharmony_ci goto out; 48553a5a1b3Sopenharmony_ci 48653a5a1b3Sopenharmony_ci *n_values = pa_json_object_get_array_length(o); 48753a5a1b3Sopenharmony_ci *values = pa_xnew(char *, *n_values); 48853a5a1b3Sopenharmony_ci 48953a5a1b3Sopenharmony_ci for (i = 0; i < *n_values; i++) { 49053a5a1b3Sopenharmony_ci o1 = pa_json_object_get_array_member(o, i); 49153a5a1b3Sopenharmony_ci 49253a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o1) != PA_JSON_TYPE_STRING) { 49353a5a1b3Sopenharmony_ci goto out; 49453a5a1b3Sopenharmony_ci } 49553a5a1b3Sopenharmony_ci 49653a5a1b3Sopenharmony_ci (*values)[i] = pa_xstrdup(pa_json_object_get_string(o1)); 49753a5a1b3Sopenharmony_ci } 49853a5a1b3Sopenharmony_ci 49953a5a1b3Sopenharmony_ci ret = 0; 50053a5a1b3Sopenharmony_ci 50153a5a1b3Sopenharmony_ciout: 50253a5a1b3Sopenharmony_ci if (ret < 0) 50353a5a1b3Sopenharmony_ci pa_log_debug("Format info property '%s' is not a valid string array.", key); 50453a5a1b3Sopenharmony_ci 50553a5a1b3Sopenharmony_ci pa_json_object_free(o); 50653a5a1b3Sopenharmony_ci return ret; 50753a5a1b3Sopenharmony_ci} 50853a5a1b3Sopenharmony_ci 50953a5a1b3Sopenharmony_civoid pa_format_info_free_string_array(char **values, int n_values) { 51053a5a1b3Sopenharmony_ci int i; 51153a5a1b3Sopenharmony_ci 51253a5a1b3Sopenharmony_ci for (i = 0; i < n_values; i++) 51353a5a1b3Sopenharmony_ci pa_xfree(values[i]); 51453a5a1b3Sopenharmony_ci 51553a5a1b3Sopenharmony_ci pa_xfree(values); 51653a5a1b3Sopenharmony_ci} 51753a5a1b3Sopenharmony_ci 51853a5a1b3Sopenharmony_ciint pa_format_info_get_sample_format(const pa_format_info *f, pa_sample_format_t *sf) { 51953a5a1b3Sopenharmony_ci int r; 52053a5a1b3Sopenharmony_ci char *sf_str; 52153a5a1b3Sopenharmony_ci pa_sample_format_t sf_local; 52253a5a1b3Sopenharmony_ci 52353a5a1b3Sopenharmony_ci pa_assert(f); 52453a5a1b3Sopenharmony_ci pa_assert(sf); 52553a5a1b3Sopenharmony_ci 52653a5a1b3Sopenharmony_ci r = pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf_str); 52753a5a1b3Sopenharmony_ci if (r < 0) 52853a5a1b3Sopenharmony_ci return r; 52953a5a1b3Sopenharmony_ci 53053a5a1b3Sopenharmony_ci sf_local = pa_parse_sample_format(sf_str); 53153a5a1b3Sopenharmony_ci pa_xfree(sf_str); 53253a5a1b3Sopenharmony_ci 53353a5a1b3Sopenharmony_ci if (!pa_sample_format_valid(sf_local)) { 53453a5a1b3Sopenharmony_ci pa_log_debug("Invalid sample format."); 53553a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 53653a5a1b3Sopenharmony_ci } 53753a5a1b3Sopenharmony_ci 53853a5a1b3Sopenharmony_ci *sf = sf_local; 53953a5a1b3Sopenharmony_ci 54053a5a1b3Sopenharmony_ci return 0; 54153a5a1b3Sopenharmony_ci} 54253a5a1b3Sopenharmony_ci 54353a5a1b3Sopenharmony_ciint pa_format_info_get_rate(const pa_format_info *f, uint32_t *rate) { 54453a5a1b3Sopenharmony_ci int r; 54553a5a1b3Sopenharmony_ci int rate_local; 54653a5a1b3Sopenharmony_ci 54753a5a1b3Sopenharmony_ci pa_assert(f); 54853a5a1b3Sopenharmony_ci pa_assert(rate); 54953a5a1b3Sopenharmony_ci 55053a5a1b3Sopenharmony_ci r = pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate_local); 55153a5a1b3Sopenharmony_ci if (r < 0) 55253a5a1b3Sopenharmony_ci return r; 55353a5a1b3Sopenharmony_ci 55453a5a1b3Sopenharmony_ci if (!pa_sample_rate_valid(rate_local)) { 55553a5a1b3Sopenharmony_ci pa_log_debug("Invalid sample rate: %i", rate_local); 55653a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 55753a5a1b3Sopenharmony_ci } 55853a5a1b3Sopenharmony_ci 55953a5a1b3Sopenharmony_ci *rate = rate_local; 56053a5a1b3Sopenharmony_ci 56153a5a1b3Sopenharmony_ci return 0; 56253a5a1b3Sopenharmony_ci} 56353a5a1b3Sopenharmony_ci 56453a5a1b3Sopenharmony_ciint pa_format_info_get_channels(const pa_format_info *f, uint8_t *channels) { 56553a5a1b3Sopenharmony_ci int r; 56653a5a1b3Sopenharmony_ci int channels_local; 56753a5a1b3Sopenharmony_ci 56853a5a1b3Sopenharmony_ci pa_assert(f); 56953a5a1b3Sopenharmony_ci pa_assert(channels); 57053a5a1b3Sopenharmony_ci 57153a5a1b3Sopenharmony_ci r = pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels_local); 57253a5a1b3Sopenharmony_ci if (r < 0) 57353a5a1b3Sopenharmony_ci return r; 57453a5a1b3Sopenharmony_ci 57553a5a1b3Sopenharmony_ci if (!pa_channels_valid(channels_local)) { 57653a5a1b3Sopenharmony_ci pa_log_debug("Invalid channel count: %i", channels_local); 57753a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 57853a5a1b3Sopenharmony_ci } 57953a5a1b3Sopenharmony_ci 58053a5a1b3Sopenharmony_ci *channels = channels_local; 58153a5a1b3Sopenharmony_ci 58253a5a1b3Sopenharmony_ci return 0; 58353a5a1b3Sopenharmony_ci} 58453a5a1b3Sopenharmony_ci 58553a5a1b3Sopenharmony_ciint pa_format_info_get_channel_map(const pa_format_info *f, pa_channel_map *map) { 58653a5a1b3Sopenharmony_ci int r; 58753a5a1b3Sopenharmony_ci char *map_str; 58853a5a1b3Sopenharmony_ci 58953a5a1b3Sopenharmony_ci pa_assert(f); 59053a5a1b3Sopenharmony_ci pa_assert(map); 59153a5a1b3Sopenharmony_ci 59253a5a1b3Sopenharmony_ci r = pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &map_str); 59353a5a1b3Sopenharmony_ci if (r < 0) 59453a5a1b3Sopenharmony_ci return r; 59553a5a1b3Sopenharmony_ci 59653a5a1b3Sopenharmony_ci map = pa_channel_map_parse(map, map_str); 59753a5a1b3Sopenharmony_ci pa_xfree(map_str); 59853a5a1b3Sopenharmony_ci 59953a5a1b3Sopenharmony_ci if (!map) { 60053a5a1b3Sopenharmony_ci pa_log_debug("Failed to parse channel map."); 60153a5a1b3Sopenharmony_ci return -PA_ERR_INVALID; 60253a5a1b3Sopenharmony_ci } 60353a5a1b3Sopenharmony_ci 60453a5a1b3Sopenharmony_ci return 0; 60553a5a1b3Sopenharmony_ci} 60653a5a1b3Sopenharmony_ci 60753a5a1b3Sopenharmony_civoid pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) { 60853a5a1b3Sopenharmony_ci pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf)); 60953a5a1b3Sopenharmony_ci} 61053a5a1b3Sopenharmony_ci 61153a5a1b3Sopenharmony_civoid pa_format_info_set_rate(pa_format_info *f, int rate) { 61253a5a1b3Sopenharmony_ci pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate); 61353a5a1b3Sopenharmony_ci} 61453a5a1b3Sopenharmony_ci 61553a5a1b3Sopenharmony_civoid pa_format_info_set_channels(pa_format_info *f, int channels) { 61653a5a1b3Sopenharmony_ci pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels); 61753a5a1b3Sopenharmony_ci} 61853a5a1b3Sopenharmony_ci 61953a5a1b3Sopenharmony_civoid pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) { 62053a5a1b3Sopenharmony_ci char map_str[PA_CHANNEL_MAP_SNPRINT_MAX]; 62153a5a1b3Sopenharmony_ci 62253a5a1b3Sopenharmony_ci pa_channel_map_snprint(map_str, sizeof(map_str), map); 62353a5a1b3Sopenharmony_ci 62453a5a1b3Sopenharmony_ci pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str); 62553a5a1b3Sopenharmony_ci} 62653a5a1b3Sopenharmony_ci 62753a5a1b3Sopenharmony_civoid pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) { 62853a5a1b3Sopenharmony_ci pa_assert(f); 62953a5a1b3Sopenharmony_ci pa_assert(key); 63053a5a1b3Sopenharmony_ci 63153a5a1b3Sopenharmony_ci pa_proplist_setf(f->plist, key, "%d", value); 63253a5a1b3Sopenharmony_ci} 63353a5a1b3Sopenharmony_ci 63453a5a1b3Sopenharmony_civoid pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) { 63553a5a1b3Sopenharmony_ci pa_strbuf *buf; 63653a5a1b3Sopenharmony_ci char *str; 63753a5a1b3Sopenharmony_ci int i; 63853a5a1b3Sopenharmony_ci 63953a5a1b3Sopenharmony_ci pa_assert(f); 64053a5a1b3Sopenharmony_ci pa_assert(key); 64153a5a1b3Sopenharmony_ci pa_assert(n_values > 0); 64253a5a1b3Sopenharmony_ci 64353a5a1b3Sopenharmony_ci buf = pa_strbuf_new(); 64453a5a1b3Sopenharmony_ci 64553a5a1b3Sopenharmony_ci pa_strbuf_printf(buf, "[ %d", values[0]); 64653a5a1b3Sopenharmony_ci 64753a5a1b3Sopenharmony_ci for (i = 1; i < n_values; i++) 64853a5a1b3Sopenharmony_ci pa_strbuf_printf(buf, ", %d", values[i]); 64953a5a1b3Sopenharmony_ci 65053a5a1b3Sopenharmony_ci pa_strbuf_printf(buf, " ]"); 65153a5a1b3Sopenharmony_ci str = pa_strbuf_to_string_free(buf); 65253a5a1b3Sopenharmony_ci 65353a5a1b3Sopenharmony_ci pa_proplist_sets(f->plist, key, str); 65453a5a1b3Sopenharmony_ci pa_xfree (str); 65553a5a1b3Sopenharmony_ci} 65653a5a1b3Sopenharmony_ci 65753a5a1b3Sopenharmony_civoid pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) { 65853a5a1b3Sopenharmony_ci pa_assert(f); 65953a5a1b3Sopenharmony_ci pa_assert(key); 66053a5a1b3Sopenharmony_ci 66153a5a1b3Sopenharmony_ci pa_proplist_setf(f->plist, key, "{ \"" PA_JSON_MIN_KEY "\": %d, \"" PA_JSON_MAX_KEY "\": %d }", 66253a5a1b3Sopenharmony_ci min, max); 66353a5a1b3Sopenharmony_ci} 66453a5a1b3Sopenharmony_ci 66553a5a1b3Sopenharmony_civoid pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) { 66653a5a1b3Sopenharmony_ci pa_assert(f); 66753a5a1b3Sopenharmony_ci pa_assert(key); 66853a5a1b3Sopenharmony_ci 66953a5a1b3Sopenharmony_ci pa_proplist_setf(f->plist, key, "\"%s\"", value); 67053a5a1b3Sopenharmony_ci} 67153a5a1b3Sopenharmony_ci 67253a5a1b3Sopenharmony_civoid pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) { 67353a5a1b3Sopenharmony_ci pa_strbuf *buf; 67453a5a1b3Sopenharmony_ci char *str; 67553a5a1b3Sopenharmony_ci int i; 67653a5a1b3Sopenharmony_ci 67753a5a1b3Sopenharmony_ci pa_assert(f); 67853a5a1b3Sopenharmony_ci pa_assert(key); 67953a5a1b3Sopenharmony_ci 68053a5a1b3Sopenharmony_ci buf = pa_strbuf_new(); 68153a5a1b3Sopenharmony_ci 68253a5a1b3Sopenharmony_ci pa_strbuf_printf(buf, "[ \"%s\"", values[0]); 68353a5a1b3Sopenharmony_ci 68453a5a1b3Sopenharmony_ci for (i = 1; i < n_values; i++) 68553a5a1b3Sopenharmony_ci pa_strbuf_printf(buf, ", \"%s\"", values[i]); 68653a5a1b3Sopenharmony_ci 68753a5a1b3Sopenharmony_ci pa_strbuf_printf(buf, " ]"); 68853a5a1b3Sopenharmony_ci str = pa_strbuf_to_string_free(buf); 68953a5a1b3Sopenharmony_ci 69053a5a1b3Sopenharmony_ci pa_proplist_sets(f->plist, key, str); 69153a5a1b3Sopenharmony_ci pa_xfree (str); 69253a5a1b3Sopenharmony_ci} 69353a5a1b3Sopenharmony_ci 69453a5a1b3Sopenharmony_cistatic bool pa_json_is_fixed_type(pa_json_object *o) { 69553a5a1b3Sopenharmony_ci switch(pa_json_object_get_type(o)) { 69653a5a1b3Sopenharmony_ci case PA_JSON_TYPE_OBJECT: 69753a5a1b3Sopenharmony_ci case PA_JSON_TYPE_ARRAY: 69853a5a1b3Sopenharmony_ci return false; 69953a5a1b3Sopenharmony_ci 70053a5a1b3Sopenharmony_ci default: 70153a5a1b3Sopenharmony_ci return true; 70253a5a1b3Sopenharmony_ci } 70353a5a1b3Sopenharmony_ci} 70453a5a1b3Sopenharmony_ci 70553a5a1b3Sopenharmony_cistatic int pa_format_info_prop_compatible(const char *one, const char *two) { 70653a5a1b3Sopenharmony_ci pa_json_object *o1 = NULL, *o2 = NULL; 70753a5a1b3Sopenharmony_ci int i, ret = 0; 70853a5a1b3Sopenharmony_ci 70953a5a1b3Sopenharmony_ci o1 = pa_json_parse(one); 71053a5a1b3Sopenharmony_ci if (!o1) 71153a5a1b3Sopenharmony_ci goto out; 71253a5a1b3Sopenharmony_ci 71353a5a1b3Sopenharmony_ci o2 = pa_json_parse(two); 71453a5a1b3Sopenharmony_ci if (!o2) 71553a5a1b3Sopenharmony_ci goto out; 71653a5a1b3Sopenharmony_ci 71753a5a1b3Sopenharmony_ci /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */ 71853a5a1b3Sopenharmony_ci pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), false); 71953a5a1b3Sopenharmony_ci 72053a5a1b3Sopenharmony_ci if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) { 72153a5a1b3Sopenharmony_ci ret = pa_json_object_equal(o1, o2); 72253a5a1b3Sopenharmony_ci goto out; 72353a5a1b3Sopenharmony_ci } 72453a5a1b3Sopenharmony_ci 72553a5a1b3Sopenharmony_ci if (pa_json_is_fixed_type(o1)) { 72653a5a1b3Sopenharmony_ci pa_json_object *tmp = o2; 72753a5a1b3Sopenharmony_ci o2 = o1; 72853a5a1b3Sopenharmony_ci o1 = tmp; 72953a5a1b3Sopenharmony_ci } 73053a5a1b3Sopenharmony_ci 73153a5a1b3Sopenharmony_ci /* o2 is now a fixed type, and o1 is not */ 73253a5a1b3Sopenharmony_ci 73353a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o1) == PA_JSON_TYPE_ARRAY) { 73453a5a1b3Sopenharmony_ci for (i = 0; i < pa_json_object_get_array_length(o1); i++) { 73553a5a1b3Sopenharmony_ci if (pa_json_object_equal(pa_json_object_get_array_member(o1, i), o2)) { 73653a5a1b3Sopenharmony_ci ret = 1; 73753a5a1b3Sopenharmony_ci break; 73853a5a1b3Sopenharmony_ci } 73953a5a1b3Sopenharmony_ci } 74053a5a1b3Sopenharmony_ci } else if (pa_json_object_get_type(o1) == PA_JSON_TYPE_OBJECT) { 74153a5a1b3Sopenharmony_ci /* o1 should be a range type */ 74253a5a1b3Sopenharmony_ci int min, max, v; 74353a5a1b3Sopenharmony_ci const pa_json_object *o_min = NULL, *o_max = NULL; 74453a5a1b3Sopenharmony_ci 74553a5a1b3Sopenharmony_ci if (pa_json_object_get_type(o2) != PA_JSON_TYPE_INT) { 74653a5a1b3Sopenharmony_ci /* We don't support non-integer ranges */ 74753a5a1b3Sopenharmony_ci goto out; 74853a5a1b3Sopenharmony_ci } 74953a5a1b3Sopenharmony_ci 75053a5a1b3Sopenharmony_ci if (!(o_min = pa_json_object_get_object_member(o1, PA_JSON_MIN_KEY)) || 75153a5a1b3Sopenharmony_ci pa_json_object_get_type(o_min) != PA_JSON_TYPE_INT) 75253a5a1b3Sopenharmony_ci goto out; 75353a5a1b3Sopenharmony_ci 75453a5a1b3Sopenharmony_ci if (!(o_max = pa_json_object_get_object_member(o1, PA_JSON_MAX_KEY)) || 75553a5a1b3Sopenharmony_ci pa_json_object_get_type(o_max) != PA_JSON_TYPE_INT) 75653a5a1b3Sopenharmony_ci goto out; 75753a5a1b3Sopenharmony_ci 75853a5a1b3Sopenharmony_ci v = pa_json_object_get_int(o2); 75953a5a1b3Sopenharmony_ci min = pa_json_object_get_int(o_min); 76053a5a1b3Sopenharmony_ci max = pa_json_object_get_int(o_max); 76153a5a1b3Sopenharmony_ci 76253a5a1b3Sopenharmony_ci ret = v >= min && v <= max; 76353a5a1b3Sopenharmony_ci } else { 76453a5a1b3Sopenharmony_ci pa_log_warn("Got a format type that we don't support"); 76553a5a1b3Sopenharmony_ci } 76653a5a1b3Sopenharmony_ci 76753a5a1b3Sopenharmony_ciout: 76853a5a1b3Sopenharmony_ci if (o1) 76953a5a1b3Sopenharmony_ci pa_json_object_free(o1); 77053a5a1b3Sopenharmony_ci if (o2) 77153a5a1b3Sopenharmony_ci pa_json_object_free(o2); 77253a5a1b3Sopenharmony_ci 77353a5a1b3Sopenharmony_ci return ret; 77453a5a1b3Sopenharmony_ci} 775