diff options
author | Lennart Poettering <lennart@poettering.net> | 2008-04-20 20:16:55 +0000 |
---|---|---|
committer | Lennart Poettering <lennart@poettering.net> | 2008-04-20 20:16:55 +0000 |
commit | 62e7bc17c41c5542779a3c395a9d47d2bd306de2 (patch) | |
tree | 4445167f4164a8af45438519fee8202c14a35892 /src/pulsecore/source.c | |
parent | 7556ef5bfc37c99064d95857626bcf9f20423c70 (diff) |
Big pile of dependant changes:
* Change pa_memblockq to carry silence memchunk instead of memblock and adapt all users
* Add new call pa_sink_input_get_silence() to get the suitable silence block for a sink input
* Implement monitoring sources properly by adding a delay queue to even out rewinds
* Remove pa_{sink|source}_ping() becaused unnecessary these days and not used
* Fix naming of various rewind related functions. Downstream is now _request_rewind(), upstream is _process_rewind()
* Fix volume adjustments for a single stream in pa_sink_render()
* Properly handle prebuf-style buffer underruns in pa_sink_input
* Don't allow rewinding to more than the last underrun
* Rework default buffering metrics selection for native protocol
* New functions pa_memblockq_prebuf_active(), pa_memblockq_silence()
* add option "mixer_reset=" to module-alsa-sink
* Other cleanups
git-svn-id: file:///home/lennart/svn/public/pulseaudio/branches/glitch-free@2283 fefdeb5f-60dc-0310-8127-8f9354f1896f
Diffstat (limited to 'src/pulsecore/source.c')
-rw-r--r-- | src/pulsecore/source.c | 121 |
1 files changed, 81 insertions, 40 deletions
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 4f963325..0de78f41 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -99,6 +99,18 @@ void pa_source_new_data_done(pa_source_new_data *data) { pa_proplist_free(data->proplist); } +static void reset_callbacks(pa_source *s) { + pa_assert(s); + + s->set_state = NULL; + s->get_volume = NULL; + s->set_volume = NULL; + s->get_mute = NULL; + s->set_mute = NULL; + s->get_latency = NULL; + s->update_requested_latency = NULL; +} + pa_source* pa_source_new( pa_core *core, pa_source_new_data *data, @@ -171,25 +183,27 @@ pa_source* pa_source_new( s->muted = data->muted; s->refresh_volume = s->refresh_muted = FALSE; - s->min_latency = DEFAULT_MIN_LATENCY; - s->max_latency = s->min_latency; - - s->get_latency = NULL; - s->set_volume = NULL; - s->get_volume = NULL; - s->set_mute = NULL; - s->get_mute = NULL; - s->set_state = NULL; - s->update_requested_latency = NULL; + reset_callbacks(s); s->userdata = NULL; s->asyncmsgq = NULL; s->rtpoll = NULL; + pa_silence_memchunk_get( + &core->silence_cache, + core->mempool, + &s->silence, + &s->sample_spec, + 0); + + s->min_latency = DEFAULT_MIN_LATENCY; + s->max_latency = s->min_latency; + s->thread_info.outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); s->thread_info.soft_volume = s->volume; s->thread_info.soft_muted = s->muted; s->thread_info.state = s->state; + s->thread_info.max_rewind = 0; s->thread_info.requested_latency_valid = TRUE; s->thread_info.requested_latency = 0; @@ -247,8 +261,8 @@ void pa_source_put(pa_source *s) { pa_source_assert_ref(s); pa_assert(s->state == PA_SINK_INIT); - pa_assert(s->rtpoll); pa_assert(s->asyncmsgq); + pa_assert(s->rtpoll); pa_assert(!s->min_latency || !s->max_latency || s->min_latency <= s->max_latency); @@ -290,13 +304,7 @@ void pa_source_unlink(pa_source *s) { else s->state = PA_SOURCE_UNLINKED; - s->get_latency = NULL; - s->get_volume = NULL; - s->set_volume = NULL; - s->set_mute = NULL; - s->get_mute = NULL; - s->set_state = NULL; - s->update_requested_latency = NULL; + reset_callbacks(s); if (linked) { pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_REMOVE, s->index); @@ -323,6 +331,9 @@ static void source_free(pa_object *o) { pa_hashmap_free(s->thread_info.outputs, NULL, NULL); + if (s->silence.memblock) + pa_memblock_unref(s->silence.memblock); + pa_xfree(s->name); pa_xfree(s->driver); @@ -332,6 +343,20 @@ static void source_free(pa_object *o) { pa_xfree(s); } +void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) { + pa_source_assert_ref(s); + pa_assert(q); + + s->asyncmsgq = q; +} + +void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) { + pa_source_assert_ref(s); + pa_assert(p); + + s->rtpoll = p; +} + int pa_source_update_status(pa_source*s) { pa_source_assert_ref(s); pa_assert(PA_SOURCE_LINKED(s->state)); @@ -352,11 +377,22 @@ int pa_source_suspend(pa_source *s, pa_bool_t suspend) { return source_set_state(s, pa_source_used_by(s) ? PA_SOURCE_RUNNING : PA_SOURCE_IDLE); } -void pa_source_ping(pa_source *s) { +void pa_source_process_rewind(pa_source *s, size_t nbytes) { + pa_source_output *o; + void *state = NULL; + pa_source_assert_ref(s); - pa_assert(PA_SOURCE_LINKED(s->state)); + pa_assert(PA_SOURCE_OPENED(s->thread_info.state)); + + if (nbytes <= 0) + return; - pa_asyncmsgq_post(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_PING, NULL, 0, NULL, NULL); + pa_log_debug("Processing rewind..."); + + while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) { + pa_source_output_assert_ref(o); + pa_source_output_process_rewind(o, nbytes); + } } void pa_source_post(pa_source*s, const pa_memchunk *chunk) { @@ -381,14 +417,18 @@ void pa_source_post(pa_source*s, const pa_memchunk *chunk) { else pa_volume_memchunk(&vchunk, &s->sample_spec, &s->thread_info.soft_volume); - while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) + while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) { + pa_source_output_assert_ref(o); pa_source_output_push(o, &vchunk); + } pa_memblock_unref(vchunk.memblock); } else { - while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) + while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) { + pa_source_output_assert_ref(o); pa_source_output_push(o, chunk); + } } } @@ -497,6 +537,7 @@ void pa_source_set_description(pa_source *s, const char *description) { return; old = pa_proplist_gets(s->proplist, PA_PROP_DEVICE_DESCRIPTION); + if (old && description && !strcmp(old, description)) return; @@ -511,20 +552,6 @@ void pa_source_set_description(pa_source *s, const char *description) { } } -void pa_source_set_asyncmsgq(pa_source *s, pa_asyncmsgq *q) { - pa_source_assert_ref(s); - pa_assert(q); - - s->asyncmsgq = q; -} - -void pa_source_set_rtpoll(pa_source *s, pa_rtpoll *p) { - pa_source_assert_ref(s); - pa_assert(p); - - s->rtpoll = p; -} - unsigned pa_source_linked_by(pa_source *s) { pa_source_assert_ref(s); pa_assert(PA_SOURCE_LINKED(s->state)); @@ -555,6 +582,8 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_ pa_hashmap_put(s->thread_info.outputs, PA_UINT32_TO_PTR(o->index), pa_source_output_ref(o)); + pa_source_output_set_max_rewind(o, s->thread_info.max_rewind); + pa_assert(!o->thread_info.attached); o->thread_info.attached = TRUE; @@ -599,9 +628,6 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_ *((pa_bool_t*) userdata) = s->thread_info.soft_muted; return 0; - case PA_SOURCE_MESSAGE_PING: - return 0; - case PA_SOURCE_MESSAGE_SET_STATE: s->thread_info.state = PA_PTR_TO_UINT(userdata); return 0; @@ -731,6 +757,21 @@ pa_usec_t pa_source_get_requested_latency(pa_source *s) { return usec; } +void pa_source_set_max_rewind(pa_source *s, size_t max_rewind) { + pa_source_output *o; + void *state = NULL; + + pa_source_assert_ref(s); + + if (max_rewind == s->thread_info.max_rewind) + return; + + s->thread_info.max_rewind = max_rewind; + + while ((o = pa_hashmap_iterate(s->thread_info.outputs, &state, NULL))) + pa_source_output_set_max_rewind(o, s->thread_info.max_rewind); +} + void pa_source_invalidate_requested_latency(pa_source *s) { pa_source_assert_ref(s); |