From c8f820ce7770d36aeb94c8f8cbd4b9afeb761f01 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 14 Apr 2025 10:45:16 +0100 Subject: [PATCH] Fix accessing state within sink_process_msg() Later versions of pulseaudio pass the state in for a PA_SINK_MESSAGE_SET_STATE in a different way from earlier versions. --- src/module-xrdp-sink.c | 82 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 7 deletions(-) diff --git a/src/module-xrdp-sink.c b/src/module-xrdp-sink.c index 44c9a0b..98c648f 100644 --- a/src/module-xrdp-sink.c +++ b/src/module-xrdp-sink.c @@ -98,6 +98,25 @@ PA_MODULE_USAGE( #undef USE_SET_STATE_IN_IO_THREAD_CB #endif +/* + * ** THIS IS A HACK ** + * + * we need to access (struct set_state_data *)->state + * from our code, but the struct is currently private to pulsecore/sink.c + * The struct was introduced for 11.99.1, and hasn't changed since. Given + * the late development status of pulseaudio now (April '25), this is + * unlikely to change again */ + +#if defined(PA_CHECK_VERSION) && PA_CHECK_VERSION(11, 99, 1) +struct set_state_data { /* Copied from pulsecore/sink.c */ + pa_sink_state_t state; + pa_suspend_cause_t suspend_cause; +}; +#define GET_STATE_FROM_SET_STATE_DATA +#else +#undef GET_STATE_FROM_SET_STATE_DATA +#endif + struct userdata { pa_core *core; pa_module *module; @@ -204,12 +223,42 @@ static pa_card *xrdp_create_card(pa_module *m, pa_device_port *port, pa_card_pro return card; } +#if !defined(PA_CHECK_VERSION) || !PA_CHECK_VERSION(11, 99, 1) +/** + * Returns a string representation of the sink state + * + * Later versions of PA provide this function in pulsecore/sink.h + * + * @param state Sink state + * @return string representation of state + */ +static const char * +pa_sink_state_to_string(pa_sink_state_t state) +{ + switch (state) + { + case PA_SINK_INIT: + return "INIT"; + case PA_SINK_RUNNING: + return "RUNNING"; + case PA_SINK_SUSPENDED: + return "SUSPENDED"; + case PA_SINK_IDLE: + return "IDLE"; + case PA_SINK_UNLINKED: + return "UNLINKED"; + } + pa_assert_not_reached(); +} +#endif + static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offset, pa_memchunk *chunk) { struct userdata *u = PA_SINK(o)->userdata; pa_usec_t now; long lat; + pa_sink_state_t sink_state; switch (code) { @@ -234,14 +283,33 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, break; case PA_SINK_MESSAGE_SET_STATE: - pa_log_debug("sink_process_msg: PA_SINK_MESSAGE_SET_STATE"); - if (PA_PTR_TO_UINT(data) == PA_SINK_RUNNING) /* 0 */ { - pa_log("sink_process_msg: running"); +#ifdef GET_STATE_FROM_SET_STATE_DATA + sink_state = ((const struct set_state_data *)data)->state; +#else + sink_state = PA_PTR_TO_UINT(data); +#endif + pa_log("sink_process_msg: PA_SINK_MESSAGE_SET_STATE [%s]", + pa_sink_state_to_string(sink_state)); + switch (sink_state) + { + case PA_SINK_INVALID_STATE: + case PA_SINK_INIT: + break; - u->timestamp = pa_rtclock_now(); - } else { - pa_log("sink_process_msg: not running"); - close_send(u); + case PA_SINK_RUNNING: + pa_log("sink_process_msg: running"); + u->timestamp = pa_rtclock_now(); + break; + + case PA_SINK_IDLE: + case PA_SINK_SUSPENDED: + case PA_SINK_UNLINKED: + pa_log("sink_process_msg: not running"); + close_send(u); + break; + + default: + pa_assert_not_reached(); } break;