From e4469df7c69316b49cad93dd288badc98fa1cad5 Mon Sep 17 00:00:00 2001 From: Sangchul Lee Date: Sat, 27 Aug 2016 21:33:17 +0900 Subject: [PATCH 3/6] volume ramp: adding volume ramping to sink-input The original patch is - https://review.tizen.org/git/?p=platform/upstream/pulseaudio.git;a=commit;h=98042248fd67ce0ab3807c5c472c0d5d8b0f99d3 - by Jaska Uimonen helsinki.fi> Signed-off-by: Sangchul Lee --- src/pulsecore/sink-input.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++ src/pulsecore/sink-input.h | 11 ++++++++- 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 8ec63b5..cc8953f 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -526,6 +526,11 @@ int pa_sink_input_new( reset_callbacks(i); i->userdata = NULL; + if (data->flags & PA_SINK_INPUT_START_RAMP_MUTED) + pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_MUTED, data->sample_spec.channels); + else + pa_cvolume_ramp_int_init(&i->ramp, PA_VOLUME_NORM, data->sample_spec.channels); + i->thread_info.state = i->state; i->thread_info.attached = false; pa_atomic_store(&i->thread_info.drained, 1); @@ -542,6 +547,8 @@ int pa_sink_input_new( i->thread_info.playing_for = 0; i->thread_info.direct_outputs = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func); + i->thread_info.ramp = i->ramp; + pa_assert_se(pa_idxset_put(core->sink_inputs, i, &i->index) == 0); pa_assert_se(pa_idxset_put(i->sink->inputs, pa_sink_input_ref(i), NULL) == 0); @@ -923,6 +930,8 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa while (tchunk.length > 0) { pa_memchunk wchunk; bool nvfs = need_volume_factor_sink; + pa_cvolume target; + pa_bool_t tmp; wchunk = tchunk; pa_memblock_ref(wchunk.memblock); @@ -959,6 +968,16 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &i->volume_factor_sink); } + /* check for possible volume ramp */ + if (pa_cvolume_ramp_active(&i->thread_info.ramp)) { + pa_memchunk_make_writable(&wchunk, 0); + pa_volume_ramp_memchunk(&wchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); + } else if ((tmp = pa_cvolume_ramp_target_active(&(i->thread_info.ramp)))) { + pa_memchunk_make_writable(&wchunk, 0); + pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); + pa_volume_memchunk(&wchunk, &i->sink->sample_spec, &target); + } + pa_memblockq_push_align(i->thread_info.render_memblockq, &wchunk); } else { pa_memchunk rchunk; @@ -975,6 +994,16 @@ void pa_sink_input_peek(pa_sink_input *i, size_t slength /* in sink bytes */, pa pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &i->volume_factor_sink); } + /* check for possible volume ramp */ + if (pa_cvolume_ramp_active(&(i->thread_info.ramp))) { + pa_memchunk_make_writable(&rchunk, 0); + pa_volume_ramp_memchunk(&rchunk, &i->sink->sample_spec, &(i->thread_info.ramp)); + } else if (pa_cvolume_ramp_target_active(&(i->thread_info.ramp))) { + pa_memchunk_make_writable(&rchunk, 0); + pa_cvolume_ramp_get_targets(&i->thread_info.ramp, &target); + pa_volume_memchunk(&rchunk, &i->sink->sample_spec, &target); + } + pa_memblockq_push_align(i->thread_info.render_memblockq, &rchunk); pa_memblock_unref(rchunk.memblock); } @@ -1339,6 +1368,31 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) { return 0; } +/* Called from main thread */ +void pa_sink_input_set_volume_ramp( + pa_sink_input *i, + const pa_cvolume_ramp *ramp, + pa_bool_t send_msg, + pa_bool_t save) { + + pa_sink_input_assert_ref(i); + pa_assert_ctl_context(); + pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); + pa_assert(ramp); + + pa_cvolume_ramp_convert(ramp, &i->ramp, i->sample_spec.rate); + + pa_log_debug("setting volume ramp with target vol:%d and length:%ld", + i->ramp.ramps[0].target, + i->ramp.ramps[0].length); + + + /* This tells the sink that volume ramp changed */ + if (send_msg) + pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, + NULL, 0, NULL) == 0); +} + /* Called from main context */ static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) { pa_sink_input_assert_ref(i); @@ -1932,6 +1986,13 @@ int pa_sink_input_process_msg(pa_msgobject *o, int code, void *userdata, int64_t } return 0; + case PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP: + /* we have ongoing ramp where we take current start values */ + pa_cvolume_ramp_start_from(&i->thread_info.ramp, &i->ramp); + i->thread_info.ramp = i->ramp; + pa_sink_input_request_rewind(i, 0, true, false, false); + return 0; + case PA_SINK_INPUT_MESSAGE_SET_SOFT_MUTE: if (i->thread_info.muted != i->muted) { i->thread_info.muted = i->muted; diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 86deab2..6e1b211 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -32,6 +32,7 @@ #include #include #include +#include typedef enum pa_sink_input_state { PA_SINK_INPUT_INIT, /*< The stream is not active yet, because pa_sink_input_put() has not been called yet */ @@ -58,7 +59,8 @@ typedef enum pa_sink_input_flags { PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256, PA_SINK_INPUT_NO_CREATE_ON_SUSPEND = 512, PA_SINK_INPUT_KILL_ON_SUSPEND = 1024, - PA_SINK_INPUT_PASSTHROUGH = 2048 + PA_SINK_INPUT_PASSTHROUGH = 2048, + PA_SINK_INPUT_START_RAMP_MUTED = 4096, } pa_sink_input_flags_t; struct pa_sink_input { @@ -121,6 +123,9 @@ struct pa_sink_input { * this.*/ bool save_sink:1, save_volume:1, save_muted:1; + /* for volume ramps */ + pa_cvolume_ramp_int ramp; + pa_resample_method_t requested_resample_method, actual_resample_method; /* Returns the chunk of audio data and drops it from the @@ -249,6 +254,8 @@ struct pa_sink_input { pa_usec_t requested_sink_latency; pa_hashmap *direct_outputs; + + pa_cvolume_ramp_int ramp; } thread_info; void *userdata; @@ -265,6 +272,7 @@ enum { PA_SINK_INPUT_MESSAGE_SET_STATE, PA_SINK_INPUT_MESSAGE_SET_REQUESTED_LATENCY, PA_SINK_INPUT_MESSAGE_GET_REQUESTED_LATENCY, + PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, PA_SINK_INPUT_MESSAGE_MAX }; @@ -370,6 +378,7 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, bool s void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa_cvolume *volume_factor); int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key); pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute); +void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, pa_bool_t send_msg, pa_bool_t save); void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save); -- 1.9.1