mirror of
https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
synced 2025-10-29 05:40:23 -04:00
add new virtual function may_move_to to sink inputs/source outputs to allow modules to forbid certain connections
This commit is contained in:
parent
309bc71f07
commit
358824b330
4 changed files with 73 additions and 22 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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,17 +635,9 @@ 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)
|
||||
if (!pa_source_output_may_move_to(o, dest))
|
||||
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.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (o->thread_info.resampler &&
|
||||
pa_sample_spec_equal(&origin->sample_spec, &dest->sample_spec) &&
|
||||
pa_channel_map_equal(&origin->channel_map, &dest->channel_map))
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue