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>
33 #include <pulsecore/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_("Subwoofer"),
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_FRONT_LEFT_OF_CENTER
;
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_FRONT_RIGHT_OF_CENTER
;
226 m
->map
[5] = PA_CHANNEL_POSITION_REAR_CENTER
;
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_REAR_CENTER
;
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
:
302 /* Following http://www.microsoft.com/whdc/device/audio/multichaud.mspx#EKLAC */
306 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
310 m
->map
[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT
;
311 m
->map
[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER
;
312 m
->map
[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT
;
316 m
->map
[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT
;
317 m
->map
[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER
;
318 m
->map
[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
;
322 m
->map
[11] = PA_CHANNEL_POSITION_TOP_CENTER
;
326 m
->map
[9] = PA_CHANNEL_POSITION_SIDE_LEFT
;
327 m
->map
[10] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
331 m
->map
[8] = PA_CHANNEL_POSITION_REAR_CENTER
;
335 m
->map
[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
;
336 m
->map
[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
;
340 m
->map
[4] = PA_CHANNEL_POSITION_REAR_LEFT
;
341 m
->map
[5] = PA_CHANNEL_POSITION_REAR_RIGHT
;
345 m
->map
[3] = PA_CHANNEL_POSITION_LFE
;
349 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
353 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
354 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
361 case PA_CHANNEL_MAP_OSS
:
365 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
369 m
->map
[6] = PA_CHANNEL_POSITION_REAR_LEFT
;
370 m
->map
[7] = PA_CHANNEL_POSITION_REAR_RIGHT
;
374 m
->map
[4] = PA_CHANNEL_POSITION_SIDE_LEFT
;
375 m
->map
[5] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
379 m
->map
[3] = PA_CHANNEL_POSITION_LFE
;
383 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
387 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
388 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
396 pa_assert_not_reached();
400 pa_channel_map
* pa_channel_map_init_extend(pa_channel_map
*m
, unsigned channels
, pa_channel_map_def_t def
) {
404 pa_assert(channels
> 0);
405 pa_assert(channels
<= PA_CHANNELS_MAX
);
406 pa_assert(def
< PA_CHANNEL_MAP_DEF_MAX
);
408 pa_channel_map_init(m
);
410 for (c
= channels
; c
> 0; c
--) {
412 if (pa_channel_map_init_auto(m
, c
, def
)) {
415 for (; c
< channels
; c
++) {
417 m
->map
[c
] = PA_CHANNEL_POSITION_AUX0
+ i
;
421 m
->channels
= (uint8_t) channels
;
430 const char* pa_channel_position_to_string(pa_channel_position_t pos
) {
432 if (pos
< 0 || pos
>= PA_CHANNEL_POSITION_MAX
)
438 const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos
) {
440 if (pos
< 0 || pos
>= PA_CHANNEL_POSITION_MAX
)
445 return _(pretty_table
[pos
]);
448 int pa_channel_map_equal(const pa_channel_map
*a
, const pa_channel_map
*b
) {
454 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
456 if (PA_UNLIKELY(a
== b
))
459 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
461 if (a
->channels
!= b
->channels
)
464 for (c
= 0; c
< a
->channels
; c
++)
465 if (a
->map
[c
] != b
->map
[c
])
471 char* pa_channel_map_snprint(char *s
, size_t l
, const pa_channel_map
*map
) {
473 pa_bool_t first
= TRUE
;
482 if (!pa_channel_map_valid(map
)) {
483 pa_snprintf(s
, l
, _("(invalid)"));
489 for (channel
= 0; channel
< map
->channels
&& l
> 1; channel
++) {
490 l
-= pa_snprintf(e
, l
, "%s%s",
492 pa_channel_position_to_string(map
->map
[channel
]));
501 pa_channel_position_t
pa_channel_position_from_string(const char *p
) {
502 pa_channel_position_t i
;
505 /* Some special aliases */
506 if (pa_streq(p
, "left"))
507 return PA_CHANNEL_POSITION_LEFT
;
508 else if (pa_streq(p
, "right"))
509 return PA_CHANNEL_POSITION_RIGHT
;
510 else if (pa_streq(p
, "center"))
511 return PA_CHANNEL_POSITION_CENTER
;
512 else if (pa_streq(p
, "subwoofer"))
513 return PA_CHANNEL_POSITION_SUBWOOFER
;
515 for (i
= 0; i
< PA_CHANNEL_POSITION_MAX
; i
++)
516 if (pa_streq(p
, table
[i
]))
519 return PA_CHANNEL_POSITION_INVALID
;
522 pa_channel_map
*pa_channel_map_parse(pa_channel_map
*rmap
, const char *s
) {
530 pa_channel_map_init(&map
);
532 /* We don't need to match against the well known channel mapping
533 * "mono" here explicitly, because that can be understood as
534 * listing with one channel called "mono". */
536 if (pa_streq(s
, "stereo")) {
538 map
.map
[0] = PA_CHANNEL_POSITION_LEFT
;
539 map
.map
[1] = PA_CHANNEL_POSITION_RIGHT
;
541 } else if (pa_streq(s
, "surround-40")) {
543 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
544 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
545 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
546 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
548 } else if (pa_streq(s
, "surround-41")) {
550 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
551 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
552 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
553 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
554 map
.map
[4] = PA_CHANNEL_POSITION_LFE
;
556 } else if (pa_streq(s
, "surround-50")) {
558 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
559 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
560 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
561 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
562 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
564 } else if (pa_streq(s
, "surround-51")) {
566 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
567 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
568 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
569 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
570 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
571 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
573 } else if (pa_streq(s
, "surround-71")) {
575 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
576 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
577 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
578 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
579 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
580 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
581 map
.map
[6] = PA_CHANNEL_POSITION_SIDE_LEFT
;
582 map
.map
[7] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
589 while ((p
= pa_split(s
, ",", &state
))) {
590 pa_channel_position_t f
;
592 if (map
.channels
>= PA_CHANNELS_MAX
) {
597 if ((f
= pa_channel_position_from_string(p
)) == PA_CHANNEL_POSITION_INVALID
) {
602 map
.map
[map
.channels
++] = f
;
608 if (!pa_channel_map_valid(&map
))
615 int pa_channel_map_valid(const pa_channel_map
*map
) {
620 if (map
->channels
<= 0 || map
->channels
> PA_CHANNELS_MAX
)
623 for (c
= 0; c
< map
->channels
; c
++)
624 if (map
->map
[c
] < 0 || map
->map
[c
] >= PA_CHANNEL_POSITION_MAX
)
630 int pa_channel_map_compatible(const pa_channel_map
*map
, const pa_sample_spec
*ss
) {
634 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
635 pa_return_val_if_fail(pa_sample_spec_valid(ss
), 0);
637 return map
->channels
== ss
->channels
;
640 int pa_channel_map_superset(const pa_channel_map
*a
, const pa_channel_map
*b
) {
641 pa_channel_position_mask_t am
, bm
;
646 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
648 if (PA_UNLIKELY(a
== b
))
651 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
653 am
= pa_channel_map_mask(a
);
654 bm
= pa_channel_map_mask(b
);
656 return (bm
& am
) == bm
;
659 int pa_channel_map_can_balance(const pa_channel_map
*map
) {
660 pa_channel_position_mask_t m
;
663 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
665 m
= pa_channel_map_mask(map
);
668 (PA_CHANNEL_POSITION_MASK_LEFT
& m
) &&
669 (PA_CHANNEL_POSITION_MASK_RIGHT
& m
);
672 int pa_channel_map_can_fade(const pa_channel_map
*map
) {
673 pa_channel_position_mask_t m
;
676 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
678 m
= pa_channel_map_mask(map
);
681 (PA_CHANNEL_POSITION_MASK_FRONT
& m
) &&
682 (PA_CHANNEL_POSITION_MASK_REAR
& m
);
685 const char* pa_channel_map_to_name(const pa_channel_map
*map
) {
686 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
691 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
693 memset(in_map
, 0, sizeof(in_map
));
695 for (c
= 0; c
< map
->channels
; c
++)
696 pa_bitset_set(in_map
, map
->map
[c
], TRUE
);
698 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
699 PA_CHANNEL_POSITION_MONO
, -1))
702 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
703 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
706 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
707 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
708 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
709 return "surround-40";
711 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
712 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
713 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
714 PA_CHANNEL_POSITION_LFE
, -1))
715 return "surround-41";
717 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
718 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
719 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
720 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
721 return "surround-50";
723 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
724 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
725 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
726 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
727 return "surround-51";
729 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
730 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
731 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
732 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
733 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
734 return "surround-71";
739 const char* pa_channel_map_to_pretty_name(const pa_channel_map
*map
) {
740 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
745 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
747 memset(in_map
, 0, sizeof(in_map
));
749 for (c
= 0; c
< map
->channels
; c
++)
750 pa_bitset_set(in_map
, map
->map
[c
], TRUE
);
754 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
755 PA_CHANNEL_POSITION_MONO
, -1))
758 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
759 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
762 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
763 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
764 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
765 return _("Surround 4.0");
767 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
768 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
769 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
770 PA_CHANNEL_POSITION_LFE
, -1))
771 return _("Surround 4.1");
773 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
774 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
775 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
776 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
777 return _("Surround 5.0");
779 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
780 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
781 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
782 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
783 return _("Surround 5.1");
785 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
786 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
787 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
788 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
789 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
790 return _("Surround 7.1");
795 int pa_channel_map_has_position(const pa_channel_map
*map
, pa_channel_position_t p
) {
798 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
799 pa_return_val_if_fail(p
< PA_CHANNEL_POSITION_MAX
, 0);
801 for (c
= 0; c
< map
->channels
; c
++)
802 if (map
->map
[c
] == p
)
808 pa_channel_position_mask_t
pa_channel_map_mask(const pa_channel_map
*map
) {
810 pa_channel_position_mask_t r
= 0;
812 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
814 for (c
= 0; c
< map
->channels
; c
++)
815 r
|= PA_CHANNEL_POSITION_MASK(map
->map
[c
]);