format: Add a type for DTS
[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 <pulse/internal.h>
29 #include <pulse/xmalloc.h>
30 #include <pulse/i18n.h>
31
32 #include <pulsecore/core-util.h>
33 #include <pulsecore/macro.h>
34
35 #include "format.h"
36
37 const char *pa_encoding_to_string(pa_encoding_t e) {
38     static const char* const table[]= {
39         [PA_ENCODING_PCM] = "pcm",
40         [PA_ENCODING_AC3_IEC61937] = "ac3-iec61937",
41         [PA_ENCODING_EAC3_IEC61937] = "eac3-iec61937",
42         [PA_ENCODING_MPEG_IEC61937] = "mpeg-iec61937",
43         [PA_ENCODING_DTS_IEC61937] = "dts-iec61937",
44         [PA_ENCODING_ANY] = "any",
45     };
46
47     if (e < 0 || e >= PA_ENCODING_MAX)
48         return NULL;
49
50     return table[e];
51 }
52
53 pa_format_info* pa_format_info_new(void) {
54     pa_format_info *f = pa_xnew(pa_format_info, 1);
55
56     f->encoding = PA_ENCODING_INVALID;
57     f->plist = pa_proplist_new();
58
59     return f;
60 }
61
62 pa_format_info* pa_format_info_copy(const pa_format_info *src) {
63     pa_format_info *dest;
64
65     pa_assert(src);
66
67     dest = pa_xnew(pa_format_info, 1);
68
69     dest->encoding = src->encoding;
70
71     if (src->plist)
72         dest->plist = pa_proplist_copy(src->plist);
73     else
74         dest->plist = NULL;
75
76     return dest;
77 }
78
79 void pa_format_info_free(pa_format_info *f) {
80     pa_assert(f);
81
82     pa_proplist_free(f->plist);
83     pa_xfree(f);
84 }
85
86 void pa_format_info_free2(pa_format_info *f, void *userdata) {
87     pa_format_info_free(f);
88 }
89
90 int pa_format_info_valid(const pa_format_info *f) {
91     return (f->encoding >= 0 && f->encoding < PA_ENCODING_MAX && f->plist != NULL);
92 }
93
94 int pa_format_info_is_pcm(const pa_format_info *f) {
95     return f->encoding == PA_ENCODING_PCM;
96 }
97
98 char *pa_format_info_snprint(char *s, size_t l, const pa_format_info *f) {
99     char *tmp;
100
101     pa_assert(s);
102     pa_assert(l > 0);
103     pa_assert(f);
104
105     pa_init_i18n();
106
107     if (!pa_format_info_valid(f))
108         pa_snprintf(s, l, _("(invalid)"));
109     else {
110         tmp = pa_proplist_to_string_sep(f->plist, ", ");
111         pa_snprintf(s, l, _("%s, %s"), pa_encoding_to_string(f->encoding), tmp[0] ? tmp : _("(no properties)"));
112         pa_xfree(tmp);
113     }
114
115     return s;
116 }
117
118 pa_bool_t pa_format_info_is_compatible(pa_format_info *first, pa_format_info *second) {
119     const char *key;
120     void *state = NULL;
121
122     pa_assert(first);
123     pa_assert(second);
124
125     if (first->encoding != second->encoding)
126         return FALSE;
127
128     while ((key = pa_proplist_iterate(first->plist, &state))) {
129         const char *value_one, *value_two;
130
131         value_one = pa_proplist_gets(first->plist, key);
132         value_two = pa_proplist_gets(second->plist, key);
133
134         if (!value_two || !pa_streq(value_one, value_two))
135             return FALSE;
136     }
137
138     return TRUE;
139 }
140
141 pa_format_info* pa_format_info_from_sample_spec(pa_sample_spec *ss, pa_channel_map *map) {
142     char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
143     pa_format_info *f;
144
145     pa_assert(ss && pa_sample_spec_valid(ss));
146     pa_assert(!map || pa_channel_map_valid(map));
147
148     f = pa_format_info_new();
149     f->encoding = PA_ENCODING_PCM;
150
151     pa_proplist_sets(f->plist, PA_PROP_FORMAT_SAMPLE_FORMAT, pa_sample_format_to_string(ss->format));
152     pa_proplist_setf(f->plist, PA_PROP_FORMAT_RATE, "%u", (unsigned int) ss->rate);
153     pa_proplist_setf(f->plist, PA_PROP_FORMAT_CHANNELS, "%u", (unsigned int) ss->channels);
154
155     if (map) {
156         pa_channel_map_snprint(cm, sizeof(cm), map);
157         pa_proplist_setf(f->plist, PA_PROP_FORMAT_CHANNEL_MAP, "%s", cm);
158     }
159
160     return f;
161 }
162
163 /* For PCM streams */
164 pa_bool_t pa_format_info_to_sample_spec(pa_format_info *f, pa_sample_spec *ss, pa_channel_map *map) {
165     const char *sf, *r, *ch;
166     uint32_t channels;
167
168     pa_assert(f);
169     pa_assert(ss);
170     pa_return_val_if_fail(f->encoding == PA_ENCODING_PCM, FALSE);
171
172     pa_return_val_if_fail(sf = pa_proplist_gets(f->plist, PA_PROP_FORMAT_SAMPLE_FORMAT), FALSE);
173     pa_return_val_if_fail(r = pa_proplist_gets(f->plist, PA_PROP_FORMAT_RATE), FALSE);
174     pa_return_val_if_fail(ch = pa_proplist_gets(f->plist, PA_PROP_FORMAT_CHANNELS), FALSE);
175
176     pa_return_val_if_fail((ss->format = pa_parse_sample_format(sf)) != PA_SAMPLE_INVALID, FALSE);
177     pa_return_val_if_fail(pa_atou(r, &ss->rate) == 0, FALSE);
178     pa_return_val_if_fail(pa_atou(ch, &channels) == 0, FALSE);
179     ss->channels = (uint8_t) channels;
180
181     if (map) {
182         const char *m = pa_proplist_gets(f->plist, PA_PROP_FORMAT_CHANNEL_MAP);
183         pa_channel_map_init(map);
184
185         if (m)
186             pa_return_val_if_fail(pa_channel_map_parse(map, m) != NULL, FALSE);
187     }
188
189     return TRUE;
190 }
191
192 /* For compressed streams */
193 pa_bool_t pa_format_info_to_sample_spec_fake(pa_format_info *f, pa_sample_spec *ss) {
194     const char *r;
195
196     pa_assert(f);
197     pa_assert(ss);
198     pa_return_val_if_fail(f->encoding != PA_ENCODING_PCM, FALSE);
199
200     ss->format = PA_SAMPLE_S16LE;
201     ss->channels = 2;
202
203     pa_return_val_if_fail(r = pa_proplist_gets(f->plist, PA_PROP_FORMAT_RATE), FALSE);
204     pa_return_val_if_fail(pa_atou(r, &ss->rate) == 0, FALSE);
205
206     return TRUE;
207 }