From 358824b330e20b9e6472fdefc4613e03b20c9abb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 21 Oct 2008 18:24:45 +0200 Subject: add new virtual function may_move_to to sink inputs/source outputs to allow modules to forbid certain connections --- src/pulsecore/sink-input.c | 42 +++++++++++++++++++++++++++++++----------- src/pulsecore/sink-input.h | 8 +++++++- src/pulsecore/source-output.c | 37 ++++++++++++++++++++++++++++--------- src/pulsecore/source-output.h | 8 +++++++- 4 files changed, 73 insertions(+), 22 deletions(-) (limited to 'src/pulsecore') diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index 13841160..0e1224f1 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -108,6 +108,7 @@ static void reset_callbacks(pa_sink_input *i) { i->kill = NULL; i->get_latency = NULL; i->state_change = NULL; + i->may_move_to = NULL; } /* Called from main context */ @@ -910,6 +911,35 @@ pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i) { return i->resample_method; } +/* Called from main context */ +pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest) { + pa_sink_input_assert_ref(i); + pa_assert(PA_SINK_INPUT_IS_LINKED(i->state)); + pa_sink_assert_ref(dest); + + if (dest == i->sink) + return TRUE; + + if (i->flags & PA_SINK_INPUT_DONT_MOVE) + return FALSE; + + if (i->sync_next || i->sync_prev) { + pa_log_warn("Moving synchronised streams not supported."); + return FALSE; + } + + if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) { + pa_log_warn("Failed to move sink input: too many inputs per sink."); + return FALSE; + } + + if (i->may_move_to) + if (!i->may_move_to(i, dest)) + return FALSE; + + return TRUE; +} + /* Called from main context */ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) { pa_resampler *new_resampler; @@ -926,19 +956,9 @@ int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest) { if (dest == origin) return 0; - if (i->flags & PA_SINK_INPUT_DONT_MOVE) + if (!pa_sink_input_may_move_to(i, dest)) return -1; - if (i->sync_next || i->sync_prev) { - pa_log_warn("Moving synchronised streams not supported."); - return -1; - } - - if (pa_idxset_size(dest->inputs) >= PA_MAX_INPUTS_PER_SINK) { - pa_log_warn("Failed to move sink input: too many inputs per sink."); - return -1; - } - /* Kill directly connected outputs */ while ((o = pa_idxset_first(i->direct_outputs, NULL))) { pa_assert(o != p); diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index ed95fe4b..97668c52 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -156,10 +156,15 @@ struct pa_sink_input { returns */ pa_usec_t (*get_latency) (pa_sink_input *i); /* may be NULL */ - /* If non_NULL this function is called from thread context if the + /* If non-NULL this function is called from thread context if the * state changes. The old state is found in thread_info.state. */ void (*state_change) (pa_sink_input *i, pa_sink_input_state_t state); /* may be NULL */ + /* If non-NULL this function is called before this sink input is + * move to a sink and if it returns FALSE the move will not + * be allowed */ + pa_bool_t (*may_move_to) (pa_sink_input *i, pa_sink *s); /* may be NULL */ + struct { pa_sink_input_state_t state; pa_atomic_t drained; @@ -292,6 +297,7 @@ pa_bool_t pa_sink_input_get_mute(pa_sink_input *i); pa_resample_method_t pa_sink_input_get_resample_method(pa_sink_input *i); int pa_sink_input_move_to(pa_sink_input *i, pa_sink *dest); +pa_bool_t pa_sink_input_may_move_to(pa_sink_input *i, pa_sink *dest); pa_sink_input_state_t pa_sink_input_get_state(pa_sink_input *i); diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 7adc7572..376402fa 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -90,6 +90,7 @@ static void reset_callbacks(pa_source_output *o) { o->kill = NULL; o->get_latency = NULL; o->state_change = NULL; + o->may_move_to = NULL; } /* Called from main context */ @@ -593,6 +594,32 @@ pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o) { return o->resample_method; } +pa_bool_t pa_source_output_may_move_to(pa_source_output *o, pa_source *dest) { + pa_source_output_assert_ref(o); + pa_assert(PA_SOURCE_OUTPUT_IS_LINKED(o->state)); + pa_source_assert_ref(dest); + + if (dest == o->source) + return TRUE; + + if (o->flags & PA_SOURCE_OUTPUT_DONT_MOVE) + return FALSE; + + if (o->direct_on_input) + return FALSE; + + if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { + pa_log_warn("Failed to move source output: too many outputs per source."); + return FALSE; + } + + if (o->may_move_to) + if (!o->may_move_to(o, dest)) + return FALSE; + + return TRUE; +} + /* Called from main context */ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { pa_source *origin; @@ -608,16 +635,8 @@ int pa_source_output_move_to(pa_source_output *o, pa_source *dest) { if (dest == origin) return 0; - if (o->flags & PA_SOURCE_OUTPUT_DONT_MOVE) - return -1; - - if (o->direct_on_input) - return -1; - - if (pa_idxset_size(dest->outputs) >= PA_MAX_OUTPUTS_PER_SOURCE) { - pa_log_warn("Failed to move source output: too many outputs per source."); + if (!pa_source_output_may_move_to(o, dest)) return -1; - } if (o->thread_info.resampler && pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) && diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index a7aac814..6ae10c62 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -126,10 +126,15 @@ struct pa_source_output { returns */ pa_usec_t (*get_latency) (pa_source_output *o); /* may be NULL */ - /* If non_NULL this function is called from thread context if the + /* If non-NULL this function is called from thread context if the * state changes. The old state is found in thread_info.state. */ void (*state_change) (pa_source_output *o, pa_source_output_state_t state); /* may be NULL */ + /* If non-NULL this function is called before this source output + * is moved to a source and if it returns FALSE the move + * will not be allowed */ + pa_bool_t (*may_move_to) (pa_source_output *o, pa_source *s); /* may be NULL */ + struct { pa_source_output_state_t state; @@ -220,6 +225,7 @@ pa_usec_t pa_source_output_get_latency(pa_source_output *i, pa_usec_t *source_la pa_resample_method_t pa_source_output_get_resample_method(pa_source_output *o); +pa_bool_t pa_source_output_may_move_to(pa_source_output *o, pa_source *dest); int pa_source_output_move_to(pa_source_output *o, pa_source *dest); #define pa_source_output_get_state(o) ((o)->state) -- cgit