]> code.delx.au - pulseaudio/blobdiff - src/pulse/channelmap.c
core: Fix uninit pointer read in protocol-native
[pulseaudio] / src / pulse / channelmap.c
index 455bda1bae1abc7d66f4049a3dfa433446edb647..72e4130eeffcae0afee44f02cf4e93c6bf2bf3f9 100644 (file)
@@ -6,7 +6,7 @@
 
   PulseAudio is free software; you can redistribute it and/or modify
   it under the terms of the GNU Lesser General Public License as published
 
   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
   or (at your option) any later version.
 
   PulseAudio is distributed in the hope that it will be useful, but
 #include <string.h>
 
 #include <pulse/xmalloc.h>
 #include <string.h>
 
 #include <pulse/xmalloc.h>
-#include <pulse/i18n.h>
+
+#include <pulsecore/i18n.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/bitset.h>
 #include <pulsecore/core-util.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/bitset.h>
+#include <pulsecore/sample-util.h>
 
 #include "channelmap.h"
 
 
 #include "channelmap.h"
 
@@ -110,7 +112,7 @@ const char *const pretty_table[PA_CHANNEL_POSITION_MAX] = {
     [PA_CHANNEL_POSITION_REAR_LEFT] = N_("Rear Left"),
     [PA_CHANNEL_POSITION_REAR_RIGHT] = N_("Rear Right"),
 
     [PA_CHANNEL_POSITION_REAR_LEFT] = N_("Rear Left"),
     [PA_CHANNEL_POSITION_REAR_RIGHT] = N_("Rear Right"),
 
-    [PA_CHANNEL_POSITION_LFE] = N_("Low Frequency Emmiter"),
+    [PA_CHANNEL_POSITION_LFE] = N_("Subwoofer"),
 
     [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = N_("Front Left-of-center"),
     [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = N_("Front Right-of-center"),
 
     [PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER] = N_("Front Left-of-center"),
     [PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER] = N_("Front Right-of-center"),
@@ -197,8 +199,7 @@ pa_channel_map* pa_channel_map_init_stereo(pa_channel_map *m) {
 
 pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
     pa_assert(m);
 
 pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, pa_channel_map_def_t def) {
     pa_assert(m);
-    pa_assert(channels > 0);
-    pa_assert(channels <= PA_CHANNELS_MAX);
+    pa_assert(pa_channels_valid(channels));
     pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
 
     pa_channel_map_init(m);
     pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
 
     pa_channel_map_init(m);
@@ -217,11 +218,11 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p
 
                 case 6:
                     m->map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
 
                 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[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:
                     return m;
 
                 case 5:
@@ -245,7 +246,7 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p
                     m->map[0] = PA_CHANNEL_POSITION_LEFT;
                     m->map[1] = PA_CHANNEL_POSITION_CENTER;
                     m->map[2] = PA_CHANNEL_POSITION_RIGHT;
                     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:
                     return m;
 
                 default:
@@ -297,6 +298,8 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p
 
         case PA_CHANNEL_MAP_WAVEEX:
 
 
         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;
             switch (channels) {
                 case 1:
                     m->map[0] = PA_CHANNEL_POSITION_MONO;
@@ -388,7 +391,6 @@ pa_channel_map* pa_channel_map_init_auto(pa_channel_map *m, unsigned channels, p
                     return NULL;
             }
 
                     return NULL;
             }
 
-
         default:
             pa_assert_not_reached();
     }
         default:
             pa_assert_not_reached();
     }
@@ -398,8 +400,7 @@ pa_channel_map* pa_channel_map_init_extend(pa_channel_map *m, unsigned channels,
     unsigned c;
 
     pa_assert(m);
     unsigned c;
 
     pa_assert(m);
-    pa_assert(channels > 0);
-    pa_assert(channels <= PA_CHANNELS_MAX);
+    pa_assert(pa_channels_valid(channels));
     pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
 
     pa_channel_map_init(m);
     pa_assert(def < PA_CHANNEL_MAP_DEF_MAX);
 
     pa_channel_map_init(m);
@@ -434,11 +435,11 @@ const char* pa_channel_position_to_string(pa_channel_position_t pos) {
 
 const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos) {
 
 
 const char* pa_channel_position_to_pretty_string(pa_channel_position_t pos) {
 
-    pa_init_i18n();
-
     if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
         return NULL;
 
     if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
         return NULL;
 
+    pa_init_i18n();
+
     return _(pretty_table[pos]);
 }
 
     return _(pretty_table[pos]);
 }
 
@@ -448,6 +449,13 @@ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
     pa_assert(a);
     pa_assert(b);
 
     pa_assert(a);
     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 0;
 
     if (a->channels != b->channels)
         return 0;
 
@@ -460,7 +468,7 @@ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
 
 char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
     unsigned channel;
 
 char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
     unsigned channel;
-    pa_bool_t first = TRUE;
+    bool first = true;
     char *e;
 
     pa_assert(s);
     char *e;
 
     pa_assert(s);
@@ -482,12 +490,33 @@ char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) {
                       pa_channel_position_to_string(map->map[channel]));
 
         e = strchr(e, 0);
                       pa_channel_position_to_string(map->map[channel]));
 
         e = strchr(e, 0);
-        first = FALSE;
+        first = false;
     }
 
     return s;
 }
 
     }
 
     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;
 pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
     const char *state;
     pa_channel_map map;
@@ -502,19 +531,19 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
      * "mono" here explicitly, because that can be understood as
      * listing with one channel called "mono". */
 
      * "mono" here explicitly, because that can be understood as
      * listing with one channel called "mono". */
 
-    if (strcmp(s, "stereo") == 0) {
+    if (pa_streq(s, "stereo")) {
         map.channels = 2;
         map.map[0] = PA_CHANNEL_POSITION_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_RIGHT;
         goto finish;
         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) {
+    } else if (pa_streq(s, "surround-40")) {
         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;
         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) {
+    } else if (pa_streq(s, "surround-41")) {
         map.channels = 5;
         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
         map.channels = 5;
         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
@@ -522,7 +551,7 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
         map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
         map.map[4] = PA_CHANNEL_POSITION_LFE;
         goto finish;
         map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
         map.map[4] = PA_CHANNEL_POSITION_LFE;
         goto finish;
-    } else if (strcmp(s, "surround-50") == 0) {
+    } else if (pa_streq(s, "surround-50")) {
         map.channels = 5;
         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
         map.channels = 5;
         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
@@ -530,7 +559,7 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
         map.map[3] = PA_CHANNEL_POSITION_REAR_RIGHT;
         map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
         goto finish;
         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) {
+    } else if (pa_streq(s, "surround-51")) {
         map.channels = 6;
         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
         map.channels = 6;
         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
@@ -539,7 +568,7 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
         map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
         map.map[5] = PA_CHANNEL_POSITION_LFE;
         goto finish;
         map.map[4] = PA_CHANNEL_POSITION_FRONT_CENTER;
         map.map[5] = PA_CHANNEL_POSITION_LFE;
         goto finish;
-    } else if (strcmp(s, "surround-71") == 0) {
+    } else if (pa_streq(s, "surround-71")) {
         map.channels = 8;
         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
         map.channels = 8;
         map.map[0] = PA_CHANNEL_POSITION_FRONT_LEFT;
         map.map[1] = PA_CHANNEL_POSITION_FRONT_RIGHT;
@@ -556,36 +585,19 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
     map.channels = 0;
 
     while ((p = pa_split(s, ",", &state))) {
     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;
         }
 
 
         if (map.channels >= PA_CHANNELS_MAX) {
             pa_xfree(p);
             return NULL;
         }
 
-        /* Some special aliases */
-        if (strcmp(p, "left") == 0)
-            map.map[map.channels++] = PA_CHANNEL_POSITION_LEFT;
-        else if (strcmp(p, "right") == 0)
-            map.map[map.channels++] = PA_CHANNEL_POSITION_RIGHT;
-        else if (strcmp(p, "center") == 0)
-            map.map[map.channels++] = PA_CHANNEL_POSITION_CENTER;
-        else if (strcmp(p, "subwoofer") == 0)
-            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);
     }
 
         pa_xfree(p);
     }
 
@@ -603,7 +615,7 @@ int pa_channel_map_valid(const pa_channel_map *map) {
 
     pa_assert(map);
 
 
     pa_assert(map);
 
-    if (map->channels <= 0 || map->channels > PA_CHANNELS_MAX)
+    if (!pa_channels_valid(map->channels))
         return 0;
 
     for (c = 0; c < map->channels; c++)
         return 0;
 
     for (c = 0; c < map->channels; c++)
@@ -617,61 +629,55 @@ int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *s
     pa_assert(map);
     pa_assert(ss);
 
     pa_assert(map);
     pa_assert(ss);
 
-    if (!pa_channel_map_valid(map))
-        return 0;
-
-    if (!pa_sample_spec_valid(ss))
-        return 0;
+    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
+    pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
 
     return map->channels == ss->channels;
 }
 
 int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
 
     return map->channels == ss->channels;
 }
 
 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_assert(a);
     pa_assert(b);
 
-    memset(in_a, 0, sizeof(in_a));
+    pa_return_val_if_fail(pa_channel_map_valid(a), 0);
 
 
-    for (i = 0; i < a->channels; i++)
-        pa_bitset_set(in_a, a->map[i], TRUE);
+    if (PA_UNLIKELY(a == b))
+        return 1;
 
 
-    for (i = 0; i < b->channels; i++)
-        if (!pa_bitset_get(in_a, b->map[i]))
-            return 0;
+    pa_return_val_if_fail(pa_channel_map_valid(b), 0);
 
 
-    return 1;
+    am = pa_channel_map_mask(a);
+    bm = pa_channel_map_mask(b);
+
+    return (bm & am) == bm;
 }
 
 int pa_channel_map_can_balance(const pa_channel_map *map) {
 }
 
 int pa_channel_map_can_balance(const pa_channel_map *map) {
-    unsigned c;
+    pa_channel_position_mask_t m;
 
     pa_assert(map);
 
     pa_assert(map);
+    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
 
 
-    for (c = 0; c < map->channels; c++)
+    m = pa_channel_map_mask(map);
 
 
-        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
+        (PA_CHANNEL_POSITION_MASK_LEFT & m) &&
+        (PA_CHANNEL_POSITION_MASK_RIGHT & m);
+}
 
 
-    return 0;
+int pa_channel_map_can_fade(const pa_channel_map *map) {
+    pa_channel_position_mask_t m;
+
+    pa_assert(map);
+    pa_return_val_if_fail(pa_channel_map_valid(map), 0);
+
+    m = pa_channel_map_mask(map);
+
+    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) {
 }
 
 const char* pa_channel_map_to_name(const pa_channel_map *map) {
@@ -680,10 +686,12 @@ const char* pa_channel_map_to_name(const pa_channel_map *map) {
 
     pa_assert(map);
 
 
     pa_assert(map);
 
+    pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
+
     memset(in_map, 0, sizeof(in_map));
 
     for (c = 0; c < map->channels; c++)
     memset(in_map, 0, sizeof(in_map));
 
     for (c = 0; c < map->channels; c++)
-        pa_bitset_set(in_map, map->map[c], TRUE);
+        pa_bitset_set(in_map, map->map[c], true);
 
     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
                          PA_CHANNEL_POSITION_MONO, -1))
 
     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
                          PA_CHANNEL_POSITION_MONO, -1))
@@ -732,10 +740,14 @@ const char* pa_channel_map_to_pretty_name(const pa_channel_map *map) {
 
     pa_assert(map);
 
 
     pa_assert(map);
 
+    pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
+
     memset(in_map, 0, sizeof(in_map));
 
     for (c = 0; c < map->channels; c++)
     memset(in_map, 0, sizeof(in_map));
 
     for (c = 0; c < map->channels; c++)
-        pa_bitset_set(in_map, map->map[c], TRUE);
+        pa_bitset_set(in_map, map->map[c], true);
+
+    pa_init_i18n();
 
     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
                          PA_CHANNEL_POSITION_MONO, -1))
 
     if (pa_bitset_equals(in_map, PA_CHANNEL_POSITION_MAX,
                          PA_CHANNEL_POSITION_MONO, -1))
@@ -777,3 +789,28 @@ const char* pa_channel_map_to_pretty_name(const pa_channel_map *map) {
 
     return NULL;
 }
 
     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;
+}