diff --git a/0001-alsa-plugins-pulse-Implement-pause.patch b/0001-alsa-plugins-pulse-Implement-pause.patch deleted file mode 100644 index 8172382..0000000 --- a/0001-alsa-plugins-pulse-Implement-pause.patch +++ /dev/null @@ -1,59 +0,0 @@ -From d9a839d51255c939f394f770b249c8a4a9600122 Mon Sep 17 00:00:00 2001 -From: Troy Moure -Date: Thu, 18 Jun 2009 14:55:21 +0100 -Subject: [PATCH] alsa-plugins/pulse: Implement 'pause'. - -Just cork or uncork the stream to pause or unpause it. - -Signed-off-by: Troy Moure -Signed-off-by: Takashi Iwai ---- - pulse/pcm_pulse.c | 25 +++++++++++++++++++++++++ - 1 files changed, 25 insertions(+), 0 deletions(-) - -diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c -index db8d1e1..c276839 100644 ---- a/pulse/pcm_pulse.c -+++ b/pulse/pcm_pulse.c -@@ -739,6 +739,30 @@ static int pulse_close(snd_pcm_ioplug_t * io) - return 0; - } - -+static int pulse_pause(snd_pcm_ioplug_t * io, int enable) -+{ -+ snd_pcm_pulse_t *pcm = io->private_data; -+ int err = 0; -+ -+ assert (pcm); -+ assert (pcm->p); -+ -+ pa_threaded_mainloop_lock(pcm->p->mainloop); -+ -+ if (pcm->stream) { -+ pa_operation *o; -+ o = pa_stream_cork(pcm->stream, enable, NULL, NULL); -+ if (o) -+ pa_operation_unref(o); -+ else -+ err = -EIO; -+ } -+ -+ pa_threaded_mainloop_unlock(pcm->p->mainloop); -+ -+ return err; -+} -+ - static const snd_pcm_ioplug_callback_t pulse_playback_callback = { - .start = pulse_start, - .stop = pulse_stop, -@@ -750,6 +774,7 @@ static const snd_pcm_ioplug_callback_t pulse_playback_callback = { - .prepare = pulse_prepare, - .hw_params = pulse_hw_params, - .close = pulse_close, -+ .pause = pulse_pause - }; - - --- -1.6.3.3 - diff --git a/0001-alsa-get-rid-of-a-number-of-assert-s.patch b/0002-pulse-get-rid-of-a-number-of-assert-s.patch similarity index 95% rename from 0001-alsa-get-rid-of-a-number-of-assert-s.patch rename to 0002-pulse-get-rid-of-a-number-of-assert-s.patch index 5a549c6..1f871e7 100644 --- a/0001-alsa-get-rid-of-a-number-of-assert-s.patch +++ b/0002-pulse-get-rid-of-a-number-of-assert-s.patch @@ -1,21 +1,23 @@ -From ae28f795b7a3f626e2c02e0805936e07b06ed290 Mon Sep 17 00:00:00 2001 +From be8799947bac41c50460111b0ac20ff8176b6b47 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 31 Jul 2009 15:25:44 +0200 -Subject: [PATCH 1/4] alsa: get rid of a number of assert()s +Subject: [PATCH 02/11] pulse: get rid of a number of assert()s Instead of hitting an assert when any of the plugin functions is called in an invalid context we should return a clean error to make sure programs are not unnecessarily aborted. This should fix issues such as http://pulseaudio.org/ticket/595 + +Signed-off-by: Takashi Iwai --- - pulse/ctl_pulse.c | 35 +++++++++++++++++------ + pulse/ctl_pulse.c | 35 ++++++++++++++++++----- pulse/pcm_pulse.c | 79 +++++++++++++++++++++++++++++++++++++++++------------ pulse/pulse.c | 34 ++++++++++++++++------- - 3 files changed, 111 insertions(+), 37 deletions(-) + 3 files changed, 112 insertions(+), 36 deletions(-) diff --git a/pulse/ctl_pulse.c b/pulse/ctl_pulse.c -index c6cf9e2..1b057ef 100644 +index c6cf9e2..2caa29b 100644 --- a/pulse/ctl_pulse.c +++ b/pulse/ctl_pulse.c @@ -125,8 +125,9 @@ static void event_cb(pa_context * c, pa_subscription_event_type_t t, @@ -105,12 +107,12 @@ index c6cf9e2..1b057ef 100644 pa_threaded_mainloop_lock(ctl->p->mainloop); if (!ctl->updated || !ctl->subscribed) -@@ -525,8 +542,8 @@ static int pulse_ctl_poll_revents(snd_ctl_ext_t * ext, struct pollfd *pfd, - snd_ctl_pulse_t *ctl = ext->private_data; +@@ -526,7 +543,9 @@ static int pulse_ctl_poll_revents(snd_ctl_ext_t * ext, struct pollfd *pfd, int err = 0; -- assert(ctl); + assert(ctl); - assert(ctl->p); ++ + if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) + return -EBADFD; @@ -394,5 +396,5 @@ index 3940238..95d8dde 100644 pa_threaded_mainloop_lock(p->mainloop); -- -1.6.3.3 +1.6.4 diff --git a/0002-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch b/0002-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch deleted file mode 100644 index 5b3d770..0000000 --- a/0002-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch +++ /dev/null @@ -1,53 +0,0 @@ -From bf4d77ef87be83c3f9f249575cc4d08e7fb554df Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Fri, 31 Jul 2009 15:32:25 +0200 -Subject: [PATCH 2/4] pulse: use PA_CONTEXT_IS_GOOD where applicable - -PA_CONTEXT_IS_GOOD is a safer way to check whether a context is still -valid. - -This patch also bumps the version requirement of libpulse to 0.9.11. ---- - configure.in | 2 +- - pulse/pulse.c | 5 ++--- - 2 files changed, 3 insertions(+), 4 deletions(-) - -diff --git a/configure.in b/configure.in -index 36740e9..f8bc669 100644 ---- a/configure.in -+++ b/configure.in -@@ -30,7 +30,7 @@ AC_ARG_ENABLE([pulseaudio], - AS_HELP_STRING([--disable-pulseaudio], [Disable building of pulseaudio plugin])) - - if test "x$enable_pulseaudio" != "xno"; then -- PKG_CHECK_MODULES(pulseaudio, [libpulse >= 0.9.2], [HAVE_PULSE=yes], [HAVE_PULSE=no]) -+ PKG_CHECK_MODULES(pulseaudio, [libpulse >= 0.9.11], [HAVE_PULSE=yes], [HAVE_PULSE=no]) - fi - AM_CONDITIONAL(HAVE_PULSE, test x$HAVE_PULSE = xyes) - -diff --git a/pulse/pulse.c b/pulse/pulse.c -index 95d8dde..dd17384 100644 ---- a/pulse/pulse.c -+++ b/pulse/pulse.c -@@ -38,7 +38,7 @@ int pulse_check_connection(snd_pulse_t * p) - - state = pa_context_get_state(p->context); - -- if (state != PA_CONTEXT_READY) -+ if (!PA_CONTEXT_IS_GOOD(state)) - return -EIO; - - return 0; -@@ -127,8 +127,7 @@ int pulse_wait_stream_state(snd_pulse_t * p, pa_stream * stream, - if (state == target) - break; - -- if (state == PA_STREAM_FAILED || -- state == PA_STREAM_TERMINATED) -+ if (!PA_STREAM_IS_GOOD(state)) - return -EIO; - - pa_threaded_mainloop_wait(p->mainloop); --- -1.6.3.3 - diff --git a/0003-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch b/0003-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch new file mode 100644 index 0000000..99abef6 --- /dev/null +++ b/0003-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch @@ -0,0 +1,41 @@ +From d2ea09f162f114480516a9d993d3d71bf357c835 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 31 Jul 2009 16:01:52 +0200 +Subject: [PATCH 03/11] pulse: use PA_CONTEXT_IS_GOOD where applicable + +PA_CONTEXT_IS_GOOD is a safer way to check whether a context is still +valid. + +This patch also bumps the version requirement of libpulse to 0.9.11. + +Signed-off-by: Takashi Iwai +--- + pulse/pulse.c | 5 ++--- + 1 files changed, 2 insertions(+), 3 deletions(-) + +diff --git a/pulse/pulse.c b/pulse/pulse.c +index 95d8dde..dd17384 100644 +--- a/pulse/pulse.c ++++ b/pulse/pulse.c +@@ -38,7 +38,7 @@ int pulse_check_connection(snd_pulse_t * p) + + state = pa_context_get_state(p->context); + +- if (state != PA_CONTEXT_READY) ++ if (!PA_CONTEXT_IS_GOOD(state)) + return -EIO; + + return 0; +@@ -127,8 +127,7 @@ int pulse_wait_stream_state(snd_pulse_t * p, pa_stream * stream, + if (state == target) + break; + +- if (state == PA_STREAM_FAILED || +- state == PA_STREAM_TERMINATED) ++ if (!PA_STREAM_IS_GOOD(state)) + return -EIO; + + pa_threaded_mainloop_wait(p->mainloop); +-- +1.6.4 + diff --git a/0003-pulse-unify-destruction-of-snd_pulse_t.patch b/0004-pulse-unify-destruction-of-snd_pulse_t.patch similarity index 80% rename from 0003-pulse-unify-destruction-of-snd_pulse_t.patch rename to 0004-pulse-unify-destruction-of-snd_pulse_t.patch index 90ab33c..379a55f 100644 --- a/0003-pulse-unify-destruction-of-snd_pulse_t.patch +++ b/0004-pulse-unify-destruction-of-snd_pulse_t.patch @@ -1,8 +1,9 @@ -From 563bf2ff83018bdd03a5159522e1fb2ce6532d47 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Fri, 31 Jul 2009 15:33:52 +0200 -Subject: [PATCH 3/4] pulse: unify destruction of snd_pulse_t +From 422958fa4b8101af842220a67e77c8090ad34a8b Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 31 Jul 2009 16:02:05 +0200 +Subject: [PATCH 04/11] pulse: unify destruction of snd_pulse_t +Signed-off-by: Takashi Iwai --- pulse/pulse.c | 31 ++++++++++++------------------- 1 files changed, 12 insertions(+), 19 deletions(-) @@ -61,5 +62,5 @@ index dd17384..ae66b0c 100644 free(p); } -- -1.6.3.3 +1.6.4 diff --git a/0004-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch b/0005-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch similarity index 75% rename from 0004-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch rename to 0005-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch index 720981f..284219d 100644 --- a/0004-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch +++ b/0005-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch @@ -1,11 +1,13 @@ -From 97e12ff5b53d569bb63d3ea32241d56f2f14cb73 Mon Sep 17 00:00:00 2001 -From: Lennart Poettering -Date: Fri, 31 Jul 2009 15:34:13 +0200 -Subject: [PATCH 4/4] pulse: call pa_threaded_mainloop_wait() to handle spurious wakeups +From 16f837ec71a254a6bff7d26faf55237c4df5749c Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Fri, 31 Jul 2009 16:02:21 +0200 +Subject: [PATCH 05/11] pulse: call pa_threaded_mainloop_wait() to handle spurious wakeups pa_threaded_mainloop_wait() can wake up for no reason, according to the specs of the underlying POSIX ptrhead_cond_wait() docs, so we need to call it in a loop here which should be cleaner anyway. + +Signed-off-by: Takashi Iwai --- pulse/pulse.c | 13 ++++++++++--- 1 files changed, 10 insertions(+), 3 deletions(-) @@ -36,5 +38,5 @@ index ae66b0c..6f58a7e 100644 pa_threaded_mainloop_unlock(p->mainloop); -- -1.6.3.3 +1.6.4 diff --git a/0006-pulse-replace-manual-mainloop-by-pa_mainloop_iterate.patch b/0006-pulse-replace-manual-mainloop-by-pa_mainloop_iterate.patch new file mode 100644 index 0000000..cbe0745 --- /dev/null +++ b/0006-pulse-replace-manual-mainloop-by-pa_mainloop_iterate.patch @@ -0,0 +1,37 @@ +From 76d34749c05ba77614f648128ad7045681f547ae Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 4 Aug 2009 23:53:51 +0200 +Subject: [PATCH 06/11] pulse: replace manual mainloop by pa_mainloop_iterate() + +The pa_mainloop_prepare()/_poll()/_dispatch() can be simplified by +simply calling pa_mainloop_iterate() which does all this in one call. + +Signed-off-by: Takashi Iwai +--- + pulse/conf_pulse.c | 10 +--------- + 1 files changed, 1 insertions(+), 9 deletions(-) + +diff --git a/pulse/conf_pulse.c b/pulse/conf_pulse.c +index 3f9e071..35dd383 100644 +--- a/pulse/conf_pulse.c ++++ b/pulse/conf_pulse.c +@@ -61,15 +61,7 @@ conf_pulse_hook_load_if_running(snd_config_t * root, snd_config_t * config, + goto out; + + do { +- err = pa_mainloop_prepare(loop, -1); +- if (err < 0) +- goto out; +- +- err = pa_mainloop_poll(loop); +- if (err < 0) +- goto out; +- +- err = pa_mainloop_dispatch(loop); ++ err = pa_mainloop_iterate(loop, 1, NULL); + if (err < 0) + goto out; + +-- +1.6.4 + diff --git a/0007-pulse-move-a-couple-of-PCM-related-functions-from-pu.patch b/0007-pulse-move-a-couple-of-PCM-related-functions-from-pu.patch new file mode 100644 index 0000000..f99b8f7 --- /dev/null +++ b/0007-pulse-move-a-couple-of-PCM-related-functions-from-pu.patch @@ -0,0 +1,315 @@ +From f74878bc610bccc4656f8194f29176cf9c956de9 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 4 Aug 2009 23:54:24 +0200 +Subject: [PATCH 07/11] pulse: move a couple of PCM related functions from pulse.c to pcm_pulse.c + +A number of functions in pulse.c are only relevant for the PCM handling, +so let's move them to pcm_pulse.c. This allows us to simplify their +argument lists a bit. + +Signed-off-by: Takashi Iwai +--- + pulse/pcm_pulse.c | 118 ++++++++++++++++++++++++++++++++++++++++++---------- + pulse/pulse.c | 55 ------------------------- + pulse/pulse.h | 4 -- + 3 files changed, 95 insertions(+), 82 deletions(-) + +diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c +index 24347f9..a625f55 100644 +--- a/pulse/pcm_pulse.c ++++ b/pulse/pcm_pulse.c +@@ -49,6 +49,32 @@ typedef struct snd_pcm_pulse { + pa_buffer_attr buffer_attr; + } snd_pcm_pulse_t; + ++static int check_stream(snd_pcm_pulse_t *pcm) ++{ ++ int err; ++ pa_stream_state_t state; ++ ++ assert(pcm); ++ ++ if (!pcm->p) ++ return -EBADFD; ++ ++ err = pulse_check_connection(pcm->p); ++ if (err < 0) ++ return err; ++ ++ if (!pcm->stream) ++ return -EBADFD; ++ ++ state = pa_stream_get_state(pcm->stream); ++ if (!PA_STREAM_IS_GOOD(state)) ++ return -EIO; ++ ++ err = 0; ++ ++ return err; ++} ++ + static int update_ptr(snd_pcm_pulse_t *pcm) + { + size_t size; +@@ -118,9 +144,53 @@ static int update_active(snd_pcm_pulse_t *pcm) { + else + pulse_poll_deactivate(pcm->p); + ++ return ret; ++} ++ ++static int wait_stream_state(snd_pcm_pulse_t *pcm, pa_stream_state_t target) ++{ ++ pa_stream_state_t state; ++ ++ assert(pcm); ++ ++ if (!pcm->p) ++ return -EBADFD; ++ ++ for (;;) { ++ int err; ++ ++ err = pulse_check_connection(pcm->p); ++ if (err < 0) ++ return err; ++ ++ if (!pcm->stream) ++ return -EBADFD; ++ ++ state = pa_stream_get_state(pcm->stream); ++ if (state == target) ++ break; ++ ++ if (!PA_STREAM_IS_GOOD(state)) ++ return -EIO; ++ ++ pa_threaded_mainloop_wait(pcm->p->mainloop); ++ } ++ + return 0; + } + ++static void stream_success_cb(pa_stream * p, int success, void *userdata) ++{ ++ snd_pcm_pulse_t *pcm = userdata; ++ ++ assert(pcm); ++ ++ if (!pcm->p) ++ return; ++ ++ pa_threaded_mainloop_signal(pcm->p->mainloop, 0); ++} ++ + static int pulse_start(snd_pcm_ioplug_t * io) + { + snd_pcm_pulse_t *pcm = io->private_data; +@@ -138,18 +208,13 @@ static int pulse_start(snd_pcm_ioplug_t * io) + if (err < 0) + goto finish; + +- if (pcm->stream == NULL) +- goto finish; +- +- o = pa_stream_cork(pcm->stream, 0, pulse_stream_success_cb, +- pcm->p); ++ o = pa_stream_cork(pcm->stream, 0, stream_success_cb, pcm); + if (!o) { + err = -EIO; + goto finish; + } + +- u = pa_stream_trigger(pcm->stream, pulse_stream_success_cb, +- pcm->p); ++ u = pa_stream_trigger(pcm->stream, stream_success_cb, pcm); + + pcm->underrun = 0; + err_o = pulse_wait_operation(pcm->p, o); +@@ -165,7 +230,6 @@ static int pulse_start(snd_pcm_ioplug_t * io) + goto finish; + } + +- + finish: + pa_threaded_mainloop_unlock(pcm->p->mainloop); + +@@ -189,18 +253,13 @@ static int pulse_stop(snd_pcm_ioplug_t * io) + if (err < 0) + goto finish; + +- if (pcm->stream == NULL) +- goto finish; +- +- o = pa_stream_cork(pcm->stream, 1, pulse_stream_success_cb, +- pcm->p); ++ o = pa_stream_cork(pcm->stream, 1, stream_success_cb, pcm); + if (!o) { + err = -EIO; + goto finish; + } + +- u = pa_stream_flush(pcm->stream, pulse_stream_success_cb, +- pcm->p); ++ u = pa_stream_flush(pcm->stream, stream_success_cb, pcm); + if (!u) { + pa_operation_unref(o); + err = -EIO; +@@ -241,7 +300,7 @@ static int pulse_drain(snd_pcm_ioplug_t * io) + if (err < 0) + goto finish; + +- o = pa_stream_drain(pcm->stream, pulse_stream_success_cb, pcm->p); ++ o = pa_stream_drain(pcm->stream, stream_success_cb, pcm); + if (!o) { + err = -EIO; + goto finish; +@@ -504,6 +563,23 @@ finish: + return ret; + } + ++static void stream_state_cb(pa_stream * p, void *userdata) ++{ ++ snd_pcm_pulse_t *pcm = userdata; ++ pa_stream_state_t state; ++ ++ assert(pcm); ++ ++ if (!pcm->p) ++ return; ++ ++ state = pa_stream_get_state(p); ++ if (!PA_STREAM_IS_GOOD(state)) ++ pulse_poll_activate(pcm->p); ++ ++ pa_threaded_mainloop_signal(pcm->p->mainloop, 0); ++} ++ + static void stream_request_cb(pa_stream * p, size_t length, void *userdata) + { + snd_pcm_pulse_t *pcm = userdata; +@@ -586,8 +662,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io) + + if (pcm->stream) { + pa_stream_disconnect(pcm->stream); +- pulse_wait_stream_state(pcm->p, pcm->stream, +- PA_STREAM_TERMINATED); ++ wait_stream_state(pcm, PA_STREAM_TERMINATED); + pa_stream_unref(pcm->stream); + pcm->stream = NULL; + } +@@ -620,9 +695,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io) + goto finish; + } + +- pa_stream_set_state_callback(pcm->stream, pulse_stream_state_cb, +- pcm->p); +- ++ pa_stream_set_state_callback(pcm->stream, stream_state_cb, pcm); + pa_stream_set_latency_update_callback(pcm->stream, stream_latency_cb, pcm); + + if (io->stream == SND_PCM_STREAM_PLAYBACK) { +@@ -659,8 +732,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io) + goto finish; + } + +- err = +- pulse_wait_stream_state(pcm->p, pcm->stream, PA_STREAM_READY); ++ err = wait_stream_state(pcm, PA_STREAM_READY); + if (err < 0) { + SNDERR("PulseAudio: Unable to create stream: %s\n", pa_strerror(pa_context_errno(pcm->p->context))); + pa_stream_unref(pcm->stream); +diff --git a/pulse/pulse.c b/pulse/pulse.c +index 6f58a7e..c313182 100644 +--- a/pulse/pulse.c ++++ b/pulse/pulse.c +@@ -44,26 +44,6 @@ int pulse_check_connection(snd_pulse_t * p) + return 0; + } + +-void pulse_stream_state_cb(pa_stream * s, void *userdata) +-{ +- snd_pulse_t *p = userdata; +- +- assert(s); +- assert(p); +- +- pa_threaded_mainloop_signal(p->mainloop, 0); +-} +- +-void pulse_stream_success_cb(pa_stream * s, int success, void *userdata) +-{ +- snd_pulse_t *p = userdata; +- +- assert(s); +- assert(p); +- +- pa_threaded_mainloop_signal(p->mainloop, 0); +-} +- + void pulse_context_success_cb(pa_context * c, int success, void *userdata) + { + snd_pulse_t *p = userdata; +@@ -101,41 +81,6 @@ int pulse_wait_operation(snd_pulse_t * p, pa_operation * o) + return 0; + } + +-int pulse_wait_stream_state(snd_pulse_t * p, pa_stream * stream, +- pa_stream_state_t target) +-{ +- pa_stream_state_t state; +- +- assert(p); +- assert(stream); +- +- if (p->state != PULSE_STATE_READY) +- return -EBADFD; +- +- if (!p->mainloop) +- return -EBADFD; +- +- for (;;) { +- int err; +- +- err = pulse_check_connection(p); +- if (err < 0) +- return err; +- +- state = pa_stream_get_state(stream); +- +- if (state == target) +- break; +- +- if (!PA_STREAM_IS_GOOD(state)) +- return -EIO; +- +- pa_threaded_mainloop_wait(p->mainloop); +- } +- +- return 0; +-} +- + static void context_state_cb(pa_context * c, void *userdata) + { + snd_pulse_t *p = userdata; +diff --git a/pulse/pulse.h b/pulse/pulse.h +index 7bf1a5b..51f9a11 100644 +--- a/pulse/pulse.h ++++ b/pulse/pulse.h +@@ -41,13 +41,9 @@ typedef struct snd_pulse { + + int pulse_check_connection(snd_pulse_t * p); + +-void pulse_stream_state_cb(pa_stream * s, void *userdata); +-void pulse_stream_success_cb(pa_stream * s, int success, void *userdata); + void pulse_context_success_cb(pa_context * c, int success, void *userdata); + + int pulse_wait_operation(snd_pulse_t * p, pa_operation * o); +-int pulse_wait_stream_state(snd_pulse_t * p, pa_stream * stream, +- pa_stream_state_t target); + + snd_pulse_t *pulse_new(void); + void pulse_free(snd_pulse_t * p); +-- +1.6.4 + diff --git a/0008-pulse-get-rid-of-redundant-state-variable.patch b/0008-pulse-get-rid-of-redundant-state-variable.patch new file mode 100644 index 0000000..25d9075 --- /dev/null +++ b/0008-pulse-get-rid-of-redundant-state-variable.patch @@ -0,0 +1,87 @@ +From c3acf0f4df121fef0014bd165fa86ccb1060d669 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 4 Aug 2009 23:54:42 +0200 +Subject: [PATCH 08/11] pulse: get rid of redundant state variable + +snd_pulse_t::state was mostly shadowing the state of +pa_context_get_state(snd_pulse_t::context), so get rid of it and use the +state of the context directly. + +Signed-off-by: Takashi Iwai +--- + pulse/pulse.c | 14 +++----------- + pulse/pulse.h | 6 ------ + 2 files changed, 3 insertions(+), 17 deletions(-) + +diff --git a/pulse/pulse.c b/pulse/pulse.c +index c313182..9c05171 100644 +--- a/pulse/pulse.c ++++ b/pulse/pulse.c +@@ -59,12 +59,6 @@ int pulse_wait_operation(snd_pulse_t * p, pa_operation * o) + assert(p); + assert(o); + +- if (p->state != PULSE_STATE_READY) +- return -EBADFD; +- +- if (!p->mainloop) +- return -EBADFD; +- + for (;;) { + int err; + +@@ -124,8 +118,6 @@ snd_pulse_t *pulse_new(void) + if (!p) + return NULL; + +- p->state = PULSE_STATE_INIT; +- + if (pipe(fd)) { + free(p); + return NULL; +@@ -192,13 +184,15 @@ void pulse_free(snd_pulse_t * p) + int pulse_connect(snd_pulse_t * p, const char *server) + { + int err; ++ pa_context_state_t state; + + assert(p); + + if (!p->context || !p->mainloop) + return -EBADFD; + +- if (p->state != PULSE_STATE_INIT) ++ state = pa_context_get_state(p->context); ++ if (state != PA_CONTEXT_UNCONNECTED) + return -EBADFD; + + pa_threaded_mainloop_lock(p->mainloop); +@@ -221,8 +215,6 @@ int pulse_connect(snd_pulse_t * p, const char *server) + + pa_threaded_mainloop_unlock(p->mainloop); + +- p->state = PULSE_STATE_READY; +- + return 0; + + error: +diff --git a/pulse/pulse.h b/pulse/pulse.h +index 51f9a11..e98124f 100644 +--- a/pulse/pulse.h ++++ b/pulse/pulse.h +@@ -31,12 +31,6 @@ typedef struct snd_pulse { + pa_context *context; + + int thread_fd, main_fd; +- +- enum { +- PULSE_STATE_INIT, +- PULSE_STATE_READY, +- } state; +- + } snd_pulse_t; + + int pulse_check_connection(snd_pulse_t * p); +-- +1.6.4 + diff --git a/0009-pulse-unify-stream-context-state-checks.patch b/0009-pulse-unify-stream-context-state-checks.patch new file mode 100644 index 0000000..72103f5 --- /dev/null +++ b/0009-pulse-unify-stream-context-state-checks.patch @@ -0,0 +1,434 @@ +From 59ccd2aca941b4653803f5415b4985ab35de0c35 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 4 Aug 2009 23:55:05 +0200 +Subject: [PATCH 09/11] pulse: unify stream/context state checks + +Unify (and simplify) the paths that check for the validity of a +stream/context: always call into check_stream()/pulse_check_connection() +when applicable instead of rolling our own checks each time. Also check +for validity of mainloop before locking it. + +Signed-off-by: Takashi Iwai +--- + pulse/ctl_pulse.c | 72 ++++++++++++++++++++++++++++++++---------- + pulse/pcm_pulse.c | 90 +++++++++++++++++++++++----------------------------- + 2 files changed, 95 insertions(+), 67 deletions(-) + +diff --git a/pulse/ctl_pulse.c b/pulse/ctl_pulse.c +index 2caa29b..879f260 100644 +--- a/pulse/ctl_pulse.c ++++ b/pulse/ctl_pulse.c +@@ -150,9 +150,13 @@ static int pulse_update_volume(snd_ctl_pulse_t * ctl) + + assert(ctl); + +- if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ if (!ctl->p) + return -EBADFD; + ++ err = pulse_check_connection(ctl->p); ++ if (err < 0) ++ return err; ++ + o = pa_context_get_sink_info_by_name(ctl->p->context, ctl->sink, + sink_info_cb, ctl); + if (o) { +@@ -182,17 +186,27 @@ static int pulse_update_volume(snd_ctl_pulse_t * ctl) + static int pulse_elem_count(snd_ctl_ext_t * ext) + { + snd_ctl_pulse_t *ctl = ext->private_data; +- int count = 0; ++ int count = 0, err; + + assert(ctl); + ++ if (!ctl->p || !ctl->p->mainloop) ++ return -EBADFD; ++ + pa_threaded_mainloop_lock(ctl->p->mainloop); + ++ err = pulse_check_connection(ctl->p); ++ if (err < 0) { ++ count = err; ++ goto finish; ++ } ++ + if (ctl->source) + count += 2; + if (ctl->sink) + count += 2; + ++finish: + pa_threaded_mainloop_unlock(ctl->p->mainloop); + + return count; +@@ -202,16 +216,21 @@ static int pulse_elem_list(snd_ctl_ext_t * ext, unsigned int offset, + snd_ctl_elem_id_t * id) + { + snd_ctl_pulse_t *ctl = ext->private_data; ++ int err; + + assert(ctl); + +- if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ if (!ctl->p || !ctl->p->mainloop) + return -EBADFD; + + snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); + + pa_threaded_mainloop_lock(ctl->p->mainloop); + ++ err = pulse_check_connection(ctl->p); ++ if (err < 0) ++ goto finish; ++ + if (ctl->source) { + if (offset == 0) + snd_ctl_elem_id_set_name(id, SOURCE_VOL_NAME); +@@ -220,14 +239,19 @@ static int pulse_elem_list(snd_ctl_ext_t * ext, unsigned int offset, + } else + offset += 2; + ++ err = 0; ++ ++finish: + pa_threaded_mainloop_unlock(ctl->p->mainloop); + +- if (offset == 2) +- snd_ctl_elem_id_set_name(id, SINK_VOL_NAME); +- else if (offset == 3) +- snd_ctl_elem_id_set_name(id, SINK_MUTE_NAME); ++ if (err >= 0) { ++ if (offset == 2) ++ snd_ctl_elem_id_set_name(id, SINK_VOL_NAME); ++ else if (offset == 3) ++ snd_ctl_elem_id_set_name(id, SINK_MUTE_NAME); ++ } + +- return 0; ++ return err; + } + + static snd_ctl_ext_key_t pulse_find_elem(snd_ctl_ext_t * ext, +@@ -266,7 +290,7 @@ static int pulse_get_attribute(snd_ctl_ext_t * ext, snd_ctl_ext_key_t key, + + assert(ctl); + +- if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ if (!ctl->p || !ctl->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); +@@ -319,7 +343,7 @@ static int pulse_read_integer(snd_ctl_ext_t * ext, snd_ctl_ext_key_t key, + + assert(ctl); + +- if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ if (!ctl->p || !ctl->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); +@@ -371,7 +395,7 @@ static int pulse_write_integer(snd_ctl_ext_t * ext, snd_ctl_ext_key_t key, + + assert(ctl); + +- if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ if (!ctl->p || !ctl->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); +@@ -476,7 +500,7 @@ static void pulse_subscribe_events(snd_ctl_ext_t * ext, int subscribe) + + assert(ctl); + +- if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ if (!ctl->p || !ctl->p->mainloop) + return; + + pa_threaded_mainloop_lock(ctl->p->mainloop); +@@ -491,17 +515,23 @@ static int pulse_read_event(snd_ctl_ext_t * ext, snd_ctl_elem_id_t * id, + { + snd_ctl_pulse_t *ctl = ext->private_data; + int offset; +- int err = -EAGAIN; ++ int err; + + assert(ctl); + +- if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ if (!ctl->p || !ctl->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); + +- if (!ctl->updated || !ctl->subscribed) ++ err = pulse_check_connection(ctl->p); ++ if (err < 0) ++ goto finish; ++ ++ if (!ctl->updated || !ctl->subscribed) { ++ err = -EAGAIN; + goto finish; ++ } + + if (ctl->source) + offset = 2; +@@ -540,20 +570,28 @@ static int pulse_ctl_poll_revents(snd_ctl_ext_t * ext, struct pollfd *pfd, + unsigned short *revents) + { + snd_ctl_pulse_t *ctl = ext->private_data; +- int err = 0; ++ int err; + + assert(ctl); + +- if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ if (!ctl->p || !ctl->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); + ++ err = pulse_check_connection(ctl->p); ++ if (err < 0) ++ goto finish; ++ + if (ctl->updated) + *revents = POLLIN; + else + *revents = 0; + ++ err = 0; ++ ++finish: ++ + pa_threaded_mainloop_unlock(ctl->p->mainloop); + + return err; +diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c +index a625f55..98983f8 100644 +--- a/pulse/pcm_pulse.c ++++ b/pulse/pcm_pulse.c +@@ -135,11 +135,15 @@ static int update_active(snd_pcm_pulse_t *pcm) { + if (!pcm->p) + return -EBADFD; + +- ret = check_active(pcm); ++ ret = check_stream(pcm); + if (ret < 0) +- return ret; ++ goto finish; ++ ++ ret = check_active(pcm); + +- if (ret > 0) ++finish: ++ ++ if (ret != 0) /* On error signal the caller, too */ + pulse_poll_activate(pcm->p); + else + pulse_poll_deactivate(pcm->p); +@@ -199,12 +203,12 @@ static int pulse_start(snd_pcm_ioplug_t * io) + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- err = pulse_check_connection(pcm->p); ++ err = check_stream(pcm); + if (err < 0) + goto finish; + +@@ -244,12 +248,12 @@ static int pulse_stop(snd_pcm_ioplug_t * io) + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- err = pulse_check_connection(pcm->p); ++ err = check_stream(pcm); + if (err < 0) + goto finish; + +@@ -291,12 +295,12 @@ static int pulse_drain(snd_pcm_ioplug_t * io) + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- err = pulse_check_connection(pcm->p); ++ err = check_stream(pcm); + if (err < 0) + goto finish; + +@@ -328,7 +332,7 @@ static snd_pcm_sframes_t pulse_pointer(snd_pcm_ioplug_t * io) + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + if (io->state == SND_PCM_STATE_XRUN) +@@ -339,12 +343,7 @@ static snd_pcm_sframes_t pulse_pointer(snd_pcm_ioplug_t * io) + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- if (!pcm->stream) { +- ret = -EBADFD; +- goto finish; +- } +- +- ret = pulse_check_connection(pcm->p); ++ ret = check_stream(pcm); + if (ret < 0) + goto finish; + +@@ -379,18 +378,13 @@ static int pulse_delay(snd_pcm_ioplug_t * io, snd_pcm_sframes_t * delayp) + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- if (!pcm->stream) { +- err = -EBADFD; +- goto finish; +- } +- + for (;;) { +- err = pulse_check_connection(pcm->p); ++ err = check_stream(pcm); + if (err < 0) + goto finish; + +@@ -433,17 +427,12 @@ static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t * io, + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- if (!pcm->stream) { +- ret = -EBADFD; +- goto finish; +- } +- +- ret = pulse_check_connection(pcm->p); ++ ret = check_stream(pcm); + if (ret < 0) + goto finish; + +@@ -493,17 +482,12 @@ static snd_pcm_sframes_t pulse_read(snd_pcm_ioplug_t * io, + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- if (!pcm->stream) { +- ret = -EBADFD; +- goto finish; +- } +- +- ret = pulse_check_connection(pcm->p); ++ ret = check_stream(pcm); + if (ret < 0) + goto finish; + +@@ -624,13 +608,16 @@ static int pulse_pcm_poll_revents(snd_pcm_ioplug_t * io, + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- err = check_active(pcm); ++ err = check_stream(pcm); ++ if (err < 0) ++ goto finish; + ++ err = check_active(pcm); + if (err < 0) + goto finish; + +@@ -655,7 +642,7 @@ static int pulse_prepare(snd_pcm_ioplug_t * io) + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); +@@ -757,7 +744,7 @@ static int pulse_hw_params(snd_pcm_ioplug_t * io, + + assert(pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); +@@ -856,23 +843,26 @@ static int pulse_pause(snd_pcm_ioplug_t * io, int enable) + { + snd_pcm_pulse_t *pcm = io->private_data; + int err = 0; ++ pa_operation *o; + + assert (pcm); + +- if (!pcm->p) ++ if (!pcm->p || !pcm->p->mainloop) + return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- if (pcm->stream) { +- pa_operation *o; +- o = pa_stream_cork(pcm->stream, enable, NULL, NULL); +- if (o) +- pa_operation_unref(o); +- else +- err = -EIO; +- } ++ err = check_stream(pcm); ++ if (err < 0) ++ goto finish; ++ ++ o = pa_stream_cork(pcm->stream, enable, NULL, NULL); ++ if (o) ++ pa_operation_unref(o); ++ else ++ err = -EIO; + ++finish: + pa_threaded_mainloop_unlock(pcm->p->mainloop); + + return err; +-- +1.6.4 + diff --git a/0010-pulse-rework-object-destruction-paths-a-bit.patch b/0010-pulse-rework-object-destruction-paths-a-bit.patch new file mode 100644 index 0000000..5783e4d --- /dev/null +++ b/0010-pulse-rework-object-destruction-paths-a-bit.patch @@ -0,0 +1,73 @@ +From 50562a9d5d54270ab67f183013204d24cdbeff21 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 4 Aug 2009 23:55:28 +0200 +Subject: [PATCH 10/11] pulse: rework object destruction paths a bit + +Make sure we deal better with partially initialized structs. + +Don't check for pointer state before calling free() since free() does +that anyway. + +Signed-off-by: Takashi Iwai +--- + pulse/ctl_pulse.c | 7 ++----- + pulse/pcm_pulse.c | 19 ++++++++++--------- + 2 files changed, 12 insertions(+), 14 deletions(-) + +diff --git a/pulse/ctl_pulse.c b/pulse/ctl_pulse.c +index 879f260..85863ed 100644 +--- a/pulse/ctl_pulse.c ++++ b/pulse/ctl_pulse.c +@@ -606,11 +606,8 @@ static void pulse_close(snd_ctl_ext_t * ext) + if (ctl->p) + pulse_free(ctl->p); + +- if (ctl->source) +- free(ctl->source); +- if (ctl->sink) +- free(ctl->sink); +- ++ free(ctl->source); ++ free(ctl->sink); + free(ctl); + } + +diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c +index 98983f8..02a837e 100644 +--- a/pulse/pcm_pulse.c ++++ b/pulse/pcm_pulse.c +@@ -819,21 +819,22 @@ static int pulse_close(snd_pcm_ioplug_t * io) + + assert(pcm); + +- pa_threaded_mainloop_lock(pcm->p->mainloop); ++ if (pcm->p && pcm->p->mainloop) { + +- if (pcm->stream) { +- pa_stream_disconnect(pcm->stream); +- pa_stream_unref(pcm->stream); +- } ++ pa_threaded_mainloop_lock(pcm->p->mainloop); + +- pa_threaded_mainloop_unlock(pcm->p->mainloop); ++ if (pcm->stream) { ++ pa_stream_disconnect(pcm->stream); ++ pa_stream_unref(pcm->stream); ++ } ++ ++ pa_threaded_mainloop_unlock(pcm->p->mainloop); ++ } + + if (pcm->p) + pulse_free(pcm->p); + +- if (pcm->device) +- free(pcm->device); +- ++ free(pcm->device); + free(pcm); + + return 0; +-- +1.6.4 + diff --git a/0011-pulse-immediately-trigger-EIO-when-connection-is-dro.patch b/0011-pulse-immediately-trigger-EIO-when-connection-is-dro.patch new file mode 100644 index 0000000..615c6ed --- /dev/null +++ b/0011-pulse-immediately-trigger-EIO-when-connection-is-dro.patch @@ -0,0 +1,42 @@ +From 4c71fdd22dbfaf7b5fb7de62bbc9dd4002e788db Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 4 Aug 2009 23:56:00 +0200 +Subject: [PATCH 11/11] pulse: immediately trigger EIO when connection is dropped + +When the connection is dropped notify the application immediately +instead of waiting until the applications calls into us the next time. + +This makes "aplay" handle connections shutdown similar to hardware +unplugs: an immediate EIO is thrown. + +Signed-off-by: Takashi Iwai +--- + pulse/pulse.c | 9 ++++++++- + 1 files changed, 8 insertions(+), 1 deletions(-) + +diff --git a/pulse/pulse.c b/pulse/pulse.c +index 9c05171..f26363a 100644 +--- a/pulse/pulse.c ++++ b/pulse/pulse.c +@@ -77,10 +77,17 @@ int pulse_wait_operation(snd_pulse_t * p, pa_operation * o) + + static void context_state_cb(pa_context * c, void *userdata) + { ++ pa_context_state_t state; + snd_pulse_t *p = userdata; + assert(c); + +- switch (pa_context_get_state(c)) { ++ state = pa_context_get_state(c); ++ ++ /* When we get disconnected, tell the process */ ++ if (!PA_CONTEXT_IS_GOOD(state)) ++ pulse_poll_activate(p); ++ ++ switch (state) { + case PA_CONTEXT_READY: + case PA_CONTEXT_TERMINATED: + case PA_CONTEXT_FAILED: +-- +1.6.4 + diff --git a/alsa-plugins.spec b/alsa-plugins.spec index 37d745e..2fc9255 100644 --- a/alsa-plugins.spec +++ b/alsa-plugins.spec @@ -1,6 +1,6 @@ Name: alsa-plugins Version: 1.0.20 -Release: 4%{?dist} +Release: 5%{?dist} Summary: The Advanced Linux Sound Architecture (ALSA) Plugins # All packages are LGPLv2+ with the exception of samplerate which is GPLv2+ License: GPLv2+ and LGPLv2+ @@ -16,11 +16,17 @@ Source6: vdownmix.conf Source7: pulse-default.conf Source8: arcamav.conf BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -Patch0: 0001-alsa-plugins-pulse-Implement-pause.patch -Patch1: 0001-alsa-get-rid-of-a-number-of-assert-s.patch -Patch2: 0002-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch -Patch3: 0003-pulse-unify-destruction-of-snd_pulse_t.patch -Patch4: 0004-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch +Patch1: 0001-alsa-plugins-pulse-Implement-pause.patch +Patch2: 0002-pulse-get-rid-of-a-number-of-assert-s.patch +Patch3: 0003-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch +Patch4: 0004-pulse-unify-destruction-of-snd_pulse_t.patch +Patch5: 0005-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch +Patch6: 0006-pulse-replace-manual-mainloop-by-pa_mainloop_iterate.patch +Patch7: 0007-pulse-move-a-couple-of-PCM-related-functions-from-pu.patch +Patch8: 0008-pulse-get-rid-of-redundant-state-variable.patch +Patch9: 0009-pulse-unify-stream-context-state-checks.patch +Patch10: 0010-pulse-rework-object-destruction-paths-a-bit.patch +Patch11: 0011-pulse-immediately-trigger-EIO-when-connection-is-dro.patch BuildRequires: alsa-lib-devel @@ -128,11 +134,17 @@ pre-processing of a mono stream like denoise using libspeex DSP API. %prep %setup -q -n %{name}-%{version}%{?prever} -%patch0 -p1 %patch1 -p1 %patch2 -p1 %patch3 -p1 %patch4 -p1 +%patch5 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 %build %configure --disable-static \ @@ -235,6 +247,9 @@ rm -rf $RPM_BUILD_ROOT %changelog +* Tue Aug 4 2009 Lennart Poettering - 1.0.20-5 +- Add a couple of more clean up patches for the pulse plugin + * Fri Jul 31 2009 Lennart Poettering - 1.0.20-4 - Add a couple of clean up patches for the pulse plugin