volume hooks
authorMarc-Andre Lureau <marcandre.lureau@gmail.com>
Mon, 6 Oct 2008 22:37:38 +0000 (01:37 +0300)
committerLennart Poettering <lennart@poettering.net>
Mon, 6 Oct 2008 23:54:30 +0000 (01:54 +0200)
Signed-off-by: Lennart Poettering <lennart@poettering.net>
src/pulsecore/core.h
src/pulsecore/protocol-native.c
src/pulsecore/sink-input.c
src/pulsecore/sink-input.h
src/pulsecore/sink.c
src/pulsecore/sink.h

index 3955908..f796fb9 100644 (file)
@@ -49,6 +49,7 @@ typedef enum pa_core_hook {
     PA_CORE_HOOK_SINK_UNLINK_POST,
     PA_CORE_HOOK_SINK_STATE_CHANGED,
     PA_CORE_HOOK_SINK_PROPLIST_CHANGED,
+    PA_CORE_HOOK_SINK_SET_VOLUME,
     PA_CORE_HOOK_SOURCE_NEW,
     PA_CORE_HOOK_SOURCE_FIXATE,
     PA_CORE_HOOK_SOURCE_PUT,
@@ -65,6 +66,7 @@ typedef enum pa_core_hook {
     PA_CORE_HOOK_SINK_INPUT_MOVE_POST,
     PA_CORE_HOOK_SINK_INPUT_STATE_CHANGED,
     PA_CORE_HOOK_SINK_INPUT_PROPLIST_CHANGED,
+    PA_CORE_HOOK_SINK_INPUT_SET_VOLUME,
     PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
     PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE,
     PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
index 778aab5..46dcb14 100644 (file)
@@ -2722,7 +2722,7 @@ static void sink_input_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t,
     pa_tagstruct_putu32(t, s->sink->index);
     pa_tagstruct_put_sample_spec(t, &fixed_ss);
     pa_tagstruct_put_channel_map(t, &s->channel_map);
-    pa_tagstruct_put_cvolume(t, &s->volume);
+    pa_tagstruct_put_cvolume(t, pa_sink_input_get_volume(s));
     pa_tagstruct_put_usec(t, pa_sink_input_get_latency(s, &sink_latency));
     pa_tagstruct_put_usec(t, sink_latency);
     pa_tagstruct_puts(t, pa_resample_method_to_string(pa_sink_input_get_resample_method(s)));
index 4f70347..9a3c49c 100644 (file)
@@ -75,7 +75,7 @@ void pa_sink_input_new_data_set_volume(pa_sink_input_new_data *data, const pa_cv
     pa_assert(data);
 
     if ((data->volume_is_set = !!volume))
-        data->volume = *volume;
+        data->volume = data->virtual_volume = *volume;
 }
 
 void pa_sink_input_new_data_set_muted(pa_sink_input_new_data *data, pa_bool_t mute) {
@@ -156,6 +156,8 @@ pa_sink_input* pa_sink_input_new(
     pa_return_null_if_fail(pa_cvolume_valid(&data->volume));
     pa_return_null_if_fail(data->volume.channels == data->sample_spec.channels);
 
+    data->virtual_volume = data->volume;
+
     if (!data->muted_is_set)
         data->muted = FALSE;
 
@@ -227,7 +229,9 @@ pa_sink_input* pa_sink_input_new(
     i->sample_spec = data->sample_spec;
     i->channel_map = data->channel_map;
 
+    i->virtual_volume = data->virtual_volume;
     i->volume = data->volume;
+
     i->muted = data->muted;
 
     if (data->sync_base) {
@@ -784,17 +788,30 @@ pa_usec_t pa_sink_input_get_requested_latency(pa_sink_input *i) {
 
 /* Called from main context */
 void pa_sink_input_set_volume(pa_sink_input *i, const pa_cvolume *volume) {
+    pa_sink_input_set_volume_data data;
+
     pa_sink_input_assert_ref(i);
     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
     pa_assert(volume);
 
-    if (pa_cvolume_equal(&i->volume, volume))
+    data.sink_input = i;
+    data.virtual_volume = *volume;
+    data.volume = *volume;
+
+    if (pa_hook_fire(&i->core->hooks[PA_CORE_HOOK_SINK_INPUT_SET_VOLUME], &data) < 0) {
         return;
+    }
 
-    i->volume = *volume;
+    if (!pa_cvolume_equal(&i->volume, &data.volume)) {
+        i->volume = data.volume;
+       pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, &data.volume, 0, NULL) == 0);
+        return;
+    }
 
-    pa_assert_se(pa_asyncmsgq_send(i->sink->asyncmsgq, PA_MSGOBJECT(i), PA_SINK_INPUT_MESSAGE_SET_VOLUME, &i->volume, 0, NULL) == 0);
-    pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    if (!pa_cvolume_equal(&i->virtual_volume, &data.virtual_volume)) {
+        i->virtual_volume = data.virtual_volume;
+        pa_subscription_post(i->sink->core, PA_SUBSCRIPTION_EVENT_SINK_INPUT|PA_SUBSCRIPTION_EVENT_CHANGE, i->index);
+    }
 }
 
 /* Called from main context */
@@ -802,7 +819,7 @@ const pa_cvolume *pa_sink_input_get_volume(pa_sink_input *i) {
     pa_sink_input_assert_ref(i);
     pa_assert(PA_SINK_INPUT_IS_LINKED(i->state));
 
-    return &i->volume;
+    return &i->virtual_volume;
 }
 
 /* Called from main context */
index 7663f22..ed95fe4 100644 (file)
@@ -89,6 +89,8 @@ struct pa_sink_input {
 
     pa_sink_input *sync_prev, *sync_next;
 
+    pa_cvolume virtual_volume;
+
     pa_cvolume volume;
     pa_bool_t muted;
 
@@ -218,6 +220,9 @@ typedef struct pa_sink_input_new_data {
 
     pa_sample_spec sample_spec;
     pa_channel_map channel_map;
+
+    pa_cvolume virtual_volume;
+
     pa_cvolume volume;
     pa_bool_t muted:1;
 
@@ -239,6 +244,12 @@ typedef struct pa_sink_input_move_hook_data {
     pa_sink *destination;
 } pa_sink_input_move_hook_data;
 
+typedef struct pa_sink_set_input_volume_data {
+  pa_sink_input *sink_input;
+  pa_cvolume virtual_volume;
+  pa_cvolume volume;
+} pa_sink_input_set_volume_data;
+
 /* To be called by the implementing module only */
 
 pa_sink_input* pa_sink_input_new(
index e04fc08..d20a49d 100644 (file)
@@ -843,13 +843,21 @@ pa_usec_t pa_sink_get_latency(pa_sink *s) {
 /* Called from main thread */
 void pa_sink_set_volume(pa_sink *s, const pa_cvolume *volume) {
     pa_bool_t changed;
+    pa_sink_set_volume_data data;
 
     pa_sink_assert_ref(s);
     pa_assert(PA_SINK_IS_LINKED(s->state));
     pa_assert(volume);
 
-    changed = !pa_cvolume_equal(volume, &s->volume);
-    s->volume = *volume;
+    data.sink = s;
+    data.volume = *volume;
+
+    changed = !pa_cvolume_equal(&data.volume, &s->volume);
+
+    if (changed && pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_SET_VOLUME], &data) < 0)
+        return;
+
+    s->volume = data.volume;
 
     if (s->set_volume && s->set_volume(s) < 0)
         s->set_volume = NULL;
index 672bdd3..74671b4 100644 (file)
@@ -206,6 +206,11 @@ void pa_sink_new_data_set_volume(pa_sink_new_data *data, const pa_cvolume *volum
 void pa_sink_new_data_set_muted(pa_sink_new_data *data, pa_bool_t mute);
 void pa_sink_new_data_done(pa_sink_new_data *data);
 
+typedef struct pa_sink_set_volume_data {
+  pa_sink *sink;
+  pa_cvolume volume;
+} pa_sink_set_volume_data;
+
 /* To be called exclusively by the sink driver, from main context */
 
 pa_sink* pa_sink_new(