Add a couple of more clean up patches for the pulse plugin

This commit is contained in:
Lennart Poettering 2009-08-04 22:15:24 +00:00
parent 1ae1f5d7ae
commit c6ba4aa84c
13 changed files with 1075 additions and 138 deletions

View File

@ -1,59 +0,0 @@
From d9a839d51255c939f394f770b249c8a4a9600122 Mon Sep 17 00:00:00 2001
From: Troy Moure <twmoure@szypr.net>
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 <twmoure@szypr.net>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
---
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

View File

@ -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 <lennart@poettering.net>
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 <tiwai@suse.de>
---
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

View File

@ -1,53 +0,0 @@
From bf4d77ef87be83c3f9f249575cc4d08e7fb554df Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
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

View File

@ -0,0 +1,41 @@
From d2ea09f162f114480516a9d993d3d71bf357c835 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -1,8 +1,9 @@
From 563bf2ff83018bdd03a5159522e1fb2ce6532d47 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
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 <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -1,11 +1,13 @@
From 97e12ff5b53d569bb63d3ea32241d56f2f14cb73 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <lennart@poettering.net>
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 <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -0,0 +1,37 @@
From 76d34749c05ba77614f648128ad7045681f547ae Mon Sep 17 00:00:00 2001
From: Lennart Poettering <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -0,0 +1,315 @@
From f74878bc610bccc4656f8194f29176cf9c956de9 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -0,0 +1,87 @@
From c3acf0f4df121fef0014bd165fa86ccb1060d669 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -0,0 +1,434 @@
From 59ccd2aca941b4653803f5415b4985ab35de0c35 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -0,0 +1,73 @@
From 50562a9d5d54270ab67f183013204d24cdbeff21 Mon Sep 17 00:00:00 2001
From: Lennart Poettering <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -0,0 +1,42 @@
From 4c71fdd22dbfaf7b5fb7de62bbc9dd4002e788db Mon Sep 17 00:00:00 2001
From: Lennart Poettering <mznyfn@0pointer.de>
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 <tiwai@suse.de>
---
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

View File

@ -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 <lpoetter@redhat.com> - 1.0.20-5
- Add a couple of more clean up patches for the pulse plugin
* Fri Jul 31 2009 Lennart Poettering <lpoetter@redhat.com> - 1.0.20-4
- Add a couple of clean up patches for the pulse plugin