/* get stream_ducking */
pa_assert_se((sd = pa_hashmap_get(m->stream_duckings, (const void*)id)));
+ if (enable) {
+ snprintf(sd->vol_key, VOLUME_KEY_LENGTH, "stream_ducking_%u_%s", id, target_stream);
+ snprintf(sd->target_role, STREAM_ROLE_STR_MAX, "%s", target_stream);
+ sd->duration = duration;
+ sd->set_vol = PA_VOLUME_NORM * ratio;
+ }
+
/* set volume ramp factor to target stream */
PA_IDXSET_FOREACH(stream, m->core->sink_inputs, idx) {
if (!pa_safe_streq(target_stream, pa_proplist_gets(stream->proplist, PA_PROP_MEDIA_ROLE)))
sd->ducking_stream_count++;
if (enable) {
- pa_volume_t set_vol;
pa_cvolume_ramp vol_ramp;
- snprintf(sd->vol_ramp_key, VOLUME_RAMP_KEY_LENGTH, "stream_ducking_%u_%s", id, target_stream);
-
pa_idxset_put(sd->idx_ducking_streams, (void *)stream, NULL);
- set_vol = PA_VOLUME_NORM * ratio;
-
- pa_log_info("ducking: [%p] set vol [%u], key [%s]", stream, set_vol, sd->vol_ramp_key);
+ pa_log_info("ducking: [%p] set vol [%u], key [%s], role [%s]",
+ stream, sd->set_vol, sd->vol_key, sd->target_role);
pa_cvolume_ramp_set(&vol_ramp, stream->volume.channels,
- PA_VOLUME_RAMP_TYPE_LINEAR, (long)duration, set_vol);
+ PA_VOLUME_RAMP_TYPE_LINEAR, (long)duration, sd->set_vol);
- pa_sink_input_add_volume_ramp_factor(stream, sd->vol_ramp_key, &vol_ramp, true);
+ pa_sink_input_add_volume_ramp_factor(stream, sd->vol_key, &vol_ramp, true);
} else {
- pa_log_info("unducking : remove volume ramp factor [key:%s]", sd->vol_ramp_key);
+ pa_log_info("unducking : remove volume(ramp) factor [key:%s]", sd->vol_key);
- pa_sink_input_remove_volume_ramp_factor(stream, sd->vol_ramp_key, true);
+ pa_sink_input_remove_volume_factor(stream, sd->vol_key);
+ pa_sink_input_remove_volume_ramp_factor(stream, sd->vol_key, true);
}
}
#define STREAM_FOCUS_STATE_RELEASED "0"
#define STREAM_FOCUS_STATE_ACQUIRED "1"
-#define VOLUME_RAMP_KEY_LENGTH 24
+#define VOLUME_KEY_LENGTH 24
+#define STREAM_ROLE_STR_MAX 32
#define AVAIL_DEVICES_MAX 16
#define AVAIL_FRAMEWORKS_MAX 16
} stream_parent;
typedef struct _stream_ducking {
+ bool is_ducked;
int trigger_index;
int ducking_stream_count;
+ char vol_key[VOLUME_KEY_LENGTH];
+ char target_role[STREAM_ROLE_STR_MAX];
+ uint32_t duration;
+ pa_volume_t set_vol;
pa_idxset *idx_ducking_streams;
- char vol_ramp_key[VOLUME_RAMP_KEY_LENGTH];
- bool is_ducked;
} stream_ducking;
typedef struct _filter_info {
pa_idxset_remove_by_data(streams, i, NULL);
}
+/* Remove the sink-input from ducking streams */
+static void remove_sink_input_from_ducking_streams(pa_stream_manager *m, pa_sink_input *i) {
+ uint32_t idx = 0;
+ stream_ducking *sd = NULL;
+ void *stream = NULL;
+ void *state;
+
+ pa_assert(m);
+
+ PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) {
+ PA_IDXSET_FOREACH(stream, sd->idx_ducking_streams, idx) {
+ if (stream == i) {
+ pa_log_info("remove ducking stream[i:%u,%p] from idx_ducking_streams", i->index, i);
+ pa_idxset_remove_by_data(sd->idx_ducking_streams, stream, NULL);
+ return;
+ }
+ }
+ }
+}
+
+/* Add the sink-input to ducking streams */
+static void add_sink_input_to_ducking_streams(pa_stream_manager *m, pa_sink_input *i) {
+ stream_ducking *sd = NULL;
+ void *state;
+
+ pa_assert(m);
+
+ PA_HASHMAP_FOREACH(sd, m->stream_duckings, state) {
+ pa_cvolume_ramp vol_ramp;
+ pa_cvolume vol;
+
+ if (!pa_safe_streq(sd->target_role, pa_proplist_gets(i->proplist, PA_PROP_MEDIA_ROLE)))
+ continue;
+
+ pa_log_info("add ducking stream[i:%u,%p] to idx_ducking_streams, volume %u",
+ i->index, i, sd->set_vol);
+
+ pa_idxset_put(sd->idx_ducking_streams, (void *)i, NULL);
+
+ pa_cvolume_ramp_set(&vol_ramp, i->volume.channels,
+ PA_VOLUME_RAMP_TYPE_LINEAR, (long)sd->duration, sd->set_vol);
+
+ vol.channels = i->volume.channels;
+ vol.values[0] = sd->set_vol;
+
+ pa_sink_input_add_volume_factor(i, sd->vol_key, &vol);
+ pa_sink_input_add_volume_ramp_factor(i, sd->vol_key, &vol_ramp, false);
+
+ return;
+ }
+}
+
static pa_hook_result_t sink_input_new_cb(pa_core *core, pa_sink_input_new_data *new_data, pa_stream_manager *m) {
pa_core_assert_ref(core);
m->on_call = true;
}
+ add_sink_input_to_ducking_streams(m, i);
+
return PA_HOOK_OK;
}
m->on_call = false;
set_media_active_device(m);
}
+
remove_sink_input_from_muted_streams(m, i);
+ remove_sink_input_from_ducking_streams(m, i);
+
process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_REMOVE_PARENT_ID, false);
process_stream(m, i, STREAM_SINK_INPUT, PROCESS_COMMAND_CHANGE_ROUTE_BY_STREAM_ENDED, false);
pa_log_info(" - remove sd(%p), idx(%u)", sd, idx);
PA_IDXSET_FOREACH(stream, sd->idx_ducking_streams, ducking_idx) {
- pa_log_info("remove volume ramp for remained stream %p, key %s", stream, sd->vol_ramp_key);
- pa_sink_input_remove_volume_ramp_factor(stream, sd->vol_ramp_key, true);
+ pa_log_info("remove volume ramp for remained stream %p, key %s", stream, sd->vol_key);
+ pa_sink_input_remove_volume_factor(stream, sd->vol_key);
+ pa_sink_input_remove_volume_ramp_factor(stream, sd->vol_key, true);
}
pa_idxset_free(sd->idx_ducking_streams, NULL);