if (make_rset)
pa_murphyif_create_resource_set(u, node, resdef);
+
+ pa_fader_apply_volume_limits(u, node->stamp);
}
}
else {
mir_node *node;
pa_muxnode *mux;
pa_nodeset_resdef *resdef;
+ bool loopback;
pa_assert(u);
pa_assert(data);
mnam = (m = data->module) ? m->name : "";
if (pa_streq(mnam, "module-combine-sink")) {
+ loopback = false;
type = mir_node_type_unknown;
if (!(mux = pa_multiplex_find_by_module(multiplex, m)) ||
}
}
else {
- if (pa_streq(mnam, "module-loopback")) {
+ loopback = pa_streq(mnam, "module-loopback");
+
+ if (loopback) {
if (!(node = pa_utils_get_node_from_data(u, mir_input, data))) {
pa_log_debug("can't find loopback node for sink-input");
return;
pa_log_debug("start corked");
}
}
+
pa_utils_set_stream_routing_properties(pl, type, data->sink);
}
schedule_stream_uncorking(u, sink);
}
#endif
-
if (pa_sink_input_new_data_set_sink(data, sink, FALSE))
pa_log_debug("set sink %u for new sink-input", sink->index);
else
pa_log("can't set sink %u for new sink-input", sink->index);
}
}
+
+ if (loopback && data->sink && data->sink->module) {
+ if (pa_streq(data->sink->module->name, "module-combine-sink"))
+ return;
+ }
+
+ pa_log_debug("set sink-input ramp-muted");
+ data->flags |= PA_SINK_INPUT_START_RAMP_MUTED;
}
csinp = pa_idxset_get_by_index(core->sink_inputs,
data.mux->defstream_index);
s = csinp ? csinp->sink : NULL;
+
+ if ((sinp->flags & PA_SINK_INPUT_START_RAMP_MUTED)) {
+ pa_log_debug("ramp '%s' to 100%", media);
+ pa_fader_ramp_volume(u, sinp, PA_VOLUME_NORM);
+ }
}
}
pa_log_debug(" stream %u (class %u)", sinp->index, class);
- if (!class)
- pa_log_debug(" skipping");
+ if (!class) {
+ if (!(sinp->flags & PA_SINK_INPUT_START_RAMP_MUTED))
+ pa_log_debug(" skipping");
+ else {
+ sinp->flags &= ~PA_SINK_INPUT_START_RAMP_MUTED;
+ time = transit->fade_in;
+
+ pa_log_debug(" attenuation 0 dB "
+ "transition time %u ms", time);
+ set_stream_volume_limit(u, sinp, PA_VOLUME_NORM, time);
+ }
+ }
else {
dB = mir_volume_apply_limits(u, node, class, stamp);
newvol = pa_sw_volume_from_dB(dB);
} /* PA_IDXSET_FOREACH sink */
}
+void pa_fader_ramp_volume(struct userdata *u,
+ pa_sink_input *sinp,
+ pa_volume_t newvol)
+{
+ transition_time *transit;
+ pa_bool_t rampit;
+ pa_volume_t oldvol;
+ pa_cvolume_ramp_int *ramp;
+ uint32_t time;
+ pa_cvolume_ramp rampvol;
+
+ pa_assert(u);
+ pa_assert(u->fader);
+ pa_assert(sinp);
+
+ transit = &u->fader->transit;
+ rampit = transit->fade_in > 0 && transit->fade_out > 0;
+ ramp = &sinp->ramp;
+ oldvol = ramp->ramps[0].target;
+
+ if (rampit && oldvol != newvol) {
+ time = (oldvol > newvol) ? transit->fade_out : transit->fade_in;
+
+ pa_cvolume_ramp_set(&rampvol,
+ sinp->volume.channels,
+ PA_VOLUME_RAMP_TYPE_LINEAR,
+ time, newvol);
+
+ pa_sink_input_set_volume_ramp(sinp, &rampvol, TRUE, FALSE);
+ }
+}
+
+
+void pa_fader_set_volume(struct userdata *u,
+ pa_sink_input *sinp,
+ pa_volume_t newvol)
+{
+ pa_volume_t oldvol;
+ pa_cvolume_ramp_int *ramp;
+ pa_cvolume_ramp rampvol;
+
+ pa_assert(u);
+ pa_assert(sinp);
+
+ ramp = &sinp->ramp;
+ oldvol = ramp->ramps[0].target;
+
+ if (oldvol != newvol) {
+ pa_cvolume_ramp_set(&rampvol,
+ sinp->volume.channels,
+ PA_VOLUME_RAMP_TYPE_LINEAR,
+ 0, newvol);
+
+ pa_sink_input_set_volume_ramp(sinp, &rampvol, TRUE, FALSE);
+ }
+}
+
+pa_volume_t pa_fader_get_volume(struct userdata *u, pa_sink_input *sinp)
+{
+ pa_cvolume_ramp_int *ramp;
+ pa_volume_t vol;
+
+ pa_assert(u);
+ pa_assert(sinp);
+
+ ramp = &sinp->ramp;
+ vol = ramp->ramps[0].target;
+
+ return vol;
+}
static void set_stream_volume_limit(struct userdata *u,
pa_sink_input *sinp,
void pa_fader_apply_volume_limits(struct userdata *, uint32_t);
+void pa_fader_ramp_volume(struct userdata *, pa_sink_input *, pa_volume_t);
+void pa_fader_set_volume(struct userdata *, pa_sink_input *, pa_volume_t);
+pa_volume_t pa_fader_get_volume(struct userdata *, pa_sink_input *);
#endif /* foomirfaderfoo */
#include "stream-state.h"
#include "node.h"
#include "loopback.h"
+#include "fader.h"
static const char *scache_driver = "play-memblockq.c";
static pa_sink_input_flags_t flag_mask = PA_SINK_INPUT_NO_CREATE_ON_SUSPEND |
PA_SINK_INPUT_KILL_ON_SUSPEND;
-static void sink_input_block(pa_sink_input *, pa_bool_t);
+static void sink_input_block(struct userdata *, pa_sink_input *, pa_bool_t);
pa_bool_t pa_stream_state_start_corked(struct userdata *u,
pa_sink_input_new_data *data,
case PA_STREAM_BLOCK:
pa_log_debug("blocking '%s'", node->amname);
- sink_input_block(sinp, TRUE);
+ sink_input_block(u, sinp, TRUE);
break;
case PA_STREAM_RUN:
pa_log_debug("unblock '%s'", node->amname);
- sink_input_block(sinp, FALSE);
+ sink_input_block(u, sinp, FALSE);
break;
default:
}
-static void sink_input_block(pa_sink_input *sinp, pa_bool_t block)
+static void sink_input_block(struct userdata *u,
+ pa_sink_input *sinp,
+ pa_bool_t block)
{
const char *event;
pa_proplist *pl;
bool block_by_mute;
bool muted, corked;
+ pa_volume_t oldvol;
pa_assert(sinp);
block_by_mute ? "muting":"corking");
if (block_by_mute) {
- if ((muted && !block) || (!muted && block))
+ if ((muted && !block) || (!muted && block)) {
+ if (!block) {
+ oldvol = pa_fader_get_volume(u, sinp);
+
+ pa_log_debug("fading in to %u", oldvol);
+
+ pa_fader_set_volume(u, sinp, 0);
+ pa_fader_ramp_volume(u, sinp, oldvol);
+ }
+
pa_sink_input_set_mute(sinp, block, FALSE);
+ }
}
else {
if ((corked && !block) || (!corked && block)) {