diff options
author | Lennart Poettering <lennart@poettering.net> | 2008-05-09 22:48:37 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2008-05-09 22:48:37 +0000 |
commit | df92b23fa6e520127309c2f63e1f22c7d222e734 (patch) | |
tree | e12de600757d4ab8b76cef7828b2a9c604540af7 /src/pulsecore/sink.c | |
parent | 580d56358d9d15792613fc4be886c71059c58a36 (diff) |
- Fix moving of sink inputs between sinks
- Don't write more than a single buffer size in the ALSA driver at a time, to give the clients time to fill up the memblockq again
- Add API for querying the requested latency of a sink input/source output
- Drop get_letancy() from vtable of sinks/sources
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2392 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src/pulsecore/sink.c')
-rw-r--r-- | src/pulsecore/sink.c | 131 |
1 files changed, 65 insertions, 66 deletions
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index d3bacbfd..31c3cfc8 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -113,7 +113,6 @@ static void reset_callbacks(pa_sink *s) { s->set_volume = NULL; s->get_mute = NULL; s->set_mute = NULL; - s->get_latency = NULL; s->request_rewind = NULL; s->update_requested_latency = NULL; } @@ -769,9 +768,6 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) { if (!PA_SINK_IS_OPENED(s->state)) return 0; - if (s->get_latency) - return s->get_latency(s); - if (pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) return 0; @@ -930,6 +926,10 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse case PA_SINK_MESSAGE_ADD_INPUT: { pa_sink_input *i = PA_SINK_INPUT(userdata); + /* If you change anything here, make sure to change the + * sink input handling a few lines down at + * PA_SINK_MESSAGE_FINISH_MOVE, too. */ + pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i)); /* Since the caller sleeps in pa_sink_input_put(), we can @@ -965,10 +965,6 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse * slow start, i.e. need some time to buffer client * samples before beginning streaming. */ - /* If you change anything here, make sure to change the - * ghost sink input handling a few lines down at - * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */ - return 0; } @@ -977,7 +973,7 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse /* If you change anything here, make sure to change the * sink input handling a few lines down at - * PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER, too. */ + * PA_SINK_MESSAGE_PREPAPRE_MOVE, too. */ pa_sink_input_set_state_within_thread(i, i->state); @@ -1013,85 +1009,88 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse return 0; } - case PA_SINK_MESSAGE_REMOVE_INPUT_AND_BUFFER: { - pa_sink_input_move_info *info = userdata; - int volume_is_norm; + case PA_SINK_MESSAGE_START_MOVE: { + pa_sink_input *i = PA_SINK_INPUT(userdata); /* We don't support moving synchronized streams. */ - pa_assert(!info->sink_input->sync_prev); - pa_assert(!info->sink_input->sync_next); - pa_assert(!info->sink_input->thread_info.sync_next); - pa_assert(!info->sink_input->thread_info.sync_prev); + pa_assert(!i->sync_prev); + pa_assert(!i->sync_next); + pa_assert(!i->thread_info.sync_next); + pa_assert(!i->thread_info.sync_prev); - if (info->sink_input->detach) - info->sink_input->detach(info->sink_input); + if (i->thread_info.state != PA_SINK_INPUT_CORKED) { + pa_usec_t usec = 0; + size_t sink_nbytes, total_nbytes; - pa_assert(info->sink_input->thread_info.attached); - info->sink_input->thread_info.attached = FALSE; - pa_sink_invalidate_requested_latency(info->sink_input->sink); + /* Get the latency of the sink */ + if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) + usec = 0; - if (info->ghost_sink_input) { - pa_assert(info->buffer_bytes > 0); - pa_assert(info->buffer); + sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec); + total_nbytes = sink_nbytes + pa_memblockq_get_length(i->thread_info.render_memblockq); - volume_is_norm = pa_cvolume_is_norm(&info->sink_input->thread_info.volume); + if (total_nbytes > 0) { + i->thread_info.rewrite_nbytes = i->thread_info.resampler ? pa_resampler_request(i->thread_info.resampler, total_nbytes) : total_nbytes; + i->thread_info.rewrite_flush = TRUE; + pa_sink_input_process_rewind(i, sink_nbytes); + } + } - pa_log_debug("Buffering %lu bytes ...", (unsigned long) info->buffer_bytes); + if (i->detach) + i->detach(i); - while (info->buffer_bytes > 0) { - pa_memchunk memchunk; - pa_cvolume volume; - size_t n; + pa_assert(i->thread_info.attached); + i->thread_info.attached = FALSE; - if (pa_sink_input_peek(info->sink_input, info->buffer_bytes, &memchunk, &volume) < 0) - break; + /* Let's remove the sink input ...*/ + if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index))) + pa_sink_input_unref(i); - n = memchunk.length > info->buffer_bytes ? info->buffer_bytes : memchunk.length; - pa_sink_input_drop(info->sink_input, n); - memchunk.length = n; + pa_sink_invalidate_requested_latency(s); - if (!volume_is_norm) { - pa_memchunk_make_writable(&memchunk, 0); - pa_volume_memchunk(&memchunk, &s->sample_spec, &volume); - } + pa_log_debug("Requesting rewind due to started move"); + pa_sink_request_rewind(s, 0); - if (pa_memblockq_push(info->buffer, &memchunk) < 0) { - pa_memblock_unref(memchunk.memblock); - break; - } + return 0; + } - pa_memblock_unref(memchunk.memblock); - info->buffer_bytes -= n; - } + case PA_SINK_MESSAGE_FINISH_MOVE: { + pa_sink_input *i = PA_SINK_INPUT(userdata); - /* Add the remaining already resampled chunks to the buffer */ - pa_memblockq_splice(info->buffer, info->sink_input->thread_info.render_memblockq); + /* We don't support moving synchronized streams. */ + pa_assert(!i->sync_prev); + pa_assert(!i->sync_next); + pa_assert(!i->thread_info.sync_next); + pa_assert(!i->thread_info.sync_prev); - pa_memblockq_sink_input_set_queue(info->ghost_sink_input, info->buffer); + pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(i->index), pa_sink_input_ref(i)); - pa_log_debug("Buffered %lu bytes ...", (unsigned long) pa_memblockq_get_length(info->buffer)); - } + pa_assert(!i->thread_info.attached); + i->thread_info.attached = TRUE; - /* Let's remove the sink input ...*/ - if (pa_hashmap_remove(s->thread_info.inputs, PA_UINT32_TO_PTR(info->sink_input->index))) - pa_sink_input_unref(info->sink_input); + if (i->attach) + i->attach(i); - /* .. and add the ghost sink input instead */ - if (info->ghost_sink_input) { - pa_hashmap_put(s->thread_info.inputs, PA_UINT32_TO_PTR(info->ghost_sink_input->index), pa_sink_input_ref(info->ghost_sink_input)); - info->ghost_sink_input->thread_info.sync_prev = info->ghost_sink_input->thread_info.sync_next = NULL; + pa_sink_input_update_max_rewind(i, s->thread_info.max_rewind); - pa_sink_input_update_max_rewind(info->ghost_sink_input, s->thread_info.max_rewind); + pa_sink_input_set_requested_latency_within_thread(i, i->thread_info.requested_sink_latency); - pa_assert(!info->ghost_sink_input->thread_info.attached); - info->ghost_sink_input->thread_info.attached = TRUE; + if (i->thread_info.state != PA_SINK_INPUT_CORKED) { + pa_usec_t usec = 0; + size_t nbytes; - if (info->ghost_sink_input->attach) - info->ghost_sink_input->attach(info->ghost_sink_input); - } + /* Get the latency of the sink */ + if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0) + usec = 0; - pa_sink_invalidate_requested_latency(s); - pa_sink_request_rewind(s, 0); + nbytes = pa_usec_to_bytes(usec, &s->sample_spec); + + if (nbytes > 0) + pa_sink_input_drop(i, nbytes); + + pa_log_debug("Requesting rewind due to finished move"); + pa_sink_request_rewind(s, nbytes); + } return 0; } |