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