diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c index 8786c98b7..5e8172893 100644 --- a/src/modules/alsa/alsa-sink.c +++ b/src/modules/alsa/alsa-sink.c @@ -1232,7 +1232,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse } /* Called from main context */ -static int sink_set_state_cb(pa_sink *s, pa_sink_state_t new_state) { +static int sink_set_state_cb(pa_sink *s, pa_sink_state_t new_state, pa_suspend_cause_t new_suspend_cause) { pa_sink_state_t old_state; struct userdata *u; diff --git a/src/modules/alsa/alsa-source.c b/src/modules/alsa/alsa-source.c index ba369284c..79d3364a6 100644 --- a/src/modules/alsa/alsa-source.c +++ b/src/modules/alsa/alsa-source.c @@ -1087,7 +1087,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off } /* Called from main context */ -static int source_set_state_cb(pa_source *s, pa_source_state_t new_state) { +static int source_set_state_cb(pa_source *s, pa_source_state_t new_state, pa_suspend_cause_t new_suspend_cause) { pa_source_state_t old_state; struct userdata *u; diff --git a/src/modules/echo-cancel/module-echo-cancel.c b/src/modules/echo-cancel/module-echo-cancel.c index 0702f2fd6..8e416563f 100644 --- a/src/modules/echo-cancel/module-echo-cancel.c +++ b/src/modules/echo-cancel/module-echo-cancel.c @@ -477,7 +477,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of } /* Called from main context */ -static int source_set_state_cb(pa_source *s, pa_source_state_t state) { +static int source_set_state_cb(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_source_assert_ref(s); @@ -502,7 +502,7 @@ static int source_set_state_cb(pa_source *s, pa_source_state_t state) { } /* Called from main context */ -static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) { +static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(s); diff --git a/src/modules/macosx/module-coreaudio-device.c b/src/modules/macosx/module-coreaudio-device.c index 73e332a31..f9ef7c5a0 100644 --- a/src/modules/macosx/module-coreaudio-device.c +++ b/src/modules/macosx/module-coreaudio-device.c @@ -353,7 +353,7 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off return pa_source_process_msg(o, code, data, offset, chunk);; } -static int ca_sink_set_state(pa_sink *s, pa_sink_state_t state) { +static int ca_sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { coreaudio_sink *sink = s->userdata; switch (state) { @@ -511,7 +511,7 @@ static int ca_device_create_sink(pa_module *m, AudioBuffer *buf, int channel_idx return 0; } -static int ca_source_set_state(pa_source *s, pa_source_state_t state) { +static int ca_source_set_state(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause) { coreaudio_source *source = s->userdata; switch (state) { diff --git a/src/modules/module-combine-sink.c b/src/modules/module-combine-sink.c index baaac44d5..7a80028ae 100644 --- a/src/modules/module-combine-sink.c +++ b/src/modules/module-combine-sink.c @@ -680,12 +680,17 @@ static void unsuspend(struct userdata *u) { } /* Called from main context */ -static int sink_set_state(pa_sink *sink, pa_sink_state_t state) { +static int sink_set_state(pa_sink *sink, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(sink); pa_assert_se(u = sink->userdata); + /* It may be that only the suspend cause is changing, in which + * case there's nothing to do. */ + if (state == u->sink->state) + return 0; + /* Please note that in contrast to the ALSA modules we call * suspend/unsuspend from main context here! */ diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c index d35511530..bcc8dafe9 100644 --- a/src/modules/module-equalizer-sink.c +++ b/src/modules/module-equalizer-sink.c @@ -285,7 +285,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of } /* Called from main context */ -static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) { +static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(s); diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c index 323a989a9..4d5cd68f3 100644 --- a/src/modules/module-ladspa-sink.c +++ b/src/modules/module-ladspa-sink.c @@ -392,7 +392,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of } /* Called from main context */ -static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) { +static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(s); diff --git a/src/modules/module-remap-sink.c b/src/modules/module-remap-sink.c index 1599e160f..f063576f2 100644 --- a/src/modules/module-remap-sink.c +++ b/src/modules/module-remap-sink.c @@ -112,7 +112,7 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse } /* Called from main context */ -static int sink_set_state(pa_sink *s, pa_sink_state_t state) { +static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(s); diff --git a/src/modules/module-remap-source.c b/src/modules/module-remap-source.c index 109c913ca..88eccc221 100644 --- a/src/modules/module-remap-source.c +++ b/src/modules/module-remap-source.c @@ -108,7 +108,7 @@ static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t } /* Called from main context */ -static int source_set_state_cb(pa_source *s, pa_source_state_t state) { +static int source_set_state_cb(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_source_assert_ref(s); diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c index e54a8242f..1db79ef60 100644 --- a/src/modules/module-tunnel.c +++ b/src/modules/module-tunnel.c @@ -568,11 +568,16 @@ static int sink_process_msg(pa_msgobject *o, int code, void *data, int64_t offse } /* Called from main context */ -static int sink_set_state(pa_sink *s, pa_sink_state_t state) { +static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(s); u = s->userdata; + /* It may be that only the suspend cause is changing, in which + * case there's nothing to do. */ + if (state == s->state) + return 0; + switch ((pa_sink_state_t) state) { case PA_SINK_SUSPENDED: @@ -665,11 +670,16 @@ static int source_process_msg(pa_msgobject *o, int code, void *data, int64_t off } /* Called from main context */ -static int source_set_state(pa_source *s, pa_source_state_t state) { +static int source_set_state(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_source_assert_ref(s); u = s->userdata; + /* It may be that only the suspend cause is changing, in which + * case there's nothing to do. */ + if (state == s->state) + return 0; + switch ((pa_source_state_t) state) { case PA_SOURCE_SUSPENDED: diff --git a/src/modules/module-virtual-sink.c b/src/modules/module-virtual-sink.c index d477fb21d..5fa4ce4d3 100644 --- a/src/modules/module-virtual-sink.c +++ b/src/modules/module-virtual-sink.c @@ -124,7 +124,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of } /* Called from main context */ -static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) { +static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(s); diff --git a/src/modules/module-virtual-source.c b/src/modules/module-virtual-source.c index df0f4cb38..c002ae843 100644 --- a/src/modules/module-virtual-source.c +++ b/src/modules/module-virtual-source.c @@ -111,7 +111,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of } /* Called from main context */ -static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) { +static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(s); @@ -194,7 +194,7 @@ static int source_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t } /* Called from main context */ -static int source_set_state_cb(pa_source *s, pa_source_state_t state) { +static int source_set_state_cb(pa_source *s, pa_source_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_source_assert_ref(s); diff --git a/src/modules/module-virtual-surround-sink.c b/src/modules/module-virtual-surround-sink.c index 143b5caca..876d618e1 100644 --- a/src/modules/module-virtual-surround-sink.c +++ b/src/modules/module-virtual-surround-sink.c @@ -152,7 +152,7 @@ static int sink_process_msg_cb(pa_msgobject *o, int code, void *data, int64_t of } /* Called from main context */ -static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state) { +static int sink_set_state_cb(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t suspend_cause) { struct userdata *u; pa_sink_assert_ref(s); diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c index 50e17c176..0dfc91c87 100644 --- a/src/pulsecore/sink.c +++ b/src/pulsecore/sink.c @@ -427,8 +427,8 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t * cause, or it might just add unnecessary complexity, given that the * current approach of not setting any suspend cause works well enough. */ - if (s->set_state && state_changed) { - ret = s->set_state(s, state); + if (s->set_state) { + ret = s->set_state(s, state, suspend_cause); /* set_state() is allowed to fail only when resuming. */ pa_assert(ret >= 0 || resuming); } @@ -439,7 +439,7 @@ static int sink_set_state(pa_sink *s, pa_sink_state_t state, pa_suspend_cause_t pa_assert(resuming); if (s->set_state) - s->set_state(s, PA_SINK_SUSPENDED); + s->set_state(s, PA_SINK_SUSPENDED, 0); } if (suspend_cause_changed) { diff --git a/src/pulsecore/sink.h b/src/pulsecore/sink.h index 3fb230123..b7e21f9f0 100644 --- a/src/pulsecore/sink.h +++ b/src/pulsecore/sink.h @@ -126,8 +126,16 @@ struct pa_sink { /* Called when the main loop requests a state change. Called from * main loop context. If returns -1 the state change will be - * inhibited */ - int (*set_state)(pa_sink *s, pa_sink_state_t state); /* may be NULL */ + * inhibited. This will also be called even if only the suspend cause + * changes. + * + * s->state and s->suspend_cause haven't been updated yet when this is + * called, so the callback can get the old state through those variables. + * + * If set_state() is successful, the IO thread will be notified with the + * SET_STATE message. The message handler is allowed to fail, in which + * case the old state is restored, and set_state() is called again. */ + int (*set_state)(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 c46dc2b17..7ea75ff05 100644 --- a/src/pulsecore/source.c +++ b/src/pulsecore/source.c @@ -381,8 +381,8 @@ static int source_set_state(pa_source *s, pa_source_state_t state, pa_suspend_ca * cause, or it might just add unnecessary complexity, given that the * current approach of not setting any suspend cause works well enough. */ - if (s->set_state && state_changed) { - ret = s->set_state(s, state); + if (s->set_state) { + ret = s->set_state(s, state, suspend_cause); /* set_state() is allowed to fail only when resuming. */ pa_assert(ret >= 0 || resuming); } @@ -393,7 +393,7 @@ static int source_set_state(pa_source *s, pa_source_state_t state, pa_suspend_ca pa_assert(resuming); if (s->set_state) - s->set_state(s, PA_SOURCE_SUSPENDED); + s->set_state(s, PA_SOURCE_SUSPENDED, 0); } if (suspend_cause_changed) { diff --git a/src/pulsecore/source.h b/src/pulsecore/source.h index 75ce241f1..ea3147255 100644 --- a/src/pulsecore/source.h +++ b/src/pulsecore/source.h @@ -127,8 +127,16 @@ struct pa_source { /* Called when the main loop requests a state change. Called from * main loop context. If returns -1 the state change will be - * inhibited */ - int (*set_state)(pa_source*source, pa_source_state_t state); /* may be NULL */ + * inhibited. This will also be called even if only the suspend cause + * changes. + * + * s->state and s->suspend_cause haven't been updated yet when this is + * called, so the callback can get the old state through those variables. + * + * If set_state() is successful, the IO thread will be notified with the + * SET_STATE message. The message handler is allowed to fail, in which + * case the old state is restored, and set_state() is called again. */ + int (*set_state)(pa_source *source, 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