core-format: Add pa_format_info_get_channel_map()
[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(pa_format_info *first, 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(pa_sample_spec *ss, 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(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
221     int ret = -PA_ERR_INVALID;
222
223     pa_assert(f);
224     pa_assert(ss);
225
226     if (!pa_format_info_is_pcm(f))
227         return pa_format_info_to_sample_spec_fake(f, ss, map);
228
229     if (pa_format_info_get_sample_format(f, &ss->format) < 0)
230         goto out;
231     if (pa_format_info_get_rate(f, &ss->rate) < 0)
232         goto out;
233     if (pa_format_info_get_channels(f, &ss->channels) < 0)
234         goto out;
235     if (map && pa_format_info_get_channel_map(f, map) < 0)
236         goto out;
237
238     ret = 0;
239
240 out:
241     return ret;
242 }
243
244 pa_prop_type_t pa_format_info_get_prop_type(pa_format_info *f, const char *key) {
245     const char *str;
246     json_object *o, *o1;
247     pa_prop_type_t type;
248
249     pa_assert(f);
250     pa_assert(key);
251
252     str = pa_proplist_gets(f->plist, key);
253     if (!str)
254         return PA_PROP_TYPE_INVALID;
255
256     o = json_tokener_parse(str);
257     if (is_error(o))
258         return PA_PROP_TYPE_INVALID;
259
260     switch (json_object_get_type(o)) {
261         case json_type_int:
262             type = PA_PROP_TYPE_INT;
263             break;
264
265         case json_type_string:
266             type = PA_PROP_TYPE_STRING;
267             break;
268
269         case json_type_array:
270             if (json_object_array_length(o) == 0) {
271                 /* Unlikely, but let's account for this anyway. We need at
272                  * least one element to figure out the array type. */
273                 type = PA_PROP_TYPE_INVALID;
274                 break;
275             }
276
277             o1 = json_object_array_get_idx(o, 1);
278
279             if (json_object_get_type(o1) == json_type_int)
280                 type = PA_PROP_TYPE_INT_ARRAY;
281             else if (json_object_get_type(o1) == json_type_string)
282                 type = PA_PROP_TYPE_STRING_ARRAY;
283             else
284                 type = PA_PROP_TYPE_INVALID;
285
286             json_object_put(o1);
287             break;
288
289         case json_type_object:
290             /* We actually know at this point that it's a int range, but let's
291              * confirm. */
292             o1 = json_object_object_get(o, PA_JSON_MIN_KEY);
293             if (!o1) {
294                 type = PA_PROP_TYPE_INVALID;
295                 break;
296             }
297             json_object_put(o1);
298
299             o1 = json_object_object_get(o, PA_JSON_MAX_KEY);
300             if (!o1) {
301                 type = PA_PROP_TYPE_INVALID;
302                 break;
303             }
304             json_object_put(o1);
305
306             type = PA_PROP_TYPE_INT_RANGE;
307             break;
308
309         default:
310             type = PA_PROP_TYPE_INVALID;
311             break;
312     }
313
314     json_object_put(o);
315     return type;
316 }
317
318 int pa_format_info_get_prop_int(pa_format_info *f, const char *key, int *v) {
319     const char *str;
320     json_object *o;
321
322     pa_assert(f);
323     pa_assert(key);
324     pa_assert(v);
325
326     str = pa_proplist_gets(f->plist, key);
327     if (!str)
328         return -PA_ERR_NOENTITY;
329
330     o = json_tokener_parse(str);
331     if (is_error(o))
332         return -PA_ERR_INVALID;
333
334     if (json_object_get_type(o) != json_type_int) {
335         json_object_put(o);
336         return -PA_ERR_INVALID;
337     }
338
339     *v = json_object_get_int(o);
340     json_object_put(o);
341
342     return 0;
343 }
344
345 int pa_format_info_get_prop_int_range(pa_format_info *f, const char *key, int *min, int *max) {
346     const char *str;
347     json_object *o, *o1;
348     int ret = -PA_ERR_INVALID;
349
350     pa_assert(f);
351     pa_assert(key);
352     pa_assert(min);
353     pa_assert(max);
354
355     str = pa_proplist_gets(f->plist, key);
356     if (!str)
357         return -PA_ERR_NOENTITY;
358
359     o = json_tokener_parse(str);
360     if (is_error(o))
361         return -PA_ERR_INVALID;
362
363     if (json_object_get_type(o) != json_type_object)
364         goto out;
365
366     if (!(o1 = json_object_object_get(o, PA_JSON_MIN_KEY)))
367         goto out;
368
369     *min = json_object_get_int(o1);
370     json_object_put(o1);
371
372     if (!(o1 = json_object_object_get(o, PA_JSON_MAX_KEY)))
373         goto out;
374
375     *max = json_object_get_int(o1);
376     json_object_put(o1);
377
378     ret = 0;
379
380 out:
381     json_object_put(o);
382     return ret;
383 }
384
385 int pa_format_info_get_prop_int_array(pa_format_info *f, const char *key, int **values, int *n_values) {
386     const char *str;
387     json_object *o, *o1;
388     int i, ret = -PA_ERR_INVALID;
389
390     pa_assert(f);
391     pa_assert(key);
392     pa_assert(values);
393     pa_assert(n_values);
394
395     str = pa_proplist_gets(f->plist, key);
396     if (!str)
397         return -PA_ERR_NOENTITY;
398
399     o = json_tokener_parse(str);
400     if (is_error(o))
401         return -PA_ERR_INVALID;
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             json_object_put(o1);
414             goto out;
415         }
416
417         (*values)[i] = json_object_get_int(o1);
418         json_object_put(o1);
419     }
420
421     ret = 0;
422
423 out:
424     json_object_put(o);
425     return ret;
426 }
427
428 int pa_format_info_get_prop_string(pa_format_info *f, const char *key, char **v) {
429     const char *str = NULL;
430     json_object *o;
431
432     pa_assert(f);
433     pa_assert(key);
434     pa_assert(v);
435
436     str = pa_proplist_gets(f->plist, key);
437     if (!str)
438         return -PA_ERR_NOENTITY;
439
440     o = json_tokener_parse(str);
441     if (is_error(o))
442         return -PA_ERR_INVALID;
443
444     if (json_object_get_type(o) != json_type_string) {
445         json_object_put(o);
446         return -PA_ERR_INVALID;
447     }
448
449     *v = pa_xstrdup(json_object_get_string(o));
450     json_object_put(o);
451
452     return 0;
453 }
454
455 int pa_format_info_get_prop_string_array(pa_format_info *f, const char *key, char ***values, int *n_values) {
456     const char *str;
457     json_object *o, *o1;
458     int i, ret = -PA_ERR_INVALID;
459
460     pa_assert(f);
461     pa_assert(key);
462     pa_assert(values);
463     pa_assert(n_values);
464
465     str = pa_proplist_gets(f->plist, key);
466     if (!str)
467         return -PA_ERR_NOENTITY;
468
469     o = json_tokener_parse(str);
470     if (is_error(o))
471         return -PA_ERR_INVALID;
472
473     if (json_object_get_type(o) != json_type_array)
474         goto out;
475
476     *n_values = json_object_array_length(o);
477     *values = pa_xnew(char *, *n_values);
478
479     for (i = 0; i < *n_values; i++) {
480         o1 = json_object_array_get_idx(o, i);
481
482         if (json_object_get_type(o1) != json_type_string) {
483             json_object_put(o1);
484             goto out;
485         }
486
487         (*values)[i] = pa_xstrdup(json_object_get_string(o1));
488         json_object_put(o1);
489     }
490
491     ret = 0;
492
493 out:
494     json_object_put(o);
495     return ret;
496 }
497
498 void pa_format_info_free_string_array(char **values, int n_values) {
499     int i;
500
501     for (i = 0; i < n_values; i++)
502         pa_xfree(values[i]);
503
504     pa_xfree(values);
505 }
506
507 void pa_format_info_set_sample_format(pa_format_info *f, pa_sample_format_t sf) {
508     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(sf));
509 }
510
511 void pa_format_info_set_rate(pa_format_info *f, int rate) {
512     pa_format_info_set_prop_int(f, PA_PROP_FORMAT_RATE, rate);
513 }
514
515 void pa_format_info_set_channels(pa_format_info *f, int channels) {
516     pa_format_info_set_prop_int(f, PA_PROP_FORMAT_CHANNELS, channels);
517 }
518
519 void pa_format_info_set_channel_map(pa_format_info *f, const pa_channel_map *map) {
520     char map_str[PA_CHANNEL_MAP_SNPRINT_MAX];
521
522     pa_channel_map_snprint(map_str, sizeof(map_str), map);
523
524     pa_format_info_set_prop_string(f, PA_PROP_FORMAT_CHANNEL_MAP, map_str);
525 }
526
527 void pa_format_info_set_prop_int(pa_format_info *f, const char *key, int value) {
528     json_object *o;
529
530     pa_assert(f);
531     pa_assert(key);
532
533     o = json_object_new_int(value);
534
535     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
536
537     json_object_put(o);
538 }
539
540 void pa_format_info_set_prop_int_array(pa_format_info *f, const char *key, const int *values, int n_values) {
541     json_object *o;
542     int i;
543
544     pa_assert(f);
545     pa_assert(key);
546
547     o = json_object_new_array();
548
549     for (i = 0; i < n_values; i++)
550         json_object_array_add(o, json_object_new_int(values[i]));
551
552     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
553
554     json_object_put(o);
555 }
556
557 void pa_format_info_set_prop_int_range(pa_format_info *f, const char *key, int min, int max) {
558     json_object *o;
559
560     pa_assert(f);
561     pa_assert(key);
562
563     o = json_object_new_object();
564
565     json_object_object_add(o, PA_JSON_MIN_KEY, json_object_new_int(min));
566     json_object_object_add(o, PA_JSON_MAX_KEY, json_object_new_int(max));
567
568     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
569
570     json_object_put(o);
571 }
572
573 void pa_format_info_set_prop_string(pa_format_info *f, const char *key, const char *value) {
574     json_object *o;
575
576     pa_assert(f);
577     pa_assert(key);
578
579     o = json_object_new_string(value);
580
581     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
582
583     json_object_put(o);
584 }
585
586 void pa_format_info_set_prop_string_array(pa_format_info *f, const char *key, const char **values, int n_values) {
587     json_object *o;
588     int i;
589
590     pa_assert(f);
591     pa_assert(key);
592
593     o = json_object_new_array();
594
595     for (i = 0; i < n_values; i++)
596         json_object_array_add(o, json_object_new_string(values[i]));
597
598     pa_proplist_sets(f->plist, key, json_object_to_json_string(o));
599
600     json_object_put(o);
601 }
602
603 static bool pa_json_is_fixed_type(json_object *o) {
604     switch(json_object_get_type(o)) {
605         case json_type_object:
606         case json_type_array:
607             return false;
608
609         default:
610             return true;
611     }
612 }
613
614 static int pa_json_value_equal(json_object *o1, json_object *o2) {
615     return (json_object_get_type(o1) == json_object_get_type(o2)) &&
616         pa_streq(json_object_to_json_string(o1), json_object_to_json_string(o2));
617 }
618
619 static int pa_format_info_prop_compatible(const char *one, const char *two) {
620     json_object *o1 = NULL, *o2 = NULL;
621     int i, ret = 0;
622
623     o1 = json_tokener_parse(one);
624     if (is_error(o1))
625         goto out;
626
627     o2 = json_tokener_parse(two);
628     if (is_error(o2))
629         goto out;
630
631     /* We don't deal with both values being non-fixed - just because there is no immediate need (FIXME) */
632     pa_return_val_if_fail(pa_json_is_fixed_type(o1) || pa_json_is_fixed_type(o2), false);
633
634     if (pa_json_is_fixed_type(o1) && pa_json_is_fixed_type(o2)) {
635         ret = pa_json_value_equal(o1, o2);
636         goto out;
637     }
638
639     if (pa_json_is_fixed_type(o1)) {
640         json_object *tmp = o2;
641         o2 = o1;
642         o1 = tmp;
643     }
644
645     /* o2 is now a fixed type, and o1 is not */
646
647     if (json_object_get_type(o1) == json_type_array) {
648         for (i = 0; i < json_object_array_length(o1); i++) {
649             if (pa_json_value_equal(json_object_array_get_idx(o1, i), o2)) {
650                 ret = 1;
651                 break;
652             }
653         }
654     } else if (json_object_get_type(o1) == json_type_object) {
655         /* o1 should be a range type */
656         int min, max, v;
657         json_object *o_min = NULL, *o_max = NULL;
658
659         if (json_object_get_type(o2) != json_type_int) {
660             /* We don't support non-integer ranges */
661             goto out;
662         }
663
664         o_min = json_object_object_get(o1, PA_JSON_MIN_KEY);
665         if (!o_min || json_object_get_type(o_min) != json_type_int)
666             goto out;
667
668         o_max = json_object_object_get(o1, PA_JSON_MAX_KEY);
669         if (!o_max || json_object_get_type(o_max) != json_type_int)
670             goto out;
671
672         v = json_object_get_int(o2);
673         min = json_object_get_int(o_min);
674         max = json_object_get_int(o_max);
675
676         ret = v >= min && v <= max;
677     } else {
678         pa_log_warn("Got a format type that we don't support");
679     }
680
681 out:
682     if (o1)
683         json_object_put(o1);
684     if (o2)
685         json_object_put(o2);
686
687     return ret;
688 }