summaryrefslogtreecommitdiffstats
path: root/pulse/pcm_pulse.c
diff options
context:
space:
mode:
Diffstat (limited to 'pulse/pcm_pulse.c')
-rw-r--r--pulse/pcm_pulse.c118
1 files changed, 95 insertions, 23 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);