]> code.delx.au - pulseaudio/commitdiff
add new virtual function may_move_to to sink inputs/source outputs to allow modules...
authorLennart Poettering <lennart@poettering.net>
Tue, 21 Oct 2008 16:24:45 +0000 (18:24 +0200)
committerLennart Poettering <lennart@poettering.net>
Tue, 21 Oct 2008 16:24:45 +0000 (18:24 +0200)
src/pulsecore/sink-input.c
src/pulsecore/sink-input.h
src/pulsecore/source-output.c
src/pulsecore/source-output.h

index 138411605788abd0a79fa0e97d5a718c27f0aff8..0e1224f13d18f3323065318b4195ac8312f63cc0 100644 (file)
@@ -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);
index ed95fe4bc1051ce11b6f4bedf1c8317219344b58..97668c5295beee1296462c7c2f7ebc00cfb39604 100644 (file)
@@ -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);
 
index 7adc7572e4a070557b811c841cdda82f89c78ba2..376402fa480efcf5cbe7a2c75eb85a51b1b041f7 100644 (file)
@@ -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) &&
index a7aac8143788fcc008d114719dfa28acdcc8ffed..6ae10c6264e10c5b636dad0dfb8caf20a7dcc099 100644 (file)
@@ -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)