[pulseaudio-commits] [SCM] PulseAudio Sound Server branch, master, updated. v0.9.19-373-g66cfa72

Colin Guthrie gitmailer-noreply at 0pointer.de
Wed Feb 10 17:52:09 PST 2010


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

- Log -----------------------------------------------------------------
66cfa72 native: rework handling of seeks that depend on variables the client does not know anything about
d090995 client: implement $PULSE_LATENCY_MSEC
fb55798 pacat: allow configuration of latency in msec
544fa0b udev: use ID_MODEL_ENC instead of ID_MODEL if it is set
4315f27 alsa: cover bass boost mixer element
63ebd05 udev: rework modem detection a bit
c2ab61c udev: handle sound cards with both modem and audio properly
7b89c85 alsa: Cover the 'Int Mic Boost' element.
7f6531d alsa: cover Input Source:Int Mic
54025c9 cpu: check for CMOV flag before using this intsruction in assembly
c88e468 alsa: ignore volume changes from the hw if we are not on the active console
ce7bd05 udev: make sure we get events only for sound devices
f732c23 log: add an easy way to disable log rate limiting
41ce7cb bluetooth: fix invalid memory access
7f7455b once: make once related variables volatile
66ddeed udev: don't forget to unref devices we are not interested in
9ac12b7 client: verify connection state in pa_stream_connect_upload()
7ab9bea client: detect forking in sample cache API, too
e8a2d12 bluetooth: don't hit an assert if latency is queried for a stooped recording stream
21250ff bluetooth: destruct stream only if it is not already destructed
3455478 core: make sure we always return a valid memblock in sink_input_pop() callbacks
699233f native: fix request counter miscalculations
66dbca1 dbus: remove filter functions only if they were actually set before
5e2a80c bump soname
63abcc8 build-sys: bump soname
-----------------------------------------------------------------------

Summary of changes:
 configure.ac                                       |    2 +-
 man/pacat.1.xml.in                                 |   96 ++++++++++++++---
 src/modules/alsa/alsa-mixer.c                      |    2 +
 src/modules/alsa/alsa-sink.c                       |    3 +
 src/modules/alsa/alsa-source.c                     |    3 +
 .../alsa/mixer/paths/analog-input-mic.conf.common  |    9 ++
 .../alsa/mixer/paths/analog-input.conf.common      |    4 +
 .../alsa/mixer/paths/analog-output.conf.common     |   11 ++
 src/modules/bluetooth/bluetooth-util.c             |   13 ++-
 src/modules/bluetooth/module-bluetooth-device.c    |   45 +++++---
 src/modules/bluetooth/module-bluetooth-proximity.c |   11 +-
 src/modules/module-combine.c                       |    6 +-
 src/modules/module-console-kit.c                   |    9 ++-
 src/modules/module-hal-detect.c                    |   10 +-
 src/modules/module-ladspa-sink.c                   |    6 +-
 src/modules/module-loopback.c                      |    4 +-
 src/modules/module-udev-detect.c                   |   69 ++++++++++++-
 src/modules/udev-util.c                            |  110 ++++++++++++++++++++
 src/pulse/context.c                                |   25 +----
 src/pulse/internal.h                               |    1 +
 src/pulse/scache.c                                 |   10 ++-
 src/pulse/stream.c                                 |   47 +++++++-
 src/pulsecore/cpu-x86.c                            |    6 +-
 src/pulsecore/cpu-x86.h                            |    4 +-
 src/pulsecore/flist.h                              |    2 +-
 src/pulsecore/log.c                                |   88 +++++++++-------
 src/pulsecore/memblockq.c                          |  105 +++++++++----------
 src/pulsecore/memblockq.h                          |    2 +-
 src/pulsecore/once.c                               |    3 +-
 src/pulsecore/play-memchunk.c                      |    6 +-
 src/pulsecore/protocol-esound.c                    |    5 +-
 src/pulsecore/protocol-native.c                    |   13 ++-
 src/pulsecore/protocol-simple.c                    |    6 +-
 src/pulsecore/sink-input.c                         |    2 +-
 src/pulsecore/sound-file-stream.c                  |    5 +-
 src/pulsecore/svolume_mmx.c                        |    2 +-
 src/pulsecore/thread-posix.c                       |    8 +-
 src/pulsecore/thread.h                             |    2 +-
 src/utils/pacat.c                                  |   46 +++++++--
 39 files changed, 593 insertions(+), 208 deletions(-)

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

commit 63abcc83307fd74d6556e8a679d647b5b5920868
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Nov 11 05:32:24 2009 +0100

    build-sys: bump soname

diff --git a/configure.ac b/configure.ac
index 6b540e4..b4f94c1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,7 +44,7 @@ AC_SUBST(PA_PROTOCOL_VERSION, 17)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z
-AC_SUBST(LIBPULSE_VERSION_INFO, [12:0:12])
+AC_SUBST(LIBPULSE_VERSION_INFO, [12:1:12])
 
 # A simplified, synchronous, ABI-stable interface for client
 # applications, for the version info x:y:z always will hold y=z

commit 5e2a80c7e33a9f32058d53c33519197567a9887a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Nov 23 05:07:00 2009 +0100

    bump soname

diff --git a/configure.ac b/configure.ac
index b4f94c1..8abaabb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,7 +44,7 @@ AC_SUBST(PA_PROTOCOL_VERSION, 17)
 
 # The stable ABI for client applications, for the version info x:y:z
 # always will hold y=z
-AC_SUBST(LIBPULSE_VERSION_INFO, [12:1:12])
+AC_SUBST(LIBPULSE_VERSION_INFO, [12:2:12])
 
 # A simplified, synchronous, ABI-stable interface for client
 # applications, for the version info x:y:z always will hold y=z

commit 66dbca1e06af0607a2d0fc6b8d14ef1ebb034f0a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 8 20:06:21 2010 +0100

    dbus: remove filter functions only if they were actually set before
    
    This fixes an assert when destructing modules that have not been fully
    initialized.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=548525

diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 47d6200..795d510 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -37,6 +37,7 @@ struct pa_bluetooth_discovery {
     PA_LLIST_HEAD(pa_dbus_pending, pending);
     pa_hashmap *devices;
     pa_hook hook;
+    pa_bool_t filter_added;
 };
 
 static void get_properties_reply(DBusPendingCall *pending, void *userdata);
@@ -788,6 +789,7 @@ pa_bluetooth_discovery* pa_bluetooth_discovery_get(pa_core *c) {
         pa_log_error("Failed to add filter function");
         goto fail;
     }
+    y->filter_added = TRUE;
 
     if (pa_dbus_add_matches(
                 pa_dbus_connection_get(y->connection), &err,
@@ -856,7 +858,8 @@ void pa_bluetooth_discovery_unref(pa_bluetooth_discovery *y) {
                                "type='signal',sender='org.bluez',interface='org.bluez.AudioSink',member='PropertyChanged'",
                                "type='signal',sender='org.bluez',interface='org.bluez.AudioSource',member='PropertyChanged'", NULL);
 
-        dbus_connection_remove_filter(pa_dbus_connection_get(y->connection), filter_cb, y);
+        if (y->filter_added)
+            dbus_connection_remove_filter(pa_dbus_connection_get(y->connection), filter_cb, y);
 
         pa_dbus_connection_unref(y->connection);
     }
diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 0ba1421..19676df 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -179,6 +179,8 @@ struct userdata {
 
     int stream_write_type;
     int service_write_type, service_read_type;
+
+    pa_bool_t filter_added;
 };
 
 #define FIXED_LATENCY_PLAYBACK_A2DP (25*PA_USEC_PER_MSEC)
@@ -2405,6 +2407,7 @@ int pa__init(pa_module* m) {
         pa_log_error("Failed to add filter function");
         goto fail;
     }
+    u->filter_added = TRUE;
 
     speaker = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='SpeakerGainChanged',path='%s'", u->path);
     mike = pa_sprintf_malloc("type='signal',sender='org.bluez',interface='org.bluez.Headset',member='MicrophoneGainChanged',path='%s'", u->path);
@@ -2494,7 +2497,9 @@ void pa__done(pa_module *m) {
             pa_xfree(mike);
         }
 
-        dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
+        if (u->filter_added)
+            dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
+
         pa_dbus_connection_unref(u->connection);
     }
 
diff --git a/src/modules/bluetooth/module-bluetooth-proximity.c b/src/modules/bluetooth/module-bluetooth-proximity.c
index c4cfd73..3eed9ce 100644
--- a/src/modules/bluetooth/module-bluetooth-proximity.c
+++ b/src/modules/bluetooth/module-bluetooth-proximity.c
@@ -92,7 +92,8 @@ struct userdata {
     unsigned n_found;
     unsigned n_unknown;
 
-    pa_bool_t muted;
+    pa_bool_t muted:1;
+    pa_bool_t filter_added:1;
 };
 
 static void update_volume(struct userdata *u) {
@@ -358,9 +359,10 @@ static int add_matches(struct userdata *u, pa_bool_t add) {
     } else
         dbus_bus_remove_match(pa_dbus_connection_get(u->dbus_connection), filter2, &e);
 
-    if (add)
+    if (add) {
         pa_assert_se(dbus_connection_add_filter(pa_dbus_connection_get(u->dbus_connection), filter_func, u, NULL));
-    else
+        u->filter_added = TRUE;
+    } else if (u->filter_added)
         dbus_connection_remove_filter(pa_dbus_connection_get(u->dbus_connection), filter_func, u);
 
     r = 0;
@@ -393,9 +395,6 @@ int pa__init(pa_module*m) {
     u->sink_name = pa_xstrdup(pa_modargs_get_value(ma, "sink", NULL));
     u->hci = pa_xstrdup(pa_modargs_get_value(ma, "hci", DEFAULT_HCI));
     u->hci_path = pa_sprintf_malloc("/org/bluez/%s", u->hci);
-    u->n_found = u->n_unknown = 0;
-    u->muted = FALSE;
-
     u->bondings = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
 
     if (!(u->dbus_connection = pa_dbus_bus_get(m->core, DBUS_BUS_SYSTEM, &e))) {
diff --git a/src/modules/module-console-kit.c b/src/modules/module-console-kit.c
index 103f5c4..875852f 100644
--- a/src/modules/module-console-kit.c
+++ b/src/modules/module-console-kit.c
@@ -67,6 +67,7 @@ struct userdata {
     pa_core *core;
     pa_dbus_connection *connection;
     pa_hashmap *sessions;
+    pa_bool_t filter_added;
 };
 
 static void add_session(struct userdata *u, const char *id) {
@@ -300,7 +301,7 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    m->userdata = u = pa_xnew(struct userdata, 1);
+    m->userdata = u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
     u->module = m;
     u->connection = connection;
@@ -311,6 +312,8 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    u->filter_added = TRUE;
+
     if (pa_dbus_add_matches(
                 pa_dbus_connection_get(connection), &error,
                 "type='signal',sender='org.freedesktop.ConsoleKit',interface='org.freedesktop.ConsoleKit.Seat',member='SessionAdded'",
@@ -359,7 +362,9 @@ void pa__done(pa_module *m) {
                 "type='signal',sender='org.freedesktop.ConsoleKit',interface='org.freedesktop.ConsoleKit.Seat',member='SessionAdded'",
                 "type='signal',sender='org.freedesktop.ConsoleKit',interface='org.freedesktop.ConsoleKit.Seat',member='SessionRemoved'", NULL);
 
-        dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
+        if (u->filter_added)
+            dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
+
         pa_dbus_connection_unref(u->connection);
     }
 
diff --git a/src/modules/module-hal-detect.c b/src/modules/module-hal-detect.c
index 1851913..23d4010 100644
--- a/src/modules/module-hal-detect.c
+++ b/src/modules/module-hal-detect.c
@@ -87,6 +87,7 @@ struct userdata {
 #ifdef HAVE_OSS_OUTPUT
     pa_bool_t init_subdevs;
 #endif
+    pa_bool_t filter_added:1;
 };
 
 #define CAPABILITY_ALSA "alsa"
@@ -733,12 +734,9 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
-    m->userdata = u = pa_xnew(struct userdata, 1);
+    m->userdata = u = pa_xnew0(struct userdata, 1);
     u->core = m->core;
-    u->context = NULL;
-    u->connection = NULL;
     u->devices = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
-    u->capability = NULL;
 
 #ifdef HAVE_ALSA
     u->use_tsched = TRUE;
@@ -800,6 +798,7 @@ int pa__init(pa_module*m) {
         pa_log_error("Failed to add filter function");
         goto fail;
     }
+    u->filter_added = TRUE;
 
     if (pa_dbus_add_matches(
                 pa_dbus_connection_get(u->connection), &error,
@@ -856,7 +855,8 @@ void pa__done(pa_module *m) {
                 "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLRemoved'",
                 "type='signal',interface='org.pulseaudio.Server',member='DirtyGiveUpMessage'", NULL);
 
-        dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
+        if (u->filter_added)
+            dbus_connection_remove_filter(pa_dbus_connection_get(u->connection), filter_cb, u);
         pa_dbus_connection_unref(u->connection);
     }
 
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 83e0dbb..8875bfd 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -145,7 +145,7 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
 
     pa_init_i18n();
 
-    c = pa_xnew(pa_context, 1);
+    c = pa_xnew0(pa_context, 1);
     PA_REFCNT_INIT(c);
 
     c->proplist = p ? pa_proplist_copy(p) : pa_proplist_new();
@@ -157,9 +157,6 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
     c->system_bus = c->session_bus = NULL;
 #endif
     c->mainloop = mainloop;
-    c->client = NULL;
-    c->pstream = NULL;
-    c->pdispatch = NULL;
     c->playback_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
     c->record_streams = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
     c->client_index = PA_INVALID_INDEX;
@@ -170,22 +167,9 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
 
     c->error = PA_OK;
     c->state = PA_CONTEXT_UNCONNECTED;
-    c->ctag = 0;
-    c->csyncid = 0;
 
     reset_callbacks(c);
 
-    c->is_local = FALSE;
-    c->server_list = NULL;
-    c->server = NULL;
-
-    c->do_shm = FALSE;
-
-    c->server_specified = FALSE;
-    c->no_fail = FALSE;
-    c->do_autospawn = FALSE;
-    memset(&c->spawn_api, 0, sizeof(c->spawn_api));
-
 #ifndef MSG_NOSIGNAL
 #ifdef SIGPIPE
     pa_check_signal_is_blocked(SIGPIPE);
@@ -255,12 +239,14 @@ static void context_free(pa_context *c) {
 
 #ifdef HAVE_DBUS
     if (c->system_bus) {
-        dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->system_bus), filter_cb, c);
+        if (c->filter_added)
+            dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->system_bus), filter_cb, c);
         pa_dbus_wrap_connection_free(c->system_bus);
     }
 
     if (c->session_bus) {
-        dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->session_bus), filter_cb, c);
+        if (c->filter_added)
+            dbus_connection_remove_filter(pa_dbus_wrap_connection_get(c->session_bus), filter_cb, c);
         pa_dbus_wrap_connection_free(c->session_bus);
     }
 #endif
@@ -794,6 +780,7 @@ static void track_pulseaudio_on_dbus(pa_context *c, DBusBusType type, pa_dbus_wr
         pa_log_warn("Failed to add filter function");
         goto fail;
     }
+    c->filter_added = TRUE;
 
     if (pa_dbus_add_matches(
                 pa_dbus_wrap_connection_get(*conn), &error,
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index 9545d50..ab702b9 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -90,6 +90,7 @@ struct pa_context {
     pa_bool_t no_fail:1;
     pa_bool_t do_autospawn:1;
     pa_bool_t use_rtclock:1;
+    pa_bool_t filter_added:1;
     pa_spawn_api spawn_api;
 
     pa_strlist *server_list;

commit 699233fb47d133f6ea1e36e8354a386c23608d5a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 8 20:07:34 2010 +0100

    native: fix request counter miscalculations
    
    Do not subtract bytes the client sends us beyond what we requested from
    our missing bytes counter.
    
    This was mostly a thinko that caused servers asking for too little data
    when the client initially sent more data than requested, because that
    data sent too much was accounted for twice.
    
    This commit fixes this miscalculation.
    
    http://bugzilla.redhat.com/show_bug.cgi?id=534130

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 4081256..0f9e50a 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -741,6 +741,8 @@ void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tag
 
     s->requested_bytes += bytes;
 
+    /* pa_log("got request for %lli, now at %lli", (long long) bytes, (long long) s->requested_bytes); */
+
     if (s->requested_bytes > 0 && s->write_callback)
         s->write_callback(s, (size_t) s->requested_bytes, s->write_userdata);
 
@@ -1362,6 +1364,8 @@ int pa_stream_write(
      * that's OK, the server side applies the same error */
     s->requested_bytes -= (seek == PA_SEEK_RELATIVE ? offset : 0) + (int64_t) length;
 
+    /* pa_log("wrote %lli, now at %lli", (long long) length, (long long) s->requested_bytes); */
+
     if (s->direction == PA_STREAM_PLAYBACK) {
 
         /* Update latency request correction */
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 32758be..4641801 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -55,8 +55,7 @@ struct pa_memblockq {
     pa_bool_t in_prebuf;
     pa_memchunk silence;
     pa_mcalign *mcalign;
-    int64_t missing;
-    size_t requested;
+    int64_t missing, requested;
 };
 
 pa_memblockq* pa_memblockq_new(
@@ -84,8 +83,8 @@ pa_memblockq* pa_memblockq_new(
     pa_log_debug("memblockq requested: maxlength=%lu, tlength=%lu, base=%lu, prebuf=%lu, minreq=%lu maxrewind=%lu",
                  (unsigned long) maxlength, (unsigned long) tlength, (unsigned long) base, (unsigned long) prebuf, (unsigned long) minreq, (unsigned long) maxrewind);
 
-    bq->missing = 0;
-    bq->requested = bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = bq->maxrewind = 0;
+    bq->missing = bq->requested = 0;
+    bq->maxlength = bq->tlength = bq->prebuf = bq->minreq = bq->maxrewind = 0;
     bq->in_prebuf = TRUE;
 
     pa_memblockq_set_maxlength(bq, maxlength);
@@ -246,10 +245,34 @@ static pa_bool_t can_push(pa_memblockq *bq, size_t l) {
     return TRUE;
 }
 
+static void write_index_changed(pa_memblockq *bq, int64_t old_write_index, pa_bool_t account) {
+    int64_t delta;
+
+    pa_assert(bq);
+
+    delta = bq->write_index - old_write_index;
+
+    if (account)
+        bq->requested -= delta;
+
+    /* pa_log("pushed/seeked %lli: requested counter at %lli, account=%i", (long long) delta, (long long) bq->requested, account); */
+}
+
+static void read_index_changed(pa_memblockq *bq, int64_t old_read_index) {
+    int64_t delta;
+
+    pa_assert(bq);
+
+    delta = bq->read_index - old_read_index;
+    bq->missing += delta;
+
+    /* pa_log("popped %lli: missing counter at %lli", (long long) delta, (long long) bq->missing); */
+}
+
 int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
     struct list_item *q, *n;
     pa_memchunk chunk;
-    int64_t old, delta;
+    int64_t old;
 
     pa_assert(bq);
     pa_assert(uchunk);
@@ -409,18 +432,7 @@ int pa_memblockq_push(pa_memblockq* bq, const pa_memchunk *uchunk) {
 
 finish:
 
-    delta = bq->write_index - old;
-
-    if (delta >= (int64_t) bq->requested) {
-        delta -= (int64_t) bq->requested;
-        bq->requested = 0;
-    } else {
-        bq->requested -= (size_t) delta;
-        delta = 0;
-    }
-
-    bq->missing -= delta;
-
+    write_index_changed(bq, old, TRUE);
     return 0;
 }
 
@@ -514,7 +526,7 @@ int pa_memblockq_peek(pa_memblockq* bq, pa_memchunk *chunk) {
 }
 
 void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
-    int64_t old, delta;
+    int64_t old;
     pa_assert(bq);
     pa_assert(length % bq->base == 0);
 
@@ -553,19 +565,21 @@ void pa_memblockq_drop(pa_memblockq *bq, size_t length) {
     }
 
     drop_backlog(bq);
-
-    delta = bq->read_index - old;
-    bq->missing += delta;
+    read_index_changed(bq, old);
 }
 
 void pa_memblockq_rewind(pa_memblockq *bq, size_t length) {
+    int64_t old;
     pa_assert(bq);
     pa_assert(length % bq->base == 0);
 
+    old = bq->read_index;
+
     /* This is kind of the inverse of pa_memblockq_drop() */
 
     bq->read_index -= (int64_t) length;
-    bq->missing -= (int64_t) length;
+
+    read_index_changed(bq, old);
 }
 
 pa_bool_t pa_memblockq_is_readable(pa_memblockq *bq) {
@@ -602,7 +616,7 @@ size_t pa_memblockq_missing(pa_memblockq *bq) {
 }
 
 void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek, pa_bool_t account) {
-    int64_t old, delta;
+    int64_t old;
     pa_assert(bq);
 
     old = bq->write_index;
@@ -625,24 +639,11 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek, pa
     }
 
     drop_backlog(bq);
-
-    delta = bq->write_index - old;
-
-    if (account) {
-        if (delta >= (int64_t) bq->requested) {
-            delta -= (int64_t) bq->requested;
-            bq->requested = 0;
-        } else if (delta >= 0) {
-            bq->requested -= (size_t) delta;
-            delta = 0;
-        }
-    }
-
-    bq->missing -= delta;
+    write_index_changed(bq, old, account);
 }
 
 void pa_memblockq_flush_write(pa_memblockq *bq) {
-    int64_t old, delta;
+    int64_t old;
     pa_assert(bq);
 
     pa_memblockq_silence(bq);
@@ -651,22 +652,11 @@ void pa_memblockq_flush_write(pa_memblockq *bq) {
     bq->write_index = bq->read_index;
 
     pa_memblockq_prebuf_force(bq);
-
-    delta = bq->write_index - old;
-
-    if (delta >= (int64_t) bq->requested) {
-        delta -= (int64_t) bq->requested;
-        bq->requested = 0;
-    } else if (delta >= 0) {
-        bq->requested -= (size_t) delta;
-        delta = 0;
-    }
-
-    bq->missing -= delta;
+    write_index_changed(bq, old, TRUE);
 }
 
 void pa_memblockq_flush_read(pa_memblockq *bq) {
-    int64_t old, delta;
+    int64_t old;
     pa_assert(bq);
 
     pa_memblockq_silence(bq);
@@ -675,9 +665,7 @@ void pa_memblockq_flush_read(pa_memblockq *bq) {
     bq->read_index = bq->write_index;
 
     pa_memblockq_prebuf_force(bq);
-
-    delta = bq->read_index - old;
-    bq->missing += delta;
+    read_index_changed(bq, old);
 }
 
 size_t pa_memblockq_get_tlength(pa_memblockq *bq) {
@@ -774,8 +762,11 @@ size_t pa_memblockq_pop_missing(pa_memblockq *bq) {
         return 0;
 
     l = (size_t) bq->missing;
+
+    bq->requested += bq->missing;
     bq->missing = 0;
-    bq->requested += l;
+
+    /* pa_log("sent %lli: request counter is at %lli", (long long) l, (long long) bq->requested); */
 
     return l;
 }
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index d49a78e..89f33d0 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1114,6 +1114,8 @@ static playback_stream* playback_stream_new(
 
     *missing = (uint32_t) pa_memblockq_pop_missing(s->memblockq);
 
+    /* pa_log("missing original: %li", (long int) *missing); */
+
     *ss = s->sink_input->sample_spec;
     *map = s->sink_input->channel_map;
 
@@ -1138,11 +1140,12 @@ static void playback_stream_request_bytes(playback_stream *s) {
 
     m = pa_memblockq_pop_missing(s->memblockq);
 
-    /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu)", */
+    /* pa_log("request_bytes(%lu) (tlength=%lu minreq=%lu length=%lu really missing=%lli)", */
     /*        (unsigned long) m, */
     /*        pa_memblockq_get_tlength(s->memblockq), */
     /*        pa_memblockq_get_minreq(s->memblockq), */
-    /*        pa_memblockq_get_length(s->memblockq)); */
+    /*        pa_memblockq_get_length(s->memblockq), */
+    /*        (long long) pa_memblockq_get_tlength(s->memblockq) - (long long) pa_memblockq_get_length(s->memblockq)); */
 
     if (m <= 0)
         return;

commit 345547853bcb0825c0afb5b2528a8f1d5339a8ea
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 8 21:51:30 2010 +0100

    core: make sure we always return a valid memblock in sink_input_pop() callbacks
    
    https://bugzilla.redhat.com/show_bug.cgi?id=553607

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index a186c89..62e6267 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -890,7 +890,7 @@ static struct output *output_new(struct userdata *u, pa_sink *sink) {
             1,
             0,
             0,
-            NULL);
+            &u->sink->silence);
 
     pa_assert_se(pa_idxset_put(u->outputs, o, NULL) == 0);
     update_description(u);
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 994c778..185871b 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -476,6 +476,7 @@ int pa__init(pa_module*m) {
     unsigned long input_port, output_port, p, j, n_control;
     unsigned c;
     pa_bool_t *use_default = NULL;
+    pa_memchunk silence;
 
     pa_assert(m);
 
@@ -514,7 +515,10 @@ int pa__init(pa_module*m) {
     u = pa_xnew0(struct userdata, 1);
     u->module = m;
     m->userdata = u;
-    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);
+
+    pa_silence_memchunk_get(&m->core->silence_cache, m->core->mempool, &silence, &ss, 0);
+    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, &silence);
+    pa_memblock_unref(silence.memblock);
 
     if (!(e = getenv("LADSPA_PATH")))
         e = LADSPA_PATH;
diff --git a/src/pulsecore/play-memchunk.c b/src/pulsecore/play-memchunk.c
index f127d7a..1a3bd5b 100644
--- a/src/pulsecore/play-memchunk.c
+++ b/src/pulsecore/play-memchunk.c
@@ -47,12 +47,16 @@ int pa_play_memchunk(
 
     pa_memblockq *q;
     int r;
+    pa_memchunk silence;
 
     pa_assert(sink);
     pa_assert(ss);
     pa_assert(chunk);
 
-    q = pa_memblockq_new(0, chunk->length, 0, pa_frame_size(ss), 1, 1, 0, NULL);
+    pa_silence_memchunk_get(&sink->core->silence_cache, sink->core->mempool, &silence, ss, 0);
+    q = pa_memblockq_new(0, chunk->length, 0, pa_frame_size(ss), 1, 1, 0, &silence);
+    pa_memblock_unref(silence.memblock);
+
     pa_assert_se(pa_memblockq_push(q, chunk) >= 0);
 
     if ((r = pa_play_memblockq(sink, ss, map, q, volume, p, sink_input_index)) < 0) {
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index 2326eb3..a89f327 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -389,6 +389,7 @@ static int esd_proto_stream_play(connection *c, esd_proto_t request, const void
     size_t l;
     pa_sink *sink = NULL;
     pa_sink_input_new_data sdata;
+    pa_memchunk silence;
 
     connection_assert_ref(c);
     pa_assert(data);
@@ -435,6 +436,7 @@ static int esd_proto_stream_play(connection *c, esd_proto_t request, const void
     CHECK_VALIDITY(c->sink_input, "Failed to create sink input.");
 
     l = (size_t) ((double) pa_bytes_per_second(&ss)*PLAYBACK_BUFFER_SECONDS);
+    pa_sink_input_get_silence(c->sink_input, &silence);
     c->input_memblockq = pa_memblockq_new(
             0,
             l,
@@ -443,7 +445,8 @@ static int esd_proto_stream_play(connection *c, esd_proto_t request, const void
             (size_t) -1,
             l/PLAYBACK_BUFFER_FRAGMENTS,
             0,
-            NULL);
+            &silence);
+    pa_memblock_unref(silence.memblock);
     pa_iochannel_socket_set_rcvbuf(c->io, l);
 
     c->sink_input->parent.process_msg = sink_input_process_msg;
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index a9f7389..fb2e564 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -525,6 +525,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
 
     if (o->playback) {
         pa_sink_input_new_data data;
+        pa_memchunk silence;
         size_t l;
         pa_sink *sink;
 
@@ -559,6 +560,7 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
         pa_sink_input_set_requested_latency(c->sink_input, DEFAULT_SINK_LATENCY);
 
         l = (size_t) ((double) pa_bytes_per_second(&o->sample_spec)*PLAYBACK_BUFFER_SECONDS);
+        pa_sink_input_get_silence(c->sink_input, &silence);
         c->input_memblockq = pa_memblockq_new(
                 0,
                 l,
@@ -567,7 +569,9 @@ void pa_simple_protocol_connect(pa_simple_protocol *p, pa_iochannel *io, pa_simp
                 (size_t) -1,
                 l/PLAYBACK_BUFFER_FRAGMENTS,
                 0,
-                NULL);
+                &silence);
+        pa_memblock_unref(silence.memblock);
+
         pa_iochannel_socket_set_rcvbuf(io, l);
 
         pa_atomic_store(&c->playback.missing, (int) pa_memblockq_missing(c->input_memblockq));
diff --git a/src/pulsecore/sound-file-stream.c b/src/pulsecore/sound-file-stream.c
index 53674ba..4037dca 100644
--- a/src/pulsecore/sound-file-stream.c
+++ b/src/pulsecore/sound-file-stream.c
@@ -239,6 +239,7 @@ int pa_play_file(
     pa_sink_input_new_data data;
     int fd;
     SF_INFO sfi;
+    pa_memchunk silence;
 
     pa_assert(sink);
     pa_assert(fname);
@@ -320,7 +321,9 @@ int pa_play_file(
     u->sink_input->state_change = sink_input_state_change_cb;
     u->sink_input->userdata = u;
 
-    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, NULL);
+    pa_sink_input_get_silence(u->sink_input, &silence);
+    u->memblockq = pa_memblockq_new(0, MEMBLOCKQ_MAXLENGTH, 0, pa_frame_size(&ss), 1, 1, 0, &silence);
+    pa_memblock_unref(silence.memblock);
 
     pa_sink_input_put(u->sink_input);
 

commit 21250ff1a7ad9f3494f1d9f8aeb651c5f01dc942
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 8 22:18:15 2010 +0100

    bluetooth: destruct stream only if it is not already destructed
    
    https://bugzilla.redhat.com/show_bug.cgi?id=551842

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 19676df..2bbae41 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -823,23 +823,25 @@ static int stop_stream_fd(struct userdata *u) {
 
     pa_assert(u);
     pa_assert(u->rtpoll);
-    pa_assert(u->rtpoll_item);
-    pa_assert(u->stream_fd >= 0);
 
-    pa_rtpoll_item_free(u->rtpoll_item);
-    u->rtpoll_item = NULL;
+    if (u->rtpoll_item) {
+        pa_rtpoll_item_free(u->rtpoll_item);
+        u->rtpoll_item = NULL;
+    }
 
-    memset(msg.buf, 0, BT_SUGGESTED_BUFFER_SIZE);
-    msg.start_req.h.type = BT_REQUEST;
-    msg.start_req.h.name = BT_STOP_STREAM;
-    msg.start_req.h.length = sizeof(msg.start_req);
+    if (u->stream_fd >= 0) {
+        memset(msg.buf, 0, BT_SUGGESTED_BUFFER_SIZE);
+        msg.start_req.h.type = BT_REQUEST;
+        msg.start_req.h.name = BT_STOP_STREAM;
+        msg.start_req.h.length = sizeof(msg.start_req);
 
-    if (service_send(u, &msg.start_req.h) < 0 ||
-        service_expect(u, &msg.rsp, sizeof(msg), BT_STOP_STREAM, sizeof(msg.start_rsp)) < 0)
-        r = -1;
+        if (service_send(u, &msg.start_req.h) < 0 ||
+            service_expect(u, &msg.rsp, sizeof(msg), BT_STOP_STREAM, sizeof(msg.start_rsp)) < 0)
+            r = -1;
 
-    pa_close(u->stream_fd);
-    u->stream_fd = -1;
+        pa_close(u->stream_fd);
+        u->stream_fd = -1;
+    }
 
     if (u->read_smoother) {
         pa_smoother_free(u->read_smoother);

commit e8a2d127249dfb255efd03f7eebbbbe5502e5951
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 8 23:44:42 2010 +0100

    bluetooth: don't hit an assert if latency is queried for a stooped recording stream
    
    https://bugzilla.redhat.com/show_bug.cgi?id=537422

diff --git a/src/modules/bluetooth/module-bluetooth-device.c b/src/modules/bluetooth/module-bluetooth-device.c
index 2bbae41..d6868b8 100644
--- a/src/modules/bluetooth/module-bluetooth-device.c
+++ b/src/modules/bluetooth/module-bluetooth-device.c
@@ -972,10 +972,14 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
         case PA_SOURCE_MESSAGE_GET_LATENCY: {
             pa_usec_t wi, ri;
 
-            wi = pa_smoother_get(u->read_smoother, pa_rtclock_now());
-            ri = pa_bytes_to_usec(u->read_index, &u->sample_spec);
+            if (u->read_smoother) {
+                wi = pa_smoother_get(u->read_smoother, pa_rtclock_now());
+                ri = pa_bytes_to_usec(u->read_index, &u->sample_spec);
+
+                *((pa_usec_t*) data) = (wi > ri ? wi - ri : 0) + u->source->thread_info.fixed_latency;
+            } else
+                *((pa_usec_t*) data) = 0;
 
-            *((pa_usec_t*) data) = (wi > ri ? wi - ri : 0) + u->source->thread_info.fixed_latency;
             return 0;
         }
 

commit 7ab9bea29dc9b3174be6b6a3a557c934b8265533
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jan 12 03:01:14 2010 +0100

    client: detect forking in sample cache API, too

diff --git a/src/pulse/scache.c b/src/pulse/scache.c
index 27da688..2a7602f 100644
--- a/src/pulse/scache.c
+++ b/src/pulse/scache.c
@@ -28,15 +28,15 @@
 #include <string.h>
 
 #include <pulse/utf8.h>
+#include <pulse/scache.h>
 
 #include <pulsecore/pstream-util.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/proplist-util.h>
 
+#include "fork-detect.h"
 #include "internal.h"
 
-#include "scache.h"
-
 int pa_stream_connect_upload(pa_stream *s, size_t length) {
     pa_tagstruct *t;
     uint32_t tag;
@@ -45,6 +45,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) {
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID);
     PA_CHECK_VALIDITY(s->context, length == (size_t) (uint32_t) length, PA_ERR_INVALID);
@@ -85,6 +86,7 @@ int pa_stream_finish_upload(pa_stream *s) {
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
 
+    PA_CHECK_VALIDITY(s->context, !pa_detect_fork(), PA_ERR_FORKED);
     PA_CHECK_VALIDITY(s->context, s->channel_valid, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
@@ -174,6 +176,7 @@ pa_operation *pa_context_play_sample(pa_context *c, const char *name, const char
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
+    PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
     PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID);
@@ -213,6 +216,7 @@ pa_operation *pa_context_play_sample_with_proplist(pa_context *c, const char *na
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
+    PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
     PA_CHECK_VALIDITY_RETURN_NULL(c, !dev || *dev, PA_ERR_INVALID);
@@ -255,6 +259,7 @@ pa_operation* pa_context_remove_sample(pa_context *c, const char *name, pa_conte
     pa_assert(c);
     pa_assert(PA_REFCNT_VALUE(c) >= 1);
 
+    PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
     PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY_RETURN_NULL(c, name && *name, PA_ERR_INVALID);
 
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 0f9e50a..a4f34d9 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -29,6 +29,7 @@
 #include <string.h>
 
 #include <pulse/def.h>
+#include <pulse/stream.h>
 #include <pulse/timeval.h>
 #include <pulse/rtclock.h>
 #include <pulse/xmalloc.h>

commit 9ac12b7048b466effa551bd707648f66df18fe8a
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jan 12 03:01:27 2010 +0100

    client: verify connection state in pa_stream_connect_upload()
    
    Make suer we check the connection state before going on, so that we can
    rely that s->context->pstream is properly initialized.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=539500

diff --git a/src/pulse/scache.c b/src/pulse/scache.c
index 2a7602f..b2169b6 100644
--- a/src/pulse/scache.c
+++ b/src/pulse/scache.c
@@ -49,6 +49,7 @@ int pa_stream_connect_upload(pa_stream *s, size_t length) {
     PA_CHECK_VALIDITY(s->context, s->state == PA_STREAM_UNCONNECTED, PA_ERR_BADSTATE);
     PA_CHECK_VALIDITY(s->context, length > 0, PA_ERR_INVALID);
     PA_CHECK_VALIDITY(s->context, length == (size_t) (uint32_t) length, PA_ERR_INVALID);
+    PA_CHECK_VALIDITY(s->context, s->context->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
 
     if (!(name = pa_proplist_gets(s->proplist, PA_PROP_EVENT_ID)))
         name = pa_proplist_gets(s->proplist, PA_PROP_MEDIA_NAME);

commit 66ddeede9ea02cc97178d42c7be18067519eed8f
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jan 12 23:01:24 2010 +0100

    udev: don't forget to unref devices we are not interested in
    
    https://bugzilla.redhat.com/show_bug.cgi?id=552932

diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
index f17695b..dfd13ee 100644
--- a/src/modules/module-udev-detect.c
+++ b/src/modules/module-udev-detect.c
@@ -416,8 +416,10 @@ static void monitor_cb(
         goto fail;
     }
 
-    if (!path_get_card_id(udev_device_get_devpath(dev)))
+    if (!path_get_card_id(udev_device_get_devpath(dev))) {
+        udev_device_unref(dev);
         return;
+    }
 
     process_device(u, dev);
     udev_device_unref(dev);

commit 7f7455b1be68d2ff5706ccf85eff1a96f7c43d34
Author: Lennart Poettering <lennart at poettering.net>
Date:   Tue Jan 12 23:03:04 2010 +0100

    once: make once related variables volatile

diff --git a/src/pulsecore/flist.h b/src/pulsecore/flist.h
index e147486..184e599 100644
--- a/src/pulsecore/flist.h
+++ b/src/pulsecore/flist.h
@@ -45,7 +45,7 @@ void* pa_flist_pop(pa_flist*l);
 
 #define PA_STATIC_FLIST_DECLARE(name, size, free_cb)                    \
     static struct {                                                     \
-        pa_flist *flist;                                                \
+        pa_flist *volatile flist;                                       \
         pa_once once;                                                   \
     } name##_flist = { NULL, PA_ONCE_INIT };                            \
     static void name##_flist_init(void) {                               \
diff --git a/src/pulsecore/once.c b/src/pulsecore/once.c
index 05a3ad2..4e509e0 100644
--- a/src/pulsecore/once.c
+++ b/src/pulsecore/once.c
@@ -29,8 +29,6 @@
 #include "once.h"
 
 pa_bool_t pa_once_begin(pa_once *control) {
-    pa_mutex *m;
-
     pa_assert(control);
 
     if (pa_atomic_load(&control->done))
@@ -43,6 +41,7 @@ pa_bool_t pa_once_begin(pa_once *control) {
      * executed by us. Hence the awkward locking. */
 
     for (;;) {
+        pa_mutex *m;
 
         if ((m = pa_atomic_ptr_load(&control->mutex))) {
 
diff --git a/src/pulsecore/thread-posix.c b/src/pulsecore/thread-posix.c
index fdab270..bc0d6e3 100644
--- a/src/pulsecore/thread-posix.c
+++ b/src/pulsecore/thread-posix.c
@@ -80,11 +80,9 @@ pa_thread* pa_thread_new(pa_thread_func_t thread_func, void *userdata) {
 
     pa_assert(thread_func);
 
-    t = pa_xnew(pa_thread, 1);
+    t = pa_xnew0(pa_thread, 1);
     t->thread_func = thread_func;
     t->userdata = userdata;
-    t->joined = FALSE;
-    pa_atomic_store(&t->running, 0);
 
     if (pthread_create(&t->id, NULL, internal_thread_func, t) < 0) {
         pa_xfree(t);
@@ -135,10 +133,8 @@ pa_thread* pa_thread_self(void) {
     /* This is a foreign thread, let's create a pthread structure to
      * make sure that we can always return a sensible pointer */
 
-    t = pa_xnew(pa_thread, 1);
+    t = pa_xnew0(pa_thread, 1);
     t->id = pthread_self();
-    t->thread_func = NULL;
-    t->userdata = NULL;
     t->joined = TRUE;
     pa_atomic_store(&t->running, 2);
 
diff --git a/src/pulsecore/thread.h b/src/pulsecore/thread.h
index 25eace6..60c1267 100644
--- a/src/pulsecore/thread.h
+++ b/src/pulsecore/thread.h
@@ -55,7 +55,7 @@ void *pa_tls_set(pa_tls *t, void *userdata);
 #define PA_STATIC_TLS_DECLARE(name, free_cb)                            \
     static struct {                                                     \
         pa_once once;                                                   \
-        pa_tls *tls;                                                    \
+        pa_tls *volatile tls;                                           \
     } name##_tls = {                                                    \
         .once = PA_ONCE_INIT,                                           \
         .tls = NULL                                                     \

commit 41ce7cbde9e3f936c134e3982e5587ce831d04de
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 13 17:24:37 2010 +0100

    bluetooth: fix invalid memory access
    
    When an GetProperties() reply arrives after we already deleted the
    device structure for it make sure we don't accidentaly touch the
    invalidated object.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=543205

diff --git a/src/modules/bluetooth/bluetooth-util.c b/src/modules/bluetooth/bluetooth-util.c
index 795d510..b2c0429 100644
--- a/src/modules/bluetooth/bluetooth-util.c
+++ b/src/modules/bluetooth/bluetooth-util.c
@@ -342,7 +342,13 @@ static void get_properties_reply(DBusPendingCall *pending, void *userdata) {
 /*                  dbus_message_get_interface(p->message), */
 /*                  dbus_message_get_path(p->message)); */
 
-    d = p->call_data;
+    /* We don't use p->call_data here right-away since the device
+     * might already be invalidated at this point */
+
+    if (!(d = pa_hashmap_get(y->devices, dbus_message_get_path(p->message))))
+        return;
+
+    pa_assert(p->call_data == d);
 
     valid = dbus_message_get_type(r) == DBUS_MESSAGE_TYPE_ERROR ? -1 : 1;
 

commit f732c23d9504e16b4412755fc11e692e2f4dbacc
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 13 17:35:04 2010 +0100

    log: add an easy way to disable log rate limiting
    
    Should help with debuggin bugs like:
    
    https://bugzilla.redhat.com/show_bug.cgi?id=554405

diff --git a/src/pulsecore/log.c b/src/pulsecore/log.c
index 8c21ee6..0c5a317 100644
--- a/src/pulsecore/log.c
+++ b/src/pulsecore/log.c
@@ -61,6 +61,7 @@
 #define ENV_LOG_PRINT_LEVEL "PULSE_LOG_LEVEL"
 #define ENV_LOG_BACKTRACE "PULSE_LOG_BACKTRACE"
 #define ENV_LOG_BACKTRACE_SKIP "PULSE_LOG_BACKTRACE_SKIP"
+#define ENV_LOG_NO_RATELIMIT "PULSE_LOG_NO_RATE_LIMIT"
 
 static char *ident = NULL; /* in local charset format */
 static pa_log_target_t target = PA_LOG_STDERR, target_override;
@@ -68,6 +69,7 @@ static pa_bool_t target_override_set = FALSE;
 static pa_log_level_t maximum_level = PA_LOG_ERROR, maximum_level_override = PA_LOG_ERROR;
 static unsigned show_backtrace = 0, show_backtrace_override = 0, skip_backtrace = 0;
 static pa_log_flags_t flags = 0, flags_override = 0;
+static pa_bool_t no_rate_limit = FALSE;
 
 #ifdef HAVE_SYSLOG_H
 static const int level_to_syslog[] = {
@@ -195,54 +197,61 @@ static char* get_backtrace(unsigned show_nframes) {
 #endif
 
 static void init_defaults(void) {
-    const char *e;
+    PA_ONCE_BEGIN {
 
-    if (!ident) {
-        char binary[256];
-        if (pa_get_binary_name(binary, sizeof(binary)))
-            pa_log_set_ident(binary);
-    }
+        const char *e;
 
-    if (getenv(ENV_LOG_SYSLOG)) {
-        target_override = PA_LOG_SYSLOG;
-        target_override_set = TRUE;
-    }
+        if (!ident) {
+            char binary[256];
+            if (pa_get_binary_name(binary, sizeof(binary)))
+                pa_log_set_ident(binary);
+        }
 
-    if ((e = getenv(ENV_LOG_LEVEL))) {
-        maximum_level_override = (pa_log_level_t) atoi(e);
+        if (getenv(ENV_LOG_SYSLOG)) {
+            target_override = PA_LOG_SYSLOG;
+            target_override_set = TRUE;
+        }
 
-        if (maximum_level_override >= PA_LOG_LEVEL_MAX)
-            maximum_level_override = PA_LOG_LEVEL_MAX-1;
-    }
+        if ((e = getenv(ENV_LOG_LEVEL))) {
+            maximum_level_override = (pa_log_level_t) atoi(e);
 
-    if (getenv(ENV_LOG_COLORS))
-        flags_override |= PA_LOG_COLORS;
+            if (maximum_level_override >= PA_LOG_LEVEL_MAX)
+                maximum_level_override = PA_LOG_LEVEL_MAX-1;
+        }
 
-    if (getenv(ENV_LOG_PRINT_TIME))
-        flags_override |= PA_LOG_PRINT_TIME;
+        if (getenv(ENV_LOG_COLORS))
+            flags_override |= PA_LOG_COLORS;
 
-    if (getenv(ENV_LOG_PRINT_FILE))
-        flags_override |= PA_LOG_PRINT_FILE;
+        if (getenv(ENV_LOG_PRINT_TIME))
+            flags_override |= PA_LOG_PRINT_TIME;
 
-    if (getenv(ENV_LOG_PRINT_META))
-        flags_override |= PA_LOG_PRINT_META;
+        if (getenv(ENV_LOG_PRINT_FILE))
+            flags_override |= PA_LOG_PRINT_FILE;
 
-    if (getenv(ENV_LOG_PRINT_LEVEL))
-        flags_override |= PA_LOG_PRINT_LEVEL;
+        if (getenv(ENV_LOG_PRINT_META))
+            flags_override |= PA_LOG_PRINT_META;
 
-    if ((e = getenv(ENV_LOG_BACKTRACE))) {
-        show_backtrace_override = (unsigned) atoi(e);
+        if (getenv(ENV_LOG_PRINT_LEVEL))
+            flags_override |= PA_LOG_PRINT_LEVEL;
 
-        if (show_backtrace_override <= 0)
-            show_backtrace_override = 0;
-    }
+        if ((e = getenv(ENV_LOG_BACKTRACE))) {
+            show_backtrace_override = (unsigned) atoi(e);
 
-    if ((e = getenv(ENV_LOG_BACKTRACE_SKIP))) {
-        skip_backtrace = (unsigned) atoi(e);
+            if (show_backtrace_override <= 0)
+                show_backtrace_override = 0;
+        }
 
-        if (skip_backtrace <= 0)
-            skip_backtrace = 0;
-    }
+        if ((e = getenv(ENV_LOG_BACKTRACE_SKIP))) {
+            skip_backtrace = (unsigned) atoi(e);
+
+            if (skip_backtrace <= 0)
+                skip_backtrace = 0;
+        }
+
+        if (getenv(ENV_LOG_NO_RATELIMIT))
+            no_rate_limit = TRUE;
+
+    } PA_ONCE_END;
 }
 
 void pa_log_levelv_meta(
@@ -268,9 +277,7 @@ void pa_log_levelv_meta(
     pa_assert(level < PA_LOG_LEVEL_MAX);
     pa_assert(format);
 
-    PA_ONCE_BEGIN {
-        init_defaults();
-    } PA_ONCE_END;
+    init_defaults();
 
     _target = target_override_set ? target_override : target;
     _maximum_level = PA_MAX(maximum_level, maximum_level_override);
@@ -428,5 +435,10 @@ pa_bool_t pa_log_ratelimit(void) {
     /* Not more than 10 messages every 5s */
     static PA_DEFINE_RATELIMIT(ratelimit, 5 * PA_USEC_PER_SEC, 10);
 
+    init_defaults();
+
+    if (no_rate_limit)
+        return TRUE;
+
     return pa_ratelimit_test(&ratelimit);
 }

commit ce7bd05ca50c946ea6b3ec9a9dcb9bfd7e90ac5e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 13 19:41:44 2010 +0100

    udev: make sure we get events only for sound devices

diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
index dfd13ee..9b1fdb0 100644
--- a/src/modules/module-udev-detect.c
+++ b/src/modules/module-udev-detect.c
@@ -639,6 +639,11 @@ int pa__init(pa_module *m) {
         goto fail;
     }
 
+    if (udev_monitor_filter_add_match_subsystem_devtype(u->monitor, "sound", NULL) < 0) {
+        pa_log("Failed to subscribe to sound devices.");
+        goto fail;
+    }
+
     errno = 0;
     if (udev_monitor_enable_receiving(u->monitor) < 0) {
         pa_log("Failed to enable monitor: %s", pa_cstrerror(errno));

commit c88e4680f050a6ac65335b1d8148287cc4566b00
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 13 20:30:36 2010 +0100

    alsa: ignore volume changes from the hw if we are not on the active console

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index ed16c83..690480f 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1103,6 +1103,9 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
     if (mask == SND_CTL_EVENT_MASK_REMOVE)
         return 0;
 
+    if (u->sink->suspend_cause & PA_SUSPEND_SESSION)
+        return 0;
+
     if (mask & SND_CTL_EVENT_MASK_VALUE) {
         pa_sink_get_volume(u->sink, TRUE);
         pa_sink_get_mute(u->sink, TRUE);
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 157698e..f8b583e 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1051,6 +1051,9 @@ static int mixer_callback(snd_mixer_elem_t *elem, unsigned int mask) {
     if (mask == SND_CTL_EVENT_MASK_REMOVE)
         return 0;
 
+    if (u->source->suspend_cause & PA_SUSPEND_SESSION)
+        return 0;
+
     if (mask & SND_CTL_EVENT_MASK_VALUE) {
         pa_source_get_volume(u->source, TRUE);
         pa_source_get_mute(u->source, TRUE);

commit 54025c96a7133964aa1568fe6d2e6c5ad05651bf
Author: Lennart Poettering <lennart at poettering.net>
Date:   Wed Jan 13 20:31:17 2010 +0100

    cpu: check for CMOV flag before using this intsruction in assembly
    
    http://pulseaudio.org/ticket/776

diff --git a/src/pulsecore/cpu-x86.c b/src/pulsecore/cpu-x86.c
index f194a60..b173072 100644
--- a/src/pulsecore/cpu-x86.c
+++ b/src/pulsecore/cpu-x86.c
@@ -57,6 +57,9 @@ void pa_cpu_init_x86 (void) {
     if (level >= 1) {
         get_cpuid (0x00000001, &eax, &ebx, &ecx, &edx);
 
+        if (edx & (1<<15))
+          flags |= PA_CPU_X86_CMOV;
+
         if (edx & (1<<23))
           flags |= PA_CPU_X86_MMX;
 
@@ -97,7 +100,8 @@ void pa_cpu_init_x86 (void) {
           flags |= PA_CPU_X86_3DNOW;
     }
 
-    pa_log_info ("CPU flags: %s%s%s%s%s%s%s%s%s%s",
+    pa_log_info ("CPU flags: %s%s%s%s%s%s%s%s%s%s%s",
+    (flags & PA_CPU_X86_CMOV) ? "CMOV " : "",
     (flags & PA_CPU_X86_MMX) ? "MMX " : "",
     (flags & PA_CPU_X86_SSE) ? "SSE " : "",
     (flags & PA_CPU_X86_SSE2) ? "SSE2 " : "",
diff --git a/src/pulsecore/cpu-x86.h b/src/pulsecore/cpu-x86.h
index f6484c5..285c203 100644
--- a/src/pulsecore/cpu-x86.h
+++ b/src/pulsecore/cpu-x86.h
@@ -35,12 +35,12 @@ typedef enum pa_cpu_x86_flag {
     PA_CPU_X86_SSE4_1    = (1 << 6),
     PA_CPU_X86_SSE4_2    = (1 << 7),
     PA_CPU_X86_3DNOW     = (1 << 8),
-    PA_CPU_X86_3DNOWEXT  = (1 << 9)
+    PA_CPU_X86_3DNOWEXT  = (1 << 9),
+    PA_CPU_X86_CMOV      = (1 << 10)
 } pa_cpu_x86_flag_t;
 
 void pa_cpu_init_x86 (void);
 
-
 #if defined (__i386__)
 typedef int32_t pa_reg_x86;
 #define PA_REG_a "eax"
diff --git a/src/pulsecore/svolume_mmx.c b/src/pulsecore/svolume_mmx.c
index a011789..0e222cd 100644
--- a/src/pulsecore/svolume_mmx.c
+++ b/src/pulsecore/svolume_mmx.c
@@ -309,7 +309,7 @@ void pa_volume_func_init_mmx (pa_cpu_x86_flag_t flags) {
     run_test ();
 #endif
 
-    if (flags & PA_CPU_X86_MMX) {
+    if ((flags & PA_CPU_X86_MMX) && (flags & PA_CPU_X86_CMOV)) {
         pa_log_info("Initialising MMX optimized functions.");
 
         pa_set_volume_func (PA_SAMPLE_S16NE, (pa_do_volume_func_t) pa_volume_s16ne_mmx);

commit 7f6531d3ce15fd46f75cafa61f9896d2adf6fe94
Author: Colin Guthrie <cguthrie at mandriva.org>
Date:   Wed Jan 13 23:44:00 2010 +0000

    alsa: cover Input Source:Int Mic
    
    As seen on some HDA chips (e.g. Fujitsu Siemens S6410)
    Refs http://pulseaudio.org/ticket/772

diff --git a/src/modules/alsa/mixer/paths/analog-input.conf.common b/src/modules/alsa/mixer/paths/analog-input.conf.common
index 951e11f..fbdc8fb 100644
--- a/src/modules/alsa/mixer/paths/analog-input.conf.common
+++ b/src/modules/alsa/mixer/paths/analog-input.conf.common
@@ -78,6 +78,10 @@ priority = 19
 name = input-microphone
 priority = 19
 
+[Option Input Source:Int Mic]
+name = input-microphone
+priority = 19
+
 [Option Input Source:Internal Mic]
 name = input-microphone
 priority = 19

commit 7b89c8531c1bde251f2c9f247bf65bd1b20ce9c9
Author: Colin Guthrie <cguthrie at mandriva.org>
Date:   Wed Jan 13 23:47:21 2010 +0000

    alsa: Cover the 'Int Mic Boost' element.
    
    This is not 100% ideal as we have not way to tie specific boosts to specific
    inputs and this particular chipset (as noted in #772) appears to
    support just that.
    
    For the time being incorporate it into the normal boost logic.
    
    See http://pulseaudio.org/ticket/772

diff --git a/src/modules/alsa/mixer/paths/analog-input-mic.conf.common b/src/modules/alsa/mixer/paths/analog-input-mic.conf.common
index b35e7af..4663305 100644
--- a/src/modules/alsa/mixer/paths/analog-input-mic.conf.common
+++ b/src/modules/alsa/mixer/paths/analog-input-mic.conf.common
@@ -61,3 +61,12 @@ name = input-boost-on
 
 [Option Front Mic Boost:off]
 name = input-boost-off
+
+[Element Int Mic Boost]
+switch = select
+
+[Option Int Mic Boost:on]
+name = input-boost-on
+
+[Option Int Mic Boost:off]
+name = input-boost-off

commit c2ab61c54d8b9d9a18a56ce873debf530c7f6d4a
Author: Daniel T. Chen <crimsun at ubuntu.com>
Date:   Thu Jan 14 00:57:27 2010 +0100

    udev: handle sound cards with both modem and audio properly
    
    http://pulseaudio.org/ticket/681
    https://bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/394500

diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
index 9b1fdb0..4019cd8 100644
--- a/src/modules/module-udev-detect.c
+++ b/src/modules/module-udev-detect.c
@@ -103,13 +103,17 @@ static const char *path_get_card_id(const char *path) {
     return e + 5;
 }
 
+static const char *pa_udev_get_sysattr(const char *card_idx, const char *name);
+
 static pa_bool_t is_card_busy(const char *id) {
-    char *card_path = NULL, *pcm_path = NULL, *sub_status = NULL;
+    const char *pcm_class;
+    char *card_path = NULL, *pcm_path = NULL, *sub_status = NULL,
+         *sysfs_path = NULL;
     DIR *card_dir = NULL, *pcm_dir = NULL;
     FILE *status_file = NULL;
     size_t len;
     struct dirent *space = NULL, *de;
-    pa_bool_t busy = FALSE;
+    pa_bool_t busy = FALSE, is_modem = FALSE;
     int r;
 
     pa_assert(id);
@@ -127,6 +131,17 @@ static pa_bool_t is_card_busy(const char *id) {
     len = offsetof(struct dirent, d_name) + fpathconf(dirfd(card_dir), _PC_NAME_MAX) + 1;
     space = pa_xmalloc(len);
 
+    /* Also check /sys/class/sound/card.../pcmC...D6p/pcm_class. An HDA
+     * modem can be used simultaneously with generic playback/record. */
+
+    pa_xfree(sysfs_path);
+    sysfs_path = pa_sprintf_malloc("pcmC%sD6p/pcm_class", id);
+
+    pcm_class = pa_udev_get_sysattr(id, sysfs_path);
+
+    if (pcm_class && pa_streq(pcm_class, "modem"))
+        is_modem = TRUE;
+
     for (;;) {
         de = NULL;
 
@@ -182,7 +197,7 @@ static pa_bool_t is_card_busy(const char *id) {
                 continue;
             }
 
-            if (!pa_streq(line, "closed\n")) {
+            if (!is_modem && !pa_streq(line, "closed\n")) {
                 busy = TRUE;
                 break;
             }
@@ -193,6 +208,7 @@ fail:
 
     pa_xfree(card_path);
     pa_xfree(pcm_path);
+    pa_xfree(sysfs_path);
     pa_xfree(sub_status);
     pa_xfree(space);
 
@@ -594,6 +610,43 @@ static int setup_inotify(struct userdata *u) {
     return 0;
 }
 
+static const char *pa_udev_get_sysattr(const char *card_idx, const char *name) {
+    struct udev *udev;
+    struct udev_device *card = NULL;
+    char *t, *r = NULL;
+    const char *v;
+
+    pa_assert(card_idx);
+    pa_assert(name);
+
+    if (!(udev = udev_new())) {
+        pa_log_error("Failed to allocate udev context.");
+        goto finish;
+    }
+
+    t = pa_sprintf_malloc("%s/class/sound/card%s", udev_get_sys_path(udev), card_idx);
+    card = udev_device_new_from_syspath(udev, t);
+    pa_xfree(t);
+
+    if (!card) {
+        pa_log_error("Failed to get card object.");
+        goto finish;
+    }
+
+    if ((v = udev_device_get_sysattr_value(card, name)) && *v)
+        r = pa_xstrdup(v);
+
+finish:
+
+    if (card)
+        udev_device_unref(card);
+
+    if (udev)
+        udev_unref(udev);
+
+    return r;
+}
+
 int pa__init(pa_module *m) {
     struct userdata *u = NULL;
     pa_modargs *ma;

commit 63ebd054644f009631e25ad68e93a70415cd0c0c
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 14 02:06:52 2010 +0100

    udev: rework modem detection a bit
    
    Check every single pcm device of a card whether it is a modem.

diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
index 4019cd8..7695d3c 100644
--- a/src/modules/module-udev-detect.c
+++ b/src/modules/module-udev-detect.c
@@ -103,17 +103,70 @@ static const char *path_get_card_id(const char *path) {
     return e + 5;
 }
 
-static const char *pa_udev_get_sysattr(const char *card_idx, const char *name);
+static char *card_get_sysattr(const char *card_idx, const char *name) {
+    struct udev *udev;
+    struct udev_device *card = NULL;
+    char *t, *r = NULL;
+    const char *v;
+
+    pa_assert(card_idx);
+    pa_assert(name);
+
+    if (!(udev = udev_new())) {
+        pa_log_error("Failed to allocate udev context.");
+        goto finish;
+    }
+
+    t = pa_sprintf_malloc("%s/class/sound/card%s", udev_get_sys_path(udev), card_idx);
+    card = udev_device_new_from_syspath(udev, t);
+    pa_xfree(t);
+
+    if (!card) {
+        pa_log_error("Failed to get card object.");
+        goto finish;
+    }
+
+    if ((v = udev_device_get_sysattr_value(card, name)) && *v)
+        r = pa_xstrdup(v);
+
+finish:
+
+    if (card)
+        udev_device_unref(card);
+
+    if (udev)
+        udev_unref(udev);
+
+    return r;
+}
+
+static pa_bool_t pcm_is_modem(const char *card_idx, const char *pcm) {
+    char *sysfs_path, *pcm_class;
+    pa_bool_t is_modem;
+
+    pa_assert(card_idx);
+    pa_assert(pcm);
+
+    /* Check /sys/class/sound/card.../pcmC...../pcm_class. An HDA
+     * modem can be used simultaneously with generic
+     * playback/record. */
+
+    sysfs_path = pa_sprintf_malloc("pcmC%sD%s/pcm_class", card_idx, pcm);
+    pcm_class = card_get_sysattr(card_idx, sysfs_path);
+    is_modem = pcm_class && pa_streq(pcm_class, "modem");
+    pa_xfree(pcm_class);
+    pa_xfree(sysfs_path);
+
+    return is_modem;
+}
 
 static pa_bool_t is_card_busy(const char *id) {
-    const char *pcm_class;
-    char *card_path = NULL, *pcm_path = NULL, *sub_status = NULL,
-         *sysfs_path = NULL;
+    char *card_path = NULL, *pcm_path = NULL, *sub_status = NULL;
     DIR *card_dir = NULL, *pcm_dir = NULL;
     FILE *status_file = NULL;
     size_t len;
     struct dirent *space = NULL, *de;
-    pa_bool_t busy = FALSE, is_modem = FALSE;
+    pa_bool_t busy = FALSE;
     int r;
 
     pa_assert(id);
@@ -131,17 +184,6 @@ static pa_bool_t is_card_busy(const char *id) {
     len = offsetof(struct dirent, d_name) + fpathconf(dirfd(card_dir), _PC_NAME_MAX) + 1;
     space = pa_xmalloc(len);
 
-    /* Also check /sys/class/sound/card.../pcmC...D6p/pcm_class. An HDA
-     * modem can be used simultaneously with generic playback/record. */
-
-    pa_xfree(sysfs_path);
-    sysfs_path = pa_sprintf_malloc("pcmC%sD6p/pcm_class", id);
-
-    pcm_class = pa_udev_get_sysattr(id, sysfs_path);
-
-    if (pcm_class && pa_streq(pcm_class, "modem"))
-        is_modem = TRUE;
-
     for (;;) {
         de = NULL;
 
@@ -156,6 +198,9 @@ static pa_bool_t is_card_busy(const char *id) {
         if (!pa_startswith(de->d_name, "pcm"))
             continue;
 
+        if (pcm_is_modem(id, de->d_name + 3))
+            continue;
+
         pa_xfree(pcm_path);
         pcm_path = pa_sprintf_malloc("%s/%s", card_path, de->d_name);
 
@@ -197,7 +242,7 @@ static pa_bool_t is_card_busy(const char *id) {
                 continue;
             }
 
-            if (!is_modem && !pa_streq(line, "closed\n")) {
+            if (!pa_streq(line, "closed\n")) {
                 busy = TRUE;
                 break;
             }
@@ -208,7 +253,6 @@ fail:
 
     pa_xfree(card_path);
     pa_xfree(pcm_path);
-    pa_xfree(sysfs_path);
     pa_xfree(sub_status);
     pa_xfree(space);
 
@@ -610,43 +654,6 @@ static int setup_inotify(struct userdata *u) {
     return 0;
 }
 
-static const char *pa_udev_get_sysattr(const char *card_idx, const char *name) {
-    struct udev *udev;
-    struct udev_device *card = NULL;
-    char *t, *r = NULL;
-    const char *v;
-
-    pa_assert(card_idx);
-    pa_assert(name);
-
-    if (!(udev = udev_new())) {
-        pa_log_error("Failed to allocate udev context.");
-        goto finish;
-    }
-
-    t = pa_sprintf_malloc("%s/class/sound/card%s", udev_get_sys_path(udev), card_idx);
-    card = udev_device_new_from_syspath(udev, t);
-    pa_xfree(t);
-
-    if (!card) {
-        pa_log_error("Failed to get card object.");
-        goto finish;
-    }
-
-    if ((v = udev_device_get_sysattr_value(card, name)) && *v)
-        r = pa_xstrdup(v);
-
-finish:
-
-    if (card)
-        udev_device_unref(card);
-
-    if (udev)
-        udev_unref(udev);
-
-    return r;
-}
-
 int pa__init(pa_module *m) {
     struct userdata *u = NULL;
     pa_modargs *ma;

commit 4315f277bcdb89d2e17c7bf9bd5ac0c2b9b3aa6e
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 14 02:53:50 2010 +0100

    alsa: cover bass boost mixer element
    
    http://pulseaudio.org/ticket/740

diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 8b13239..8bbd1f5 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -1713,6 +1713,8 @@ static int option_verify(pa_alsa_option *o) {
         { "input-boost-off",           N_("No Boost") },
         { "output-amplifier-on",       N_("Amplifier") },
         { "output-amplifier-off",      N_("No Amplifier") },
+        { "output-bass-boost-on",      N_("Bass Boost") },
+        { "output-bass-boost-off",     N_("No Bass Boost") },
         { "output-speaker",            N_("Speaker") },
         { "output-headphones",         N_("Headphones") }
     };
diff --git a/src/modules/alsa/mixer/paths/analog-output.conf.common b/src/modules/alsa/mixer/paths/analog-output.conf.common
index fd7f0cf..6131da5 100644
--- a/src/modules/alsa/mixer/paths/analog-output.conf.common
+++ b/src/modules/alsa/mixer/paths/analog-output.conf.common
@@ -110,6 +110,17 @@ priority = 10
 name = output-amplifier-off
 priority = 0
 
+[Element Bass Boost]
+switch = select
+
+[Option Bass Boost:on]
+name = output-bass-boost-on
+priority = 0
+
+[Option Bass Boost:off]
+name = output-bass-boost-off
+priority = 10
+
 ;;; 'Analog Output'
 
 [Element Analog Output]

commit 544fa0b7dbc5ba5684f2a4dac7dbc7eebb74afc6
Author: Lennart Poettering <lennart at poettering.net>
Date:   Thu Jan 14 20:31:00 2010 +0100

    udev: use ID_MODEL_ENC instead of ID_MODEL if it is set
    
    That way we should be able to make use of the nicer USB strings the USB
    hw provides.
    
    Fixes the issues pointed out in:
    
    https://tango.0pointer.de/pipermail/pulseaudio-discuss/2010-January/006248.html

diff --git a/src/modules/udev-util.c b/src/modules/udev-util.c
index cc82446..eee5409 100644
--- a/src/modules/udev-util.c
+++ b/src/modules/udev-util.c
@@ -58,6 +58,112 @@ static int read_id(struct udev_device *d, const char *n) {
     return u;
 }
 
+static int dehex(char x) {
+    if (x >= '0' && x <= '9')
+        return x - '0';
+
+    if (x >= 'A' && x <= 'F')
+        return x - 'A';
+
+    if (x >= 'a' && x <= 'f')
+        return x - 'a';
+
+    return -1;
+}
+
+static void proplist_sets_unescape(pa_proplist *p, const char *prop, const char *s) {
+    const char *f;
+    char *t, *r;
+    int c;
+
+    enum {
+        TEXT,
+        BACKSLASH,
+        EX,
+        FIRST
+    } state = TEXT;
+
+    /* The resulting string is definitely shorter than the source string */
+    r = pa_xnew(char, strlen(s)+1);
+
+    for (f = s, t = r; *f; f++) {
+
+        switch (state) {
+
+            case TEXT:
+                if (*f == '\\')
+                    state = BACKSLASH;
+                else
+                    *(t++) = *f;
+                break;
+
+            case BACKSLASH:
+                if (*f == 'x')
+                    state = EX;
+                else {
+                    *(t++) = '\\';
+                    *(t++) = *f;
+                    state = TEXT;
+                }
+                break;
+
+            case EX:
+                c = dehex(*f);
+
+                if (c < 0) {
+                    *(t++) = '\\';
+                    *(t++) = 'x';
+                    *(t++) = *f;
+                    state = TEXT;
+                } else
+                    state = FIRST;
+
+                break;
+
+            case FIRST: {
+                int d = dehex(*f);
+
+                if (d < 0) {
+                    *(t++) = '\\';
+                    *(t++) = 'x';
+                    *(t++) = *(f-1);
+                    *(t++) = *f;
+                } else
+                    *(t++) = (char) (c << 4) | d;
+
+                state = TEXT;
+                break;
+            }
+        }
+    }
+
+    switch (state) {
+
+        case TEXT:
+            break;
+
+        case BACKSLASH:
+            *(t++) = '\\';
+            break;
+
+        case EX:
+            *(t++) = '\\';
+            *(t++) = 'x';
+            break;
+
+        case FIRST:
+            *(t++) = '\\';
+            *(t++) = 'x';
+            *(t++) = *(f-1);
+            break;
+    }
+
+    *t = 0;
+
+    pa_proplist_sets(p, prop, r);
+    pa_xfree(r);
+}
+
 int pa_udev_get_info(int card_idx, pa_proplist *p) {
     int r = -1;
     struct udev *udev;
@@ -107,6 +213,8 @@ int pa_udev_get_info(int card_idx, pa_proplist *p) {
     if (!pa_proplist_contains(p, PA_PROP_DEVICE_VENDOR_NAME)) {
         if ((v = udev_device_get_property_value(card, "ID_VENDOR_FROM_DATABASE")) && *v)
             pa_proplist_sets(p, PA_PROP_DEVICE_VENDOR_NAME, v);
+        else if ((v = udev_device_get_property_value(card, "ID_VENDOR_ENC")) && *v)
+            proplist_sets_unescape(p, PA_PROP_DEVICE_VENDOR_NAME, v);
         else if ((v = udev_device_get_property_value(card, "ID_VENDOR")) && *v)
             pa_proplist_sets(p, PA_PROP_DEVICE_VENDOR_NAME, v);
     }
@@ -118,6 +226,8 @@ int pa_udev_get_info(int card_idx, pa_proplist *p) {
     if (!pa_proplist_contains(p, PA_PROP_DEVICE_PRODUCT_NAME)) {
         if ((v = udev_device_get_property_value(card, "ID_MODEL_FROM_DATABASE")) && *v)
             pa_proplist_sets(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
+        else if ((v = udev_device_get_property_value(card, "ID_MODEL_ENC")) && *v)
+            proplist_sets_unescape(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
         else if ((v = udev_device_get_property_value(card, "ID_MODEL")) && *v)
             pa_proplist_sets(p, PA_PROP_DEVICE_PRODUCT_NAME, v);
     }

commit fb55798a3eb73b4c00225232408b766f74533409
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 15 01:25:21 2010 +0100

    pacat: allow configuration of latency in msec

diff --git a/man/pacat.1.xml.in b/man/pacat.1.xml.in
index 68a3a12..2e27450 100644
--- a/man/pacat.1.xml.in
+++ b/man/pacat.1.xml.in
@@ -21,18 +21,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 USA.
 -->
 
-<manpage name="pacat" section="1" desc="Play back or record raw audio streams on a PulseAudio sound server">
+<manpage name="pacat" section="1" desc="Play back or record raw or encoded audio streams on a PulseAudio sound server">
 
   <synopsis>
+    <cmd>paplay [<arg>options</arg>] [<arg>FILE</arg>]</cmd>
+    <cmd>parecord [<arg>options</arg>] [<arg>FILE</arg>]</cmd>
     <cmd>pacat [<arg>options</arg>] [<arg>FILE</arg>]</cmd>
     <cmd>parec [<arg>options</arg>] [<arg>FILE</arg>]</cmd>
-    <cmd>paplay <opt>--help</opt></cmd>
-    <cmd>paplay <opt>--version</opt></cmd>
+    <cmd>pamon [<arg>options</arg>] [<arg>FILE</arg>]</cmd>
+    <cmd>pacat <opt>--help</opt></cmd>
+    <cmd>pacat <opt>--version</opt></cmd>
   </synopsis>
 
   <description>
     <p><file>pacat</file> is a simple tool for playing back or
-    capturing raw audio files on a PulseAudio sound server.</p>
+    capturing raw or encoded audio files on a PulseAudio sound
+    server.</p>
   </description>
 
   <options>
@@ -52,13 +56,13 @@ USA.
     <option>
       <p><opt>-r | --record</opt></p>
 
-      <optdesc><p>Capture raw audio data and write it to the specified file or to STDOUT if none is specified. If the tool is called under the name <file>parec</file> this is the default.</p></optdesc>
+      <optdesc><p>Capture audio data and write it to the specified file or to STDOUT if none is specified. If the tool is called under the name <file>parec</file> this is the default.</p></optdesc>
     </option>
 
     <option>
       <p><opt>-p | --playback</opt></p>
 
-      <optdesc><p>Read raw audio data from the specified file or STDIN if none is specified, and play it back. If the tool is called under the name <file>pacat</file> this is the default.</p></optdesc>
+      <optdesc><p>Read audio data from the specified file or STDIN if none is specified, and play it back. If the tool is called under the name <file>pacat</file> this is the default.</p></optdesc>
     </option>
 
     <option>
@@ -108,14 +112,17 @@ USA.
 
       <optdesc><p>Capture or play back audio with the specified sample
       format. Specify one of <opt>u8</opt>, <opt>s16le</opt>,
-      <opt>s16be</opt>, <opt>s32le</opt>,
-      <opt>s32be</opt>, <opt>float32le</opt>, <opt>float32be</opt>,
-      <opt>ulaw</opt>, <opt>alaw</opt>. Depending on the endianess of
-      the CPU the
-      formats <opt>s16ne</opt>, <opt>s16re</opt>, <opt>s32ne</opt>, <opt>s32re</opt>,
-      <opt>float32ne</opt>, <opt>float32re</opt> (for native,
-      resp. reverse endian) are available as aliases. Defaults to
-      s16ne.</p></optdesc>
+      <opt>s16be</opt>, <opt>s32le</opt>, <opt>s32be</opt>,
+      <opt>float32le</opt>, <opt>float32be</opt>, <opt>ulaw</opt>,
+      <opt>alaw</opt>, <opt>s32le</opt>, <opt>s32be</opt>,
+      <opt>s24le</opt>, <opt>s24be</opt>, <opt>s24-32le</opt>,
+      <opt>s24-32be</opt>. Depending on the endianess of the CPU the
+      formats <opt>s16ne</opt>, <opt>s16re</opt>, <opt>s32ne</opt>,
+      <opt>s32re</opt>, <opt>float32ne</opt>, <opt>float32re</opt>,
+      <opt>s32ne</opt>, <opt>s32re</opt>, <opt>s24ne</opt>,
+      <opt>s24re</opt>, <opt>s24-32ne</opt>, <opt>s24-32re</opt> (for
+      native, resp. reverse endian) are available as aliases. Defaults
+      to s16ne.</p></optdesc>
     </option>
 
     <option>
@@ -170,6 +177,65 @@ USA.
       <optdesc><p>Never remap channels. Instead of mapping channels by their name this will match them solely by their index/order.</p></optdesc>
     </option>
 
+    <option>
+      <p><opt>--latency</opt><arg>=BYTES</arg></p>
+      <optdesc><p>Explicitly configure the latency, with a time
+      specified in bytes in the selected sample format. If left out
+      the server will pick the latency, usually relatively high for
+      power saving reasons. Use either this option or
+      <opt>--latency-msec</opt>, but not both.</p></optdesc>
+    </option>
+
+    <option>
+      <p><opt>--latency-msec</opt><arg>=MSEC</arg></p>
+      <optdesc><p>Explicitly configure the latency, with a time
+      specified in miliseconds. If left out the server will pick the
+      latency, usually relatively high for power saving reasons. Use
+      either this option or <opt>--latency</opt>, but not
+      both.</p></optdesc>
+    </option>
+
+    <option>
+      <p><opt>--process-time</opt><arg>=BYTES</arg></p>
+      <optdesc><p>Explicitly configure the process time, with a time
+      specified in bytes in the selected sample format. If left out
+      the server will pick the process time. Use either this option or
+      <opt>--process-time-msec</opt>, but not both.</p></optdesc>
+    </option>
+
+    <option>
+      <p><opt>--process-time-msec</opt><arg>=MSEC</arg></p>
+      <optdesc><p>Explicitly configure the process time, with a time
+      specified in miliseconds. If left out the server will pick the
+      process time. Use either this option or <opt>--process-time</opt>,
+      but not both.</p></optdesc>
+    </option>
+
+    <option>
+      <p><opt>--property</opt><arg>=PROPERTY=VALUE</arg></p>
+      <optdesc><p>Attach a property to the client and stream. May be
+      used multiple times</p></optdesc>
+    </option>
+
+    <option>
+      <p><opt>--raw</opt></p>
+      <optdesc><p>Play/record raw audio data. This is the default if
+      this program is invoked as <cmd>pacat</cmd>, <cmd>parec</cmd> or
+      <cmd>pamon</cmd>.</p></optdesc>
+    </option>
+
+    <option>
+      <p><opt>--file-format</opt><arg>[=FFORMAT]</arg></p>
+      <optdesc><p>Play/record encoded audio data in the file format
+      specified. This is the default if this program is invoked as
+      <cmd>paplay</cmd> and <cmd>parecord</cmd>.</p></optdesc>
+    </option>
+
+    <option>
+      <p><opt>--list-file-formats</opt></p>
+      <optdesc><p>List supported file formats.</p></optdesc>
+    </option>
+
   </options>
 
   <section name="Authors">
@@ -178,7 +244,7 @@ USA.
 
   <section name="See also">
     <p>
-      <manref name="pulseaudio" section="1"/>, <manref name="paplay" section="1"/>
+      <manref name="pulseaudio" section="1"/>, <manref name="pactl" section="1"/>
     </p>
   </section>
 
diff --git a/src/utils/pacat.c b/src/utils/pacat.c
index d348c16..1036af6 100644
--- a/src/utils/pacat.c
+++ b/src/utils/pacat.c
@@ -45,6 +45,7 @@
 #include <pulsecore/core-util.h>
 #include <pulsecore/log.h>
 #include <pulsecore/sndfile-util.h>
+#include <pulsecore/core-util.h>
 
 #define TIME_EVENT_USEC 50000
 
@@ -86,6 +87,7 @@ static sf_count_t (*writef_function)(SNDFILE *_sndfile, const void *ptr, sf_coun
 static pa_stream_flags_t flags = 0;
 
 static size_t latency = 0, process_time = 0;
+static int32_t latency_msec = 0, process_time_msec = 0;
 
 static pa_bool_t raw = TRUE;
 static int file_format = -1;
@@ -434,19 +436,25 @@ static void context_state_callback(pa_context *c, void *userdata) {
             buffer_attr.maxlength = (uint32_t) -1;
             buffer_attr.prebuf = (uint32_t) -1;
 
-            if (latency > 0) {
+            if (latency_msec > 0) {
+                buffer_attr.fragsize = buffer_attr.tlength = pa_usec_to_bytes(latency_msec * PA_USEC_PER_MSEC, &sample_spec);
+                flags |= PA_STREAM_ADJUST_LATENCY;
+            } else if (latency > 0) {
                 buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) latency;
-                buffer_attr.minreq = (uint32_t) process_time;
                 flags |= PA_STREAM_ADJUST_LATENCY;
-            } else {
-                buffer_attr.tlength = (uint32_t) -1;
+            } else
+                buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) -1;
+
+            if (process_time_msec > 0) {
+                buffer_attr.minreq = pa_usec_to_bytes(process_time_msec * PA_USEC_PER_MSEC, &sample_spec);
+            } else if (process_time > 0)
+                buffer_attr.minreq = (uint32_t) process_time;
+            else
                 buffer_attr.minreq = (uint32_t) -1;
-                buffer_attr.fragsize = (uint32_t) -1;
-            }
 
             if (mode == PLAYBACK) {
                 pa_cvolume cv;
-                if (pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL) < 0) {
+                if (pa_stream_connect_playback(stream, device, &buffer_attr, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL) < 0) {
                     pa_log(_("pa_stream_connect_playback() failed: %s"), pa_strerror(pa_context_errno(c)));
                     goto fail;
                 }
@@ -634,9 +642,11 @@ static void help(const char *argv0) {
              "      --no-remap                        Map channels by index instead of name.\n"
              "      --latency=BYTES                   Request the specified latency in bytes.\n"
              "      --process-time=BYTES              Request the specified process time per request in bytes.\n"
+             "      --latency-msec=MSEC               Request the specified latency in msec.\n"
+             "      --process-time-msec=MSEC          Request the specified process time per request in msec.\n"
              "      --property=PROPERTY=VALUE         Set the specified property to the specified value.\n"
              "      --raw                             Record/play raw PCM data.\n"
-             "      --file-format=FFORMAT             Record/play formatted PCM data.\n"
+             "      --file-format[=FFORMAT]           Record/play formatted PCM data.\n"
              "      --list-file-formats               List available file formats.\n")
            , argv0);
 }
@@ -659,7 +669,9 @@ enum {
     ARG_RAW,
     ARG_PROPERTY,
     ARG_FILE_FORMAT,
-    ARG_LIST_FILE_FORMATS
+    ARG_LIST_FILE_FORMATS,
+    ARG_LATENCY_MSEC,
+    ARG_PROCESS_TIME_MSEC
 };
 
 int main(int argc, char *argv[]) {
@@ -695,6 +707,8 @@ int main(int argc, char *argv[]) {
         {"raw",          0, NULL, ARG_RAW},
         {"file-format",  2, NULL, ARG_FILE_FORMAT},
         {"list-file-formats", 0, NULL, ARG_LIST_FILE_FORMATS},
+        {"latency-msec", 1, NULL, ARG_LATENCY_MSEC},
+        {"process-time-msec", 1, NULL, ARG_PROCESS_TIME_MSEC},
         {NULL,           0, NULL, 0}
     };
 
@@ -854,6 +868,20 @@ int main(int argc, char *argv[]) {
                 }
                 break;
 
+            case ARG_LATENCY_MSEC:
+                if (((latency_msec = (int32_t) atoi(optarg))) <= 0) {
+                    pa_log(_("Invalid latency specification '%s'"), optarg);
+                    goto quit;
+                }
+                break;
+
+            case ARG_PROCESS_TIME_MSEC:
+                if (((process_time_msec = (int32_t) atoi(optarg))) <= 0) {
+                    pa_log(_("Invalid process time specification '%s'"), optarg);
+                    goto quit;
+                }
+                break;
+
             case ARG_PROPERTY: {
                 char *t;
 

commit d09099526220fb87ac8c4f6bae298b23744d0dae
Author: Lennart Poettering <lennart at poettering.net>
Date:   Fri Jan 15 01:25:42 2010 +0100

    client: implement $PULSE_LATENCY_MSEC
    
    This allows easy overriding of a clients latency setting for debugging
    purposes.
    
    http://pulseaudio.org/ticket/753

diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index a4f34d9..5e42ab2 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -39,6 +39,7 @@
 #include <pulsecore/hashmap.h>
 #include <pulsecore/macro.h>
 #include <pulsecore/core-rtclock.h>
+#include <pulsecore/core-util.h>
 
 #include "fork-detect.h"
 #include "internal.h"
@@ -855,10 +856,28 @@ static void create_stream_complete(pa_stream *s) {
     check_smoother_status(s, TRUE, FALSE, FALSE);
 }
 
-static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_sample_spec *ss) {
+static void patch_buffer_attr(pa_stream *s, pa_buffer_attr *attr, pa_stream_flags_t *flags) {
+    const char *e;
+
     pa_assert(s);
     pa_assert(attr);
-    pa_assert(ss);
+
+    if ((e = getenv("PULSE_LATENCY_MSEC"))) {
+        uint32_t ms;
+
+        if (pa_atou(e, &ms) < 0 || ms <= 0)
+            pa_log_debug("Failed to parse $PULSE_LATENCY_MSEC: %s", e);
+        else {
+            attr->maxlength = (uint32_t) -1;
+            attr->tlength = pa_usec_to_bytes(ms * PA_USEC_PER_MSEC, &s->sample_spec);
+            attr->minreq = (uint32_t) -1;
+            attr->prebuf = (uint32_t) -1;
+            attr->fragsize = attr->tlength;
+        }
+
+        if (flags)
+            *flags |= PA_STREAM_ADJUST_LATENCY;
+    }
 
     if (s->context->version >= 13)
         return;
@@ -873,7 +892,7 @@ static void automatic_buffer_attr(pa_stream *s, pa_buffer_attr *attr, const pa_s
         attr->maxlength = 4*1024*1024; /* 4MB is the maximum queue length PulseAudio <= 0.9.9 supported. */
 
     if (attr->tlength == (uint32_t) -1)
-        attr->tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, ss); /* 250ms of buffering */
+        attr->tlength = (uint32_t) pa_usec_to_bytes(250*PA_USEC_PER_MSEC, &s->sample_spec); /* 250ms of buffering */
 
     if (attr->minreq == (uint32_t) -1)
         attr->minreq = (attr->tlength)/5; /* Ask for more data when there are only 200ms left in the playback buffer */
@@ -1065,15 +1084,16 @@ static int create_stream(
     pa_stream_ref(s);
 
     s->direction = direction;
-    s->flags = flags;
-    s->corked = !!(flags & PA_STREAM_START_CORKED);
 
     if (sync_stream)
         s->syncid = sync_stream->syncid;
 
     if (attr)
         s->buffer_attr = *attr;
-    automatic_buffer_attr(s, &s->buffer_attr, &s->sample_spec);
+    patch_buffer_attr(s, &s->buffer_attr, &flags);
+
+    s->flags = flags;
+    s->corked = !!(flags & PA_STREAM_START_CORKED);
 
     if (flags & PA_STREAM_INTERPOLATE_TIMING) {
         pa_usec_t x;
@@ -2420,6 +2440,7 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr
     pa_operation *o;
     pa_tagstruct *t;
     uint32_t tag;
+    pa_buffer_attr copy;
 
     pa_assert(s);
     pa_assert(PA_REFCNT_VALUE(s) >= 1);
@@ -2443,6 +2464,10 @@ pa_operation* pa_stream_set_buffer_attr(pa_stream *s, const pa_buffer_attr *attr
             &tag);
     pa_tagstruct_putu32(t, s->channel);
 
+    copy = *attr;
+    patch_buffer_attr(s, &copy, NULL);
+    attr = &copy;
+
     pa_tagstruct_putu32(t, attr->maxlength);
 
     if (s->direction == PA_STREAM_PLAYBACK)

commit 66cfa72eb4fd4669dfd7e465c07c41bb7e6d3d85
Author: Lennart Poettering <lennart at poettering.net>
Date:   Mon Jan 18 01:33:04 2010 +0100

    native: rework handling of seeks that depend on variables the client does not know anything about
    
    All seeks/flushes that depend on the playback buffer read pointer cannot
    be accounted for properly in the client since it does not know the
    actual read pointer. Due to that the clients do not account for it at
    all. We need do the same on the server side. And we did, but a little
    bit too extreme. While we properly have not applied the changes to the
    "request" counter we still do have to apply it to the "missing" counter.
    This patch fixes that.

diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c
index 62e6267..cffb901 100644
--- a/src/modules/module-combine.c
+++ b/src/modules/module-combine.c
@@ -562,7 +562,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64
             if (PA_SINK_IS_OPENED(o->sink_input->sink->thread_info.state))
                 pa_memblockq_push_align(o->memblockq, chunk);
             else
-                pa_memblockq_flush_write(o->memblockq);
+                pa_memblockq_flush_write(o->memblockq, TRUE);
 
             return 0;
     }
@@ -982,7 +982,7 @@ static void output_disable(struct output *o) {
     o->sink_input = NULL;
 
     /* Finally, drop all queued data */
-    pa_memblockq_flush_write(o->memblockq);
+    pa_memblockq_flush_write(o->memblockq, TRUE);
     pa_asyncmsgq_flush(o->inq, FALSE);
     pa_asyncmsgq_flush(o->outq, FALSE);
 }
diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index bb0182b..15ef96e 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -430,7 +430,7 @@ static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, in
             if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
                 pa_memblockq_push_align(u->memblockq, chunk);
             else
-                pa_memblockq_flush_write(u->memblockq);
+                pa_memblockq_flush_write(u->memblockq, TRUE);
 
             update_min_memblockq_length(u);
 
@@ -457,7 +457,7 @@ static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, in
             if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state))
                 pa_memblockq_seek(u->memblockq, -offset, PA_SEEK_RELATIVE, TRUE);
             else
-                pa_memblockq_flush_write(u->memblockq);
+                pa_memblockq_flush_write(u->memblockq, TRUE);
 
             u->recv_counter -= offset;
 
diff --git a/src/pulse/stream.c b/src/pulse/stream.c
index 5e42ab2..36514e0 100644
--- a/src/pulse/stream.c
+++ b/src/pulse/stream.c
@@ -2154,6 +2154,11 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use
          * index, but the read index might jump. */
         invalidate_indexes(s, TRUE, FALSE);
 
+    /* Note that we do not update requested_bytes here. This is
+     * because we cannot really know how data actually was dropped
+     * from the write index due to this. This 'error' will be applied
+     * by both client and server and hence we should be fine. */
+
     return o;
 }
 
diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c
index 4641801..2b063fa 100644
--- a/src/pulsecore/memblockq.c
+++ b/src/pulsecore/memblockq.c
@@ -254,6 +254,8 @@ static void write_index_changed(pa_memblockq *bq, int64_t old_write_index, pa_bo
 
     if (account)
         bq->requested -= delta;
+    else
+        bq->missing -= delta;
 
     /* pa_log("pushed/seeked %lli: requested counter at %lli, account=%i", (long long) delta, (long long) bq->requested, account); */
 }
@@ -642,7 +644,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek, pa
     write_index_changed(bq, old, account);
 }
 
-void pa_memblockq_flush_write(pa_memblockq *bq) {
+void pa_memblockq_flush_write(pa_memblockq *bq, pa_bool_t account) {
     int64_t old;
     pa_assert(bq);
 
@@ -652,7 +654,7 @@ void pa_memblockq_flush_write(pa_memblockq *bq) {
     bq->write_index = bq->read_index;
 
     pa_memblockq_prebuf_force(bq);
-    write_index_changed(bq, old, TRUE);
+    write_index_changed(bq, old, account);
 }
 
 void pa_memblockq_flush_read(pa_memblockq *bq) {
diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h
index b756549..402c6cd 100644
--- a/src/pulsecore/memblockq.h
+++ b/src/pulsecore/memblockq.h
@@ -118,7 +118,7 @@ size_t pa_memblockq_pop_missing(pa_memblockq *bq);
 int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source);
 
 /* Set the queue to silence, set write index to read index */
-void pa_memblockq_flush_write(pa_memblockq *bq);
+void pa_memblockq_flush_write(pa_memblockq *bq, pa_bool_t account);
 
 /* Set the queue to silence, set write read index to write index*/
 void pa_memblockq_flush_read(pa_memblockq *bq);
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 89f33d0..ff24612 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -1326,6 +1326,10 @@ static void handle_seek(playback_stream *s, int64_t indexw) {
     playback_stream_request_bytes(s);
 }
 
+static void flush_write_no_account(pa_memblockq *q) {
+    pa_memblockq_flush_write(q, FALSE);
+}
+
 /* Called from thread context */
 static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
     pa_sink_input *i = PA_SINK_INPUT(o);
@@ -1387,7 +1391,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int
 
             switch  (code) {
                 case SINK_INPUT_MESSAGE_FLUSH:
-                    func = pa_memblockq_flush_write;
+                    func = flush_write_no_account;
                     break;
 
                 case SINK_INPUT_MESSAGE_PREBUF_FORCE:
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index e73999d..395110b 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -842,7 +842,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam
         /* We were asked to drop all buffered data, and rerequest new
          * data from implementor the next time push() is called */
 
-        pa_memblockq_flush_write(i->thread_info.render_memblockq);
+        pa_memblockq_flush_write(i->thread_info.render_memblockq, TRUE);
 
     } else if (i->thread_info.rewrite_nbytes > 0) {
         size_t max_rewrite, amount;

-- 
hooks/post-receive
PulseAudio Sound Server



More information about the pulseaudio-commits mailing list