summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-07-28 21:00:16 +0000
committerLennart Poettering <lennart@poettering.net>2007-07-28 21:00:16 +0000
commit8aee345ccb8292fe2acf354dc9419eb2208eeef8 (patch)
treefafa932addef36acffcd89a037b9ec4b0593e9d2
parent5fbb8e12d6d7a881100f53ea77f646b2bb32fc08 (diff)
Fix suspending/resuming
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1556 fefdeb5f-60dc-0310-8127-8f9354f1896f
-rw-r--r--src/modules/module-alsa-sink.c110
1 files changed, 58 insertions, 52 deletions
diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c
index 1350090e..05fb90bb 100644
--- a/src/modules/module-alsa-sink.c
+++ b/src/modules/module-alsa-sink.c
@@ -116,6 +116,7 @@ static int mmap_write(struct userdata *u) {
int err;
const snd_pcm_channel_area_t *areas;
snd_pcm_uframes_t offset, frames;
+ int work_done = 0;
pa_assert(u);
pa_assert(u->sink);
@@ -134,8 +135,8 @@ static int mmap_write(struct userdata *u) {
if ((err = snd_pcm_recover(u->pcm_handle, n, 1)) == 0)
continue;
- if (err == EAGAIN)
- return 0;
+ if (err == -EAGAIN)
+ return work_done;
pa_log("snd_pcm_avail_update: %s", snd_strerror(n));
return -1;
@@ -144,7 +145,7 @@ static int mmap_write(struct userdata *u) {
/* pa_log("Got request for %i samples", (int) n); */
if (n <= 0)
- return 0;
+ return work_done;
frames = n;
@@ -158,8 +159,8 @@ static int mmap_write(struct userdata *u) {
if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
continue;
- if (err == EAGAIN)
- return 0;
+ if (err == -EAGAIN)
+ return work_done;
pa_log("Failed to write data to DSP: %s", snd_strerror(err));
return -1;
@@ -195,13 +196,15 @@ static int mmap_write(struct userdata *u) {
if ((err = snd_pcm_recover(u->pcm_handle, err, 1)) == 0)
continue;
- if (err == EAGAIN)
- return 0;
+ if (err == -EAGAIN)
+ return work_done;
pa_log("Failed to write data to DSP: %s", snd_strerror(err));
return -1;
}
+ work_done = 1;
+
/* pa_log("wrote %i samples", (int) frames); */
}
}
@@ -279,7 +282,7 @@ static int unsuspend(struct userdata *u) {
goto fail;
}
- if (!nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
+ if (nfrags != u->nfragments || period_size*u->frame_size != u->fragment_size) {
pa_log_warn("Resume failed, couldn't restore original fragment settings.");
goto fail;
}
@@ -318,17 +321,28 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *
case PA_SINK_MESSAGE_SET_STATE:
- if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
- pa_assert(u->sink->thread_info.state != PA_SINK_SUSPENDED);
-
- if (suspend(u) < 0)
- return -1;
+ switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
- } else if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
- pa_assert(PA_PTR_TO_UINT(data) != PA_SINK_SUSPENDED);
+ case PA_SINK_SUSPENDED:
+ pa_assert(PA_SINK_OPENED(u->sink->thread_info.state));
+
+ if (suspend(u) < 0)
+ return -1;
+
+ break;
+
+ case PA_SINK_IDLE:
+ case PA_SINK_RUNNING:
+
+ if (u->sink->thread_info.state == PA_SINK_SUSPENDED) {
+ if (unsuspend(u) < 0)
+ return -1;
+ }
+
+ break;
- if (unsuspend(u) < 0)
- return -1;
+ case PA_SINK_DISCONNECTED:
+ ;
}
break;
@@ -499,7 +513,7 @@ static void thread_func(void *userdata) {
pa_memchunk chunk;
int r;
-/* pa_log("loop"); */
+/* pa_log("loop"); */
/* Check whether there is a message for us to process */
if (pa_asyncmsgq_get(u->asyncmsgq, &object, &code, &data, &chunk, 0) == 0) {
@@ -521,19 +535,15 @@ static void thread_func(void *userdata) {
/* Render some data and write it to the dsp */
- if (u->sink->thread_info.state != PA_SINK_SUSPENDED && ((revents & POLLOUT) || u->first == 1)) {
+ if (PA_SINK_OPENED(u->sink->thread_info.state) && ((revents & POLLOUT) || u->first == 1)) {
+ int work_done = 0;
+ pa_assert(u->pcm_handle);
if (u->use_mmap) {
- int ret;
- if ((ret = mmap_write(u)) < 0)
+ if ((work_done = mmap_write(u)) < 0)
goto fail;
- revents &= ~POLLOUT;
-
- if (ret > 0)
- continue;
-
} else {
ssize_t l;
@@ -542,11 +552,11 @@ static void thread_func(void *userdata) {
l = snd_pcm_status_get_avail(status) * u->frame_size;
else
l = u->fragment_size;
-
- do {
+
+ while (l > 0) {
void *p;
snd_pcm_sframes_t t;
-
+
pa_assert(l > 0);
if (u->memchunk.length <= 0)
@@ -558,7 +568,7 @@ static void thread_func(void *userdata) {
t = snd_pcm_writei(u->pcm_handle, (uint8_t*) p + u->memchunk.index, u->memchunk.length / u->frame_size);
pa_memblock_release(u->memchunk.memblock);
-/* pa_log("wrote %i bytes of %u", t, l); */
+/* pa_log("wrote %i bytes of %u (%u)", t*u->frame_size, u->memchunk.length, l); */
pa_assert(t != 0);
@@ -572,12 +582,9 @@ static void thread_func(void *userdata) {
if ((t = snd_pcm_recover(u->pcm_handle, t, 1)) == 0)
continue;
- if (t == EAGAIN) {
- pa_log_debug("EAGAIN");
-
- revents &= ~POLLOUT;
+ if (t == -EAGAIN) {
+ pa_log_debug("EAGAIN");
break;
-
} else {
pa_log("Failed to write data to DSP: %s", snd_strerror(t));
goto fail;
@@ -594,24 +601,23 @@ static void thread_func(void *userdata) {
}
l -= t * u->frame_size;
-
- revents &= ~POLLOUT;
+
+ work_done = 1;
}
-
- } while (l > 0);
-
- continue;
+ }
}
- if (u->first) {
- pa_log_info("Starting playback.");
-
- if ((err = snd_pcm_start(u->pcm_handle)) < 0) {
- pa_log("Failed to start PCM playback: %s", snd_strerror(err));
- goto fail;
- }
+ revents &= ~POLLOUT;
+
+ if (work_done) {
- u->first = 0;
+ if (u->first) {
+ pa_log_info("Starting playback.");
+ snd_pcm_start(u->pcm_handle);
+ u->first = 0;
+ }
+
+ continue;
}
}
@@ -619,8 +625,8 @@ static void thread_func(void *userdata) {
if (pa_asyncmsgq_before_poll(u->asyncmsgq) < 0)
continue;
-/* pa_log("polling for %i", POLLFD_ALSA_BASE + (u->sink->thread_info.state != PA_SINK_SUSPENDED ? n_alsa_fds : 0)); */
- r = poll(pollfd, POLLFD_ALSA_BASE + (u->sink->thread_info.state != PA_SINK_SUSPENDED ? n_alsa_fds : 0), -1);
+/* pa_log("polling for %i", POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? n_alsa_fds : 0)); */
+ r = poll(pollfd, POLLFD_ALSA_BASE + (PA_SINK_OPENED(u->sink->thread_info.state) ? n_alsa_fds : 0), -1);
/*pa_log("polling got dsp=%i amq=%i (%i)", r > 0 ? pollfd[POLLFD_DSP].revents : 0, r > 0 ? pollfd[POLLFD_ASYNCQ].revents : 0, r); */
/* pa_log("poll end"); */
@@ -639,7 +645,7 @@ static void thread_func(void *userdata) {
pa_assert(r > 0);
- if (u->sink->thread_info.state != PA_SINK_SUSPENDED) {
+ if (PA_SINK_OPENED(u->sink->thread_info.state)) {
if ((err = snd_pcm_poll_descriptors_revents(u->pcm_handle, pollfd + POLLFD_ALSA_BASE, n_alsa_fds, &revents)) < 0) {
pa_log("snd_pcm_poll_descriptors_revents() failed: %s", snd_strerror(err));
goto fail;