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