format: Don't _put() objects obtained with json_object_object_get() or json_object_ar...
[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, write to the Free Software
20   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21   USA.
22 ***/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <json.h>
29
30 #include <pulse/internal.h>
31 #include <pulse/xmalloc.h>
32
33 #include <pulsecore/core-format.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/i18n.h>
36 #include <pulsecore/macro.h>
37
38 #include "format.h"
39
40 #define PA_JSON_MIN_KEY "min"
41 #define PA_JSON_MAX_KEY "max"
42
43 static int pa_format_info_prop_compatible(const char *one, const char *two);
44
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",
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     json_object *o, *o1;
242     pa_prop_type_t type;
243
244     pa_assert(f);
245     pa_assert(key);
246
247     str = pa_proplist_gets(f->plist, key);
248     if (!str)
249         return PA_PROP_TYPE_INVALID;
250
251     o = json_tokener_parse(str);
252     if (is_error(o))
253         return PA_PROP_TYPE_INVALID;
254
255     switch (json_object_get_type(o)) {
256         case json_type_int:
257             type = PA_PROP_TYPE_INT;
258             break;
259
260         case json_type_string:
261             type = PA_PROP_TYPE_STRING;
262             break;
263
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;
269                 break;
270             }
271
272             o1 = json_object_array_get_idx(o, 1);
273
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;
278             else
279                 type = PA_PROP_TYPE_INVALID;
280
281             break;
282
283         case json_type_object:
284             /* We actually know at this point that it's a int range, but let's
285              * confirm. */
286             o1 = json_object_object_get(o, PA_JSON_MIN_KEY);
287             if (!o1) {
288                 type = PA_PROP_TYPE_INVALID;
289                 break;
290             }
291
292             o1 = json_object_object_get(o, PA_JSON_MAX_KEY);
293             if (!o1) {
294                 type = PA_PROP_TYPE_INVALID;
295                 break;
296             }
297
298             type = PA_PROP_TYPE_INT_RANGE;
299             break;
300
301         default:
302             type = PA_PROP_TYPE_INVALID;
303             break;
304     }
305
306     json_object_put(o);
307     return type;
308 }
309
310 int pa_format_info_get_prop_int(const pa_format_info *f, const char *key, int *v) {
311     const char *str;
312     json_object *o;
313
314     pa_assert(f);
315     pa_assert(key);
316     pa_assert(v);
317
318     str = pa_proplist_gets(f->plist, key);
319     if (!str)
320         return -PA_ERR_NOENTITY;
321
322     o = json_tokener_parse(str);
323     if (is_error(o)) {
324         pa_log_debug("Failed to parse format info property '%s'.", key);
325         return -PA_ERR_INVALID;
326     }
327
328     if (json_object_get_type(o) != json_type_int) {
329         pa_log_debug("Format info property '%s' type is not int.", key);
330         json_object_put(o);
331         return -PA_ERR_INVALID;
332     }
333
334     *v = json_object_get_int(o);
335     json_object_put(o);
336
337     return 0;
338 }
339
340 int pa_format_info_get_prop_int_range(const pa_format_info *f, const char *key, int *min, int *max) {
341     const char *str;
342     json_object *o, *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 = json_tokener_parse(str);
355     if (is_error(o)) {
356         pa_log_debug("Failed to parse format info property '%s'.", key);
357         return -PA_ERR_INVALID;
358     }
359
360     if (json_object_get_type(o) != json_type_object)
361         goto out;
362
363     if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
364         goto out;
365
366     *min = json_object_get_int(o1);
367
368     if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
369         goto out;
370
371     *max = json_object_get_int(o1);
372
373     ret = 0;
374
375 out:
376     if (ret < 0)
377         pa_log_debug("Format info property '%s' is not a valid int range.", key);
378
379     json_object_put(o);
380     return ret;
381 }
382
383 int pa_format_info_get_prop_int_array(const pa_format_info *f, const char *key, int **values, int *n_values) {
384     const char *str;
385     json_object *o, *o1;
386     int i, ret = -PA_ERR_INVALID;
387
388     pa_assert(f);
389     pa_assert(key);
390     pa_assert(values);
391     pa_assert(n_values);
392
393     str = pa_proplist_gets(f->plist, key);
394     if (!str)
395         return -PA_ERR_NOENTITY;
396
397     o = json_tokener_parse(str);
398     if (is_error(o)) {
399         pa_log_debug("Failed to parse format info property '%s'.", key);
400         return -PA_ERR_INVALID;
401     }
402
403     if (json_object_get_type(o) != json_type_array)
404         goto out;
405
406     *n_values = json_object_array_length(o);
407     *values = pa_xnew(int, *n_values);
408
409     for (i = 0; i < *n_values; i++) {
410         o1 = json_object_array_get_idx(o, i);
411
412         if (json_object_get_type(o1) != json_type_int) {
413             goto out;
414         }
415
416         (*values)[i] = json_object_get_int(o1);
417     }
418
419     ret = 0;
420
421 out:
422     if (ret < 0)
423         pa_log_debug("Format info property '%s' is not a valid int array.", key);
424
425     json_object_put(o);
426     return ret;
427 }
428
429 int pa_format_info_get_prop_string(const pa_format_info *f, const char *key, char **v) {
430     const char *str = NULL;
431     json_object *o;
432
433     pa_assert(f);
434     pa_assert(key);
435     pa_assert(v);
436
437     str = pa_proplist_gets(f->plist, key);
438     if (!str)
439         return -PA_ERR_NOENTITY;
440
441     o = json_tokener_parse(str);
442     if (is_error(o)) {
443         pa_log_debug("Failed to parse format info property '%s'.", key);
444         return -PA_ERR_INVALID;
445     }
446
447     if (json_object_get_type(o) != json_type_string) {
448         pa_log_debug("Format info property '%s' type is not string.", key);
449         json_object_put(o);
450         return -PA_ERR_INVALID;
451     }
452
453     *v = pa_xstrdup(json_object_get_string(o));
454     json_object_put(o);
455
456     return 0;
457 }
458
459 int pa_format_info_get_prop_string_array(const pa_format_info *f, const char *key, char ***values, int *n_values) {
460     const char *str;
461     json_object *o, *o1;
462     int i, ret = -PA_ERR_INVALID;
463
464     pa_assert(f);
465     pa_assert(key);
466     pa_assert(values);
467     pa_assert(n_values);
468
469     str = pa_proplist_gets(f->plist, key);
470     if (!str)
471         return -PA_ERR_NOENTITY;
472
473     o = json_tokener_parse(str);
474     if (is_error(o)) {
475         pa_log_debug("Failed to parse format info property '%s'.", key);
476         return -PA_ERR_INVALID;
477     }
478
479     if (json_object_get_type(o) != json_type_array)
480         goto out;
481
482     *n_values = json_object_array_length(o);
483     *values = pa_xnew(char *, *n_values);
484
485     for (i = 0; i < *n_values; i++) {
486         o1 = json_object_array_get_idx(o, i);
487
488         if (json_object_get_type(o1) != json_type_string) {
489             goto out;
490         }
491
492         (*values)[i] = pa_xstrdup(json_object_get_string(o1));
493     }
494
495     ret = 0;
496
497 out:
498     if (ret < 0)
499         pa_log_debug("Format info property '%s' is not a valid string array.", key);
500
501     json_object_put(o);
502     return ret;
503 }
504
505 void pa_format_info_free_string_array(char **values, int n_values) {
506     int i;
507
508     for (i = 0; i < n_values; i++)
509         pa_xfree(values[i]);
510
511     pa_xfree(values);
512 }
513
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));
516 }
517
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);
520 }
521
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);
524 }
525
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];
528
529     pa_channel_map_snprint(map_str, sizeof(map_str), map);
530
531     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
532 }
533
534 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
535     json_object *o;
536
537     pa_assert(f);
538     pa_assert(key);
539
540     o = json_object_new_int(value);
541
542     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
543
544     json_object_put(o);
545 }
546
547 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
548     json_object *o;
549     int i;
550
551     pa_assert(f);
552     pa_assert(key);
553
554     o = json_object_new_array();
555
556     for (i = 0; i < n_values; i++)
557         json_object_array_add(o, json_object_new_int(values[i]));
558
559     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
560
561     json_object_put(o);
562 }
563
564 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
565     json_object *o;
566
567     pa_assert(f);
568     pa_assert(key);
569
570     o = json_object_new_object();
571
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));
574
575     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
576
577     json_object_put(o);
578 }
579
580 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
581     json_object *o;
582
583     pa_assert(f);
584     pa_assert(key);
585
586     o = json_object_new_string(value);
587
588     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
589
590     json_object_put(o);
591 }
592
593 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
594     json_object *o;
595     int i;
596
597     pa_assert(f);
598     pa_assert(key);
599
600     o = json_object_new_array();
601
602     for (i = 0; i < n_values; i++)
603         json_object_array_add(o, json_object_new_string(values[i]));
604
605     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
606
607     json_object_put(o);
608 }
609
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:
614             return false;
615
616         default:
617             return true;
618     }
619 }
620
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));
624 }
625
626 static int pa_format_info_prop_compatible(const char *one, const char *two) {
627     json_object *o1 = NULL, *o2 = NULL;
628     int i, ret = 0;
629
630     o1 = json_tokener_parse(one);
631     if (is_error(o1))
632         goto out;
633
634     o2 = json_tokener_parse(two);
635     if (is_error(o2))
636         goto out;
637
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);
640
641     if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
642         ret = pa_json_value_equal(o1, o2);
643         goto out;
644     }
645
646     if (pa_json_is_fixed_type(o1)) {
647         json_object *tmp = o2;
648         o2 = o1;
649         o1 = tmp;
650     }
651
652     /* o2 is now a fixed type, and o1 is not */
653
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)) {
657                 ret = 1;
658                 break;
659             }
660         }
661     } else if (json_object_get_type(o1) == json_type_object) {
662         /* o1 should be a range type */
663         int min, max, v;
664         json_object *o_min = NULL, *o_max = NULL;
665
666         if (json_object_get_type(o2) != json_type_int) {
667             /* We don't support non-integer ranges */
668             goto out;
669         }
670
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)
673             goto out;
674
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)
677             goto out;
678
679         v = json_object_get_int(o2);
680         min = json_object_get_int(o_min);
681         max = json_object_get_int(o_max);
682
683         ret = v >= min && v <= max;
684     } else {
685         pa_log_warn("Got a format type that we don't support");
686     }
687
688 out:
689     if (o1)
690         json_object_put(o1);
691     if (o2)
692         json_object_put(o2);
693
694     return ret;
695 }