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,
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,
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)));
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) {
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;
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) {
/* 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 */
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 */
pa_sink_input *sync_prev, *sync_next;
+ pa_cvolume virtual_volume;
+
pa_cvolume volume;
pa_bool_t muted;
pa_sample_spec sample_spec;
pa_channel_map channel_map;
+
+ pa_cvolume virtual_volume;
+
pa_cvolume volume;
pa_bool_t muted:1;
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(
/* 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;
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(