[pulseaudio-discuss] [PATCH 6/8] pass pa_suspend_cause_t to SINK/SOURCE_SET_STATE handlers

Tanu Kaskinen tanuk at iki.fi
Mon Feb 19 14:48:24 UTC 2018


The suspend cause isn't yet used by any of the handlers. The alsa sink
and source will use it to sync the mixer when the SESSION suspend cause
is removed. Currently the syncing is done in pa_sink/source_suspend(),
and I want to change that, because pa_sink/source_suspend() shouldn't
have any alsa specific code.
---
 src/modules/alsa/alsa-sink.c                 | 11 +++++++++--
 src/modules/alsa/alsa-source.c               | 11 +++++++++--
 src/modules/bluetooth/module-bluez4-device.c | 22 ++++++++++++++++++----
 src/modules/bluetooth/module-bluez5-device.c | 22 ++++++++++++++++++----
 src/modules/echo-cancel/module-echo-cancel.c |  2 +-
 src/modules/module-combine-sink.c            | 10 +++++++++-
 src/modules/module-equalizer-sink.c          |  2 +-
 src/modules/module-esound-sink.c             | 11 +++++++++--
 src/modules/module-ladspa-sink.c             |  2 +-
 src/modules/module-null-sink.c               |  6 ++++--
 src/modules/module-null-source.c             |  2 +-
 src/modules/module-pipe-sink.c               |  9 ++++++---
 src/modules/module-remap-sink.c              |  2 +-
 src/modules/module-sine-source.c             |  2 +-
 src/modules/module-solaris.c                 | 23 ++++++++++++++++++-----
 src/modules/module-tunnel-sink-new.c         | 12 ++++++++++--
 src/modules/module-tunnel-source-new.c       | 12 ++++++++++--
 src/modules/module-virtual-sink.c            |  2 +-
 src/modules/module-virtual-surround-sink.c   |  2 +-
 src/modules/oss/module-oss.c                 | 24 ++++++++++++++++++------
 src/modules/raop/raop-sink.c                 |  9 ++++++++-
 src/pulsecore/sink.c                         | 15 +++++++++------
 src/pulsecore/sink.h                         | 23 +++++++++++++++++++++++
 src/pulsecore/source.c                       | 15 +++++++++------
 src/pulsecore/source.h                       | 23 +++++++++++++++++++++++
 25 files changed, 218 insertions(+), 56 deletions(-)

diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index 5c8ccf319..adc6c0c82 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1185,9 +1185,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             return 0;
         }
 
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
-            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SINK_SUSPENDED: {
                     pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
@@ -1224,6 +1230,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             }
 
             break;
+        }
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c
index fec6c4e0e..61062d230 100644
--- a/src/modules/alsa/alsa-source.c
+++ b/src/modules/alsa/alsa-source.c
@@ -1040,9 +1040,15 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             return 0;
         }
 
-        case PA_SOURCE_MESSAGE_SET_STATE:
+        case PA_SOURCE_MESSAGE_SET_STATE: {
+            pa_source_state_t new_state = ((pa_source_message_set_state *) data)->state;
 
-            switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->source->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SOURCE_SUSPENDED: {
                     pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
@@ -1079,6 +1085,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             }
 
             break;
+        }
     }
 
     return pa_source_process_msg(o, code, data, offset, chunk);
diff --git a/src/modules/bluetooth/module-bluez4-device.c b/src/modules/bluetooth/module-bluez4-device.c
index ff1782264..c458fd26a 100644
--- a/src/modules/bluetooth/module-bluez4-device.c
+++ b/src/modules/bluetooth/module-bluez4-device.c
@@ -388,9 +388,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
     switch (code) {
 
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
-            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SINK_SUSPENDED:
                     /* Ignore if transition is PA_SINK_INIT->PA_SINK_SUSPENDED */
@@ -426,6 +432,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                     ;
             }
             break;
+        }
 
         case PA_SINK_MESSAGE_GET_LATENCY: {
 
@@ -466,9 +473,15 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
     switch (code) {
 
-        case PA_SOURCE_MESSAGE_SET_STATE:
+        case PA_SOURCE_MESSAGE_SET_STATE: {
+            pa_source_state_t new_state = ((pa_source_message_set_state *) data)->state;
 
-            switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->source->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SOURCE_SUSPENDED:
                     /* Ignore if transition is PA_SOURCE_INIT->PA_SOURCE_SUSPENDED */
@@ -505,6 +518,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
                     ;
             }
             break;
+        }
 
         case PA_SOURCE_MESSAGE_GET_LATENCY: {
             int64_t wi, ri;
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index 7970dda70..855cc8f80 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -893,9 +893,15 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
     switch (code) {
 
-        case PA_SOURCE_MESSAGE_SET_STATE:
+        case PA_SOURCE_MESSAGE_SET_STATE: {
+            pa_source_state_t new_state = ((pa_source_message_set_state *) data)->state;
 
-            switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->source->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SOURCE_SUSPENDED:
                     /* Ignore if transition is PA_SOURCE_INIT->PA_SOURCE_SUSPENDED */
@@ -932,6 +938,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             }
 
             break;
+        }
 
         case PA_SOURCE_MESSAGE_GET_LATENCY: {
             int64_t wi, ri;
@@ -1065,9 +1072,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
     switch (code) {
 
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
-            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SINK_SUSPENDED:
                     /* Ignore if transition is PA_SINK_INIT->PA_SINK_SUSPENDED */
@@ -1101,6 +1114,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             }
 
             break;
+        }
 
         case PA_SINK_MESSAGE_GET_LATENCY: {
             int64_t wi, ri;
diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c
index 8e416563f..0863496ae 100644
--- a/src/modules/echo-cancel/module-echo-cancel.c
+++ b/src/modules/echo-cancel/module-echo-cancel.c
@@ -460,7 +460,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
             return 0;
 
         case PA_SINK_MESSAGE_SET_STATE: {
-            pa_sink_state_t new_state = (pa_sink_state_t) PA_PTR_TO_UINT(data);
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
             /* When set to running or idle for the first time, request a rewind
              * of the master sink to make sure we are heard immediately */
diff --git a/src/modules/module-combine-sink.c b/src/modules/module-combine-sink.c
index 7a80028ae..ea4451f95 100644
--- a/src/modules/module-combine-sink.c
+++ b/src/modules/module-combine-sink.c
@@ -860,7 +860,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
     switch (code) {
 
         case PA_SINK_MESSAGE_SET_STATE: {
-            bool running = (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING);
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
+            bool running;
+
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
+            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 bcc8dafe9..4032be157 100644
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -269,7 +269,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
         }
 
         case PA_SINK_MESSAGE_SET_STATE: {
-            pa_sink_state_t new_state = (pa_sink_state_t) PA_PTR_TO_UINT(data);
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
             /* When set to running or idle for the first time, request a rewind
              * of the master sink to make sure we are heard immediately */
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index d93ad9c5b..16c709f11 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -141,9 +141,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
     switch (code) {
 
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
-            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SINK_SUSPENDED:
                     pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
@@ -166,6 +172,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             }
 
             break;
+        }
 
         case PA_SINK_MESSAGE_GET_LATENCY: {
             pa_usec_t w, r;
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index 4d5cd68f3..66dba02fb 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -376,7 +376,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
         return 0;
 
         case PA_SINK_MESSAGE_SET_STATE: {
-            pa_sink_state_t new_state = (pa_sink_state_t) PA_PTR_TO_UINT(data);
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
             /* When set to running or idle for the first time, request a rewind
              * of the master sink to make sure we are heard immediately */
diff --git a/src/modules/module-null-sink.c b/src/modules/module-null-sink.c
index c29722fad..63bf0325a 100644
--- a/src/modules/module-null-sink.c
+++ b/src/modules/module-null-sink.c
@@ -89,14 +89,16 @@ static int sink_process_msg(
     struct userdata *u = PA_SINK(o)->userdata;
 
     switch (code) {
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
             if (u->sink->thread_info.state == PA_SINK_SUSPENDED || u->sink->thread_info.state == PA_SINK_INIT) {
-                if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING || PA_PTR_TO_UINT(data) == PA_SINK_IDLE)
+                if (new_state == PA_SINK_RUNNING || new_state == PA_SINK_IDLE)
                     u->timestamp = pa_rtclock_now();
             }
 
             break;
+        }
 
         case PA_SINK_MESSAGE_GET_LATENCY: {
             pa_usec_t now;
diff --git a/src/modules/module-null-source.c b/src/modules/module-null-source.c
index 41f17bd98..cb0df6cc6 100644
--- a/src/modules/module-null-source.c
+++ b/src/modules/module-null-source.c
@@ -91,7 +91,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
     switch (code) {
         case PA_SOURCE_MESSAGE_SET_STATE:
 
-            if (PA_PTR_TO_UINT(data) == PA_SOURCE_RUNNING)
+            if (((pa_source_message_set_state *) data)->state == PA_SOURCE_RUNNING)
                 u->timestamp = pa_rtclock_now();
 
             break;
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index fc909af15..fccef6dd2 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -110,12 +110,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
     struct userdata *u = PA_SINK(o)->userdata;
 
     switch (code) {
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
+
             if (u->sink->thread_info.state == PA_SINK_SUSPENDED || u->sink->thread_info.state == PA_SINK_INIT) {
-                if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING || PA_PTR_TO_UINT(data) == PA_SINK_IDLE)
+                if (new_state == PA_SINK_RUNNING || new_state == PA_SINK_IDLE)
                     u->timestamp = pa_rtclock_now();
             } else if (u->sink->thread_info.state == PA_SINK_RUNNING || u->sink->thread_info.state == PA_SINK_IDLE) {
-                if (PA_PTR_TO_UINT(data) == PA_SINK_SUSPENDED) {
+                if (new_state == PA_SINK_SUSPENDED) {
                     /* Clear potential FIFO error flag */
                     u->fifo_error = false;
 
@@ -127,6 +129,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
                 }
             }
             break;
+        }
 
         case PA_SINK_MESSAGE_GET_LATENCY:
             if (u->use_system_clock_for_timing) {
diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c
index f063576f2..58084ea0d 100644
--- a/src/modules/module-remap-sink.c
+++ b/src/modules/module-remap-sink.c
@@ -96,7 +96,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             return 0;
 
         case PA_SINK_MESSAGE_SET_STATE: {
-            pa_sink_state_t new_state = (pa_sink_state_t) PA_PTR_TO_UINT(data);
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
             /* When set to running or idle for the first time, request a rewind
              * of the master sink to make sure we are heard immediately */
diff --git a/src/modules/module-sine-source.c b/src/modules/module-sine-source.c
index f4c297384..e2b650295 100644
--- a/src/modules/module-sine-source.c
+++ b/src/modules/module-sine-source.c
@@ -89,7 +89,7 @@ static int source_process_msg(
 
         case PA_SOURCE_MESSAGE_SET_STATE:
 
-            if (PA_PTR_TO_UINT(data) == PA_SOURCE_RUNNING)
+            if (((pa_source_message_set_state *) data)->state == PA_SOURCE_RUNNING)
                 u->timestamp = pa_rtclock_now();
 
             break;
diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c
index a4960b8b7..302bbcded 100644
--- a/src/modules/module-solaris.c
+++ b/src/modules/module-solaris.c
@@ -391,9 +391,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             *((int64_t*) data) = sink_get_latency(u, &PA_SINK(o)->sample_spec);
             return 0;
 
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
-            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SINK_SUSPENDED:
 
@@ -432,6 +438,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             }
 
             break;
+        }
     }
 
     return pa_sink_process_msg(o, code, data, offset, chunk);
@@ -446,9 +453,15 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             *((pa_usec_t*) data) = source_get_latency(u, &PA_SOURCE(o)->sample_spec);
             return 0;
 
-        case PA_SOURCE_MESSAGE_SET_STATE:
+        case PA_SOURCE_MESSAGE_SET_STATE: {
+            pa_source_state_t new_state = ((pa_source_message_set_state *) data)->state;
+
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->source->thread_info.state)
+                break;
 
-            switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
+            switch (new_state) {
 
                 case PA_SOURCE_SUSPENDED:
 
@@ -480,7 +493,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
             }
             break;
-
+        }
     }
 
     return pa_source_process_msg(o, code, data, offset, chunk);
diff --git a/src/modules/module-tunnel-sink-new.c b/src/modules/module-tunnel-sink-new.c
index 8a67b81f1..df7b1ada7 100644
--- a/src/modules/module-tunnel-sink-new.c
+++ b/src/modules/module-tunnel-sink-new.c
@@ -429,11 +429,18 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
             *((int64_t*) data) = remote_latency;
             return 0;
         }
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
+
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
             if (!u->stream || pa_stream_get_state(u->stream) != PA_STREAM_READY)
                 break;
 
-            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+            switch (new_state) {
                 case PA_SINK_SUSPENDED: {
                     cork_stream(u, true);
                     break;
@@ -449,6 +456,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
                     break;
             }
             break;
+        }
     }
     return pa_sink_process_msg(o, code, data, offset, chunk);
 }
diff --git a/src/modules/module-tunnel-source-new.c b/src/modules/module-tunnel-source-new.c
index 7ad077111..6ed7128ff 100644
--- a/src/modules/module-tunnel-source-new.c
+++ b/src/modules/module-tunnel-source-new.c
@@ -428,11 +428,18 @@ static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t
 
             return 0;
         }
-        case PA_SOURCE_MESSAGE_SET_STATE:
+        case PA_SOURCE_MESSAGE_SET_STATE: {
+            pa_source_state_t new_state = ((pa_source_message_set_state *) data)->state;
+
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->source->thread_info.state)
+                break;
+
             if (!u->stream || pa_stream_get_state(u->stream) != PA_STREAM_READY)
                 break;
 
-            switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
+            switch (new_state) {
                 case PA_SOURCE_SUSPENDED: {
                     cork_stream(u, true);
                     break;
@@ -448,6 +455,7 @@ static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t
                     break;
             }
             break;
+        }
     }
     return pa_source_process_msg(o, code, data, offset, chunk);
 }
diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-sink.c
index 5fa4ce4d3..aa72d0c07 100644
--- a/src/modules/module-virtual-sink.c
+++ b/src/modules/module-virtual-sink.c
@@ -108,7 +108,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
             return 0;
 
         case PA_SINK_MESSAGE_SET_STATE: {
-            pa_sink_state_t new_state = (pa_sink_state_t) PA_PTR_TO_UINT(data);
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
             /* When set to running or idle for the first time, request a rewind
              * of the master sink to make sure we are heard immediately */
diff --git a/src/modules/module-virtual-surround-sink.c b/src/modules/module-virtual-surround-sink.c
index 876d618e1..4ffe3ab2b 100644
--- a/src/modules/module-virtual-surround-sink.c
+++ b/src/modules/module-virtual-surround-sink.c
@@ -136,7 +136,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of
             return 0;
 
         case PA_SINK_MESSAGE_SET_STATE: {
-            pa_sink_state_t new_state = (pa_sink_state_t) PA_PTR_TO_UINT(data);
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
             /* When set to running or idle for the first time, request a rewind
              * of the master sink to make sure we are heard immediately */
diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c
index fb978b5ee..0e39f52a7 100644
--- a/src/modules/oss/module-oss.c
+++ b/src/modules/oss/module-oss.c
@@ -661,9 +661,15 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             return 0;
         }
 
-        case PA_SINK_MESSAGE_SET_STATE:
+        case PA_SINK_MESSAGE_SET_STATE: {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
 
-            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
+            switch (new_state) {
 
                 case PA_SINK_SUSPENDED:
                     pa_assert(PA_SINK_IS_OPENED(u->sink->thread_info.state));
@@ -709,7 +715,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
             }
 
             break;
-
+        }
     }
 
     ret = pa_sink_process_msg(o, code, data, offset, chunk);
@@ -743,9 +749,15 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
             return 0;
         }
 
-        case PA_SOURCE_MESSAGE_SET_STATE:
+        case PA_SOURCE_MESSAGE_SET_STATE: {
+            pa_source_state_t new_state = ((pa_source_message_set_state *) data)->state;
 
-            switch ((pa_source_state_t) PA_PTR_TO_UINT(data)) {
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->source->thread_info.state)
+                break;
+
+            switch (new_state) {
                 case PA_SOURCE_SUSPENDED:
                     pa_assert(PA_SOURCE_IS_OPENED(u->source->thread_info.state));
 
@@ -789,7 +801,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off
 
             }
             break;
-
+        }
     }
 
     ret = pa_source_process_msg(o, code, data, offset, chunk);
diff --git a/src/modules/raop/raop-sink.c b/src/modules/raop/raop-sink.c
index 936129cf5..ba990347b 100644
--- a/src/modules/raop/raop-sink.c
+++ b/src/modules/raop/raop-sink.c
@@ -137,7 +137,14 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse
 
     switch (code) {
         case PA_SINK_MESSAGE_SET_STATE: {
-            switch ((pa_sink_state_t) PA_PTR_TO_UINT(data)) {
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) data)->state;
+
+            /* It may be that only the suspend cause is changing, in which
+             * case there's nothing to do. */
+            if (new_state == u->sink->thread_info.state)
+                break;
+
+            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 0dfc91c87..a9c2b3a8e 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -433,14 +433,17 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t
         pa_assert(ret >= 0 || resuming);
     }
 
-    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 (ret >= 0 && s->asyncmsgq) {
+        pa_sink_message_set_state 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)
                 s->set_state(s, PA_SINK_SUSPENDED, 0);
         }
+    }
 
     if (suspend_cause_changed) {
         char old_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
@@ -2845,12 +2848,12 @@ int pa_sink_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offse
             return 0;
 
         case PA_SINK_MESSAGE_SET_STATE: {
-
+            pa_sink_state_t new_state = ((pa_sink_message_set_state *) userdata)->state;
             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(new_state)) ||
+                (PA_SINK_IS_OPENED(s->thread_info.state) && new_state == PA_SINK_SUSPENDED);
 
-            s->thread_info.state = PA_PTR_TO_UINT(userdata);
+            s->thread_info.state = new_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 b7e21f9f0..1f0f981c3 100644
--- a/src/pulsecore/sink.h
+++ b/src/pulsecore/sink.h
@@ -332,7 +332,24 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_SET_MUTE,
     PA_SINK_MESSAGE_GET_LATENCY,
     PA_SINK_MESSAGE_GET_REQUESTED_LATENCY,
+
+    /* Sent when changing the sink state or suspend cause.
+     *
+     * pa_sink.state and pa_sink.suspend_cause haven't been updated yet when
+     * sending the message. The new state and suspend cause are available in
+     * the message userdata, which is a pa_sink_message_set_state struct.
+     *
+     * Prior to sending the message, the set_state() callback is called from
+     * the main thread, and if set_state() fails, then this message is not
+     * sent. The message handler is allowed to fail when changing the state
+     * from INIT or SUSPENDED to IDLE or RUNNING. If the message handler
+     * signals failure, the state change is reverted.
+     *
+     * If the message handler doesn't indicate failure, pa_sink_process_msg()
+     * has to be called to complete the state change in the IO thread. In case
+     * of failure, however, pa_sink_process_msg() must not be called. */
     PA_SINK_MESSAGE_SET_STATE,
+
     PA_SINK_MESSAGE_START_MOVE,
     PA_SINK_MESSAGE_FINISH_MOVE,
     PA_SINK_MESSAGE_SET_LATENCY_RANGE,
@@ -349,6 +366,12 @@ typedef enum pa_sink_message {
     PA_SINK_MESSAGE_MAX
 } pa_sink_message_t;
 
+/* Used as userdata for the SET_STATE message. */
+typedef struct pa_sink_message_set_state {
+    pa_sink_state_t state; /* The new state. */
+    pa_suspend_cause_t suspend_cause; /* The new suspend cause. */
+} pa_sink_message_set_state;
+
 typedef struct pa_sink_new_data {
     pa_suspend_cause_t suspend_cause;
 
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 7ea75ff05..88e8632c0 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -387,14 +387,17 @@ static int source_set_state(pa_source *s, pa_source_state_t state, pa_suspend_ca
         pa_assert(ret >= 0 || resuming);
     }
 
-    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 (ret >= 0 && s->asyncmsgq) {
+        pa_source_message_set_state 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)
                 s->set_state(s, PA_SOURCE_SUSPENDED, 0);
         }
+    }
 
     if (suspend_cause_changed) {
         char old_cause_buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE];
@@ -2219,12 +2222,12 @@ int pa_source_process_msg(pa_msgobject *object, int code, void *userdata, int64_
             return 0;
 
         case PA_SOURCE_MESSAGE_SET_STATE: {
-
+            pa_source_state_t new_state = ((pa_source_message_set_state *) userdata)->state;
             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(new_state)) ||
+                (PA_SOURCE_IS_OPENED(s->thread_info.state) && new_state == PA_SOURCE_SUSPENDED);
 
-            s->thread_info.state = PA_PTR_TO_UINT(userdata);
+            s->thread_info.state = new_state;
 
             if (suspend_change) {
                 pa_source_output *o;
diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h
index ea3147255..035aa185e 100644
--- a/src/pulsecore/source.h
+++ b/src/pulsecore/source.h
@@ -274,7 +274,24 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_SET_MUTE,
     PA_SOURCE_MESSAGE_GET_LATENCY,
     PA_SOURCE_MESSAGE_GET_REQUESTED_LATENCY,
+
+    /* Sent when changing the source state or suspend cause.
+     *
+     * pa_source.state and pa_source.suspend_cause haven't been updated yet when
+     * sending the message. The new state and suspend cause are available in
+     * the message userdata, which is a pa_source_message_set_state struct.
+     *
+     * Prior to sending the message, the set_state() callback is called from
+     * the main thread, and if set_state() fails, then this message is not
+     * sent. The message handler is allowed to fail when changing the state
+     * from INIT or SUSPENDED to IDLE or RUNNING. If the message handler
+     * signals failure, the state change is reverted.
+     *
+     * If the message handler doesn't indicate failure, pa_source_process_msg()
+     * has to be called to complete the state change in the IO thread. In case
+     * of failure, however, pa_source_process_msg() must not be called. */
     PA_SOURCE_MESSAGE_SET_STATE,
+
     PA_SOURCE_MESSAGE_SET_LATENCY_RANGE,
     PA_SOURCE_MESSAGE_GET_LATENCY_RANGE,
     PA_SOURCE_MESSAGE_SET_FIXED_LATENCY,
@@ -287,6 +304,12 @@ typedef enum pa_source_message {
     PA_SOURCE_MESSAGE_MAX
 } pa_source_message_t;
 
+/* Used as userdata for the SET_STATE message. */
+typedef struct pa_source_message_set_state {
+    pa_source_state_t state; /* The new state. */
+    pa_suspend_cause_t suspend_cause; /* The new suspend cause. */
+} pa_source_message_set_state;
+
 typedef struct pa_source_new_data {
     pa_suspend_cause_t suspend_cause;
 
-- 
2.15.1



More information about the pulseaudio-discuss mailing list