json: remove json from public API
[platform/upstream/pulseaudio.git] / src / pulse / format.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2011 Intel Corporation
5   Copyright 2011 Collabora Multimedia
6   Copyright 2011 Arun Raghavan <arun.raghavan@collabora.co.uk>
7
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.
12
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.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <pulse/internal.h>
27 #include <pulse/xmalloc.h>
28
29 #include <pulsecore/core-format.h>
30 #include <pulsecore/core-util.h>
31 #include <pulsecore/i18n.h>
32 #include <pulsecore/json.h>
33 #include <pulsecore/macro.h>
34 #include <pulsecore/strbuf.h>
35
36 #include "format.h"
37
38 #define PA_JSON_MIN_KEY "min"
39 #define PA_JSON_MAX_KEY "max"
40
41 static int pa_format_info_prop_compatible(const char *one, const char *two);
42
43 static const char* const _encoding_str_table[]= {
44     [PA_ENCODING_PCM] = "pcm",
45     [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
46     [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
47     [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
48     [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
49     [PA_ENCODING_MPEG2_AAC_IEC61937] = "mpeg2-aac-iec61937",
50     [PA_ENCODING_TRUEHD_IEC61937] = "truehd-iec61937",
51     [PA_ENCODING_DTSHD_IEC61937] = "dtshd-iec61937",
52     [PA_ENCODING_ANY] = "any",
53 };
54
55 const char *pa_encoding_to_string(pa_encoding_t e) {
56     if (e < 0 || e >= PA_ENCODING_MAX)
57         return NULL;
58
59     return _encoding_str_table[e];
60 }
61
62 pa_encoding_t pa_encoding_from_string(const char *encoding) {
63     pa_encoding_t e;
64
65     for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
66         if (pa_streq(_encoding_str_table[e], encoding))
67             return e;
68
69     return PA_ENCODING_INVALID;
70 }
71
72 pa_format_info* pa_format_info_new(void) {
73     pa_format_info *f = pa_xnew(pa_format_info, 1);
74
75     f->encoding = PA_ENCODING_INVALID;
76     f->plist = pa_proplist_new();
77
78     return f;
79 }
80
81 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
82     pa_format_info *dest;
83
84     pa_assert(src);
85
86     dest = pa_xnew(pa_format_info, 1);
87
88     dest->encoding = src->encoding;
89
90     if (src->plist)
91         dest->plist = pa_proplist_copy(src->plist);
92     else
93         dest->plist = NULL;
94
95     return dest;
96 }
97
98 void pa_format_info_free(pa_format_info *f) {
99     pa_assert(f);
100
101     pa_proplist_free(f->plist);
102     pa_xfree(f);
103 }
104
105 int pa_format_info_valid(const pa_format_info *f) {
106     return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
107 }
108
109 int pa_format_info_is_pcm(const pa_format_info *f) {
110     return f->encoding == PA_ENCODING_PCM;
111 }
112
113 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
114     char *tmp;
115
116     pa_assert(s);
117     pa_assert(l > 0);
118     pa_assert(f);
119
120     pa_init_i18n();
121
122     if (!pa_format_info_valid(f))
123         pa_snprintf(s, l, _("(invalid)"));
124     else {
125         tmp = pa_proplist_to_string_sep(f->plist, "  ");
126         if (tmp[0])
127             pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
128         else
129             pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
130         pa_xfree(tmp);
131     }
132
133     return s;
134 }
135
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;
139     size_t pos;
140
141     pos = strcspn(str, ",");
142
143     encoding = pa_xstrndup(str, pos);
144     f->encoding = pa_encoding_from_string(pa_strip(encoding));
145     if (f->encoding == PA_ENCODING_INVALID)
146         goto error;
147
148     if (pos != strlen(str)) {
149         pa_proplist *plist;
150
151         properties = pa_xstrdup(&str[pos+1]);
152         plist = pa_proplist_from_string(properties);
153
154         if (!plist)
155             goto error;
156
157         pa_proplist_free(f->plist);
158         f->plist = plist;
159     }
160
161 out:
162     if (encoding)
163         pa_xfree(encoding);
164     if (properties)
165         pa_xfree(properties);
166     return f;
167
168 error:
169     pa_format_info_free(f);
170     f = NULL;
171     goto out;
172 }
173
174 int pa_format_info_is_compatible(const pa_format_info *first, const pa_format_info *second) {
175     const char *key;
176     void *state = NULL;
177
178     pa_assert(first);
179     pa_assert(second);
180
181     if (first->encoding != second->encoding)
182         return false;
183
184     while ((key = pa_proplist_iterate(first->plist, &state))) {
185         const char *value_one, *value_two;
186
187         value_one = pa_proplist_gets(first->plist, key);
188         value_two = pa_proplist_gets(second->plist, key);
189
190         if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
191             return false;
192     }
193
194     return true;
195 }
196
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];
199     pa_format_info *f;
200
201     pa_assert(ss && pa_sample_spec_valid(ss));
202     pa_assert(!map || pa_channel_map_valid(map));
203
204     f = pa_format_info_new();
205     f->encoding = PA_ENCODING_PCM;
206
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);
210
211     if (map) {
212         pa_channel_map_snprint(cm, sizeof(cm), map);
213         pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
214     }
215
216     return f;
217 }
218
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) {
221     pa_assert(f);
222     pa_assert(ss);
223
224     if (!pa_format_info_is_pcm(f))
225         return pa_format_info_to_sample_spec_fake(f, ss, map);
226
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;
235
236     return 0;
237 }
238
239 pa_prop_type_t pa_format_info_get_prop_type(const pa_format_info *f, const char *key) {
240     const char *str;
241     pa_json_object *o;
242     const pa_json_object *o1;
243     pa_prop_type_t type;
244
245     pa_assert(f);
246     pa_assert(key);
247
248     str = pa_proplist_gets(f->plist, key);
249     if (!str)
250         return PA_PROP_TYPE_INVALID;
251
252     o = pa_json_parse(str);
253     if (!o)
254         return PA_PROP_TYPE_INVALID;
255
256     switch (pa_json_object_get_type(o)) {
257         case PA_JSON_TYPE_INT:
258             type = PA_PROP_TYPE_INT;
259             break;
260
261         case PA_JSON_TYPE_STRING:
262             type = PA_PROP_TYPE_STRING;
263             break;
264
265         case PA_JSON_TYPE_ARRAY:
266             if (pa_json_object_get_array_length(o) == 0) {
267                 /* Unlikely, but let's account for this anyway. We need at
268                  * least one element to figure out the array type. */
269                 type = PA_PROP_TYPE_INVALID;
270                 break;
271             }
272
273             o1 = pa_json_object_get_array_member(o, 0);
274
275             if (pa_json_object_get_type(o1) == PA_JSON_TYPE_INT)
276                 type = PA_PROP_TYPE_INT_ARRAY;
277             else if (pa_json_object_get_type(o1) == PA_JSON_TYPE_STRING)
278                 type = PA_PROP_TYPE_STRING_ARRAY;
279             else
280                 type = PA_PROP_TYPE_INVALID;
281
282             break;
283
284         case PA_JSON_TYPE_OBJECT:
285             /* We actually know at this point that it's a int range, but let's
286              * confirm. */
287             if (!pa_json_object_get_object_member(o, PA_JSON_MIN_KEY)) {
288                 type = PA_PROP_TYPE_INVALID;
289                 break;
290             }
291
292             if (!pa_json_object_get_object_member(o, PA_JSON_MAX_KEY)) {
293                 type = PA_PROP_TYPE_INVALID;
294                 break;
295             }
296
297             type = PA_PROP_TYPE_INT_RANGE;
298             break;
299
300         default:
301             type = PA_PROP_TYPE_INVALID;
302             break;
303     }
304
305     pa_json_object_free(o);
306     return type;
307 }
308
309 int pa_format_info_get_prop_int(const pa_format_info *f, const char *key, int *v) {
310     const char *str;
311     pa_json_object *o;
312
313     pa_assert(f);
314     pa_assert(key);
315     pa_assert(v);
316
317     str = pa_proplist_gets(f->plist, key);
318     if (!str)
319         return -PA_ERR_NOENTITY;
320
321     o = pa_json_parse(str);
322     if (!o) {
323         pa_log_debug("Failed to parse format info property '%s'.", key);
324         return -PA_ERR_INVALID;
325     }
326
327     if (pa_json_object_get_type(o) != PA_JSON_TYPE_INT) {
328         pa_log_debug("Format info property '%s' type is not int.", key);
329         pa_json_object_free(o);
330         return -PA_ERR_INVALID;
331     }
332
333     *v = pa_json_object_get_int(o);
334     pa_json_object_free(o);
335
336     return 0;
337 }
338
339 int pa_format_info_get_prop_int_range(const pa_format_info *f, const char *key, int *min, int *max) {
340     const char *str;
341     pa_json_object *o;
342     const pa_json_object *o1;
343     int ret = -PA_ERR_INVALID;
344
345     pa_assert(f);
346     pa_assert(key);
347     pa_assert(min);
348     pa_assert(max);
349
350     str = pa_proplist_gets(f->plist, key);
351     if (!str)
352         return -PA_ERR_NOENTITY;
353
354     o = pa_json_parse(str);
355     if (!o) {
356         pa_log_debug("Failed to parse format info property '%s'.", key);
357         return -PA_ERR_INVALID;
358     }
359
360     if (pa_json_object_get_type(o) != PA_JSON_TYPE_OBJECT)
361         goto out;
362
363     if (!(o1 = pa_json_object_get_object_member(o, PA_JSON_MIN_KEY)) ||
364             (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT))
365         goto out;
366
367     *min = pa_json_object_get_int(o1);
368
369     if (!(o1 = pa_json_object_get_object_member(o, PA_JSON_MAX_KEY)) ||
370             (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT))
371         goto out;
372
373     *max = pa_json_object_get_int(o1);
374
375     ret = 0;
376
377 out:
378     if (ret < 0)
379         pa_log_debug("Format info property '%s' is not a valid int range.", key);
380
381     pa_json_object_free(o);
382     return ret;
383 }
384
385 int pa_format_info_get_prop_int_array(const pa_format_info *f, const char *key, int **values, int *n_values) {
386     const char *str;
387     pa_json_object *o;
388     const pa_json_object *o1;
389     int i, ret = -PA_ERR_INVALID;
390
391     pa_assert(f);
392     pa_assert(key);
393     pa_assert(values);
394     pa_assert(n_values);
395
396     str = pa_proplist_gets(f->plist, key);
397     if (!str)
398         return -PA_ERR_NOENTITY;
399
400     o = pa_json_parse(str);
401     if (!o) {
402         pa_log_debug("Failed to parse format info property '%s'.", key);
403         return -PA_ERR_INVALID;
404     }
405
406     if (pa_json_object_get_type(o) != PA_JSON_TYPE_ARRAY)
407         goto out;
408
409     *n_values = pa_json_object_get_array_length(o);
410     *values = pa_xnew(int, *n_values);
411
412     for (i = 0; i < *n_values; i++) {
413         o1 = pa_json_object_get_array_member(o, i);
414
415         if (pa_json_object_get_type(o1) != PA_JSON_TYPE_INT) {
416             goto out;
417         }
418
419         (*values)[i] = pa_json_object_get_int(o1);
420     }
421
422     ret = 0;
423
424 out:
425     if (ret < 0)
426         pa_log_debug("Format info property '%s' is not a valid int array.", key);
427
428     pa_json_object_free(o);
429     return ret;
430 }
431
432 int pa_format_info_get_prop_string(const pa_format_info *f, const char *key, char **v) {
433     const char *str = NULL;
434     pa_json_object *o;
435
436     pa_assert(f);
437     pa_assert(key);
438     pa_assert(v);
439
440     str = pa_proplist_gets(f->plist, key);
441     if (!str)
442         return -PA_ERR_NOENTITY;
443
444     o = pa_json_parse(str);
445     if (!o) {
446         pa_log_debug("Failed to parse format info property '%s'.", key);
447         return -PA_ERR_INVALID;
448     }
449
450     if (pa_json_object_get_type(o) != PA_JSON_TYPE_STRING) {
451         pa_log_debug("Format info property '%s' type is not string.", key);
452         pa_json_object_free(o);
453         return -PA_ERR_INVALID;
454     }
455
456     *v = pa_xstrdup(pa_json_object_get_string(o));
457     pa_json_object_free(o);
458
459     return 0;
460 }
461
462 int pa_format_info_get_prop_string_array(const pa_format_info *f, const char *key, char ***values, int *n_values) {
463     const char *str;
464     pa_json_object *o;
465     const pa_json_object *o1;
466     int i, ret = -PA_ERR_INVALID;
467
468     pa_assert(f);
469     pa_assert(key);
470     pa_assert(values);
471     pa_assert(n_values);
472
473     str = pa_proplist_gets(f->plist, key);
474     if (!str)
475         return -PA_ERR_NOENTITY;
476
477     o = pa_json_parse(str);
478     if (!o) {
479         pa_log_debug("Failed to parse format info property '%s'.", key);
480         return -PA_ERR_INVALID;
481     }
482
483     if (pa_json_object_get_type(o) != PA_JSON_TYPE_ARRAY)
484         goto out;
485
486     *n_values = pa_json_object_get_array_length(o);
487     *values = pa_xnew(char *, *n_values);
488
489     for (i = 0; i < *n_values; i++) {
490         o1 = pa_json_object_get_array_member(o, i);
491
492         if (pa_json_object_get_type(o1) != PA_JSON_TYPE_STRING) {
493             goto out;
494         }
495
496         (*values)[i] = pa_xstrdup(pa_json_object_get_string(o1));
497     }
498
499     ret = 0;
500
501 out:
502     if (ret < 0)
503         pa_log_debug("Format info property '%s' is not a valid string array.", key);
504
505     pa_json_object_free(o);
506     return ret;
507 }
508
509 void pa_format_info_free_string_array(char **values, int n_values) {
510     int i;
511
512     for (i = 0; i < n_values; i++)
513         pa_xfree(values[i]);
514
515     pa_xfree(values);
516 }
517
518 int pa_format_info_get_sample_format(const pa_format_info *f, pa_sample_format_t *sf) {
519     int r;
520     char *sf_str;
521     pa_sample_format_t sf_local;
522
523     pa_assert(f);
524     pa_assert(sf);
525
526     r = pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf_str);
527     if (r < 0)
528         return r;
529
530     sf_local = pa_parse_sample_format(sf_str);
531     pa_xfree(sf_str);
532
533     if (!pa_sample_format_valid(sf_local)) {
534         pa_log_debug("Invalid sample format.");
535         return -PA_ERR_INVALID;
536     }
537
538     *sf = sf_local;
539
540     return 0;
541 }
542
543 int pa_format_info_get_rate(const pa_format_info *f, uint32_t *rate) {
544     int r;
545     int rate_local;
546
547     pa_assert(f);
548     pa_assert(rate);
549
550     r = pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate_local);
551     if (r < 0)
552         return r;
553
554     if (!pa_sample_rate_valid(rate_local)) {
555         pa_log_debug("Invalid sample rate: %i", rate_local);
556         return -PA_ERR_INVALID;
557     }
558
559     *rate = rate_local;
560
561     return 0;
562 }
563
564 int pa_format_info_get_channels(const pa_format_info *f, uint8_t *channels) {
565     int r;
566     int channels_local;
567
568     pa_assert(f);
569     pa_assert(channels);
570
571     r = pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels_local);
572     if (r < 0)
573         return r;
574
575     if (!pa_channels_valid(channels_local)) {
576         pa_log_debug("Invalid channel count: %i", channels_local);
577         return -PA_ERR_INVALID;
578     }
579
580     *channels = channels_local;
581
582     return 0;
583 }
584
585 int pa_format_info_get_channel_map(const pa_format_info *f, pa_channel_map *map) {
586     int r;
587     char *map_str;
588
589     pa_assert(f);
590     pa_assert(map);
591
592     r = pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &map_str);
593     if (r < 0)
594         return r;
595
596     map = pa_channel_map_parse(map, map_str);
597     pa_xfree(map_str);
598
599     if (!map) {
600         pa_log_debug("Failed to parse channel map.");
601         return -PA_ERR_INVALID;
602     }
603
604     return 0;
605 }
606
607 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
608     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
609 }
610
611 void pa_format_info_set_rate(pa_format_info *f, int rate) {
612     pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
613 }
614
615 void pa_format_info_set_channels(pa_format_info *f, int channels) {
616     pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
617 }
618
619 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
620     char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
621
622     pa_channel_map_snprint(map_str, sizeof(map_str), map);
623
624     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
625 }
626
627 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
628     pa_assert(f);
629     pa_assert(key);
630
631     pa_proplist_setf(f->plist, key, "%d", value);
632 }
633
634 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
635     pa_strbuf *buf;
636     char *str;
637     int i;
638
639     pa_assert(f);
640     pa_assert(key);
641     pa_assert(n_values > 0);
642
643     buf = pa_strbuf_new();
644
645     pa_strbuf_printf(buf, "[ %d", values[0]);
646
647     for (i = 1; i < n_values; i++)
648         pa_strbuf_printf(buf, ", %d", values[i]);
649
650     pa_strbuf_printf(buf, " ]");
651     str = pa_strbuf_to_string_free(buf);
652
653     pa_proplist_sets(f->plist, key, str);
654     pa_xfree (str);
655 }
656
657 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
658     pa_assert(f);
659     pa_assert(key);
660
661     pa_proplist_setf(f->plist, key, "{ \"" PA_JSON_MIN_KEY "\": %d, \"" PA_JSON_MAX_KEY "\": %d }",
662             min, max);
663 }
664
665 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
666     pa_assert(f);
667     pa_assert(key);
668
669     pa_proplist_setf(f->plist, key, "\"%s\"", value);
670 }
671
672 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
673     pa_strbuf *buf;
674     char *str;
675     int i;
676
677     pa_assert(f);
678     pa_assert(key);
679
680     buf = pa_strbuf_new();
681
682     pa_strbuf_printf(buf, "[ \"%s\"", values[0]);
683
684     for (i = 1; i < n_values; i++)
685         pa_strbuf_printf(buf, ", \"%s\"", values[i]);
686
687     pa_strbuf_printf(buf, " ]");
688     str = pa_strbuf_to_string_free(buf);
689
690     pa_proplist_sets(f->plist, key, str);
691     pa_xfree (str);
692 }
693
694 static bool pa_json_is_fixed_type(pa_json_object *o) {
695     switch(pa_json_object_get_type(o)) {
696         case PA_JSON_TYPE_OBJECT:
697         case PA_JSON_TYPE_ARRAY:
698             return false;
699
700         default:
701             return true;
702     }
703 }
704
705 static int pa_format_info_prop_compatible(const char *one, const char *two) {
706     pa_json_object *o1 = NULL, *o2 = NULL;
707     int i, ret = 0;
708
709     o1 = pa_json_parse(one);
710     if (!o1)
711         goto out;
712
713     o2 = pa_json_parse(two);
714     if (!o2)
715         goto out;
716
717     /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
718     pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), false);
719
720     if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
721         ret = pa_json_object_equal(o1, o2);
722         goto out;
723     }
724
725     if (pa_json_is_fixed_type(o1)) {
726         pa_json_object *tmp = o2;
727         o2 = o1;
728         o1 = tmp;
729     }
730
731     /* o2 is now a fixed type, and o1 is not */
732
733     if (pa_json_object_get_type(o1) == PA_JSON_TYPE_ARRAY) {
734         for (i = 0; i < pa_json_object_get_array_length(o1); i++) {
735             if (pa_json_object_equal(pa_json_object_get_array_member(o1, i), o2)) {
736                 ret = 1;
737                 break;
738             }
739         }
740     } else if (pa_json_object_get_type(o1) == PA_JSON_TYPE_OBJECT) {
741         /* o1 should be a range type */
742         int min, max, v;
743         const pa_json_object *o_min = NULL, *o_max = NULL;
744
745         if (pa_json_object_get_type(o2) != PA_JSON_TYPE_INT) {
746             /* We don't support non-integer ranges */
747             goto out;
748         }
749
750         if (!(o_min = pa_json_object_get_object_member(o1, PA_JSON_MIN_KEY)) ||
751             pa_json_object_get_type(o_min) != PA_JSON_TYPE_INT)
752             goto out;
753
754         if (!(o_max = pa_json_object_get_object_member(o1, PA_JSON_MAX_KEY)) ||
755             pa_json_object_get_type(o_max) != PA_JSON_TYPE_INT)
756             goto out;
757
758         v = pa_json_object_get_int(o2);
759         min = pa_json_object_get_int(o_min);
760         max = pa_json_object_get_int(o_max);
761
762         ret = v >= min && v <= max;
763     } else {
764         pa_log_warn("Got a format type that we don't support");
765     }
766
767 out:
768     if (o1)
769         pa_json_object_free(o1);
770     if (o2)
771         pa_json_object_free(o2);
772
773     return ret;
774 }