From 44e54e603f7729f968ff2c456c63a4a55ee1a0d7 Mon Sep 17 00:00:00 2001 From: Janos Kovacs Date: Fri, 4 Oct 2013 15:24:49 +0300 Subject: [PATCH] ramp-mute new streams Change-Id: Id8346e44fa7ee23e71e5489d51bdeeff8ecf581e --- murphy/discover.c | 23 ++++++++++++-- murphy/fader.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++-- murphy/fader.h | 3 ++ murphy/stream-state.c | 24 ++++++++++++--- 4 files changed, 125 insertions(+), 9 deletions(-) diff --git a/murphy/discover.c b/murphy/discover.c index 6e2c7b6..ad79839 100644 --- a/murphy/discover.c +++ b/murphy/discover.c @@ -654,6 +654,8 @@ void pa_discover_add_source(struct userdata *u, pa_source *source) if (make_rset) pa_murphyif_create_resource_set(u, node, resdef); + + pa_fader_apply_volume_limits(u, node->stamp); } } else { @@ -838,6 +840,7 @@ void pa_discover_preroute_sink_input(struct userdata *u, mir_node *node; pa_muxnode *mux; pa_nodeset_resdef *resdef; + bool loopback; pa_assert(u); pa_assert(data); @@ -849,6 +852,7 @@ void pa_discover_preroute_sink_input(struct userdata *u, 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)) || @@ -863,7 +867,9 @@ void pa_discover_preroute_sink_input(struct userdata *u, } } 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; @@ -889,6 +895,7 @@ void pa_discover_preroute_sink_input(struct userdata *u, pa_log_debug("start corked"); } } + pa_utils_set_stream_routing_properties(pl, type, data->sink); } @@ -913,13 +920,20 @@ void pa_discover_preroute_sink_input(struct userdata *u, 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; } @@ -1049,6 +1063,11 @@ void pa_discover_add_sink_input(struct userdata *u, pa_sink_input *sinp) 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); + } } } diff --git a/murphy/fader.c b/murphy/fader.c index 7963ce3..c37e278 100644 --- a/murphy/fader.c +++ b/murphy/fader.c @@ -113,8 +113,18 @@ void pa_fader_apply_volume_limits(struct userdata *u, uint32_t stamp) 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); @@ -148,6 +158,76 @@ void pa_fader_apply_volume_limits(struct userdata *u, uint32_t stamp) } /* 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, diff --git a/murphy/fader.h b/murphy/fader.h index 378c6b7..66fe48e 100644 --- a/murphy/fader.h +++ b/murphy/fader.h @@ -31,6 +31,9 @@ void pa_fader_done(struct userdata *); 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 */ diff --git a/murphy/stream-state.c b/murphy/stream-state.c index 4990079..baac0fe 100644 --- a/murphy/stream-state.c +++ b/murphy/stream-state.c @@ -30,13 +30,14 @@ #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, @@ -118,12 +119,12 @@ void pa_stream_state_change(struct userdata *u, mir_node *node, int req) 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: @@ -140,12 +141,15 @@ void pa_stream_state_change(struct userdata *u, mir_node *node, int req) } -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); @@ -168,8 +172,18 @@ static void sink_input_block(pa_sink_input *sinp, pa_bool_t block) 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)) { -- 2.7.4