2 * module-murphy-ivi -- PulseAudio module for providing audio routing support
3 * Copyright (c) 2012, Intel Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU Lesser General Public License,
7 * version 2.1, as published by the Free Software Foundation.
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.
12 * See the GNU Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
25 #include <pulsecore/pulsecore-config.h>
27 #include <pulse/proplist.h>
28 #include <pulsecore/core-util.h>
29 #include <pulsecore/sink.h>
30 #include <pulsecore/sink-input.h>
45 transition_time transit;
48 static void set_stream_volume_limit(struct userdata *, pa_sink_input *,
49 pa_volume_t, uint32_t);
51 pa_fader *pa_fader_init(const char *fade_out_str, const char *fade_in_str)
53 pa_fader *fader = pa_xnew0(pa_fader, 1);
55 if (!fade_out_str || pa_atou(fade_out_str, &fader->transit.fade_out) < 0)
56 fader->transit.fade_out = 100;
58 if (!fade_in_str || pa_atou(fade_in_str, &fader->transit.fade_in) < 0)
59 fader->transit.fade_in = 1000;
61 if (fader->transit.fade_out > 10000)
62 fader->transit.fade_out = 10000;
64 if (fader->transit.fade_in > 10000)
65 fader->transit.fade_in = 10000;
67 pa_log_info("fader transition times: out %u ms, in %u ms",
68 fader->transit.fade_out, fader->transit.fade_in);
73 void pa_fader_done(struct userdata *u)
82 void pa_fader_apply_volume_limits(struct userdata *u, uint32_t stamp)
85 transition_time *transit;
88 pa_cvolume_ramp_int *ramp;
99 pa_assert_se(u->fader);
100 pa_assert_se((core = u->core));
102 transit = &u->fader->transit;
103 rampit = transit->fade_in > 0 && transit->fade_out > 0;
105 pa_log_debug("applying volume limits ...");
107 PA_IDXSET_FOREACH(sink, core->sinks, i) {
108 if ((node = pa_discover_find_node_by_ptr(u, sink))) {
109 pa_log_debug(" node '%s'", node->amname);
111 PA_IDXSET_FOREACH(sinp, sink->inputs, j) {
112 class = pa_utils_get_stream_class(sinp->proplist);
114 pa_log_debug(" stream %u (class %u)", sinp->index, class);
117 if (!(sinp->flags & PA_SINK_INPUT_START_RAMP_MUTED))
118 pa_log_debug(" skipping");
120 sinp->flags &= ~PA_SINK_INPUT_START_RAMP_MUTED;
121 time = transit->fade_in;
123 pa_log_debug(" attenuation 0 dB "
124 "transition time %u ms", time);
125 set_stream_volume_limit(u, sinp, PA_VOLUME_NORM, time);
129 dB = mir_volume_apply_limits(u, node, class, stamp);
130 newvol = pa_sw_volume_from_dB(dB);
134 oldvol = ramp->ramps[0].target;
137 time = transit->fade_out;
138 else if (oldvol < newvol)
139 time = transit->fade_in;
144 oldvol = sinp->volume_factor.values[0];
148 if (oldvol == newvol)
149 pa_log_debug(" attenuation %.2lf dB",dB);
151 pa_log_debug(" attenuation %.2lf dB "
152 "transition time %u ms", dB, time);
153 set_stream_volume_limit(u, sinp, newvol, time);
156 } /* PA_IDXSET_FOREACH sinp */
158 } /* PA_IDXSET_FOREACH sink */
161 void pa_fader_ramp_volume(struct userdata *u,
165 transition_time *transit;
168 pa_cvolume_ramp_int *ramp;
170 pa_cvolume_ramp rampvol;
176 transit = &u->fader->transit;
177 rampit = transit->fade_in > 0 && transit->fade_out > 0;
179 oldvol = ramp->ramps[0].target;
181 if (rampit && oldvol != newvol) {
182 time = (oldvol > newvol) ? transit->fade_out : transit->fade_in;
184 pa_cvolume_ramp_set(&rampvol,
185 sinp->volume.channels,
186 PA_VOLUME_RAMP_TYPE_LINEAR,
189 pa_sink_input_set_volume_ramp(sinp, &rampvol, true, false);
194 void pa_fader_set_volume(struct userdata *u,
199 pa_cvolume_ramp_int *ramp;
200 pa_cvolume_ramp rampvol;
206 oldvol = ramp->ramps[0].target;
208 if (oldvol != newvol) {
209 pa_cvolume_ramp_set(&rampvol,
210 sinp->volume.channels,
211 PA_VOLUME_RAMP_TYPE_LINEAR,
214 pa_sink_input_set_volume_ramp(sinp, &rampvol, true, false);
218 pa_volume_t pa_fader_get_volume(struct userdata *u, pa_sink_input *sinp)
220 pa_cvolume_ramp_int *ramp;
227 vol = ramp->ramps[0].target;
232 static void set_stream_volume_limit(struct userdata *u,
238 pa_cvolume_ramp rampvol;
242 pa_assert_se((sink = sinp->sink));
245 pa_cvolume_set(&sinp->volume_factor, sinp->volume.channels, vol);
247 if (pa_sink_flat_volume_enabled(sink)) {
248 pa_sink_set_volume(sink, NULL, true, false);
251 pa_sw_cvolume_multiply(&sinp->soft_volume, &sinp->real_ratio,
252 &sinp->volume_factor);
254 pa_asyncmsgq_send(sink->asyncmsgq, PA_MSGOBJECT(sinp),
255 PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME,
260 pa_cvolume_ramp_set(&rampvol,
261 sinp->volume.channels,
262 PA_VOLUME_RAMP_TYPE_LINEAR,
266 pa_sink_input_set_volume_ramp(sinp, &rampvol, true, false);
274 * indent-tabs-mode: nil