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