s->n_corked = 0;
s->volume = data->volume;
+ s->base_volume = PA_VOLUME_NORM;
+ s->virtual_volume = s->volume;
+
s->muted = data->muted;
s->refresh_volume = s->refresh_muted = FALSE;
pa_proplist_setf(source_data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Monitor of %s", dn ? dn : s->name);
pa_proplist_sets(source_data.proplist, PA_PROP_DEVICE_CLASS, "monitor");
- s->monitor_source = pa_source_new(core, &source_data, 0);
+ s->monitor_source = pa_source_new(core, &source_data, PA_SOURCE_LATENCY);
pa_source_new_data_done(&source_data);
if (!PA_SINK_IS_OPENED(s->state))
return 0;
+ if (!(s->flags & PA_SINK_LATENCY))
+ return 0;
+
pa_assert_se(pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) == 0);
return usec;
pa_assert(pa_cvolume_compatible(volume, &s->sample_spec));
data.sink = s;
- data.volume = *volume;
+ data.virtual_volume = data.volume = *volume;
- changed = !pa_cvolume_equal(&data.volume, &s->volume);
+ changed = !pa_cvolume_equal(&data.virtual_volume, &s->virtual_volume) ||
+ !pa_cvolume_equal(&data.volume, &s->volume);
if (changed) {
if (pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_SET_VOLUME], &data) < 0)
return;
- changed = !pa_cvolume_equal(&data.volume, &s->volume);
+ changed = !pa_cvolume_equal(&data.virtual_volume, &s->virtual_volume); /* from client-side view */
}
s->volume = data.volume;
+ s->virtual_volume = data.virtual_volume;
if (s->set_volume && s->set_volume(s) < 0)
s->set_volume = NULL;
if (!s->set_volume)
- pa_sink_set_soft_volume(s, volume);
+ pa_sink_set_soft_volume(s, &s->volume);
if (changed)
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
pa_assert(PA_SINK_IS_LINKED(s->state));
if (s->refresh_volume || force_refresh) {
- struct pa_cvolume old_volume = s->volume;
+ struct pa_cvolume old_volume = s->virtual_volume;
if (s->get_volume && s->get_volume(s) < 0)
s->get_volume = NULL;
- if (!s->get_volume)
+ if (!s->get_volume) {
pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_VOLUME, &s->volume, 0, NULL);
+ s->virtual_volume = s->volume;
+ }
- if (!pa_cvolume_equal(&old_volume, &s->volume))
+ if (!pa_cvolume_equal(&old_volume, &s->virtual_volume))
pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
}
- return &s->volume;
+ return &s->virtual_volume;
}
/* Called from main thread */
return s->muted;
}
+/* Called from main thread */
+pa_bool_t pa_sink_update_proplist(pa_sink *s, pa_update_mode_t mode, pa_proplist *p) {
+
+ pa_sink_assert_ref(s);
+
+ pa_proplist_update(s->proplist, mode, p);
+
+ if (PA_SINK_IS_LINKED(s->state)) {
+ pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_PROPLIST_CHANGED], s);
+ pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+ }
+
+ return TRUE;
+}
+
/* Called from main thread */
void pa_sink_set_description(pa_sink *s, const char *description) {
const char *old;
ret = pa_idxset_size(s->inputs);
/* We add in the number of streams connected to us here. Please
- * not the asymmmetry to pa_sink_used_by()! */
+ * note the asymmmetry to pa_sink_used_by()! */
if (s->monitor_source)
ret += pa_source_linked_by(s->monitor_source);
return ret - s->n_corked;
}
+/* Called from main thread */
+unsigned pa_sink_check_suspend(pa_sink *s) {
+ unsigned ret;
+ pa_sink_input *i;
+ uint32_t idx;
+
+ pa_sink_assert_ref(s);
+
+ if (!PA_SINK_IS_LINKED(s->state))
+ return 0;
+
+ ret = 0;
+
+ for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx))) {
+ pa_sink_input_state_t st;
+
+ st = pa_sink_input_get_state(i);
+ pa_assert(PA_SINK_INPUT_IS_LINKED(st));
+
+ if (st == PA_SINK_INPUT_CORKED)
+ continue;
+
+ if (i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND)
+ continue;
+
+ ret ++;
+ }
+
+ if (s->monitor_source)
+ ret += pa_source_check_suspend(s->monitor_source);
+
+ return ret;
+}
+
/* Called from IO thread, except when it is not */
int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
pa_sink *s = PA_SINK(o);
size_t sink_nbytes, total_nbytes;
/* Get the latency of the sink */
- if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+ if (!(s->flags & PA_SINK_LATENCY) ||
+ PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
usec = 0;
sink_nbytes = pa_usec_to_bytes(usec, &s->sample_spec);
size_t nbytes;
/* Get the latency of the sink */
- if (PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
+ if (!(s->flags & PA_SINK_LATENCY) ||
+ PA_MSGOBJECT(s)->process_msg(PA_MSGOBJECT(s), PA_SINK_MESSAGE_GET_LATENCY, &usec, 0, NULL) < 0)
usec = 0;
nbytes = pa_usec_to_bytes(usec, &s->sample_spec);