[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.13-493-gf6ec971

Lennart Poettering gitmailer-noreply at 0pointer.de
Wed Feb 4 08:21:27 PST 2009


This is an automated email from the git hooks/post-receive script. It was
generated because of a push to the "PulseAudio Sound Server" repository.

The master branch has been updated
      from  921882de548e17bbdd79bd8eb2c2ce7d36412cf4 (commit)

- Log -----------------------------------------------------------------
f6ec971... clarify things a bit
12b7359... add a few additional validity checks
83ddc09... add new calls pa_replace() and pa_unescape()
a625ca7... make gcc shut up
078a8d5... rearrange a few things
d6dd907... simplify code a bit by using pa_sample_size_of_format()
a6fe991... beef up proplist test a bit
9a27b8f... in addition to per-property env vars PULSE_PROP_xxx look for for a stringified PULSE_PROP env var
b445741... fix up parser in pa_proplist_from_string() to handle escapes correctly; make pa_proplist_to_string() escape quotes properly
0fc59e4... add new API pa_ascii_valid(), pa_ascii_filter()
ce76216... add pa_sample_size_of_format()
32e5e64... add a lot of validity checking
b51ed38... add a bit of missing i18n
543115a... add new API pa_cvolume_compatible_with_channel_map()
-----------------------------------------------------------------------

Summary of changes:
 src/map-file                   |    4 +
 src/pulse/channelmap.c         |   49 ++++--
 src/pulse/ext-stream-restore.c |   48 +++++-
 src/pulse/ext-stream-restore.h |    8 +-
 src/pulse/operation.c          |    1 +
 src/pulse/proplist.c           |  384 ++++++++++++++++++++++++++++++++--------
 src/pulse/proplist.h           |    2 +-
 src/pulse/sample.c             |   38 +++-
 src/pulse/sample.h             |    4 +
 src/pulse/utf8.c               |   26 +++
 src/pulse/utf8.h               |    6 +
 src/pulse/volume.c             |   62 ++++++--
 src/pulse/volume.h             |    8 +-
 src/pulsecore/core-util.c      |   47 +++++
 src/pulsecore/core-util.h      |    4 +
 src/pulsecore/envelope.c       |    7 +
 src/pulsecore/modargs.c        |  179 ++++++++++---------
 src/pulsecore/proplist-util.c  |   10 +
 src/pulsecore/resampler.c      |   12 +--
 src/tests/proplist-test.c      |   19 ++-
 20 files changed, 692 insertions(+), 226 deletions(-)

-----------------------------------------------------------------------

commit 543115ae1726e853624a6214ad58187f6d84c95a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Feb 3 21:15:32 2009 +0100

    add new API pa_cvolume_compatible_with_channel_map()

diff --git a/src/map-file b/src/map-file
index 3aa1d7a..d7addfe 100644
--- a/src/map-file
+++ b/src/map-file
@@ -109,6 +109,7 @@ pa_context_unref;
 pa_cvolume_avg;
 pa_cvolume_channels_equal_to;
 pa_cvolume_compatible;
+pa_cvolume_compatible_with_channel_map;
 pa_cvolume_equal;
 pa_cvolume_get_balance;
 pa_cvolume_get_fade;
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index 01a28e8..e920288 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -428,6 +428,19 @@ int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) {
     return v->channels == ss->channels;
 }
 
+int pa_cvolume_compatible_with_channel_map(const pa_cvolume *v, const pa_channel_map *cm) {
+    pa_assert(v);
+    pa_assert(cm);
+
+    if (!pa_cvolume_valid(v))
+        return 0;
+
+    if (!pa_channel_map_valid(cm))
+        return 0;
+
+    return v->channels == cm->channels;
+}
+
 static void get_avg_lr(const pa_channel_map *map, const pa_cvolume *v, pa_volume_t *l, pa_volume_t *r) {
     int c;
     pa_volume_t left = 0, right = 0;
diff --git a/src/pulse/volume.h b/src/pulse/volume.h
index 9ad3e9b..8bfd068 100644
--- a/src/pulse/volume.h
+++ b/src/pulse/volume.h
@@ -230,10 +230,14 @@ double pa_sw_volume_to_linear(pa_volume_t v) PA_GCC_CONST;
 /** Remap a volume from one channel mapping to a different channel mapping. \since 0.9.12 */
 pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa_channel_map *to);
 
-/** Return non-zero if the specified volume is compatible with
- * the specified sample spec. \since 0.9.13 */
+/** Return non-zero if the specified volume is compatible with the
+ * specified sample spec. \since 0.9.13 */
 int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) PA_GCC_PURE;
 
+/** Return non-zero if the specified volume is compatible with the
+ * specified sample spec. \since 0.9.15 */
+int pa_cvolume_compatible_with_channel_map(const pa_cvolume *v, const pa_channel_map *cm) PA_GCC_PURE;
+
 /** Calculate a 'balance' value for the specified volume with the
  * specified channel map. The return value will range from -1.0f
  * (left) to +1.0f (right). If no balance value is applicable to this

commit b51ed381162b43e55c665dbdb61e2ce4a796a4df
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Feb 3 21:56:52 2009 +0100

    add a bit of missing i18n

diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index 6ff30c2..43e5f83 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -434,11 +434,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) {
 
-    pa_init_i18n();
-
     if (pos < 0 || pos >= PA_CHANNEL_POSITION_MAX)
         return NULL;
 
+    pa_init_i18n();
+
     return _(pretty_table[pos]);
 }
 
@@ -502,19 +502,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". */
 
-    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;
-    } 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;
-    } 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;
@@ -522,7 +522,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;
-    } 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;
@@ -530,7 +530,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;
-    } 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;
@@ -539,7 +539,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;
-    } 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;
@@ -563,13 +563,13 @@ pa_channel_map *pa_channel_map_parse(pa_channel_map *rmap, const char *s) {
         }
 
         /* Some special aliases */
-        if (strcmp(p, "left") == 0)
+        if (pa_streq(p, "left"))
             map.map[map.channels++] = PA_CHANNEL_POSITION_LEFT;
-        else if (strcmp(p, "right") == 0)
+        else if (pa_streq(p, "right"))
             map.map[map.channels++] = PA_CHANNEL_POSITION_RIGHT;
-        else if (strcmp(p, "center") == 0)
+        else if (pa_streq(p, "center"))
             map.map[map.channels++] = PA_CHANNEL_POSITION_CENTER;
-        else if (strcmp(p, "subwoofer") == 0)
+        else if (pa_streq(p, "subwoofer"))
             map.map[map.channels++] = PA_CHANNEL_POSITION_SUBWOOFER;
         else {
             pa_channel_position_t i;
@@ -784,6 +784,8 @@ const char* pa_channel_map_to_pretty_name(const pa_channel_map *map) {
     for (c = 0; c < map->channels; c++)
         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))
         return _("Mono");
diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index a6c7734..5528a59 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -151,22 +151,25 @@ char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
     if (!pa_sample_spec_valid(spec))
         pa_snprintf(s, l, _("(invalid)"));
     else
-        pa_snprintf(s, l, "%s %uch %uHz", pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
+        pa_snprintf(s, l, _("%s %uch %uHz"), pa_sample_format_to_string(spec->format), spec->channels, spec->rate);
 
     return s;
 }
 
 char* pa_bytes_snprint(char *s, size_t l, unsigned v) {
     pa_assert(s);
+    pa_assert(l > 0);
+
+    pa_init_i18n();
 
     if (v >= ((unsigned) 1024)*1024*1024)
-        pa_snprintf(s, l, "%0.1f GiB", ((double) v)/1024/1024/1024);
+        pa_snprintf(s, l, _("%0.1f GiB"), ((double) v)/1024/1024/1024);
     else if (v >= ((unsigned) 1024)*1024)
-        pa_snprintf(s, l, "%0.1f MiB", ((double) v)/1024/1024);
+        pa_snprintf(s, l, _("%0.1f MiB"), ((double) v)/1024/1024);
     else if (v >= (unsigned) 1024)
-        pa_snprintf(s, l, "%0.1f KiB", ((double) v)/1024);
+        pa_snprintf(s, l, _("%0.1f KiB"), ((double) v)/1024);
     else
-        pa_snprintf(s, l, "%u B", (unsigned) v);
+        pa_snprintf(s, l, _("%u B"), (unsigned) v);
 
     return s;
 }

commit 32e5e64921febb219c0b7ed8ca7da141b4ad0f23
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Feb 3 21:57:58 2009 +0100

    add a lot of validity checking

diff --git a/src/pulse/channelmap.c b/src/pulse/channelmap.c
index 43e5f83..983b897 100644
--- a/src/pulse/channelmap.c
+++ b/src/pulse/channelmap.c
@@ -448,6 +448,9 @@ int pa_channel_map_equal(const pa_channel_map *a, const pa_channel_map *b) {
     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);
+
     if (a->channels != b->channels)
         return 0;
 
@@ -617,11 +620,8 @@ int pa_channel_map_compatible(const pa_channel_map *map, const pa_sample_spec *s
     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;
 }
@@ -633,6 +633,9 @@ int pa_channel_map_superset(const pa_channel_map *a, const pa_channel_map *b) {
     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));
 
     for (i = 0; i < a->channels; i++)
@@ -651,6 +654,8 @@ int pa_channel_map_can_balance(const pa_channel_map *map) {
 
     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]) {
@@ -687,6 +692,10 @@ int pa_channel_map_can_fade(const pa_channel_map *map) {
     unsigned c;
     pa_bool_t front = FALSE, rear = FALSE;
 
+    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]) {
@@ -727,6 +736,8 @@ const char* pa_channel_map_to_name(const pa_channel_map *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++)
@@ -779,6 +790,8 @@ const char* pa_channel_map_to_pretty_name(const pa_channel_map *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++)
diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index 5528a59..ff86d0b 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -55,31 +55,35 @@ size_t pa_sample_size(const pa_sample_spec *spec) {
     };
 
     pa_assert(spec);
-    pa_assert(spec->format >= 0);
-    pa_assert(spec->format < PA_SAMPLE_MAX);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
 
     return table[spec->format];
 }
 
 size_t pa_frame_size(const pa_sample_spec *spec) {
     pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
 
     return pa_sample_size(spec) * spec->channels;
 }
 
 size_t pa_bytes_per_second(const pa_sample_spec *spec) {
     pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
+
     return spec->rate*pa_frame_size(spec);
 }
 
 pa_usec_t pa_bytes_to_usec(uint64_t length, const pa_sample_spec *spec) {
     pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
 
     return (((pa_usec_t) (length / pa_frame_size(spec)) * PA_USEC_PER_SEC) / spec->rate);
 }
 
 size_t pa_usec_to_bytes(pa_usec_t t, const pa_sample_spec *spec) {
     pa_assert(spec);
+    pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
 
     return (size_t) (((t * spec->rate) / PA_USEC_PER_SEC)) * pa_frame_size(spec);
 }
@@ -112,6 +116,9 @@ int pa_sample_spec_equal(const pa_sample_spec*a, const pa_sample_spec*b) {
     pa_assert(a);
     pa_assert(b);
 
+    pa_return_val_if_fail(pa_sample_spec_valid(a), 0);
+    pa_return_val_if_fail(pa_sample_spec_valid(b), 0);
+
     return
         (a->format == b->format) &&
         (a->rate == b->rate) &&
@@ -143,7 +150,7 @@ const char *pa_sample_format_to_string(pa_sample_format_t f) {
 
 char *pa_sample_spec_snprint(char *s, size_t l, const pa_sample_spec *spec) {
     pa_assert(s);
-    pa_assert(l);
+    pa_assert(l > 0);
     pa_assert(spec);
 
     pa_init_i18n();
diff --git a/src/pulse/volume.c b/src/pulse/volume.c
index e920288..54838e8 100644
--- a/src/pulse/volume.c
+++ b/src/pulse/volume.c
@@ -37,6 +37,9 @@ int pa_cvolume_equal(const pa_cvolume *a, const pa_cvolume *b) {
     pa_assert(a);
     pa_assert(b);
 
+    pa_return_val_if_fail(pa_cvolume_valid(a), 0);
+    pa_return_val_if_fail(pa_cvolume_valid(b), 0);
+
     if (a->channels != b->channels)
         return 0;
 
@@ -78,7 +81,9 @@ pa_cvolume* pa_cvolume_set(pa_cvolume *a, unsigned channels, pa_volume_t v) {
 pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
     uint64_t sum = 0;
     int i;
+
     pa_assert(a);
+    pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
 
     for (i = 0; i < a->channels; i++)
         sum += a->values[i];
@@ -91,7 +96,9 @@ pa_volume_t pa_cvolume_avg(const pa_cvolume *a) {
 pa_volume_t pa_cvolume_max(const pa_cvolume *a) {
     pa_volume_t m = 0;
     int i;
+
     pa_assert(a);
+    pa_return_val_if_fail(pa_cvolume_valid(a), PA_VOLUME_MUTED);
 
     for (i = 0; i < a->channels; i++)
         if (a->values[i] > m)
@@ -247,11 +254,12 @@ char *pa_sw_volume_snprint_dB(char *s, size_t l, pa_volume_t v) {
     return s;
 }
 
-/** Return non-zero if the volume of all channels is equal to the specified value */
 int pa_cvolume_channels_equal_to(const pa_cvolume *a, pa_volume_t v) {
     unsigned c;
     pa_assert(a);
 
+    pa_return_val_if_fail(pa_cvolume_valid(a), 0);
+
     for (c = 0; c < a->channels; c++)
         if (a->values[c] != v)
             return 0;
@@ -266,6 +274,9 @@ pa_cvolume *pa_sw_cvolume_multiply(pa_cvolume *dest, const pa_cvolume *a, const
     pa_assert(a);
     pa_assert(b);
 
+    pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+    pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
+
     for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++)
         dest->values[i] = pa_sw_volume_multiply(a->values[i], b->values[i]);
 
@@ -281,6 +292,9 @@ pa_cvolume *pa_sw_cvolume_divide(pa_cvolume *dest, const pa_cvolume *a, const pa
     pa_assert(a);
     pa_assert(b);
 
+    pa_return_val_if_fail(pa_cvolume_valid(a), NULL);
+    pa_return_val_if_fail(pa_cvolume_valid(b), NULL);
+
     for (i = 0; i < a->channels && i < b->channels && i < PA_CHANNELS_MAX; i++)
         dest->values[i] = pa_sw_volume_divide(a->values[i], b->values[i]);
 
@@ -373,7 +387,11 @@ pa_cvolume *pa_cvolume_remap(pa_cvolume *v, const pa_channel_map *from, const pa
     pa_assert(v);
     pa_assert(from);
     pa_assert(to);
-    pa_assert(v->channels == from->channels);
+
+    pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+    pa_return_val_if_fail(pa_channel_map_valid(from), NULL);
+    pa_return_val_if_fail(pa_channel_map_valid(to), NULL);
+    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, from), NULL);
 
     if (pa_channel_map_equal(from, to))
         return v;
@@ -419,11 +437,8 @@ int pa_cvolume_compatible(const pa_cvolume *v, const pa_sample_spec *ss) {
     pa_assert(v);
     pa_assert(ss);
 
-    if (!pa_cvolume_valid(v))
-        return 0;
-
-    if (!pa_sample_spec_valid(ss))
-        return 0;
+    pa_return_val_if_fail(pa_cvolume_valid(v), 0);
+    pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
 
     return v->channels == ss->channels;
 }
@@ -432,11 +447,8 @@ int pa_cvolume_compatible_with_channel_map(const pa_cvolume *v, const pa_channel
     pa_assert(v);
     pa_assert(cm);
 
-    if (!pa_cvolume_valid(v))
-        return 0;
-
-    if (!pa_channel_map_valid(cm))
-        return 0;
+    pa_return_val_if_fail(pa_cvolume_valid(v), 0);
+    pa_return_val_if_fail(pa_channel_map_valid(cm), 0);
 
     return v->channels == cm->channels;
 }
@@ -478,7 +490,10 @@ float pa_cvolume_get_balance(const pa_cvolume *v, const pa_channel_map *map) {
 
     pa_assert(v);
     pa_assert(map);
-    pa_assert(map->channels == v->channels);
+
+    pa_return_val_if_fail(pa_cvolume_valid(v), 0.0f);
+    pa_return_val_if_fail(pa_channel_map_valid(map), 0.0f);
+    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
 
     if (!pa_channel_map_can_balance(map))
         return 0.0f;
@@ -507,12 +522,15 @@ pa_cvolume* pa_cvolume_set_balance(pa_cvolume *v, const pa_channel_map *map, flo
     pa_volume_t left, nleft, right, nright, m;
     unsigned c;
 
-    pa_assert(map->channels == v->channels);
     pa_assert(map);
     pa_assert(v);
     pa_assert(new_balance >= -1.0f);
     pa_assert(new_balance <= 1.0f);
 
+    pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+    pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
+    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
+
     if (!pa_channel_map_can_balance(map))
         return v;
 
@@ -551,6 +569,9 @@ pa_cvolume* pa_cvolume_scale(pa_cvolume *v, pa_volume_t max) {
 
     pa_assert(v);
 
+    pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+    pa_return_val_if_fail(max != (pa_volume_t) -1, NULL);
+
     for (c = 0; c < v->channels; c++)
         if (v->values[c] > t)
             t = v->values[c];
@@ -601,7 +622,10 @@ float pa_cvolume_get_fade(const pa_cvolume *v, const pa_channel_map *map) {
 
     pa_assert(v);
     pa_assert(map);
-    pa_assert(map->channels == v->channels);
+
+    pa_return_val_if_fail(pa_cvolume_valid(v), 0.0f);
+    pa_return_val_if_fail(pa_channel_map_valid(map), 0.0f);
+    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), 0.0f);
 
     if (!pa_channel_map_can_fade(map))
         return 0.0f;
@@ -621,12 +645,15 @@ pa_cvolume* pa_cvolume_set_fade(pa_cvolume *v, const pa_channel_map *map, float
     pa_volume_t front, nfront, rear, nrear, m;
     unsigned c;
 
-    pa_assert(map->channels == v->channels);
     pa_assert(map);
     pa_assert(v);
     pa_assert(new_fade >= -1.0f);
     pa_assert(new_fade <= 1.0f);
 
+    pa_return_val_if_fail(pa_cvolume_valid(v), NULL);
+    pa_return_val_if_fail(pa_channel_map_valid(map), NULL);
+    pa_return_val_if_fail(pa_cvolume_compatible_with_channel_map(v, map), NULL);
+
     if (!pa_channel_map_can_fade(map))
         return v;
 

commit ce76216bce9981c31ebab2ca5a97d6c5c0509edd
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:10:15 2009 +0100

    add pa_sample_size_of_format()

diff --git a/src/map-file b/src/map-file
index d7addfe..cdb9deb 100644
--- a/src/map-file
+++ b/src/map-file
@@ -181,6 +181,7 @@ pa_proplist_unset_many;
 pa_proplist_update;
 pa_sample_format_to_string;
 pa_sample_size;
+pa_sample_size_of_format;
 pa_sample_spec_equal;
 pa_sample_spec_init;
 pa_sample_spec_snprint;
diff --git a/src/pulse/sample.c b/src/pulse/sample.c
index ff86d0b..4b13a33 100644
--- a/src/pulse/sample.c
+++ b/src/pulse/sample.c
@@ -36,7 +36,7 @@
 
 #include "sample.h"
 
-size_t pa_sample_size(const pa_sample_spec *spec) {
+size_t pa_sample_size_of_format(pa_sample_format_t f) {
 
     static const size_t table[] = {
         [PA_SAMPLE_U8] = 1,
@@ -54,10 +54,18 @@ size_t pa_sample_size(const pa_sample_spec *spec) {
         [PA_SAMPLE_S24_32BE] = 4
     };
 
+    pa_assert(f >= 0);
+    pa_assert(f < PA_SAMPLE_MAX);
+
+    return table[f];
+}
+
+size_t pa_sample_size(const pa_sample_spec *spec) {
+
     pa_assert(spec);
     pa_return_val_if_fail(pa_sample_spec_valid(spec), 0);
 
-    return table[spec->format];
+    return pa_sample_size_of_format(spec->format);
 }
 
 size_t pa_frame_size(const pa_sample_spec *spec) {
diff --git a/src/pulse/sample.h b/src/pulse/sample.h
index 45a481f..3c05b54 100644
--- a/src/pulse/sample.h
+++ b/src/pulse/sample.h
@@ -261,6 +261,10 @@ size_t pa_frame_size(const pa_sample_spec *spec) PA_GCC_PURE;
 /** Return the size of a sample with the specific sample type */
 size_t pa_sample_size(const pa_sample_spec *spec) PA_GCC_PURE;
 
+/** Similar to pa_sample_size() but take a sample format instead of a
+ * full sample spec. \since 0.9.15 */
+size_t pa_sample_size_of_format(pa_sample_format_t f) PA_GCC_PURE;
+
 /** Calculate the time the specified bytes take to play with the
  * specified sample type. The return value will always be rounded
  * down for non-integral return values. */

commit 0fc59e4585937b155125ef01b0e8c2ae9e5f6cee
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:11:56 2009 +0100

    add new API pa_ascii_valid(), pa_ascii_filter()

diff --git a/src/map-file b/src/map-file
index cdb9deb..ca4e7a7 100644
--- a/src/map-file
+++ b/src/map-file
@@ -1,5 +1,7 @@
 PULSE_0 {
 global:
+pa_ascii_filter;
+pa_ascii_valid;
 pa_browser_new;
 pa_browser_new_full;
 pa_browser_ref;
diff --git a/src/pulse/utf8.c b/src/pulse/utf8.c
index 7671be4..6b58bde 100644
--- a/src/pulse/utf8.c
+++ b/src/pulse/utf8.c
@@ -263,3 +263,29 @@ char* pa_locale_to_utf8 (const char *str) {
 }
 
 #endif
+
+char *pa_ascii_valid(const char *str) {
+    const char *p;
+    pa_assert(str);
+
+    for (p = str; *p; p++)
+        if ((unsigned char) *p >= 128)
+            return NULL;
+
+    return (char*) str;
+}
+
+char *pa_ascii_filter(const char *str) {
+    char *r, *s, *d;
+    pa_assert(str);
+
+    r = pa_xstrdup(str);
+
+    for (s = r, d = r; *s; s++)
+        if ((unsigned char) *s < 128)
+            *(d++) = *s;
+
+    *d = 0;
+
+    return r;
+}
diff --git a/src/pulse/utf8.h b/src/pulse/utf8.h
index 4d75195..b9f7495 100644
--- a/src/pulse/utf8.h
+++ b/src/pulse/utf8.h
@@ -36,9 +36,15 @@ PA_C_DECL_BEGIN
 /** Test if the specified strings qualifies as valid UTF8. Return the string if so, otherwise NULL */
 char *pa_utf8_valid(const char *str) PA_GCC_PURE;
 
+/** Test if the specified strings qualifies as valid 7-bit ASCII. Return the string if so, otherwise NULL. \since 0.9.15 */
+char *pa_ascii_valid(const char *str) PA_GCC_PURE;
+
 /** Filter all invalid UTF8 characters from the specified string, returning a new fully UTF8 valid string. Don't forget to free the returned string with pa_xfree() */
 char *pa_utf8_filter(const char *str);
 
+/** Filter all invalid ASCII characters from the specified string, returning a new fully ASCII valid string. Don't forget to free the returned string with pa_xfree(). \since 0.9.15 */
+char *pa_ascii_filter(const char *str);
+
 /** Convert a UTF-8 string to the current locale. Free the string using pa_xfree(). */
 char* pa_utf8_to_locale (const char *str);
 

commit b445741ddf61de662eddbbe9fc90817ac0e24c5b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:14:59 2009 +0100

    fix up parser in pa_proplist_from_string() to handle escapes correctly; make pa_proplist_to_string() escape quotes properly

diff --git a/src/pulse/proplist.c b/src/pulse/proplist.c
index 282fe5c..db4c934 100644
--- a/src/pulse/proplist.c
+++ b/src/pulse/proplist.c
@@ -24,6 +24,7 @@
 #endif
 
 #include <string.h>
+#include <ctype.h>
 
 #include <pulse/xmalloc.h>
 #include <pulse/utf8.h>
@@ -46,7 +47,7 @@ struct property {
 
 static pa_bool_t property_name_valid(const char *key) {
 
-    if (!pa_utf8_valid(key))
+    if (!pa_ascii_valid(key))
         return FALSE;
 
     if (strlen(key) <= 0)
@@ -64,8 +65,6 @@ static void property_free(struct property *prop) {
 }
 
 pa_proplist* pa_proplist_new(void) {
-    pa_init_i18n();
-
     return MAKE_PROPLIST(pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func));
 }
 
@@ -83,6 +82,7 @@ int pa_proplist_sets(pa_proplist *p, const char *key, const char *value) {
 
     pa_assert(p);
     pa_assert(key);
+    pa_assert(value);
 
     if (!property_name_valid(key) || !pa_utf8_valid(value))
         return -1;
@@ -104,25 +104,130 @@ int pa_proplist_sets(pa_proplist *p, const char *key, const char *value) {
 }
 
 /** Will accept only valid UTF-8 */
+static int proplist_setn(pa_proplist *p, const char *key, size_t key_length, const char *value, size_t value_length) {
+    struct property *prop;
+    pa_bool_t add = FALSE;
+    char *k, *v;
+
+    pa_assert(p);
+    pa_assert(key);
+    pa_assert(value);
+
+    k = pa_xstrndup(key, key_length);
+    v = pa_xstrndup(value, value_length);
+
+    if (!property_name_valid(k) || !pa_utf8_valid(v)) {
+        pa_xfree(k);
+        pa_xfree(v);
+        return -1;
+    }
+
+    if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), k))) {
+        prop = pa_xnew(struct property, 1);
+        prop->key = k;
+        add = TRUE;
+    } else {
+        pa_xfree(prop->value);
+        pa_xfree(k);
+    }
+
+    prop->value = v;
+    prop->nbytes = strlen(v)+1;
+
+    if (add)
+        pa_hashmap_put(MAKE_HASHMAP(p), prop->key, prop);
+
+    return 0;
+}
+
+static int proplist_sethex(pa_proplist *p, const char *key, size_t key_length, const char *value, size_t value_length) {
+    struct property *prop;
+    pa_bool_t add = FALSE;
+    char *k, *v;
+    uint8_t *d;
+    size_t dn;
+
+    pa_assert(p);
+    pa_assert(key);
+    pa_assert(value);
+
+    k = pa_xstrndup(key, key_length);
+
+    if (!property_name_valid(k)) {
+        pa_xfree(k);
+        return -1;
+    }
+
+    v = pa_xstrndup(value, value_length);
+    d = pa_xmalloc(value_length*2+1);
+
+    if ((dn = pa_parsehex(v, d, value_length*2)) == (size_t) -1) {
+        pa_xfree(k);
+        pa_xfree(v);
+        pa_xfree(d);
+        return -1;
+    }
+
+    pa_xfree(v);
+
+    if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), k))) {
+        prop = pa_xnew(struct property, 1);
+        prop->key = k;
+        add = TRUE;
+    } else {
+        pa_xfree(prop->value);
+        pa_xfree(k);
+    }
+
+    d[dn] = 0;
+    prop->value = d;
+    prop->nbytes = dn;
+
+    if (add)
+        pa_hashmap_put(MAKE_HASHMAP(p), prop->key, prop);
+
+    return 0;
+}
+
+/** Will accept only valid UTF-8 */
 int pa_proplist_setf(pa_proplist *p, const char *key, const char *format, ...) {
+    struct property *prop;
+    pa_bool_t add = FALSE;
     va_list ap;
-    int r;
-    char *t;
+    char *v;
 
     pa_assert(p);
     pa_assert(key);
+    pa_assert(format);
 
     if (!property_name_valid(key) || !pa_utf8_valid(format))
         return -1;
 
     va_start(ap, format);
-    t = pa_vsprintf_malloc(format, ap);
+    v = pa_vsprintf_malloc(format, ap);
     va_end(ap);
 
-    r = pa_proplist_sets(p, key, t);
+    if (!pa_utf8_valid(v))
+        goto fail;
 
-    pa_xfree(t);
-    return r;
+    if (!(prop = pa_hashmap_get(MAKE_HASHMAP(p), key))) {
+        prop = pa_xnew(struct property, 1);
+        prop->key = pa_xstrdup(key);
+        add = TRUE;
+    } else
+        pa_xfree(prop->value);
+
+    prop->value = v;
+    prop->nbytes = strlen(v)+1;
+
+    if (add)
+        pa_hashmap_put(MAKE_HASHMAP(p), prop->key, prop);
+
+    return 0;
+
+fail:
+    pa_xfree(v);
+    return -1;
 }
 
 int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nbytes) {
@@ -131,6 +236,7 @@ int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nb
 
     pa_assert(p);
     pa_assert(key);
+    pa_assert(data);
 
     if (!property_name_valid(key))
         return -1;
@@ -142,7 +248,9 @@ int pa_proplist_set(pa_proplist *p, const char *key, const void *data, size_t nb
     } else
         pa_xfree(prop->value);
 
-    prop->value = pa_xmemdup(data, nbytes);
+    prop->value = pa_xmalloc(nbytes+1);
+    memcpy(prop->value, data, nbytes);
+    ((char*) prop->value)[nbytes] = 0;
     prop->nbytes = nbytes;
 
     if (add)
@@ -183,6 +291,8 @@ int pa_proplist_get(pa_proplist *p, const char *key, const void **data, size_t *
 
     pa_assert(p);
     pa_assert(key);
+    pa_assert(data);
+    pa_assert(nbytes);
 
     if (!property_name_valid(key))
         return -1;
@@ -275,9 +385,32 @@ char *pa_proplist_to_string_sep(pa_proplist *p, const char *sep) {
         if (!pa_strbuf_isempty(buf))
             pa_strbuf_puts(buf, sep);
 
-        if ((v = pa_proplist_gets(p, key)))
-            pa_strbuf_printf(buf, "%s = \"%s\"", key, v);
-        else {
+        if ((v = pa_proplist_gets(p, key))) {
+            const char *t;
+
+            pa_strbuf_printf(buf, "%s = \"", key);
+
+            for (t = v;;) {
+                size_t h;
+
+                h = strcspn(t, "\"");
+
+                if (h > 0)
+                    pa_strbuf_putsn(buf, t, h);
+
+                t += h;
+
+                if (*t == 0)
+                    break;
+
+                pa_assert(*t == '"');
+                pa_strbuf_puts(buf, "\\\"");
+
+                t++;
+            }
+
+            pa_strbuf_puts(buf, "\"");
+        } else {
             const void *value;
             size_t nbytes;
             char *c;
@@ -304,88 +437,189 @@ char *pa_proplist_to_string(pa_proplist *p) {
     return t;
 }
 
-/* Remove all whitepsapce from the beginning and the end of *s. *s may
- * be modified. (from conf-parser.c) */
-#define WHITESPACE " \t\n"
-#define in_string(c,s) (strchr(s,c) != NULL)
-
-static char *strip(char *s) {
-    char *b = s+strspn(s, WHITESPACE);
-    char *e, *l = NULL;
-
-    for (e = b; *e; e++)
-        if (!in_string(*e, WHITESPACE))
-            l = e;
+pa_proplist *pa_proplist_from_string(const char *s) {
+    enum {
+        WHITESPACE,
+        KEY,
+        AFTER_KEY,
+        VALUE_START,
+        VALUE_SIMPLE,
+        VALUE_DOUBLE_QUOTES,
+        VALUE_DOUBLE_QUOTES_ESCAPE,
+        VALUE_TICKS,
+        VALUE_TICKS_ESCAPED,
+        VALUE_HEX
+    } state;
+
+    pa_proplist *pl;
+    const char *p, *key = NULL, *value = NULL;
+    size_t key_len = 0, value_len = 0;
+
+    pa_assert(s);
+
+    pl = pa_proplist_new();
+
+    state = WHITESPACE;
+
+    for (p = s;; p++) {
+        switch (state) {
+
+            case WHITESPACE:
+                if (*p == 0)
+                    goto success;
+                else if (*p == '=')
+                    goto fail;
+                else if (!isspace(*p)) {
+                    key = p;
+                    state = KEY;
+                    key_len = 1;
+                }
+                break;
 
-    if (l)
-        *(l+1) = 0;
+            case KEY:
+                if (*p == 0)
+                    goto fail;
+                else if (*p == '=')
+                    state = VALUE_START;
+                else if (isspace(*p))
+                    state = AFTER_KEY;
+                else
+                    key_len++;
+                break;
 
-    return b;
-}
+            case AFTER_KEY:
+                if (*p == 0)
+                    goto fail;
+                else if (*p == '=')
+                    state = VALUE_START;
+                else if (!isspace(*p))
+                    goto fail;
+                break;
 
-pa_proplist *pa_proplist_from_string(const char *str) {
-    pa_proplist *p;
-    char *s, *v, *k, *e;
+            case VALUE_START:
+                if (*p == 0)
+                    goto fail;
+                else if (strncmp(p, "hex:", 4) == 0) {
+                    state = VALUE_HEX;
+                    value = p+4;
+                    value_len = 0;
+                    p += 3;
+                } else if (*p == '\'') {
+                    state = VALUE_TICKS;
+                    value = p+1;
+                    value_len = 0;
+                } else if (*p == '"') {
+                    state = VALUE_DOUBLE_QUOTES;
+                    value = p+1;
+                    value_len = 0;
+                } else if (!isspace(*p)) {
+                    state = VALUE_SIMPLE;
+                    value = p;
+                    value_len = 1;
+                }
+                break;
 
-    pa_assert(str);
-    pa_assert_se(p = pa_proplist_new());
-    pa_assert_se(s = strdup(str));
+            case VALUE_SIMPLE:
+                if (*p == 0 || isspace(*p)) {
+                    if (proplist_setn(pl, key, key_len, value, value_len) < 0)
+                        goto fail;
 
-    for (k = s; *k; k = e) {
-        k = k+strspn(k, WHITESPACE);
+                    if (*p == 0)
+                        goto success;
 
-        if (!*k)
-            break;
+                    state = WHITESPACE;
+                } else
+                    value_len++;
+                break;
 
-        if (!(v = strchr(k, '='))) {
-            pa_log("Missing '='.");
-            break;
-        }
+            case VALUE_DOUBLE_QUOTES:
+                if (*p == 0)
+                    goto fail;
+                else if (*p == '"') {
+                    char *v;
+
+                    v = pa_unescape(pa_xstrndup(value, value_len));
+
+                    if (proplist_setn(pl, key, key_len, v, strlen(v)) < 0) {
+                        pa_xfree(v);
+                        goto fail;
+                    }
+
+                    pa_xfree(v);
+                    state = WHITESPACE;
+                } else if (*p == '\\') {
+                    state = VALUE_DOUBLE_QUOTES_ESCAPE;
+                    value_len++;
+                } else
+                    value_len++;
+                break;
 
-        *v++ = '\0';
-        k = strip(k);
+            case VALUE_DOUBLE_QUOTES_ESCAPE:
+                if (*p == 0)
+                    goto fail;
+                else {
+                    state = VALUE_DOUBLE_QUOTES;
+                    value_len++;
+                }
+                break;
 
-        v = v+strspn(v, WHITESPACE);
-        if (*v == '"') {
-            v++;
-            if (!(e = strchr(v, '"'))) { /* FIXME: handle escape */
-                pa_log("Missing '\"' at end of string value.");
+            case VALUE_TICKS:
+                if (*p == 0)
+                    goto fail;
+                else if (*p == '\'') {
+                    char *v;
+
+                    v = pa_unescape(pa_xstrndup(value, value_len));
+
+                    if (proplist_setn(pl, key, key_len, v, strlen(v)) < 0) {
+                        pa_xfree(v);
+                        goto fail;
+                    }
+
+                    pa_xfree(v);
+                    state = WHITESPACE;
+                } else if (*p == '\\') {
+                    state = VALUE_TICKS_ESCAPED;
+                    value_len++;
+                } else
+                    value_len++;
                 break;
-            }
-            *e++ = '\0';
-            pa_proplist_sets(p, k, v);
-        } else {
-            uint8_t *blob;
 
-            if (*v++ != 'h' || *v++ != 'e' || *v++ != 'x' || *v++ != ':') {
-                pa_log("Value must be a string or \"hex:\"");
+            case VALUE_TICKS_ESCAPED:
+                if (*p == 0)
+                    goto fail;
+                else {
+                    state = VALUE_TICKS;
+                    value_len++;
+                }
                 break;
-            }
 
-            e = v;
-            while (in_string(*e, "0123456789abcdefABCDEF"))
-                ++e;
+            case VALUE_HEX:
+                if ((*p >= '0' && *p <= '9') ||
+                    (*p >= 'A' && *p <= 'F') ||
+                    (*p >= 'a' && *p <= 'f')) {
+                    value_len++;
+                } else if (*p == 0 || isspace(*p)) {
 
-            if ((e - v) % 2) {
-                pa_log("Invalid \"hex:\" value data");
-                break;
-            }
+                    if (proplist_sethex(pl, key, key_len, value, value_len) < 0)
+                        goto fail;
 
-            blob = pa_xmalloc((size_t)(e-v)/2);
-            if (pa_parsehex(v, blob, (e-v)/2) != (size_t)((e-v)/2)) {
-                pa_log("Invalid \"hex:\" value data");
-                pa_xfree(blob);
-                break;
-            }
+                    if (*p == 0)
+                        goto success;
 
-            pa_proplist_set(p, k, blob, (e-v)/2);
-            pa_xfree(blob);
+                    state = WHITESPACE;
+                } else
+                    goto fail;
+                break;
         }
     }
 
-    pa_xfree(s);
+success:
+    return MAKE_PROPLIST(pl);
 
-    return p;
+fail:
+    pa_proplist_free(pl);
+    return NULL;
 }
 
 int pa_proplist_contains(pa_proplist *p, const char *key) {
diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index 990ffd1..d611406 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -136,7 +136,7 @@ PA_C_DECL_BEGIN
 #define PA_PROP_MODULE_USAGE                   "module.usage"
 #define PA_PROP_MODULE_VERSION                 "module.version"
 
-/** A property list object. Basically a dictionary with UTF-8 strings
+/** A property list object. Basically a dictionary with ASCII strings
  * as keys and arbitrary data as values. \since 0.9.11 */
 typedef struct pa_proplist pa_proplist;
 

commit 9a27b8f0e8a6cd1863c95770777aa2536ec5fbb2
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:16:13 2009 +0100

    in addition to per-property env vars PULSE_PROP_xxx look for for a stringified PULSE_PROP env var

diff --git a/src/pulsecore/proplist-util.c b/src/pulsecore/proplist-util.c
index 4920c27..522c7af 100644
--- a/src/pulsecore/proplist-util.c
+++ b/src/pulsecore/proplist-util.c
@@ -41,6 +41,7 @@ void pa_init_proplist(pa_proplist *p) {
     extern char **environ;
 #endif
     char **e;
+    const char *pp;
 
     pa_assert(p);
 
@@ -75,6 +76,15 @@ void pa_init_proplist(pa_proplist *p) {
         }
     }
 
+    if ((pp = getenv("PULSE_PROP"))) {
+        pa_proplist *t;
+
+        if ((t = pa_proplist_from_string(pp))) {
+            pa_proplist_update(p, PA_UPDATE_MERGE, t);
+            pa_proplist_free(t);
+        }
+    }
+
     if (!pa_proplist_contains(p, PA_PROP_APPLICATION_PROCESS_ID)) {
         char t[32];
         pa_snprintf(t, sizeof(t), "%lu", (unsigned long) getpid());

commit a6fe99171669ae03fd5453cc8fa924f21dc9a050
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:16:32 2009 +0100

    beef up proplist test a bit

diff --git a/src/tests/proplist-test.c b/src/tests/proplist-test.c
index f69fa68..5526bb7 100644
--- a/src/tests/proplist-test.c
+++ b/src/tests/proplist-test.c
@@ -29,8 +29,9 @@
 #include <pulsecore/core-util.h>
 
 int main(int argc, char*argv[]) {
-    pa_proplist *a, *b, *c;
-    char *s, *t, *u;
+    pa_proplist *a, *b, *c, *d;
+    char *s, *t, *u, *v;
+    const char *text;
 
     a = pa_proplist_new();
     pa_assert_se(pa_proplist_sets(a, PA_PROP_MEDIA_TITLE, "Brandenburgische Konzerte") == 0);
@@ -63,5 +64,19 @@ int main(int argc, char*argv[]) {
     pa_proplist_free(b);
     pa_proplist_free(c);
 
+    text = "  eins = zwei drei = \"\\\"vier\\\"\" fuenf=sechs sieben ='\\a\\c\\h\\t\\'\\\"' neun= hex:0123456789abCDef ";
+
+    printf("%s\n", text);
+    d = pa_proplist_from_string(text);
+    v = pa_proplist_to_string(d);
+    pa_proplist_free(d);
+    printf("%s\n", v);
+    d = pa_proplist_from_string(v);
+    pa_xfree(v);
+    v = pa_proplist_to_string(d);
+    pa_proplist_free(d);
+    printf("%s\n", v);
+    pa_xfree(v);
+
     return 0;
 }

commit d6dd907cc87e3c6c86ec4d05a2f533bb8fcf677b
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:16:53 2009 +0100

    simplify code a bit by using pa_sample_size_of_format()

diff --git a/src/pulsecore/resampler.c b/src/pulsecore/resampler.c
index be390db..78ad553 100644
--- a/src/pulsecore/resampler.c
+++ b/src/pulsecore/resampler.c
@@ -156,16 +156,6 @@ static int (* const init_table[])(pa_resampler*r) = {
     [PA_RESAMPLER_PEAKS]                   = peaks_init,
 };
 
-static inline size_t sample_size(pa_sample_format_t f) {
-    pa_sample_spec ss = {
-        .format = f,
-        .rate = 0,
-        .channels = 1
-    };
-
-    return pa_sample_size(&ss);
-}
-
 pa_resampler* pa_resampler_new(
         pa_mempool *pool,
         const pa_sample_spec *a,
@@ -275,7 +265,7 @@ pa_resampler* pa_resampler_new(
 
     pa_log_info("Using %s as working format.", pa_sample_format_to_string(r->work_format));
 
-    r->w_sz = sample_size(r->work_format);
+    r->w_sz = pa_sample_size_of_format(r->work_format);
 
     if (r->i_ss.format == r->work_format)
         r->to_work_format_func = NULL;

commit 078a8d583f205f57b99b32fe12d33e04742c07f6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:17:32 2009 +0100

    rearrange a few things

diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c
index 9e60125..866e6e0 100644
--- a/src/pulsecore/modargs.c
+++ b/src/pulsecore/modargs.c
@@ -79,106 +79,111 @@ static int add_key_value(pa_hashmap *map, char *key, char *value, const char* co
 }
 
 pa_modargs *pa_modargs_new(const char *args, const char* const* valid_keys) {
-    pa_hashmap *map = NULL;
+    enum {
+        WHITESPACE,
+        KEY,
+        VALUE_START,
+        VALUE_SIMPLE,
+        VALUE_DOUBLE_QUOTES,
+        VALUE_TICKS
+    } state;
+
+    const char *p, *key = NULL, *value = NULL;
+    size_t key_len = 0, value_len = 0;
+    pa_hashmap *map;
 
     map = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
 
-    if (args) {
-        enum {
-            WHITESPACE,
-            KEY,
-            VALUE_START,
-            VALUE_SIMPLE,
-            VALUE_DOUBLE_QUOTES,
-            VALUE_TICKS
-        } state;
-
-        const char *p, *key, *value;
-        size_t key_len = 0, value_len = 0;
-
-        key = value = NULL;
-        state = WHITESPACE;
-        for (p = args; *p; p++) {
-            switch (state) {
-                case WHITESPACE:
-                    if (*p == '=')
+    if (!args)
+        return (pa_modargs*) map;
+
+    state = WHITESPACE;
+
+    for (p = args; *p; p++) {
+        switch (state) {
+
+            case WHITESPACE:
+                if (*p == '=')
+                    goto fail;
+                else if (!isspace(*p)) {
+                    key = p;
+                    state = KEY;
+                    key_len = 1;
+                }
+                break;
+
+            case KEY:
+                if (*p == '=')
+                    state = VALUE_START;
+                else if (isspace(*p))
+                    goto fail;
+                else
+                    key_len++;
+                break;
+
+            case  VALUE_START:
+                if (*p == '\'') {
+                    state = VALUE_TICKS;
+                    value = p+1;
+                    value_len = 0;
+                } else if (*p == '"') {
+                    state = VALUE_DOUBLE_QUOTES;
+                    value = p+1;
+                    value_len = 0;
+                } else if (isspace(*p)) {
+                    if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(""), valid_keys) < 0)
                         goto fail;
-                    else if (!isspace(*p)) {
-                        key = p;
-                        state = KEY;
-                        key_len = 1;
-                    }
-                    break;
-                case KEY:
-                    if (*p == '=')
-                        state = VALUE_START;
-                    else if (isspace(*p))
+                    state = WHITESPACE;
+                } else {
+                    state = VALUE_SIMPLE;
+                    value = p;
+                    value_len = 1;
+                }
+                break;
+
+            case VALUE_SIMPLE:
+                if (isspace(*p)) {
+                    if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
                         goto fail;
-                    else
-                        key_len++;
-                    break;
-                case  VALUE_START:
-                    if (*p == '\'') {
-                        state = VALUE_TICKS;
-                        value = p+1;
-                        value_len = 0;
-                    } else if (*p == '"') {
-                        state = VALUE_DOUBLE_QUOTES;
-                        value = p+1;
-                        value_len = 0;
-                    } else if (isspace(*p)) {
-                        if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(""), valid_keys) < 0)
-                            goto fail;
-                        state = WHITESPACE;
-                    } else {
-                        state = VALUE_SIMPLE;
-                        value = p;
-                        value_len = 1;
-                    }
-                    break;
-                case VALUE_SIMPLE:
-                    if (isspace(*p)) {
-                        if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
-                            goto fail;
-                        state = WHITESPACE;
-                    } else
-                        value_len++;
-                    break;
-                case VALUE_DOUBLE_QUOTES:
-                    if (*p == '"') {
-                        if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
-                            goto fail;
-                        state = WHITESPACE;
-                    } else
-                        value_len++;
-                    break;
-                case VALUE_TICKS:
-                    if (*p == '\'') {
-                        if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
-                            goto fail;
-                        state = WHITESPACE;
-                    } else
-                        value_len++;
-                    break;
-            }
+                    state = WHITESPACE;
+                } else
+                    value_len++;
+                break;
+
+            case VALUE_DOUBLE_QUOTES:
+                if (*p == '"') {
+                    if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
+                        goto fail;
+                    state = WHITESPACE;
+                } else
+                    value_len++;
+                break;
+
+            case VALUE_TICKS:
+                if (*p == '\'') {
+                    if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrndup(value, value_len), valid_keys) < 0)
+                        goto fail;
+                    state = WHITESPACE;
+                } else
+                    value_len++;
+                break;
         }
+    }
 
-        if (state == VALUE_START) {
-            if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(""), valid_keys) < 0)
-                goto fail;
-        } else if (state == VALUE_SIMPLE) {
-            if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(value), valid_keys) < 0)
-                goto fail;
-        } else if (state != WHITESPACE)
+    if (state == VALUE_START) {
+        if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(""), valid_keys) < 0)
             goto fail;
-    }
+    } else if (state == VALUE_SIMPLE) {
+        if (add_key_value(map, pa_xstrndup(key, key_len), pa_xstrdup(value), valid_keys) < 0)
+            goto fail;
+    } else if (state != WHITESPACE)
+        goto fail;
 
     return (pa_modargs*) map;
 
 fail:
 
-    if (map)
-        pa_modargs_free((pa_modargs*) map);
+    pa_modargs_free((pa_modargs*) map);
 
     return NULL;
 }

commit a625ca7c74d8a21b36527c06524ac281e67308f3
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:17:48 2009 +0100

    make gcc shut up

diff --git a/src/pulsecore/envelope.c b/src/pulsecore/envelope.c
index b57b643..fd6a948 100644
--- a/src/pulsecore/envelope.c
+++ b/src/pulsecore/envelope.c
@@ -744,6 +744,13 @@ void pa_envelope_apply(pa_envelope *e, pa_memchunk *chunk) {
                 break;
             }
 
+            case PA_SAMPLE_S24LE:
+            case PA_SAMPLE_S24BE:
+            case PA_SAMPLE_S24_32LE:
+            case PA_SAMPLE_S24_32BE:
+                /* FIXME */
+                pa_assert_not_reached();
+
             case PA_SAMPLE_MAX:
             case PA_SAMPLE_INVALID:
                 pa_assert_not_reached();

commit 83ddc0936e52120f2af86a552f3adb240a4f0ac4
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:19:15 2009 +0100

    add new calls pa_replace() and pa_unescape()

diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index e65b179..b7ebdeb 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -97,6 +97,7 @@
 #include <pulsecore/log.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/thread.h>
+#include <pulsecore/strbuf.h>
 
 #include "core-util.h"
 
@@ -2553,3 +2554,49 @@ unsigned pa_ncpus(void) {
 
     return ncpus <= 0 ? 1 : (unsigned) ncpus;
 }
+
+char *pa_replace(const char*s, const char*a, const char *b) {
+    pa_strbuf *sb;
+    size_t an;
+
+    pa_assert(s);
+    pa_assert(a);
+    pa_assert(b);
+
+    an = strlen(a);
+    sb = pa_strbuf_new();
+
+    for (;;) {
+        const char *p;
+
+        if (!(p = strstr(s, a)))
+            break;
+
+        pa_strbuf_putsn(sb, s, p-s);
+        pa_strbuf_puts(sb, b);
+        s = p + an;
+    }
+
+    pa_strbuf_puts(sb, s);
+
+    return pa_strbuf_tostring_free(sb);
+}
+
+char *pa_unescape(char *p) {
+    char *s, *d;
+    pa_bool_t escaped = FALSE;
+
+    for (s = p, d = p; *s; s++) {
+        if (!escaped && *s == '\\') {
+            escaped = TRUE;
+            continue;
+        }
+
+        *(d++) = *s;
+        escaped = FALSE;
+    }
+
+    *d = 0;
+
+    return p;
+}
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 18901f4..442815f 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -215,4 +215,8 @@ void pa_reduce(unsigned *num, unsigned *den);
 
 unsigned pa_ncpus(void);
 
+char *pa_replace(const char*s, const char*a, const char *b);
+
+char *pa_unescape(char *p);
+
 #endif

commit 12b735962a3794f1e64c7bf54d67dc7d8c4b8643
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:20:36 2009 +0100

    add a few additional validity checks

diff --git a/src/pulse/ext-stream-restore.c b/src/pulse/ext-stream-restore.c
index 703179c..469c822 100644
--- a/src/pulse/ext-stream-restore.c
+++ b/src/pulse/ext-stream-restore.c
@@ -30,6 +30,7 @@
 #include <pulsecore/pstream-util.h>
 
 #include "internal.h"
+#include "operation.h"
 
 #include "ext-stream-restore.h"
 
@@ -191,8 +192,8 @@ pa_operation *pa_ext_stream_restore_write(
         void *userdata) {
 
     uint32_t tag;
-    pa_operation *o;
-    pa_tagstruct *t;
+    pa_operation *o = NULL;
+    pa_tagstruct *t = NULL;
 
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
@@ -213,7 +214,15 @@ pa_operation *pa_ext_stream_restore_write(
     pa_tagstruct_put_boolean(t, apply_immediately);
 
     for (; n > 0; n--, data++) {
+        if (!data->name || !*data->name)
+            goto fail;
+
         pa_tagstruct_puts(t, data->name);
+
+        if (data->volume.channels > 0 &&
+            !pa_cvolume_compatible_with_channel_map(&data->volume, &data->channel_map))
+            goto fail;
+
         pa_tagstruct_put_channel_map(t, &data->channel_map);
         pa_tagstruct_put_cvolume(t, &data->volume);
         pa_tagstruct_puts(t, data->device);
@@ -224,6 +233,18 @@ pa_operation *pa_ext_stream_restore_write(
     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
     return o;
+
+fail:
+    if (o) {
+        pa_operation_cancel(o);
+        pa_operation_unref(o);
+    }
+
+    if (t)
+        pa_tagstruct_free(t);
+
+    pa_context_set_error(c, PA_ERR_INVALID);
+    return NULL;
 }
 
 pa_operation *pa_ext_stream_restore_delete(
@@ -233,8 +254,8 @@ pa_operation *pa_ext_stream_restore_delete(
         void *userdata) {
 
     uint32_t tag;
-    pa_operation *o;
-    pa_tagstruct *t;
+    pa_operation *o = NULL;
+    pa_tagstruct *t = NULL;
     const char *const *k;
 
     pa_assert(c);
@@ -251,13 +272,29 @@ pa_operation *pa_ext_stream_restore_delete(
     pa_tagstruct_puts(t, "module-stream-restore");
     pa_tagstruct_putu32(t, SUBCOMMAND_DELETE);
 
-    for (k = s; *k; k++)
+    for (k = s; *k; k++) {
+        if (!*k || !**k)
+            goto fail;
+
         pa_tagstruct_puts(t, *k);
+    }
 
     pa_pstream_send_tagstruct(c->pstream, t);
     pa_pdispatch_register_reply(c->pdispatch, tag, DEFAULT_TIMEOUT, pa_context_simple_ack_callback, pa_operation_ref(o), (pa_free_cb_t) pa_operation_unref);
 
     return o;
+
+fail:
+    if (o) {
+        pa_operation_cancel(o);
+        pa_operation_unref(o);
+    }
+
+    if (t)
+        pa_tagstruct_free(t);
+
+    pa_context_set_error(c, PA_ERR_INVALID);
+    return NULL;
 }
 
 pa_operation *pa_ext_stream_restore_subscribe(
@@ -322,5 +359,4 @@ void pa_ext_stream_restore_command(pa_context *c, uint32_t tag, pa_tagstruct *t)
 
     if (c->ext_stream_restore.callback)
         c->ext_stream_restore.callback(c, c->ext_stream_restore.userdata);
-
 }
diff --git a/src/pulse/operation.c b/src/pulse/operation.c
index 13b470a..aa2bbc0 100644
--- a/src/pulse/operation.c
+++ b/src/pulse/operation.c
@@ -62,6 +62,7 @@ pa_operation *pa_operation_ref(pa_operation *o) {
     PA_REFCNT_INC(o);
     return o;
 }
+
 void pa_operation_unref(pa_operation *o) {
     pa_assert(o);
     pa_assert(PA_REFCNT_VALUE(o) >= 1);

commit f6ec971e887e68ba74fb7132dcedddc9b6f2b2db
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Feb 4 17:20:58 2009 +0100

    clarify things a bit

diff --git a/src/pulse/ext-stream-restore.h b/src/pulse/ext-stream-restore.h
index ac01d23..cf9f4cc 100644
--- a/src/pulse/ext-stream-restore.h
+++ b/src/pulse/ext-stream-restore.h
@@ -36,10 +36,10 @@ PA_C_DECL_BEGIN
  * maintained by module-stream-restore. \since 0.9.12 */
 typedef struct pa_ext_stream_restore_info {
     const char *name;            /**< Identifier string of the stream. A string like "sink-input-by-role:" or similar followed by some arbitrary property value. */
-    pa_channel_map channel_map;  /**< The channel map for the volume field */
-    pa_cvolume volume;           /**< The volume of the stream when it was seen last, if applicable */
-    const char *device;          /**< The sink/source of the stream when it was last seen */
-    int mute;                    /**< The boolean mute state of the stream when it was last seen, if applicable */
+    pa_channel_map channel_map;  /**< The channel map for the volume field, if applicable */
+    pa_cvolume volume;           /**< The volume of the stream when it was seen last, if applicable and saved */
+    const char *device;          /**< The sink/source of the stream when it was last seen, if applicable and saved */
+    int mute;                    /**< The boolean mute state of the stream when it was last seen, if applicable and saved */
 } pa_ext_stream_restore_info;
 
 /** Callback prototype for pa_ext_stream_restore_test(). \since 0.9.12 */

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list