153a5a1b3Sopenharmony_ci/***
253a5a1b3Sopenharmony_ci  This file is part of PulseAudio.
353a5a1b3Sopenharmony_ci
453a5a1b3Sopenharmony_ci  Copyright 2005-2006 Lennart Poettering
553a5a1b3Sopenharmony_ci  Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
653a5a1b3Sopenharmony_ci
753a5a1b3Sopenharmony_ci  PulseAudio is free software; you can redistribute it and/or modify
853a5a1b3Sopenharmony_ci  it under the terms of the GNU Lesser General Public License as published
953a5a1b3Sopenharmony_ci  by the Free Software Foundation; either version 2.1 of the License,
1053a5a1b3Sopenharmony_ci  or (at your option) any later version.
1153a5a1b3Sopenharmony_ci
1253a5a1b3Sopenharmony_ci  PulseAudio is distributed in the hope that it will be useful, but
1353a5a1b3Sopenharmony_ci  WITHOUT ANY WARRANTY; without even the implied warranty of
1453a5a1b3Sopenharmony_ci  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1553a5a1b3Sopenharmony_ci  General Public License for more details.
1653a5a1b3Sopenharmony_ci
1753a5a1b3Sopenharmony_ci  You should have received a copy of the GNU Lesser General Public License
1853a5a1b3Sopenharmony_ci  along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
1953a5a1b3Sopenharmony_ci***/
2053a5a1b3Sopenharmony_ci
2153a5a1b3Sopenharmony_ci#ifdef HAVE_CONFIG_H
2253a5a1b3Sopenharmony_ci#include <config.h>
2353a5a1b3Sopenharmony_ci#endif
2453a5a1b3Sopenharmony_ci
2553a5a1b3Sopenharmony_ci#include <stdlib.h>
2653a5a1b3Sopenharmony_ci#include <stdio.h>
2753a5a1b3Sopenharmony_ci#include <string.h>
2853a5a1b3Sopenharmony_ci
2953a5a1b3Sopenharmony_ci#include <pulse/xmalloc.h>
3053a5a1b3Sopenharmony_ci
3153a5a1b3Sopenharmony_ci#include <pulsecore/i18n.h>
3253a5a1b3Sopenharmony_ci#include <pulsecore/core-util.h>
3353a5a1b3Sopenharmony_ci#include <pulsecore/macro.h>
3453a5a1b3Sopenharmony_ci#include <pulsecore/bitset.h>
3553a5a1b3Sopenharmony_ci#include <pulsecore/sample-util.h>
3653a5a1b3Sopenharmony_ci
3753a5a1b3Sopenharmony_ci#include "channelmap.h"
3853a5a1b3Sopenharmony_ci
3953a5a1b3Sopenharmony_cistatic const char *const table[PA_CHANNEL_POSITION_MAX] = {
4053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_MONO] = "mono",
4153a5a1b3Sopenharmony_ci
4253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_CENTER] = "front-center",
4353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_LEFT] = "front-left",
4453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_RIGHT] = "front-right",
4553a5a1b3Sopenharmony_ci
4653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_REAR_CENTER] = "rear-center",
4753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_REAR_LEFT] = "rear-left",
4853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_REAR_RIGHT] = "rear-right",
4953a5a1b3Sopenharmony_ci
5053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_LFE] = "lfe",
5153a5a1b3Sopenharmony_ci
5253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = "front-left-of-center",
5353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = "front-right-of-center",
5453a5a1b3Sopenharmony_ci
5553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_SIDE_LEFT] = "side-left",
5653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_SIDE_RIGHT] = "side-right",
5753a5a1b3Sopenharmony_ci
5853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX0] = "aux0",
5953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX1] = "aux1",
6053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX2] = "aux2",
6153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX3] = "aux3",
6253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX4] = "aux4",
6353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX5] = "aux5",
6453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX6] = "aux6",
6553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX7] = "aux7",
6653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX8] = "aux8",
6753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX9] = "aux9",
6853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX10] = "aux10",
6953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX11] = "aux11",
7053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX12] = "aux12",
7153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX13] = "aux13",
7253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX14] = "aux14",
7353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX15] = "aux15",
7453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX16] = "aux16",
7553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX17] = "aux17",
7653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX18] = "aux18",
7753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX19] = "aux19",
7853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX20] = "aux20",
7953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX21] = "aux21",
8053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX22] = "aux22",
8153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX23] = "aux23",
8253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX24] = "aux24",
8353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX25] = "aux25",
8453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX26] = "aux26",
8553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX27] = "aux27",
8653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX28] = "aux28",
8753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX29] = "aux29",
8853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX30] = "aux30",
8953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX31] = "aux31",
9053a5a1b3Sopenharmony_ci
9153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_CENTER] = "top-center",
9253a5a1b3Sopenharmony_ci
9353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = "top-front-center",
9453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = "top-front-left",
9553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = "top-front-right",
9653a5a1b3Sopenharmony_ci
9753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = "top-rear-center",
9853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = "top-rear-left",
9953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = "top-rear-right"
10053a5a1b3Sopenharmony_ci};
10153a5a1b3Sopenharmony_ci
10253a5a1b3Sopenharmony_cistatic const char *const pretty_table[PA_CHANNEL_POSITION_MAX] = {
10353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_MONO] = N_("Mono"),
10453a5a1b3Sopenharmony_ci
10553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_CENTER] = N_("Front Center"),
10653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_LEFT] = N_("Front Left"),
10753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_RIGHT] = N_("Front Right"),
10853a5a1b3Sopenharmony_ci
10953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_REAR_CENTER] = N_("Rear Center"),
11053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_REAR_LEFT] = N_("Rear Left"),
11153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_REAR_RIGHT] = N_("Rear Right"),
11253a5a1b3Sopenharmony_ci
11353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_LFE] = N_("Subwoofer"),
11453a5a1b3Sopenharmony_ci
11553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = N_("Front Left-of-center"),
11653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = N_("Front Right-of-center"),
11753a5a1b3Sopenharmony_ci
11853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_SIDE_LEFT] = N_("Side Left"),
11953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_SIDE_RIGHT] = N_("Side Right"),
12053a5a1b3Sopenharmony_ci
12153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX0] = N_("Auxiliary 0"),
12253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX1] = N_("Auxiliary 1"),
12353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX2] = N_("Auxiliary 2"),
12453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX3] = N_("Auxiliary 3"),
12553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX4] = N_("Auxiliary 4"),
12653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX5] = N_("Auxiliary 5"),
12753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX6] = N_("Auxiliary 6"),
12853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX7] = N_("Auxiliary 7"),
12953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX8] = N_("Auxiliary 8"),
13053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX9] = N_("Auxiliary 9"),
13153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX10] = N_("Auxiliary 10"),
13253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX11] = N_("Auxiliary 11"),
13353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX12] = N_("Auxiliary 12"),
13453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX13] = N_("Auxiliary 13"),
13553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX14] = N_("Auxiliary 14"),
13653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX15] = N_("Auxiliary 15"),
13753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX16] = N_("Auxiliary 16"),
13853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX17] = N_("Auxiliary 17"),
13953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX18] = N_("Auxiliary 18"),
14053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX19] = N_("Auxiliary 19"),
14153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX20] = N_("Auxiliary 20"),
14253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX21] = N_("Auxiliary 21"),
14353a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX22] = N_("Auxiliary 22"),
14453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX23] = N_("Auxiliary 23"),
14553a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX24] = N_("Auxiliary 24"),
14653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX25] = N_("Auxiliary 25"),
14753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX26] = N_("Auxiliary 26"),
14853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX27] = N_("Auxiliary 27"),
14953a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX28] = N_("Auxiliary 28"),
15053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX29] = N_("Auxiliary 29"),
15153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX30] = N_("Auxiliary 30"),
15253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_AUX31] = N_("Auxiliary 31"),
15353a5a1b3Sopenharmony_ci
15453a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_CENTER] = N_("Top Center"),
15553a5a1b3Sopenharmony_ci
15653a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_FRONT_CENTER] = N_("Top Front Center"),
15753a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_FRONT_LEFT] = N_("Top Front Left"),
15853a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_FRONT_RIGHT] = N_("Top Front Right"),
15953a5a1b3Sopenharmony_ci
16053a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_REAR_CENTER] = N_("Top Rear Center"),
16153a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_REAR_LEFT] = N_("Top Rear Left"),
16253a5a1b3Sopenharmony_ci    [PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = N_("Top Rear Right")
16353a5a1b3Sopenharmony_ci};
16453a5a1b3Sopenharmony_ci
16553a5a1b3Sopenharmony_cipa_channel_map* pa_channel_map_init(pa_channel_map *m) {
16653a5a1b3Sopenharmony_ci    unsigned c;
16753a5a1b3Sopenharmony_ci    pa_assert(m);
16853a5a1b3Sopenharmony_ci
16953a5a1b3Sopenharmony_ci    m->channels = 0;
17053a5a1b3Sopenharmony_ci
17153a5a1b3Sopenharmony_ci    for (c = 0; c < PA_CHANNELS_MAX; c++)
17253a5a1b3Sopenharmony_ci        m->map[c] = PA_CHANNEL_POSITION_INVALID;
17353a5a1b3Sopenharmony_ci
17453a5a1b3Sopenharmony_ci    return m;
17553a5a1b3Sopenharmony_ci}
17653a5a1b3Sopenharmony_ci
17753a5a1b3Sopenharmony_cipa_channel_map* pa_channel_map_init_mono(pa_channel_map *m) {
17853a5a1b3Sopenharmony_ci    pa_assert(m);
17953a5a1b3Sopenharmony_ci
18053a5a1b3Sopenharmony_ci    pa_channel_map_init(m);
18153a5a1b3Sopenharmony_ci
18253a5a1b3Sopenharmony_ci    m->channels = 1;
18353a5a1b3Sopenharmony_ci    m->map[0] = PA_CHANNEL_POSITION_MONO;
18453a5a1b3Sopenharmony_ci    return m;
18553a5a1b3Sopenharmony_ci}
18653a5a1b3Sopenharmony_ci
18753a5a1b3Sopenharmony_cipa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
18853a5a1b3Sopenharmony_ci    pa_assert(m);
18953a5a1b3Sopenharmony_ci
19053a5a1b3Sopenharmony_ci    pa_channel_map_init(m);
19153a5a1b3Sopenharmony_ci
19253a5a1b3Sopenharmony_ci    m->channels = 2;
19353a5a1b3Sopenharmony_ci    m->map[0] = PA_CHANNEL_POSITION_LEFT;
19453a5a1b3Sopenharmony_ci    m->map[1] = PA_CHANNEL_POSITION_RIGHT;
19553a5a1b3Sopenharmony_ci    return m;
19653a5a1b3Sopenharmony_ci}
19753a5a1b3Sopenharmony_ci
19853a5a1b3Sopenharmony_cipa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
19953a5a1b3Sopenharmony_ci    pa_assert(m);
20053a5a1b3Sopenharmony_ci    pa_assert(pa_channels_valid(channels));
20153a5a1b3Sopenharmony_ci    pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
20253a5a1b3Sopenharmony_ci
20353a5a1b3Sopenharmony_ci    pa_channel_map_init(m);
20453a5a1b3Sopenharmony_ci
20553a5a1b3Sopenharmony_ci    m->channels = (uint8_t) channels;
20653a5a1b3Sopenharmony_ci
20753a5a1b3Sopenharmony_ci    switch (def) {
20853a5a1b3Sopenharmony_ci        case PA_CHANNEL_MAP_AIFF:
20953a5a1b3Sopenharmony_ci
21053a5a1b3Sopenharmony_ci            /* This is somewhat compatible with RFC3551 */
21153a5a1b3Sopenharmony_ci
21253a5a1b3Sopenharmony_ci            switch (channels) {
21353a5a1b3Sopenharmony_ci                case 1:
21453a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_MONO;
21553a5a1b3Sopenharmony_ci                    return m;
21653a5a1b3Sopenharmony_ci
21753a5a1b3Sopenharmony_ci                case 6:
21853a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
21953a5a1b3Sopenharmony_ci                    m->map[1] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
22053a5a1b3Sopenharmony_ci                    m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
22153a5a1b3Sopenharmony_ci                    m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT;
22253a5a1b3Sopenharmony_ci                    m->map[4] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
22353a5a1b3Sopenharmony_ci                    m->map[5] = PA_CHANNEL_POSITION_REAR_CENTER;
22453a5a1b3Sopenharmony_ci                    return m;
22553a5a1b3Sopenharmony_ci
22653a5a1b3Sopenharmony_ci                case 5:
22753a5a1b3Sopenharmony_ci                    m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
22853a5a1b3Sopenharmony_ci                    m->map[3] = PA_CHANNEL_POSITION_REAR_LEFT;
22953a5a1b3Sopenharmony_ci                    m->map[4] = PA_CHANNEL_POSITION_REAR_RIGHT;
23053a5a1b3Sopenharmony_ci                    /* Fall through */
23153a5a1b3Sopenharmony_ci
23253a5a1b3Sopenharmony_ci                case 2:
23353a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
23453a5a1b3Sopenharmony_ci                    m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
23553a5a1b3Sopenharmony_ci                    return m;
23653a5a1b3Sopenharmony_ci
23753a5a1b3Sopenharmony_ci                case 3:
23853a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_LEFT;
23953a5a1b3Sopenharmony_ci                    m->map[1] = PA_CHANNEL_POSITION_RIGHT;
24053a5a1b3Sopenharmony_ci                    m->map[2] = PA_CHANNEL_POSITION_CENTER;
24153a5a1b3Sopenharmony_ci                    return m;
24253a5a1b3Sopenharmony_ci
24353a5a1b3Sopenharmony_ci                case 4:
24453a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_LEFT;
24553a5a1b3Sopenharmony_ci                    m->map[1] = PA_CHANNEL_POSITION_CENTER;
24653a5a1b3Sopenharmony_ci                    m->map[2] = PA_CHANNEL_POSITION_RIGHT;
24753a5a1b3Sopenharmony_ci                    m->map[3] = PA_CHANNEL_POSITION_REAR_CENTER;
24853a5a1b3Sopenharmony_ci                    return m;
24953a5a1b3Sopenharmony_ci
25053a5a1b3Sopenharmony_ci                default:
25153a5a1b3Sopenharmony_ci                    return NULL;
25253a5a1b3Sopenharmony_ci            }
25353a5a1b3Sopenharmony_ci
25453a5a1b3Sopenharmony_ci        case PA_CHANNEL_MAP_ALSA:
25553a5a1b3Sopenharmony_ci
25653a5a1b3Sopenharmony_ci            switch (channels) {
25753a5a1b3Sopenharmony_ci                case 1:
25853a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_MONO;
25953a5a1b3Sopenharmony_ci                    return m;
26053a5a1b3Sopenharmony_ci
26153a5a1b3Sopenharmony_ci                case 8:
26253a5a1b3Sopenharmony_ci                    m->map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
26353a5a1b3Sopenharmony_ci                    m->map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
26453a5a1b3Sopenharmony_ci                    /* Fall through */
26553a5a1b3Sopenharmony_ci
26653a5a1b3Sopenharmony_ci                case 6:
26753a5a1b3Sopenharmony_ci                    m->map[5] = PA_CHANNEL_POSITION_LFE;
26853a5a1b3Sopenharmony_ci                    /* Fall through */
26953a5a1b3Sopenharmony_ci
27053a5a1b3Sopenharmony_ci                case 5:
27153a5a1b3Sopenharmony_ci                    m->map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
27253a5a1b3Sopenharmony_ci                    /* Fall through */
27353a5a1b3Sopenharmony_ci
27453a5a1b3Sopenharmony_ci                case 4:
27553a5a1b3Sopenharmony_ci                    m->map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
27653a5a1b3Sopenharmony_ci                    m->map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
27753a5a1b3Sopenharmony_ci                    /* Fall through */
27853a5a1b3Sopenharmony_ci
27953a5a1b3Sopenharmony_ci                case 2:
28053a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
28153a5a1b3Sopenharmony_ci                    m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
28253a5a1b3Sopenharmony_ci                    return m;
28353a5a1b3Sopenharmony_ci
28453a5a1b3Sopenharmony_ci                default:
28553a5a1b3Sopenharmony_ci                    return NULL;
28653a5a1b3Sopenharmony_ci            }
28753a5a1b3Sopenharmony_ci
28853a5a1b3Sopenharmony_ci        case PA_CHANNEL_MAP_AUX: {
28953a5a1b3Sopenharmony_ci            unsigned i;
29053a5a1b3Sopenharmony_ci
29153a5a1b3Sopenharmony_ci            for (i = 0; i < channels; i++)
29253a5a1b3Sopenharmony_ci                m->map[i] = PA_CHANNEL_POSITION_AUX0 + i;
29353a5a1b3Sopenharmony_ci
29453a5a1b3Sopenharmony_ci            return m;
29553a5a1b3Sopenharmony_ci        }
29653a5a1b3Sopenharmony_ci
29753a5a1b3Sopenharmony_ci        case PA_CHANNEL_MAP_WAVEEX:
29853a5a1b3Sopenharmony_ci
29953a5a1b3Sopenharmony_ci            /* following: https://docs.microsoft.com/en-us/previous-versions/windows/hardware/design/dn653308(v=vs.85) */
30053a5a1b3Sopenharmony_ci            switch (channels) {
30153a5a1b3Sopenharmony_ci                case 1:
30253a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_MONO;
30353a5a1b3Sopenharmony_ci                    return m;
30453a5a1b3Sopenharmony_ci
30553a5a1b3Sopenharmony_ci                case 18:
30653a5a1b3Sopenharmony_ci                    m->map[15] = PA_CHANNEL_POSITION_TOP_REAR_LEFT;
30753a5a1b3Sopenharmony_ci                    m->map[16] = PA_CHANNEL_POSITION_TOP_REAR_CENTER;
30853a5a1b3Sopenharmony_ci                    m->map[17] = PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
30953a5a1b3Sopenharmony_ci                    /* Fall through */
31053a5a1b3Sopenharmony_ci
31153a5a1b3Sopenharmony_ci                case 15:
31253a5a1b3Sopenharmony_ci                    m->map[12] = PA_CHANNEL_POSITION_TOP_FRONT_LEFT;
31353a5a1b3Sopenharmony_ci                    m->map[13] = PA_CHANNEL_POSITION_TOP_FRONT_CENTER;
31453a5a1b3Sopenharmony_ci                    m->map[14] = PA_CHANNEL_POSITION_TOP_FRONT_RIGHT;
31553a5a1b3Sopenharmony_ci                    /* Fall through */
31653a5a1b3Sopenharmony_ci
31753a5a1b3Sopenharmony_ci                case 12:
31853a5a1b3Sopenharmony_ci                    m->map[11] = PA_CHANNEL_POSITION_TOP_CENTER;
31953a5a1b3Sopenharmony_ci                    /* Fall through */
32053a5a1b3Sopenharmony_ci
32153a5a1b3Sopenharmony_ci                case 11:
32253a5a1b3Sopenharmony_ci                    m->map[9] = PA_CHANNEL_POSITION_SIDE_LEFT;
32353a5a1b3Sopenharmony_ci                    m->map[10] = PA_CHANNEL_POSITION_SIDE_RIGHT;
32453a5a1b3Sopenharmony_ci                    /* Fall through */
32553a5a1b3Sopenharmony_ci
32653a5a1b3Sopenharmony_ci                case 9:
32753a5a1b3Sopenharmony_ci                    m->map[8] = PA_CHANNEL_POSITION_REAR_CENTER;
32853a5a1b3Sopenharmony_ci                    /* Fall through */
32953a5a1b3Sopenharmony_ci
33053a5a1b3Sopenharmony_ci                case 8:
33153a5a1b3Sopenharmony_ci                    m->map[6] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
33253a5a1b3Sopenharmony_ci                    m->map[7] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
33353a5a1b3Sopenharmony_ci                    /* Fall through */
33453a5a1b3Sopenharmony_ci
33553a5a1b3Sopenharmony_ci                case 6:
33653a5a1b3Sopenharmony_ci                    m->map[4] = PA_CHANNEL_POSITION_REAR_LEFT;
33753a5a1b3Sopenharmony_ci                    m->map[5] = PA_CHANNEL_POSITION_REAR_RIGHT;
33853a5a1b3Sopenharmony_ci                    /* Fall through */
33953a5a1b3Sopenharmony_ci
34053a5a1b3Sopenharmony_ci                case 4:
34153a5a1b3Sopenharmony_ci                    m->map[3] = PA_CHANNEL_POSITION_LFE;
34253a5a1b3Sopenharmony_ci                    /* Fall through */
34353a5a1b3Sopenharmony_ci
34453a5a1b3Sopenharmony_ci                case 3:
34553a5a1b3Sopenharmony_ci                    m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
34653a5a1b3Sopenharmony_ci                    /* Fall through */
34753a5a1b3Sopenharmony_ci
34853a5a1b3Sopenharmony_ci                case 2:
34953a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
35053a5a1b3Sopenharmony_ci                    m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
35153a5a1b3Sopenharmony_ci                    return m;
35253a5a1b3Sopenharmony_ci
35353a5a1b3Sopenharmony_ci                default:
35453a5a1b3Sopenharmony_ci                    return NULL;
35553a5a1b3Sopenharmony_ci            }
35653a5a1b3Sopenharmony_ci
35753a5a1b3Sopenharmony_ci        case PA_CHANNEL_MAP_OSS:
35853a5a1b3Sopenharmony_ci
35953a5a1b3Sopenharmony_ci            switch (channels) {
36053a5a1b3Sopenharmony_ci                case 1:
36153a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_MONO;
36253a5a1b3Sopenharmony_ci                    return m;
36353a5a1b3Sopenharmony_ci
36453a5a1b3Sopenharmony_ci                case 8:
36553a5a1b3Sopenharmony_ci                    m->map[6] = PA_CHANNEL_POSITION_REAR_LEFT;
36653a5a1b3Sopenharmony_ci                    m->map[7] = PA_CHANNEL_POSITION_REAR_RIGHT;
36753a5a1b3Sopenharmony_ci                    /* Fall through */
36853a5a1b3Sopenharmony_ci
36953a5a1b3Sopenharmony_ci                case 6:
37053a5a1b3Sopenharmony_ci                    m->map[4] = PA_CHANNEL_POSITION_SIDE_LEFT;
37153a5a1b3Sopenharmony_ci                    m->map[5] = PA_CHANNEL_POSITION_SIDE_RIGHT;
37253a5a1b3Sopenharmony_ci                    /* Fall through */
37353a5a1b3Sopenharmony_ci
37453a5a1b3Sopenharmony_ci                case 4:
37553a5a1b3Sopenharmony_ci                    m->map[3] = PA_CHANNEL_POSITION_LFE;
37653a5a1b3Sopenharmony_ci                    /* Fall through */
37753a5a1b3Sopenharmony_ci
37853a5a1b3Sopenharmony_ci                case 3:
37953a5a1b3Sopenharmony_ci                    m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
38053a5a1b3Sopenharmony_ci                    /* Fall through */
38153a5a1b3Sopenharmony_ci
38253a5a1b3Sopenharmony_ci                case 2:
38353a5a1b3Sopenharmony_ci                    m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
38453a5a1b3Sopenharmony_ci                    m->map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
38553a5a1b3Sopenharmony_ci                    return m;
38653a5a1b3Sopenharmony_ci
38753a5a1b3Sopenharmony_ci                default:
38853a5a1b3Sopenharmony_ci                    return NULL;
38953a5a1b3Sopenharmony_ci            }
39053a5a1b3Sopenharmony_ci
39153a5a1b3Sopenharmony_ci        default:
39253a5a1b3Sopenharmony_ci            pa_assert_not_reached();
39353a5a1b3Sopenharmony_ci    }
39453a5a1b3Sopenharmony_ci}
39553a5a1b3Sopenharmony_ci
39653a5a1b3Sopenharmony_cipa_channel_map* pa_channel_map_init_extend(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
39753a5a1b3Sopenharmony_ci    unsigned c;
39853a5a1b3Sopenharmony_ci
39953a5a1b3Sopenharmony_ci    pa_assert(m);
40053a5a1b3Sopenharmony_ci    pa_assert(pa_channels_valid(channels));
40153a5a1b3Sopenharmony_ci    pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
40253a5a1b3Sopenharmony_ci
40353a5a1b3Sopenharmony_ci    pa_channel_map_init(m);
40453a5a1b3Sopenharmony_ci
40553a5a1b3Sopenharmony_ci    for (c = channels; c > 0; c--) {
40653a5a1b3Sopenharmony_ci
40753a5a1b3Sopenharmony_ci        if (pa_channel_map_init_auto(m, c, def)) {
40853a5a1b3Sopenharmony_ci            unsigned i = 0;
40953a5a1b3Sopenharmony_ci
41053a5a1b3Sopenharmony_ci            for (; c < channels; c++) {
41153a5a1b3Sopenharmony_ci
41253a5a1b3Sopenharmony_ci                m->map[c] = PA_CHANNEL_POSITION_AUX0 + i;
41353a5a1b3Sopenharmony_ci                i++;
41453a5a1b3Sopenharmony_ci            }
41553a5a1b3Sopenharmony_ci
41653a5a1b3Sopenharmony_ci            m->channels = (uint8_t) channels;
41753a5a1b3Sopenharmony_ci
41853a5a1b3Sopenharmony_ci            return m;
41953a5a1b3Sopenharmony_ci        }
42053a5a1b3Sopenharmony_ci    }
42153a5a1b3Sopenharmony_ci
42253a5a1b3Sopenharmony_ci    return NULL;
42353a5a1b3Sopenharmony_ci}
42453a5a1b3Sopenharmony_ci
42553a5a1b3Sopenharmony_ciconst char* pa_channel_position_to_string(pa_channel_position_t pos) {
42653a5a1b3Sopenharmony_ci
42753a5a1b3Sopenharmony_ci    if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
42853a5a1b3Sopenharmony_ci        return NULL;
42953a5a1b3Sopenharmony_ci
43053a5a1b3Sopenharmony_ci    return table[pos];
43153a5a1b3Sopenharmony_ci}
43253a5a1b3Sopenharmony_ci
43353a5a1b3Sopenharmony_ciconst char* pa_channel_position_to_pretty_string(pa_channel_position_t pos) {
43453a5a1b3Sopenharmony_ci
43553a5a1b3Sopenharmony_ci    if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
43653a5a1b3Sopenharmony_ci        return NULL;
43753a5a1b3Sopenharmony_ci
43853a5a1b3Sopenharmony_ci    pa_init_i18n();
43953a5a1b3Sopenharmony_ci
44053a5a1b3Sopenharmony_ci    return _(pretty_table[pos]);
44153a5a1b3Sopenharmony_ci}
44253a5a1b3Sopenharmony_ci
44353a5a1b3Sopenharmony_ciint pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
44453a5a1b3Sopenharmony_ci    unsigned c;
44553a5a1b3Sopenharmony_ci
44653a5a1b3Sopenharmony_ci    pa_assert(a);
44753a5a1b3Sopenharmony_ci    pa_assert(b);
44853a5a1b3Sopenharmony_ci
44953a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(a), 0);
45053a5a1b3Sopenharmony_ci
45153a5a1b3Sopenharmony_ci    if (PA_UNLIKELY(a == b))
45253a5a1b3Sopenharmony_ci        return 1;
45353a5a1b3Sopenharmony_ci
45453a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(b), 0);
45553a5a1b3Sopenharmony_ci
45653a5a1b3Sopenharmony_ci    if (a->channels != b->channels)
45753a5a1b3Sopenharmony_ci        return 0;
45853a5a1b3Sopenharmony_ci
45953a5a1b3Sopenharmony_ci    for (c = 0; c < a->channels; c++)
46053a5a1b3Sopenharmony_ci        if (a->map[c] != b->map[c])
46153a5a1b3Sopenharmony_ci            return 0;
46253a5a1b3Sopenharmony_ci
46353a5a1b3Sopenharmony_ci    return 1;
46453a5a1b3Sopenharmony_ci}
46553a5a1b3Sopenharmony_ci
46653a5a1b3Sopenharmony_cichar* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
46753a5a1b3Sopenharmony_ci    unsigned channel;
46853a5a1b3Sopenharmony_ci    bool first = true;
46953a5a1b3Sopenharmony_ci    char *e;
47053a5a1b3Sopenharmony_ci
47153a5a1b3Sopenharmony_ci    pa_assert(s);
47253a5a1b3Sopenharmony_ci    pa_assert(l > 0);
47353a5a1b3Sopenharmony_ci    pa_assert(map);
47453a5a1b3Sopenharmony_ci
47553a5a1b3Sopenharmony_ci    pa_init_i18n();
47653a5a1b3Sopenharmony_ci
47753a5a1b3Sopenharmony_ci    if (!pa_channel_map_valid(map)) {
47853a5a1b3Sopenharmony_ci        pa_snprintf(s, l, _("(invalid)"));
47953a5a1b3Sopenharmony_ci        return s;
48053a5a1b3Sopenharmony_ci    }
48153a5a1b3Sopenharmony_ci
48253a5a1b3Sopenharmony_ci    *(e = s) = 0;
48353a5a1b3Sopenharmony_ci
48453a5a1b3Sopenharmony_ci    for (channel = 0; channel < map->channels && l > 1; channel++) {
48553a5a1b3Sopenharmony_ci        l -= pa_snprintf(e, l, "%s%s",
48653a5a1b3Sopenharmony_ci                      first ? "" : ",",
48753a5a1b3Sopenharmony_ci                      pa_channel_position_to_string(map->map[channel]));
48853a5a1b3Sopenharmony_ci
48953a5a1b3Sopenharmony_ci        e = strchr(e, 0);
49053a5a1b3Sopenharmony_ci        first = false;
49153a5a1b3Sopenharmony_ci    }
49253a5a1b3Sopenharmony_ci
49353a5a1b3Sopenharmony_ci    return s;
49453a5a1b3Sopenharmony_ci}
49553a5a1b3Sopenharmony_ci
49653a5a1b3Sopenharmony_cipa_channel_position_t pa_channel_position_from_string(const char *p) {
49753a5a1b3Sopenharmony_ci    pa_channel_position_t i;
49853a5a1b3Sopenharmony_ci    pa_assert(p);
49953a5a1b3Sopenharmony_ci
50053a5a1b3Sopenharmony_ci    /* Some special aliases */
50153a5a1b3Sopenharmony_ci    if (pa_streq(p, "left"))
50253a5a1b3Sopenharmony_ci        return PA_CHANNEL_POSITION_LEFT;
50353a5a1b3Sopenharmony_ci    else if (pa_streq(p, "right"))
50453a5a1b3Sopenharmony_ci        return PA_CHANNEL_POSITION_RIGHT;
50553a5a1b3Sopenharmony_ci    else if (pa_streq(p, "center"))
50653a5a1b3Sopenharmony_ci        return PA_CHANNEL_POSITION_CENTER;
50753a5a1b3Sopenharmony_ci    else if (pa_streq(p, "subwoofer"))
50853a5a1b3Sopenharmony_ci        return PA_CHANNEL_POSITION_SUBWOOFER;
50953a5a1b3Sopenharmony_ci
51053a5a1b3Sopenharmony_ci    for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++)
51153a5a1b3Sopenharmony_ci        if (pa_streq(p, table[i]))
51253a5a1b3Sopenharmony_ci            return i;
51353a5a1b3Sopenharmony_ci
51453a5a1b3Sopenharmony_ci    return PA_CHANNEL_POSITION_INVALID;
51553a5a1b3Sopenharmony_ci}
51653a5a1b3Sopenharmony_ci
51753a5a1b3Sopenharmony_cipa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
51853a5a1b3Sopenharmony_ci    const char *state;
51953a5a1b3Sopenharmony_ci    pa_channel_map map;
52053a5a1b3Sopenharmony_ci    char *p;
52153a5a1b3Sopenharmony_ci
52253a5a1b3Sopenharmony_ci    pa_assert(rmap);
52353a5a1b3Sopenharmony_ci    pa_assert(s);
52453a5a1b3Sopenharmony_ci
52553a5a1b3Sopenharmony_ci    pa_channel_map_init(&map);
52653a5a1b3Sopenharmony_ci
52753a5a1b3Sopenharmony_ci    /* We don't need to match against the well known channel mapping
52853a5a1b3Sopenharmony_ci     * "mono" here explicitly, because that can be understood as
52953a5a1b3Sopenharmony_ci     * listing with one channel called "mono". */
53053a5a1b3Sopenharmony_ci
53153a5a1b3Sopenharmony_ci    if (pa_streq(s, "stereo")) {
53253a5a1b3Sopenharmony_ci        map.channels = 2;
53353a5a1b3Sopenharmony_ci        map.map[0] = PA_CHANNEL_POSITION_LEFT;
53453a5a1b3Sopenharmony_ci        map.map[1] = PA_CHANNEL_POSITION_RIGHT;
53553a5a1b3Sopenharmony_ci        goto finish;
53653a5a1b3Sopenharmony_ci    } else if (pa_streq(s, "surround-21")) {
53753a5a1b3Sopenharmony_ci        map.channels = 3;
53853a5a1b3Sopenharmony_ci        map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
53953a5a1b3Sopenharmony_ci        map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
54053a5a1b3Sopenharmony_ci        map.map[2] = PA_CHANNEL_POSITION_LFE;
54153a5a1b3Sopenharmony_ci        goto finish;
54253a5a1b3Sopenharmony_ci    } else if (pa_streq(s, "surround-40")) {
54353a5a1b3Sopenharmony_ci        map.channels = 4;
54453a5a1b3Sopenharmony_ci        map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
54553a5a1b3Sopenharmony_ci        map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
54653a5a1b3Sopenharmony_ci        map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
54753a5a1b3Sopenharmony_ci        map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
54853a5a1b3Sopenharmony_ci        goto finish;
54953a5a1b3Sopenharmony_ci    } else if (pa_streq(s, "surround-41")) {
55053a5a1b3Sopenharmony_ci        map.channels = 5;
55153a5a1b3Sopenharmony_ci        map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
55253a5a1b3Sopenharmony_ci        map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
55353a5a1b3Sopenharmony_ci        map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
55453a5a1b3Sopenharmony_ci        map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
55553a5a1b3Sopenharmony_ci        map.map[4] = PA_CHANNEL_POSITION_LFE;
55653a5a1b3Sopenharmony_ci        goto finish;
55753a5a1b3Sopenharmony_ci    } else if (pa_streq(s, "surround-50")) {
55853a5a1b3Sopenharmony_ci        map.channels = 5;
55953a5a1b3Sopenharmony_ci        map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
56053a5a1b3Sopenharmony_ci        map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
56153a5a1b3Sopenharmony_ci        map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
56253a5a1b3Sopenharmony_ci        map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
56353a5a1b3Sopenharmony_ci        map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
56453a5a1b3Sopenharmony_ci        goto finish;
56553a5a1b3Sopenharmony_ci    } else if (pa_streq(s, "surround-51")) {
56653a5a1b3Sopenharmony_ci        map.channels = 6;
56753a5a1b3Sopenharmony_ci        map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
56853a5a1b3Sopenharmony_ci        map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
56953a5a1b3Sopenharmony_ci        map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
57053a5a1b3Sopenharmony_ci        map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
57153a5a1b3Sopenharmony_ci        map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
57253a5a1b3Sopenharmony_ci        map.map[5] = PA_CHANNEL_POSITION_LFE;
57353a5a1b3Sopenharmony_ci        goto finish;
57453a5a1b3Sopenharmony_ci    } else if (pa_streq(s, "surround-71")) {
57553a5a1b3Sopenharmony_ci        map.channels = 8;
57653a5a1b3Sopenharmony_ci        map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
57753a5a1b3Sopenharmony_ci        map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
57853a5a1b3Sopenharmony_ci        map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT;
57953a5a1b3Sopenharmony_ci        map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
58053a5a1b3Sopenharmony_ci        map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
58153a5a1b3Sopenharmony_ci        map.map[5] = PA_CHANNEL_POSITION_LFE;
58253a5a1b3Sopenharmony_ci        map.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT;
58353a5a1b3Sopenharmony_ci        map.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT;
58453a5a1b3Sopenharmony_ci        goto finish;
58553a5a1b3Sopenharmony_ci    }
58653a5a1b3Sopenharmony_ci
58753a5a1b3Sopenharmony_ci    state = NULL;
58853a5a1b3Sopenharmony_ci    map.channels = 0;
58953a5a1b3Sopenharmony_ci
59053a5a1b3Sopenharmony_ci    while ((p = pa_split(s, ",", &state))) {
59153a5a1b3Sopenharmony_ci        pa_channel_position_t f;
59253a5a1b3Sopenharmony_ci
59353a5a1b3Sopenharmony_ci        if (map.channels >= PA_CHANNELS_MAX) {
59453a5a1b3Sopenharmony_ci            pa_xfree(p);
59553a5a1b3Sopenharmony_ci            return NULL;
59653a5a1b3Sopenharmony_ci        }
59753a5a1b3Sopenharmony_ci
59853a5a1b3Sopenharmony_ci        if ((f = pa_channel_position_from_string(p)) == PA_CHANNEL_POSITION_INVALID) {
59953a5a1b3Sopenharmony_ci            pa_xfree(p);
60053a5a1b3Sopenharmony_ci            return NULL;
60153a5a1b3Sopenharmony_ci        }
60253a5a1b3Sopenharmony_ci
60353a5a1b3Sopenharmony_ci        map.map[map.channels++] = f;
60453a5a1b3Sopenharmony_ci        pa_xfree(p);
60553a5a1b3Sopenharmony_ci    }
60653a5a1b3Sopenharmony_ci
60753a5a1b3Sopenharmony_cifinish:
60853a5a1b3Sopenharmony_ci
60953a5a1b3Sopenharmony_ci    if (!pa_channel_map_valid(&map))
61053a5a1b3Sopenharmony_ci        return NULL;
61153a5a1b3Sopenharmony_ci
61253a5a1b3Sopenharmony_ci    *rmap = map;
61353a5a1b3Sopenharmony_ci    return rmap;
61453a5a1b3Sopenharmony_ci}
61553a5a1b3Sopenharmony_ci
61653a5a1b3Sopenharmony_ciint pa_channel_map_valid(const pa_channel_map *map) {
61753a5a1b3Sopenharmony_ci    unsigned c;
61853a5a1b3Sopenharmony_ci
61953a5a1b3Sopenharmony_ci    pa_assert(map);
62053a5a1b3Sopenharmony_ci
62153a5a1b3Sopenharmony_ci    if (!pa_channels_valid(map->channels))
62253a5a1b3Sopenharmony_ci        return 0;
62353a5a1b3Sopenharmony_ci
62453a5a1b3Sopenharmony_ci    for (c = 0; c < map->channels; c++)
62553a5a1b3Sopenharmony_ci        if (map->map[c] < 0 || map->map[c] >= PA_CHANNEL_POSITION_MAX)
62653a5a1b3Sopenharmony_ci            return 0;
62753a5a1b3Sopenharmony_ci
62853a5a1b3Sopenharmony_ci    return 1;
62953a5a1b3Sopenharmony_ci}
63053a5a1b3Sopenharmony_ci
63153a5a1b3Sopenharmony_ciint pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *ss) {
63253a5a1b3Sopenharmony_ci    pa_assert(map);
63353a5a1b3Sopenharmony_ci    pa_assert(ss);
63453a5a1b3Sopenharmony_ci
63553a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
63653a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
63753a5a1b3Sopenharmony_ci
63853a5a1b3Sopenharmony_ci    return map->channels == ss->channels;
63953a5a1b3Sopenharmony_ci}
64053a5a1b3Sopenharmony_ci
64153a5a1b3Sopenharmony_ciint pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
64253a5a1b3Sopenharmony_ci    pa_channel_position_mask_t am, bm;
64353a5a1b3Sopenharmony_ci
64453a5a1b3Sopenharmony_ci    pa_assert(a);
64553a5a1b3Sopenharmony_ci    pa_assert(b);
64653a5a1b3Sopenharmony_ci
64753a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(a), 0);
64853a5a1b3Sopenharmony_ci
64953a5a1b3Sopenharmony_ci    if (PA_UNLIKELY(a == b))
65053a5a1b3Sopenharmony_ci        return 1;
65153a5a1b3Sopenharmony_ci
65253a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(b), 0);
65353a5a1b3Sopenharmony_ci
65453a5a1b3Sopenharmony_ci    am = pa_channel_map_mask(a);
65553a5a1b3Sopenharmony_ci    bm = pa_channel_map_mask(b);
65653a5a1b3Sopenharmony_ci
65753a5a1b3Sopenharmony_ci    return (bm & am) == bm;
65853a5a1b3Sopenharmony_ci}
65953a5a1b3Sopenharmony_ci
66053a5a1b3Sopenharmony_ciint pa_channel_map_can_balance(const pa_channel_map *map) {
66153a5a1b3Sopenharmony_ci    pa_channel_position_mask_t m;
66253a5a1b3Sopenharmony_ci
66353a5a1b3Sopenharmony_ci    pa_assert(map);
66453a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
66553a5a1b3Sopenharmony_ci
66653a5a1b3Sopenharmony_ci    m = pa_channel_map_mask(map);
66753a5a1b3Sopenharmony_ci
66853a5a1b3Sopenharmony_ci    return
66953a5a1b3Sopenharmony_ci        (PA_CHANNEL_POSITION_MASK_LEFT & m) &&
67053a5a1b3Sopenharmony_ci        (PA_CHANNEL_POSITION_MASK_RIGHT & m);
67153a5a1b3Sopenharmony_ci}
67253a5a1b3Sopenharmony_ci
67353a5a1b3Sopenharmony_ciint pa_channel_map_can_fade(const pa_channel_map *map) {
67453a5a1b3Sopenharmony_ci    pa_channel_position_mask_t m;
67553a5a1b3Sopenharmony_ci
67653a5a1b3Sopenharmony_ci    pa_assert(map);
67753a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
67853a5a1b3Sopenharmony_ci
67953a5a1b3Sopenharmony_ci    m = pa_channel_map_mask(map);
68053a5a1b3Sopenharmony_ci
68153a5a1b3Sopenharmony_ci    return
68253a5a1b3Sopenharmony_ci        (PA_CHANNEL_POSITION_MASK_FRONT & m) &&
68353a5a1b3Sopenharmony_ci        (PA_CHANNEL_POSITION_MASK_REAR & m);
68453a5a1b3Sopenharmony_ci}
68553a5a1b3Sopenharmony_ci
68653a5a1b3Sopenharmony_ciint pa_channel_map_can_lfe_balance(const pa_channel_map *map) {
68753a5a1b3Sopenharmony_ci    pa_channel_position_mask_t m;
68853a5a1b3Sopenharmony_ci
68953a5a1b3Sopenharmony_ci    pa_assert(map);
69053a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
69153a5a1b3Sopenharmony_ci
69253a5a1b3Sopenharmony_ci    m = pa_channel_map_mask(map);
69353a5a1b3Sopenharmony_ci
69453a5a1b3Sopenharmony_ci    return
69553a5a1b3Sopenharmony_ci        (PA_CHANNEL_POSITION_MASK_LFE & m) &&
69653a5a1b3Sopenharmony_ci        (PA_CHANNEL_POSITION_MASK_HFE & m);
69753a5a1b3Sopenharmony_ci}
69853a5a1b3Sopenharmony_ci
69953a5a1b3Sopenharmony_ciconst char* pa_channel_map_to_name(const pa_channel_map *map) {
70053a5a1b3Sopenharmony_ci    pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)];
70153a5a1b3Sopenharmony_ci    unsigned c;
70253a5a1b3Sopenharmony_ci
70353a5a1b3Sopenharmony_ci    pa_assert(map);
70453a5a1b3Sopenharmony_ci
70553a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
70653a5a1b3Sopenharmony_ci
70753a5a1b3Sopenharmony_ci    memset(in_map, 0, sizeof(in_map));
70853a5a1b3Sopenharmony_ci
70953a5a1b3Sopenharmony_ci    for (c = 0; c < map->channels; c++)
71053a5a1b3Sopenharmony_ci        pa_bitset_set(in_map, map->map[c], true);
71153a5a1b3Sopenharmony_ci
71253a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
71353a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_MONO, -1))
71453a5a1b3Sopenharmony_ci        return "mono";
71553a5a1b3Sopenharmony_ci
71653a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
71753a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1))
71853a5a1b3Sopenharmony_ci        return "stereo";
71953a5a1b3Sopenharmony_ci
72053a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
72153a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
72253a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, -1))
72353a5a1b3Sopenharmony_ci        return "surround-40";
72453a5a1b3Sopenharmony_ci
72553a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
72653a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
72753a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
72853a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_LFE, -1))
72953a5a1b3Sopenharmony_ci        return "surround-41";
73053a5a1b3Sopenharmony_ci
73153a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
73253a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
73353a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
73453a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_CENTER, -1))
73553a5a1b3Sopenharmony_ci        return "surround-50";
73653a5a1b3Sopenharmony_ci
73753a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
73853a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
73953a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
74053a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1))
74153a5a1b3Sopenharmony_ci        return "surround-51";
74253a5a1b3Sopenharmony_ci
74353a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
74453a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
74553a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
74653a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
74753a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, -1))
74853a5a1b3Sopenharmony_ci        return "surround-71";
74953a5a1b3Sopenharmony_ci
75053a5a1b3Sopenharmony_ci    return NULL;
75153a5a1b3Sopenharmony_ci}
75253a5a1b3Sopenharmony_ci
75353a5a1b3Sopenharmony_ciconst char* pa_channel_map_to_pretty_name(const pa_channel_map *map) {
75453a5a1b3Sopenharmony_ci    pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)];
75553a5a1b3Sopenharmony_ci    unsigned c;
75653a5a1b3Sopenharmony_ci
75753a5a1b3Sopenharmony_ci    pa_assert(map);
75853a5a1b3Sopenharmony_ci
75953a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
76053a5a1b3Sopenharmony_ci
76153a5a1b3Sopenharmony_ci    memset(in_map, 0, sizeof(in_map));
76253a5a1b3Sopenharmony_ci
76353a5a1b3Sopenharmony_ci    for (c = 0; c < map->channels; c++)
76453a5a1b3Sopenharmony_ci        pa_bitset_set(in_map, map->map[c], true);
76553a5a1b3Sopenharmony_ci
76653a5a1b3Sopenharmony_ci    pa_init_i18n();
76753a5a1b3Sopenharmony_ci
76853a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
76953a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_MONO, -1))
77053a5a1b3Sopenharmony_ci        return _("Mono");
77153a5a1b3Sopenharmony_ci
77253a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
77353a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1))
77453a5a1b3Sopenharmony_ci        return _("Stereo");
77553a5a1b3Sopenharmony_ci
77653a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
77753a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
77853a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, -1))
77953a5a1b3Sopenharmony_ci        return _("Surround 4.0");
78053a5a1b3Sopenharmony_ci
78153a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
78253a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
78353a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
78453a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_LFE, -1))
78553a5a1b3Sopenharmony_ci        return _("Surround 4.1");
78653a5a1b3Sopenharmony_ci
78753a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
78853a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
78953a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
79053a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_CENTER, -1))
79153a5a1b3Sopenharmony_ci        return _("Surround 5.0");
79253a5a1b3Sopenharmony_ci
79353a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
79453a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
79553a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
79653a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1))
79753a5a1b3Sopenharmony_ci        return _("Surround 5.1");
79853a5a1b3Sopenharmony_ci
79953a5a1b3Sopenharmony_ci    if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
80053a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT,
80153a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT,
80253a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE,
80353a5a1b3Sopenharmony_ci                         PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, -1))
80453a5a1b3Sopenharmony_ci        return _("Surround 7.1");
80553a5a1b3Sopenharmony_ci
80653a5a1b3Sopenharmony_ci    return NULL;
80753a5a1b3Sopenharmony_ci}
80853a5a1b3Sopenharmony_ci
80953a5a1b3Sopenharmony_ciint pa_channel_map_has_position(const pa_channel_map *map, pa_channel_position_t p) {
81053a5a1b3Sopenharmony_ci    unsigned c;
81153a5a1b3Sopenharmony_ci
81253a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
81353a5a1b3Sopenharmony_ci    pa_return_val_if_fail(p < PA_CHANNEL_POSITION_MAX, 0);
81453a5a1b3Sopenharmony_ci
81553a5a1b3Sopenharmony_ci    for (c = 0; c < map->channels; c++)
81653a5a1b3Sopenharmony_ci        if (map->map[c] == p)
81753a5a1b3Sopenharmony_ci            return 1;
81853a5a1b3Sopenharmony_ci
81953a5a1b3Sopenharmony_ci    return 0;
82053a5a1b3Sopenharmony_ci}
82153a5a1b3Sopenharmony_ci
82253a5a1b3Sopenharmony_cipa_channel_position_mask_t pa_channel_map_mask(const pa_channel_map *map) {
82353a5a1b3Sopenharmony_ci    unsigned c;
82453a5a1b3Sopenharmony_ci    pa_channel_position_mask_t r = 0;
82553a5a1b3Sopenharmony_ci
82653a5a1b3Sopenharmony_ci    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
82753a5a1b3Sopenharmony_ci
82853a5a1b3Sopenharmony_ci    for (c = 0; c < map->channels; c++)
82953a5a1b3Sopenharmony_ci        r |= PA_CHANNEL_POSITION_MASK(map->map[c]);
83053a5a1b3Sopenharmony_ci
83153a5a1b3Sopenharmony_ci    return r;
83253a5a1b3Sopenharmony_ci}
833