[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v1.0-dev-260-g1f602de

Colin Guthrie gitmailer-noreply at 0pointer.de
Tue Apr 19 03:01:24 PDT 2011


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  aaab340d4e3c57d58755151310f59a0ee96554b1 (commit)

- Log -----------------------------------------------------------------
1f602de interpol-test: remove unused include getopt.h
67ba373 vala: More vala fixes
0b24574 volume: Get more data from volume tests
837e0a9 stream-restore: Check for readability before reading volume
a44092d pa_poll(): Simplify detection of invalid fds in select() emulation mode
a2581e6 sink-input: Check flat volume with pa_sink_flat_volume_enabled().
0e60a80 filter-heuristics: New module that applies some basic heuristics regarding filters.
9a2a045 filter-apply: New module to automatically load filter sinks (and move streams) based on sink-input property hints.
3465892 equalizer: Use sink_master as the module argument rather than just master.
-----------------------------------------------------------------------

Summary of changes:
 src/Makefile.am                        |   16 ++-
 src/modules/module-equalizer-sink.c    |    6 +-
 src/modules/module-filter-apply.c      |  400 ++++++++++++++++++++++++++++++++
 src/modules/module-filter-heuristics.c |  117 ++++++++++
 src/modules/module-stream-restore.c    |    2 +-
 src/pulsecore/poll.c                   |   29 +++-
 src/pulsecore/sink-input.c             |    4 +-
 src/pulsecore/svolume_arm.c            |   50 +++-
 src/pulsecore/svolume_mmx.c            |   46 +++-
 src/pulsecore/svolume_orc.c            |   62 ++++--
 src/pulsecore/svolume_sse.c            |   46 +++-
 src/tests/interpol-test.c              |    1 -
 vala/libpulse.vapi                     |   10 +-
 13 files changed, 717 insertions(+), 72 deletions(-)
 create mode 100644 src/modules/module-filter-apply.c
 create mode 100644 src/modules/module-filter-heuristics.c

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

commit 34658927a3821cfc411703962af08fd3c334c277
Author: Colin Guthrie <colin at mageia.org>
Date:   Thu Apr 14 13:00:58 2011 +0200

    equalizer: Use sink_master as the module argument rather than just master.
    
    This brings more uniformity to arguments to match module-echo-cancel
    (which needs both sink and source masters, hence the disambiguation).
    
    This will allow other modules to load filters in a more uniform way
    in the future without kludges to deal with variation in arguments.

diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
index bb350c3..0bbb23a 100644
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -79,7 +79,7 @@ PA_MODULE_LOAD_ONCE(FALSE);
 PA_MODULE_USAGE(
         _("sink_name=<name of the sink> "
           "sink_properties=<properties for the sink> "
-          "master=<sink to connect to> "
+          "sink_master=<sink to connect to> "
           "format=<sample format> "
           "rate=<sample rate> "
           "channels=<number of channels> "
@@ -133,7 +133,7 @@ struct userdata {
 static const char* const valid_modargs[] = {
     "sink_name",
     "sink_properties",
-    "master",
+    "sink_master",
     "format",
     "rate",
     "channels",
@@ -1088,7 +1088,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "master", NULL), PA_NAMEREG_SINK))) {
+    if (!(master = pa_namereg_get(m->core, pa_modargs_get_value(ma, "sink_master", NULL), PA_NAMEREG_SINK))) {
         pa_log("Master sink not found");
         goto fail;
     }

commit 9a2a045d7c74ecc3c3471252b2cecb64f96e654d
Author: Colin Guthrie <colin at mageia.org>
Date:   Thu Apr 14 13:04:03 2011 +0200

    filter-apply: New module to automatically load filter sinks (and move streams) based on sink-input property hints.
    
    This module does not yet deal with modules that need matched inputs/outputs
    (i.e. echo-cancel) but this will be added in due course.

diff --git a/src/Makefile.am b/src/Makefile.am
index dc2a1cd..b9e24b1 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1052,7 +1052,8 @@ modlibexec_LTLIBRARIES += \
 		module-loopback.la \
 		module-virtual-sink.la \
 		module-virtual-source.la \
-		module-switch-on-connect.la
+		module-switch-on-connect.la \
+		module-filter-apply.la
 
 # See comment at librtp.la above
 if !OS_IS_WIN32
@@ -1340,7 +1341,8 @@ SYMDEF_FILES = \
 		module-loopback-symdef.h \
 		module-virtual-sink-symdef.h \
 		module-virtual-source-symdef.h \
-		module-switch-on-connect-symdef.h
+		module-switch-on-connect-symdef.h \
+		module-filter-apply-symdef.h
 
 EXTRA_DIST += $(SYMDEF_FILES)
 BUILT_SOURCES += $(SYMDEF_FILES) builddirs
@@ -1486,6 +1488,10 @@ module_switch_on_connect_la_SOURCES = modules/module-switch-on-connect.c
 module_switch_on_connect_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_switch_on_connect_la_LIBADD = $(MODULE_LIBADD)
 
+module_filter_apply_la_SOURCES = modules/module-filter-apply.c
+module_filter_apply_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_filter_apply_la_LIBADD = $(MODULE_LIBADD)
+
 module_remap_sink_la_SOURCES = modules/module-remap-sink.c
 module_remap_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_remap_sink_la_LIBADD = $(MODULE_LIBADD)
diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c
new file mode 100644
index 0000000..d4bded5
--- /dev/null
+++ b/src/modules/module-filter-apply.c
@@ -0,0 +1,400 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2011 Colin Guthrie
+
+  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.1 of the License,
+  or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulse/timeval.h>
+#include <pulse/rtclock.h>
+
+#include <pulsecore/macro.h>
+#include <pulsecore/hashmap.h>
+#include <pulsecore/hook-list.h>
+#include <pulsecore/core.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/sink-input.h>
+#include <pulsecore/modargs.h>
+
+#include "module-filter-apply-symdef.h"
+
+#define PA_PROP_FILTER_WANT "filter.want"
+#define PA_PROP_FILTER_SUPPRESS "filter.suppress"
+
+
+PA_MODULE_AUTHOR("Colin Guthrie");
+PA_MODULE_DESCRIPTION("Load filter sinks automatically when needed");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(TRUE);
+
+static const char* const valid_modargs[] = {
+    NULL
+};
+
+#define HOUSEKEEPING_INTERVAL (10 * PA_USEC_PER_SEC)
+
+struct filter {
+    char *name;
+    pa_sink* parent_sink;
+    uint32_t module_index;
+    pa_sink* sink;
+};
+
+struct userdata {
+    pa_core *core;
+    pa_hashmap *filters;
+    pa_hook_slot
+        *sink_input_put_slot,
+        *sink_input_proplist_slot,
+        *sink_input_unlink_slot,
+        *sink_unlink_slot;
+    pa_time_event *housekeeping_time_event;
+};
+
+static unsigned filter_hash(const void *p) {
+    const struct filter *f = p;
+
+    return
+        (unsigned) f->parent_sink->index +
+        pa_idxset_string_hash_func(f->name);
+}
+
+static int filter_compare(const void *a, const void *b) {
+    const struct filter *fa = a, *fb = b;
+    int r;
+
+    if (fa->parent_sink != fb->parent_sink)
+        return 1;
+    if ((r = strcmp(fa->name, fb->name)))
+        return r;
+
+    return 0;
+}
+
+static struct filter *filter_new(const char *name, pa_sink* parent_sink) {
+    struct filter *f;
+
+    f = pa_xnew(struct filter, 1);
+    f->name = pa_xstrdup(name);
+    pa_assert_se(f->parent_sink = parent_sink);
+    f->module_index = PA_INVALID_INDEX;
+    f->sink = NULL;
+    return f;
+}
+
+static void filter_free(struct filter *f) {
+    pa_assert(f);
+
+    pa_xfree(f->name);
+    pa_xfree(f);
+}
+
+static const char* should_filter(pa_sink_input *i) {
+    const char *want;
+
+    /* If the stream doesn't what any filter, then let it be. */
+    if ((want = pa_proplist_gets(i->proplist, PA_PROP_FILTER_WANT)) && !pa_streq(want, "")) {
+        const char* suppress = pa_proplist_gets(i->proplist, PA_PROP_FILTER_SUPPRESS);
+
+        if (!suppress || !pa_streq(suppress, want))
+            return want;
+    }
+
+    return NULL;
+}
+
+static void housekeeping_time_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) {
+    struct userdata *u = userdata;
+    struct filter *filter;
+    void *state;
+
+    pa_assert(a);
+    pa_assert(e);
+    pa_assert(u);
+
+    pa_assert(e == u->housekeeping_time_event);
+    u->core->mainloop->time_free(u->housekeeping_time_event);
+    u->housekeeping_time_event = NULL;
+
+    PA_HASHMAP_FOREACH(filter, u->filters, state) {
+        if (filter->sink && pa_idxset_size(filter->sink->inputs) == 0) {
+            uint32_t idx;
+
+            pa_log_debug("Detected filter %s as no longer used on sink %s. Unloading.", filter->name, filter->sink->name);
+            idx = filter->module_index;
+            pa_hashmap_remove(u->filters, filter);
+            filter_free(filter);
+            pa_module_unload_request_by_index(u->core, idx, TRUE);
+        }
+    }
+
+    pa_log_info("Housekeeping Done.");
+}
+
+static void trigger_housekeeping(struct userdata *u) {
+    pa_assert(u);
+
+    if (u->housekeeping_time_event)
+        return;
+
+    u->housekeeping_time_event = pa_core_rttime_new(u->core, pa_rtclock_now() + HOUSEKEEPING_INTERVAL, housekeeping_time_callback, u);
+}
+
+static void move_input_for_filter(pa_sink_input *i, struct filter* filter, pa_bool_t restore) {
+    pa_sink *sink;
+
+    pa_assert(i);
+    pa_assert(filter);
+
+    pa_assert_se(sink = (restore ? filter->parent_sink : filter->sink));
+
+    if (pa_sink_input_move_to(i, sink, FALSE) < 0)
+        pa_log_info("Failed to move sink input %u \"%s\" to <%s>.", i->index,
+                    pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), sink->name);
+    else
+        pa_log_info("Sucessfully moved sink input %u \"%s\" to <%s>.", i->index,
+                    pa_strnull(pa_proplist_gets(i->proplist, PA_PROP_APPLICATION_NAME)), sink->name);
+}
+
+static pa_hook_result_t process(struct userdata *u, pa_sink_input *i) {
+    const char *want;
+    pa_bool_t done_something = FALSE;
+
+    pa_assert(u);
+    pa_sink_input_assert_ref(i);
+
+    /* If there is no sink yet, we can't do much */
+    if (!i->sink)
+        return PA_HOOK_OK;
+
+    /* If the stream doesn't what any filter, then let it be. */
+    if ((want = should_filter(i))) {
+        char *module_name;
+        struct filter *fltr, *filter;
+
+        /* We need to ensure the SI is playing on a sink of this type
+         * attached to the sink it's "officially" playing on */
+
+        if (!i->sink->module)
+            return PA_HOOK_OK;
+
+        module_name = pa_sprintf_malloc("module-%s", want);
+        if (pa_streq(i->sink->module->name, module_name)) {
+            pa_log_debug("Stream appears to be playing on an appropriate sink already. Ignoring.");
+            pa_xfree(module_name);
+            return PA_HOOK_OK;
+        }
+
+        fltr = filter_new(want, i->sink);
+
+        if (!(filter = pa_hashmap_get(u->filters, fltr))) {
+            char *args;
+            pa_module *m;
+
+            args = pa_sprintf_malloc("sink_master=%s", i->sink->name);
+            pa_log_debug("Loading %s with arguments '%s'", module_name, args);
+
+            if ((m = pa_module_load(u->core, module_name, args))) {
+                uint32_t idx;
+                pa_sink *sink;
+
+                fltr->module_index = m->index;
+                /* We cannot use the SINK_PUT hook here to detect our sink as it'll
+                 * be called during the module load so we wont yet have put the filter
+                 * in our hashmap to compare... so we have to search for it */
+                PA_IDXSET_FOREACH(sink, u->core->sinks, idx) {
+                    if (sink->module == m) {
+                        fltr->sink = sink;
+                        break;
+                    }
+                }
+                pa_hashmap_put(u->filters, fltr, fltr);
+                filter = fltr;
+                fltr = NULL;
+                done_something = TRUE;
+            }
+            pa_xfree(args);
+        }
+        pa_xfree(fltr);
+
+        if (!filter) {
+            pa_log("Unable to load %s for sink <%s>", module_name, i->sink->name);
+            pa_xfree(module_name);
+            return PA_HOOK_OK;
+        }
+        pa_xfree(module_name);
+
+        if (filter->sink) {
+            /* We can move the sink_input now as the know the destination.
+             * If this isn't true, we will do it later when the sink appears. */
+            move_input_for_filter(i, filter, FALSE);
+            done_something = TRUE;
+        }
+    } else {
+        void *state;
+        struct filter *filter = NULL;
+
+        /* We do not want to filter... but are we already filtered?
+         * This can happen if an input's proplist changes */
+        PA_HASHMAP_FOREACH(filter, u->filters, state) {
+            if (i->sink == filter->sink) {
+                move_input_for_filter(i, filter, TRUE);
+                done_something = TRUE;
+                break;
+            }
+        }
+    }
+
+    if (done_something)
+        trigger_housekeeping(u);
+
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_input_put_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
+    pa_core_assert_ref(core);
+    pa_sink_input_assert_ref(i);
+
+    return process(u, i);
+}
+
+static pa_hook_result_t sink_input_proplist_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
+    pa_core_assert_ref(core);
+    pa_sink_input_assert_ref(i);
+
+    return process(u, i);
+}
+
+static pa_hook_result_t sink_input_unlink_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
+    pa_core_assert_ref(core);
+    pa_sink_input_assert_ref(i);
+
+    pa_assert(u);
+
+    if (pa_hashmap_size(u->filters) > 0)
+        trigger_housekeeping(u);
+
+    return PA_HOOK_OK;
+}
+
+static pa_hook_result_t sink_unlink_cb(pa_core *core, pa_sink *sink, struct userdata *u) {
+    void *state;
+    struct filter *filter = NULL;
+
+    pa_core_assert_ref(core);
+    pa_sink_assert_ref(sink);
+    pa_assert(u);
+
+    /* If either the parent or the sink we've loaded disappears,
+     * we should remove it from our hashmap */
+    PA_HASHMAP_FOREACH(filter, u->filters, state) {
+        if (filter->parent_sink == sink || filter->sink == sink) {
+            uint32_t idx;
+
+            /* Attempt to rescue any streams to the parent sink as this is likely
+             * the best course of action (as opposed to a generic rescue via
+             * module-rescue-streams */
+            if (filter->sink == sink) {
+                pa_sink_input *i;
+
+                PA_IDXSET_FOREACH(i, sink->inputs, idx)
+                    move_input_for_filter(i, filter, TRUE);
+            }
+
+            idx = filter->module_index;
+            pa_hashmap_remove(u->filters, filter);
+            filter_free(filter);
+            pa_module_unload_request_by_index(u->core, idx, TRUE);
+        }
+    }
+
+    return PA_HOOK_OK;
+}
+
+
+int pa__init(pa_module *m) {
+    pa_modargs *ma = NULL;
+    struct userdata *u;
+
+    pa_assert(m);
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("Failed to parse module arguments");
+        goto fail;
+    }
+
+    m->userdata = u = pa_xnew0(struct userdata, 1);
+
+    u->core = m->core;
+
+    u->filters = pa_hashmap_new(filter_hash, filter_compare);
+
+    u->sink_input_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_put_cb, u);
+    u->sink_input_proplist_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_proplist_cb, u);
+    u->sink_input_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_input_unlink_cb, u);
+    u->sink_unlink_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_UNLINK], PA_HOOK_LATE, (pa_hook_cb_t) sink_unlink_cb, u);
+
+    pa_modargs_free(ma);
+
+    return 0;
+
+fail:
+    pa__done(m);
+
+    if (ma)
+        pa_modargs_free(ma);
+
+    return -1;
+}
+
+void pa__done(pa_module *m) {
+    struct userdata* u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->sink_input_put_slot)
+        pa_hook_slot_free(u->sink_input_put_slot);
+    if (u->sink_input_proplist_slot)
+        pa_hook_slot_free(u->sink_input_proplist_slot);
+    if (u->sink_input_unlink_slot)
+        pa_hook_slot_free(u->sink_input_unlink_slot);
+    if (u->sink_unlink_slot)
+        pa_hook_slot_free(u->sink_unlink_slot);
+
+    if (u->housekeeping_time_event)
+        u->core->mainloop->time_free(u->housekeeping_time_event);
+
+    if (u->filters) {
+        struct filter *f;
+
+        while ((f = pa_hashmap_steal_first(u->filters))) {
+            pa_module_unload_request_by_index(u->core, f->module_index, TRUE);
+            filter_free(f);
+        }
+
+        pa_hashmap_free(u->filters, NULL, NULL);
+    }
+
+    pa_xfree(u);
+}

commit 0e60a80afae49fbde327388be485f7f5691828b8
Author: Colin Guthrie <colin at mageia.org>
Date:   Thu Apr 14 13:05:45 2011 +0200

    filter-heuristics: New module that applies some basic heuristics regarding filters.
    
    At present the only heuristic is one to apply the echo-cancel filter
    when dealing with phone streams.

diff --git a/src/Makefile.am b/src/Makefile.am
index b9e24b1..cfa2e1f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1053,7 +1053,8 @@ modlibexec_LTLIBRARIES += \
 		module-virtual-sink.la \
 		module-virtual-source.la \
 		module-switch-on-connect.la \
-		module-filter-apply.la
+		module-filter-apply.la \
+		module-filter-heuristics.la
 
 # See comment at librtp.la above
 if !OS_IS_WIN32
@@ -1342,7 +1343,8 @@ SYMDEF_FILES = \
 		module-virtual-sink-symdef.h \
 		module-virtual-source-symdef.h \
 		module-switch-on-connect-symdef.h \
-		module-filter-apply-symdef.h
+		module-filter-apply-symdef.h \
+		module-filter-heuristics-symdef.h
 
 EXTRA_DIST += $(SYMDEF_FILES)
 BUILT_SOURCES += $(SYMDEF_FILES) builddirs
@@ -1492,6 +1494,10 @@ module_filter_apply_la_SOURCES = modules/module-filter-apply.c
 module_filter_apply_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_filter_apply_la_LIBADD = $(MODULE_LIBADD)
 
+module_filter_heuristics_la_SOURCES = modules/module-filter-heuristics.c
+module_filter_heuristics_la_LDFLAGS = $(MODULE_LDFLAGS)
+module_filter_heuristics_la_LIBADD = $(MODULE_LIBADD)
+
 module_remap_sink_la_SOURCES = modules/module-remap-sink.c
 module_remap_sink_la_LDFLAGS = $(MODULE_LDFLAGS)
 module_remap_sink_la_LIBADD = $(MODULE_LIBADD)
diff --git a/src/modules/module-filter-heuristics.c b/src/modules/module-filter-heuristics.c
new file mode 100644
index 0000000..fb01f85
--- /dev/null
+++ b/src/modules/module-filter-heuristics.c
@@ -0,0 +1,117 @@
+/***
+  This file is part of PulseAudio.
+
+  Copyright 2011 Colin Guthrie
+
+  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.1 of the License,
+  or (at your option) any later version.
+
+  PulseAudio is distributed in the hope that it will be useful, but
+  WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+  General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public License
+  along with PulseAudio; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+  USA.
+***/
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <pulsecore/macro.h>
+#include <pulsecore/hashmap.h>
+#include <pulsecore/hook-list.h>
+#include <pulsecore/core.h>
+#include <pulsecore/core-util.h>
+#include <pulsecore/sink-input.h>
+#include <pulsecore/modargs.h>
+
+#include "module-filter-heuristics-symdef.h"
+
+#define PA_PROP_FILTER_WANT "filter.want"
+#define PA_PROP_FILTER_SUPPRESS "filter.suppress"
+
+
+PA_MODULE_AUTHOR("Colin Guthrie");
+PA_MODULE_DESCRIPTION("Detect when various filters are desirable");
+PA_MODULE_VERSION(PACKAGE_VERSION);
+PA_MODULE_LOAD_ONCE(TRUE);
+
+static const char* const valid_modargs[] = {
+    NULL
+};
+
+struct userdata {
+    pa_core *core;
+    pa_hook_slot
+        *sink_input_put_slot;
+};
+
+static pa_hook_result_t sink_input_put_cb(pa_core *core, pa_sink_input *i, struct userdata *u) {
+    const char *role;
+
+    pa_core_assert_ref(core);
+    pa_sink_input_assert_ref(i);
+    pa_assert(u);
+
+    /* If the stream already specifies what it wants, then let it be. */
+    if (pa_proplist_gets(i->proplist, PA_PROP_FILTER_WANT))
+        return PA_HOOK_OK;
+
+    if ((role = pa_proplist_gets(i->proplist, PA_PROP_MEDIA_ROLE)) && pa_streq(role, "phone"))
+        pa_proplist_sets(i->proplist, PA_PROP_FILTER_WANT, "echo-cancel");
+
+    return PA_HOOK_OK;
+}
+
+int pa__init(pa_module *m) {
+    pa_modargs *ma = NULL;
+    struct userdata *u;
+
+    pa_assert(m);
+
+    if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
+        pa_log("Failed to parse module arguments");
+        goto fail;
+    }
+
+    m->userdata = u = pa_xnew(struct userdata, 1);
+
+    u->core = m->core;
+
+    u->sink_input_put_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SINK_INPUT_PUT], PA_HOOK_LATE-1, (pa_hook_cb_t) sink_input_put_cb, u);
+
+    pa_modargs_free(ma);
+
+    return 0;
+
+fail:
+    pa__done(m);
+
+    if (ma)
+        pa_modargs_free(ma);
+
+    return -1;
+
+
+}
+
+void pa__done(pa_module *m) {
+    struct userdata* u;
+
+    pa_assert(m);
+
+    if (!(u = m->userdata))
+        return;
+
+    if (u->sink_input_put_slot)
+        pa_hook_slot_free(u->sink_input_put_slot);
+
+    pa_xfree(u);
+
+}

commit a2581e6688c3fdcde4734f52a6b5fbc489f782b3
Author: Tanu Kaskinen <tanuk at iki.fi>
Date:   Fri Apr 15 18:36:38 2011 +0300

    sink-input: Check flat volume with pa_sink_flat_volume_enabled().
    
    Checking just the flag doesn't work if the sink uses volume sharing, because
    such sinks never have PA_SINK_FLAT_VOLUME set.

diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index 46f26f9..1931d99 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -1020,7 +1020,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo
     pa_assert(volume->channels == 1 || pa_cvolume_compatible(volume, &i->sample_spec));
     pa_assert(i->volume_writable);
 
-    if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) {
+    if (!absolute && pa_sink_flat_volume_enabled(i->sink)) {
         v = i->sink->reference_volume;
         pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
 
@@ -1043,7 +1043,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo
     i->volume = *volume;
     i->save_volume = save;
 
-    if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
+    if (pa_sink_flat_volume_enabled(i->sink)) {
         /* We are in flat volume mode, so let's update all sink input
          * volumes and update the flat volume of the sink */
 

commit a44092d39de9a0abb4f3e3eaede219efe67e3964
Author: Daniel Mack <zonque at gmail.com>
Date:   Wed Apr 13 19:51:49 2011 +0200

    pa_poll(): Simplify detection of invalid fds in select() emulation mode
    
    For systems which have a fcntl() implementation, we can simplify the
    code which determines whether a file selector is valid in pa_poll().
    
    The old code, which is harder to read and more expensive, stays around
    for all platforms we need to emulate poll() for using select(), and
    which don't provide fcntl(). IOW, for Windows.
    
    On Mac OS X, however, the detection for bad fds via more select() calls
    doesn't work, resulting in hung main loops, so the patch fixes a real
    bug there.

diff --git a/src/pulsecore/poll.c b/src/pulsecore/poll.c
index df4feb0..d5abb04 100644
--- a/src/pulsecore/poll.c
+++ b/src/pulsecore/poll.c
@@ -40,6 +40,7 @@
 #endif
 
 #include <errno.h>
+#include <fcntl.h>
 
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
@@ -111,13 +112,18 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
 
     if ((ready == -1) && (errno == EBADF)) {
         ready = 0;
+        maxfd = -1;
+
+#ifdef OS_IS_WIN32
+        /*
+         * Windows has no fcntl(), so we have to trick around with more
+         * select() calls to find out what went wrong
+         */
 
         FD_ZERO (&rset);
         FD_ZERO (&wset);
         FD_ZERO (&xset);
 
-        maxfd = -1;
-
         for (f = fds; f < &fds[nfds]; ++f) {
             if (f->fd != -1) {
                 fd_set sngl_rset, sngl_wset, sngl_xset;
@@ -156,6 +162,25 @@ int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
             }
         }
 
+#else /* !OS_IS_WIN32 */
+
+        for (f = fds; f < &fds[nfds]; f++)
+            if (f->fd != -1) {
+                /* use fcntl() to find out whether the descriptor is valid */
+                if (fcntl(f->fd, F_GETFL) != -1) {
+                    if (f->fd > maxfd && (f->events & (POLLIN|POLLOUT|POLLPRI))) {
+                        maxfd = f->fd;
+                        ready++;
+                    }
+                } else {
+                    FD_CLR(f->fd, &rset);
+                    FD_CLR(f->fd, &wset);
+                    FD_CLR(f->fd, &xset);
+                }
+            }
+
+#endif
+
         if (ready) {
         /* Linux alters the tv struct... but it shouldn't matter here ...
          * as we're going to be a little bit out anyway as we've just eaten

commit 837e0a960630251ce30c124da5e65079b748d978
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Tue Apr 12 13:11:40 2011 +0530

    stream-restore: Check for readability before reading volume
    
    This avoids an assert in pa_sink_input_get_volume() when connecting a
    passthrough stream.

diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index d27982b..4d1ea04 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -1168,7 +1168,7 @@ static void subscribe_callback(pa_core *c, pa_subscription_event_type_t t, uint3
             created_new_entry = FALSE;
         }
 
-        if (sink_input->save_volume) {
+        if (sink_input->save_volume && pa_sink_input_is_volume_readable(sink_input)) {
             pa_assert(sink_input->volume_writable);
 
             entry.channel_map = sink_input->channel_map;

commit 0b2457432a95fc3b0ffdca815d14a7576a6d4b67
Author: Arun Raghavan <arun.raghavan at collabora.co.uk>
Date:   Sun Apr 17 15:28:15 2011 +0530

    volume: Get more data from volume tests
    
    This makes the volume tests run in two loops and print the minimum,
    maximum and standard deviation of readings from the inner loop. This
    makes it easier to reason out performance drops (i.e. algorithmic
    problems vs. other system issues such as processor contention).

diff --git a/src/pulsecore/svolume_arm.c b/src/pulsecore/svolume_arm.c
index 42e8cbf..098f10e 100644
--- a/src/pulsecore/svolume_arm.c
+++ b/src/pulsecore/svolume_arm.c
@@ -130,6 +130,7 @@ static void pa_volume_s16ne_arm(int16_t *samples, int32_t *volumes, unsigned cha
 #define CHANNELS 2
 #define SAMPLES 1022
 #define TIMES 1000
+#define TIMES2 100
 #define PADDING 16
 
 static void run_test(void) {
@@ -140,6 +141,9 @@ static void run_test(void) {
     int i, j, padding;
     pa_do_volume_func_t func;
     pa_usec_t start, stop;
+    int k;
+    pa_usec_t min = INT_MAX, max = 0;
+    double s1 = 0, s2 = 0;
 
     func = pa_get_volume_func(PA_SAMPLE_S16NE);
 
@@ -159,25 +163,45 @@ static void run_test(void) {
     for (i = 0; i < SAMPLES; i++) {
         if (samples[i] != samples_ref[i]) {
             printf ("%d: %04x != %04x (%04x * %04x)\n", i, samples[i], samples_ref[i],
-                  samples_orig[i], volumes[i % CHANNELS]);
+                      samples_orig[i], volumes[i % CHANNELS]);
         }
     }
 
-    start = pa_rtclock_now();
-    for (j = 0; j < TIMES; j++) {
-        memcpy(samples, samples_orig, sizeof(samples));
-        pa_volume_s16ne_arm(samples, volumes, CHANNELS, sizeof(samples));
+    for (k = 0; k < TIMES2; k++) {
+        start = pa_rtclock_now();
+        for (j = 0; j < TIMES; j++) {
+            memcpy(samples, samples_orig, sizeof(samples));
+            pa_volume_s16ne_arm(samples, volumes, CHANNELS, sizeof(samples));
+        }
+        stop = pa_rtclock_now();
+
+        if (min > (stop - start)) min = stop - start;
+        if (max < (stop - start)) max = stop - start;
+        s1 += stop - start;
+        s2 += (stop - start) * (stop - start);
     }
-    stop = pa_rtclock_now();
-    pa_log_info("ARM: %llu usec.", (long long unsigned int) (stop - start));
+    pa_log_info("ARM: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
+            (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
+
+    min = INT_MAX; max = 0;
+    s1 = s2 = 0;
+    for (k = 0; k < TIMES2; k++) {
+        start = pa_rtclock_now();
+        for (j = 0; j < TIMES; j++) {
+            memcpy(samples_ref, samples_orig, sizeof(samples));
+            func(samples_ref, volumes, CHANNELS, sizeof(samples));
+        }
+        stop = pa_rtclock_now();
 
-    start = pa_rtclock_now();
-    for (j = 0; j < TIMES; j++) {
-        memcpy(samples_ref, samples_orig, sizeof(samples));
-        func(samples_ref, volumes, CHANNELS, sizeof(samples));
+        if (min > (stop - start)) min = stop - start;
+        if (max < (stop - start)) max = stop - start;
+        s1 += stop - start;
+        s2 += (stop - start) * (stop - start);
     }
-    stop = pa_rtclock_now();
-    pa_log_info("ref: %llu usec.", (long long unsigned int) (stop - start));
+    pa_log_info("ref: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
+            (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
+
+    pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0);
 }
 #endif
 
diff --git a/src/pulsecore/svolume_mmx.c b/src/pulsecore/svolume_mmx.c
index 421156e..7286b4a 100644
--- a/src/pulsecore/svolume_mmx.c
+++ b/src/pulsecore/svolume_mmx.c
@@ -241,6 +241,7 @@ static void pa_volume_s16re_mmx(int16_t *samples, int32_t *volumes, unsigned cha
 #define CHANNELS 2
 #define SAMPLES 1022
 #define TIMES 1000
+#define TIMES2 100
 #define PADDING 16
 
 static void run_test(void) {
@@ -251,6 +252,9 @@ static void run_test(void) {
     int i, j, padding;
     pa_do_volume_func_t func;
     pa_usec_t start, stop;
+    int k;
+    pa_usec_t min = INT_MAX, max = 0;
+    double s1 = 0, s2 = 0;
 
     func = pa_get_volume_func(PA_SAMPLE_S16NE);
 
@@ -277,21 +281,39 @@ static void run_test(void) {
         }
     }
 
-    start = pa_rtclock_now();
-    for (j = 0; j < TIMES; j++) {
-        memcpy(samples, samples_orig, sizeof(samples));
-        pa_volume_s16ne_mmx(samples, volumes, CHANNELS, sizeof(samples));
+    for (k = 0; k < TIMES2; k++) {
+        start = pa_rtclock_now();
+        for (j = 0; j < TIMES; j++) {
+            memcpy(samples, samples_orig, sizeof(samples));
+            pa_volume_s16ne_mmx(samples, volumes, CHANNELS, sizeof(samples));
+        }
+        stop = pa_rtclock_now();
+
+        if (min > (stop - start)) min = stop - start;
+        if (max < (stop - start)) max = stop - start;
+        s1 += stop - start;
+        s2 += (stop - start) * (stop - start);
     }
-    stop = pa_rtclock_now();
-    pa_log_info("MMX: %llu usec.", (long long unsigned int)(stop - start));
+    pa_log_info("MMX: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
+            (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
+
+    min = INT_MAX; max = 0;
+    s1 = s2 = 0;
+    for (k = 0; k < TIMES2; k++) {
+        start = pa_rtclock_now();
+        for (j = 0; j < TIMES; j++) {
+            memcpy(samples_ref, samples_orig, sizeof(samples));
+            func(samples_ref, volumes, CHANNELS, sizeof(samples));
+        }
+        stop = pa_rtclock_now();
 
-    start = pa_rtclock_now();
-    for (j = 0; j < TIMES; j++) {
-        memcpy(samples_ref, samples_orig, sizeof(samples));
-        func(samples_ref, volumes, CHANNELS, sizeof(samples));
+        if (min > (stop - start)) min = stop - start;
+        if (max < (stop - start)) max = stop - start;
+        s1 += stop - start;
+        s2 += (stop - start) * (stop - start);
     }
-    stop = pa_rtclock_now();
-    pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
+    pa_log_info("ref: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
+            (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
 
     pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0);
 }
diff --git a/src/pulsecore/svolume_orc.c b/src/pulsecore/svolume_orc.c
index db07ba6..270b291 100644
--- a/src/pulsecore/svolume_orc.c
+++ b/src/pulsecore/svolume_orc.c
@@ -52,9 +52,10 @@ pa_volume_s16ne_orc(int16_t *samples, int32_t *volumes, unsigned channels, unsig
 #define CHANNELS 2
 #define SAMPLES 1022
 #define TIMES 1000
+#define TIMES2 100
 #define PADDING 16
 
-static void run_test (void) {
+static void run_test(void) {
     int16_t samples[SAMPLES];
     int16_t samples_ref[SAMPLES];
     int16_t samples_orig[SAMPLES];
@@ -62,22 +63,25 @@ static void run_test (void) {
     int i, j, padding;
     pa_do_volume_func_t func;
     pa_usec_t start, stop;
+    int k;
+    pa_usec_t min = INT_MAX, max = 0;
+    double s1 = 0, s2 = 0;
 
-    func = pa_get_volume_func (PA_SAMPLE_S16NE);
+    func = pa_get_volume_func(PA_SAMPLE_S16NE);
 
-    printf ("checking ORC %zd\n", sizeof (samples));
+    printf("checking ORC %zd\n", sizeof(samples));
 
-    pa_random (samples, sizeof (samples));
-    memcpy (samples_ref, samples, sizeof (samples));
-    memcpy (samples_orig, samples, sizeof (samples));
+    pa_random(samples, sizeof(samples));
+    memcpy(samples_ref, samples, sizeof(samples));
+    memcpy(samples_orig, samples, sizeof(samples));
 
     for (i = 0; i < CHANNELS; i++)
         volumes[i] = PA_CLAMP_VOLUME(rand() >> 1);
     for (padding = 0; padding < PADDING; padding++, i++)
         volumes[i] = volumes[padding];
 
-    func (samples_ref, volumes, CHANNELS, sizeof (samples));
-    pa_volume_s16ne_orc (samples, volumes, CHANNELS, sizeof (samples));
+    func(samples_ref, volumes, CHANNELS, sizeof(samples));
+    pa_volume_s16ne_orc(samples, volumes, CHANNELS, sizeof(samples));
     for (i = 0; i < SAMPLES; i++) {
         if (samples[i] != samples_ref[i]) {
             printf ("%d: %04x != %04x (%04x * %04x)\n", i, samples[i], samples_ref[i],
@@ -85,21 +89,39 @@ static void run_test (void) {
         }
     }
 
-    start = pa_rtclock_now();
-    for (j = 0; j < TIMES; j++) {
-        memcpy (samples, samples_orig, sizeof (samples));
-        pa_volume_s16ne_orc (samples, volumes, CHANNELS, sizeof (samples));
+    for (k = 0; k < TIMES2; k++) {
+        start = pa_rtclock_now();
+        for (j = 0; j < TIMES; j++) {
+            memcpy(samples, samples_orig, sizeof(samples));
+            pa_volume_s16ne_orc(samples, volumes, CHANNELS, sizeof(samples));
+        }
+        stop = pa_rtclock_now();
+
+        if (min > (stop - start)) min = stop - start;
+        if (max < (stop - start)) max = stop - start;
+        s1 += stop - start;
+        s2 += (stop - start) * (stop - start);
     }
-    stop = pa_rtclock_now();
-    pa_log_info("ORC: %llu usec.", (long long unsigned int)(stop - start));
+    pa_log_info("ORC: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
+            (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
+
+    min = INT_MAX; max = 0;
+    s1 = s2 = 0;
+    for (k = 0; k < TIMES2; k++) {
+        start = pa_rtclock_now();
+        for (j = 0; j < TIMES; j++) {
+            memcpy(samples_ref, samples_orig, sizeof(samples));
+            func(samples_ref, volumes, CHANNELS, sizeof(samples));
+        }
+        stop = pa_rtclock_now();
 
-    start = pa_rtclock_now();
-    for (j = 0; j < TIMES; j++) {
-        memcpy (samples_ref, samples_orig, sizeof (samples));
-        func (samples_ref, volumes, CHANNELS, sizeof (samples));
+        if (min > (stop - start)) min = stop - start;
+        if (max < (stop - start)) max = stop - start;
+        s1 += stop - start;
+        s2 += (stop - start) * (stop - start);
     }
-    stop = pa_rtclock_now();
-    pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
+    pa_log_info("ref: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
+            (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
 
     pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0);
 }
diff --git a/src/pulsecore/svolume_sse.c b/src/pulsecore/svolume_sse.c
index ef07a24..8fed69b 100644
--- a/src/pulsecore/svolume_sse.c
+++ b/src/pulsecore/svolume_sse.c
@@ -253,6 +253,7 @@ static void pa_volume_s16re_sse2(int16_t *samples, int32_t *volumes, unsigned ch
 #define CHANNELS 2
 #define SAMPLES 1022
 #define TIMES 1000
+#define TIMES2 100
 #define PADDING 16
 
 static void run_test(void) {
@@ -263,6 +264,9 @@ static void run_test(void) {
     int i, j, padding;
     pa_do_volume_func_t func;
     pa_usec_t start, stop;
+    int k;
+    pa_usec_t min = INT_MAX, max = 0;
+    double s1 = 0, s2 = 0;
 
     func = pa_get_volume_func(PA_SAMPLE_S16NE);
 
@@ -286,21 +290,39 @@ static void run_test(void) {
         }
     }
 
-    start = pa_rtclock_now();
-    for (j = 0; j < TIMES; j++) {
-        memcpy(samples, samples_orig, sizeof(samples));
-        pa_volume_s16ne_sse2(samples, volumes, CHANNELS, sizeof(samples));
+    for (k = 0; k < TIMES2; k++) {
+        start = pa_rtclock_now();
+        for (j = 0; j < TIMES; j++) {
+            memcpy(samples, samples_orig, sizeof(samples));
+            pa_volume_s16ne_sse2(samples, volumes, CHANNELS, sizeof(samples));
+        }
+        stop = pa_rtclock_now();
+
+        if (min > (stop - start)) min = stop - start;
+        if (max < (stop - start)) max = stop - start;
+        s1 += stop - start;
+        s2 += (stop - start) * (stop - start);
     }
-    stop = pa_rtclock_now();
-    pa_log_info("SSE: %llu usec.", (long long unsigned int)(stop - start));
+    pa_log_info("SSE: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
+            (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
+
+    min = INT_MAX; max = 0;
+    s1 = s2 = 0;
+    for (k = 0; k < TIMES2; k++) {
+        start = pa_rtclock_now();
+        for (j = 0; j < TIMES; j++) {
+            memcpy(samples_ref, samples_orig, sizeof(samples));
+            func(samples_ref, volumes, CHANNELS, sizeof(samples));
+        }
+        stop = pa_rtclock_now();
 
-    start = pa_rtclock_now();
-    for (j = 0; j < TIMES; j++) {
-        memcpy(samples_ref, samples_orig, sizeof(samples));
-        func(samples_ref, volumes, CHANNELS, sizeof (samples));
+        if (min > (stop - start)) min = stop - start;
+        if (max < (stop - start)) max = stop - start;
+        s1 += stop - start;
+        s2 += (stop - start) * (stop - start);
     }
-    stop = pa_rtclock_now();
-    pa_log_info("ref: %llu usec.", (long long unsigned int)(stop - start));
+    pa_log_info("ref: %llu usec (min = %llu, max = %llu, stddev = %g).", (long long unsigned int)s1,
+            (long long unsigned int)min, (long long unsigned int)max, sqrt(TIMES2 * s2 - s1 * s1) / TIMES2);
 
     pa_assert_se(memcmp(samples_ref, samples, sizeof(samples)) == 0);
 }

commit 67ba3734eabf0cfaff6528c0e54db35dc839653a
Author: Alexander Kurtz <kurtz.alex at googlemail.com>
Date:   Mon Apr 18 10:28:05 2011 +0200

    vala: More vala fixes
    
    1. Remove the "has_destroy_function=false" attribute. It was only
    necessary because of a bug in vala which is fixed in 0.12. [1]
    
    2. Add sizes to all fixed-size arrays to make vala recognize them as
    such. Using symbolic constants for this is not yet supported. [2]
    
    3. CardInfo struct: Move the brackets in the list of available profiles
    to the type to make it clear that this is a dynamically-sized array. [3]
    
    [1] http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=622773
    [2] https://bugzilla.gnome.org/show_bug.cgi?id=647788
    [3] http://0pointer.de/lennart/projects/pulseaudio/doxygen/structpa__card__info.html

diff --git a/vala/libpulse.vapi b/vala/libpulse.vapi
index 06f412d..3e595f8 100644
--- a/vala/libpulse.vapi
+++ b/vala/libpulse.vapi
@@ -243,7 +243,8 @@ namespace PulseAudio {
         [CCode (cname="pa_cvolume")]
         public struct CVolume {
                 public uint8 channels;
-                public Volume values[];
+                // TODO: Replace array length with CHANNELS_MAX once vala's bug #647788 is fixed
+                public Volume values[32];
 
                 [CCode (cname="PA_SW_CVOLUME_SNPRINT_DB_MAX")]
                 public static const size_t SW_SNPRINT_DB_MAX;
@@ -373,10 +374,11 @@ namespace PulseAudio {
                 public unowned CVolume? dec(Volume minus = 1);
         }
 
-        [CCode (cname="pa_channel_map",has_destroy_function=false)]
+        [CCode (cname="pa_channel_map")]
         public struct ChannelMap {
                 public uint8 channels;
-                public ChannelPosition map[];
+                // TODO: Replace array length with CHANNELS_MAX once vala's bug #647788 is fixed
+                public ChannelPosition map[32];
 
                 [CCode (cname="PA_CHANNEL_MAP_SNPRINT_MAX")]
                 public static const size_t SNPRINT_MAX;
@@ -1350,7 +1352,7 @@ namespace PulseAudio {
                 public uint32 owner_module;
                 public string driver;
                 public uint32 n_profiles;
-                public CardProfileInfo profiles[];
+                public CardProfileInfo[] profiles;
                 public CardProfileInfo *active_profile;
                 public Proplist proplist;
         }

commit 1f602ded57bbae5d33e0a239a543e1009ea2634d
Author: Marc-André Lureau <marcandre.lureau at gmail.com>
Date:   Tue Apr 19 09:46:45 2011 +0300

    interpol-test: remove unused include getopt.h

diff --git a/src/tests/interpol-test.c b/src/tests/interpol-test.c
index 007555c..ca5c50b 100644
--- a/src/tests/interpol-test.c
+++ b/src/tests/interpol-test.c
@@ -28,7 +28,6 @@
 #include <assert.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <getopt.h>
 #include <math.h>
 
 #include <pulse/pulseaudio.h>

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list