From 6afbbba1025d04ee5ebeadba563c138e1d7b2aed Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 28 Jul 2007 22:56:39 +0000 Subject: [PATCH] fix suspending logic git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/lennart@1559 fefdeb5f-60dc-0310-8127-8f9354f1896f --- src/modules/module-oss.c | 149 ++++++++++++++++++++++++++++------------------- 1 file changed, 89 insertions(+), 60 deletions(-) diff --git a/src/modules/module-oss.c b/src/modules/module-oss.c index 7ead678..63f4d40 100644 --- a/src/modules/module-oss.c +++ b/src/modules/module-oss.c @@ -158,18 +158,20 @@ static const char* const valid_modargs[] = { static void trigger(struct userdata *u, int quick) { int enable_bits = 0, zero = 0; -/* pa_log_debug("trigger"); */ + if (u->fd < 0) + return; + + pa_log_debug("trigger"); - if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED) + if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) enable_bits |= PCM_ENABLE_INPUT; - if (u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED) + if (u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) enable_bits |= PCM_ENABLE_OUTPUT; if (u->use_mmap) { if (!quick) - /* First, let's stop all playback, capturing */ ioctl(u->fd, SNDCTL_DSP_SETTRIGGER, &zero); #ifdef SNDCTL_DSP_HALT @@ -199,7 +201,7 @@ static void trigger(struct userdata *u, int quick) { * register the fd as ready. */ - if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED) { + if (u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) { uint8_t *buf = pa_xnew(uint8_t, u->in_fragment_size); pa_read(u->fd, buf, u->in_fragment_size, NULL); pa_xfree(buf); @@ -212,6 +214,8 @@ static void mmap_fill_memblocks(struct userdata *u, unsigned n) { pa_assert(u); pa_assert(u->out_mmap_memblocks); +/* pa_log("Mmmap writing %u blocks", n); */ + while (n > 0) { pa_memchunk chunk; @@ -241,10 +245,11 @@ static void mmap_fill_memblocks(struct userdata *u, unsigned n) { static int mmap_write(struct userdata *u) { struct count_info info; - pa_assert(u); pa_assert(u->sink); +/* pa_log("Mmmap writing..."); */ + if (ioctl(u->fd, SNDCTL_DSP_GETOPTR, &info) < 0) { pa_log("SNDCTL_DSP_GETOPTR: %s", pa_cstrerror(errno)); return -1; @@ -263,6 +268,8 @@ static void mmap_post_memblocks(struct userdata *u, unsigned n) { pa_assert(u); pa_assert(u->in_mmap_memblocks); +/* pa_log("Mmmap reading %u blocks", n); */ + while (n > 0) { pa_memchunk chunk; @@ -317,6 +324,8 @@ static int mmap_read(struct userdata *u) { pa_assert(u); pa_assert(u->source); +/* pa_log("Mmmap reading..."); */ + if (ioctl(u->fd, SNDCTL_DSP_GETIPTR, &info) < 0) { pa_log("SNDCTL_DSP_GETIPTR: %s", pa_cstrerror(errno)); return -1; @@ -437,6 +446,8 @@ static int suspend(struct userdata *u) { pa_assert(u); pa_assert(u->fd >= 0); + pa_log_debug("Suspending..."); + if (u->out_mmap_memblocks) { unsigned i; for (i = 0; i < u->out_nfrags; i++) @@ -559,15 +570,7 @@ static int unsuspend(struct userdata *u) { u->out_mmap_current = u->in_mmap_current = 0; u->out_mmap_saved_nfrags = u->in_mmap_saved_nfrags = 0; - - if (u->sink) - pa_sink_get_volume(u->sink); - if (u->source) - pa_source_get_volume(u->source); - /* Now, start only what we need */ - trigger(u, 0); - pa_log_debug("Resumed successfully..."); return 0; @@ -580,7 +583,7 @@ fail: static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) { struct userdata *u = PA_SINK(o)->userdata; - int do_trigger = 0, ret; + int do_trigger = 0, ret, quick = 1; switch (code) { @@ -601,30 +604,44 @@ 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); + switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) { - if (u->source_suspended) { - if (suspend(u) < 0) - return -1; - } else - do_trigger = 1; + case PA_SINK_SUSPENDED: + pa_assert(PA_SINK_OPENED(u->sink->thread_info.state)); - u->sink_suspended = 1; - - } else if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { - pa_assert(PA_PTR_TO_UINT(data) != PA_SINK_SUSPENDED); + if (!u->source || u->source_suspended) { + if (suspend(u) < 0) + return -1; + } - if (u->source_suspended) { - if (unsuspend(u) < 0) - return -1; - } else do_trigger = 1; - u->out_mmap_current = 0; - u->out_mmap_saved_nfrags = 0; + u->sink_suspended = 1; + break; + + case PA_SINK_IDLE: + case PA_SINK_RUNNING: + + if (u->sink->thread_info.state == PA_SINK_SUSPENDED) { + + if (!u->source || u->source_suspended) { + if (unsuspend(u) < 0) + return -1; + quick = 0; + } + + do_trigger = 1; + + u->out_mmap_current = 0; + u->out_mmap_saved_nfrags = 0; + + u->sink_suspended = 0; + } + + break; - u->sink_suspended = 0; + case PA_SINK_DISCONNECTED: + ; } break; @@ -659,14 +676,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk * ret = pa_sink_process_msg(o, code, data, chunk); if (do_trigger) - trigger(u, 1); + trigger(u, quick); return ret; } static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk *chunk) { struct userdata *u = PA_SOURCE(o)->userdata; - int do_trigger = 0, ret; + int do_trigger = 0, ret, quick = 1; switch (code) { @@ -686,32 +703,44 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk case PA_SOURCE_MESSAGE_SET_STATE: - if (PA_PTR_TO_UINT(data) == PA_SOURCE_SUSPENDED) { - pa_assert(u->source->thread_info.state != PA_SOURCE_SUSPENDED); + switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) { + case PA_SOURCE_SUSPENDED: + pa_assert(PA_SOURCE_OPENED(u->source->thread_info.state)); + + if (!u->sink || u->sink_suspended) { + if (suspend(u) < 0) + return -1; + } - if (u->sink_suspended) { - if (suspend(u) < 0) - return -1; - } else do_trigger = 1; + + u->source_suspended = 1; + break; - u->source_suspended = 1; + case PA_SOURCE_IDLE: + case PA_SOURCE_RUNNING: + + if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) { - } else if (u->source->thread_info.state == PA_SOURCE_SUSPENDED) { - pa_assert(PA_PTR_TO_UINT(data) != PA_SOURCE_SUSPENDED); + if (!u->sink || u->sink_suspended) { + if (unsuspend(u) < 0) + return -1; + quick = 0; + } - if (u->sink_suspended) { - if (unsuspend(u) < 0) - return -1; - } else - do_trigger = 1; - - u->in_mmap_current = 0; - u->in_mmap_saved_nfrags = 0; + do_trigger = 1; + + u->in_mmap_current = 0; + u->in_mmap_saved_nfrags = 0; + + u->source_suspended = 0; + } + break; - u->source_suspended = 0; - } + case PA_SOURCE_DISCONNECTED: + ; + } break; case PA_SOURCE_MESSAGE_SET_VOLUME: @@ -744,7 +773,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, pa_memchunk ret = pa_source_process_msg(o, code, data, chunk); if (do_trigger) - trigger(u, 1); + trigger(u, quick); return ret; } @@ -779,7 +808,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) { @@ -801,7 +830,7 @@ static void thread_func(void *userdata) { /* Render some data and write it to the dsp */ - if (u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED && (pollfd[POLLFD_DSP].revents & POLLOUT)) { + if (u->sink && u->sink->thread_info.state != PA_SINK_DISCONNECTED && u->fd >= 0 && (pollfd[POLLFD_DSP].revents & POLLOUT)) { if (u->use_mmap) { int ret; @@ -892,7 +921,7 @@ static void thread_func(void *userdata) { /* Try to read some data and pass it on to the source driver */ - if (u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED && ((pollfd[POLLFD_DSP].revents & POLLIN))) { + if (u->source && u->source->thread_info.state != PA_SOURCE_DISCONNECTED && u->fd >= 0 && ((pollfd[POLLFD_DSP].revents & POLLIN))) { if (u->use_mmap) { int ret; @@ -980,8 +1009,8 @@ static void thread_func(void *userdata) { if (u->fd >= 0) { pollfd[POLLFD_DSP].fd = u->fd; pollfd[POLLFD_DSP].events = - ((u->source && u->source->thread_info.state != PA_SOURCE_SUSPENDED) ? POLLIN : 0) | - ((u->sink && u->sink->thread_info.state != PA_SINK_SUSPENDED) ? POLLOUT : 0); + ((u->source && PA_SOURCE_OPENED(u->source->thread_info.state)) ? POLLIN : 0) | + ((u->sink && PA_SINK_OPENED(u->sink->thread_info.state)) ? POLLOUT : 0); } /* Hmm, nothing to do. Let's sleep */ -- 2.7.4