implement PA_STREAM_FAIL_ON_SUSPEND logic
authorLennart Poettering <lennart@poettering.net>
Tue, 3 Feb 2009 01:23:46 +0000 (02:23 +0100)
committerLennart Poettering <lennart@poettering.net>
Tue, 3 Feb 2009 01:23:46 +0000 (02:23 +0100)
src/pulse/def.h
src/pulse/stream.c
src/pulsecore/cli-text.c
src/pulsecore/protocol-native.c
src/pulsecore/sink-input.c
src/pulsecore/sink-input.h
src/pulsecore/sink.c
src/pulsecore/source-output.c
src/pulsecore/source-output.h
src/pulsecore/source.c

index 7517a7a..85ac701 100644 (file)
@@ -237,12 +237,17 @@ typedef enum pa_stream_flags {
      * checked whether the device this stream is connected to should
      * auto-suspend. \since 0.9.15 */
 
-    PA_STREAM_START_UNMUTED = 0x10000U
+    PA_STREAM_START_UNMUTED = 0x10000U,
     /**< Create in unmuted state. If neither PA_STREAM_START_UNMUTED
      * nor PA_STREAM_START_MUTED it is left to the server to decide
      * whether to create the stream in muted or in unmuted
      * state. \since 0.9.15 */
 
+    PA_STREAM_FAIL_ON_SUSPEND = 0x20000U
+    /**< If the sink/source this stream is connected to is suspended
+     * during the creation of this stream, cause it to fail. If the
+     * sink/source is being suspended during creation of this stream,
+     * make sure this stream is terminated. \since 0.9.15 */
 } pa_stream_flags_t;
 
 /** \cond fulldocs */
@@ -268,6 +273,7 @@ typedef enum pa_stream_flags {
 #define PA_STREAM_EARLY_REQUESTS PA_STREAM_EARLY_REQUESTS
 #define PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND
 #define PA_STREAM_START_UNMUTED PA_STREAM_START_UNMUTED
+#define PA_STREAM_FAIL_ON_SUSPEND PA_STREAM_FAIL_ON_SUSPEND
 
 /** \endcond */
 
index 4efe63e..fe2514d 100644 (file)
@@ -891,7 +891,8 @@ static int create_stream(
                                               PA_STREAM_ADJUST_LATENCY|
                                               PA_STREAM_EARLY_REQUESTS|
                                               PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND|
-                                              PA_STREAM_START_UNMUTED)), PA_ERR_INVALID);
+                                              PA_STREAM_START_UNMUTED|
+                                              PA_STREAM_FAIL_ON_SUSPEND)), PA_ERR_INVALID);
 
     PA_CHECK_VALIDITY(s->context, s->context->version >= 12 || !(flags & PA_STREAM_VARIABLE_RATE), PA_ERR_NOTSUPPORTED);
     PA_CHECK_VALIDITY(s->context, s->context->version >= 13 || !(flags & PA_STREAM_PEAK_DETECT), PA_ERR_NOTSUPPORTED);
@@ -1017,6 +1018,7 @@ static int create_stream(
             pa_tagstruct_put_boolean(t, flags & (PA_STREAM_START_MUTED|PA_STREAM_START_UNMUTED));
 
         pa_tagstruct_put_boolean(t, flags & PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND);
+        pa_tagstruct_put_boolean(t, flags & PA_STREAM_FAIL_ON_SUSPEND);
     }
 
     pa_pstream_send_tagstruct(s->context->pstream, t);
index 57129d0..8ca8f2d 100644 (file)
@@ -421,7 +421,7 @@ char *pa_source_output_list_to_string(pa_core *c) {
             s,
             "    index: %u\n"
             "\tdriver: <%s>\n"
-            "\tflags: %s%s%s%s%s%s%s%s\n"
+            "\tflags: %s%s%s%s%s%s%s%s%s%s\n"
             "\tstate: %s\n"
             "\tsource: %u <%s>\n"
             "\tcurrent latency: %0.2f ms\n"
@@ -439,6 +439,8 @@ char *pa_source_output_list_to_string(pa_core *c) {
             o->flags & PA_SOURCE_OUTPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
             o->flags & PA_SOURCE_OUTPUT_FIX_RATE ? "FIX_RATE " : "",
             o->flags & PA_SOURCE_OUTPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
+            o->flags & PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "",
+            o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND ? "FAIL_ON_SUSPEND " : "",
             state_table[pa_source_output_get_state(o)],
             o->source->index, o->source->name,
             (double) pa_source_output_get_latency(o, NULL) / PA_USEC_PER_MSEC,
@@ -498,7 +500,7 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             s,
             "    index: %u\n"
             "\tdriver: <%s>\n"
-            "\tflags: %s%s%s%s%s%s%s%s\n"
+            "\tflags: %s%s%s%s%s%s%s%s%s%s\n"
             "\tstate: %s\n"
             "\tsink: %u <%s>\n"
             "\tvolume: %s\n"
@@ -520,6 +522,8 @@ char *pa_sink_input_list_to_string(pa_core *c) {
             i->flags & PA_SINK_INPUT_FIX_FORMAT ? "FIX_FORMAT " : "",
             i->flags & PA_SINK_INPUT_FIX_RATE ? "FIX_RATE " : "",
             i->flags & PA_SINK_INPUT_FIX_CHANNELS ? "FIX_CHANNELS " : "",
+            i->flags & PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND ? "DONT_INHIBIT_AUTO_SUSPEND " : "",
+            i->flags & PA_SINK_INPUT_FAIL_ON_SUSPEND ? "FAIL_ON_SUSPEND " : "",
             state_table[pa_sink_input_get_state(i)],
             i->sink->index, i->sink->name,
             pa_cvolume_snprint(cv, sizeof(cv), pa_sink_input_get_volume(i)),
index c962165..e8080bf 100644 (file)
@@ -1691,8 +1691,8 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
         adjust_latency = FALSE,
         early_requests = FALSE,
         dont_inhibit_auto_suspend = FALSE,
-        muted_set = FALSE;
-
+        muted_set = FALSE,
+        fail_on_suspend = FALSE;
     pa_sink_input_flags_t flags = 0;
     pa_proplist *p;
     pa_bool_t volume_set = TRUE;
@@ -1775,7 +1775,8 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
     if (c->version >= 15) {
 
         if (pa_tagstruct_get_boolean(t, &muted_set) < 0 ||
-            pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0) {
+            pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
+            pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
             protocol_error(c);
             pa_proplist_free(p);
             return;
@@ -1814,7 +1815,8 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u
         (fix_channels ?  PA_SINK_INPUT_FIX_CHANNELS : 0) |
         (no_move ?  PA_SINK_INPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SINK_INPUT_VARIABLE_RATE : 0) |
-        (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0);
+        (dont_inhibit_auto_suspend ? PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
+        (fail_on_suspend ? PA_SINK_INPUT_FAIL_ON_SUSPEND : 0);
 
     /* Only since protocol version 15 there's a seperate muted_set
      * flag. For older versions we synthesize it here */
@@ -1942,7 +1944,8 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
         adjust_latency = FALSE,
         peak_detect = FALSE,
         early_requests = FALSE,
-        dont_inhibit_auto_suspend = FALSE;
+        dont_inhibit_auto_suspend = FALSE,
+        fail_on_suspend = FALSE;
     pa_source_output_flags_t flags = 0;
     pa_proplist *p;
     uint32_t direct_on_input_idx = PA_INVALID_INDEX;
@@ -2016,7 +2019,8 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
 
     if (c->version >= 15) {
 
-        if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0) {
+        if (pa_tagstruct_get_boolean(t, &dont_inhibit_auto_suspend) < 0 ||
+            pa_tagstruct_get_boolean(t, &fail_on_suspend) < 0) {
             protocol_error(c);
             pa_proplist_free(p);
             return;
@@ -2064,7 +2068,8 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin
         (fix_channels ?  PA_SOURCE_OUTPUT_FIX_CHANNELS : 0) |
         (no_move ?  PA_SOURCE_OUTPUT_DONT_MOVE : 0) |
         (variable_rate ?  PA_SOURCE_OUTPUT_VARIABLE_RATE : 0) |
-        (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0);
+        (dont_inhibit_auto_suspend ? PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND : 0) |
+        (fail_on_suspend ? PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND : 0);
 
     s = record_stream_new(c, source, &ss, &map, peak_detect, &maxlength, &fragment_size, flags, p, adjust_latency, direct_on_input, early_requests);
     pa_proplist_free(p);
index d4d1119..8bc434e 100644 (file)
@@ -144,9 +144,13 @@ pa_sink_input* pa_sink_input_new(
     }
 
     pa_return_null_if_fail(data->sink);
-    pa_return_null_if_fail(pa_sink_get_state(data->sink) != PA_SINK_UNLINKED);
+    pa_return_null_if_fail(PA_SINK_IS_LINKED(pa_sink_get_state(data->sink)));
     pa_return_null_if_fail(!data->sync_base || (data->sync_base->sink == data->sink && pa_sink_input_get_state(data->sync_base) == PA_SINK_INPUT_CORKED));
 
+    if ((flags & PA_SINK_INPUT_FAIL_ON_SUSPEND) &&
+        pa_sink_get_state(data->sink) == PA_SINK_SUSPENDED)
+        return NULL;
+
     if (!data->sample_spec_is_set)
         data->sample_spec = data->sink->sample_spec;
 
index 893d869..c27f625 100644 (file)
@@ -58,6 +58,7 @@ typedef enum pa_sink_input_flags {
     PA_SINK_INPUT_FIX_RATE = 64,
     PA_SINK_INPUT_FIX_CHANNELS = 128,
     PA_SINK_INPUT_DONT_INHIBIT_AUTO_SUSPEND = 256,
+    PA_SINK_INPUT_FAIL_ON_SUSPEND = 512
 } pa_sink_input_flags_t;
 
 struct pa_sink_input {
index b669a71..a3b6b14 100644 (file)
@@ -305,6 +305,11 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
 
     s->state = state;
 
+    if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    }
+
     if (suspend_change) {
         pa_sink_input *i;
         uint32_t idx;
@@ -312,15 +317,13 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state) {
         /* We're suspending or resuming, tell everyone about it */
 
         for (i = PA_SINK_INPUT(pa_idxset_first(s->inputs, &idx)); i; i = PA_SINK_INPUT(pa_idxset_next(s->inputs, &idx)))
-            if (i->suspend)
+            if (s->state == PA_SINK_SUSPENDED &&
+                (i->flags & PA_SINK_INPUT_FAIL_ON_SUSPEND))
+                pa_sink_input_kill(i);
+            else if (i->suspend)
                 i->suspend(i, state == PA_SINK_SUSPENDED);
     }
 
-    if (state != PA_SINK_UNLINKED) { /* if we enter UNLINKED state pa_sink_unlink() will fire the apropriate events */
-        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SINK_STATE_CHANGED], s);
-        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SINK | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
-    }
-
     return 0;
 }
 
index 1e1ac4e..9ef9b50 100644 (file)
@@ -118,10 +118,13 @@ pa_source_output* pa_source_output_new(
     }
 
     pa_return_null_if_fail(data->source);
-    pa_return_null_if_fail(pa_source_get_state(data->source) != PA_SOURCE_UNLINKED);
-
+    pa_return_null_if_fail(PA_SOURCE_IS_LINKED(pa_source_get_state(data->source)));
     pa_return_null_if_fail(!data->direct_on_input || data->direct_on_input->sink == data->source->monitor_of);
 
+    if ((flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND) &&
+        pa_source_get_state(data->source) == PA_SOURCE_SUSPENDED)
+        return NULL;
+
     if (!data->sample_spec_is_set)
         data->sample_spec = data->source->sample_spec;
 
index 79b4926..f4f9462 100644 (file)
@@ -54,7 +54,8 @@ typedef enum pa_source_output_flags {
     PA_SOURCE_OUTPUT_FIX_FORMAT = 32,
     PA_SOURCE_OUTPUT_FIX_RATE = 64,
     PA_SOURCE_OUTPUT_FIX_CHANNELS = 128,
-    PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND = 256
+    PA_SOURCE_OUTPUT_DONT_INHIBIT_AUTO_SUSPEND = 256,
+    PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND = 512
 } pa_source_output_flags_t;
 
 struct pa_source_output {
index 886f8d6..04c7f8b 100644 (file)
@@ -267,6 +267,11 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
 
     s->state = state;
 
+    if (state != PA_SOURCE_UNLINKED) { /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
+        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
+        pa_subscription_post(s->core, PA_SUBSCRIPTION_EVENT_SOURCE | PA_SUBSCRIPTION_EVENT_CHANGE, s->index);
+    }
+
     if (suspend_change) {
         pa_source_output *o;
         uint32_t idx;
@@ -274,12 +279,13 @@ static int source_set_state(pa_source *s, pa_source_state_t state) {
         /* We're suspending or resuming, tell everyone about it */
 
         for (o = PA_SOURCE_OUTPUT(pa_idxset_first(s->outputs, &idx)); o; o = PA_SOURCE_OUTPUT(pa_idxset_next(s->outputs, &idx)))
-            if (o->suspend)
+            if (s->state == PA_SOURCE_SUSPENDED &&
+                (o->flags & PA_SOURCE_OUTPUT_FAIL_ON_SUSPEND))
+                pa_source_output_kill(o);
+            else if (o->suspend)
                 o->suspend(o, state == PA_SOURCE_SUSPENDED);
     }
 
-    if (state != PA_SOURCE_UNLINKED) /* if we enter UNLINKED state pa_source_unlink() will fire the apropriate events */
-        pa_hook_fire(&s->core->hooks[PA_CORE_HOOK_SOURCE_STATE_CHANGED], s);
 
     return 0;
 }