From e47d03dea446d0387a7c07a470c9c680537d9c34 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 3 Feb 2009 02:23:46 +0100 Subject: implement PA_STREAM_FAIL_ON_SUSPEND logic --- src/pulse/def.h | 8 +++++++- src/pulse/stream.c | 4 +++- src/pulsecore/cli-text.c | 8 ++++++-- src/pulsecore/protocol-native.c | 19 ++++++++++++------- src/pulsecore/sink-input.c | 6 +++++- src/pulsecore/sink-input.h | 1 + src/pulsecore/sink.c | 15 +++++++++------ src/pulsecore/source-output.c | 7 +++++-- src/pulsecore/source-output.h | 3 ++- src/pulsecore/source.c | 12 +++++++++--- 10 files changed, 59 insertions(+), 24 deletions(-) diff --git a/src/pulse/def.h b/src/pulse/def.h index 7517a7aa..85ac701d 100644 --- a/src/pulse/def.h +++ b/src/pulse/def.h @@ -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 */ diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 4efe63e9..fe2514d9 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -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); diff --git a/src/pulsecore/cli-text.c b/src/pulsecore/cli-text.c index 57129d0c..8ca8f2d9 100644 --- a/src/pulsecore/cli-text.c +++ b/src/pulsecore/cli-text.c @@ -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)), diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index c9621652..e8080bfe 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -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); diff --git a/src/pulsecore/sink-input.c b/src/pulsecore/sink-input.c index d4d11194..8bc434ea 100644 --- a/src/pulsecore/sink-input.c +++ b/src/pulsecore/sink-input.c @@ -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; diff --git a/src/pulsecore/sink-input.h b/src/pulsecore/sink-input.h index 893d8690..c27f6253 100644 --- a/src/pulsecore/sink-input.h +++ b/src/pulsecore/sink-input.h @@ -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 { diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index b669a71d..a3b6b146 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -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; } diff --git a/src/pulsecore/source-output.c b/src/pulsecore/source-output.c index 1e1ac4e1..9ef9b500 100644 --- a/src/pulsecore/source-output.c +++ b/src/pulsecore/source-output.c @@ -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; diff --git a/src/pulsecore/source-output.h b/src/pulsecore/source-output.h index 79b4926b..f4f94623 100644 --- a/src/pulsecore/source-output.h +++ b/src/pulsecore/source-output.h @@ -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 { diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c index 886f8d60..04c7f8b7 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -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; } -- cgit