From 8a5e135e0c08f9882f7f6020d97e37a5fff87f56 Mon Sep 17 00:00:00 2001
From: Lennart Poettering
Date: Fri, 15 Jan 2010 01:58:51 +0000
Subject: [PATCH] apply 31 updated from upstream
---
...er-functions-only-if-they-were-actua.patch | 289 ++++++++++++++++++
...-fix-request-counter-miscalculations.patch | 275 +++++++++++++++++
...e-always-return-a-valid-memblock-in-.patch | 161 ++++++++++
...ct-stream-only-if-it-is-not-already-.patch | 56 ++++
...hit-an-assert-if-latency-is-queried-.patch | 35 +++
...tect-forking-in-sample-cache-API-too.patch | 87 ++++++
...nnection-state-in-pa_stream_connect_.patch | 28 ++
...t-to-unref-devices-we-are-not-intere.patch | 29 ++
...make-once-related-variables-volatile.patch | 91 ++++++
...-bluetooth-fix-invalid-memory-access.patch | 36 +++
...asy-way-to-disable-log-rate-limiting.patch | 154 ++++++++++
...we-get-events-only-for-sound-devices.patch | 28 ++
...me-changes-from-the-hw-if-we-are-not.patch | 41 +++
...OV-flag-before-using-this-intsructio.patch | 80 +++++
0015-alsa-cover-Input-Source-Int-Mic.patch | 29 ++
...alsa-Cover-the-Int-Mic-Boost-element.patch | 36 +++
...d-cards-with-both-modem-and-audio-pr.patch | 117 +++++++
0018-udev-rework-modem-detection-a-bit.patch | 182 +++++++++++
...e-name-on-the-bus-then-return-in-sta.patch | 39 +++
...-alsa-cover-bass-boost-mixer-element.patch | 49 +++
0021-Mark-shared-variables-as-volatile.patch | 55 ++++
...L_ENC-instead-of-ID_MODEL-if-it-is-s.patch | 153 ++++++++++
...low-configuration-of-latency-in-msec.patch | 268 ++++++++++++++++
...-client-implement-PULSE_LATENCY_MSEC.patch | 107 +++++++
...lude-dolby-channel-names-in-comments.patch | 57 ++++
...le-set-for-M-Audio-FastTrack-Pro-USB.patch | 116 +++++++
...p-Properly-initialise-m-n_waiting_fo.patch | 35 +++
...LASS-instead-of-SOUND_FORM_FACTOR-wh.patch | 29 ++
...-src-pulsecore-cpu-arm.c-FTBFS-fixes.patch | 39 +++
...g-warnings-which-now-cause-buildd-fa.patch | 33 ++
...a_stream-pointers-to-hashmaps-instea.patch | 180 +++++++++++
pulseaudio.spec | 88 +++++-
32 files changed, 3000 insertions(+), 2 deletions(-)
create mode 100644 0001-dbus-remove-filter-functions-only-if-they-were-actua.patch
create mode 100644 0002-native-fix-request-counter-miscalculations.patch
create mode 100644 0003-core-make-sure-we-always-return-a-valid-memblock-in-.patch
create mode 100644 0004-bluetooth-destruct-stream-only-if-it-is-not-already-.patch
create mode 100644 0005-bluetooth-don-t-hit-an-assert-if-latency-is-queried-.patch
create mode 100644 0006-client-detect-forking-in-sample-cache-API-too.patch
create mode 100644 0007-client-verify-connection-state-in-pa_stream_connect_.patch
create mode 100644 0008-udev-don-t-forget-to-unref-devices-we-are-not-intere.patch
create mode 100644 0009-once-make-once-related-variables-volatile.patch
create mode 100644 0010-bluetooth-fix-invalid-memory-access.patch
create mode 100644 0011-log-add-an-easy-way-to-disable-log-rate-limiting.patch
create mode 100644 0012-udev-make-sure-we-get-events-only-for-sound-devices.patch
create mode 100644 0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-not.patch
create mode 100644 0014-cpu-check-for-CMOV-flag-before-using-this-intsructio.patch
create mode 100644 0015-alsa-cover-Input-Source-Int-Mic.patch
create mode 100644 0016-alsa-Cover-the-Int-Mic-Boost-element.patch
create mode 100644 0017-udev-handle-sound-cards-with-both-modem-and-audio-pr.patch
create mode 100644 0018-udev-rework-modem-detection-a-bit.patch
create mode 100644 0019-daemon-first-take-name-on-the-bus-then-return-in-sta.patch
create mode 100644 0020-alsa-cover-bass-boost-mixer-element.patch
create mode 100644 0021-Mark-shared-variables-as-volatile.patch
create mode 100644 0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is-s.patch
create mode 100644 0023-pacat-allow-configuration-of-latency-in-msec.patch
create mode 100644 0024-client-implement-PULSE_LATENCY_MSEC.patch
create mode 100644 0025-client-include-dolby-channel-names-in-comments.patch
create mode 100644 0026-alsa-add-profile-set-for-M-Audio-FastTrack-Pro-USB.patch
create mode 100644 0027-threaded-mainloop-Properly-initialise-m-n_waiting_fo.patch
create mode 100644 0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-wh.patch
create mode 100644 0029-More-src-pulsecore-cpu-arm.c-FTBFS-fixes.patch
create mode 100644 0030-Fix-the-following-warnings-which-now-cause-buildd-fa.patch
create mode 100644 0031-libpulse-Store-pa_stream-pointers-to-hashmaps-instea.patch
diff --git a/0001-dbus-remove-filter-functions-only-if-they-were-actua.patch b/0001-dbus-remove-filter-functions-only-if-they-were-actua.patch
new file mode 100644
index 0000000..0a0ead4
--- /dev/null
+++ b/0001-dbus-remove-filter-functions-only-if-they-were-actua.patch
@@ -0,0 +1,289 @@
+From c41ee00893b6b0d5cc48ee041b8e4835eac548f0 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Fri, 8 Jan 2010 20:06:21 +0100
+Subject: [PATCH 01/31] 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
+---
+ src/modules/bluetooth/bluetooth-util.c | 5 +++-
+ src/modules/bluetooth/module-bluetooth-device.c | 7 ++++-
+ src/modules/bluetooth/module-bluetooth-proximity.c | 11 ++++----
+ src/modules/module-console-kit.c | 9 +++++-
+ src/modules/module-hal-detect.c | 10 ++++----
+ src/pulse/context.c | 25 ++++---------------
+ src/pulse/internal.h | 1 +
+ 7 files changed, 34 insertions(+), 34 deletions(-)
+
+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 7468d0a..c83230d 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_dynarray_new();
+ c->record_streams = pa_dynarray_new();
+ 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 b371bfc..c3ebf74 100644
+--- a/src/pulse/internal.h
++++ b/src/pulse/internal.h
+@@ -91,6 +91,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;
+--
+1.6.6
+
diff --git a/0002-native-fix-request-counter-miscalculations.patch b/0002-native-fix-request-counter-miscalculations.patch
new file mode 100644
index 0000000..23021aa
--- /dev/null
+++ b/0002-native-fix-request-counter-miscalculations.patch
@@ -0,0 +1,275 @@
+From 8d356659e69556fa25d0579a66084f820683e2b8 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Fri, 8 Jan 2010 20:07:34 +0100
+Subject: [PATCH 02/31] 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
+---
+ src/pulse/stream.c | 4 ++
+ src/pulsecore/memblockq.c | 101 ++++++++++++++++++---------------------
+ src/pulsecore/protocol-native.c | 7 ++-
+ 3 files changed, 55 insertions(+), 57 deletions(-)
+
+diff --git a/src/pulse/stream.c b/src/pulse/stream.c
+index d01985b..793277a 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);
+
+@@ -1354,6 +1356,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 6e35762..b7b3f59 100644
+--- a/src/pulsecore/protocol-native.c
++++ b/src/pulsecore/protocol-native.c
+@@ -1113,6 +1113,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;
+
+@@ -1137,11 +1139,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;
+--
+1.6.6
+
diff --git a/0003-core-make-sure-we-always-return-a-valid-memblock-in-.patch b/0003-core-make-sure-we-always-return-a-valid-memblock-in-.patch
new file mode 100644
index 0000000..aa772cd
--- /dev/null
+++ b/0003-core-make-sure-we-always-return-a-valid-memblock-in-.patch
@@ -0,0 +1,161 @@
+From 3eed219a50c943251b41814e779cc37daf47e8f4 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Fri, 8 Jan 2010 21:51:30 +0100
+Subject: [PATCH 03/31] core: make sure we always return a valid memblock in sink_input_pop() callbacks
+
+https://bugzilla.redhat.com/show_bug.cgi?id=553607
+---
+ src/modules/module-combine.c | 2 +-
+ src/modules/module-ladspa-sink.c | 6 +++++-
+ src/pulsecore/play-memchunk.c | 6 +++++-
+ src/pulsecore/protocol-esound.c | 5 ++++-
+ src/pulsecore/protocol-simple.c | 6 +++++-
+ src/pulsecore/sound-file-stream.c | 5 ++++-
+ 6 files changed, 24 insertions(+), 6 deletions(-)
+
+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 16de492..2025c2a 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);
+@@ -324,7 +325,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);
+
+--
+1.6.6
+
diff --git a/0004-bluetooth-destruct-stream-only-if-it-is-not-already-.patch b/0004-bluetooth-destruct-stream-only-if-it-is-not-already-.patch
new file mode 100644
index 0000000..8191b5f
--- /dev/null
+++ b/0004-bluetooth-destruct-stream-only-if-it-is-not-already-.patch
@@ -0,0 +1,56 @@
+From 11688eca4b2beb7aa1adcd4aa9a3ee933f7385fb Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Fri, 8 Jan 2010 22:18:15 +0100
+Subject: [PATCH 04/31] bluetooth: destruct stream only if it is not already destructed
+
+https://bugzilla.redhat.com/show_bug.cgi?id=551842
+---
+ src/modules/bluetooth/module-bluetooth-device.c | 28 ++++++++++++----------
+ 1 files changed, 15 insertions(+), 13 deletions(-)
+
+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);
+--
+1.6.6
+
diff --git a/0005-bluetooth-don-t-hit-an-assert-if-latency-is-queried-.patch b/0005-bluetooth-don-t-hit-an-assert-if-latency-is-queried-.patch
new file mode 100644
index 0000000..94eeae6
--- /dev/null
+++ b/0005-bluetooth-don-t-hit-an-assert-if-latency-is-queried-.patch
@@ -0,0 +1,35 @@
+From e7d9f891e2a8e6b670098b80315ca1f0010c35ca Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Fri, 8 Jan 2010 23:44:42 +0100
+Subject: [PATCH 05/31] bluetooth: don't hit an assert if latency is queried for a stooped recording stream
+
+https://bugzilla.redhat.com/show_bug.cgi?id=537422
+---
+ src/modules/bluetooth/module-bluetooth-device.c | 10 +++++++---
+ 1 files changed, 7 insertions(+), 3 deletions(-)
+
+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;
+ }
+
+--
+1.6.6
+
diff --git a/0006-client-detect-forking-in-sample-cache-API-too.patch b/0006-client-detect-forking-in-sample-cache-API-too.patch
new file mode 100644
index 0000000..1a59d11
--- /dev/null
+++ b/0006-client-detect-forking-in-sample-cache-API-too.patch
@@ -0,0 +1,87 @@
+From bf50dc42306857e361267d2ad39b737ad05b8604 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Tue, 12 Jan 2010 03:01:14 +0100
+Subject: [PATCH 06/31] client: detect forking in sample cache API, too
+
+---
+ src/pulse/scache.c | 9 +++++++--
+ src/pulse/stream.c | 1 +
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+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
+
+ #include
++#include
+
+ #include
+ #include
+ #include
+
++#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 793277a..79b2868 100644
+--- a/src/pulse/stream.c
++++ b/src/pulse/stream.c
+@@ -29,6 +29,7 @@
+ #include
+
+ #include
++#include
+ #include
+ #include
+ #include
+--
+1.6.6
+
diff --git a/0007-client-verify-connection-state-in-pa_stream_connect_.patch b/0007-client-verify-connection-state-in-pa_stream_connect_.patch
new file mode 100644
index 0000000..e05dd76
--- /dev/null
+++ b/0007-client-verify-connection-state-in-pa_stream_connect_.patch
@@ -0,0 +1,28 @@
+From 78811c5653d0ba508b6558ba4578b61da26c60cf Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Tue, 12 Jan 2010 03:01:27 +0100
+Subject: [PATCH 07/31] 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
+---
+ src/pulse/scache.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+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);
+--
+1.6.6
+
diff --git a/0008-udev-don-t-forget-to-unref-devices-we-are-not-intere.patch b/0008-udev-don-t-forget-to-unref-devices-we-are-not-intere.patch
new file mode 100644
index 0000000..7b2bc8a
--- /dev/null
+++ b/0008-udev-don-t-forget-to-unref-devices-we-are-not-intere.patch
@@ -0,0 +1,29 @@
+From 15a3018bda8ee92393671ceaf272be418e95a81f Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Tue, 12 Jan 2010 23:01:24 +0100
+Subject: [PATCH 08/31] udev: don't forget to unref devices we are not interested in
+
+https://bugzilla.redhat.com/show_bug.cgi?id=552932
+---
+ src/modules/module-udev-detect.c | 4 +++-
+ 1 files changed, 3 insertions(+), 1 deletions(-)
+
+diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
+index 1b1e9c1..7508d9a 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);
+--
+1.6.6
+
diff --git a/0009-once-make-once-related-variables-volatile.patch b/0009-once-make-once-related-variables-volatile.patch
new file mode 100644
index 0000000..6bbe675
--- /dev/null
+++ b/0009-once-make-once-related-variables-volatile.patch
@@ -0,0 +1,91 @@
+From 73ae1fce001253677b7ab633f42d3c3300fe5cf5 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Tue, 12 Jan 2010 23:03:04 +0100
+Subject: [PATCH 09/31] once: make once related variables volatile
+
+---
+ src/pulsecore/flist.h | 2 +-
+ src/pulsecore/once.c | 3 +--
+ src/pulsecore/thread-posix.c | 8 ++------
+ src/pulsecore/thread.h | 2 +-
+ 4 files changed, 5 insertions(+), 10 deletions(-)
+
+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 \
+--
+1.6.6
+
diff --git a/0010-bluetooth-fix-invalid-memory-access.patch b/0010-bluetooth-fix-invalid-memory-access.patch
new file mode 100644
index 0000000..e1373f3
--- /dev/null
+++ b/0010-bluetooth-fix-invalid-memory-access.patch
@@ -0,0 +1,36 @@
+From 4bcb1a909f936a63628273e7d35726bc64785eeb Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Wed, 13 Jan 2010 17:24:37 +0100
+Subject: [PATCH 10/31] 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
+---
+ src/modules/bluetooth/bluetooth-util.c | 8 +++++++-
+ 1 files changed, 7 insertions(+), 1 deletions(-)
+
+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;
+
+--
+1.6.6
+
diff --git a/0011-log-add-an-easy-way-to-disable-log-rate-limiting.patch b/0011-log-add-an-easy-way-to-disable-log-rate-limiting.patch
new file mode 100644
index 0000000..271ab73
--- /dev/null
+++ b/0011-log-add-an-easy-way-to-disable-log-rate-limiting.patch
@@ -0,0 +1,154 @@
+From 21b484e056be445fdaf00f91ce50bc40b1ac9623 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Wed, 13 Jan 2010 17:35:04 +0100
+Subject: [PATCH 11/31] 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
+---
+ src/pulsecore/log.c | 88 +++++++++++++++++++++++++++++----------------------
+ 1 files changed, 50 insertions(+), 38 deletions(-)
+
+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);
+ }
+--
+1.6.6
+
diff --git a/0012-udev-make-sure-we-get-events-only-for-sound-devices.patch b/0012-udev-make-sure-we-get-events-only-for-sound-devices.patch
new file mode 100644
index 0000000..b9fc6a7
--- /dev/null
+++ b/0012-udev-make-sure-we-get-events-only-for-sound-devices.patch
@@ -0,0 +1,28 @@
+From 9b37dce4223aaf7a5f48b04b52c89b46ad97cf73 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Wed, 13 Jan 2010 19:41:44 +0100
+Subject: [PATCH 12/31] udev: make sure we get events only for sound devices
+
+---
+ src/modules/module-udev-detect.c | 5 +++++
+ 1 files changed, 5 insertions(+), 0 deletions(-)
+
+diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
+index 7508d9a..58635a5 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));
+--
+1.6.6
+
diff --git a/0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-not.patch b/0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-not.patch
new file mode 100644
index 0000000..72a4f2a
--- /dev/null
+++ b/0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-not.patch
@@ -0,0 +1,41 @@
+From 540ec7b961256d6c7702448ca995f61268064190 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Wed, 13 Jan 2010 20:30:36 +0100
+Subject: [PATCH 13/31] alsa: ignore volume changes from the hw if we are not on the active console
+
+---
+ src/modules/alsa/alsa-sink.c | 3 +++
+ src/modules/alsa/alsa-source.c | 3 +++
+ 2 files changed, 6 insertions(+), 0 deletions(-)
+
+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);
+--
+1.6.6
+
diff --git a/0014-cpu-check-for-CMOV-flag-before-using-this-intsructio.patch b/0014-cpu-check-for-CMOV-flag-before-using-this-intsructio.patch
new file mode 100644
index 0000000..8daf5ba
--- /dev/null
+++ b/0014-cpu-check-for-CMOV-flag-before-using-this-intsructio.patch
@@ -0,0 +1,80 @@
+From 170812755e0ac235ed2b7182ef637eb317d8b2b2 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Wed, 13 Jan 2010 20:31:17 +0100
+Subject: [PATCH 14/31] cpu: check for CMOV flag before using this intsruction in assembly
+
+http://pulseaudio.org/ticket/776
+---
+ src/pulsecore/cpu-x86.c | 6 +++++-
+ src/pulsecore/cpu-x86.h | 6 +++---
+ src/pulsecore/svolume_mmx.c | 2 +-
+ 3 files changed, 9 insertions(+), 5 deletions(-)
+
+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 b40eb5c..285c203 100644
+--- a/src/pulsecore/cpu-x86.h
++++ b/src/pulsecore/cpu-x86.h
+@@ -5,7 +5,7 @@
+ This file is part of PulseAudio.
+
+ Copyright 2004-2006 Lennart Poettering
+- Copyright 2009 Wim Taymans
++ Copyright 2009 Wim Taymans
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as published
+@@ -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 46923ed..e50ebee 100644
+--- a/src/pulsecore/svolume_mmx.c
++++ b/src/pulsecore/svolume_mmx.c
+@@ -305,7 +305,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);
+--
+1.6.6
+
diff --git a/0015-alsa-cover-Input-Source-Int-Mic.patch b/0015-alsa-cover-Input-Source-Int-Mic.patch
new file mode 100644
index 0000000..5836e49
--- /dev/null
+++ b/0015-alsa-cover-Input-Source-Int-Mic.patch
@@ -0,0 +1,29 @@
+From 67c6535222508bd84a122860023a8dc7fd44cd35 Mon Sep 17 00:00:00 2001
+From: Colin Guthrie
+Date: Wed, 13 Jan 2010 23:44:00 +0000
+Subject: [PATCH 15/31] alsa: cover Input Source:Int Mic
+
+As seen on some HDA chips (e.g. Fujitsu Siemens S6410)
+Refs http://pulseaudio.org/ticket/772
+---
+ .../alsa/mixer/paths/analog-input.conf.common | 4 ++++
+ 1 files changed, 4 insertions(+), 0 deletions(-)
+
+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
+--
+1.6.6
+
diff --git a/0016-alsa-Cover-the-Int-Mic-Boost-element.patch b/0016-alsa-Cover-the-Int-Mic-Boost-element.patch
new file mode 100644
index 0000000..ffa826f
--- /dev/null
+++ b/0016-alsa-Cover-the-Int-Mic-Boost-element.patch
@@ -0,0 +1,36 @@
+From 291cd096015d540d5064bfae94a66adc3bc3fc64 Mon Sep 17 00:00:00 2001
+From: Colin Guthrie
+Date: Wed, 13 Jan 2010 23:47:21 +0000
+Subject: [PATCH 16/31] 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
+---
+ .../alsa/mixer/paths/analog-input-mic.conf.common | 9 +++++++++
+ 1 files changed, 9 insertions(+), 0 deletions(-)
+
+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
+--
+1.6.6
+
diff --git a/0017-udev-handle-sound-cards-with-both-modem-and-audio-pr.patch b/0017-udev-handle-sound-cards-with-both-modem-and-audio-pr.patch
new file mode 100644
index 0000000..1a0e782
--- /dev/null
+++ b/0017-udev-handle-sound-cards-with-both-modem-and-audio-pr.patch
@@ -0,0 +1,117 @@
+From 63c968bf775ec7e172b89e45ddc4981d79587bc5 Mon Sep 17 00:00:00 2001
+From: Daniel T. Chen
+Date: Thu, 14 Jan 2010 00:57:27 +0100
+Subject: [PATCH 17/31] udev: handle sound cards with both modem and audio properly
+
+http://pulseaudio.org/ticket/681
+https://bugs.launchpad.net/ubuntu/+source/pulseaudio/+bug/394500
+---
+ src/modules/module-udev-detect.c | 59 ++++++++++++++++++++++++++++++++++++--
+ 1 files changed, 56 insertions(+), 3 deletions(-)
+
+diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
+index 58635a5..1fe9fdc 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;
+--
+1.6.6
+
diff --git a/0018-udev-rework-modem-detection-a-bit.patch b/0018-udev-rework-modem-detection-a-bit.patch
new file mode 100644
index 0000000..acd476c
--- /dev/null
+++ b/0018-udev-rework-modem-detection-a-bit.patch
@@ -0,0 +1,182 @@
+From acb4996203f6723d92a9b0df4e60db83c65116fc Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Thu, 14 Jan 2010 02:06:52 +0100
+Subject: [PATCH 18/31] udev: rework modem detection a bit
+
+Check every single pcm device of a card whether it is a modem.
+---
+ src/modules/module-udev-detect.c | 117 ++++++++++++++++++++------------------
+ 1 files changed, 62 insertions(+), 55 deletions(-)
+
+diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
+index 1fe9fdc..b8568b2 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;
+--
+1.6.6
+
diff --git a/0019-daemon-first-take-name-on-the-bus-then-return-in-sta.patch b/0019-daemon-first-take-name-on-the-bus-then-return-in-sta.patch
new file mode 100644
index 0000000..0074506
--- /dev/null
+++ b/0019-daemon-first-take-name-on-the-bus-then-return-in-sta.patch
@@ -0,0 +1,39 @@
+From 93cb75d78ed82c40e525a8b30f1ead147ad35ead Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Thu, 14 Jan 2010 02:33:49 +0100
+Subject: [PATCH 19/31] daemon: first take name on the bus, then return in starter process
+
+http://pulseaudio.org/ticket/748
+---
+ src/daemon/main.c | 8 ++++----
+ 1 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/src/daemon/main.c b/src/daemon/main.c
+index eafd72a..c7e202a 100644
+--- a/src/daemon/main.c
++++ b/src/daemon/main.c
+@@ -952,6 +952,10 @@ int main(int argc, char *argv[]) {
+ goto finish;
+ }
+
++#ifdef HAVE_DBUS
++ dbus = register_dbus(c);
++#endif
++
+ #ifdef HAVE_FORK
+ if (daemon_pipe[1] >= 0) {
+ int ok = 0;
+@@ -961,10 +965,6 @@ int main(int argc, char *argv[]) {
+ }
+ #endif
+
+-#ifdef HAVE_DBUS
+- dbus = register_dbus(c);
+-#endif
+-
+ pa_log_info(_("Daemon startup complete."));
+
+ retval = 0;
+--
+1.6.6
+
diff --git a/0020-alsa-cover-bass-boost-mixer-element.patch b/0020-alsa-cover-bass-boost-mixer-element.patch
new file mode 100644
index 0000000..9323d26
--- /dev/null
+++ b/0020-alsa-cover-bass-boost-mixer-element.patch
@@ -0,0 +1,49 @@
+From 48e0f6808bcc8e07622e4a45b3aabfc4679e9966 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Thu, 14 Jan 2010 02:53:50 +0100
+Subject: [PATCH 20/31] alsa: cover bass boost mixer element
+
+http://pulseaudio.org/ticket/740
+---
+ src/modules/alsa/alsa-mixer.c | 2 ++
+ .../alsa/mixer/paths/analog-output.conf.common | 11 +++++++++++
+ 2 files changed, 13 insertions(+), 0 deletions(-)
+
+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]
+--
+1.6.6
+
diff --git a/0021-Mark-shared-variables-as-volatile.patch b/0021-Mark-shared-variables-as-volatile.patch
new file mode 100644
index 0000000..a9c0f37
--- /dev/null
+++ b/0021-Mark-shared-variables-as-volatile.patch
@@ -0,0 +1,55 @@
+From 366e6d7e90d3bebc98a1af3cfb04b4cfc8cff6f5 Mon Sep 17 00:00:00 2001
+From: Arun Raghavan
+Date: Sun, 6 Dec 2009 12:20:53 +0530
+Subject: [PATCH 21/31] Mark shared variables as volatile
+
+'n_waiting' and 'n_waiting_for_accept' may be accessed from mulitple
+threads, and thus need to be marked as volatile to suppres certain
+compiler optimisations. All uses are protected by a mutex, so we don't
+need to worry about cache issues (added documentation for this as well).
+
+This addresses bug #738.
+---
+ src/pulse/thread-mainloop.c | 5 ++++-
+ 1 files changed, 4 insertions(+), 1 deletions(-)
+
+diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c
+index a2b98ce..14ed926 100644
+--- a/src/pulse/thread-mainloop.c
++++ b/src/pulse/thread-mainloop.c
+@@ -51,7 +51,7 @@
+
+ struct pa_threaded_mainloop {
+ pa_mainloop *real_mainloop;
+- int n_waiting, n_waiting_for_accept;
++ volatile int n_waiting, n_waiting_for_accept;
+
+ pa_thread* thread;
+ pa_mutex* mutex;
+@@ -185,6 +185,7 @@ void pa_threaded_mainloop_unlock(pa_threaded_mainloop *m) {
+ pa_mutex_unlock(m->mutex);
+ }
+
++/* Called with the lock taken */
+ void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) {
+ pa_assert(m);
+
+@@ -198,6 +199,7 @@ void pa_threaded_mainloop_signal(pa_threaded_mainloop *m, int wait_for_accept) {
+ }
+ }
+
++/* Called with the lock taken */
+ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) {
+ pa_assert(m);
+
+@@ -212,6 +214,7 @@ void pa_threaded_mainloop_wait(pa_threaded_mainloop *m) {
+ m->n_waiting --;
+ }
+
++/* Called with the lock taken */
+ void pa_threaded_mainloop_accept(pa_threaded_mainloop *m) {
+ pa_assert(m);
+
+--
+1.6.6
+
diff --git a/0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is-s.patch b/0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is-s.patch
new file mode 100644
index 0000000..593d29d
--- /dev/null
+++ b/0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is-s.patch
@@ -0,0 +1,153 @@
+From e129f8577a405266a5b7d4a7ee75bd56dd43953e Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Thu, 14 Jan 2010 20:31:00 +0100
+Subject: [PATCH 22/31] 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
+---
+ src/modules/udev-util.c | 110 +++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 110 insertions(+), 0 deletions(-)
+
+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);
+ }
+--
+1.6.6
+
diff --git a/0023-pacat-allow-configuration-of-latency-in-msec.patch b/0023-pacat-allow-configuration-of-latency-in-msec.patch
new file mode 100644
index 0000000..74d3336
--- /dev/null
+++ b/0023-pacat-allow-configuration-of-latency-in-msec.patch
@@ -0,0 +1,268 @@
+From 27df02779a26e0356497a39bee04a28138ba52af Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Fri, 15 Jan 2010 01:25:21 +0100
+Subject: [PATCH 23/31] pacat: allow configuration of latency in msec
+
+---
+ man/pacat.1.xml.in | 96 +++++++++++++++++++++++++++++++++++++++++++--------
+ src/utils/pacat.c | 46 ++++++++++++++++++++-----
+ 2 files changed, 118 insertions(+), 24 deletions(-)
+
+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.
+ -->
+
+-
++
+
+
++ paplay [options] [FILE]
++ parecord [options] [FILE]
+ pacat [options] [FILE]
+ parec [options] [FILE]
+- paplay --help
+- paplay --version
++ pamon [options] [FILE]
++ pacat --help
++ pacat --version
+
+
+
+ pacat is a simple tool for playing back or
+- capturing raw audio files on a PulseAudio sound server.
++ capturing raw or encoded audio files on a PulseAudio sound
++ server.
+
+
+
+@@ -52,13 +56,13 @@ USA.
+
+
+
+
+
+
+
+
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+
+
+
+@@ -178,7 +244,7 @@ USA.
+
+
+
+diff --git a/src/utils/pacat.c b/src/utils/pacat.c
+index 5f29ba3..a5d2e9a 100644
+--- a/src/utils/pacat.c
++++ b/src/utils/pacat.c
+@@ -45,6 +45,7 @@
+ #include
+ #include
+ #include
++#include
+
+ #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;
+
+--
+1.6.6
+
diff --git a/0024-client-implement-PULSE_LATENCY_MSEC.patch b/0024-client-implement-PULSE_LATENCY_MSEC.patch
new file mode 100644
index 0000000..56c1ebe
--- /dev/null
+++ b/0024-client-implement-PULSE_LATENCY_MSEC.patch
@@ -0,0 +1,107 @@
+From fa64230107bd348ceda271dc9db74765c694d311 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Fri, 15 Jan 2010 01:25:42 +0100
+Subject: [PATCH 24/31] client: implement $PULSE_LATENCY_MSEC
+
+This allows easy overriding of a clients latency setting for debugging
+purposes.
+
+http://pulseaudio.org/ticket/753
+---
+ src/pulse/stream.c | 37 +++++++++++++++++++++++++++++++------
+ 1 files changed, 31 insertions(+), 6 deletions(-)
+
+diff --git a/src/pulse/stream.c b/src/pulse/stream.c
+index 79b2868..daeb53a 100644
+--- a/src/pulse/stream.c
++++ b/src/pulse/stream.c
+@@ -39,6 +39,7 @@
+ #include
+ #include
+ #include
++#include
+
+ #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 */
+@@ -1064,15 +1083,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;
+@@ -2412,6 +2432,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);
+@@ -2435,6 +2456,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, ©, NULL);
++ attr = ©
++
+ pa_tagstruct_putu32(t, attr->maxlength);
+
+ if (s->direction == PA_STREAM_PLAYBACK)
+--
+1.6.6
+
diff --git a/0025-client-include-dolby-channel-names-in-comments.patch b/0025-client-include-dolby-channel-names-in-comments.patch
new file mode 100644
index 0000000..a3616e6
--- /dev/null
+++ b/0025-client-include-dolby-channel-names-in-comments.patch
@@ -0,0 +1,57 @@
+From 86144ee6cb6af54903a8d3d8395751ae26a4d134 Mon Sep 17 00:00:00 2001
+From: Lennart Poettering
+Date: Thu, 14 Jan 2010 21:32:26 +0100
+Subject: [PATCH 25/31] client: include dolby channel names in comments
+
+---
+ src/pulse/channelmap.h | 20 ++++++++++----------
+ 1 files changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/src/pulse/channelmap.h b/src/pulse/channelmap.h
+index 469effc..d1d5c8b 100644
+--- a/src/pulse/channelmap.h
++++ b/src/pulse/channelmap.h
+@@ -74,9 +74,9 @@ typedef enum pa_channel_position {
+ PA_CHANNEL_POSITION_INVALID = -1,
+ PA_CHANNEL_POSITION_MONO = 0,
+
+- PA_CHANNEL_POSITION_FRONT_LEFT, /* Apple calls this 'Left' */
+- PA_CHANNEL_POSITION_FRONT_RIGHT, /* Apple calls this 'Right' */
+- PA_CHANNEL_POSITION_FRONT_CENTER, /* Apple calls this 'Center' */
++ PA_CHANNEL_POSITION_FRONT_LEFT, /* Apple, Dolby call this 'Left' */
++ PA_CHANNEL_POSITION_FRONT_RIGHT, /* Apple, Dolby call this 'Right' */
++ PA_CHANNEL_POSITION_FRONT_CENTER, /* Apple, Dolby call this 'Center' */
+
+ /** \cond fulldocs */
+ PA_CHANNEL_POSITION_LEFT = PA_CHANNEL_POSITION_FRONT_LEFT,
+@@ -84,20 +84,20 @@ typedef enum pa_channel_position {
+ PA_CHANNEL_POSITION_CENTER = PA_CHANNEL_POSITION_FRONT_CENTER,
+ /** \endcond */
+
+- PA_CHANNEL_POSITION_REAR_CENTER, /* Microsoft calls this 'Back Center', Apple calls this 'Center Surround' */
+- PA_CHANNEL_POSITION_REAR_LEFT, /* Microsoft calls this 'Back Left', Apple calls this 'Left Surround' */
+- PA_CHANNEL_POSITION_REAR_RIGHT, /* Microsoft calls this 'Back Right', Apple calls this 'Right Surround' */
++ PA_CHANNEL_POSITION_REAR_CENTER, /* Microsoft calls this 'Back Center', Apple calls this 'Center Surround', Dolby calls this 'Surround Rear Center' */
++ PA_CHANNEL_POSITION_REAR_LEFT, /* Microsoft calls this 'Back Left', Apple calls this 'Left Surround' (!), Dolby calls this 'Surround Rear Left' */
++ PA_CHANNEL_POSITION_REAR_RIGHT, /* Microsoft calls this 'Back Right', Apple calls this 'Right Surround' (!), Dolby calls this 'Surround Rear Right' */
+
+ PA_CHANNEL_POSITION_LFE, /* Microsoft calls this 'Low Frequency', Apple calls this 'LFEScreen' */
+ /** \cond fulldocs */
+ PA_CHANNEL_POSITION_SUBWOOFER = PA_CHANNEL_POSITION_LFE,
+ /** \endcond */
+
+- PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */
+- PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */
++ PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, /* Apple, Dolby call this 'Left Center' */
++ PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, /* Apple, Dolby call this 'Right Center */
+
+- PA_CHANNEL_POSITION_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */
+- PA_CHANNEL_POSITION_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */
++ PA_CHANNEL_POSITION_SIDE_LEFT, /* Apple calls this 'Left Surround Direct', Dolby calls this 'Surround Left' (!) */
++ PA_CHANNEL_POSITION_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct', Dolby calls this 'Surround Right' (!) */
+
+ PA_CHANNEL_POSITION_AUX0,
+ PA_CHANNEL_POSITION_AUX1,
+--
+1.6.6
+
diff --git a/0026-alsa-add-profile-set-for-M-Audio-FastTrack-Pro-USB.patch b/0026-alsa-add-profile-set-for-M-Audio-FastTrack-Pro-USB.patch
new file mode 100644
index 0000000..d1abddd
--- /dev/null
+++ b/0026-alsa-add-profile-set-for-M-Audio-FastTrack-Pro-USB.patch
@@ -0,0 +1,116 @@
+From 66e1a2d05139d7968d41d9f1a88c22093cdd04d5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?David=20K=C3=A5gedal?=
+Date: Tue, 5 Jan 2010 20:14:11 +0100
+Subject: [PATCH 26/31] alsa: add profile set for M-Audio FastTrack Pro USB
+
+---
+ .../alsa/mixer/profile-sets/90-pulseaudio.rules | 1 +
+ .../mixer/profile-sets/maudio-fasttrack-pro.conf | 85 ++++++++++++++++++++
+ 2 files changed, 86 insertions(+), 0 deletions(-)
+ create mode 100644 src/modules/alsa/mixer/profile-sets/maudio-fasttrack-pro.conf
+
+diff --git a/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules b/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
+index ea1a2fe..b8e88d0 100644
+--- a/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
++++ b/src/modules/alsa/mixer/profile-sets/90-pulseaudio.rules
+@@ -22,5 +22,6 @@ KERNEL!="card*", GOTO="pulseaudio_end"
+
+ SUBSYSTEMS=="usb", ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="1978", ENV{PULSE_PROFILE_SET}="native-instruments-audio8dj.conf"
+ SUBSYSTEMS=="usb", ATTRS{idVendor}=="17cc", ATTRS{idProduct}=="0839", ENV{PULSE_PROFILE_SET}="native-instruments-audio4dj.conf"
++SUBSYSTEMS=="usb", ATTRS{idVendor}=="0763", ATTRS{idProduct}=="2012", ENV{PULSE_PROFILE_SET}="maudio-fasttrack-pro.conf"
+
+ LABEL="pulseaudio_end"
+diff --git a/src/modules/alsa/mixer/profile-sets/maudio-fasttrack-pro.conf b/src/modules/alsa/mixer/profile-sets/maudio-fasttrack-pro.conf
+new file mode 100644
+index 0000000..75f5112
+--- /dev/null
++++ b/src/modules/alsa/mixer/profile-sets/maudio-fasttrack-pro.conf
+@@ -0,0 +1,85 @@
++# This file is part of PulseAudio.
++#
++# 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.
++
++; M-Audio FastTrack Pro
++;
++; This card has one duplex stereo channel called A and an additional
++; stereo output channel called B.
++;
++; We knowingly only define a subset of the theoretically possible
++; mapping combinations as profiles here.
++;
++; See default.conf for an explanation on the directives used here.
++
++[General]
++auto-profiles = no
++
++[Mapping analog-stereo-a-output]
++description = Analog Stereo Channel A
++device-strings = hw:%f,0,0
++channel-map = left,right
++direction = output
++
++[Mapping analog-stereo-a-input]
++description = Analog Stereo Channel A
++device-strings = hw:%f,0,0
++channel-map = left,right
++direction = input
++
++[Mapping analog-stereo-b-output]
++description = Analog Stereo Channel B
++device-strings = hw:%f,1,0
++channel-map = left,right
++direction = output
++
++[Profile output:analog-stereo-all+input:analog-stereo-all]
++description = Analog Stereo Duplex Channel A, Analog Stereo output Channel B
++output-mappings = analog-stereo-a-output analog-stereo-b-output
++input-mappings = analog-stereo-a-input
++priority = 100
++skip-probe = yes
++
++[Profile output:analog-stereo-a-output+input:analog-stereo-a-input]
++description = Analog Stereo Duplex Channel A
++output-mappings = analog-stereo-a-output
++input-mappings = analog-stereo-a-input
++priority = 40
++skip-probe = yes
++
++[Profile output:analog-stereo-b+input:analog-stereo-b]
++description = Analog Stereo Output Channel B
++output-mappings = analog-stereo-b-output
++input-mappings =
++priority = 50
++skip-probe = yes
++
++[Profile output:analog-stereo-a]
++description = Analog Stereo Output Channel A
++output-mappings = analog-stereo-a-output
++priority = 5
++skip-probe = yes
++
++[Profile output:analog-stereo-b]
++description = Analog Stereo Output Channel B
++output-mappings = analog-stereo-b-output
++priority = 6
++skip-probe = yes
++
++[Profile input:analog-stereo-a]
++description = Analog Stereo Input Channel A
++input-mappings = analog-stereo-a-input
++priority = 2
++skip-probe = yes
+--
+1.6.6
+
diff --git a/0027-threaded-mainloop-Properly-initialise-m-n_waiting_fo.patch b/0027-threaded-mainloop-Properly-initialise-m-n_waiting_fo.patch
new file mode 100644
index 0000000..efcc6c3
--- /dev/null
+++ b/0027-threaded-mainloop-Properly-initialise-m-n_waiting_fo.patch
@@ -0,0 +1,35 @@
+From a2418effe7c4bc54390939ccd07dd6227e6cdfa5 Mon Sep 17 00:00:00 2001
+From: Daniel T Chen
+Date: Mon, 4 Jan 2010 21:44:37 -0500
+Subject: [PATCH 27/31] threaded-mainloop: Properly initialise m->n_waiting_for_accept to prevent deadlock
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Compiler optimisations have been seen to initialise
+m->n_waiting_for_accept to a positive non-zero value, so the while() in
+pa_threaded_mainloop_signal() never proceeds. Fix this by properly
+initializing m->n_waiting_for_accept in pa_threaded_mainloop_new().
+
+Patch from Iain Bucław.
+
+https://bugs.launchpad.net/bugs/502992
+---
+ src/pulse/thread-mainloop.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/src/pulse/thread-mainloop.c b/src/pulse/thread-mainloop.c
+index 14ed926..1693404 100644
+--- a/src/pulse/thread-mainloop.c
++++ b/src/pulse/thread-mainloop.c
+@@ -116,6 +116,7 @@ pa_threaded_mainloop *pa_threaded_mainloop_new(void) {
+ pa_mainloop_set_poll_func(m->real_mainloop, poll_func, m->mutex);
+
+ m->n_waiting = 0;
++ m->n_waiting_for_accept = 0;
+
+ return m;
+ }
+--
+1.6.6
+
diff --git a/0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-wh.patch b/0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-wh.patch
new file mode 100644
index 0000000..1632174
--- /dev/null
+++ b/0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-wh.patch
@@ -0,0 +1,29 @@
+From 8c7148a4eaecd687a004b0611748452fd4b41e92 Mon Sep 17 00:00:00 2001
+From: Daniel T Chen
+Date: Mon, 4 Jan 2010 21:53:36 -0500
+Subject: [PATCH 28/31] udev: Use SOUND_CLASS instead of SOUND_FORM_FACTOR when checking for modem
+
+The fact whether an ALSA card is a modem is stored in the SOUND_CLASS,
+not the SOUND_FORM_FACTOR property. So read it from there.
+
+Patch from Whoopie.
+---
+ src/modules/module-udev-detect.c | 2 +-
+ 1 files changed, 1 insertions(+), 1 deletions(-)
+
+diff --git a/src/modules/module-udev-detect.c b/src/modules/module-udev-detect.c
+index b8568b2..3cf3e58 100644
+--- a/src/modules/module-udev-detect.c
++++ b/src/modules/module-udev-detect.c
+@@ -426,7 +426,7 @@ static void process_device(struct userdata *u, struct udev_device *dev) {
+ return;
+ }
+
+- if ((ff = udev_device_get_property_value(dev, "SOUND_FORM_FACTOR")) &&
++ if ((ff = udev_device_get_property_value(dev, "SOUND_CLASS")) &&
+ pa_streq(ff, "modem")) {
+ pa_log_debug("Ignoring %s, because it is a modem.", udev_device_get_devpath(dev));
+ return;
+--
+1.6.6
+
diff --git a/0029-More-src-pulsecore-cpu-arm.c-FTBFS-fixes.patch b/0029-More-src-pulsecore-cpu-arm.c-FTBFS-fixes.patch
new file mode 100644
index 0000000..5054102
--- /dev/null
+++ b/0029-More-src-pulsecore-cpu-arm.c-FTBFS-fixes.patch
@@ -0,0 +1,39 @@
+From 09c416e11fe4f53c468f68ad0a67f4696241050a Mon Sep 17 00:00:00 2001
+From: Daniel T Chen
+Date: Wed, 16 Dec 2009 23:55:05 -0500
+Subject: [PATCH 29/31] More src/pulsecore/cpu-arm.c FTBFS fixes
+
+Fix missing argument to pa_read(), and be consistent with declaration of
+state variable in pa_cpu_init_arm().
+
+Signed-off-by: Daniel T Chen
+---
+ src/pulsecore/cpu-arm.c | 5 +++--
+ 1 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/src/pulsecore/cpu-arm.c b/src/pulsecore/cpu-arm.c
+index 453b784..61299cc 100644
+--- a/src/pulsecore/cpu-arm.c
++++ b/src/pulsecore/cpu-arm.c
+@@ -67,7 +67,7 @@ static char *get_cpuinfo(void) {
+ return NULL;
+ }
+
+- if ((n = pa_read(fd, cpuinfo, MAX_BUFFER-1)) < 0) {
++ if ((n = pa_read(fd, cpuinfo, MAX_BUFFER-1, NULL)) < 0) {
+ pa_xfree(cpuinfo);
+ pa_close(fd);
+ return NULL;
+@@ -105,7 +105,8 @@ void pa_cpu_init_arm (void) {
+ }
+ /* get the CPU features */
+ if ((line = get_cpuinfo_line (cpuinfo, "Features"))) {
+- char *state = NULL, *current;
++ const char *state = NULL;
++ char *current;
+
+ while ((current = pa_split_spaces (line, &state))) {
+ if (!strcmp (current, "vfp"))
+--
+1.6.6
+
diff --git a/0030-Fix-the-following-warnings-which-now-cause-buildd-fa.patch b/0030-Fix-the-following-warnings-which-now-cause-buildd-fa.patch
new file mode 100644
index 0000000..a095b84
--- /dev/null
+++ b/0030-Fix-the-following-warnings-which-now-cause-buildd-fa.patch
@@ -0,0 +1,33 @@
+From fd5c802ecb5ae5ed9b294422410761126a37d1b3 Mon Sep 17 00:00:00 2001
+From: Daniel T Chen
+Date: Wed, 16 Dec 2009 22:53:18 -0500
+Subject: [PATCH 30/31] Fix the following warnings (which now cause buildd failures in Ubuntu 10.04):
+
+pulsecore/cpu-arm.c: In function 'get_cpuinfo':
+pulsecore/cpu-arm.c:70: warning: implicit declaration of function 'pa_read' [-Wimplicit-function-declaration]
+pulsecore/cpu-arm.c:72: warning: implicit declaration of function 'pa_close' [-Wimplicit-function-declaration]
+pulsecore/cpu-arm.c: In function 'pa_cpu_init_arm':
+pulsecore/cpu-arm.c:110: warning: implicit declaration of function 'pa_split_spaces' [-Wimplicit-function-declaration]
+pulsecore/cpu-arm.c:110: warning: assignment makes pointer from integer without a cast
+Function `pa_split_spaces' implicitly converted to pointer at pulsecore/cpu-arm.c:110
+
+Signed-off-by: Daniel T Chen
+---
+ src/pulsecore/cpu-arm.c | 1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/src/pulsecore/cpu-arm.c b/src/pulsecore/cpu-arm.c
+index 61299cc..56d0bbc 100644
+--- a/src/pulsecore/cpu-arm.c
++++ b/src/pulsecore/cpu-arm.c
+@@ -30,6 +30,7 @@
+ #include
+
+ #include
++#include
+ #include
+
+ #include "cpu-arm.h"
+--
+1.6.6
+
diff --git a/0031-libpulse-Store-pa_stream-pointers-to-hashmaps-instea.patch b/0031-libpulse-Store-pa_stream-pointers-to-hashmaps-instea.patch
new file mode 100644
index 0000000..ea30b68
--- /dev/null
+++ b/0031-libpulse-Store-pa_stream-pointers-to-hashmaps-instea.patch
@@ -0,0 +1,180 @@
+From 52c66b47664d47154b2c8368e32beef27d4b2d03 Mon Sep 17 00:00:00 2001
+From: Tanu Kaskinen
+Date: Thu, 3 Dec 2009 13:22:05 +0200
+Subject: [PATCH 31/31] libpulse: Store pa_stream pointers to hashmaps instead of dynarrays.
+
+Since the stream identifiers (channels) are monotonically growing integer, it
+isn't a good idea to use them as index to a dynamic array, because the array
+will grow all the time. This is not a problem with client connections that
+don't create many streams, but, for example, long-running clients that use
+libcanberra for playing event sounds, this means that the client connection
+effectively leaks memory.
+---
+ src/pulse/context.c | 12 ++++++------
+ src/pulse/internal.h | 3 +--
+ src/pulse/stream.c | 20 ++++++++++----------
+ 3 files changed, 17 insertions(+), 18 deletions(-)
+
+diff --git a/src/pulse/context.c b/src/pulse/context.c
+index c83230d..91f4817 100644
+--- a/src/pulse/context.c
++++ b/src/pulse/context.c
+@@ -63,7 +63,7 @@
+ #include
+ #include
+ #include
+-#include
++#include
+ #include
+ #include
+ #include
+@@ -157,8 +157,8 @@ 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->playback_streams = pa_dynarray_new();
+- c->record_streams = pa_dynarray_new();
++ 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;
+ c->use_rtclock = pa_mainloop_is_our_api(mainloop);
+
+@@ -252,9 +252,9 @@ static void context_free(pa_context *c) {
+ #endif
+
+ if (c->record_streams)
+- pa_dynarray_free(c->record_streams, NULL, NULL);
++ pa_hashmap_free(c->record_streams, NULL, NULL);
+ if (c->playback_streams)
+- pa_dynarray_free(c->playback_streams, NULL, NULL);
++ pa_hashmap_free(c->playback_streams, NULL, NULL);
+
+ if (c->mempool)
+ pa_mempool_free(c->mempool);
+@@ -361,7 +361,7 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o
+
+ pa_context_ref(c);
+
+- if ((s = pa_dynarray_get(c->record_streams, channel))) {
++ if ((s = pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(channel)))) {
+
+ if (chunk->memblock) {
+ pa_memblockq_seek(s->record_memblockq, offset, seek, TRUE);
+diff --git a/src/pulse/internal.h b/src/pulse/internal.h
+index c3ebf74..ab702b9 100644
+--- a/src/pulse/internal.h
++++ b/src/pulse/internal.h
+@@ -34,7 +34,6 @@
+ #include
+ #include
+ #include
+-#include
+ #include
+ #include
+ #include
+@@ -66,7 +65,7 @@ struct pa_context {
+ pa_pstream *pstream;
+ pa_pdispatch *pdispatch;
+
+- pa_dynarray *record_streams, *playback_streams;
++ pa_hashmap *record_streams, *playback_streams;
+ PA_LLIST_HEAD(pa_stream, streams);
+ PA_LLIST_HEAD(pa_operation, operations);
+
+diff --git a/src/pulse/stream.c b/src/pulse/stream.c
+index daeb53a..ab8f8f4 100644
+--- a/src/pulse/stream.c
++++ b/src/pulse/stream.c
+@@ -201,7 +201,7 @@ static void stream_unlink(pa_stream *s) {
+ pa_pdispatch_unregister_reply(s->context->pdispatch, s);
+
+ if (s->channel_valid) {
+- pa_dynarray_put((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, s->channel, NULL);
++ pa_hashmap_remove((s->direction == PA_STREAM_PLAYBACK) ? s->context->playback_streams : s->context->record_streams, PA_UINT32_TO_PTR(s->channel));
+ s->channel = 0;
+ s->channel_valid = FALSE;
+ }
+@@ -356,7 +356,7 @@ void pa_command_stream_killed(pa_pdispatch *pd, uint32_t command, uint32_t tag,
+ goto finish;
+ }
+
+- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, channel)))
++ if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_STREAM_KILLED ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+@@ -476,7 +476,7 @@ void pa_command_stream_moved(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
+ goto finish;
+ }
+
+- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_MOVED ? c->playback_streams : c->record_streams, channel)))
++ if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_STREAM_MOVED ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+@@ -559,7 +559,7 @@ void pa_command_stream_buffer_attr(pa_pdispatch *pd, uint32_t command, uint32_t
+ goto finish;
+ }
+
+- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED ? c->playback_streams : c->record_streams, channel)))
++ if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+@@ -611,7 +611,7 @@ void pa_command_stream_suspended(pa_pdispatch *pd, uint32_t command, uint32_t ta
+ goto finish;
+ }
+
+- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED ? c->playback_streams : c->record_streams, channel)))
++ if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_STREAM_SUSPENDED ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+@@ -653,7 +653,7 @@ void pa_command_stream_started(pa_pdispatch *pd, uint32_t command, uint32_t tag,
+ goto finish;
+ }
+
+- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
++ if (!(s = pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(channel))))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+@@ -699,7 +699,7 @@ void pa_command_stream_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, p
+ goto finish;
+ }
+
+- if (!(s = pa_dynarray_get(command == PA_COMMAND_PLAYBACK_STREAM_EVENT ? c->playback_streams : c->record_streams, channel)))
++ if (!(s = pa_hashmap_get(command == PA_COMMAND_PLAYBACK_STREAM_EVENT ? c->playback_streams : c->record_streams, PA_UINT32_TO_PTR(channel))))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+@@ -735,7 +735,7 @@ void pa_command_request(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tag
+ goto finish;
+ }
+
+- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
++ if (!(s = pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(channel))))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+@@ -771,7 +771,7 @@ void pa_command_overflow_or_underflow(pa_pdispatch *pd, uint32_t command, uint32
+ goto finish;
+ }
+
+- if (!(s = pa_dynarray_get(c->playback_streams, channel)))
++ if (!(s = pa_hashmap_get(c->playback_streams, PA_UINT32_TO_PTR(channel))))
+ goto finish;
+
+ if (s->state != PA_STREAM_READY)
+@@ -1019,7 +1019,7 @@ void pa_create_stream_callback(pa_pdispatch *pd, uint32_t command, uint32_t tag,
+ }
+
+ s->channel_valid = TRUE;
+- pa_dynarray_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, s->channel, s);
++ pa_hashmap_put((s->direction == PA_STREAM_RECORD) ? s->context->record_streams : s->context->playback_streams, PA_UINT32_TO_PTR(s->channel), s);
+
+ create_stream_complete(s);
+
+--
+1.6.6
+
diff --git a/pulseaudio.spec b/pulseaudio.spec
index d24aa81..fc8fc0c 100644
--- a/pulseaudio.spec
+++ b/pulseaudio.spec
@@ -1,11 +1,42 @@
Name: pulseaudio
Summary: Improved Linux Sound Server
Version: 0.9.21
-Release: 3%{?dist}
+Release: 4%{?dist}
License: LGPLv2+
Group: System Environment/Daemons
Source0: http://0pointer.de/lennart/projects/pulseaudio/pulseaudio-%{version}.tar.gz
Source1: default.pa-for-gdm
+Patch0: 0001-dbus-remove-filter-functions-only-if-they-were-actua.patch
+Patch1: 0002-native-fix-request-counter-miscalculations.patch
+Patch2: 0003-core-make-sure-we-always-return-a-valid-memblock-in-.patch
+Patch3: 0004-bluetooth-destruct-stream-only-if-it-is-not-already-.patch
+Patch4: 0005-bluetooth-don-t-hit-an-assert-if-latency-is-queried-.patch
+Patch5: 0006-client-detect-forking-in-sample-cache-API-too.patch
+Patch6: 0007-client-verify-connection-state-in-pa_stream_connect_.patch
+Patch7: 0008-udev-don-t-forget-to-unref-devices-we-are-not-intere.patch
+Patch8: 0009-once-make-once-related-variables-volatile.patch
+Patch9: 0010-bluetooth-fix-invalid-memory-access.patch
+Patch10: 0011-log-add-an-easy-way-to-disable-log-rate-limiting.patch
+Patch11: 0012-udev-make-sure-we-get-events-only-for-sound-devices.patch
+Patch12: 0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-not.patch
+Patch13: 0014-cpu-check-for-CMOV-flag-before-using-this-intsructio.patch
+Patch14: 0015-alsa-cover-Input-Source-Int-Mic.patch
+Patch15: 0016-alsa-Cover-the-Int-Mic-Boost-element.patch
+Patch16: 0017-udev-handle-sound-cards-with-both-modem-and-audio-pr.patch
+Patch17: 0018-udev-rework-modem-detection-a-bit.patch
+Patch18: 0019-daemon-first-take-name-on-the-bus-then-return-in-sta.patch
+Patch19: 0020-alsa-cover-bass-boost-mixer-element.patch
+Patch20: 0021-Mark-shared-variables-as-volatile.patch
+Patch21: 0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is-s.patch
+Patch22: 0023-pacat-allow-configuration-of-latency-in-msec.patch
+Patch23: 0024-client-implement-PULSE_LATENCY_MSEC.patch
+Patch24: 0025-client-include-dolby-channel-names-in-comments.patch
+Patch25: 0026-alsa-add-profile-set-for-M-Audio-FastTrack-Pro-USB.patch
+Patch26: 0027-threaded-mainloop-Properly-initialise-m-n_waiting_fo.patch
+Patch27: 0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-wh.patch
+Patch28: 0029-More-src-pulsecore-cpu-arm.c-FTBFS-fixes.patch
+Patch29: 0030-Fix-the-following-warnings-which-now-cause-buildd-fa.patch
+Patch30: 0031-libpulse-Store-pa_stream-pointers-to-hashmaps-instea.patch
URL: http://pulseaudio.org/
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: m4
@@ -25,10 +56,14 @@ BuildRequires: glib2-devel
BuildRequires: gtk2-devel
BuildRequires: GConf2-devel
BuildRequires: avahi-devel
+%if 0%{?rhel} == 0
BuildRequires: lirc-devel
BuildRequires: jack-audio-connection-kit-devel
+%endif
BuildRequires: libatomic_ops-static, libatomic_ops-devel
+%ifnarch s390 s390x
BuildRequires: bluez-libs-devel
+%endif
BuildRequires: libXt-devel
BuildRequires: xorg-x11-proto-devel
BuildRequires: libXtst-devel
@@ -64,6 +99,7 @@ Obsoletes: esound
A compatibility script that allows applications to call /usr/bin/esd
and start PulseAudio with EsounD protocol modules.
+%if 0%{?rhel} == 0
%package module-lirc
Summary: LIRC support for the PulseAudio sound server
Group: System Environment/Daemons
@@ -71,6 +107,7 @@ Requires: %{name} = %{version}-%{release}
%description module-lirc
LIRC volume control module for the PulseAudio sound server.
+%endif
%package module-x11
Summary: X11 support for the PulseAudio sound server
@@ -90,6 +127,7 @@ Requires: pulseaudio-utils
%description module-zeroconf
Zeroconf publishing module for the PulseAudio sound server.
+%ifnarch s390 s390x
%package module-bluetooth
Summary: Bluetooth support for the PulseAudio sound server
Group: System Environment/Daemons
@@ -102,7 +140,9 @@ Contains Bluetooth audio (A2DP/HSP/HFP) support for the PulseAudio sound server.
Also contains a module that can be used to automatically turn down the volume if
a bluetooth mobile phone leaves the proximity or turn it up again if it enters the
proximity again
+%endif
+%if 0%{?rhel} == 0
%package module-jack
Summary: JACK support for the PulseAudio sound server
Group: System Environment/Daemons
@@ -110,6 +150,7 @@ Requires: %{name} = %{version}-%{release}
%description module-jack
JACK sink and source modules for the PulseAudio sound server.
+%endif
%package module-gconf
Summary: GConf support for the PulseAudio sound server
@@ -168,9 +209,11 @@ Group: Development/Libraries
Requires: %{name}-libs = %{version}-%{release}
Requires: %{name}-libs-glib2 = %{version}-%{release}
Requires: %{name}-libs-zeroconf = %{version}-%{release}
-Requires: pkgconfig
+Requires: pkgconfig
Requires: glib2-devel
+%if 0%{?rhel} == 0
Requires: vala
+%endif
Provides: pulseaudio-lib-devel
Obsoletes: pulseaudio-lib-devel
@@ -200,6 +243,37 @@ This package contains GDM integration hooks for the PulseAudio sound server.
%prep
%setup -q -T -b0
+%patch0 -p1
+%patch1 -p1
+%patch2 -p1
+%patch3 -p1
+%patch4 -p1
+%patch5 -p1
+%patch6 -p1
+%patch7 -p1
+%patch8 -p1
+%patch9 -p1
+%patch10 -p1
+%patch11 -p1
+%patch12 -p1
+%patch13 -p1
+%patch14 -p1
+%patch15 -p1
+%patch16 -p1
+%patch17 -p1
+%patch18 -p1
+%patch19 -p1
+%patch20 -p1
+%patch21 -p1
+%patch22 -p1
+%patch23 -p1
+%patch24 -p1
+%patch25 -p1
+%patch26 -p1
+%patch27 -p1
+%patch28 -p1
+%patch29 -p1
+%patch30 -p1
%build
%configure --disable-static --disable-rpath --with-system-user=pulse --with-system-group=pulse --with-access-group=pulse-access --disable-hal
@@ -338,9 +412,11 @@ exit 0
%{_bindir}/esdcompat
%{_mandir}/man1/esdcompat.1.gz
+%if 0%{?rhel} == 0
%files module-lirc
%defattr(-,root,root)
%{_libdir}/pulse-%{version}/modules/module-lirc.so
+%endif
%files module-x11
%defattr(-,root,root)
@@ -362,11 +438,14 @@ exit 0
%{_libdir}/pulse-%{version}/modules/module-raop-discover.so
%{_libdir}/pulse-%{version}/modules/module-raop-sink.so
+%if 0%{?rhel} == 0
%files module-jack
%defattr(-,root,root)
%{_libdir}/pulse-%{version}/modules/module-jack-sink.so
%{_libdir}/pulse-%{version}/modules/module-jack-source.so
+%endif
+%ifnarch s390 s390x
%files module-bluetooth
%defattr(-,root,root)
%{_libdir}/pulse-%{version}/modules/module-bluetooth-proximity.so
@@ -376,6 +455,7 @@ exit 0
%{_libdir}/pulse-%{version}/modules/libbluetooth-sbc.so
%{_libdir}/pulse-%{version}/modules/libbluetooth-util.so
%{_libexecdir}/pulse/proximity-helper
+%endif
%files module-gconf
%defattr(-,root,root)
@@ -439,6 +519,10 @@ exit 0
%attr(0600, gdm, gdm) %{_localstatedir}/lib/gdm/.pulse/default.pa
%changelog
+* Fri Jan 15 2010 Lennart Poettering - 0.9.21-4
+- backport 31 fixes from upstream git
+- sync spec file with rhel
+
* Tue Dec 8 2009 Michael Schwendt - 0.9.21-3
- Explicitly BR libatomic_ops-static in accordance with the Packaging
Guidelines (libatomic_ops-devel is still static-only).