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_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);
456 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
458 if (a
->channels
!= b
->channels
)
461 for (c
= 0; c
< a
->channels
; c
++)
462 if (a
->map
[c
] != b
->map
[c
])
468 char* pa_channel_map_snprint(char *s
, size_t l
, const pa_channel_map
*map
) {
470 pa_bool_t first
= TRUE
;
479 if (!pa_channel_map_valid(map
)) {
480 pa_snprintf(s
, l
, _("(invalid)"));
486 for (channel
= 0; channel
< map
->channels
&& l
> 1; channel
++) {
487 l
-= pa_snprintf(e
, l
, "%s%s",
489 pa_channel_position_to_string(map
->map
[channel
]));
498 pa_channel_position_t
pa_channel_position_from_string(const char *p
) {
499 pa_channel_position_t i
;
502 /* Some special aliases */
503 if (pa_streq(p
, "left"))
504 return PA_CHANNEL_POSITION_LEFT
;
505 else if (pa_streq(p
, "right"))
506 return PA_CHANNEL_POSITION_RIGHT
;
507 else if (pa_streq(p
, "center"))
508 return PA_CHANNEL_POSITION_CENTER
;
509 else if (pa_streq(p
, "subwoofer"))
510 return PA_CHANNEL_POSITION_SUBWOOFER
;
512 for (i
= 0; i
< PA_CHANNEL_POSITION_MAX
; i
++)
513 if (pa_streq(p
, table
[i
]))
516 return PA_CHANNEL_POSITION_INVALID
;
519 pa_channel_map
*pa_channel_map_parse(pa_channel_map
*rmap
, const char *s
) {
527 pa_channel_map_init(&map
);
529 /* We don't need to match against the well known channel mapping
530 * "mono" here explicitly, because that can be understood as
531 * listing with one channel called "mono". */
533 if (pa_streq(s
, "stereo")) {
535 map
.map
[0] = PA_CHANNEL_POSITION_LEFT
;
536 map
.map
[1] = PA_CHANNEL_POSITION_RIGHT
;
538 } else if (pa_streq(s
, "surround-40")) {
540 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
541 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
542 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
543 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
545 } else if (pa_streq(s
, "surround-41")) {
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
;
551 map
.map
[4] = PA_CHANNEL_POSITION_LFE
;
553 } else if (pa_streq(s
, "surround-50")) {
555 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
556 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
557 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
558 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
559 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
561 } else if (pa_streq(s
, "surround-51")) {
563 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
564 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
565 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
566 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
567 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
568 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
570 } else if (pa_streq(s
, "surround-71")) {
572 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
573 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
574 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
575 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
576 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
577 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
578 map
.map
[6] = PA_CHANNEL_POSITION_SIDE_LEFT
;
579 map
.map
[7] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
586 while ((p
= pa_split(s
, ",", &state
))) {
587 pa_channel_position_t f
;
589 if (map
.channels
>= PA_CHANNELS_MAX
) {
594 if ((f
= pa_channel_position_from_string(p
)) == PA_CHANNEL_POSITION_INVALID
) {
599 map
.map
[map
.channels
++] = f
;
605 if (!pa_channel_map_valid(&map
))
612 int pa_channel_map_valid(const pa_channel_map
*map
) {
617 if (map
->channels
<= 0 || map
->channels
> PA_CHANNELS_MAX
)
620 for (c
= 0; c
< map
->channels
; c
++)
621 if (map
->map
[c
] < 0 || map
->map
[c
] >= PA_CHANNEL_POSITION_MAX
)
627 int pa_channel_map_compatible(const pa_channel_map
*map
, const pa_sample_spec
*ss
) {
631 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
632 pa_return_val_if_fail(pa_sample_spec_valid(ss
), 0);
634 return map
->channels
== ss
->channels
;
637 int pa_channel_map_superset(const pa_channel_map
*a
, const pa_channel_map
*b
) {
638 pa_channel_position_mask_t am
, bm
;
643 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
644 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
646 am
= pa_channel_map_mask(a
);
647 bm
= pa_channel_map_mask(b
);
649 return (bm
& am
) == bm
;
652 int pa_channel_map_can_balance(const pa_channel_map
*map
) {
653 pa_channel_position_mask_t m
;
656 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
658 m
= pa_channel_map_mask(map
);
661 (PA_CHANNEL_POSITION_MASK_LEFT
& m
) &&
662 (PA_CHANNEL_POSITION_MASK_RIGHT
& m
);
665 int pa_channel_map_can_fade(const pa_channel_map
*map
) {
666 pa_channel_position_mask_t m
;
669 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
671 m
= pa_channel_map_mask(map
);
674 (PA_CHANNEL_POSITION_MASK_FRONT
& m
) &&
675 (PA_CHANNEL_POSITION_MASK_REAR
& m
);
678 const char* pa_channel_map_to_name(const pa_channel_map
*map
) {
679 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
684 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
686 memset(in_map
, 0, sizeof(in_map
));
688 for (c
= 0; c
< map
->channels
; c
++)
689 pa_bitset_set(in_map
, map
->map
[c
], TRUE
);
691 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
692 PA_CHANNEL_POSITION_MONO
, -1))
695 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
696 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
699 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
700 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
701 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
702 return "surround-40";
704 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
705 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
706 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
707 PA_CHANNEL_POSITION_LFE
, -1))
708 return "surround-41";
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
,
713 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
714 return "surround-50";
716 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
717 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
718 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
719 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
720 return "surround-51";
722 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
723 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
724 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
725 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
726 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
727 return "surround-71";
732 const char* pa_channel_map_to_pretty_name(const pa_channel_map
*map
) {
733 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
738 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
740 memset(in_map
, 0, sizeof(in_map
));
742 for (c
= 0; c
< map
->channels
; c
++)
743 pa_bitset_set(in_map
, map
->map
[c
], TRUE
);
747 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
748 PA_CHANNEL_POSITION_MONO
, -1))
751 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
752 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
755 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
756 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
757 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
758 return _("Surround 4.0");
760 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
761 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
762 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
763 PA_CHANNEL_POSITION_LFE
, -1))
764 return _("Surround 4.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
,
769 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
770 return _("Surround 5.0");
772 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
773 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
774 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
775 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
776 return _("Surround 5.1");
778 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
779 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
780 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
781 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
782 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
783 return _("Surround 7.1");
788 int pa_channel_map_has_position(const pa_channel_map
*map
, pa_channel_position_t p
) {
791 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
792 pa_return_val_if_fail(p
< PA_CHANNEL_POSITION_MAX
, 0);
794 for (c
= 0; c
< map
->channels
; c
++)
795 if (map
->map
[c
] == p
)
801 pa_channel_position_mask_t
pa_channel_map_mask(const pa_channel_map
*map
) {
803 pa_channel_position_mask_t r
= 0;
805 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
807 for (c
= 0; c
< map
->channels
; c
++)
808 r
|= PA_CHANNEL_POSITION_MASK(map
->map
[c
]);