summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/modules/alsa/alsa-sink.c7
-rw-r--r--src/modules/alsa/alsa-source.c7
-rw-r--r--src/modules/bluetooth/module-bluez4-device.c4
-rw-r--r--src/modules/bluetooth/module-bluez5-device.c4
-rw-r--r--src/modules/echo-cancel/module-echo-cancel.c2
-rw-r--r--src/modules/module-combine-sink.c7
-rw-r--r--src/modules/module-equalizer-sink.c2
-rw-r--r--src/modules/module-esound-sink.c7
-rw-r--r--src/modules/module-ladspa-sink.c2
-rw-r--r--src/modules/module-null-sink.c2
-rw-r--r--src/modules/module-null-source.c2
-rw-r--r--src/modules/module-pipe-sink.c2
-rw-r--r--src/modules/module-remap-sink.c2
-rw-r--r--src/modules/module-sine-source.c2
-rw-r--r--src/modules/module-solaris.c14
-rw-r--r--src/modules/module-tunnel-sink-new.c7
-rw-r--r--src/modules/module-tunnel-source-new.c7
-rw-r--r--src/modules/module-virtual-sink.c2
-rw-r--r--src/modules/module-virtual-surround-sink.c2
-rw-r--r--src/modules/oss/module-oss.c14
-rw-r--r--src/modules/raop/raop-sink.c7
-rw-r--r--src/pulsecore/sink.c59
-rw-r--r--src/pulsecore/sink.h2
-rw-r--r--src/pulsecore/source.c59
-rw-r--r--src/pulsecore/source.h2
25 files changed, 172 insertions, 55 deletions
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 9e335374c..3b962b90e 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1209,12 +1209,17 @@ static int sink_set_state_in_main_thread_cb(pa_sink *s, pa_sink_state_t new_stat
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
switch (new_state) {
case PA_SINK_SUSPENDED: {
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index 312b2596a..69da88dab 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1064,12 +1064,17 @@ static int source_set_state_in_main_thread_cb(pa_source *s, pa_source_state_t ne
}
/* Called from the IO thread. */
-static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state) {
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
switch (new_state) {
case PA_SOURCE_SUSPENDED: {
diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c
index 85eb7986b..79d75c11b 100644
--- a/src/modules/bluetooth/module-bluez4-device.c
+++ b/src/modules/bluetooth/module-bluez4-device.c
@@ -413,7 +413,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
@@ -487,7 +487,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
}
/* Called from the IO thread. */
-static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state) {
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index 5e189ba24..c3acc1dc6 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -915,7 +915,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
}
/* Called from the IO thread. */
-static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state) {
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
@@ -1092,7 +1092,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index 893c41eeb..c8065d823 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -514,7 +514,7 @@ static int sink_set_state_in_main_thread_cb(pa_sink *s, pa_sink_state_t state, p
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-combine-sink.c b/src/modules/module-combine-sink.c
index bbd416b6f..f7649a365 100644
--- a/src/modules/module-combine-sink.c
+++ b/src/modules/module-combine-sink.c
@@ -719,13 +719,18 @@ static int sink_set_state_in_main_thread_cb(pa_sink *sink, pa_sink_state_t state
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
bool running;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
running = new_state == PA_SINK_RUNNING;
pa_atomic_store(&u->thread_info.running, running);
diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
index 36029b389..43375999d 100644
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -288,7 +288,7 @@ static int sink_set_state_in_main_thread_cb(pa_sink *s, pa_sink_state_t state, p
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 9fea2da74..3f6b8116b 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -169,12 +169,17 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
switch (new_state) {
case PA_SINK_SUSPENDED:
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index de866d96a..d677381d8 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -395,7 +395,7 @@ static int sink_set_state_in_main_thread_cb(pa_sink *s, pa_sink_state_t state, p
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index 16b0b6870..baaf06477 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -103,7 +103,7 @@ static int sink_process_msg(
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-null-source.c b/src/modules/module-null-source.c
index ae67206a3..0e4c8d2f2 100644
--- a/src/modules/module-null-source.c
+++ b/src/modules/module-null-source.c
@@ -103,7 +103,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
}
/* Called from the IO thread. */
-static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state) {
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index b2378059b..fc01206b6 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -136,7 +136,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index 56e7a85fd..f53b6b150 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -115,7 +115,7 @@ static int sink_set_state_in_main_thread(pa_sink *s, pa_sink_state_t state, pa_s
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-sine-source.c b/src/modules/module-sine-source.c
index 39fb71ab3..803fae5e9 100644
--- a/src/modules/module-sine-source.c
+++ b/src/modules/module-sine-source.c
@@ -103,7 +103,7 @@ static int source_process_msg(
}
/* Called from the IO thread. */
-static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state) {
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c
index e68f2a93d..ef42b3d9a 100644
--- a/src/modules/module-solaris.c
+++ b/src/modules/module-solaris.c
@@ -396,12 +396,17 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
switch (new_state) {
case PA_SINK_SUSPENDED:
@@ -457,12 +462,17 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
}
/* Called from the IO thread. */
-static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state) {
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
switch (new_state) {
case PA_SOURCE_SUSPENDED:
diff --git a/src/modules/module-tunnel-sink-new.c b/src/modules/module-tunnel-sink-new.c
index 313903372..802e6a59a 100644
--- a/src/modules/module-tunnel-sink-new.c
+++ b/src/modules/module-tunnel-sink-new.c
@@ -434,12 +434,17 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
if (!u->stream || pa_stream_get_state(u->stream) != PA_STREAM_READY)
return 0;
diff --git a/src/modules/module-tunnel-source-new.c b/src/modules/module-tunnel-source-new.c
index d0a5414ad..b41f53e2f 100644
--- a/src/modules/module-tunnel-source-new.c
+++ b/src/modules/module-tunnel-source-new.c
@@ -433,12 +433,17 @@ static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t
}
/* Called from the IO thread. */
-static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state) {
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
if (!u->stream || pa_stream_get_state(u->stream) != PA_STREAM_READY)
return 0;
diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-sink.c
index 68ad20076..e13455235 100644
--- a/src/modules/module-virtual-sink.c
+++ b/src/modules/module-virtual-sink.c
@@ -127,7 +127,7 @@ static int sink_set_state_in_main_thread_cb(pa_sink *s, pa_sink_state_t state, p
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/module-virtual-surround-sink.c b/src/modules/module-virtual-surround-sink.c
index 7c5e246cf..2c3d54ba5 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -155,7 +155,7 @@ static int sink_set_state_in_main_thread_cb(pa_sink *s, pa_sink_state_t state, p
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c
index d2551bcfc..42a6e3b03 100644
--- a/src/modules/oss/module-oss.c
+++ b/src/modules/oss/module-oss.c
@@ -666,7 +666,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
bool do_trigger = false;
bool quick = true;
@@ -674,6 +674,11 @@ static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state)
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
switch (new_state) {
case PA_SINK_SUSPENDED:
@@ -749,7 +754,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
}
/* Called from the IO thread. */
-static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state) {
+static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
bool do_trigger = false;
bool quick = true;
@@ -757,6 +762,11 @@ static int source_set_state_in_io_thread_cb(pa_source *s, pa_source_state_t new_
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
switch (new_state) {
case PA_SOURCE_SUSPENDED:
diff --git a/src/modules/raop/raop-sink.c b/src/modules/raop/raop-sink.c
index baa346641..818cdfe01 100644
--- a/src/modules/raop/raop-sink.c
+++ b/src/modules/raop/raop-sink.c
@@ -221,12 +221,17 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
}
/* Called from the IO thread. */
-static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state) {
+static int sink_set_state_in_io_thread_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) {
struct userdata *u;
pa_assert(s);
pa_assert_se(u = s->userdata);
+ /* It may be that only the suspend cause is changing, in which case there's
+ * nothing to do. */
+ if (new_state == s->thread_info.state)
+ return 0;
+
switch (new_state) {
case PA_SINK_SUSPENDED:
pa_log_debug("RAOP: SUSPENDED");
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 2c9334931..2174354f2 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -69,6 +69,11 @@ struct sink_message_set_port {
int ret;
};
+struct set_state_data {
+ pa_sink_state_t state;
+ pa_suspend_cause_t suspend_cause;
+};
+
static void sink_free(pa_object *s);
static void pa_sink_volume_change_push(pa_sink *s);
@@ -429,19 +434,49 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t
* current approach of not setting any suspend cause works well enough. */
if (s->set_state_in_main_thread) {
- ret = s->set_state_in_main_thread(s, state, suspend_cause);
- /* set_state_in_main_thread() is allowed to fail only when resuming. */
- pa_assert(ret >= 0 || resuming);
+ if ((ret = s->set_state_in_main_thread(s, state, suspend_cause)) < 0) {
+ /* set_state_in_main_thread() is allowed to fail only when resuming. */
+ pa_assert(resuming);
+
+ /* If resuming fails, we set the state to SUSPENDED and
+ * suspend_cause to 0. */
+ state = PA_SINK_SUSPENDED;
+ suspend_cause = 0;
+ state_changed = false;
+ suspend_cause_changed = suspend_cause != s->suspend_cause;
+ resuming = false;
+
+ /* We know the state isn't changing. If the suspend cause isn't
+ * changing either, then there's nothing more to do. */
+ if (!suspend_cause_changed)
+ return ret;
+ }
}
- if (ret >= 0 && s->asyncmsgq && state_changed)
- if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
+ if (s->asyncmsgq) {
+ struct set_state_data data = { .state = state, .suspend_cause = suspend_cause };
+
+ if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SINK_MESSAGE_SET_STATE, &data, 0, NULL)) < 0) {
/* SET_STATE is allowed to fail only when resuming. */
pa_assert(resuming);
if (s->set_state_in_main_thread)
s->set_state_in_main_thread(s, PA_SINK_SUSPENDED, 0);
+
+ /* If resuming fails, we set the state to SUSPENDED and
+ * suspend_cause to 0. */
+ state = PA_SINK_SUSPENDED;
+ suspend_cause = 0;
+ state_changed = false;
+ suspend_cause_changed = suspend_cause != s->suspend_cause;
+ resuming = false;
+
+ /* We know the state isn't changing. If the suspend cause isn't
+ * changing either, then there's nothing more to do. */
+ if (!suspend_cause_changed)
+ return ret;
}
+ }
if (suspend_cause_changed) {
char old_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
@@ -452,9 +487,6 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t
s->suspend_cause = suspend_cause;
}
- if (ret < 0)
- goto finish;
-
if (state_changed) {
pa_log_debug("%s: state: %s -> %s", s->name, pa_sink_state_to_string(s->state), pa_sink_state_to_string(state));
s->state = state;
@@ -481,7 +513,6 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t
i->suspend(i, state == PA_SINK_SUSPENDED);
}
-finish:
if ((suspending || resuming || suspend_cause_changed) && s->monitor_source && state != PA_SINK_UNLINKED)
pa_source_sync_suspend(s->monitor_source);
@@ -2846,19 +2877,19 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
return 0;
case PA_SINK_MESSAGE_SET_STATE: {
-
+ struct set_state_data *data = userdata;
bool suspend_change =
- (s->thread_info.state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
- (PA_SINK_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SINK_SUSPENDED);
+ (s->thread_info.state == PA_SINK_SUSPENDED && PA_SINK_IS_OPENED(data->state)) ||
+ (PA_SINK_IS_OPENED(s->thread_info.state) && data->state == PA_SINK_SUSPENDED);
if (s->set_state_in_io_thread) {
int r;
- if ((r = s->set_state_in_io_thread(s, PA_PTR_TO_UINT(userdata))) < 0)
+ if ((r = s->set_state_in_io_thread(s, data->state, data->suspend_cause)) < 0)
return r;
}
- s->thread_info.state = PA_PTR_TO_UINT(userdata);
+ s->thread_info.state = data->state;
if (s->thread_info.state == PA_SINK_SUSPENDED) {
s->thread_info.rewind_nbytes = 0;
diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h
index e1ea52495..3e9191d27 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -148,7 +148,7 @@ struct pa_sink {
* are updated only after all the callback calls. In case of failure, the
* state is set to SUSPENDED and the suspend cause is set to 0. */
int (*set_state_in_main_thread)(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause); /* may be NULL */
- int (*set_state_in_io_thread)(pa_sink *s, pa_sink_state_t state); /* may be NULL */
+ int (*set_state_in_io_thread)(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause); /* may be NULL */
/* Sink drivers that support hardware volume may set this
* callback. This is called when the current volume needs to be
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index dd56eb082..e04463c65 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -61,6 +61,11 @@ struct source_message_set_port {
int ret;
};
+struct set_state_data {
+ pa_source_state_t state;
+ pa_suspend_cause_t suspend_cause;
+};
+
static void source_free(pa_object *o);
static void pa_source_volume_change_push(pa_source *s);
@@ -383,19 +388,49 @@ static int source_set_state(pa_source *s, pa_source_state_t state, pa_suspend_ca
* current approach of not setting any suspend cause works well enough. */
if (s->set_state_in_main_thread) {
- ret = s->set_state_in_main_thread(s, state, suspend_cause);
- /* set_state_in_main_thread() is allowed to fail only when resuming. */
- pa_assert(ret >= 0 || resuming);
+ if ((ret = s->set_state_in_main_thread(s, state, suspend_cause)) < 0) {
+ /* set_state_in_main_thread() is allowed to fail only when resuming. */
+ pa_assert(resuming);
+
+ /* If resuming fails, we set the state to SUSPENDED and
+ * suspend_cause to 0. */
+ state = PA_SOURCE_SUSPENDED;
+ suspend_cause = 0;
+ state_changed = false;
+ suspend_cause_changed = suspend_cause != s->suspend_cause;
+ resuming = false;
+
+ /* We know the state isn't changing. If the suspend cause isn't
+ * changing either, then there's nothing more to do. */
+ if (!suspend_cause_changed)
+ return ret;
+ }
}
- if (ret >= 0 && s->asyncmsgq && state_changed)
- if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, PA_UINT_TO_PTR(state), 0, NULL)) < 0) {
+ if (s->asyncmsgq) {
+ struct set_state_data data = { .state = state, .suspend_cause = suspend_cause };
+
+ if ((ret = pa_asyncmsgq_send(s->asyncmsgq, PA_MSGOBJECT(s), PA_SOURCE_MESSAGE_SET_STATE, &data, 0, NULL)) < 0) {
/* SET_STATE is allowed to fail only when resuming. */
pa_assert(resuming);
if (s->set_state_in_main_thread)
s->set_state_in_main_thread(s, PA_SOURCE_SUSPENDED, 0);
+
+ /* If resuming fails, we set the state to SUSPENDED and
+ * suspend_cause to 0. */
+ state = PA_SOURCE_SUSPENDED;
+ suspend_cause = 0;
+ state_changed = false;
+ suspend_cause_changed = suspend_cause != s->suspend_cause;
+ resuming = false;
+
+ /* We know the state isn't changing. If the suspend cause isn't
+ * changing either, then there's nothing more to do. */
+ if (!suspend_cause_changed)
+ return ret;
}
+ }
if (suspend_cause_changed) {
char old_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
@@ -406,9 +441,6 @@ static int source_set_state(pa_source *s, pa_source_state_t state, pa_suspend_ca
s->suspend_cause = suspend_cause;
}
- if (ret < 0)
- goto finish;
-
if (state_changed) {
pa_log_debug("%s: state: %s -> %s", s->name, pa_source_state_to_string(s->state), pa_source_state_to_string(state));
s->state = state;
@@ -435,7 +467,6 @@ static int source_set_state(pa_source *s, pa_source_state_t state, pa_suspend_ca
o->suspend(o, state == PA_SOURCE_SUSPENDED);
}
-finish:
return ret;
}
@@ -2220,19 +2251,19 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
return 0;
case PA_SOURCE_MESSAGE_SET_STATE: {
-
+ struct set_state_data *data = userdata;
bool suspend_change =
- (s->thread_info.state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(PA_PTR_TO_UINT(userdata))) ||
- (PA_SOURCE_IS_OPENED(s->thread_info.state) && PA_PTR_TO_UINT(userdata) == PA_SOURCE_SUSPENDED);
+ (s->thread_info.state == PA_SOURCE_SUSPENDED && PA_SOURCE_IS_OPENED(data->state)) ||
+ (PA_SOURCE_IS_OPENED(s->thread_info.state) && data->state == PA_SOURCE_SUSPENDED);
if (s->set_state_in_io_thread) {
int r;
- if ((r = s->set_state_in_io_thread(s, PA_PTR_TO_UINT(userdata))) < 0)
+ if ((r = s->set_state_in_io_thread(s, data->state, data->suspend_cause)) < 0)
return r;
}
- s->thread_info.state = PA_PTR_TO_UINT(userdata);
+ s->thread_info.state = data->state;
if (suspend_change) {
pa_source_output *o;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index c4fda7965..96327165d 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -149,7 +149,7 @@ struct pa_source {
* are updated only after all the callback calls. In case of failure, the
* state is set to SUSPENDED and the suspend cause is set to 0. */
int (*set_state_in_main_thread)(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause); /* may be NULL */
- int (*set_state_in_io_thread)(pa_source *s, pa_source_state_t state); /* may be NULL */
+ int (*set_state_in_io_thread)(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause); /* may be NULL */
/* Called when the volume is queried. Called from main loop
* context. If this is NULL a PA_SOURCE_MESSAGE_GET_VOLUME message