PulseAudio is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published
- by the Free Software Foundation; either version 2 of the License,
+ by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
PulseAudio is distributed in the hope that it will be useful, but
#include <pulse/xmalloc.h>
#include <pulse/i18n.h>
+
#include <pulsecore/core-util.h>
#include <pulsecore/macro.h>
#include <pulsecore/bitset.h>
+#include <pulsecore/sample-util.h>
#include "channelmap.h"
case 6:
m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
- m->map[1] = PA_CHANNEL_POSITION_SIDE_LEFT;
+ m->map[1] = PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER;
m->map[2] = PA_CHANNEL_POSITION_FRONT_CENTER;
m->map[3] = PA_CHANNEL_POSITION_FRONT_RIGHT;
- m->map[4] = PA_CHANNEL_POSITION_SIDE_RIGHT;
- m->map[5] = PA_CHANNEL_POSITION_LFE;
+ m->map[4] = PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
+ m->map[5] = PA_CHANNEL_POSITION_REAR_CENTER;
return m;
case 5:
m->map[0] = PA_CHANNEL_POSITION_LEFT;
m->map[1] = PA_CHANNEL_POSITION_CENTER;
m->map[2] = PA_CHANNEL_POSITION_RIGHT;
- m->map[3] = PA_CHANNEL_POSITION_LFE;
+ m->map[3] = PA_CHANNEL_POSITION_REAR_CENTER;
return m;
default:
case PA_CHANNEL_MAP_WAVEEX:
+ /* Following http://www.microsoft.com/whdc/device/audio/multichaud.mspx#EKLAC */
+
switch (channels) {
case 1:
m->map[0] = PA_CHANNEL_POSITION_MONO;
pa_assert(b);
pa_return_val_if_fail(pa_channel_map_valid(a), 0);
+
+ if (PA_UNLIKELY(a == b))
+ return 1;
+
pa_return_val_if_fail(pa_channel_map_valid(b), 0);
if (a->channels != b->channels)
return s;
}
+pa_channel_position_t pa_channel_position_from_string(const char *p) {
+ pa_channel_position_t i;
+ pa_assert(p);
+
+ /* Some special aliases */
+ if (pa_streq(p, "left"))
+ return PA_CHANNEL_POSITION_LEFT;
+ else if (pa_streq(p, "right"))
+ return PA_CHANNEL_POSITION_RIGHT;
+ else if (pa_streq(p, "center"))
+ return PA_CHANNEL_POSITION_CENTER;
+ else if (pa_streq(p, "subwoofer"))
+ return PA_CHANNEL_POSITION_SUBWOOFER;
+
+ for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++)
+ if (pa_streq(p, table[i]))
+ return i;
+
+ return PA_CHANNEL_POSITION_INVALID;
+}
+
pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
const char *state;
pa_channel_map map;
map.channels = 0;
while ((p = pa_split(s, ",", &state))) {
+ pa_channel_position_t f;
if (map.channels >= PA_CHANNELS_MAX) {
pa_xfree(p);
return NULL;
}
- /* Some special aliases */
- if (pa_streq(p, "left"))
- map.map[map.channels++] = PA_CHANNEL_POSITION_LEFT;
- else if (pa_streq(p, "right"))
- map.map[map.channels++] = PA_CHANNEL_POSITION_RIGHT;
- else if (pa_streq(p, "center"))
- map.map[map.channels++] = PA_CHANNEL_POSITION_CENTER;
- else if (pa_streq(p, "subwoofer"))
- map.map[map.channels++] = PA_CHANNEL_POSITION_SUBWOOFER;
- else {
- pa_channel_position_t i;
-
- for (i = 0; i < PA_CHANNEL_POSITION_MAX; i++)
- if (strcmp(p, table[i]) == 0) {
- map.map[map.channels++] = i;
- break;
- }
-
- if (i >= PA_CHANNEL_POSITION_MAX) {
- pa_xfree(p);
- return NULL;
- }
+ if ((f = pa_channel_position_from_string(p)) == PA_CHANNEL_POSITION_INVALID) {
+ pa_xfree(p);
+ return NULL;
}
+ map.map[map.channels++] = f;
pa_xfree(p);
}
}
int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
- pa_bitset_t in_a[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)];
- unsigned i;
+ pa_channel_position_mask_t am, bm;
pa_assert(a);
pa_assert(b);
pa_return_val_if_fail(pa_channel_map_valid(a), 0);
- pa_return_val_if_fail(pa_channel_map_valid(b), 0);
- memset(in_a, 0, sizeof(in_a));
+ if (PA_UNLIKELY(a == b))
+ return 1;
- for (i = 0; i < a->channels; i++)
- pa_bitset_set(in_a, a->map[i], TRUE);
+ pa_return_val_if_fail(pa_channel_map_valid(b), 0);
- for (i = 0; i < b->channels; i++)
- if (!pa_bitset_get(in_a, b->map[i]))
- return 0;
+ am = pa_channel_map_mask(a);
+ bm = pa_channel_map_mask(b);
- return 1;
+ return (bm & am) == bm;
}
int pa_channel_map_can_balance(const pa_channel_map *map) {
- unsigned c;
- pa_bool_t left = FALSE, right = FALSE;
+ pa_channel_position_mask_t m;
pa_assert(map);
-
pa_return_val_if_fail(pa_channel_map_valid(map), 0);
- for (c = 0; c < map->channels; c++) {
-
- switch (map->map[c]) {
- case PA_CHANNEL_POSITION_LEFT:
- case PA_CHANNEL_POSITION_REAR_LEFT:
- case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
- case PA_CHANNEL_POSITION_SIDE_LEFT:
- case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:
- case PA_CHANNEL_POSITION_TOP_REAR_LEFT:
- left = TRUE;
- break;
-
- case PA_CHANNEL_POSITION_RIGHT:
- case PA_CHANNEL_POSITION_REAR_RIGHT:
- case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
- case PA_CHANNEL_POSITION_SIDE_RIGHT:
- case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:
- case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:
- right = TRUE;
- break;
-
- default:
- ;
- }
-
- if (left && right)
- return 1;
- }
+ m = pa_channel_map_mask(map);
- return 0;
+ return
+ (PA_CHANNEL_POSITION_MASK_LEFT & m) &&
+ (PA_CHANNEL_POSITION_MASK_RIGHT & m);
}
int pa_channel_map_can_fade(const pa_channel_map *map) {
- unsigned c;
- pa_bool_t front = FALSE, rear = FALSE;
+ pa_channel_position_mask_t m;
pa_assert(map);
-
pa_return_val_if_fail(pa_channel_map_valid(map), 0);
- for (c = 0; c < map->channels; c++) {
-
- switch (map->map[c]) {
- case PA_CHANNEL_POSITION_FRONT_LEFT:
- case PA_CHANNEL_POSITION_FRONT_RIGHT:
- case PA_CHANNEL_POSITION_FRONT_CENTER:
- case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER:
- case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER:
- case PA_CHANNEL_POSITION_TOP_FRONT_LEFT:
- case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT:
- case PA_CHANNEL_POSITION_TOP_FRONT_CENTER:
- front = TRUE;
- break;
-
- case PA_CHANNEL_POSITION_REAR_LEFT:
- case PA_CHANNEL_POSITION_REAR_RIGHT:
- case PA_CHANNEL_POSITION_REAR_CENTER:
- case PA_CHANNEL_POSITION_TOP_REAR_LEFT:
- case PA_CHANNEL_POSITION_TOP_REAR_RIGHT:
- case PA_CHANNEL_POSITION_TOP_REAR_CENTER:
- rear = TRUE;
- break;
-
- default:
- ;
- }
-
- if (front && rear)
- return 1;
- }
+ m = pa_channel_map_mask(map);
- return 0;
+ return
+ (PA_CHANNEL_POSITION_MASK_FRONT & m) &&
+ (PA_CHANNEL_POSITION_MASK_REAR & m);
}
const char* pa_channel_map_to_name(const pa_channel_map *map) {
return NULL;
}
+
+int pa_channel_map_has_position(const pa_channel_map *map, pa_channel_position_t p) {
+ unsigned c;
+
+ pa_return_val_if_fail(pa_channel_map_valid(map), 0);
+ pa_return_val_if_fail(p < PA_CHANNEL_POSITION_MAX, 0);
+
+ for (c = 0; c < map->channels; c++)
+ if (map->map[c] == p)
+ return 1;
+
+ return 0;
+}
+
+pa_channel_position_mask_t pa_channel_map_mask(const pa_channel_map *map) {
+ unsigned c;
+ pa_channel_position_mask_t r = 0;
+
+ pa_return_val_if_fail(pa_channel_map_valid(map), 0);
+
+ for (c = 0; c < map->channels; c++)
+ r |= PA_CHANNEL_POSITION_MASK(map->map[c]);
+
+ return r;
+}