From eab1cb8df952bc302d14efd1640d96f8bbdb148a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 26 Jun 2008 02:56:00 +0200 Subject: make sure to call process_rewind() under all circumstances before we do the next loop iteration --- src/modules/module-alsa-sink.c | 11 +++++++---- src/modules/module-combine.c | 1 - src/modules/module-esound-sink.c | 4 ++++ src/modules/module-jack-sink.c | 4 ++++ src/modules/module-null-sink.c | 8 ++++++-- src/modules/module-pipe-sink.c | 8 ++++++-- src/modules/module-tunnel.c | 6 ++++++ src/pulsecore/sink-input.c | 23 +++++++++++----------- src/pulsecore/sink.c | 42 +++++++++++++++++++++++----------------- src/pulsecore/sink.h | 1 + 10 files changed, 69 insertions(+), 39 deletions(-) (limited to 'src') diff --git a/src/modules/module-alsa-sink.c b/src/modules/module-alsa-sink.c index 6765775a..5818dee2 100644 --- a/src/modules/module-alsa-sink.c +++ b/src/modules/module-alsa-sink.c @@ -882,7 +882,7 @@ static void sink_update_requested_latency_cb(pa_sink *s) { if (u->hwbuf_unused_frames > before) { pa_log_debug("Requesting rewind due to latency change."); - pa_sink_request_rewind(s, 0); + pa_sink_request_rewind(s, (size_t) -1); } } @@ -967,9 +967,12 @@ static void thread_func(void *userdata) { int work_done; pa_usec_t sleep_usec; - if (u->sink->thread_info.rewind_nbytes > 0) - if (process_rewind(u) < 0) - goto fail; + if (u->sink->thread_info.rewind_requested) { + if (u->sink->thread_info.rewind_nbytes <= 0) + pa_sink_process_rewind(u->sink, 0); + else if (process_rewind(u) < 0) + goto fail; + } if (u->use_mmap) work_done = mmap_write(u, &sleep_usec); diff --git a/src/modules/module-combine.c b/src/modules/module-combine.c index 8c155da0..7d8e140b 100644 --- a/src/modules/module-combine.c +++ b/src/modules/module-combine.c @@ -410,7 +410,6 @@ static void sink_input_process_rewind_cb(pa_sink_input *i, size_t nbytes) { struct output *o; pa_sink_input_assert_ref(i); - pa_assert(nbytes > 0); pa_assert_se(o = i->userdata); pa_memblockq_rewind(o->memblockq, nbytes); diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c index e189febd..6ca64978 100644 --- a/src/modules/module-esound-sink.c +++ b/src/modules/module-esound-sink.c @@ -204,6 +204,10 @@ static void thread_func(void *userdata) { for (;;) { int ret; + if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) + if (u->sink->thread_info.rewind_requested) + pa_sink_process_rewind(u->sink, 0); + if (u->rtpoll_item) { struct pollfd *pollfd; pollfd = pa_rtpoll_item_get_pollfd(u->rtpoll_item, NULL); diff --git a/src/modules/module-jack-sink.c b/src/modules/module-jack-sink.c index c4d47f8e..edc543a8 100644 --- a/src/modules/module-jack-sink.c +++ b/src/modules/module-jack-sink.c @@ -222,6 +222,10 @@ static void thread_func(void *userdata) { for (;;) { int ret; + if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) + if (u->sink->thread_info.rewind_requested) + pa_sink_process_rewind(u->sink, 0); + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) goto fail; diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c index 604ab158..9162960f 100644 --- a/src/modules/module-null-sink.c +++ b/src/modules/module-null-sink.c @@ -204,8 +204,12 @@ static void thread_func(void *userdata) { now = pa_rtclock_usec(); - if (u->sink->thread_info.rewind_nbytes > 0) - process_rewind(u, now); + if (u->sink->thread_info.rewind_requested) { + if (u->sink->thread_info.rewind_nbytes > 0) + process_rewind(u, now); + else + pa_sink_process_rewind(u->sink, 0); + } if (u->timestamp <= now) process_render(u, now); diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c index cd25b890..0999935b 100644 --- a/src/modules/module-pipe-sink.c +++ b/src/modules/module-pipe-sink.c @@ -184,8 +184,12 @@ static void thread_func(void *userdata) { /* Render some data and write it to the fifo */ if (u->sink->thread_info.state == PA_SINK_RUNNING) { - if (u->sink->thread_info.rewind_nbytes > 0) - process_rewind(u); + if (u->sink->thread_info.rewind_requested) { + if (u->sink->thread_info.rewind_nbytes > 0) + process_rewind(u); + else + pa_sink_process_rewind(u->sink, 0); + } if (pollfd->revents) { if (process_render(u) < 0) diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index 86f30817..1890646f 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -605,6 +605,12 @@ static void thread_func(void *userdata) { for (;;) { int ret; +#ifdef TUNNEL_SINK + if (PA_SINK_IS_OPENED(u->sink->thread_info.state)) + if (u->sink->thread_info.rewind_requested) + pa_sink_process_rewind(u->sink, 0); +#endif + if ((ret = pa_rtpoll_run(u->rtpoll, TRUE)) < 0) goto fail; diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index be169709..4086b85b 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -491,12 +491,6 @@ int pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink frames */, pa i->thread_info.state == PA_SINK_INPUT_CORKED || i->thread_info.state == PA_SINK_INPUT_DRAINED); - /* If there's still some rewrite request the handle, but the sink - didn't do this for us, we do it here. However, since the sink - apparently doesn't support rewinding, we pass 0 here. This still - allows rewinding through the render buffer. */ - pa_sink_input_process_rewind(i, 0); - block_size_max_sink_input = i->thread_info.resampler ? pa_resampler_max_block_size(i->thread_info.resampler) : pa_frame_align(pa_mempool_block_size_max(i->sink->core->mempool), &i->sample_spec); @@ -633,18 +627,13 @@ void pa_sink_input_drop(pa_sink_input *i, size_t nbytes /* in sink sample spec * /* pa_log_debug("dropping %lu", (unsigned long) nbytes); */ - /* If there's still some rewrite request the handle, but the sink - didn't do this for us, we do it here. However, since the sink - apparently doesn't support rewinding, we pass 0 here. This still - allows rewinding through the render buffer. */ - pa_sink_input_process_rewind(i, 0); - pa_memblockq_drop(i->thread_info.render_memblockq, nbytes); } /* Called from thread context */ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sample spec */) { size_t lbq; + pa_bool_t called; pa_sink_input_assert_ref(i); pa_assert(PA_SINK_INPUT_IS_LINKED(i->thread_info.state)); @@ -685,6 +674,7 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam /* Tell the implementor */ if (i->process_rewind) i->process_rewind(i, amount); + called = TRUE; /* Convert back to to sink domain */ if (i->thread_info.resampler) @@ -703,6 +693,10 @@ void pa_sink_input_process_rewind(pa_sink_input *i, size_t nbytes /* in sink sam } } + if (!called) + if (i->process_rewind) + i->process_rewind(i, 0); + i->thread_info.rewrite_nbytes = 0; i->thread_info.rewrite_flush = FALSE; } @@ -1143,6 +1137,8 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam pa_sink_input_assert_ref(i); pa_assert(i->thread_info.rewrite_nbytes == 0); +/* pa_log_debug("request rewrite %lu", (unsigned long) nbytes); */ + /* We don't take rewind requests while we are corked */ if (i->thread_info.state == PA_SINK_INPUT_CORKED) return; @@ -1184,6 +1180,9 @@ void pa_sink_input_request_rewind(pa_sink_input *i, size_t nbytes /* in our sam if (nbytes > lbq) pa_sink_request_rewind(i->sink, nbytes - lbq); + else + /* This call will make sure process_rewind() is called later */ + pa_sink_request_rewind(i->sink, 0); } /* Called from main context */ diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index edb023b2..0866829a 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -212,6 +212,7 @@ pa_sink* pa_sink_new( s->thread_info.soft_muted = FALSE; s->thread_info.state = s->state; s->thread_info.rewind_nbytes = 0; + s->thread_info.rewind_requested = FALSE; s->thread_info.max_rewind = 0; s->thread_info.max_request = 0; s->thread_info.requested_latency_valid = FALSE; @@ -454,21 +455,20 @@ void pa_sink_process_rewind(pa_sink *s, size_t nbytes) { pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->thread_info.state)); - /* Make sure the sink code already reset the counter! */ - pa_assert(s->thread_info.rewind_nbytes <= 0); - - if (nbytes <= 0) - return; + s->thread_info.rewind_nbytes = 0; + s->thread_info.rewind_requested = FALSE; - pa_log_debug("Processing rewind..."); + if (nbytes > 0) + pa_log_debug("Processing rewind..."); while ((i = pa_hashmap_iterate(s->thread_info.inputs, &state, NULL))) { pa_sink_input_assert_ref(i); pa_sink_input_process_rewind(i, nbytes); } - if (s->monitor_source && PA_SOURCE_IS_OPENED(s->monitor_source->thread_info.state)) - pa_source_process_rewind(s->monitor_source, nbytes); + if (nbytes > 0) + if (s->monitor_source && PA_SOURCE_IS_OPENED(s->monitor_source->thread_info.state)) + pa_source_process_rewind(s->monitor_source, nbytes); } /* Called from IO thread context */ @@ -620,7 +620,8 @@ void pa_sink_render(pa_sink*s, size_t length, pa_memchunk *result) { pa_sink_ref(s); - s->thread_info.rewind_nbytes = 0; + pa_assert(!s->thread_info.rewind_requested); + pa_assert(s->thread_info.rewind_nbytes == 0); if (length <= 0) length = pa_frame_align(MIX_BUFFER_LENGTH, &s->sample_spec); @@ -696,7 +697,8 @@ void pa_sink_render_into(pa_sink*s, pa_memchunk *target) { pa_sink_ref(s); - s->thread_info.rewind_nbytes = 0; + pa_assert(!s->thread_info.rewind_requested); + pa_assert(s->thread_info.rewind_nbytes == 0); length = target->length; block_size_max = pa_mempool_block_size_max(s->core->mempool); @@ -774,7 +776,8 @@ void pa_sink_render_into_full(pa_sink *s, pa_memchunk *target) { pa_sink_ref(s); - s->thread_info.rewind_nbytes = 0; + pa_assert(!s->thread_info.rewind_requested); + pa_assert(s->thread_info.rewind_nbytes == 0); l = target->length; d = 0; @@ -800,7 +803,8 @@ void pa_sink_render_full(pa_sink *s, size_t length, pa_memchunk *result) { pa_assert(pa_frame_aligned(length, &s->sample_spec)); pa_assert(result); - s->thread_info.rewind_nbytes = 0; + pa_assert(!s->thread_info.rewind_requested); + pa_assert(s->thread_info.rewind_nbytes == 0); /*** This needs optimization ***/ @@ -1067,7 +1071,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse pa_sink_input_unref(i); pa_sink_invalidate_requested_latency(s); - pa_sink_request_rewind(s, 0); + pa_sink_request_rewind(s, (size_t) -1); return 0; } @@ -1112,7 +1116,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse pa_sink_invalidate_requested_latency(s); pa_log_debug("Requesting rewind due to started move"); - pa_sink_request_rewind(s, 0); + pa_sink_request_rewind(s, (size_t) -1); return 0; } @@ -1162,13 +1166,13 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse case PA_SINK_MESSAGE_SET_VOLUME: s->thread_info.soft_volume = *((pa_cvolume*) userdata); - pa_sink_request_rewind(s, 0); + pa_sink_request_rewind(s, (size_t) -1); return 0; case PA_SINK_MESSAGE_SET_MUTE: s->thread_info.soft_muted = PA_PTR_TO_UINT(userdata); - pa_sink_request_rewind(s, 0); + pa_sink_request_rewind(s, (size_t) -1); return 0; case PA_SINK_MESSAGE_GET_VOLUME: @@ -1309,15 +1313,17 @@ void pa_sink_request_rewind(pa_sink*s, size_t nbytes) { pa_sink_assert_ref(s); pa_assert(PA_SINK_IS_LINKED(s->thread_info.state)); - if (nbytes <= 0) + if (nbytes == (size_t) -1) nbytes = s->thread_info.max_rewind; nbytes = PA_MIN(nbytes, s->thread_info.max_rewind); - if (nbytes <= s->thread_info.rewind_nbytes) + if (s->thread_info.rewind_requested && + nbytes <= s->thread_info.rewind_nbytes) return; s->thread_info.rewind_nbytes = nbytes; + s->thread_info.rewind_requested = TRUE; if (s->request_rewind) s->request_rewind(s); diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index b73944e8..604be269 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -145,6 +145,7 @@ struct pa_sink { /* Maximum of what clients requested to rewind in this cycle */ size_t rewind_nbytes; + pa_bool_t rewind_requested; pa_usec_t min_latency; /* we won't go below this latency */ pa_usec_t max_latency; /* An upper limit for the latencies */ -- cgit