From 18e975fc5ef68a89875c77974570884b9214a009 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 20 Jul 2009 17:34:17 +0200 Subject: merged --- src/pulsecore/source-output.c | 114 ++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 42 deletions(-) (limited to 'src/pulsecore/source-output.c') diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 373d5637..4ba25ae4 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -87,7 +87,8 @@ static void reset_callbacks(pa_source_output *o) { o->attach = NULL; o->detach = NULL; o->suspend = NULL; - o->moved = NULL; + o->suspend_within_thread = NULL; + o->moving = NULL; o->kill = NULL; o->get_latency = NULL; o->state_change = NULL; @@ -434,11 +435,30 @@ void pa_source_output_push(pa_source_output *o, const pa_memchunk *chunk) { if (pa_memblockq_push(o->thread_info.delay_memblockq, chunk) < 0) { pa_log_debug("Delay queue overflow!"); - pa_memblockq_seek(o->thread_info.delay_memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE); + pa_memblockq_seek(o->thread_info.delay_memblockq, (int64_t) chunk->length, PA_SEEK_RELATIVE, TRUE); } limit = o->process_rewind ? 0 : o->source->thread_info.max_rewind; + if (limit > 0 && o->source->monitor_of) { + pa_usec_t latency; + size_t n; + + /* Hmm, check the latency for knowing how much of the buffered + * data is actually still unplayed and might hence still + * change. This is suboptimal. Ideally we'd have a call like + * pa_sink_get_changeable_size() or so that tells us how much + * of the queued data is actually still changeable. Hence + * FIXME! */ + + latency = pa_sink_get_latency_within_thread(o->source->monitor_of); + + n = pa_usec_to_bytes(latency, &o->source->sample_spec); + + if (n < limit) + limit = n; + } + /* Implement the delay queue */ while ((length = pa_memblockq_get_length(o->thread_info.delay_memblockq)) > limit) { pa_memchunk qchunk; @@ -515,27 +535,16 @@ void pa_source_output_update_max_rewind(pa_source_output *o, size_t nbytes /* i o->update_max_rewind(o, o->thread_info.resampler ? pa_resampler_result(o->thread_info.resampler, nbytes) : nbytes); } -/* Called from thread context */ -static pa_usec_t fixup_latency(pa_source *s, pa_usec_t usec) { - pa_source_assert_ref(s); - - if (usec == (pa_usec_t) -1) - return usec; - - if (s->thread_info.max_latency > 0 && usec > s->thread_info.max_latency) - usec = s->thread_info.max_latency; - - if (s->thread_info.min_latency > 0 && usec < s->thread_info.min_latency) - usec = s->thread_info.min_latency; - - return usec; -} - /* Called from thread context */ pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output *o, pa_usec_t usec) { pa_source_output_assert_ref(o); - usec = fixup_latency(o->source, usec); + if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY)) + usec = o->source->fixed_latency; + + if (usec != (pa_usec_t) -1) + usec = PA_CLAMP(usec, o->source->thread_info.min_latency, o->source->thread_info.max_latency); + o->thread_info.requested_source_latency = usec; pa_source_invalidate_requested_latency(o->source); @@ -546,31 +555,44 @@ pa_usec_t pa_source_output_set_requested_latency_within_thread(pa_source_output pa_usec_t pa_source_output_set_requested_latency(pa_source_output *o, pa_usec_t usec) { pa_source_output_assert_ref(o); - if (PA_SOURCE_OUTPUT_IS_LINKED(o->state)) + if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) { pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_SET_REQUESTED_LATENCY, &usec, 0, NULL) == 0); - else - /* If this source output is not realized yet, we have to touch - * the thread info data directly */ + return usec; + } - o->thread_info.requested_source_latency = usec; + /* If this source output is not realized yet or is being moved, we + * have to touch the thread info data directly */ + + if (o->source) { + if (!(o->source->flags & PA_SOURCE_DYNAMIC_LATENCY)) + usec = o->source->fixed_latency; + + if (usec != (pa_usec_t) -1) { + pa_usec_t min_latency, max_latency; + pa_source_get_latency_range(o->source, &min_latency, &max_latency); + usec = PA_CLAMP(usec, min_latency, max_latency); + } + } + + o->thread_info.requested_source_latency = usec; return usec; } /* Called from main context */ pa_usec_t pa_source_output_get_requested_latency(pa_source_output *o) { - pa_usec_t usec = 0; - pa_source_output_assert_ref(o); - if (PA_SOURCE_OUTPUT_IS_LINKED(o->state)) + if (PA_SOURCE_OUTPUT_IS_LINKED(o->state) && o->source) { + pa_usec_t usec = 0; pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o), PA_SOURCE_OUTPUT_MESSAGE_GET_REQUESTED_LATENCY, &usec, 0, NULL) == 0); - else - /* If this source output is not realized yet, we have to touch - * the thread info data directly */ - usec = o->thread_info.requested_source_latency; + return usec; + } - return usec; + /* If this source output is not realized yet or is being moved, we + * have to touch the thread info data directly */ + + return o->thread_info.requested_source_latency; } /* Called from main context */ @@ -707,6 +729,8 @@ int pa_source_output_start_move(pa_source_output *o) { pa_source_update_status(o->source); o->source = NULL; + pa_source_output_unref(o); + return 0; } @@ -749,9 +773,12 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t } else new_resampler = NULL; + if (o->moving) + o->moving(o, dest); + o->source = dest; o->save_source = save; - pa_idxset_put(o->source->outputs, o, NULL); + pa_idxset_put(o->source->outputs, pa_source_output_ref(o), NULL); if (pa_source_output_get_state(o) == PA_SOURCE_OUTPUT_CORKED) o->source->n_corked++; @@ -776,14 +803,12 @@ int pa_source_output_finish_move(pa_source_output *o, pa_source *dest, pa_bool_t } pa_source_update_status(dest); + pa_assert_se(pa_asyncmsgq_send(o->source->asyncmsgq, PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_ADD_OUTPUT, o, 0, NULL) == 0); pa_log_debug("Successfully moved source output %i to %s.", o->index, dest->name); /* Notify everyone */ - if (o->moved) - o->moved(o); - pa_hook_fire(&o->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_MOVE_FINISH], o); pa_subscription_post(o->core, PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT|PA_SUBSCRIPTION_EVENT_CHANGE, o->index); @@ -805,11 +830,19 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest, pa_bool_t sav if (!pa_source_output_may_move_to(o, dest)) return -PA_ERR_NOTSUPPORTED; - if ((r = pa_source_output_start_move(o)) < 0) + pa_source_output_ref(o); + + if ((r = pa_source_output_start_move(o)) < 0) { + pa_source_output_unref(o); return r; + } - if ((r = pa_source_output_finish_move(o, dest, save)) < 0) + if ((r = pa_source_output_finish_move(o, dest, save)) < 0) { + pa_source_output_unref(o); return r; + } + + pa_source_output_unref(o); return 0; } @@ -836,12 +869,9 @@ int pa_source_output_process_msg(pa_msgobject *mo, int code, void *userdata, int case PA_SOURCE_OUTPUT_MESSAGE_GET_LATENCY: { pa_usec_t *r = userdata; - pa_usec_t source_usec = 0; r[0] += pa_bytes_to_usec(pa_memblockq_get_length(o->thread_info.delay_memblockq), &o->source->sample_spec); - - if (o->source->parent.process_msg(PA_MSGOBJECT(o->source), PA_SOURCE_MESSAGE_GET_LATENCY, &source_usec, 0, NULL) >= 0) - r[1] += source_usec; + r[1] += pa_source_get_latency_within_thread(o->source); return 0; } -- cgit