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_("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
;
397 pa_assert_not_reached();
401 pa_channel_map
* pa_channel_map_init_extend(pa_channel_map
*m
, unsigned channels
, pa_channel_map_def_t def
) {
405 pa_assert(channels
> 0);
406 pa_assert(channels
<= PA_CHANNELS_MAX
);
407 pa_assert(def
< PA_CHANNEL_MAP_DEF_MAX
);
409 pa_channel_map_init(m
);
411 for (c
= channels
; c
> 0; c
--) {
413 if (pa_channel_map_init_auto(m
, c
, def
)) {
416 for (; c
< channels
; c
++) {
418 m
->map
[c
] = PA_CHANNEL_POSITION_AUX0
+ i
;
422 m
->channels
= (uint8_t) channels
;
431 const char* pa_channel_position_to_string(pa_channel_position_t pos
) {
433 if (pos
< 0 || pos
>= PA_CHANNEL_POSITION_MAX
)
439 const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos
) {
441 if (pos
< 0 || pos
>= PA_CHANNEL_POSITION_MAX
)
446 return _(pretty_table
[pos
]);
449 int pa_channel_map_equal(const pa_channel_map
*a
, const pa_channel_map
*b
) {
455 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
457 if (PA_UNLIKELY(a
== b
))
460 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
462 if (a
->channels
!= b
->channels
)
465 for (c
= 0; c
< a
->channels
; c
++)
466 if (a
->map
[c
] != b
->map
[c
])
472 char* pa_channel_map_snprint(char *s
, size_t l
, const pa_channel_map
*map
) {
474 pa_bool_t first
= TRUE
;
483 if (!pa_channel_map_valid(map
)) {
484 pa_snprintf(s
, l
, _("(invalid)"));
490 for (channel
= 0; channel
< map
->channels
&& l
> 1; channel
++) {
491 l
-= pa_snprintf(e
, l
, "%s%s",
493 pa_channel_position_to_string(map
->map
[channel
]));
502 pa_channel_position_t
pa_channel_position_from_string(const char *p
) {
503 pa_channel_position_t i
;
506 /* Some special aliases */
507 if (pa_streq(p
, "left"))
508 return PA_CHANNEL_POSITION_LEFT
;
509 else if (pa_streq(p
, "right"))
510 return PA_CHANNEL_POSITION_RIGHT
;
511 else if (pa_streq(p
, "center"))
512 return PA_CHANNEL_POSITION_CENTER
;
513 else if (pa_streq(p
, "subwoofer"))
514 return PA_CHANNEL_POSITION_SUBWOOFER
;
516 for (i
= 0; i
< PA_CHANNEL_POSITION_MAX
; i
++)
517 if (pa_streq(p
, table
[i
]))
520 return PA_CHANNEL_POSITION_INVALID
;
523 pa_channel_map
*pa_channel_map_parse(pa_channel_map
*rmap
, const char *s
) {
531 pa_channel_map_init(&map
);
533 /* We don't need to match against the well known channel mapping
534 * "mono" here explicitly, because that can be understood as
535 * listing with one channel called "mono". */
537 if (pa_streq(s
, "stereo")) {
539 map
.map
[0] = PA_CHANNEL_POSITION_LEFT
;
540 map
.map
[1] = PA_CHANNEL_POSITION_RIGHT
;
542 } else if (pa_streq(s
, "surround-40")) {
544 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
545 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
546 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
547 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
549 } else if (pa_streq(s
, "surround-41")) {
551 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
552 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
553 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
554 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
555 map
.map
[4] = PA_CHANNEL_POSITION_LFE
;
557 } else if (pa_streq(s
, "surround-50")) {
559 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
560 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
561 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
562 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
563 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
565 } else if (pa_streq(s
, "surround-51")) {
567 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
568 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
569 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
570 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
571 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
572 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
574 } else if (pa_streq(s
, "surround-71")) {
576 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
577 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
578 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
579 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
580 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
581 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
582 map
.map
[6] = PA_CHANNEL_POSITION_SIDE_LEFT
;
583 map
.map
[7] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
590 while ((p
= pa_split(s
, ",", &state
))) {
591 pa_channel_position_t f
;
593 if (map
.channels
>= PA_CHANNELS_MAX
) {
598 if ((f
= pa_channel_position_from_string(p
)) == PA_CHANNEL_POSITION_INVALID
) {
603 map
.map
[map
.channels
++] = f
;
609 if (!pa_channel_map_valid(&map
))
616 int pa_channel_map_valid(const pa_channel_map
*map
) {
621 if (map
->channels
<= 0 || map
->channels
> PA_CHANNELS_MAX
)
624 for (c
= 0; c
< map
->channels
; c
++)
625 if (map
->map
[c
] < 0 || map
->map
[c
] >= PA_CHANNEL_POSITION_MAX
)
631 int pa_channel_map_compatible(const pa_channel_map
*map
, const pa_sample_spec
*ss
) {
635 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
636 pa_return_val_if_fail(pa_sample_spec_valid(ss
), 0);
638 return map
->channels
== ss
->channels
;
641 int pa_channel_map_superset(const pa_channel_map
*a
, const pa_channel_map
*b
) {
642 pa_channel_position_mask_t am
, bm
;
647 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
649 if (PA_UNLIKELY(a
== b
))
652 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
654 am
= pa_channel_map_mask(a
);
655 bm
= pa_channel_map_mask(b
);
657 return (bm
& am
) == bm
;
660 int pa_channel_map_can_balance(const pa_channel_map
*map
) {
661 pa_channel_position_mask_t m
;
664 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
666 m
= pa_channel_map_mask(map
);
669 (PA_CHANNEL_POSITION_MASK_LEFT
& m
) &&
670 (PA_CHANNEL_POSITION_MASK_RIGHT
& m
);
673 int pa_channel_map_can_fade(const pa_channel_map
*map
) {
674 pa_channel_position_mask_t m
;
677 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
679 m
= pa_channel_map_mask(map
);
682 (PA_CHANNEL_POSITION_MASK_FRONT
& m
) &&
683 (PA_CHANNEL_POSITION_MASK_REAR
& m
);
686 const char* pa_channel_map_to_name(const pa_channel_map
*map
) {
687 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
692 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
694 memset(in_map
, 0, sizeof(in_map
));
696 for (c
= 0; c
< map
->channels
; c
++)
697 pa_bitset_set(in_map
, map
->map
[c
], TRUE
);
699 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
700 PA_CHANNEL_POSITION_MONO
, -1))
703 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
704 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
707 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
708 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
709 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
710 return "surround-40";
712 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
713 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
714 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
715 PA_CHANNEL_POSITION_LFE
, -1))
716 return "surround-41";
718 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
719 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
720 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
721 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
722 return "surround-50";
724 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
725 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
726 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
727 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
728 return "surround-51";
730 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
731 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
732 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
733 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
734 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
735 return "surround-71";
740 const char* pa_channel_map_to_pretty_name(const pa_channel_map
*map
) {
741 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
746 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
748 memset(in_map
, 0, sizeof(in_map
));
750 for (c
= 0; c
< map
->channels
; c
++)
751 pa_bitset_set(in_map
, map
->map
[c
], TRUE
);
755 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
756 PA_CHANNEL_POSITION_MONO
, -1))
759 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
760 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
763 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
764 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
765 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
766 return _("Surround 4.0");
768 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
769 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
770 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
771 PA_CHANNEL_POSITION_LFE
, -1))
772 return _("Surround 4.1");
774 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
775 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
776 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
777 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
778 return _("Surround 5.0");
780 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
781 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
782 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
783 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
784 return _("Surround 5.1");
786 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
787 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
788 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
789 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
790 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
791 return _("Surround 7.1");
796 int pa_channel_map_has_position(const pa_channel_map
*map
, pa_channel_position_t p
) {
799 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
800 pa_return_val_if_fail(p
< PA_CHANNEL_POSITION_MAX
, 0);
802 for (c
= 0; c
< map
->channels
; c
++)
803 if (map
->map
[c
] == p
)
809 pa_channel_position_mask_t
pa_channel_map_mask(const pa_channel_map
*map
) {
811 pa_channel_position_mask_t r
= 0;
813 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
815 for (c
= 0; c
< map
->channels
; c
++)
816 r
|= PA_CHANNEL_POSITION_MASK(map
->map
[c
]);