diff --git a/0001-alsa-get-rid-of-a-number-of-assert-s.patch b/0001-alsa-get-rid-of-a-number-of-assert-s.patch new file mode 100644 index 0000000..5a549c6 --- /dev/null +++ b/0001-alsa-get-rid-of-a-number-of-assert-s.patch @@ -0,0 +1,398 @@ +From ae28f795b7a3f626e2c02e0805936e07b06ed290 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 + +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 +--- + pulse/ctl_pulse.c | 35 +++++++++++++++++------ + pulse/pcm_pulse.c | 79 +++++++++++++++++++++++++++++++++++++++++------------ + pulse/pulse.c | 34 ++++++++++++++++------- + 3 files changed, 111 insertions(+), 37 deletions(-) + +diff --git a/pulse/ctl_pulse.c b/pulse/ctl_pulse.c +index c6cf9e2..1b057ef 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, + pa_operation *o; + + assert(ctl); +- assert(ctl->p); +- assert(ctl->p->context); ++ ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return; + + o = pa_context_get_sink_info_by_name(ctl->p->context, ctl->sink, + sink_info_cb, ctl); +@@ -148,8 +149,9 @@ static int pulse_update_volume(snd_ctl_pulse_t * ctl) + pa_operation *o; + + assert(ctl); +- assert(ctl->p); +- assert(ctl->p->context); ++ ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return -EBADFD; + + o = pa_context_get_sink_info_by_name(ctl->p->context, ctl->sink, + sink_info_cb, ctl); +@@ -203,6 +205,9 @@ static int pulse_elem_list(snd_ctl_ext_t * ext, unsigned int offset, + + assert(ctl); + ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return -EBADFD; ++ + snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER); + + pa_threaded_mainloop_lock(ctl->p->mainloop); +@@ -260,7 +265,9 @@ static int pulse_get_attribute(snd_ctl_ext_t * ext, snd_ctl_ext_key_t key, + return -EINVAL; + + assert(ctl); +- assert(ctl->p); ++ ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); + +@@ -311,7 +318,9 @@ static int pulse_read_integer(snd_ctl_ext_t * ext, snd_ctl_ext_key_t key, + pa_cvolume *vol = NULL; + + assert(ctl); +- assert(ctl->p); ++ ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); + +@@ -361,7 +370,9 @@ static int pulse_write_integer(snd_ctl_ext_t * ext, snd_ctl_ext_key_t key, + pa_cvolume *vol = NULL; + + assert(ctl); +- assert(ctl->p && ctl->p->context); ++ ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); + +@@ -465,6 +476,9 @@ static void pulse_subscribe_events(snd_ctl_ext_t * ext, int subscribe) + + assert(ctl); + ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return; ++ + pa_threaded_mainloop_lock(ctl->p->mainloop); + + ctl->subscribed = !!(subscribe & SND_CTL_EVENT_MASK_VALUE); +@@ -481,6 +495,9 @@ static int pulse_read_event(snd_ctl_ext_t * ext, snd_ctl_elem_id_t * id, + + assert(ctl); + ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return -EBADFD; ++ + 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; + int err = 0; + +- assert(ctl); +- assert(ctl->p); ++ if (!ctl->p || !ctl->p->mainloop || !ctl->p->context) ++ return -EBADFD; + + pa_threaded_mainloop_lock(ctl->p->mainloop); + +diff --git a/pulse/pcm_pulse.c b/pulse/pcm_pulse.c +index c276839..24347f9 100644 +--- a/pulse/pcm_pulse.c ++++ b/pulse/pcm_pulse.c +@@ -106,6 +106,9 @@ static int update_active(snd_pcm_pulse_t *pcm) { + + assert(pcm); + ++ if (!pcm->p) ++ return -EBADFD; ++ + ret = check_active(pcm); + if (ret < 0) + return ret; +@@ -125,7 +128,9 @@ static int pulse_start(snd_pcm_ioplug_t * io) + int err = 0, err_o = 0, err_u = 0; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +@@ -174,7 +179,9 @@ static int pulse_stop(snd_pcm_ioplug_t * io) + int err = 0, err_o = 0, err_u = 0; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +@@ -224,7 +231,9 @@ static int pulse_drain(snd_pcm_ioplug_t * io) + int err = 0; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +@@ -259,7 +268,9 @@ static snd_pcm_sframes_t pulse_pointer(snd_pcm_ioplug_t * io) + snd_pcm_sframes_t ret = 0; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + if (io->state == SND_PCM_STATE_XRUN) + return -EPIPE; +@@ -269,7 +280,10 @@ static snd_pcm_sframes_t pulse_pointer(snd_pcm_ioplug_t * io) + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- assert(pcm->stream); ++ if (!pcm->stream) { ++ ret = -EBADFD; ++ goto finish; ++ } + + ret = pulse_check_connection(pcm->p); + if (ret < 0) +@@ -305,11 +319,16 @@ static int pulse_delay(snd_pcm_ioplug_t * io, snd_pcm_sframes_t * delayp) + pa_usec_t lat = 0; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- assert(pcm->stream); ++ if (!pcm->stream) { ++ err = -EBADFD; ++ goto finish; ++ } + + for (;;) { + err = pulse_check_connection(pcm->p); +@@ -354,11 +373,16 @@ static snd_pcm_sframes_t pulse_write(snd_pcm_ioplug_t * io, + snd_pcm_sframes_t ret = 0; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- assert(pcm->stream); ++ if (!pcm->stream) { ++ ret = -EBADFD; ++ goto finish; ++ } + + ret = pulse_check_connection(pcm->p); + if (ret < 0) +@@ -409,11 +433,16 @@ static snd_pcm_sframes_t pulse_read(snd_pcm_ioplug_t * io, + snd_pcm_sframes_t ret = 0; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +- assert(pcm->stream); ++ if (!pcm->stream) { ++ ret = -EBADFD; ++ goto finish; ++ } + + ret = pulse_check_connection(pcm->p); + if (ret < 0) +@@ -480,7 +509,9 @@ static void stream_request_cb(pa_stream * p, size_t length, void *userdata) + snd_pcm_pulse_t *pcm = userdata; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return; + + update_active(pcm); + } +@@ -490,7 +521,9 @@ static void stream_underrun_cb(pa_stream * p, void *userdata) + snd_pcm_pulse_t *pcm = userdata; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return; + + pcm->underrun = 1; + } +@@ -499,7 +532,9 @@ static void stream_latency_cb(pa_stream *p, void *userdata) { + snd_pcm_pulse_t *pcm = userdata; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return; + + pa_threaded_mainloop_signal(pcm->p->mainloop, 0); + } +@@ -512,7 +547,9 @@ static int pulse_pcm_poll_revents(snd_pcm_ioplug_t * io, + snd_pcm_pulse_t *pcm = io->private_data; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +@@ -541,7 +578,9 @@ static int pulse_prepare(snd_pcm_ioplug_t * io) + unsigned c, d; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +@@ -645,7 +684,9 @@ static int pulse_hw_params(snd_pcm_ioplug_t * io, + int err = 0; + + assert(pcm); +- assert(pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +@@ -745,7 +786,9 @@ static int pulse_pause(snd_pcm_ioplug_t * io, int enable) + int err = 0; + + assert (pcm); +- assert (pcm->p); ++ ++ if (!pcm->p) ++ return -EBADFD; + + pa_threaded_mainloop_lock(pcm->p->mainloop); + +diff --git a/pulse/pulse.c b/pulse/pulse.c +index 3940238..95d8dde 100644 +--- a/pulse/pulse.c ++++ b/pulse/pulse.c +@@ -32,8 +32,9 @@ int pulse_check_connection(snd_pulse_t * p) + pa_context_state_t state; + + assert(p); +- assert(p->context); +- assert(p->mainloop); ++ ++ if (!p->context || !p->mainloop) ++ return -EBADFD; + + state = pa_context_get_state(p->context); + +@@ -77,8 +78,12 @@ int pulse_wait_operation(snd_pulse_t * p, pa_operation * o) + { + assert(p); + assert(o); +- assert(p->state == PULSE_STATE_READY); +- assert(p->mainloop); ++ ++ if (p->state != PULSE_STATE_READY) ++ return -EBADFD; ++ ++ if (!p->mainloop) ++ return -EBADFD; + + for (;;) { + int err; +@@ -103,8 +108,12 @@ int pulse_wait_stream_state(snd_pulse_t * p, pa_stream * stream, + + assert(p); + assert(stream); +- assert(p->state == PULSE_STATE_READY); +- assert(p->mainloop); ++ ++ if (p->state != PULSE_STATE_READY) ++ return -EBADFD; ++ ++ if (!p->mainloop) ++ return -EBADFD; + + for (;;) { + int err; +@@ -197,7 +206,9 @@ snd_pulse_t *pulse_new(void) + + p->context = + pa_context_new(pa_threaded_mainloop_get_api(p->mainloop), buf); +- assert(p->context); ++ ++ if (!p->context) ++ goto fail; + + pa_context_set_state_callback(p->context, context_state_cb, p); + +@@ -246,9 +257,12 @@ int pulse_connect(snd_pulse_t * p, const char *server) + int err; + + assert(p); +- assert(p->context); +- assert(p->mainloop); +- assert(p->state == PULSE_STATE_INIT); ++ ++ if (!p->context || !p->mainloop) ++ return -EBADFD; ++ ++ if (p->state != PULSE_STATE_INIT) ++ return -EBADFD; + + pa_threaded_mainloop_lock(p->mainloop); + +-- +1.6.3.3 + diff --git a/0001-alsa-plugins-pulse-Implement-pause.patch b/0001-alsa-plugins-pulse-Implement-pause.patch new file mode 100644 index 0000000..8172382 --- /dev/null +++ b/0001-alsa-plugins-pulse-Implement-pause.patch @@ -0,0 +1,59 @@ +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/0002-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch b/0002-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch new file mode 100644 index 0000000..5b3d770 --- /dev/null +++ b/0002-pulse-use-PA_CONTEXT_IS_GOOD-where-applicable.patch @@ -0,0 +1,53 @@ +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-unify-destruction-of-snd_pulse_t.patch b/0003-pulse-unify-destruction-of-snd_pulse_t.patch new file mode 100644 index 0000000..90ab33c --- /dev/null +++ b/0003-pulse-unify-destruction-of-snd_pulse_t.patch @@ -0,0 +1,65 @@ +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 + +--- + pulse/pulse.c | 31 ++++++++++++------------------- + 1 files changed, 12 insertions(+), 19 deletions(-) + +diff --git a/pulse/pulse.c b/pulse/pulse.c +index dd17384..ae66b0c 100644 +--- a/pulse/pulse.c ++++ b/pulse/pulse.c +@@ -217,36 +217,29 @@ snd_pulse_t *pulse_new(void) + return p; + + fail: ++ pulse_free(p); ++ ++ return NULL; ++} ++ ++void pulse_free(snd_pulse_t * p) ++{ + if (p->mainloop) + pa_threaded_mainloop_stop(p->mainloop); + +- if (p->context) ++ if (p->context) { ++ pa_context_disconnect(p->context); + pa_context_unref(p->context); ++ } + + if (p->mainloop) + pa_threaded_mainloop_free(p->mainloop); + +- if (p->main_fd >= 0) +- close(p->main_fd); +- + if (p->thread_fd >= 0) + close(p->thread_fd); + +- free(p); +- +- return NULL; +-} +- +-void pulse_free(snd_pulse_t * p) +-{ +- pa_threaded_mainloop_stop(p->mainloop); +- +- pa_context_disconnect(p->context); +- pa_context_unref(p->context); +- pa_threaded_mainloop_free(p->mainloop); +- +- close(p->thread_fd); +- close(p->main_fd); ++ if (p->main_fd >= 0) ++ close(p->main_fd); + + free(p); + } +-- +1.6.3.3 + diff --git a/0004-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch b/0004-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch new file mode 100644 index 0000000..720981f --- /dev/null +++ b/0004-pulse-call-pa_threaded_mainloop_wait-to-handle-spuri.patch @@ -0,0 +1,40 @@ +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 + +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. +--- + pulse/pulse.c | 13 ++++++++++--- + 1 files changed, 10 insertions(+), 3 deletions(-) + +diff --git a/pulse/pulse.c b/pulse/pulse.c +index ae66b0c..6f58a7e 100644 +--- a/pulse/pulse.c ++++ b/pulse/pulse.c +@@ -262,10 +262,17 @@ int pulse_connect(snd_pulse_t * p, const char *server) + if (err < 0) + goto error; + +- pa_threaded_mainloop_wait(p->mainloop); ++ for (;;) { ++ pa_context_state_t state = pa_context_get_state(p->context); + +- if (pa_context_get_state(p->context) != PA_CONTEXT_READY) +- goto error; ++ if (!PA_CONTEXT_IS_GOOD(state)) ++ goto error; ++ ++ if (state == PA_CONTEXT_READY) ++ break; ++ ++ pa_threaded_mainloop_wait(p->mainloop); ++ } + + pa_threaded_mainloop_unlock(p->mainloop); + +-- +1.6.3.3 +