This increments protocol version to v30 and adds two new commands to enable and disable an shm ringbuffer, as well as client side implementation. Signed-off-by: David Henningsson <david.henningsson at canonical.com> --- PROTOCOL | 15 +++++++++++ configure.ac | 2 +- src/pulse/context.c | 58 ++++++++++++++++++++++++++++++++++++++++++- src/pulsecore/native-common.h | 4 +++ 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/PROTOCOL b/PROTOCOL index 850b953..9aeeecb 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -351,6 +351,21 @@ New field in all commands that send/receive profile introspection data The field is added once for every profile. +## v30, implemented by >= 6.0 +# +A new protocol mechanism supported: Two ringbuffers in shared memory. +Pulseaudio fdsem (wrappers around event file descriptors) are used for +signalling new data. +The protocol has a new SHM flag telling whether a SHM memblock is writable +by both sides. + +PA_COMMAND_ENABLE_RINGBUFFER +Tells the client to start listening on the additional SHM ringbuffer channel. +This command also has ancillary data (two eventfds attached to it). + +PA_COMMAND_DISABLE_RINGBUFFER +Tells the client to stop listening on the additional SHM ringbuffer channel. + #### If you just changed the protocol, read this ## module-tunnel depends on the sink/source/sink-input/source-input protocol ## internals, so if you changed these, you might have broken module-tunnel. diff --git a/configure.ac b/configure.ac index e75973f..b7aeef9 100644 --- a/configure.ac +++ b/configure.ac @@ -41,7 +41,7 @@ AC_SUBST(PA_MINOR, pa_minor) AC_SUBST(PA_MAJORMINOR, pa_major.pa_minor) AC_SUBST(PA_API_VERSION, 12) -AC_SUBST(PA_PROTOCOL_VERSION, 29) +AC_SUBST(PA_PROTOCOL_VERSION, 30) # The stable ABI for client applications, for the version info x:y:z # always will hold y=z diff --git a/src/pulse/context.c b/src/pulse/context.c index 7456ee5..5cde5be 100644 --- a/src/pulse/context.c +++ b/src/pulse/context.c @@ -72,6 +72,8 @@ #include "context.h" void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void pa_command_enable_ringbuffer(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); +static void pa_command_disable_ringbuffer(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata); static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_REQUEST] = pa_command_request, @@ -90,7 +92,9 @@ static const pa_pdispatch_cb_t command_table[PA_COMMAND_MAX] = { [PA_COMMAND_RECORD_STREAM_EVENT] = pa_command_stream_event, [PA_COMMAND_CLIENT_EVENT] = pa_command_client_event, [PA_COMMAND_PLAYBACK_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr, - [PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr + [PA_COMMAND_RECORD_BUFFER_ATTR_CHANGED] = pa_command_stream_buffer_attr, + [PA_COMMAND_ENABLE_RINGBUFFER] = pa_command_enable_ringbuffer, + [PA_COMMAND_DISABLE_RINGBUFFER] = pa_command_disable_ringbuffer, }; static void context_free(pa_context *c); @@ -1395,6 +1399,58 @@ finish: pa_context_unref(c); } +static void pa_command_enable_ringbuffer(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; + pa_srchannel *sr; + pa_srchannel_template srt; + const int *fds; + int nfd; + + pa_assert(pd); + pa_assert(command == PA_COMMAND_ENABLE_RINGBUFFER); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + if (!c->srmemblock) { + pa_context_fail(c, PA_ERR_PROTOCOL); + return; + } + + fds = pa_pdispatch_fds(pd, &nfd); + if (nfd != 2 || !fds || fds[0] == -1 || fds[1] == -1) { + pa_context_fail(c, PA_ERR_PROTOCOL); + return; + } + + pa_context_ref(c); + + srt.memblock = c->srmemblock; + srt.readfd = fds[0]; + srt.writefd = fds[1]; + sr = pa_srchannel_new_from_template(c->mainloop, &srt); + pa_pstream_send_simple_ack(c->pstream, tag); + + pa_pstream_set_srchannel(c->pstream, sr); + + pa_context_unref(c); +} + +static void pa_command_disable_ringbuffer(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { + pa_context *c = userdata; + + pa_assert(pd); + pa_assert(command == PA_COMMAND_DISABLE_RINGBUFFER); + pa_assert(t); + pa_assert(c); + pa_assert(PA_REFCNT_VALUE(c) >= 1); + + pa_pstream_set_srchannel(c->pstream, NULL); + + pa_pstream_send_simple_ack(c->pstream, tag); +} + + void pa_command_client_event(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) { pa_context *c = userdata; pa_proplist *pl = NULL; diff --git a/src/pulsecore/native-common.h b/src/pulsecore/native-common.h index dad82e0..bf94435 100644 --- a/src/pulsecore/native-common.h +++ b/src/pulsecore/native-common.h @@ -176,6 +176,10 @@ enum { /* Supported since protocol v27 (3.0) */ PA_COMMAND_SET_PORT_LATENCY_OFFSET, + /* Supported since protocol v30 (6.0) */ + PA_COMMAND_ENABLE_RINGBUFFER, + PA_COMMAND_DISABLE_RINGBUFFER, + PA_COMMAND_MAX }; -- 1.9.1