diff options
-rw-r--r-- | src/map-file | 3 | ||||
-rw-r--r-- | src/pulse/channelmap.c | 187 | ||||
-rw-r--r-- | src/pulse/channelmap.h | 21 |
3 files changed, 207 insertions, 4 deletions
diff --git a/src/map-file b/src/map-file index 55b13e13..cb5c749d 100644 --- a/src/map-file +++ b/src/map-file @@ -9,6 +9,7 @@ pa_browser_unref; pa_bytes_per_second; pa_bytes_snprint; pa_bytes_to_usec; +pa_channel_map_can_balance; pa_channel_map_compatible; pa_channel_map_equal; pa_channel_map_init; @@ -19,6 +20,8 @@ pa_channel_map_init_stereo; pa_channel_map_parse; pa_channel_map_snprint; pa_channel_map_superset; +pa_channel_map_to_name; +pa_channel_map_to_pretty_name; pa_channel_map_valid; pa_channel_position_to_pretty_string; pa_channel_position_to_string; diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c index 26eae599..455bda1b 100644 --- a/src/pulse/channelmap.c +++ b/src/pulse/channelmap.c @@ -32,6 +32,7 @@ #include <pulse/i18n.h> #include <pulsecore/core-util.h> #include <pulsecore/macro.h> +#include <pulsecore/bitset.h> #include "channelmap.h" @@ -497,11 +498,58 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) { pa_channel_map_init(&map); + /* We don't need to match against the well known channel mapping + * "mono" here explicitly, because that can be understood as + * listing with one channel called "mono". */ + if (strcmp(s, "stereo") == 0) { map.channels = 2; map.map[0] = PA_CHANNEL_POSITION_LEFT; map.map[1] = PA_CHANNEL_POSITION_RIGHT; goto finish; + } else if (strcmp(s, "surround-40") == 0) { + map.channels = 4; + map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + goto finish; + } else if (strcmp(s, "surround-41") == 0) { + map.channels = 5; + map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + map.map[4] = PA_CHANNEL_POSITION_LFE; + goto finish; + } else if (strcmp(s, "surround-50") == 0) { + map.channels = 5; + map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; + goto finish; + } else if (strcmp(s, "surround-51") == 0) { + map.channels = 6; + map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; + map.map[5] = PA_CHANNEL_POSITION_LFE; + goto finish; + } else if (strcmp(s, "surround-71") == 0) { + map.channels = 8; + map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT; + map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT; + map.map[2] = PA_CHANNEL_POSITION_REAR_LEFT; + map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT; + map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER; + map.map[5] = PA_CHANNEL_POSITION_LFE; + map.map[6] = PA_CHANNEL_POSITION_SIDE_LEFT; + map.map[7] = PA_CHANNEL_POSITION_SIDE_RIGHT; + goto finish; } state = NULL; @@ -579,7 +627,7 @@ int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *s } int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) { - pa_bool_t in_a[PA_CHANNEL_POSITION_MAX]; + pa_bitset_t in_a[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)]; unsigned i; pa_assert(a); @@ -588,11 +636,144 @@ int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) { memset(in_a, 0, sizeof(in_a)); for (i = 0; i < a->channels; i++) - in_a[a->map[i]] = TRUE; + pa_bitset_set(in_a, a->map[i], TRUE); for (i = 0; i < b->channels; i++) - if (!in_a[b->map[i]]) + if (!pa_bitset_get(in_a, b->map[i])) return 0; return 1; } + +int pa_channel_map_can_balance(const pa_channel_map *map) { + unsigned c; + + pa_assert(map); + + for (c = 0; c < map->channels; c++) + + switch (map->map[c]) { + case PA_CHANNEL_POSITION_LEFT: + case PA_CHANNEL_POSITION_RIGHT: + case PA_CHANNEL_POSITION_REAR_LEFT: + case PA_CHANNEL_POSITION_REAR_RIGHT: + case PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER: + case PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER: + case PA_CHANNEL_POSITION_SIDE_LEFT: + case PA_CHANNEL_POSITION_SIDE_RIGHT: + case PA_CHANNEL_POSITION_TOP_FRONT_LEFT: + case PA_CHANNEL_POSITION_TOP_FRONT_RIGHT: + case PA_CHANNEL_POSITION_TOP_REAR_LEFT: + case PA_CHANNEL_POSITION_TOP_REAR_RIGHT: + return 1; + + default: + ; + } + + return 0; +} + +const char* pa_channel_map_to_name(const pa_channel_map *map) { + pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)]; + unsigned c; + + pa_assert(map); + + memset(in_map, 0, sizeof(in_map)); + + for (c = 0; c < map->channels; c++) + pa_bitset_set(in_map, map->map[c], TRUE); + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_MONO, -1)) + return "mono"; + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1)) + return "stereo"; + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, -1)) + return "surround-40"; + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_LFE, -1)) + return "surround-41"; + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, -1)) + return "surround-50"; + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1)) + return "surround-51"; + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, -1)) + return "surround-71"; + + return NULL; +} + +const char* pa_channel_map_to_pretty_name(const pa_channel_map *map) { + pa_bitset_t in_map[PA_BITSET_ELEMENTS(PA_CHANNEL_POSITION_MAX)]; + unsigned c; + + pa_assert(map); + + memset(in_map, 0, sizeof(in_map)); + + for (c = 0; c < map->channels; c++) + pa_bitset_set(in_map, map->map[c], TRUE); + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_MONO, -1)) + return _("Mono"); + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT, -1)) + return _("Stereo"); + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, -1)) + return _("Surround 4.0"); + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_LFE, -1)) + return _("Surround 4.1"); + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, -1)) + return _("Surround 5.0"); + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, -1)) + return _("Surround 5.1"); + + if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX, + PA_CHANNEL_POSITION_FRONT_LEFT, PA_CHANNEL_POSITION_FRONT_RIGHT, + PA_CHANNEL_POSITION_REAR_LEFT, PA_CHANNEL_POSITION_REAR_RIGHT, + PA_CHANNEL_POSITION_FRONT_CENTER, PA_CHANNEL_POSITION_LFE, + PA_CHANNEL_POSITION_SIDE_LEFT, PA_CHANNEL_POSITION_SIDE_RIGHT, -1)) + return _("Surround 7.1"); + + return NULL; +} diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h index a6c044f1..6e92e761 100644 --- a/src/pulse/channelmap.h +++ b/src/pulse/channelmap.h @@ -214,7 +214,10 @@ const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos); /** Make a humand readable string from the specified channel map */ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map); -/** Parse a channel position list into a channel map structure. */ +/** Parse a channel position list or well-known mapping name into a + * channel map structure. This turns the output of + * pa_channel_map_snprint() and pa_channel_map_to_name() back into a + * pa_channel_map */ pa_channel_map *pa_channel_map_parse(pa_channel_map *map, const char *s); /** Compare two channel maps. Return 1 if both match. */ @@ -230,6 +233,22 @@ int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *s /** Returns non-zero if every channel defined in b is also defined in a. \since 0.9.15 */ int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) PA_GCC_PURE; +/** Returns non-zero if it makes sense to apply a volume 'balance' + * with this mapping, i.e. if there are left/right channels + * available. \since 0.9.15 */ +int pa_channel_map_can_balance(const pa_channel_map *map) PA_GCC_PURE; + +/** Tries to find a well-known channel mapping name for this channel + * mapping. I.e. "stereo", "surround-71" and so on. If the channel + * mapping is unknown NULL will be returned. This name can be parsed + * with pa_channel_map_parse() \since 0.9.15 */ +const char* pa_channel_map_to_name(const pa_channel_map *map) PA_GCC_PURE; + +/** Tries to find a human readable text label for this channel +mapping. I.e. "Stereo", "Surround 7.1" and so on. If the channel +mapping is unknown NULL will be returned. \since 0.9.15 */ +const char* pa_channel_map_to_pretty_name(const pa_channel_map *map) PA_GCC_PURE; + PA_C_DECL_END #endif |