2017-03-28 19:36 GMT+09:00 Arun Raghavan <arun at arunraghavan.net>: > > > 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(). > I'll try that on the next patchset version. >> 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. There is a case that should not be applied ramp at first(no fade-out) but need to be applied ramp later on (fade-in). e.g) during trigger role's stream playing, ducking role's stream should be duck without fade-out when it is incoming, but need to fade-in right after the trigger role's stream is ended. you can check the usage in another patch regarding stream-interaction with fading. (https://patchwork.freedesktop.org/patch/100055/) >> +} >> + >> /* 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