--- src/pulse/context.c | 53 +++++++++++++++++++++++++++++++++++++------------ src/pulse/internal.h | 4 ++- 2 files changed, 43 insertions(+), 14 deletions(-) diff --git a/src/pulse/context.c b/src/pulse/context.c index 1480af5..317377d 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -431,27 +431,29 @@ static void setup_complete_callback(pa_pdispatch *pd, uint32_t command, uint32_t pa_tagstruct *reply; pa_bool_t shm_on_remote = FALSE; - if (pa_tagstruct_getu32(t, &c->version) < 0 || + if (pa_tagstruct_getu32(t, &c->server_protocol_version) < 0 || !pa_tagstruct_eof(t)) { pa_context_fail(c, PA_ERR_PROTOCOL); goto finish; } + /* Starting with protocol version 13 the MSB of the version + tag reflects if shm is available for this connection or + not. */ + if (c->server_protocol_version >= 13) { + shm_on_remote = !!(c->server_protocol_version & 0x80000000U); + c->server_protocol_version &= 0x7FFFFFFFU; + } + + c->version = PA_MIN(c->server_protocol_version, c->protocol_version_limit); + /* Minimum supported version */ if (c->version < 8) { pa_context_fail(c, PA_ERR_VERSION); goto finish; } - /* Starting with protocol version 13 the MSB of the version - tag reflects if shm is available for this connection or - not. */ - if (c->version >= 13) { - shm_on_remote = !!(c->version & 0x80000000U); - c->version &= 0x7FFFFFFFU; - } - - pa_log_debug("Protocol version: remote %u, local %u", c->version, PA_PROTOCOL_VERSION); + pa_log_debug("Protocol version: remote %u, local %u, effective %u", c->server_protocol_version, PA_PROTOCOL_VERSION, c->version); /* Enable shared memory support if possible */ if (c->do_shm) @@ -512,6 +514,7 @@ finish: static void setup_context(pa_context *c, pa_iochannel *io) { pa_tagstruct *t; uint32_t tag; + char *d; pa_assert(c); pa_assert(io); @@ -539,9 +542,33 @@ static void setup_context(pa_context *c, pa_iochannel *io) { pa_log_debug("SHM possible: %s", pa_yes_no(c->do_shm)); + c->protocol_version_limit = PA_PROTOCOL_VERSION; + + /* If PULSE_PROTOCOL_VERSION_LIMIT is set, then we lie to the + * server about the protocol version that we support. + * + * This environment variable exists just to work around the + * protocol incompatibility in the N900 version of Pulseaudio: + * it says that it supports v16, but it's not the official v16. + * V15 works fine on the N900, so setting this environment + * variable to "15" on a remote client will avoid triggering the + * incompatibility. */ + if ((d = getenv("PULSE_PROTOCOL_VERSION_LIMIT")) && *d) { + if (pa_atou(d, &c->protocol_version_limit) >= 0) { + if ((c->protocol_version_limit >= 8) && (c->protocol_version_limit <= PA_PROTOCOL_VERSION)) + pa_log_debug("Limiting the protocol version to %u.", c->protocol_version_limit); + else { + pa_log_warn("Environment variable PULSE_PROTOCOL_VERSION_LIMIT is set to %u, which is outside the supported " + "range of 8-%u. Ignoring the variable.", c->protocol_version_limit, PA_PROTOCOL_VERSION); + c->protocol_version_limit = PA_PROTOCOL_VERSION; + } + } else + pa_log_warn("Failed to parse environment variable PULSE_PROTOCOL_VERSION_LIMIT."); + } + /* Starting with protocol version 13 we use the MSB of the version * tag for informing the other side if we could do SHM or not */ - pa_tagstruct_putu32(t, PA_PROTOCOL_VERSION | (c->do_shm ? 0x80000000U : 0)); + pa_tagstruct_putu32(t, c->protocol_version_limit | (c->do_shm ? 0x80000000U : 0)); pa_tagstruct_put_arbitrary(t, c->conf->cookie, sizeof(c->conf->cookie)); #ifdef HAVE_CREDS @@ -1304,7 +1331,7 @@ const char* pa_context_get_server(pa_context *c) { } uint32_t pa_context_get_protocol_version(pa_context *c) { - return PA_PROTOCOL_VERSION; + return c->protocol_version_limit; } uint32_t pa_context_get_server_protocol_version(pa_context *c) { @@ -1314,7 +1341,7 @@ uint32_t pa_context_get_server_protocol_version(pa_context *c) { PA_CHECK_VALIDITY_RETURN_ANY(c, !pa_detect_fork(), PA_ERR_FORKED, PA_INVALID_INDEX); PA_CHECK_VALIDITY_RETURN_ANY(c, PA_CONTEXT_IS_GOOD(c->state), PA_ERR_BADSTATE, PA_INVALID_INDEX); - return c->version; + return c->server_protocol_version; } pa_tagstruct *pa_tagstruct_command(pa_context *c, uint32_t command, uint32_t *tag) { diff --git a/src/pulse/internal.h b/src/pulse/internal.h index 40f6804..5d5d431 100644 --- a/src/pulse/internal.h +++ b/src/pulse/internal.h @@ -69,7 +69,9 @@ struct pa_context { PA_LLIST_HEAD(pa_stream, streams); PA_LLIST_HEAD(pa_operation, operations); - uint32_t version; + uint32_t version; /* min(server_protocol_version, protocol_version_limit) */ + uint32_t server_protocol_version; + uint32_t protocol_version_limit; uint32_t ctag; uint32_t csyncid; int error; -- 1.7.5.3