diff --git a/0001-dbus-remove-filter-functions-only-if-they-were-actu.patch b/0001-dbus-remove-filter-functions-only-if-they-were-actu.patch new file mode 100644 index 0000000..8a7ea41 --- /dev/null +++ b/0001-dbus-remove-filter-functions-only-if-they-were-actu.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] 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.0.2 + diff --git a/0002-native-fix-request-counter-miscalculations.patch b/0002-native-fix-request-counter-miscalculations.patch new file mode 100644 index 0000000..969026d --- /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] 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.0.2 + 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..8b6a5d4 --- /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] 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.0.2 + 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..4ab8fa3 --- /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] 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.0.2 + 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..ae45239 --- /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] 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.0.2 + 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..fc70a33 --- /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] 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.0.2 + 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..2deacf2 --- /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] 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.0.2 + diff --git a/0008-udev-don-t-forget-to-unref-devices-we-are-not-inter.patch b/0008-udev-don-t-forget-to-unref-devices-we-are-not-inter.patch new file mode 100644 index 0000000..3e9213c --- /dev/null +++ b/0008-udev-don-t-forget-to-unref-devices-we-are-not-inter.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] 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.0.2 + 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..e74cda0 --- /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] 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.0.2 + diff --git a/0010-bluetooth-fix-invalid-memory-access.patch b/0010-bluetooth-fix-invalid-memory-access.patch new file mode 100644 index 0000000..9acd9c4 --- /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] 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.0.2 + 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..7312fe6 --- /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] 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.0.2 + 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..42aee65 --- /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] 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.0.2 + diff --git a/0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-no.patch b/0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-no.patch new file mode 100644 index 0000000..818e0f8 --- /dev/null +++ b/0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-no.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] 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.0.2 + diff --git a/0014-cpu-check-for-CMOV-flag-before-using-this-intsructi.patch b/0014-cpu-check-for-CMOV-flag-before-using-this-intsructi.patch new file mode 100644 index 0000000..5c762e4 --- /dev/null +++ b/0014-cpu-check-for-CMOV-flag-before-using-this-intsructi.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] 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.0.2 + 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..53bc4c7 --- /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] 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.0.2 + 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..725679c --- /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] 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.0.2 + diff --git a/0017-udev-handle-sound-cards-with-both-modem-and-audio-p.patch b/0017-udev-handle-sound-cards-with-both-modem-and-audio-p.patch new file mode 100644 index 0000000..98e4dc1 --- /dev/null +++ b/0017-udev-handle-sound-cards-with-both-modem-and-audio-p.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] 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.0.2 + 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..e01ed3e --- /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] 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.0.2 + diff --git a/0019-daemon-first-take-name-on-the-bus-then-return-in-s.patch b/0019-daemon-first-take-name-on-the-bus-then-return-in-s.patch new file mode 100644 index 0000000..4e297f9 --- /dev/null +++ b/0019-daemon-first-take-name-on-the-bus-then-return-in-s.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] 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.0.2 + 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..271dc1d --- /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] 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.0.2 + diff --git a/0021-Mark-shared-variables-as-volatile.patch b/0021-Mark-shared-variables-as-volatile.patch new file mode 100644 index 0000000..f267aec --- /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] 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.0.2 + diff --git a/0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is.patch b/0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is.patch new file mode 100644 index 0000000..c931b34 --- /dev/null +++ b/0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is.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] 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.0.2 + 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..206da2e --- /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] 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.0.2 + diff --git a/0024-client-implement-PULSE_LATENCY_MSEC.patch b/0024-client-implement-PULSE_LATENCY_MSEC.patch new file mode 100644 index 0000000..236f3fc --- /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] 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.0.2 + 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..7bc06e2 --- /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] 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.0.2 + 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..981131e --- /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] 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.0.2 + diff --git a/0027-threaded-mainloop-Properly-initialise-m-n_waiting_.patch b/0027-threaded-mainloop-Properly-initialise-m-n_waiting_.patch new file mode 100644 index 0000000..cb4335c --- /dev/null +++ b/0027-threaded-mainloop-Properly-initialise-m-n_waiting_.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] 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.0.2 + diff --git a/0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-w.patch b/0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-w.patch new file mode 100644 index 0000000..8351ffb --- /dev/null +++ b/0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-w.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] 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.0.2 + 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..bdce026 --- /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] 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.0.2 + diff --git a/0030-Fix-the-following-warnings-which-now-cause-buildd-f.patch b/0030-Fix-the-following-warnings-which-now-cause-buildd-f.patch new file mode 100644 index 0000000..6e732b8 --- /dev/null +++ b/0030-Fix-the-following-warnings-which-now-cause-buildd-f.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] 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.0.2 + diff --git a/0031-libpulse-Store-pa_stream-pointers-to-hashmaps-inste.patch b/0031-libpulse-Store-pa_stream-pointers-to-hashmaps-inste.patch new file mode 100644 index 0000000..234b85d --- /dev/null +++ b/0031-libpulse-Store-pa_stream-pointers-to-hashmaps-inste.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] 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.0.2 + diff --git a/0032-native-rework-handling-of-seeks-that-depend-on-vari.patch b/0032-native-rework-handling-of-seeks-that-depend-on-vari.patch new file mode 100644 index 0000000..29efec8 --- /dev/null +++ b/0032-native-rework-handling-of-seeks-that-depend-on-vari.patch @@ -0,0 +1,166 @@ +From 84782f24c5f43456430c796bd12f9face24f0573 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Mon, 18 Jan 2010 01:33:04 +0100 +Subject: [PATCH] native: rework handling of seeks that depend on variables the client does not know anything about + +All seeks/flushes that depend on the playback buffer read pointer cannot +be accounted for properly in the client since it does not know the +actual read pointer. Due to that the clients do not account for it at +all. We need do the same on the server side. And we did, but a little +bit too extreme. While we properly have not applied the changes to the +"request" counter we still do have to apply it to the "missing" counter. +This patch fixes that. +--- + src/modules/module-combine.c | 4 ++-- + src/modules/module-loopback.c | 4 ++-- + src/pulse/stream.c | 5 +++++ + src/pulsecore/memblockq.c | 6 ++++-- + src/pulsecore/memblockq.h | 2 +- + src/pulsecore/protocol-native.c | 6 +++++- + src/pulsecore/sink-input.c | 2 +- + 7 files changed, 20 insertions(+), 9 deletions(-) + +diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c +index 62e6267..cffb901 100644 +--- a/src/modules/module-combine.c ++++ b/src/modules/module-combine.c +@@ -562,7 +562,7 @@ static int sink_input_process_msg(pa_msgobject *obj, int code, void *data, int64 + if (PA_SINK_IS_OPENED(o->sink_input->sink->thread_info.state)) + pa_memblockq_push_align(o->memblockq, chunk); + else +- pa_memblockq_flush_write(o->memblockq); ++ pa_memblockq_flush_write(o->memblockq, TRUE); + + return 0; + } +@@ -982,7 +982,7 @@ static void output_disable(struct output *o) { + o->sink_input = NULL; + + /* Finally, drop all queued data */ +- pa_memblockq_flush_write(o->memblockq); ++ pa_memblockq_flush_write(o->memblockq, TRUE); + pa_asyncmsgq_flush(o->inq, FALSE); + pa_asyncmsgq_flush(o->outq, FALSE); + } +diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c +index bb0182b..15ef96e 100644 +--- a/src/modules/module-loopback.c ++++ b/src/modules/module-loopback.c +@@ -430,7 +430,7 @@ static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, in + if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state)) + pa_memblockq_push_align(u->memblockq, chunk); + else +- pa_memblockq_flush_write(u->memblockq); ++ pa_memblockq_flush_write(u->memblockq, TRUE); + + update_min_memblockq_length(u); + +@@ -457,7 +457,7 @@ static int sink_input_process_msg_cb(pa_msgobject *obj, int code, void *data, in + if (PA_SINK_IS_OPENED(u->sink_input->sink->thread_info.state)) + pa_memblockq_seek(u->memblockq, -offset, PA_SEEK_RELATIVE, TRUE); + else +- pa_memblockq_flush_write(u->memblockq); ++ pa_memblockq_flush_write(u->memblockq, TRUE); + + u->recv_counter -= offset; + +diff --git a/src/pulse/stream.c b/src/pulse/stream.c +index ab8f8f4..8da40ec 100644 +--- a/src/pulse/stream.c ++++ b/src/pulse/stream.c +@@ -2146,6 +2146,11 @@ pa_operation* pa_stream_flush(pa_stream *s, pa_stream_success_cb_t cb, void *use + * index, but the read index might jump. */ + invalidate_indexes(s, TRUE, FALSE); + ++ /* Note that we do not update requested_bytes here. This is ++ * because we cannot really know how data actually was dropped ++ * from the write index due to this. This 'error' will be applied ++ * by both client and server and hence we should be fine. */ ++ + return o; + } + +diff --git a/src/pulsecore/memblockq.c b/src/pulsecore/memblockq.c +index 4641801..2b063fa 100644 +--- a/src/pulsecore/memblockq.c ++++ b/src/pulsecore/memblockq.c +@@ -254,6 +254,8 @@ static void write_index_changed(pa_memblockq *bq, int64_t old_write_index, pa_bo + + if (account) + bq->requested -= delta; ++ else ++ bq->missing -= delta; + + /* pa_log("pushed/seeked %lli: requested counter at %lli, account=%i", (long long) delta, (long long) bq->requested, account); */ + } +@@ -642,7 +644,7 @@ void pa_memblockq_seek(pa_memblockq *bq, int64_t offset, pa_seek_mode_t seek, pa + write_index_changed(bq, old, account); + } + +-void pa_memblockq_flush_write(pa_memblockq *bq) { ++void pa_memblockq_flush_write(pa_memblockq *bq, pa_bool_t account) { + int64_t old; + pa_assert(bq); + +@@ -652,7 +654,7 @@ void pa_memblockq_flush_write(pa_memblockq *bq) { + bq->write_index = bq->read_index; + + pa_memblockq_prebuf_force(bq); +- write_index_changed(bq, old, TRUE); ++ write_index_changed(bq, old, account); + } + + void pa_memblockq_flush_read(pa_memblockq *bq) { +diff --git a/src/pulsecore/memblockq.h b/src/pulsecore/memblockq.h +index 587c364..6132f31 100644 +--- a/src/pulsecore/memblockq.h ++++ b/src/pulsecore/memblockq.h +@@ -118,7 +118,7 @@ size_t pa_memblockq_pop_missing(pa_memblockq *bq); + int pa_memblockq_splice(pa_memblockq *bq, pa_memblockq *source); + + /* Set the queue to silence, set write index to read index */ +-void pa_memblockq_flush_write(pa_memblockq *bq); ++void pa_memblockq_flush_write(pa_memblockq *bq, pa_bool_t account); + + /* Set the queue to silence, set write read index to write index*/ + void pa_memblockq_flush_read(pa_memblockq *bq); +diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c +index b7b3f59..f80b0c2 100644 +--- a/src/pulsecore/protocol-native.c ++++ b/src/pulsecore/protocol-native.c +@@ -1325,6 +1325,10 @@ static void handle_seek(playback_stream *s, int64_t indexw) { + playback_stream_request_bytes(s); + } + ++static void flush_write_no_account(pa_memblockq *q) { ++ pa_memblockq_flush_write(q, FALSE); ++} ++ + /* Called from thread context */ + static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) { + pa_sink_input *i = PA_SINK_INPUT(o); +@@ -1386,7 +1390,7 @@ static int sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int + + switch (code) { + case SINK_INPUT_MESSAGE_FLUSH: +- func = pa_memblockq_flush_write; ++ func = flush_write_no_account; + break; + + case SINK_INPUT_MESSAGE_PREBUF_FORCE: +diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c +index aa84ccb..7acb25f 100644 +--- a/src/pulsecore/sink-input.c ++++ b/src/pulsecore/sink-input.c +@@ -801,7 +801,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam + /* We were asked to drop all buffered data, and rerequest new + * data from implementor the next time push() is called */ + +- pa_memblockq_flush_write(i->thread_info.render_memblockq); ++ pa_memblockq_flush_write(i->thread_info.render_memblockq, TRUE); + + } else if (i->thread_info.rewrite_nbytes > 0) { + size_t max_rewrite, amount; +-- +1.6.0.2 + diff --git a/pulseaudio.changes b/pulseaudio.changes index 66c6173..4015c1c 100644 --- a/pulseaudio.changes +++ b/pulseaudio.changes @@ -1,3 +1,11 @@ +------------------------------------------------------------------- +Tue Jan 19 22:13:22 UTC 2010 - sreeves@novell.com + +- Add set of patches backported from upstream git + [0001 - 0032].patch +- Remove pulseaudio-ticket738-mark-shared-vars-as-volatile.patch + Included in set of patches above + ------------------------------------------------------------------- Mon Jan 11 05:51:08 UTC 2010 - sreeves@novell.com diff --git a/pulseaudio.spec b/pulseaudio.spec index f012770..5e77acd 100644 --- a/pulseaudio.spec +++ b/pulseaudio.spec @@ -29,8 +29,39 @@ Source: %{name}-%{version}.tar.bz2 Source1: default.pa-for-gdm Source2: setup-pulseaudio Source99: baselibs.conf -Patch1: disabled-start.diff -Patch2: pulseaudio-ticket738-mark-shared-vars-as-volatile.patch +Patch0: disabled-start.diff +Patch1: 0001-dbus-remove-filter-functions-only-if-they-were-actu.patch +Patch2: 0002-native-fix-request-counter-miscalculations.patch +Patch3: 0003-core-make-sure-we-always-return-a-valid-memblock-in.patch +Patch4: 0004-bluetooth-destruct-stream-only-if-it-is-not-already.patch +Patch5: 0005-bluetooth-don-t-hit-an-assert-if-latency-is-queried.patch +Patch6: 0006-client-detect-forking-in-sample-cache-API-too.patch +Patch7: 0007-client-verify-connection-state-in-pa_stream_connect.patch +Patch8: 0008-udev-don-t-forget-to-unref-devices-we-are-not-inter.patch +Patch9: 0009-once-make-once-related-variables-volatile.patch +Patch10: 0010-bluetooth-fix-invalid-memory-access.patch +Patch11: 0011-log-add-an-easy-way-to-disable-log-rate-limiting.patch +Patch12: 0012-udev-make-sure-we-get-events-only-for-sound-devices.patch +Patch13: 0013-alsa-ignore-volume-changes-from-the-hw-if-we-are-no.patch +Patch14: 0014-cpu-check-for-CMOV-flag-before-using-this-intsructi.patch +Patch15: 0015-alsa-cover-Input-Source-Int-Mic.patch +Patch16: 0016-alsa-Cover-the-Int-Mic-Boost-element.patch +Patch17: 0017-udev-handle-sound-cards-with-both-modem-and-audio-p.patch +Patch18: 0018-udev-rework-modem-detection-a-bit.patch +Patch19: 0019-daemon-first-take-name-on-the-bus-then-return-in-s.patch +Patch20: 0020-alsa-cover-bass-boost-mixer-element.patch +Patch21: 0021-Mark-shared-variables-as-volatile.patch +Patch22: 0022-udev-use-ID_MODEL_ENC-instead-of-ID_MODEL-if-it-is.patch +Patch23: 0023-pacat-allow-configuration-of-latency-in-msec.patch +Patch24: 0024-client-implement-PULSE_LATENCY_MSEC.patch +Patch25: 0025-client-include-dolby-channel-names-in-comments.patch +Patch26: 0026-alsa-add-profile-set-for-M-Audio-FastTrack-Pro-USB.patch +Patch27: 0027-threaded-mainloop-Properly-initialise-m-n_waiting_.patch +Patch28: 0028-udev-Use-SOUND_CLASS-instead-of-SOUND_FORM_FACTOR-w.patch +Patch29: 0029-More-src-pulsecore-cpu-arm.c-FTBFS-fixes.patch +Patch30: 0030-Fix-the-following-warnings-which-now-cause-buildd-f.patch +Patch31: 0031-libpulse-Store-pa_stream-pointers-to-hashmaps-inste.patch +Patch32: 0032-native-rework-handling-of-seeks-that-depend-on-vari.patch Url: http://pulseaudio.org BuildRoot: %{_tmppath}/%{name}-%{version}-build BuildRequires: alsa-devel @@ -240,8 +271,39 @@ This package contains GDM integration hooks for the PulseAudio sound server. %lang_package %prep %setup -q -T -b0 -%patch1 +%patch0 +%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 +%patch31 -p1 +%patch32 -p1 %build export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing"