2 This file is part of PulseAudio.
4 Copyright 2005-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
31 #include <pulse/xmalloc.h>
32 #include <pulse/i18n.h>
34 #include <pulsecore/core-util.h>
35 #include <pulsecore/macro.h>
36 #include <pulsecore/bitset.h>
37 #include <pulsecore/sample-util.h>
39 #include "channelmap.h"
41 const char *const table[PA_CHANNEL_POSITION_MAX] = {
42 [PA_CHANNEL_POSITION_MONO] = "mono",
44 [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center",
45 [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left",
46 [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right",
48 [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center",
49 [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left",
50 [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right",
52 [PA_CHANNEL_POSITION_LFE] = "lfe",
54 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center",
55 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center",
57 [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left",
58 [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right",
60 [PA_CHANNEL_POSITION_AUX0] = "aux0",
61 [PA_CHANNEL_POSITION_AUX1] = "aux1",
62 [PA_CHANNEL_POSITION_AUX2] = "aux2",
63 [PA_CHANNEL_POSITION_AUX3] = "aux3",
64 [PA_CHANNEL_POSITION_AUX4] = "aux4",
65 [PA_CHANNEL_POSITION_AUX5] = "aux5",
66 [PA_CHANNEL_POSITION_AUX6] = "aux6",
67 [PA_CHANNEL_POSITION_AUX7] = "aux7",
68 [PA_CHANNEL_POSITION_AUX8] = "aux8",
69 [PA_CHANNEL_POSITION_AUX9] = "aux9",
70 [PA_CHANNEL_POSITION_AUX10] = "aux10",
71 [PA_CHANNEL_POSITION_AUX11] = "aux11",
72 [PA_CHANNEL_POSITION_AUX12] = "aux12",
73 [PA_CHANNEL_POSITION_AUX13] = "aux13",
74 [PA_CHANNEL_POSITION_AUX14] = "aux14",
75 [PA_CHANNEL_POSITION_AUX15] = "aux15",
76 [PA_CHANNEL_POSITION_AUX16] = "aux16",
77 [PA_CHANNEL_POSITION_AUX17] = "aux17",
78 [PA_CHANNEL_POSITION_AUX18] = "aux18",
79 [PA_CHANNEL_POSITION_AUX19] = "aux19",
80 [PA_CHANNEL_POSITION_AUX20] = "aux20",
81 [PA_CHANNEL_POSITION_AUX21] = "aux21",
82 [PA_CHANNEL_POSITION_AUX22] = "aux22",
83 [PA_CHANNEL_POSITION_AUX23] = "aux23",
84 [PA_CHANNEL_POSITION_AUX24] = "aux24",
85 [PA_CHANNEL_POSITION_AUX25] = "aux25",
86 [PA_CHANNEL_POSITION_AUX26] = "aux26",
87 [PA_CHANNEL_POSITION_AUX27] = "aux27",
88 [PA_CHANNEL_POSITION_AUX28] = "aux28",
89 [PA_CHANNEL_POSITION_AUX29] = "aux29",
90 [PA_CHANNEL_POSITION_AUX30] = "aux30",
91 [PA_CHANNEL_POSITION_AUX31] = "aux31",
93 [PA_CHANNEL_POSITION_TOP_CENTER] = "top-center",
95 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center",
96 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left",
97 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right",
99 [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center",
100 [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "top-rear-left",
101 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right"
104 const char *const pretty_table[PA_CHANNEL_POSITION_MAX] = {
105 [PA_CHANNEL_POSITION_MONO] = N_("Mono"),
107 [PA_CHANNEL_POSITION_FRONT_CENTER] = N_("Front Center"),
108 [PA_CHANNEL_POSITION_FRONT_LEFT] = N_("Front Left"),
109 [PA_CHANNEL_POSITION_FRONT_RIGHT] = N_("Front Right"),
111 [PA_CHANNEL_POSITION_REAR_CENTER] = N_("Rear Center"),
112 [PA_CHANNEL_POSITION_REAR_LEFT] = N_("Rear Left"),
113 [PA_CHANNEL_POSITION_REAR_RIGHT] = N_("Rear Right"),
115 [PA_CHANNEL_POSITION_LFE] = N_("Low Frequency Emmiter"),
117 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = N_("Front Left-of-center"),
118 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = N_("Front Right-of-center"),
120 [PA_CHANNEL_POSITION_SIDE_LEFT] = N_("Side Left"),
121 [PA_CHANNEL_POSITION_SIDE_RIGHT] = N_("Side Right"),
123 [PA_CHANNEL_POSITION_AUX0] = N_("Auxiliary 0"),
124 [PA_CHANNEL_POSITION_AUX1] = N_("Auxiliary 1"),
125 [PA_CHANNEL_POSITION_AUX2] = N_("Auxiliary 2"),
126 [PA_CHANNEL_POSITION_AUX3] = N_("Auxiliary 3"),
127 [PA_CHANNEL_POSITION_AUX4] = N_("Auxiliary 4"),
128 [PA_CHANNEL_POSITION_AUX5] = N_("Auxiliary 5"),
129 [PA_CHANNEL_POSITION_AUX6] = N_("Auxiliary 6"),
130 [PA_CHANNEL_POSITION_AUX7] = N_("Auxiliary 7"),
131 [PA_CHANNEL_POSITION_AUX8] = N_("Auxiliary 8"),
132 [PA_CHANNEL_POSITION_AUX9] = N_("Auxiliary 9"),
133 [PA_CHANNEL_POSITION_AUX10] = N_("Auxiliary 10"),
134 [PA_CHANNEL_POSITION_AUX11] = N_("Auxiliary 11"),
135 [PA_CHANNEL_POSITION_AUX12] = N_("Auxiliary 12"),
136 [PA_CHANNEL_POSITION_AUX13] = N_("Auxiliary 13"),
137 [PA_CHANNEL_POSITION_AUX14] = N_("Auxiliary 14"),
138 [PA_CHANNEL_POSITION_AUX15] = N_("Auxiliary 15"),
139 [PA_CHANNEL_POSITION_AUX16] = N_("Auxiliary 16"),
140 [PA_CHANNEL_POSITION_AUX17] = N_("Auxiliary 17"),
141 [PA_CHANNEL_POSITION_AUX18] = N_("Auxiliary 18"),
142 [PA_CHANNEL_POSITION_AUX19] = N_("Auxiliary 19"),
143 [PA_CHANNEL_POSITION_AUX20] = N_("Auxiliary 20"),
144 [PA_CHANNEL_POSITION_AUX21] = N_("Auxiliary 21"),
145 [PA_CHANNEL_POSITION_AUX22] = N_("Auxiliary 22"),
146 [PA_CHANNEL_POSITION_AUX23] = N_("Auxiliary 23"),
147 [PA_CHANNEL_POSITION_AUX24] = N_("Auxiliary 24"),
148 [PA_CHANNEL_POSITION_AUX25] = N_("Auxiliary 25"),
149 [PA_CHANNEL_POSITION_AUX26] = N_("Auxiliary 26"),
150 [PA_CHANNEL_POSITION_AUX27] = N_("Auxiliary 27"),
151 [PA_CHANNEL_POSITION_AUX28] = N_("Auxiliary 28"),
152 [PA_CHANNEL_POSITION_AUX29] = N_("Auxiliary 29"),
153 [PA_CHANNEL_POSITION_AUX30] = N_("Auxiliary 30"),
154 [PA_CHANNEL_POSITION_AUX31] = N_("Auxiliary 31"),
156 [PA_CHANNEL_POSITION_TOP_CENTER] = N_("Top Center"),
158 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = N_("Top Front Center"),
159 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = N_("Top Front Left"),
160 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = N_("Top Front Right"),
162 [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = N_("Top Rear Center"),
163 [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = N_("Top Rear Left"),
164 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = N_("Top Rear Right")
167 pa_channel_map* pa_channel_map_init(pa_channel_map *m) {
173 for (c = 0; c < PA_CHANNELS_MAX; c++)
174 m->map[c] = PA_CHANNEL_POSITION_INVALID;
179 pa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) {
182 pa_channel_map_init(m);
185 m->map[0] = PA_CHANNEL_POSITION_MONO;
189 pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
192 pa_channel_map_init(m);
195 m->map[0] = PA_CHANNEL_POSITION_LEFT;
196 m->map[1] = PA_CHANNEL_POSITION_RIGHT;
200 pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
202 pa_assert(channels > 0);
203 pa_assert(channels <= PA_CHANNELS_MAX);
204 pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
206 pa_channel_map_init(m);
208 m->channels = (uint8_t) channels;
211 case PA_CHANNEL_MAP_AIFF:
213 /* This is somewhat compatible with RFC3551 */
217 m->map[0] = PA_CHANNEL_POSITION_MONO;
221 m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
222 m->map[1] = PA_CHANNEL_POSITION_REAR_LEFT;
223 m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
224 m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT;
225 m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT;
226 m->map[5] = PA_CHANNEL_POSITION_LFE;
230 m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
231 m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT;
232 m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT;
236 m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
237 m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
241 m->map[0] = PA_CHANNEL_POSITION_LEFT;
242 m->map[1] = PA_CHANNEL_POSITION_RIGHT;
243 m->map[2] = PA_CHANNEL_POSITION_CENTER;
247 m->map[0] = PA_CHANNEL_POSITION_LEFT;
248 m->map[1] = PA_CHANNEL_POSITION_CENTER;
249 m->map[2] = PA_CHANNEL_POSITION_RIGHT;
250 m->map[3] = PA_CHANNEL_POSITION_LFE;
257 case PA_CHANNEL_MAP_ALSA:
261 m->map[0] = PA_CHANNEL_POSITION_MONO;
265 m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
266 m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
270 m->map[5] = PA_CHANNEL_POSITION_LFE;
274 m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
278 m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
279 m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
283 m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
284 m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
291 case PA_CHANNEL_MAP_AUX: {
294 for (i = 0; i < channels; i++)
295 m->map[i] = PA_CHANNEL_POSITION_AUX0 + i;
300 case PA_CHANNEL_MAP_WAVEEX:
304 m->map[0] = PA_CHANNEL_POSITION_MONO;
308 m->map[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
309 m->map[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
310 m->map[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
314 m->map[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
315 m->map[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
316 m->map[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
320 m->map[11] = PA_CHANNEL_POSITION_TOP_CENTER;
324 m->map[9] = PA_CHANNEL_POSITION_SIDE_LEFT;
325 m->map[10] = PA_CHANNEL_POSITION_SIDE_RIGHT;
329 m->map[8] = PA_CHANNEL_POSITION_REAR_CENTER;
333 m->map[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
334 m->map[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
338 m->map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
339 m->map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
343 m->map[3] = PA_CHANNEL_POSITION_LFE;
347 m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
351 m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
352 m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
359 case PA_CHANNEL_MAP_OSS:
363 m->map[0] = PA_CHANNEL_POSITION_MONO;
367 m->map[6] = PA_CHANNEL_POSITION_REAR_LEFT;
368 m->map[7] = PA_CHANNEL_POSITION_REAR_RIGHT;
372 m->map[4] = PA_CHANNEL_POSITION_SIDE_LEFT;
373 m->map[5] = PA_CHANNEL_POSITION_SIDE_RIGHT;
377 m->map[3] = PA_CHANNEL_POSITION_LFE;
381 m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
385 m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
386 m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
395 pa_assert_not_reached();
399 pa_channel_map* pa_channel_map_init_extend(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
403 pa_assert(channels > 0);
404 pa_assert(channels <= PA_CHANNELS_MAX);
405 pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
407 pa_channel_map_init(m);
409 for (c = channels; c > 0; c--) {
411 if (pa_channel_map_init_auto(m, c, def)) {
414 for (; c < channels; c++) {
416 m->map[c] = PA_CHANNEL_POSITION_AUX0 + i;
420 m->channels = (uint8_t) channels;
429 const char* pa_channel_position_to_string(pa_channel_position_t pos) {
431 if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
437 const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos) {
439 if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
444 return _(pretty_table[pos]);
447 int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
453 pa_return_val_if_fail(pa_channel_map_valid(a), 0);
454 pa_return_val_if_fail(pa_channel_map_valid(b), 0);
456 if (a->channels != b->channels)
459 for (c = 0; c < a->channels; c++)
460 if (a->map[c] != b->map[c])
466 char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
468 pa_bool_t first = TRUE;
477 if (!pa_channel_map_valid(map)) {
478 pa_snprintf(s, l, _("(invalid)"));
484 for (channel = 0; channel < map->channels && l > 1; channel++) {
485 l -= pa_snprintf(e, l, "%s%s",
487 pa_channel_position_to_string(map->map[channel]));
496 pa_channel_position_t pa_channel_position_from_string(const char *p) {
497 pa_channel_position_t i;
500 /* Some special aliases */
501 if (pa_streq(p, "left"))
502 return PA_CHANNEL_POSITION_LEFT;
503 else if (pa_streq(p, "right"))
504 return PA_CHANNEL_POSITION_RIGHT;
505 else if (pa_streq(p, "center"))
506 return PA_CHANNEL_POSITION_CENTER;
507 else if (pa_streq(p, "subwoofer"))
508 return PA_CHANNEL_POSITION_SUBWOOFER;
510 for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++)
511 if (pa_streq(p, table[i]))
514 return PA_CHANNEL_POSITION_INVALID;
517 pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
525 pa_channel_map_init(&map);
527 /* We don't need to match against the well known channel mapping
528 * "mono" here explicitly, because that can be understood as
529 * listing with one channel called "mono". */
531 if (pa_streq(s, "stereo")) {
533 map.map[0] = PA_CHANNEL_POSITION_LEFT;
534 map.map[1] = PA_CHANNEL_POSITION_RIGHT;
536 } else if (pa_streq(s, "surround-40")) {
538 map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
539 map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
540 map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
541 map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
543 } else if (pa_streq(s, "surround-41")) {
545 map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
546 map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
547 map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
548 map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
549 map.map[4] = PA_CHANNEL_POSITION_LFE;
551 } else if (pa_streq(s, "surround-50")) {
553 map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
554 map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
555 map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
556 map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
557 map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
559 } else if (pa_streq(s, "surround-51")) {
561 map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
562 map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
563 map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
564 map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
565 map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
566 map.map[5] = PA_CHANNEL_POSITION_LFE;
568 } else if (pa_streq(s, "surround-71")) {
570 map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
571 map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
572 map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
573 map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
574 map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
575 map.map[5] = PA_CHANNEL_POSITION_LFE;
576 map.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
577 map.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
584 while ((p = pa_split(s, ",", &state))) {
585 pa_channel_position_t f;
587 if (map.channels >= PA_CHANNELS_MAX) {
592 if ((f = pa_channel_position_from_string(p)) == PA_CHANNEL_POSITION_INVALID) {
597 map.map[map.channels++] = f;
603 if (!pa_channel_map_valid(&map))
610 int pa_channel_map_valid(const pa_channel_map *map) {
615 if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX)
618 for (c = 0; c < map->channels; c++)
619 if (map->map[c] < 0 || map->map[c] >= PA_CHANNEL_POSITION_MAX)
625 int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *ss) {
629 pa_return_val_if_fail(pa_channel_map_valid(map), 0);
630 pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
632 return map->channels == ss->channels;
635 int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
636 pa_channel_position_mask_t am, bm;
641 pa_return_val_if_fail(pa_channel_map_valid(a), 0);
642 pa_return_val_if_fail(pa_channel_map_valid(b), 0);
644 am = pa_channel_map_mask(a);
645 bm = pa_channel_map_mask(b);
647 return (bm & am) == bm;
650 int pa_channel_map_can_balance(const pa_channel_map *map) {
651 pa_channel_position_mask_t m;
654 pa_return_val_if_fail(pa_channel_map_valid(map), 0);
656 m = pa_channel_map_mask(map);
659 (PA_CHANNEL_POSITION_MASK_LEFT & m) &&
660 (PA_CHANNEL_POSITION_MASK_RIGHT & m);
663 int pa_channel_map_can_fade(const pa_channel_map *map) {
664 pa_channel_position_mask_t m;
667 pa_return_val_if_fail(pa_channel_map_valid(map), 0);
669 m = pa_channel_map_mask(map);
672 (PA_CHANNEL_POSITION_MASK_FRONT & m) &&
673 (PA_CHANNEL_POSITION_MASK_REAR & m);
676 const char* pa_channel_map_to_name(const pa_channel_map *map) {
677 pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)];
682 pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
684 memset(in_map, 0, sizeof(in_map));
686 for (c = 0; c < map->channels; c++)
687 pa_bitset_set(in_map, map->map[c], TRUE);
689 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
690 PA_CHANNEL_POSITION_MONO, -1))
693 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
694 PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1))
697 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
698 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
699 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, -1))
700 return "surround-40";
702 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
703 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
704 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
705 PA_CHANNEL_POSITION_LFE, -1))
706 return "surround-41";
708 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
709 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
710 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
711 PA_CHANNEL_POSITION_FRONT_CENTER, -1))
712 return "surround-50";
714 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
715 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
716 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
717 PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1))
718 return "surround-51";
720 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
721 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
722 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
723 PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
724 PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, -1))
725 return "surround-71";
730 const char* pa_channel_map_to_pretty_name(const pa_channel_map *map) {
731 pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)];
736 pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
738 memset(in_map, 0, sizeof(in_map));
740 for (c = 0; c < map->channels; c++)
741 pa_bitset_set(in_map, map->map[c], TRUE);
745 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
746 PA_CHANNEL_POSITION_MONO, -1))
749 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
750 PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1))
753 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
754 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
755 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, -1))
756 return _("Surround 4.0");
758 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
759 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
760 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
761 PA_CHANNEL_POSITION_LFE, -1))
762 return _("Surround 4.1");
764 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
765 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
766 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
767 PA_CHANNEL_POSITION_FRONT_CENTER, -1))
768 return _("Surround 5.0");
770 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
771 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
772 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
773 PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1))
774 return _("Surround 5.1");
776 if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
777 PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
778 PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
779 PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
780 PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, -1))
781 return _("Surround 7.1");
786 int pa_channel_map_has_position(const pa_channel_map *map, pa_channel_position_t p) {
789 pa_return_val_if_fail(pa_channel_map_valid(map), 0);
790 pa_return_val_if_fail(p < PA_CHANNEL_POSITION_MAX, 0);
792 for (c = 0; c < map->channels; c++)
793 if (map->map[c] == p)
799 pa_channel_position_mask_t pa_channel_map_mask(const pa_channel_map *map) {
801 pa_channel_position_mask_t r = 0;
803 pa_return_val_if_fail(pa_channel_map_valid(map), 0);
805 for (c = 0; c < map->channels; c++)
806 r |= PA_CHANNEL_POSITION_MASK(map->map[c]);