idxset: Use pa_free_cb_t instead of pa_free2_cb_t
[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-util.h>
34 #include <pulsecore/i18n.h>
35 #include <pulsecore/macro.h>
36
37 #include "format.h"
38
39 #define PA_JSON_MIN_KEY "min"
40 #define PA_JSON_MAX_KEY "max"
41
42 static int pa_format_info_prop_compatible(const char *one, const char *two);
43
44 static const char* const _encoding_str_table[]= {
45     [PA_ENCODING_PCM] = "pcm",
46     [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
47     [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
48     [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
49     [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
50     [PA_ENCODING_ANY] = "any",
51 };
52
53 const char *pa_encoding_to_string(pa_encoding_t e) {
54     if (e < 0 || e >= PA_ENCODING_MAX)
55         return NULL;
56
57     return _encoding_str_table[e];
58 }
59
60 pa_encoding_t pa_encoding_from_string(const char *encoding) {
61     pa_encoding_t e;
62
63     for (e = PA_ENCODING_ANY; e < PA_ENCODING_MAX; e++)
64         if (pa_streq(_encoding_str_table[e], encoding))
65             return e;
66
67     return PA_ENCODING_INVALID;
68 }
69
70 pa_format_info* pa_format_info_new(void) {
71     pa_format_info *f = pa_xnew(pa_format_info, 1);
72
73     f->encoding = PA_ENCODING_INVALID;
74     f->plist = pa_proplist_new();
75
76     return f;
77 }
78
79 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
80     pa_format_info *dest;
81
82     pa_assert(src);
83
84     dest = pa_xnew(pa_format_info, 1);
85
86     dest->encoding = src->encoding;
87
88     if (src->plist)
89         dest->plist = pa_proplist_copy(src->plist);
90     else
91         dest->plist = NULL;
92
93     return dest;
94 }
95
96 void pa_format_info_free(pa_format_info *f) {
97     pa_assert(f);
98
99     pa_proplist_free(f->plist);
100     pa_xfree(f);
101 }
102
103 int pa_format_info_valid(const pa_format_info *f) {
104     return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
105 }
106
107 int pa_format_info_is_pcm(const pa_format_info *f) {
108     return f->encoding == PA_ENCODING_PCM;
109 }
110
111 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
112     char *tmp;
113
114     pa_assert(s);
115     pa_assert(l > 0);
116     pa_assert(f);
117
118     pa_init_i18n();
119
120     if (!pa_format_info_valid(f))
121         pa_snprintf(s, l, _("(invalid)"));
122     else {
123         tmp = pa_proplist_to_string_sep(f->plist, "  ");
124         if (tmp[0])
125             pa_snprintf(s, l, "%s, %s", pa_encoding_to_string(f->encoding), tmp);
126         else
127             pa_snprintf(s, l, "%s", pa_encoding_to_string(f->encoding));
128         pa_xfree(tmp);
129     }
130
131     return s;
132 }
133
134 pa_format_info* pa_format_info_from_string(const char *str) {
135     pa_format_info *f = pa_format_info_new();
136     char *encoding = NULL, *properties = NULL;
137     size_t pos;
138
139     pos = strcspn(str, ",");
140
141     encoding = pa_xstrndup(str, pos);
142     f->encoding = pa_encoding_from_string(pa_strip(encoding));
143     if (f->encoding == PA_ENCODING_INVALID)
144         goto error;
145
146     if (pos != strlen(str)) {
147         pa_proplist *plist;
148
149         properties = pa_xstrdup(&str[pos+1]);
150         plist = pa_proplist_from_string(properties);
151
152         if (!plist)
153             goto error;
154
155         pa_proplist_free(f->plist);
156         f->plist = plist;
157     }
158
159 out:
160     if (encoding)
161         pa_xfree(encoding);
162     if (properties)
163         pa_xfree(properties);
164     return f;
165
166 error:
167     pa_format_info_free(f);
168     f = NULL;
169     goto out;
170 }
171
172 int pa_format_info_is_compatible(pa_format_info *first, pa_format_info *second) {
173     const char *key;
174     void *state = NULL;
175
176     pa_assert(first);
177     pa_assert(second);
178
179     if (first->encoding != second->encoding)
180         return FALSE;
181
182     while ((key = pa_proplist_iterate(first->plist, &state))) {
183         const char *value_one, *value_two;
184
185         value_one = pa_proplist_gets(first->plist, key);
186         value_two = pa_proplist_gets(second->plist, key);
187
188         if (!value_two || !pa_format_info_prop_compatible(value_one, value_two))
189             return FALSE;
190     }
191
192     return TRUE;
193 }
194
195 pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map) {
196     char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
197     pa_format_info *f;
198
199     pa_assert(ss && pa_sample_spec_valid(ss));
200     pa_assert(!map || pa_channel_map_valid(map));
201
202     f = pa_format_info_new();
203     f->encoding = PA_ENCODING_PCM;
204
205     pa_format_info_set_sample_format(f, ss->format);
206     pa_format_info_set_rate(f, ss->rate);
207     pa_format_info_set_channels(f, ss->channels);
208
209     if (map) {
210         pa_channel_map_snprint(cm, sizeof(cm), map);
211         pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, cm);
212     }
213
214     return f;
215 }
216
217 /* For compressed streams */
218 static int pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
219     int rate;
220
221     pa_assert(f);
222     pa_assert(ss);
223
224     /* Note: When we add support for non-IEC61937 encapsulated compressed
225      * formats, this function should return a non-zero values for these. */
226
227     ss->format = PA_SAMPLE_S16LE;
228     ss->channels = 2;
229
230     pa_return_val_if_fail(pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate) == 0, -PA_ERR_INVALID);
231     ss->rate = (uint32_t) rate;
232
233     if (f->encoding == PA_ENCODING_EAC3_IEC61937)
234         ss->rate *= 4;
235
236     return 0;
237 }
238
239 /* For PCM streams */
240 int pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
241     char *sf = NULL, *m = NULL;
242     int rate, channels;
243     int ret = -PA_ERR_INVALID;
244
245     pa_assert(f);
246     pa_assert(ss);
247
248     if (!pa_format_info_is_pcm(f))
249         return pa_format_info_to_sample_spec_fake(f, ss);
250
251     if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, &sf))
252         goto out;
253     if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_RATE, &rate))
254         goto out;
255     if (pa_format_info_get_prop_int(f, PA_PROP_FORMAT_CHANNELS, &channels))
256         goto out;
257
258     if ((ss->format = pa_parse_sample_format(sf)) == PA_SAMPLE_INVALID)
259         goto out;
260
261     ss->rate = (uint32_t) rate;
262     ss->channels = (uint8_t) channels;
263
264     if (map) {
265         pa_channel_map_init(map);
266
267         if (pa_format_info_get_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, &m) == 0)
268             if (pa_channel_map_parse(map, m) == NULL)
269                 goto out;
270     }
271
272     ret = 0;
273
274 out:
275     if (sf)
276         pa_xfree(sf);
277     if (m)
278         pa_xfree(m);
279
280     return ret;
281 }
282
283 pa_prop_type_t pa_format_info_get_prop_type(pa_format_info *f, const char *key) {
284     const char *str;
285     json_object *o, *o1;
286     pa_prop_type_t type;
287
288     pa_assert(f);
289     pa_assert(key);
290
291     str = pa_proplist_gets(f->plist, key);
292     if (!str)
293         return PA_PROP_TYPE_INVALID;
294
295     o = json_tokener_parse(str);
296     if (is_error(o))
297         return PA_PROP_TYPE_INVALID;
298
299     switch (json_object_get_type(o)) {
300         case json_type_int:
301             type = PA_PROP_TYPE_INT;
302             break;
303
304         case json_type_string:
305             type = PA_PROP_TYPE_STRING;
306             break;
307
308         case json_type_array:
309             if (json_object_array_length(o) == 0) {
310                 /* Unlikely, but let's account for this anyway. We need at
311                  * least one element to figure out the array type. */
312                 type = PA_PROP_TYPE_INVALID;
313                 break;
314             }
315
316             o1 = json_object_array_get_idx(o, 1);
317
318             if (json_object_get_type(o1) == json_type_int)
319                 type = PA_PROP_TYPE_INT_ARRAY;
320             else if (json_object_get_type(o1) == json_type_string)
321                 type = PA_PROP_TYPE_STRING_ARRAY;
322             else
323                 type = PA_PROP_TYPE_INVALID;
324
325             json_object_put(o1);
326             break;
327
328         case json_type_object:
329             /* We actually know at this point that it's a int range, but let's
330              * confirm. */
331             o1 = json_object_object_get(o, PA_JSON_MIN_KEY);
332             if (!o1) {
333                 type = PA_PROP_TYPE_INVALID;
334                 break;
335             }
336             json_object_put(o1);
337
338             o1 = json_object_object_get(o, PA_JSON_MAX_KEY);
339             if (!o1) {
340                 type = PA_PROP_TYPE_INVALID;
341                 break;
342             }
343             json_object_put(o1);
344
345             type = PA_PROP_TYPE_INT_RANGE;
346             break;
347
348         default:
349             type = PA_PROP_TYPE_INVALID;
350             break;
351     }
352
353     json_object_put(o);
354     return type;
355 }
356
357 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
358     const char *str;
359     json_object *o;
360
361     pa_assert(f);
362     pa_assert(key);
363     pa_assert(v);
364
365     str = pa_proplist_gets(f->plist, key);
366     if (!str)
367         return -PA_ERR_NOENTITY;
368
369     o = json_tokener_parse(str);
370     if (is_error(o))
371         return -PA_ERR_INVALID;
372
373     if (json_object_get_type(o) != json_type_int) {
374         json_object_put(o);
375         return -PA_ERR_INVALID;
376     }
377
378     *v = json_object_get_int(o);
379     json_object_put(o);
380
381     return 0;
382 }
383
384 int pa_format_info_get_prop_int_range(pa_format_info *f, const char *key, int *min, int *max) {
385     const char *str;
386     json_object *o, *o1;
387     int ret = -PA_ERR_INVALID;
388
389     pa_assert(f);
390     pa_assert(key);
391     pa_assert(min);
392     pa_assert(max);
393
394     str = pa_proplist_gets(f->plist, key);
395     if (!str)
396         return -PA_ERR_NOENTITY;
397
398     o = json_tokener_parse(str);
399     if (is_error(o))
400         return -PA_ERR_INVALID;
401
402     if (json_object_get_type(o) != json_type_object)
403         goto out;
404
405     if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
406         goto out;
407
408     *min = json_object_get_int(o1);
409     json_object_put(o1);
410
411     if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
412         goto out;
413
414     *max = json_object_get_int(o1);
415     json_object_put(o1);
416
417     ret = 0;
418
419 out:
420     json_object_put(o);
421     return ret;
422 }
423
424 int pa_format_info_get_prop_int_array(pa_format_info *f, const char *key, int **values, int *n_values)
425 {
426     const char *str;
427     json_object *o, *o1;
428     int i, ret = -PA_ERR_INVALID;
429
430     pa_assert(f);
431     pa_assert(key);
432     pa_assert(values);
433     pa_assert(n_values);
434
435     str = pa_proplist_gets(f->plist, key);
436     if (!str)
437         return -PA_ERR_NOENTITY;
438
439     o = json_tokener_parse(str);
440     if (is_error(o))
441         return -PA_ERR_INVALID;
442
443     if (json_object_get_type(o) != json_type_array)
444         goto out;
445
446     *n_values = json_object_array_length(o);
447     *values = pa_xnew(int, *n_values);
448
449     for (i = 0; i < *n_values; i++) {
450         o1 = json_object_array_get_idx(o, i);
451
452         if (json_object_get_type(o1) != json_type_int) {
453             json_object_put(o1);
454             goto out;
455         }
456
457         (*values)[i] = json_object_get_int(o1);
458         json_object_put(o1);
459     }
460
461     ret = 0;
462
463 out:
464     json_object_put(o);
465     return ret;
466 }
467
468 int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
469     const char *str = NULL;
470     json_object *o;
471
472     pa_assert(f);
473     pa_assert(key);
474     pa_assert(v);
475
476     str = pa_proplist_gets(f->plist, key);
477     if (!str)
478         return -PA_ERR_NOENTITY;
479
480     o = json_tokener_parse(str);
481     if (is_error(o))
482         return -PA_ERR_INVALID;
483
484     if (json_object_get_type(o) != json_type_string) {
485         json_object_put(o);
486         return -PA_ERR_INVALID;
487     }
488
489     *v = pa_xstrdup(json_object_get_string(o));
490     json_object_put(o);
491
492     return 0;
493 }
494
495 int pa_format_info_get_prop_string_array(pa_format_info *f, const char *key, char ***values, int *n_values)
496 {
497     const char *str;
498     json_object *o, *o1;
499     int i, ret = -PA_ERR_INVALID;
500
501     pa_assert(f);
502     pa_assert(key);
503     pa_assert(values);
504     pa_assert(n_values);
505
506     str = pa_proplist_gets(f->plist, key);
507     if (!str)
508         return -PA_ERR_NOENTITY;
509
510     o = json_tokener_parse(str);
511     if (is_error(o))
512         return -PA_ERR_INVALID;
513
514     if (json_object_get_type(o) != json_type_array)
515         goto out;
516
517     *n_values = json_object_array_length(o);
518     *values = pa_xnew(char *, *n_values);
519
520     for (i = 0; i < *n_values; i++) {
521         o1 = json_object_array_get_idx(o, i);
522
523         if (json_object_get_type(o1) != json_type_string) {
524             json_object_put(o1);
525             goto out;
526         }
527
528         (*values)[i] = pa_xstrdup(json_object_get_string(o1));
529         json_object_put(o1);
530     }
531
532     ret = 0;
533
534 out:
535     json_object_put(o);
536     return ret;
537 }
538
539 void pa_format_info_free_string_array(char **values, int n_values) {
540     int i;
541
542     for (i = 0; i < n_values; i++)
543         pa_xfree(values[i]);
544
545     pa_xfree(values);
546 }
547
548 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
549     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
550 }
551
552 void pa_format_info_set_rate(pa_format_info *f, int rate) {
553     pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
554 }
555
556 void pa_format_info_set_channels(pa_format_info *f, int channels) {
557     pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
558 }
559
560 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
561     char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
562
563     pa_channel_map_snprint(map_str, sizeof(map_str), map);
564
565     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
566 }
567
568 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
569     json_object *o;
570
571     pa_assert(f);
572     pa_assert(key);
573
574     o = json_object_new_int(value);
575
576     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
577
578     json_object_put(o);
579 }
580
581 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
582     json_object *o;
583     int i;
584
585     pa_assert(f);
586     pa_assert(key);
587
588     o = json_object_new_array();
589
590     for (i = 0; i < n_values; i++)
591         json_object_array_add(o, json_object_new_int(values[i]));
592
593     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
594
595     json_object_put(o);
596 }
597
598 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
599     json_object *o;
600
601     pa_assert(f);
602     pa_assert(key);
603
604     o = json_object_new_object();
605
606     json_object_object_add(o, PA_JSON_MIN_KEY, json_object_new_int(min));
607     json_object_object_add(o, PA_JSON_MAX_KEY, json_object_new_int(max));
608
609     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
610
611     json_object_put(o);
612 }
613
614 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
615     json_object *o;
616
617     pa_assert(f);
618     pa_assert(key);
619
620     o = json_object_new_string(value);
621
622     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
623
624     json_object_put(o);
625 }
626
627 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
628     json_object *o;
629     int i;
630
631     pa_assert(f);
632     pa_assert(key);
633
634     o = json_object_new_array();
635
636     for (i = 0; i < n_values; i++)
637         json_object_array_add(o, json_object_new_string(values[i]));
638
639     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
640
641     json_object_put(o);
642 }
643
644 static pa_bool_t pa_json_is_fixed_type(json_object *o)
645 {
646     switch(json_object_get_type(o)) {
647         case json_type_object:
648         case json_type_array:
649             return FALSE;
650
651         default:
652             return TRUE;
653     }
654 }
655
656 static int pa_json_value_equal(json_object *o1, json_object *o2) {
657     return (json_object_get_type(o1) == json_object_get_type(o2)) &&
658         pa_streq(json_object_to_json_string(o1), json_object_to_json_string(o2));
659 }
660
661 static int pa_format_info_prop_compatible(const char *one, const char *two) {
662     json_object *o1 = NULL, *o2 = NULL;
663     int i, ret = 0;
664
665     o1 = json_tokener_parse(one);
666     if (is_error(o1))
667         goto out;
668
669     o2 = json_tokener_parse(two);
670     if (is_error(o2))
671         goto out;
672
673     /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
674     pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), FALSE);
675
676     if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
677         ret = pa_json_value_equal(o1, o2);
678         goto out;
679     }
680
681     if (pa_json_is_fixed_type(o1)) {
682         json_object *tmp = o2;
683         o2 = o1;
684         o1 = tmp;
685     }
686
687     /* o2 is now a fixed type, and o1 is not */
688
689     if (json_object_get_type(o1) == json_type_array) {
690         for (i = 0; i < json_object_array_length(o1); i++) {
691             if (pa_json_value_equal(json_object_array_get_idx(o1, i), o2)) {
692                 ret = 1;
693                 break;
694             }
695         }
696     } else if (json_object_get_type(o1) == json_type_object) {
697         /* o1 should be a range type */
698         int min, max, v;
699         json_object *o_min = NULL, *o_max = NULL;
700
701         if (json_object_get_type(o2) != json_type_int) {
702             /* We don't support non-integer ranges */
703             goto out;
704         }
705
706         o_min = json_object_object_get(o1, PA_JSON_MIN_KEY);
707         if (!o_min || json_object_get_type(o_min) != json_type_int)
708             goto out;
709
710         o_max = json_object_object_get(o1, PA_JSON_MAX_KEY);
711         if (!o_max || json_object_get_type(o_max) != json_type_int)
712             goto out;
713
714         v = json_object_get_int(o2);
715         min = json_object_get_int(o_min);
716         max = json_object_get_int(o_max);
717
718         ret = v >= min && v <= max;
719     } else {
720         pa_log_warn("Got a format type that we don't support");
721     }
722
723 out:
724     if (o1)
725         json_object_put(o1);
726     if (o2)
727         json_object_put(o2);
728
729     return ret;
730 }