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>
33 #include <pulsecore/core-util.h>
34 #include <pulsecore/macro.h>
35 #include <pulsecore/bitset.h>
37 #include "channelmap.h"
39 const char *const table
[PA_CHANNEL_POSITION_MAX
] = {
40 [PA_CHANNEL_POSITION_MONO
] = "mono",
42 [PA_CHANNEL_POSITION_FRONT_CENTER
] = "front-center",
43 [PA_CHANNEL_POSITION_FRONT_LEFT
] = "front-left",
44 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = "front-right",
46 [PA_CHANNEL_POSITION_REAR_CENTER
] = "rear-center",
47 [PA_CHANNEL_POSITION_REAR_LEFT
] = "rear-left",
48 [PA_CHANNEL_POSITION_REAR_RIGHT
] = "rear-right",
50 [PA_CHANNEL_POSITION_LFE
] = "lfe",
52 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = "front-left-of-center",
53 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = "front-right-of-center",
55 [PA_CHANNEL_POSITION_SIDE_LEFT
] = "side-left",
56 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = "side-right",
58 [PA_CHANNEL_POSITION_AUX0
] = "aux0",
59 [PA_CHANNEL_POSITION_AUX1
] = "aux1",
60 [PA_CHANNEL_POSITION_AUX2
] = "aux2",
61 [PA_CHANNEL_POSITION_AUX3
] = "aux3",
62 [PA_CHANNEL_POSITION_AUX4
] = "aux4",
63 [PA_CHANNEL_POSITION_AUX5
] = "aux5",
64 [PA_CHANNEL_POSITION_AUX6
] = "aux6",
65 [PA_CHANNEL_POSITION_AUX7
] = "aux7",
66 [PA_CHANNEL_POSITION_AUX8
] = "aux8",
67 [PA_CHANNEL_POSITION_AUX9
] = "aux9",
68 [PA_CHANNEL_POSITION_AUX10
] = "aux10",
69 [PA_CHANNEL_POSITION_AUX11
] = "aux11",
70 [PA_CHANNEL_POSITION_AUX12
] = "aux12",
71 [PA_CHANNEL_POSITION_AUX13
] = "aux13",
72 [PA_CHANNEL_POSITION_AUX14
] = "aux14",
73 [PA_CHANNEL_POSITION_AUX15
] = "aux15",
74 [PA_CHANNEL_POSITION_AUX16
] = "aux16",
75 [PA_CHANNEL_POSITION_AUX17
] = "aux17",
76 [PA_CHANNEL_POSITION_AUX18
] = "aux18",
77 [PA_CHANNEL_POSITION_AUX19
] = "aux19",
78 [PA_CHANNEL_POSITION_AUX20
] = "aux20",
79 [PA_CHANNEL_POSITION_AUX21
] = "aux21",
80 [PA_CHANNEL_POSITION_AUX22
] = "aux22",
81 [PA_CHANNEL_POSITION_AUX23
] = "aux23",
82 [PA_CHANNEL_POSITION_AUX24
] = "aux24",
83 [PA_CHANNEL_POSITION_AUX25
] = "aux25",
84 [PA_CHANNEL_POSITION_AUX26
] = "aux26",
85 [PA_CHANNEL_POSITION_AUX27
] = "aux27",
86 [PA_CHANNEL_POSITION_AUX28
] = "aux28",
87 [PA_CHANNEL_POSITION_AUX29
] = "aux29",
88 [PA_CHANNEL_POSITION_AUX30
] = "aux30",
89 [PA_CHANNEL_POSITION_AUX31
] = "aux31",
91 [PA_CHANNEL_POSITION_TOP_CENTER
] = "top-center",
93 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = "top-front-center",
94 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = "top-front-left",
95 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = "top-front-right",
97 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = "top-rear-center",
98 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = "top-rear-left",
99 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = "top-rear-right"
102 const char *const pretty_table
[PA_CHANNEL_POSITION_MAX
] = {
103 [PA_CHANNEL_POSITION_MONO
] = N_("Mono"),
105 [PA_CHANNEL_POSITION_FRONT_CENTER
] = N_("Front Center"),
106 [PA_CHANNEL_POSITION_FRONT_LEFT
] = N_("Front Left"),
107 [PA_CHANNEL_POSITION_FRONT_RIGHT
] = N_("Front Right"),
109 [PA_CHANNEL_POSITION_REAR_CENTER
] = N_("Rear Center"),
110 [PA_CHANNEL_POSITION_REAR_LEFT
] = N_("Rear Left"),
111 [PA_CHANNEL_POSITION_REAR_RIGHT
] = N_("Rear Right"),
113 [PA_CHANNEL_POSITION_LFE
] = N_("Low Frequency Emmiter"),
115 [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
] = N_("Front Left-of-center"),
116 [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
] = N_("Front Right-of-center"),
118 [PA_CHANNEL_POSITION_SIDE_LEFT
] = N_("Side Left"),
119 [PA_CHANNEL_POSITION_SIDE_RIGHT
] = N_("Side Right"),
121 [PA_CHANNEL_POSITION_AUX0
] = N_("Auxiliary 0"),
122 [PA_CHANNEL_POSITION_AUX1
] = N_("Auxiliary 1"),
123 [PA_CHANNEL_POSITION_AUX2
] = N_("Auxiliary 2"),
124 [PA_CHANNEL_POSITION_AUX3
] = N_("Auxiliary 3"),
125 [PA_CHANNEL_POSITION_AUX4
] = N_("Auxiliary 4"),
126 [PA_CHANNEL_POSITION_AUX5
] = N_("Auxiliary 5"),
127 [PA_CHANNEL_POSITION_AUX6
] = N_("Auxiliary 6"),
128 [PA_CHANNEL_POSITION_AUX7
] = N_("Auxiliary 7"),
129 [PA_CHANNEL_POSITION_AUX8
] = N_("Auxiliary 8"),
130 [PA_CHANNEL_POSITION_AUX9
] = N_("Auxiliary 9"),
131 [PA_CHANNEL_POSITION_AUX10
] = N_("Auxiliary 10"),
132 [PA_CHANNEL_POSITION_AUX11
] = N_("Auxiliary 11"),
133 [PA_CHANNEL_POSITION_AUX12
] = N_("Auxiliary 12"),
134 [PA_CHANNEL_POSITION_AUX13
] = N_("Auxiliary 13"),
135 [PA_CHANNEL_POSITION_AUX14
] = N_("Auxiliary 14"),
136 [PA_CHANNEL_POSITION_AUX15
] = N_("Auxiliary 15"),
137 [PA_CHANNEL_POSITION_AUX16
] = N_("Auxiliary 16"),
138 [PA_CHANNEL_POSITION_AUX17
] = N_("Auxiliary 17"),
139 [PA_CHANNEL_POSITION_AUX18
] = N_("Auxiliary 18"),
140 [PA_CHANNEL_POSITION_AUX19
] = N_("Auxiliary 19"),
141 [PA_CHANNEL_POSITION_AUX20
] = N_("Auxiliary 20"),
142 [PA_CHANNEL_POSITION_AUX21
] = N_("Auxiliary 21"),
143 [PA_CHANNEL_POSITION_AUX22
] = N_("Auxiliary 22"),
144 [PA_CHANNEL_POSITION_AUX23
] = N_("Auxiliary 23"),
145 [PA_CHANNEL_POSITION_AUX24
] = N_("Auxiliary 24"),
146 [PA_CHANNEL_POSITION_AUX25
] = N_("Auxiliary 25"),
147 [PA_CHANNEL_POSITION_AUX26
] = N_("Auxiliary 26"),
148 [PA_CHANNEL_POSITION_AUX27
] = N_("Auxiliary 27"),
149 [PA_CHANNEL_POSITION_AUX28
] = N_("Auxiliary 28"),
150 [PA_CHANNEL_POSITION_AUX29
] = N_("Auxiliary 29"),
151 [PA_CHANNEL_POSITION_AUX30
] = N_("Auxiliary 30"),
152 [PA_CHANNEL_POSITION_AUX31
] = N_("Auxiliary 31"),
154 [PA_CHANNEL_POSITION_TOP_CENTER
] = N_("Top Center"),
156 [PA_CHANNEL_POSITION_TOP_FRONT_CENTER
] = N_("Top Front Center"),
157 [PA_CHANNEL_POSITION_TOP_FRONT_LEFT
] = N_("Top Front Left"),
158 [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
] = N_("Top Front Right"),
160 [PA_CHANNEL_POSITION_TOP_REAR_CENTER
] = N_("Top Rear Center"),
161 [PA_CHANNEL_POSITION_TOP_REAR_LEFT
] = N_("Top Rear Left"),
162 [PA_CHANNEL_POSITION_TOP_REAR_RIGHT
] = N_("Top Rear Right")
165 pa_channel_map
* pa_channel_map_init(pa_channel_map
*m
) {
171 for (c
= 0; c
< PA_CHANNELS_MAX
; c
++)
172 m
->map
[c
] = PA_CHANNEL_POSITION_INVALID
;
177 pa_channel_map
* pa_channel_map_init_mono(pa_channel_map
*m
) {
180 pa_channel_map_init(m
);
183 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
187 pa_channel_map
* pa_channel_map_init_stereo(pa_channel_map
*m
) {
190 pa_channel_map_init(m
);
193 m
->map
[0] = PA_CHANNEL_POSITION_LEFT
;
194 m
->map
[1] = PA_CHANNEL_POSITION_RIGHT
;
198 pa_channel_map
* pa_channel_map_init_auto(pa_channel_map
*m
, unsigned channels
, pa_channel_map_def_t def
) {
200 pa_assert(channels
> 0);
201 pa_assert(channels
<= PA_CHANNELS_MAX
);
202 pa_assert(def
< PA_CHANNEL_MAP_DEF_MAX
);
204 pa_channel_map_init(m
);
206 m
->channels
= (uint8_t) channels
;
209 case PA_CHANNEL_MAP_AIFF
:
211 /* This is somewhat compatible with RFC3551 */
215 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
219 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
220 m
->map
[1] = PA_CHANNEL_POSITION_REAR_LEFT
;
221 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
222 m
->map
[3] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
223 m
->map
[4] = PA_CHANNEL_POSITION_REAR_RIGHT
;
224 m
->map
[5] = PA_CHANNEL_POSITION_LFE
;
228 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
229 m
->map
[3] = PA_CHANNEL_POSITION_REAR_LEFT
;
230 m
->map
[4] = PA_CHANNEL_POSITION_REAR_RIGHT
;
234 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
235 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
239 m
->map
[0] = PA_CHANNEL_POSITION_LEFT
;
240 m
->map
[1] = PA_CHANNEL_POSITION_RIGHT
;
241 m
->map
[2] = PA_CHANNEL_POSITION_CENTER
;
245 m
->map
[0] = PA_CHANNEL_POSITION_LEFT
;
246 m
->map
[1] = PA_CHANNEL_POSITION_CENTER
;
247 m
->map
[2] = PA_CHANNEL_POSITION_RIGHT
;
248 m
->map
[3] = PA_CHANNEL_POSITION_LFE
;
255 case PA_CHANNEL_MAP_ALSA
:
259 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
263 m
->map
[6] = PA_CHANNEL_POSITION_SIDE_LEFT
;
264 m
->map
[7] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
268 m
->map
[5] = PA_CHANNEL_POSITION_LFE
;
272 m
->map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
276 m
->map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
277 m
->map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
281 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
282 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
289 case PA_CHANNEL_MAP_AUX
: {
292 for (i
= 0; i
< channels
; i
++)
293 m
->map
[i
] = PA_CHANNEL_POSITION_AUX0
+ i
;
298 case PA_CHANNEL_MAP_WAVEEX
:
302 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
306 m
->map
[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT
;
307 m
->map
[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER
;
308 m
->map
[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT
;
312 m
->map
[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT
;
313 m
->map
[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER
;
314 m
->map
[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
;
318 m
->map
[11] = PA_CHANNEL_POSITION_TOP_CENTER
;
322 m
->map
[9] = PA_CHANNEL_POSITION_SIDE_LEFT
;
323 m
->map
[10] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
327 m
->map
[8] = PA_CHANNEL_POSITION_REAR_CENTER
;
331 m
->map
[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
;
332 m
->map
[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
;
336 m
->map
[4] = PA_CHANNEL_POSITION_REAR_LEFT
;
337 m
->map
[5] = PA_CHANNEL_POSITION_REAR_RIGHT
;
341 m
->map
[3] = PA_CHANNEL_POSITION_LFE
;
345 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
349 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
350 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
357 case PA_CHANNEL_MAP_OSS
:
361 m
->map
[0] = PA_CHANNEL_POSITION_MONO
;
365 m
->map
[6] = PA_CHANNEL_POSITION_REAR_LEFT
;
366 m
->map
[7] = PA_CHANNEL_POSITION_REAR_RIGHT
;
370 m
->map
[4] = PA_CHANNEL_POSITION_SIDE_LEFT
;
371 m
->map
[5] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
375 m
->map
[3] = PA_CHANNEL_POSITION_LFE
;
379 m
->map
[2] = PA_CHANNEL_POSITION_FRONT_CENTER
;
383 m
->map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
384 m
->map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
393 pa_assert_not_reached();
397 pa_channel_map
* pa_channel_map_init_extend(pa_channel_map
*m
, unsigned channels
, pa_channel_map_def_t def
) {
401 pa_assert(channels
> 0);
402 pa_assert(channels
<= PA_CHANNELS_MAX
);
403 pa_assert(def
< PA_CHANNEL_MAP_DEF_MAX
);
405 pa_channel_map_init(m
);
407 for (c
= channels
; c
> 0; c
--) {
409 if (pa_channel_map_init_auto(m
, c
, def
)) {
412 for (; c
< channels
; c
++) {
414 m
->map
[c
] = PA_CHANNEL_POSITION_AUX0
+ i
;
418 m
->channels
= (uint8_t) channels
;
427 const char* pa_channel_position_to_string(pa_channel_position_t pos
) {
429 if (pos
< 0 || pos
>= PA_CHANNEL_POSITION_MAX
)
435 const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos
) {
437 if (pos
< 0 || pos
>= PA_CHANNEL_POSITION_MAX
)
442 return _(pretty_table
[pos
]);
445 int pa_channel_map_equal(const pa_channel_map
*a
, const pa_channel_map
*b
) {
451 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
452 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
454 if (a
->channels
!= b
->channels
)
457 for (c
= 0; c
< a
->channels
; c
++)
458 if (a
->map
[c
] != b
->map
[c
])
464 char* pa_channel_map_snprint(char *s
, size_t l
, const pa_channel_map
*map
) {
466 pa_bool_t first
= TRUE
;
475 if (!pa_channel_map_valid(map
)) {
476 pa_snprintf(s
, l
, _("(invalid)"));
482 for (channel
= 0; channel
< map
->channels
&& l
> 1; channel
++) {
483 l
-= pa_snprintf(e
, l
, "%s%s",
485 pa_channel_position_to_string(map
->map
[channel
]));
494 pa_channel_position_t
pa_channel_position_from_string(const char *p
) {
495 pa_channel_position_t i
;
498 /* Some special aliases */
499 if (pa_streq(p
, "left"))
500 return PA_CHANNEL_POSITION_LEFT
;
501 else if (pa_streq(p
, "right"))
502 return PA_CHANNEL_POSITION_RIGHT
;
503 else if (pa_streq(p
, "center"))
504 return PA_CHANNEL_POSITION_CENTER
;
505 else if (pa_streq(p
, "subwoofer"))
506 return PA_CHANNEL_POSITION_SUBWOOFER
;
508 for (i
= 0; i
< PA_CHANNEL_POSITION_MAX
; i
++)
509 if (pa_streq(p
, table
[i
]))
512 return PA_CHANNEL_POSITION_INVALID
;
515 pa_channel_map
*pa_channel_map_parse(pa_channel_map
*rmap
, const char *s
) {
523 pa_channel_map_init(&map
);
525 /* We don't need to match against the well known channel mapping
526 * "mono" here explicitly, because that can be understood as
527 * listing with one channel called "mono". */
529 if (pa_streq(s
, "stereo")) {
531 map
.map
[0] = PA_CHANNEL_POSITION_LEFT
;
532 map
.map
[1] = PA_CHANNEL_POSITION_RIGHT
;
534 } else if (pa_streq(s
, "surround-40")) {
536 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
537 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
538 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
539 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
541 } else if (pa_streq(s
, "surround-41")) {
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
;
547 map
.map
[4] = PA_CHANNEL_POSITION_LFE
;
549 } else if (pa_streq(s
, "surround-50")) {
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_FRONT_CENTER
;
557 } else if (pa_streq(s
, "surround-51")) {
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
;
564 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
566 } else if (pa_streq(s
, "surround-71")) {
568 map
.map
[0] = PA_CHANNEL_POSITION_FRONT_LEFT
;
569 map
.map
[1] = PA_CHANNEL_POSITION_FRONT_RIGHT
;
570 map
.map
[2] = PA_CHANNEL_POSITION_REAR_LEFT
;
571 map
.map
[3] = PA_CHANNEL_POSITION_REAR_RIGHT
;
572 map
.map
[4] = PA_CHANNEL_POSITION_FRONT_CENTER
;
573 map
.map
[5] = PA_CHANNEL_POSITION_LFE
;
574 map
.map
[6] = PA_CHANNEL_POSITION_SIDE_LEFT
;
575 map
.map
[7] = PA_CHANNEL_POSITION_SIDE_RIGHT
;
582 while ((p
= pa_split(s
, ",", &state
))) {
583 pa_channel_position_t f
;
585 if (map
.channels
>= PA_CHANNELS_MAX
) {
590 if ((f
= pa_channel_position_from_string(p
)) == PA_CHANNEL_POSITION_INVALID
) {
595 map
.map
[map
.channels
++] = f
;
601 if (!pa_channel_map_valid(&map
))
608 int pa_channel_map_valid(const pa_channel_map
*map
) {
613 if (map
->channels
<= 0 || map
->channels
> PA_CHANNELS_MAX
)
616 for (c
= 0; c
< map
->channels
; c
++)
617 if (map
->map
[c
] < 0 || map
->map
[c
] >= PA_CHANNEL_POSITION_MAX
)
623 int pa_channel_map_compatible(const pa_channel_map
*map
, const pa_sample_spec
*ss
) {
627 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
628 pa_return_val_if_fail(pa_sample_spec_valid(ss
), 0);
630 return map
->channels
== ss
->channels
;
633 int pa_channel_map_superset(const pa_channel_map
*a
, const pa_channel_map
*b
) {
634 pa_bitset_t in_a
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
640 pa_return_val_if_fail(pa_channel_map_valid(a
), 0);
641 pa_return_val_if_fail(pa_channel_map_valid(b
), 0);
643 memset(in_a
, 0, sizeof(in_a
));
645 for (i
= 0; i
< a
->channels
; i
++)
646 pa_bitset_set(in_a
, a
->map
[i
], TRUE
);
648 for (i
= 0; i
< b
->channels
; i
++)
649 if (!pa_bitset_get(in_a
, b
->map
[i
]))
655 int pa_channel_map_can_balance(const pa_channel_map
*map
) {
657 pa_bool_t left
= FALSE
, right
= FALSE
;
661 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
663 for (c
= 0; c
< map
->channels
; c
++) {
665 switch (map
->map
[c
]) {
666 case PA_CHANNEL_POSITION_LEFT
:
667 case PA_CHANNEL_POSITION_REAR_LEFT
:
668 case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
:
669 case PA_CHANNEL_POSITION_SIDE_LEFT
:
670 case PA_CHANNEL_POSITION_TOP_FRONT_LEFT
:
671 case PA_CHANNEL_POSITION_TOP_REAR_LEFT
:
675 case PA_CHANNEL_POSITION_RIGHT
:
676 case PA_CHANNEL_POSITION_REAR_RIGHT
:
677 case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
:
678 case PA_CHANNEL_POSITION_SIDE_RIGHT
:
679 case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
:
680 case PA_CHANNEL_POSITION_TOP_REAR_RIGHT
:
695 int pa_channel_map_can_fade(const pa_channel_map
*map
) {
697 pa_bool_t front
= FALSE
, rear
= FALSE
;
701 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
703 for (c
= 0; c
< map
->channels
; c
++) {
705 switch (map
->map
[c
]) {
706 case PA_CHANNEL_POSITION_FRONT_LEFT
:
707 case PA_CHANNEL_POSITION_FRONT_RIGHT
:
708 case PA_CHANNEL_POSITION_FRONT_CENTER
:
709 case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER
:
710 case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER
:
711 case PA_CHANNEL_POSITION_TOP_FRONT_LEFT
:
712 case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT
:
713 case PA_CHANNEL_POSITION_TOP_FRONT_CENTER
:
717 case PA_CHANNEL_POSITION_REAR_LEFT
:
718 case PA_CHANNEL_POSITION_REAR_RIGHT
:
719 case PA_CHANNEL_POSITION_REAR_CENTER
:
720 case PA_CHANNEL_POSITION_TOP_REAR_LEFT
:
721 case PA_CHANNEL_POSITION_TOP_REAR_RIGHT
:
722 case PA_CHANNEL_POSITION_TOP_REAR_CENTER
:
737 const char* pa_channel_map_to_name(const pa_channel_map
*map
) {
738 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
743 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
745 memset(in_map
, 0, sizeof(in_map
));
747 for (c
= 0; c
< map
->channels
; c
++)
748 pa_bitset_set(in_map
, map
->map
[c
], TRUE
);
750 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
751 PA_CHANNEL_POSITION_MONO
, -1))
754 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
755 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
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
, -1))
761 return "surround-40";
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
,
766 PA_CHANNEL_POSITION_LFE
, -1))
767 return "surround-41";
769 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
770 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
771 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
772 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
773 return "surround-50";
775 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
776 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
777 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
778 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
779 return "surround-51";
781 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
782 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
783 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
784 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
785 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
786 return "surround-71";
791 const char* pa_channel_map_to_pretty_name(const pa_channel_map
*map
) {
792 pa_bitset_t in_map
[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX
)];
797 pa_return_val_if_fail(pa_channel_map_valid(map
), NULL
);
799 memset(in_map
, 0, sizeof(in_map
));
801 for (c
= 0; c
< map
->channels
; c
++)
802 pa_bitset_set(in_map
, map
->map
[c
], TRUE
);
806 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
807 PA_CHANNEL_POSITION_MONO
, -1))
810 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
811 PA_CHANNEL_POSITION_LEFT
, PA_CHANNEL_POSITION_RIGHT
, -1))
814 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
815 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
816 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
, -1))
817 return _("Surround 4.0");
819 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
820 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
821 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
822 PA_CHANNEL_POSITION_LFE
, -1))
823 return _("Surround 4.1");
825 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
826 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
827 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
828 PA_CHANNEL_POSITION_FRONT_CENTER
, -1))
829 return _("Surround 5.0");
831 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
832 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
833 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
834 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
, -1))
835 return _("Surround 5.1");
837 if (pa_bitset_equals(in_map
, PA_CHANNEL_POSITION_MAX
,
838 PA_CHANNEL_POSITION_FRONT_LEFT
, PA_CHANNEL_POSITION_FRONT_RIGHT
,
839 PA_CHANNEL_POSITION_REAR_LEFT
, PA_CHANNEL_POSITION_REAR_RIGHT
,
840 PA_CHANNEL_POSITION_FRONT_CENTER
, PA_CHANNEL_POSITION_LFE
,
841 PA_CHANNEL_POSITION_SIDE_LEFT
, PA_CHANNEL_POSITION_SIDE_RIGHT
, -1))
842 return _("Surround 7.1");
847 int pa_channel_map_has_position(const pa_channel_map
*map
, pa_channel_position_t p
) {
850 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
851 pa_return_val_if_fail(p
< PA_CHANNEL_POSITION_MAX
, 0);
853 for (c
= 0; c
< map
->channels
; c
++)
854 if (map
->map
[c
] == p
)
860 pa_channel_position_mask_t
pa_channel_map_mask(const pa_channel_map
*map
) {
862 pa_channel_position_mask_t r
= 0;
864 pa_return_val_if_fail(pa_channel_map_valid(map
), 0);
866 for (c
= 0; c
< map
->channels
; c
++)
867 r
|= PA_CHANNEL_POSITION_MASK(map
->map
[c
]);