1 --- a/src/pulsecore/sink.c 2016-04-12 18:01:23.403957855 +0200
2 +++ b/src/pulsecore/sink.c 2016-04-12 18:44:49.677953506 +0200
7 + pa_cvolume_ramp_int_init(&s->ramp, PA_VOLUME_NORM, data->sample_spec.channels);
9 s->thread_info.rtpoll = NULL;
10 s->thread_info.inputs = pa_hashmap_new_full(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func, NULL,
11 (pa_free_cb_t) pa_sink_input_unref);
13 s->thread_info.volume_change_extra_delay = core->deferred_volume_extra_delay_usec;
14 s->thread_info.latency_offset = s->latency_offset;
16 + s->thread_info.ramp = s->ramp;
18 /* FIXME: This should probably be moved to pa_sink_put() */
19 pa_assert_se(pa_idxset_put(core->sinks, s, &s->index) >= 0);
27 *result = info[0].chunk;
28 pa_memblock_ref(result->memblock);
29 @@ -1198,9 +1203,20 @@
33 - } else if (!pa_cvolume_is_norm(&volume)) {
34 + } else if (!pa_cvolume_is_norm(&volume) || pa_cvolume_ramp_target_active(&s->thread_info.ramp) || pa_cvolume_ramp_active(&s->thread_info.ramp)) {
35 pa_memchunk_make_writable(result, 0);
36 - pa_volume_memchunk(result, &s->sample_spec, &volume);
37 + if (!pa_cvolume_ramp_active(&s->thread_info.ramp)) {
38 + if (!pa_cvolume_is_norm(&volume))
39 + pa_volume_memchunk(result, &s->sample_spec, &volume);
40 + pa_volume_ramp_memchunk(result, &s->sample_spec, &(s->thread_info.ramp));
43 + if (pa_cvolume_ramp_target_active(&s->thread_info.ramp)) {
44 + pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target);
45 + pa_sw_cvolume_multiply(&volume, &volume, &target);
47 + pa_volume_memchunk(result, &s->sample_spec, &volume);
56 + pa_cvolume target_vol;
58 ptr = pa_memblock_acquire(target->memblock);
60 @@ -1299,6 +1316,15 @@
61 &s->thread_info.soft_volume,
62 s->thread_info.soft_muted);
64 + if (pa_cvolume_ramp_target_active(&s->thread_info.ramp) || pa_cvolume_ramp_active(&s->thread_info.ramp)) {
65 + if (pa_cvolume_ramp_active(&s->thread_info.ramp))
66 + pa_volume_ramp_memchunk(target, &s->sample_spec, &(s->thread_info.ramp));
68 + pa_cvolume_ramp_get_targets(&s->thread_info.ramp, &target_vol);
69 + pa_volume_memchunk(target, &s->sample_spec, &target_vol);
73 pa_memblock_release(target->memblock);
76 @@ -2058,6 +2084,32 @@
77 pa_assert_se(pa_asyncmsgq_send(root_sink->asyncmsgq, PA_MSGOBJECT(root_sink), PA_SINK_MESSAGE_SET_SHARED_VOLUME, NULL, 0, NULL) == 0);
80 +/* Called from main thread */
81 +void pa_sink_set_volume_ramp(
83 + const pa_cvolume_ramp *ramp,
87 + pa_sink_assert_ref(s);
88 + pa_assert_ctl_context();
89 + pa_assert(PA_SINK_IS_LINKED(s->state));
92 + /* make sure we don't change the volume when a PASSTHROUGH input is connected ...
93 + * ... *except* if we're being invoked to reset the volume to ensure 0 dB gain */
94 + if (pa_sink_is_passthrough(s)) {
95 + pa_log_warn("Cannot do volume ramp, Sink is connected to PASSTHROUGH input");
99 + pa_cvolume_ramp_convert(ramp, &s->ramp, s->sample_spec.rate);
101 + /* This tells the sink that volume ramp changed */
103 + pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
106 /* Called from the io thread if sync volume is used, otherwise from the main thread.
107 * Only to be called by sink implementor */
108 void pa_sink_set_soft_volume(pa_sink *s, const pa_cvolume *volume) {
109 @@ -2713,6 +2765,12 @@
110 sync_input_volumes_within_thread(s);
113 + case PA_SINK_MESSAGE_SET_VOLUME_RAMP:
114 + /* if we have ongoing ramp where we take current start values */
115 + pa_cvolume_ramp_start_from(&s->thread_info.ramp, &s->ramp);
116 + s->thread_info.ramp = s->ramp;
119 case PA_SINK_MESSAGE_GET_VOLUME:
121 if ((s->flags & PA_SINK_DEFERRED_VOLUME) && s->get_volume) {
122 --- a/src/pulsecore/sink.h 2016-04-12 18:01:42.117957824 +0200
123 +++ b/src/pulsecore/sink.h 2016-04-12 18:23:29.394955642 +0200
125 pa_cvolume saved_volume;
126 bool saved_save_volume:1;
128 + /* for volume ramps */
129 + pa_cvolume_ramp_int ramp;
131 pa_asyncmsgq *asyncmsgq;
135 uint32_t volume_change_safety_margin;
136 /* Usec delay added to all volume change events, may be negative. */
137 int32_t volume_change_extra_delay;
139 + pa_cvolume_ramp_int ramp;
144 PA_SINK_MESSAGE_SET_MAX_REQUEST,
145 PA_SINK_MESSAGE_SET_PORT,
146 PA_SINK_MESSAGE_UPDATE_VOLUME_AND_MUTE,
147 + PA_SINK_MESSAGE_SET_VOLUME_RAMP,
148 PA_SINK_MESSAGE_SET_LATENCY_OFFSET,
152 void pa_sink_set_mute(pa_sink *sink, bool mute, bool save);
153 bool pa_sink_get_mute(pa_sink *sink, bool force_refresh);
155 +void pa_sink_set_volume_ramp(pa_sink *s, const pa_cvolume_ramp *ramp, bool send_msg, bool save);
157 bool pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p);
159 int pa_sink_set_port(pa_sink *s, const char *name, bool save);