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