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(pa_channels_valid(channels
));
203 pa_assert(def
< PA_CHANNEL_MAP_DEF_MAX
);
205 pa_channel_map_init(m
);
207 m
->channels
= (uint8_t) channels
;
210 case PA_CHANNEL_MAP_AIFF
:
212 /* This is somewhat compatible with RFC3551 */
216 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
220 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
221 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
;
222 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
223 m
->map
[3] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
224 m
->map
[4] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
;
225 m
->map
[5] = PA_CHANNEL_POSITION_REAR_CENTER
;
229 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
230 m
->map
[3] = PA_CHANNEL_POSITION_REAR_LEFT
;
231 m
->map
[4] = PA_CHANNEL_POSITION_REAR_RIGHT
;
235 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
236 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
240 m
->map
[0] = PA_CHANNEL_POSITION_LEFT
;
241 m
->map
[1] = PA_CHANNEL_POSITION_RIGHT
;
242 m
->map
[2] = PA_CHANNEL_POSITION_CENTER
;
246 m
->map
[0] = PA_CHANNEL_POSITION_LEFT
;
247 m
->map
[1] = PA_CHANNEL_POSITION_CENTER
;
248 m
->map
[2] = PA_CHANNEL_POSITION_RIGHT
;
249 m
->map
[3] = PA_CHANNEL_POSITION_REAR_CENTER
;
256 case PA_CHANNEL_MAP_ALSA
:
260 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
264 m
->map
[6] = PA_CHANNEL_POSITION_SIDE_LEFT
;
265 m
->map
[7] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
269 m
->map
[5] = PA_CHANNEL_POSITION_LFE
;
273 m
->map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
277 m
->map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
278 m
->map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
282 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
283 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
290 case PA_CHANNEL_MAP_AUX
: {
293 for (i
= 0; i
< channels
; i
++)
294 m
->map
[i
] = PA_CHANNEL_POSITION_AUX0
+ i
;
299 case PA_CHANNEL_MAP_WAVEEX
:
301 /* Following http://www.microsoft.com/whdc/device/audio/multichaud.mspx#EKLAC */
305 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
309 m
->map
[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT
;
310 m
->map
[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER
;
311 m
->map
[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT
;
315 m
->map
[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT
;
316 m
->map
[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER
;
317 m
->map
[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
;
321 m
->map
[11] = PA_CHANNEL_POSITION_TOP_CENTER
;
325 m
->map
[9] = PA_CHANNEL_POSITION_SIDE_LEFT
;
326 m
->map
[10] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
330 m
->map
[8] = PA_CHANNEL_POSITION_REAR_CENTER
;
334 m
->map
[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
;
335 m
->map
[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
;
339 m
->map
[4] = PA_CHANNEL_POSITION_REAR_LEFT
;
340 m
->map
[5] = PA_CHANNEL_POSITION_REAR_RIGHT
;
344 m
->map
[3] = PA_CHANNEL_POSITION_LFE
;
348 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
352 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
353 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
360 case PA_CHANNEL_MAP_OSS
:
364 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
368 m
->map
[6] = PA_CHANNEL_POSITION_REAR_LEFT
;
369 m
->map
[7] = PA_CHANNEL_POSITION_REAR_RIGHT
;
373 m
->map
[4] = PA_CHANNEL_POSITION_SIDE_LEFT
;
374 m
->map
[5] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
378 m
->map
[3] = PA_CHANNEL_POSITION_LFE
;
382 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
386 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
387 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(pa_channels_valid(channels
));
404 pa_assert(def
< PA_CHANNEL_MAP_DEF_MAX
);
406 pa_channel_map_init(m
);
408 for (c
= channels
; c
> 0; c
--) {
410 if (pa_channel_map_init_auto(m
, c
, def
)) {
413 for (; c
< channels
; c
++) {
415 m
->map
[c
] = PA_CHANNEL_POSITION_AUX0
+ i
;
419 m
->channels
= (uint8_t) channels
;
428 const char* pa_channel_position_to_string(pa_channel_position_t pos
) {
430 if (pos
< 0 || pos
>= PA_CHANNEL_POSITION_MAX
)
436 const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos
) {
438 if (pos
< 0 || pos
>= PA_CHANNEL_POSITION_MAX
)
443 return _(pretty_table
[pos
]);
446 int pa_channel_map_equal(const pa_channel_map
*a
, const pa_channel_map
*b
) {
452 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
454 if (PA_UNLIKELY(a
== b
))
457 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
459 if (a
->channels
!= b
->channels
)
462 for (c
= 0; c
< a
->channels
; c
++)
463 if (a
->map
[c
] != b
->map
[c
])
469 char* pa_channel_map_snprint(char *s
, size_t l
, const pa_channel_map
*map
) {
480 if (!pa_channel_map_valid(map
)) {
481 pa_snprintf(s
, l
, _("(invalid)"));
487 for (channel
= 0; channel
< map
->channels
&& l
> 1; channel
++) {
488 l
-= pa_snprintf(e
, l
, "%s%s",
490 pa_channel_position_to_string(map
->map
[channel
]));
499 pa_channel_position_t
pa_channel_position_from_string(const char *p
) {
500 pa_channel_position_t i
;
503 /* Some special aliases */
504 if (pa_streq(p
, "left"))
505 return PA_CHANNEL_POSITION_LEFT
;
506 else if (pa_streq(p
, "right"))
507 return PA_CHANNEL_POSITION_RIGHT
;
508 else if (pa_streq(p
, "center"))
509 return PA_CHANNEL_POSITION_CENTER
;
510 else if (pa_streq(p
, "subwoofer"))
511 return PA_CHANNEL_POSITION_SUBWOOFER
;
513 for (i
= 0; i
< PA_CHANNEL_POSITION_MAX
; i
++)
514 if (pa_streq(p
, table
[i
]))
517 return PA_CHANNEL_POSITION_INVALID
;
520 pa_channel_map
*pa_channel_map_parse(pa_channel_map
*rmap
, const char *s
) {
528 pa_channel_map_init(&map
);
530 /* We don't need to match against the well known channel mapping
531 * "mono" here explicitly, because that can be understood as
532 * listing with one channel called "mono". */
534 if (pa_streq(s
, "stereo")) {
536 map
.map
[0] = PA_CHANNEL_POSITION_LEFT
;
537 map
.map
[1] = PA_CHANNEL_POSITION_RIGHT
;
539 } else if (pa_streq(s
, "surround-21")) {
541 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
542 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
543 map
.map
[2] = PA_CHANNEL_POSITION_LFE
;
545 } else if (pa_streq(s
, "surround-40")) {
547 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
548 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
549 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
550 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
552 } else if (pa_streq(s
, "surround-41")) {
554 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
555 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
556 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
557 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
558 map
.map
[4] = PA_CHANNEL_POSITION_LFE
;
560 } else if (pa_streq(s
, "surround-50")) {
562 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
563 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
564 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
565 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
566 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
568 } else if (pa_streq(s
, "surround-51")) {
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
;
577 } else if (pa_streq(s
, "surround-71")) {
579 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
580 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
581 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
582 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
583 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
584 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
585 map
.map
[6] = PA_CHANNEL_POSITION_SIDE_LEFT
;
586 map
.map
[7] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
593 while ((p
= pa_split(s
, ",", &state
))) {
594 pa_channel_position_t f
;
596 if (map
.channels
>= PA_CHANNELS_MAX
) {
601 if ((f
= pa_channel_position_from_string(p
)) == PA_CHANNEL_POSITION_INVALID
) {
606 map
.map
[map
.channels
++] = f
;
612 if (!pa_channel_map_valid(&map
))
619 int pa_channel_map_valid(const pa_channel_map
*map
) {
624 if (!pa_channels_valid(map
->channels
))
627 for (c
= 0; c
< map
->channels
; c
++)
628 if (map
->map
[c
] < 0 || map
->map
[c
] >= PA_CHANNEL_POSITION_MAX
)
634 int pa_channel_map_compatible(const pa_channel_map
*map
, const pa_sample_spec
*ss
) {
638 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
639 pa_return_val_if_fail(pa_sample_spec_valid(ss
), 0);
641 return map
->channels
== ss
->channels
;
644 int pa_channel_map_superset(const pa_channel_map
*a
, const pa_channel_map
*b
) {
645 pa_channel_position_mask_t am
, bm
;
650 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
652 if (PA_UNLIKELY(a
== b
))
655 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
657 am
= pa_channel_map_mask(a
);
658 bm
= pa_channel_map_mask(b
);
660 return (bm
& am
) == bm
;
663 int pa_channel_map_can_balance(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_LEFT
& m
) &&
673 (PA_CHANNEL_POSITION_MASK_RIGHT
& m
);
676 int pa_channel_map_can_fade(const pa_channel_map
*map
) {
677 pa_channel_position_mask_t m
;
680 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
682 m
= pa_channel_map_mask(map
);
685 (PA_CHANNEL_POSITION_MASK_FRONT
& m
) &&
686 (PA_CHANNEL_POSITION_MASK_REAR
& m
);
689 const char* pa_channel_map_to_name(const pa_channel_map
*map
) {
690 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
695 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
697 memset(in_map
, 0, sizeof(in_map
));
699 for (c
= 0; c
< map
->channels
; c
++)
700 pa_bitset_set(in_map
, map
->map
[c
], true);
702 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
703 PA_CHANNEL_POSITION_MONO
, -1))
706 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
707 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
710 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
711 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
712 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
713 return "surround-40";
715 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
716 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
717 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
718 PA_CHANNEL_POSITION_LFE
, -1))
719 return "surround-41";
721 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
722 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
723 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
724 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
725 return "surround-50";
727 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
728 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
729 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
730 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
731 return "surround-51";
733 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
734 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
735 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
736 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
737 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
738 return "surround-71";
743 const char* pa_channel_map_to_pretty_name(const pa_channel_map
*map
) {
744 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
749 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
751 memset(in_map
, 0, sizeof(in_map
));
753 for (c
= 0; c
< map
->channels
; c
++)
754 pa_bitset_set(in_map
, map
->map
[c
], true);
758 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
759 PA_CHANNEL_POSITION_MONO
, -1))
762 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
763 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
766 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
767 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
768 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
769 return _("Surround 4.0");
771 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
772 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
773 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
774 PA_CHANNEL_POSITION_LFE
, -1))
775 return _("Surround 4.1");
777 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
778 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
779 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
780 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
781 return _("Surround 5.0");
783 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
784 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
785 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
786 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
787 return _("Surround 5.1");
789 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
790 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
791 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
792 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
793 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
794 return _("Surround 7.1");
799 int pa_channel_map_has_position(const pa_channel_map
*map
, pa_channel_position_t p
) {
802 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
803 pa_return_val_if_fail(p
< PA_CHANNEL_POSITION_MAX
, 0);
805 for (c
= 0; c
< map
->channels
; c
++)
806 if (map
->map
[c
] == p
)
812 pa_channel_position_mask_t
pa_channel_map_mask(const pa_channel_map
*map
) {
814 pa_channel_position_mask_t r
= 0;
816 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
818 for (c
= 0; c
< map
->channels
; c
++)
819 r
|= PA_CHANNEL_POSITION_MASK(map
->map
[c
]);