On Sat, 27 Aug 2016, at 06:03 PM, Sangchul Lee wrote: > The original patch is > - > https://review.tizen.org/git/?p=platform/upstream/pulseaudio.git;a=commit;h=98042248fd67ce0ab3807c5c472c0d5d8b0f99d3 > - by Jaska Uimonen <jaska.uimonen <at> helsinki.fi> > > Signed-off-by: Sangchul Lee <sc11.lee at samsung.com> > --- > src/pulsecore/sink-input.c | 61 > ++++++++++++++++++++++++++++++++++++++++++++++ > src/pulsecore/sink-input.h | 12 ++++++++- > 2 files changed, 72 insertions(+), 1 deletion(-) > > diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c > index 435e63e..ae76c05 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); > > @@ -921,6 +928,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); > @@ -957,6 +966,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; > @@ -973,6 +992,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); > + } > + This segment is repeated twice. Would be nicer to factor out into something like a check_and_apply_ramp(). > pa_memblockq_push_align(i->thread_info.render_memblockq, > &rchunk); > pa_memblock_unref(rchunk.memblock); > } > @@ -1337,6 +1366,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); When would send_msg be false? Same question applies to your later patch which adds this to the ramp volume factor API. > +} > + > /* Called from main context */ > static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) { > pa_sink_input_assert_ref(i); > @@ -2015,6 +2069,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 8bbee4e..85a0e54 100644 > --- a/src/pulsecore/sink-input.h > +++ b/src/pulsecore/sink-input.h > @@ -32,6 +32,7 @@ > #include <pulsecore/client.h> > #include <pulsecore/sink.h> > #include <pulsecore/core.h> > +#include <pulsecore/mix.h> > > 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 > }; > > @@ -368,11 +376,13 @@ 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); > > void pa_sink_input_set_property(pa_sink_input *i, const char *key, const > char *value); > void pa_sink_input_set_property_arbitrary(pa_sink_input *i, const char > *key, const uint8_t *value, size_t nbytes); > + > void pa_sink_input_update_proplist(pa_sink_input *i, pa_update_mode_t > mode, pa_proplist *p); > > pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input > *i); > -- -- Arun