summaryrefslogtreecommitdiffstats
path: root/src/pulsecore/sink-input.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pulsecore/sink-input.c')
-rw-r--r--src/pulsecore/sink-input.c164
1 files changed, 57 insertions, 107 deletions
diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
index f6d9ac73..a29334f9 100644
--- a/src/pulsecore/sink-input.c
+++ b/src/pulsecore/sink-input.c
@@ -47,6 +47,7 @@
static PA_DEFINE_CHECK_TYPE(pa_sink_input, pa_msgobject);
static void sink_input_free(pa_object *o);
+static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v);
pa_sink_input_new_data* pa_sink_input_new_data_init(pa_sink_input_new_data *data) {
pa_assert(data);
@@ -270,18 +271,20 @@ int pa_sink_input_new(
i->channel_map = data->channel_map;
if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !data->volume_is_absolute) {
+ pa_cvolume remapped;
+
/* When the 'absolute' bool is not set then we'll treat the volume
* as relative to the sink volume even in flat volume mode */
-
- pa_cvolume v = data->sink->reference_volume;
- pa_cvolume_remap(&v, &data->sink->channel_map, &data->channel_map);
- pa_sw_cvolume_multiply(&i->virtual_volume, &data->volume, &v);
+ remapped = data->sink->reference_volume;
+ pa_cvolume_remap(&remapped, &data->sink->channel_map, &data->channel_map);
+ pa_sw_cvolume_multiply(&i->volume, &data->volume, &remapped);
} else
- i->virtual_volume = data->volume;
+ i->volume = data->volume;
i->volume_factor = data->volume_factor;
- pa_cvolume_init(&i->soft_volume);
- memset(i->relative_volume, 0, sizeof(i->relative_volume));
+ i->real_ratio = i->reference_ratio = data->volume;
+ pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
+ pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
i->save_volume = data->save_volume;
i->save_sink = data->save_sink;
i->save_muted = data->save_muted;
@@ -445,11 +448,8 @@ void pa_sink_input_unlink(pa_sink_input *i) {
if (linked && i->sink) {
/* We might need to update the sink's volume if we are in flat volume mode. */
- if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
- pa_cvolume new_volume;
- pa_sink_update_flat_volume(i->sink, &new_volume);
- pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE, FALSE);
- }
+ if (i->sink->flags & PA_SINK_FLAT_VOLUME)
+ pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
if (i->sink->asyncmsgq)
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_REMOVE_INPUT, i, 0, NULL) == 0);
@@ -526,12 +526,10 @@ void pa_sink_input_put(pa_sink_input *i) {
i->state = state;
/* We might need to update the sink's volume if we are in flat volume mode. */
- if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
- pa_cvolume new_volume;
- pa_sink_update_flat_volume(i->sink, &new_volume);
- pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE, FALSE);
- } else
- pa_sink_input_set_relative_volume(i, &i->virtual_volume);
+ if (i->sink->flags & PA_SINK_FLAT_VOLUME)
+ pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
+ else
+ set_real_ratio(i, &i->volume);
i->thread_info.soft_volume = i->soft_volume;
i->thread_info.muted = i->muted;
@@ -910,6 +908,27 @@ pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
}
/* Called from main context */
+static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v) {
+ pa_sink_input_assert_ref(i);
+ pa_assert_ctl_context();
+ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
+ pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
+
+ /* This basically calculates:
+ *
+ * i->real_ratio := v
+ * i->soft_volume := i->real_ratio * i->volume_factor */
+
+ if (v)
+ i->real_ratio = *v;
+ else
+ pa_cvolume_reset(&i->real_ratio, i->sample_spec.channels);
+
+ pa_sw_cvolume_multiply(&i->soft_volume, &i->real_ratio, &i->volume_factor);
+ /* We don't copy the data to the thread_info data. That's left for someone else to do */
+}
+
+/* Called from main context */
void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_bool_t save, pa_bool_t absolute) {
pa_cvolume v;
@@ -926,29 +945,24 @@ void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume, pa_boo
volume = pa_sw_cvolume_multiply(&v, &v, volume);
}
- if (pa_cvolume_equal(volume, &i->virtual_volume))
+ if (pa_cvolume_equal(volume, &i->volume)) {
+ i->save_volume = i->save_volume || save;
return;
+ }
- i->virtual_volume = *volume;
+ i->volume = *volume;
i->save_volume = save;
- if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
- pa_cvolume new_volume;
-
+ if (i->sink->flags & PA_SINK_FLAT_VOLUME)
/* We are in flat volume mode, so let's update all sink input
* volumes and update the flat volume of the sink */
- pa_sink_update_flat_volume(i->sink, &new_volume);
- pa_sink_set_volume(i->sink, &new_volume, FALSE, TRUE, FALSE, FALSE);
-
- } else {
+ pa_sink_set_volume(i->sink, NULL, TRUE, save);
+ else {
/* OK, we are in normal volume mode. The volume only affects
* ourselves */
- pa_sink_input_set_relative_volume(i, volume);
-
- /* Hooks have the ability to play games with i->soft_volume */
- pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], i);
+ set_real_ratio(i, volume);
/* Copy the new soft_volume to the thread_info struct */
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_SOFT_VOLUME, NULL, 0, NULL) == 0);
@@ -964,68 +978,15 @@ pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, pa_bo
pa_assert_ctl_context();
pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
- if ((i->sink->flags & PA_SINK_FLAT_VOLUME) && !absolute) {
- pa_cvolume v = i->sink->reference_volume;
- pa_cvolume_remap(&v, &i->sink->channel_map, &i->channel_map);
- pa_sw_cvolume_divide(volume, &i->virtual_volume, &v);
- } else
- *volume = i->virtual_volume;
+ if (absolute || !(i->sink->flags & PA_SINK_FLAT_VOLUME))
+ *volume = i->volume;
+ else
+ *volume = i->reference_ratio;
return volume;
}
/* Called from main context */
-pa_cvolume *pa_sink_input_get_relative_volume(pa_sink_input *i, pa_cvolume *v) {
- unsigned c;
-
- pa_sink_input_assert_ref(i);
- pa_assert_ctl_context();
- pa_assert(v);
- pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
-
- /* This always returns the relative volume. Converts the float
- * version into a pa_cvolume */
-
- v->channels = i->sample_spec.channels;
-
- for (c = 0; c < v->channels; c++)
- v->values[c] = pa_sw_volume_from_linear(i->relative_volume[c]);
-
- return v;
-}
-
-/* Called from main context */
-void pa_sink_input_set_relative_volume(pa_sink_input *i, const pa_cvolume *v) {
- unsigned c;
- pa_cvolume _v;
-
- pa_sink_input_assert_ref(i);
- pa_assert_ctl_context();
- pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
- pa_assert(!v || pa_cvolume_compatible(v, &i->sample_spec));
-
- if (!v)
- v = pa_cvolume_reset(&_v, i->sample_spec.channels);
-
- /* This basically calculates:
- *
- * i->relative_volume := v
- * i->soft_volume := i->relative_volume * i->volume_factor */
-
- i->soft_volume.channels = i->sample_spec.channels;
-
- for (c = 0; c < i->sample_spec.channels; c++) {
- i->relative_volume[c] = pa_sw_volume_to_linear(v->values[c]);
-
- i->soft_volume.values[c] = pa_sw_volume_from_linear(
- i->relative_volume[c] *
- pa_sw_volume_to_linear(i->volume_factor.values[c]));
- }
-
- /* We don't copy the data to the thread_info data. That's left for someone else to do */
-}
-
-/* Called from main context */
void pa_sink_input_set_mute(pa_sink_input *i, pa_bool_t mute, pa_bool_t save) {
pa_sink_input_assert_ref(i);
pa_assert_ctl_context();
@@ -1198,20 +1159,10 @@ int pa_sink_input_start_move(pa_sink_input *i) {
if (pa_sink_input_get_state(i) == PA_SINK_INPUT_CORKED)
pa_assert_se(i->sink->n_corked-- >= 1);
- if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
- pa_cvolume new_volume;
-
- /* Make the virtual volume relative */
- pa_sink_input_get_relative_volume(i, &i->virtual_volume);
-
- /* And reset the the relative volume */
- pa_sink_input_set_relative_volume(i, NULL);
-
+ if (i->sink->flags & PA_SINK_FLAT_VOLUME)
/* We might need to update the sink's volume if we are in flat
* volume mode. */
- pa_sink_update_flat_volume(i->sink, &new_volume);
- pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE, FALSE);
- }
+ pa_sink_set_volume(i->sink, NULL, FALSE, FALSE);
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_START_MOVE, i, 0, NULL) == 0);
@@ -1295,16 +1246,15 @@ int pa_sink_input_finish_move(pa_sink_input *i, pa_sink *dest, pa_bool_t save) {
pa_sink_update_status(dest);
if (i->sink->flags & PA_SINK_FLAT_VOLUME) {
- pa_cvolume new_volume;
+ pa_cvolume remapped;
- /* Make relative volume absolute again */
- pa_cvolume t = dest->reference_volume;
- pa_cvolume_remap(&t, &dest->channel_map, &i->channel_map);
- pa_sw_cvolume_multiply(&i->virtual_volume, &i->virtual_volume, &t);
+ /* Make relative volumes absolute */
+ remapped = dest->reference_volume;
+ pa_cvolume_remap(&remapped, &dest->channel_map, &i->channel_map);
+ pa_sw_cvolume_multiply(&i->volume, &i->reference_ratio, &remapped);
/* We might need to update the sink's volume if we are in flat volume mode. */
- pa_sink_update_flat_volume(i->sink, &new_volume);
- pa_sink_set_volume(i->sink, &new_volume, FALSE, FALSE, FALSE, FALSE);
+ pa_sink_set_volume(i->sink, NULL, FALSE, i->save_volume);
}
pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i->sink), PA_SINK_MESSAGE_FINISH_MOVE, i, 0, NULL) == 0);