~diwic/ubuntu/lucid/pulseaudio/bugfixes

« back to all changes in this revision

Viewing changes to src/pulse/channelmap.c

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2006-11-12 20:00:18 UTC
  • Revision ID: james.westby@ubuntu.com-20061112200018-oji9njq7rr3te53k
Tags: upstream-0.9.5
ImportĀ upstreamĀ versionĀ 0.9.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: channelmap.c 1033 2006-06-19 21:53:48Z lennart $ */
 
2
 
 
3
/***
 
4
  This file is part of PulseAudio.
 
5
 
 
6
  PulseAudio is free software; you can redistribute it and/or modify
 
7
  it under the terms of the GNU Lesser General Public License as published
 
8
  by the Free Software Foundation; either version 2 of the License,
 
9
  or (at your option) any later version.
 
10
 
 
11
  PulseAudio is distributed in the hope that it will be useful, but
 
12
  WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 
14
  General Public License for more details.
 
15
 
 
16
  You should have received a copy of the GNU Lesser General Public License
 
17
  along with PulseAudio; if not, write to the Free Software
 
18
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 
19
  USA.
 
20
***/
 
21
 
 
22
#ifdef HAVE_CONFIG_H
 
23
#include <config.h>
 
24
#endif
 
25
 
 
26
#include <stdlib.h>
 
27
#include <assert.h>
 
28
#include <stdio.h>
 
29
#include <string.h>
 
30
 
 
31
#include <pulse/xmalloc.h>
 
32
#include <pulsecore/core-util.h>
 
33
 
 
34
#include "channelmap.h"
 
35
 
 
36
const char *const table[] = {
 
37
    [PA_CHANNEL_POSITION_MONO] = "mono",
 
38
    
 
39
    [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center",
 
40
    [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left",
 
41
    [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right",
 
42
    
 
43
    [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center",
 
44
    [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left",
 
45
    [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right",
 
46
    
 
47
    [PA_CHANNEL_POSITION_LFE] = "lfe",
 
48
    
 
49
    [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center",
 
50
    [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center",
 
51
        
 
52
    [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left",
 
53
    [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right",
 
54
    
 
55
    [PA_CHANNEL_POSITION_AUX0] = "aux0",
 
56
    [PA_CHANNEL_POSITION_AUX1] = "aux1",
 
57
    [PA_CHANNEL_POSITION_AUX2] = "aux2",
 
58
    [PA_CHANNEL_POSITION_AUX3] = "aux3",
 
59
    [PA_CHANNEL_POSITION_AUX4] = "aux4",
 
60
    [PA_CHANNEL_POSITION_AUX5] = "aux5",
 
61
    [PA_CHANNEL_POSITION_AUX6] = "aux6",
 
62
    [PA_CHANNEL_POSITION_AUX7] = "aux7",
 
63
    [PA_CHANNEL_POSITION_AUX8] = "aux8",
 
64
    [PA_CHANNEL_POSITION_AUX9] = "aux9",
 
65
    [PA_CHANNEL_POSITION_AUX10] = "aux10",
 
66
    [PA_CHANNEL_POSITION_AUX11] = "aux11",
 
67
    [PA_CHANNEL_POSITION_AUX12] = "aux12",
 
68
    [PA_CHANNEL_POSITION_AUX13] = "aux13",
 
69
    [PA_CHANNEL_POSITION_AUX14] = "aux14",
 
70
    [PA_CHANNEL_POSITION_AUX15] = "aux15",
 
71
 
 
72
    [PA_CHANNEL_POSITION_TOP_CENTER] = "top-center",
 
73
    
 
74
    [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left",
 
75
    [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right",
 
76
    [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center",
 
77
 
 
78
    [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "top-rear-left",
 
79
    [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right",
 
80
    [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center"
 
81
};
 
82
 
 
83
pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
 
84
    unsigned c;
 
85
    assert(m);
 
86
 
 
87
    m->channels = 0;
 
88
 
 
89
    for (c = 0; c < PA_CHANNELS_MAX; c++)
 
90
        m->map[c] = PA_CHANNEL_POSITION_INVALID;
 
91
 
 
92
    return m;
 
93
}
 
94
 
 
95
pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) {
 
96
    assert(m);
 
97
 
 
98
    pa_channel_map_init(m);
 
99
 
 
100
    m->channels = 1;
 
101
    m->map[0] = PA_CHANNEL_POSITION_MONO;
 
102
    return m;
 
103
}
 
104
 
 
105
pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
 
106
    assert(m);
 
107
 
 
108
    pa_channel_map_init(m);
 
109
 
 
110
    m->channels = 2;
 
111
    m->map[0] = PA_CHANNEL_POSITION_LEFT;
 
112
    m->map[1] = PA_CHANNEL_POSITION_RIGHT;
 
113
    return m;
 
114
}
 
115
 
 
116
pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
 
117
    assert(m);
 
118
    assert(channels > 0);
 
119
    assert(channels <= PA_CHANNELS_MAX);
 
120
 
 
121
    pa_channel_map_init(m);
 
122
 
 
123
    m->channels = channels;
 
124
 
 
125
    switch (def) {
 
126
        case PA_CHANNEL_MAP_AIFF:
 
127
            
 
128
            /* This is somewhat compatible with RFC3551 */
 
129
            
 
130
            switch (channels) {
 
131
                case 1:
 
132
                    m->map[0] = PA_CHANNEL_POSITION_MONO;
 
133
                    return m;
 
134
                    
 
135
                case 6:
 
136
                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
 
137
                    m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT;
 
138
                    m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
 
139
                    m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT;
 
140
                    m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT;
 
141
                    m->map[5] = PA_CHANNEL_POSITION_LFE;
 
142
                    return m;
 
143
                    
 
144
                case 5:
 
145
                    m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
 
146
                    m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT;
 
147
                    m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT;
 
148
                    /* Fall through */
 
149
                    
 
150
                case 2:
 
151
                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
 
152
                    m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
 
153
                    return m;
 
154
                    
 
155
                case 3:
 
156
                    m->map[0] = PA_CHANNEL_POSITION_LEFT;
 
157
                    m->map[1] = PA_CHANNEL_POSITION_RIGHT;
 
158
                    m->map[2] = PA_CHANNEL_POSITION_CENTER;
 
159
                    return m;
 
160
                    
 
161
                case 4:
 
162
                    m->map[0] = PA_CHANNEL_POSITION_LEFT;
 
163
                    m->map[1] = PA_CHANNEL_POSITION_CENTER;
 
164
                    m->map[2] = PA_CHANNEL_POSITION_RIGHT;
 
165
                    m->map[3] = PA_CHANNEL_POSITION_LFE;
 
166
                    return m;
 
167
                    
 
168
                default:
 
169
                    return NULL;
 
170
            }
 
171
 
 
172
        case PA_CHANNEL_MAP_ALSA:
 
173
 
 
174
            switch (channels) {
 
175
                case 1:
 
176
                    m->map[0] = PA_CHANNEL_POSITION_MONO;
 
177
                    return m;
 
178
                    
 
179
                case 8:
 
180
                    m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
 
181
                    m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
 
182
                    /* Fall through */
 
183
                    
 
184
                case 6:
 
185
                    m->map[5] = PA_CHANNEL_POSITION_LFE;
 
186
                    /* Fall through */
 
187
                    
 
188
                case 5:
 
189
                    m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
 
190
                    /* Fall through */
 
191
                    
 
192
                case 4:
 
193
                    m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
 
194
                    m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
 
195
                    /* Fall through */
 
196
                    
 
197
                case 2:
 
198
                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
 
199
                    m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
 
200
                    return m;
 
201
                    
 
202
                default:
 
203
                    return NULL;
 
204
            }
 
205
 
 
206
        case PA_CHANNEL_MAP_AUX: {
 
207
            unsigned i;
 
208
            
 
209
            if (channels >= PA_CHANNELS_MAX)
 
210
                return NULL;
 
211
 
 
212
            for (i = 0; i < channels; i++)
 
213
                m->map[i] = PA_CHANNEL_POSITION_AUX0 + i;
 
214
            
 
215
            return m;
 
216
        }
 
217
 
 
218
        case PA_CHANNEL_MAP_WAVEEX:
 
219
 
 
220
            switch (channels) {
 
221
                case 1:
 
222
                    m->map[0] = PA_CHANNEL_POSITION_MONO;
 
223
                    return m;
 
224
                    
 
225
                case 18:
 
226
                    m->map[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
 
227
                    m->map[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
 
228
                    m->map[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
 
229
                    /* Fall through */
 
230
                    
 
231
                case 15:
 
232
                    m->map[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
 
233
                    m->map[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
 
234
                    m->map[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
 
235
                    /* Fall through */
 
236
                    
 
237
                case 12:
 
238
                    m->map[11] = PA_CHANNEL_POSITION_TOP_CENTER;
 
239
                    /* Fall through */
 
240
                    
 
241
                case 11:
 
242
                    m->map[9] = PA_CHANNEL_POSITION_SIDE_LEFT;
 
243
                    m->map[10] = PA_CHANNEL_POSITION_SIDE_RIGHT;
 
244
                    /* Fall through */
 
245
                    
 
246
                case 9:
 
247
                    m->map[8] = PA_CHANNEL_POSITION_REAR_CENTER;
 
248
                    /* Fall through */
 
249
                    
 
250
                case 8:
 
251
                    m->map[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
 
252
                    m->map[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
 
253
                    /* Fall through */
 
254
                    
 
255
                case 6:
 
256
                    m->map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
 
257
                    m->map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
 
258
                    /* Fall through */
 
259
                    
 
260
                case 4:
 
261
                    m->map[3] = PA_CHANNEL_POSITION_LFE;
 
262
                    /* Fall through */
 
263
                    
 
264
                case 3:
 
265
                    m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
 
266
                    /* Fall through */
 
267
                    
 
268
                case 2:
 
269
                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
 
270
                    m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
 
271
                    return m;
 
272
                    
 
273
                default:
 
274
                    return NULL;
 
275
            }
 
276
 
 
277
        case PA_CHANNEL_MAP_OSS:
 
278
 
 
279
            switch (channels) {
 
280
                case 1:
 
281
                    m->map[0] = PA_CHANNEL_POSITION_MONO;
 
282
                    return m;
 
283
                    
 
284
                case 8:
 
285
                    m->map[6] = PA_CHANNEL_POSITION_REAR_LEFT;
 
286
                    m->map[7] = PA_CHANNEL_POSITION_REAR_RIGHT;
 
287
                    /* Fall through */
 
288
                    
 
289
                case 6:
 
290
                    m->map[4] = PA_CHANNEL_POSITION_SIDE_LEFT;
 
291
                    m->map[5] = PA_CHANNEL_POSITION_SIDE_RIGHT;
 
292
                    /* Fall through */
 
293
 
 
294
                case 4:
 
295
                    m->map[3] = PA_CHANNEL_POSITION_LFE;
 
296
                    /* Fall through */
 
297
                    
 
298
                case 3:
 
299
                    m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
 
300
                    /* Fall through */
 
301
                    
 
302
                case 2:
 
303
                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
 
304
                    m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
 
305
                    return m;
 
306
                    
 
307
                default:
 
308
                    return NULL;
 
309
            }
 
310
            
 
311
 
 
312
        default:
 
313
            return NULL;
 
314
    }
 
315
}
 
316
 
 
317
 
 
318
const char* pa_channel_position_to_string(pa_channel_position_t pos) {
 
319
 
 
320
    if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
 
321
        return NULL;
 
322
 
 
323
    return table[pos];
 
324
}
 
325
 
 
326
int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
 
327
    unsigned c;
 
328
    
 
329
    assert(a);
 
330
    assert(b);
 
331
 
 
332
    if (a->channels != b->channels)
 
333
        return 0;
 
334
    
 
335
    for (c = 0; c < a->channels; c++)
 
336
        if (a->map[c] != b->map[c])
 
337
            return 0;
 
338
 
 
339
    return 1;
 
340
}
 
341
 
 
342
char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
 
343
    unsigned channel;
 
344
    int first = 1;
 
345
    char *e;
 
346
    
 
347
    assert(s);
 
348
    assert(l > 0);
 
349
    assert(map);
 
350
 
 
351
    *(e = s) = 0;
 
352
 
 
353
    for (channel = 0; channel < map->channels && l > 1; channel++) {
 
354
        l -= snprintf(e, l, "%s%s",
 
355
                      first ? "" : ",",
 
356
                      pa_channel_position_to_string(map->map[channel]));
 
357
 
 
358
        e = strchr(e, 0);
 
359
        first = 0;
 
360
    }
 
361
 
 
362
    return s;
 
363
}
 
364
 
 
365
pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
 
366
    const char *state;
 
367
    pa_channel_map map;
 
368
    char *p;
 
369
    
 
370
    assert(rmap);
 
371
    assert(s);
 
372
 
 
373
    memset(&map, 0, sizeof(map));
 
374
 
 
375
    if (strcmp(s, "stereo") == 0) {
 
376
        map.channels = 2;
 
377
        map.map[0] = PA_CHANNEL_POSITION_LEFT;
 
378
        map.map[1] = PA_CHANNEL_POSITION_RIGHT;
 
379
        goto finish;
 
380
    }
 
381
 
 
382
    state = NULL;
 
383
    map.channels = 0;
 
384
    
 
385
    while ((p = pa_split(s, ",", &state))) {
 
386
 
 
387
        if (map.channels >= PA_CHANNELS_MAX) {
 
388
            pa_xfree(p);
 
389
            return NULL;
 
390
        }
 
391
        
 
392
        /* Some special aliases */
 
393
        if (strcmp(p, "left") == 0)
 
394
            map.map[map.channels++] = PA_CHANNEL_POSITION_LEFT;
 
395
        else if (strcmp(p, "right") == 0)
 
396
            map.map[map.channels++] = PA_CHANNEL_POSITION_RIGHT;
 
397
        else if (strcmp(p, "center") == 0)
 
398
            map.map[map.channels++] = PA_CHANNEL_POSITION_CENTER;
 
399
        else if (strcmp(p, "subwoofer") == 0)
 
400
            map.map[map.channels++] = PA_CHANNEL_POSITION_SUBWOOFER;
 
401
        else {
 
402
            pa_channel_position_t i;
 
403
            
 
404
            for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++)
 
405
                if (strcmp(p, table[i]) == 0) {
 
406
                    map.map[map.channels++] = i;
 
407
                    break;
 
408
                }
 
409
            
 
410
            if (i >= PA_CHANNEL_POSITION_MAX) {
 
411
                pa_xfree(p);
 
412
                return NULL;
 
413
            }
 
414
        }
 
415
 
 
416
        pa_xfree(p);
 
417
    }
 
418
 
 
419
finish:
 
420
    
 
421
    if (!pa_channel_map_valid(&map))
 
422
        return NULL;
 
423
    
 
424
    *rmap = map;
 
425
    return rmap;
 
426
}
 
427
 
 
428
int pa_channel_map_valid(const pa_channel_map *map) {
 
429
    unsigned c;
 
430
    
 
431
    assert(map);
 
432
 
 
433
    if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX)
 
434
        return 0;
 
435
 
 
436
    for (c = 0; c < map->channels; c++) {
 
437
        
 
438
        if (map->map[c] < 0 ||map->map[c] >= PA_CHANNEL_POSITION_MAX)
 
439
            return 0;
 
440
 
 
441
    }
 
442
 
 
443
    return 1;
 
444
}
 
445