pa_assert(i->sink); /* The destination sink should already be set. */
if (i->origin_sink && (i->origin_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
- pa_sink *root_sink = i->sink;
+ pa_sink *root_sink = pa_sink_get_master(i->sink);
pa_sink_input *origin_sink_input;
uint32_t idx;
- while (root_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
- root_sink = root_sink->input_to_master->sink;
+ if (PA_UNLIKELY(!root_sink))
+ return;
if (pa_sink_flat_volume_enabled(i->sink)) {
/* Ok, so the origin sink uses volume sharing, and flat volume is
enable_flat_volume(s, TRUE);
if (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER) {
- pa_sink *root_sink = s->input_to_master->sink;
+ pa_sink *root_sink = pa_sink_get_master(s);
- while (root_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
- root_sink = root_sink->input_to_master->sink;
+ pa_assert(root_sink);
s->reference_volume = root_sink->reference_volume;
pa_cvolume_remap(&s->reference_volume, &root_sink->channel_map, &s->channel_map);
pa_bool_t pa_sink_flat_volume_enabled(pa_sink *s) {
pa_sink_assert_ref(s);
- while (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
+ s = pa_sink_get_master(s);
+
+ if (PA_LIKELY(s))
+ return (s->flags & PA_SINK_FLAT_VOLUME);
+ else
+ return FALSE;
+}
+
+/* Called from the main thread (and also from the IO thread while the main
+ * thread is waiting). */
+pa_sink *pa_sink_get_master(pa_sink *s) {
+ pa_sink_assert_ref(s);
+
+ while (s && (s->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)) {
+ if (PA_UNLIKELY(!s->input_to_master))
+ return NULL;
+
s = s->input_to_master->sink;
+ }
- return (s->flags & PA_SINK_FLAT_VOLUME);
+ return s;
}
/* Called from main context */
pa_bool_t save) {
pa_cvolume new_reference_volume;
- pa_sink *root_sink = s;
+ pa_sink *root_sink;
pa_sink_assert_ref(s);
pa_assert_ctl_context();
/* In case of volume sharing, the volume is set for the root sink first,
* from which it's then propagated to the sharing sinks. */
- while (root_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
- root_sink = root_sink->input_to_master->sink;
+ root_sink = pa_sink_get_master(s);
+
+ if (PA_UNLIKELY(!root_sink))
+ return;
/* As a special exception we accept mono volumes on all sinks --
* even on those with more complex channel maps */
}
case PA_SINK_MESSAGE_SET_SHARED_VOLUME: {
- pa_sink *root_sink = s;
+ pa_sink *root_sink = pa_sink_get_master(s);
- while (root_sink->flags & PA_SINK_SHARE_VOLUME_WITH_MASTER)
- root_sink = root_sink->input_to_master->sink;
+ if (PA_LIKELY(root_sink))
+ set_shared_volume_within_thread(root_sink);
- set_shared_volume_within_thread(root_sink);
return 0;
}
/* Use this instead of checking s->flags & PA_SINK_FLAT_VOLUME directly. */
pa_bool_t pa_sink_flat_volume_enabled(pa_sink *s);
+/* Get the master sink when sharing volumes */
+pa_sink *pa_sink_get_master(pa_sink *s);
+
/* Is the sink in passthrough mode? (that is, is there a passthrough sink input
* connected to this sink? */
pa_bool_t pa_sink_is_passthrough(pa_sink *s);
pa_assert(o->source); /* The destination source should already be set. */
if (o->destination_source && (o->destination_source->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)) {
- pa_source *root_source = o->source;
+ pa_source *root_source;
pa_source_output *destination_source_output;
uint32_t idx;
- while (root_source->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)
- root_source = root_source->output_from_master->source;
+ root_source = pa_source_get_master(o->source);
+
+ if (PA_UNLIKELY(!root_source))
+ return;
if (pa_source_flat_volume_enabled(o->source)) {
/* Ok, so the origin source uses volume sharing, and flat volume is
enable_flat_volume(s, TRUE);
if (s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER) {
- pa_source *root_source = s->output_from_master->source;
+ pa_source *root_source = pa_source_get_master(s);
- while (root_source->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)
- root_source = root_source->output_from_master->source;
+ pa_assert(PA_LIKELY(root_source));
s->reference_volume = root_source->reference_volume;
pa_cvolume_remap(&s->reference_volume, &root_source->channel_map, &s->channel_map);
pa_bool_t pa_source_flat_volume_enabled(pa_source *s) {
pa_source_assert_ref(s);
- while (s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)
+ s = pa_source_get_master(s);
+
+ if (PA_LIKELY(s))
+ return (s->flags & PA_SOURCE_FLAT_VOLUME);
+ else
+ return FALSE;
+}
+
+/* Called from the main thread (and also from the IO thread while the main
+ * thread is waiting). */
+pa_source *pa_source_get_master(pa_source *s) {
+ pa_source_assert_ref(s);
+
+ while (s && (s->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)) {
+ if (PA_UNLIKELY(!s->output_from_master))
+ return NULL;
+
s = s->output_from_master->source;
+ }
- return (s->flags & PA_SOURCE_FLAT_VOLUME);
+ return s;
}
/* Called from main context */
pa_bool_t save) {
pa_cvolume new_reference_volume;
- pa_source *root_source = s;
+ pa_source *root_source;
pa_source_assert_ref(s);
pa_assert_ctl_context();
/* In case of volume sharing, the volume is set for the root source first,
* from which it's then propagated to the sharing sources. */
- while (root_source->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)
- root_source = root_source->output_from_master->source;
+ root_source = pa_source_get_master(s);
+
+ if (PA_UNLIKELY(!root_source))
+ return;
/* As a special exception we accept mono volumes on all sources --
* even on those with more complex channel maps */
}
case PA_SOURCE_MESSAGE_SET_SHARED_VOLUME: {
- pa_source *root_source = s;
+ pa_source *root_source = pa_source_get_master(s);
- while (root_source->flags & PA_SOURCE_SHARE_VOLUME_WITH_MASTER)
- root_source = root_source->output_from_master->source;
+ if (PA_LIKELY(root_source))
+ set_shared_volume_within_thread(root_source);
- set_shared_volume_within_thread(root_source);
return 0;
}
/* Use this instead of checking s->flags & PA_SOURCE_FLAT_VOLUME directly. */
pa_bool_t pa_source_flat_volume_enabled(pa_source *s);
+/* Get the master source when sharing volumes */
+pa_source *pa_source_get_master(pa_source *s);
+
/* Is the source in passthrough mode? (that is, is this a monitor source for a sink
* that has a passthrough sink input connected to it. */
pa_bool_t pa_source_is_passthrough(pa_source *s);