summaryrefslogtreecommitdiffstats
path: root/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch')
-rw-r--r--meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch299
1 files changed, 299 insertions, 0 deletions
diff --git a/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch
new file mode 100644
index 000000000..e371b7ec5
--- /dev/null
+++ b/meta-agl-profile-core/recipes-multimedia/pulseaudio/pulseaudio/0005-sink-input-volume-Add-support-for-volume-ramp-factor.patch
@@ -0,0 +1,299 @@
+From a98e78ccc4f12d6efad2832a09202651e2a8b6cd Mon Sep 17 00:00:00 2001
+From: Sangchul Lee <sangchul1011@gmail.com>
+Date: Sat, 27 Aug 2016 21:33:19 +0900
+Subject: [PATCH 5/6] sink-input, volume: Add support for volume ramp factor
+
+Previously, using pa_sink_input_set_volume_ramp() is hard to manage
+if there are several callers. These new volume ramp factor APIs make it
+easy for caller to use and to set more than one volume ramp factor.
+New volume ramp factor will be applied by the multiplication of the other
+ramp factors that have been already set.
+
+APIs are added as below.
+ - pa_sink_input_add_volume_ramp_factor()
+ - pa_sink_input_remove_volume_ramp_factor()
+ - pa_cvolume_ramp_compatible()
+ - pa_sw_cvolume_ramp_multiply()
+ - pa_cvolume_ramp_valid()
+
+Signed-off-by: Sangchul Lee <sc11.lee@samsung.com>
+---
+ src/map-file | 3 ++
+ src/pulse/volume.c | 44 ++++++++++++++++++
+ src/pulse/volume.h | 9 ++++
+ src/pulsecore/sink-input.c | 108 +++++++++++++++++++++++++++++++++++++++++++++
+ src/pulsecore/sink-input.h | 5 +++
+ 5 files changed, 169 insertions(+)
+
+diff --git a/src/map-file b/src/map-file
+index ef9b57d..7577c14 100644
+--- a/src/map-file
++++ b/src/map-file
+@@ -142,6 +142,8 @@ pa_cvolume_ramp_equal;
+ pa_cvolume_ramp_init;
+ pa_cvolume_ramp_set;
+ pa_cvolume_ramp_channel_ramp_set;
++pa_cvolume_ramp_compatible;
++pa_cvolume_ramp_valid;
+ pa_cvolume_remap;
+ pa_cvolume_scale;
+ pa_cvolume_scale_mask;
+@@ -344,6 +346,7 @@ pa_sw_cvolume_divide_scalar;
+ pa_sw_cvolume_multiply;
+ pa_sw_cvolume_multiply_scalar;
+ pa_sw_cvolume_snprint_dB;
++pa_sw_cvolume_ramp_multiply;
+ pa_sw_volume_divide;
+ pa_sw_volume_from_dB;
+ pa_sw_volume_from_linear;
+diff --git a/src/pulse/volume.c b/src/pulse/volume.c
+index 85072c1..8d99150 100644
+--- a/src/pulse/volume.c
++++ b/src/pulse/volume.c
+@@ -1049,3 +1049,47 @@ pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigne
+
+ return ramp;
+ }
++
++int pa_cvolume_ramp_compatible(const pa_cvolume_ramp *ramp, const pa_sample_spec *ss) {
++
++ pa_assert(ramp);
++ pa_assert(ss);
++
++ pa_return_val_if_fail(pa_cvolume_ramp_valid(ramp), 0);
++ pa_return_val_if_fail(pa_sample_spec_valid(ss), 0);
++
++ return ramp->channels == ss->channels;
++}
++
++pa_cvolume_ramp *pa_sw_cvolume_ramp_multiply(pa_cvolume_ramp *dest, const pa_cvolume_ramp *a, const pa_cvolume_ramp *b) {
++ unsigned i;
++
++ pa_assert(dest);
++ pa_assert(a);
++ pa_assert(b);
++
++ pa_return_val_if_fail(pa_cvolume_ramp_valid(a), NULL);
++ pa_return_val_if_fail(pa_cvolume_ramp_valid(b), NULL);
++
++ for (i = 0; i < a->channels && i < b->channels; i++)
++ dest->ramps[i].target = pa_sw_volume_multiply(a->ramps[i].target, b->ramps[i].target);
++
++ dest->channels = (uint8_t) i;
++
++ return dest;
++}
++
++int pa_cvolume_ramp_valid(const pa_cvolume_ramp *ramp) {
++ unsigned c;
++
++ pa_assert(ramp);
++
++ if (!pa_channels_valid(ramp->channels))
++ return 0;
++
++ for (c = 0; c < ramp->channels; c++)
++ if (!PA_VOLUME_IS_VALID(ramp->ramps[c].target))
++ return 0;
++
++ return 1;
++}
+diff --git a/src/pulse/volume.h b/src/pulse/volume.h
+index 2ae3451..65fcb08 100644
+--- a/src/pulse/volume.h
++++ b/src/pulse/volume.h
+@@ -458,12 +458,21 @@ int pa_cvolume_ramp_equal(const pa_cvolume_ramp *a, const pa_cvolume_ramp *b);
+ /** Init volume ramp struct */
+ pa_cvolume_ramp* pa_cvolume_ramp_init(pa_cvolume_ramp *ramp);
+
++/** Set the volume ramp of the first n channels to PA_VOLUME_NORM */
++#define pa_cvolume_ramp_reset(a, n, t, l) pa_cvolume_ramp_set((a), (n), (t), (l), PA_VOLUME_NORM)
++
+ /** Set first n channels of ramp struct to certain value */
+ pa_cvolume_ramp* pa_cvolume_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol);
+
+ /** Set individual channel in the channel struct */
+ pa_cvolume_ramp* pa_cvolume_ramp_channel_ramp_set(pa_cvolume_ramp *ramp, unsigned channel, pa_volume_ramp_type_t type, long time, pa_volume_t vol);
+
++int pa_cvolume_ramp_compatible(const pa_cvolume_ramp *ramp, const pa_sample_spec *ss);
++
++int pa_cvolume_ramp_valid(const pa_cvolume_ramp *ramp);
++
++pa_cvolume_ramp *pa_sw_cvolume_ramp_multiply(pa_cvolume_ramp *dest, const pa_cvolume_ramp *a, const pa_cvolume_ramp *b);
++
+ PA_C_DECL_END
+
+ #endif
+diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c
+index e1968e0..6f89aa1 100644
+--- a/src/pulsecore/sink-input.c
++++ b/src/pulsecore/sink-input.c
+@@ -53,6 +53,11 @@ struct volume_factor_entry {
+ pa_cvolume volume;
+ };
+
++struct volume_ramp_factor_entry {
++ char *key;
++ pa_cvolume_ramp ramp;
++};
++
+ static struct volume_factor_entry *volume_factor_entry_new(const char *key, const pa_cvolume *volume) {
+ struct volume_factor_entry *entry;
+
+@@ -83,6 +88,37 @@ static void volume_factor_from_hashmap(pa_cvolume *v, pa_hashmap *items, uint8_t
+ pa_sw_cvolume_multiply(v, v, &entry->volume);
+ }
+
++static struct volume_ramp_factor_entry *volume_ramp_factor_entry_new(const char *key, const pa_cvolume_ramp *ramp) {
++ struct volume_ramp_factor_entry *entry;
++
++ pa_assert(key);
++ pa_assert(ramp);
++
++ entry = pa_xnew(struct volume_ramp_factor_entry, 1);
++ entry->key = pa_xstrdup(key);
++
++ entry->ramp = *ramp;
++
++ return entry;
++}
++
++static void volume_ramp_factor_entry_free(struct volume_ramp_factor_entry *ramp_entry) {
++ pa_assert(ramp_entry);
++
++ pa_xfree(ramp_entry->key);
++ pa_xfree(ramp_entry);
++}
++
++static void volume_ramp_factor_from_hashmap(pa_cvolume_ramp *r, pa_hashmap *items, uint8_t channels, pa_volume_ramp_type_t type, long length) {
++ struct volume_ramp_factor_entry *entry;
++ void *state = NULL;
++
++ pa_cvolume_ramp_reset(r, channels, type, length);
++ PA_HASHMAP_FOREACH(entry, items, state)
++ pa_sw_cvolume_ramp_multiply(r, r, &entry->ramp);
++
++}
++
+ static void sink_input_free(pa_object *o);
+ static void set_real_ratio(pa_sink_input *i, const pa_cvolume *v);
+
+@@ -500,6 +536,8 @@ int pa_sink_input_new(
+ i->volume_factor_sink_items = data->volume_factor_sink_items;
+ data->volume_factor_sink_items = NULL;
+ volume_factor_from_hashmap(&i->volume_factor_sink, i->volume_factor_sink_items, i->sink->sample_spec.channels);
++ i->ramp_factor_items = pa_hashmap_new_full(pa_idxset_string_hash_func, pa_idxset_string_compare_func, NULL,
++ (pa_free_cb_t) volume_ramp_factor_entry_free);
+
+ i->real_ratio = i->reference_ratio = data->volume;
+ pa_cvolume_reset(&i->soft_volume, i->sample_spec.channels);
+@@ -764,6 +802,9 @@ static void sink_input_free(pa_object *o) {
+ if (i->volume_factor_sink_items)
+ pa_hashmap_free(i->volume_factor_sink_items);
+
++ if (i->ramp_factor_items)
++ pa_hashmap_free(i->ramp_factor_items);
++
+ pa_xfree(i->driver);
+ pa_xfree(i);
+ }
+@@ -1367,6 +1408,73 @@ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key) {
+ return 0;
+ }
+
++void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg) {
++ struct volume_ramp_factor_entry *r;
++
++ pa_sink_input_assert_ref(i);
++ pa_assert_ctl_context();
++ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
++ pa_assert(ramp_factor);
++ pa_assert(key);
++ pa_assert(pa_cvolume_ramp_valid(ramp_factor));
++ pa_assert(ramp_factor->channels == 1 || pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec));
++
++ r = volume_ramp_factor_entry_new(key, ramp_factor);
++ if (!pa_cvolume_ramp_compatible(ramp_factor, &i->sample_spec))
++ pa_cvolume_ramp_set(&r->ramp, i->sample_spec.channels, ramp_factor->ramps[0].type, ramp_factor->ramps[0].length, ramp_factor->ramps[0].target);
++
++ pa_assert_se(pa_hashmap_put(i->ramp_factor_items, r->key, r) >= 0);
++ if (pa_hashmap_size(i->ramp_factor_items) == 1)
++ pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, r->ramp.ramps[0].target);
++ else
++ pa_sw_cvolume_ramp_multiply(&i->ramp_factor, &i->ramp_factor, &r->ramp);
++
++ pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate);
++
++ if (send_msg)
++ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
++
++ return 0;
++}
++
++/* Returns 0 if an entry was removed and -1 if no entry for the given key was
++ * found. */
++int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg) {
++ struct volume_ramp_factor_entry *r;
++
++ pa_sink_input_assert_ref(i);
++ pa_assert(key);
++ pa_assert_ctl_context();
++ pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
++
++ r = pa_hashmap_remove(i->ramp_factor_items, key);
++ if (!r)
++ return -1;
++
++ switch (pa_hashmap_size(i->ramp_factor_items)) {
++ case 0:
++ pa_cvolume_ramp_reset(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length);
++ break;
++ case 1: {
++ struct volume_ramp_factor_entry *rf;
++ rf = pa_hashmap_first(i->ramp_factor_items);
++ pa_cvolume_ramp_set(&i->ramp_factor, i->sample_spec.channels, r->ramp.ramps[0].type, r->ramp.ramps[0].length, rf->ramp.ramps[0].target);
++ break;
++ }
++ default:
++ volume_ramp_factor_from_hashmap(&i->ramp_factor, i->ramp_factor_items, i->ramp_factor.channels, i->ramp_factor.ramps[0].type, i->ramp_factor.ramps[0].length);
++ }
++
++ volume_ramp_factor_entry_free(r);
++
++ pa_cvolume_ramp_convert(&i->ramp_factor, &i->ramp, i->sample_spec.rate);
++
++ if (send_msg)
++ pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME_RAMP, NULL, 0, NULL) == 0);
++
++ return 0;
++}
++
+ /* Called from main thread */
+ void pa_sink_input_set_volume_ramp(
+ pa_sink_input *i,
+diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h
+index 92f61c3..5430d53 100644
+--- a/src/pulsecore/sink-input.h
++++ b/src/pulsecore/sink-input.h
+@@ -113,6 +113,9 @@ struct pa_sink_input {
+ pa_cvolume volume_factor_sink; /* A second volume factor in format of the sink this stream is connected to. */
+ pa_hashmap *volume_factor_sink_items;
+
++ pa_cvolume_ramp ramp_factor;
++ pa_hashmap *ramp_factor_items;
++
+ bool volume_writable:1;
+
+ bool muted:1;
+@@ -379,6 +382,8 @@ void pa_sink_input_add_volume_factor(pa_sink_input *i, const char *key, const pa
+ int pa_sink_input_remove_volume_factor(pa_sink_input *i, const char *key);
+ pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i, pa_cvolume *volume, bool absolute);
+ void pa_sink_input_set_volume_ramp(pa_sink_input *i, const pa_cvolume_ramp *ramp, bool send_msg);
++void pa_sink_input_add_volume_ramp_factor(pa_sink_input *i, const char *key, const pa_cvolume_ramp *ramp_factor, bool send_msg);
++int pa_sink_input_remove_volume_ramp_factor(pa_sink_input *i, const char *key, bool send_msg);
+
+ void pa_sink_input_set_mute(pa_sink_input *i, bool mute, bool save);
+
+--
+1.9.1
+