Skip to content

Commit

Permalink
Protocol, client: Add commands to enable srbchannel
Browse files Browse the repository at this point in the history
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@canonical.com>
  • Loading branch information
David Henningsson committed Jun 27, 2014
1 parent 4931637 commit 1827991
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 2 deletions.
20 changes: 20 additions & 0 deletions PROTOCOL
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,26 @@ 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_SRBCHANNEL
First sent from server to client, tells the client to start listening on
the additional SHM ringbuffer channel.
This command also has ancillary data (two eventfds attached to it).
Must be directly followed by a memblock which is the ringbuffer memory.
When memblock is received by the client, it acks by sending
PA_COMMAND_ENABLE_SRBCHANNEL back (without ancillary or memblock data).

PA_COMMAND_DISABLE_SRBCHANNEL
Tells the client to stop listening on the additional SHM ringbuffer channel.
Acked by client by sending PA_COMMAND_DISABLE_SRBCHANNEL back.

#### 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.
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
108 changes: 107 additions & 1 deletion src/pulse/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,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_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata);
static void pa_command_disable_srbchannel(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,
Expand All @@ -87,7 +89,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_SRBCHANNEL] = pa_command_enable_srbchannel,
[PA_COMMAND_DISABLE_SRBCHANNEL] = pa_command_disable_srbchannel,
};
static void context_free(pa_context *c);

Expand Down Expand Up @@ -165,6 +169,9 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
c->conf = pa_client_conf_new();
pa_client_conf_load(c->conf, true, true);

c->srb_template.readfd = -1;
c->srb_template.writefd = -1;

if (!(c->mempool = pa_mempool_new(!c->conf->disable_shm, c->conf->shm_size))) {

if (!c->conf->disable_shm)
Expand Down Expand Up @@ -206,6 +213,11 @@ static void context_unlink(pa_context *c) {
c->pstream = NULL;
}

if (c->srb_template.memblock) {
pa_memblock_unref(c->srb_template.memblock);
c->srb_template.memblock = NULL;
}

if (c->client) {
pa_socket_client_unref(c->client);
c->client = NULL;
Expand Down Expand Up @@ -331,6 +343,35 @@ static void pstream_packet_callback(pa_pstream *p, pa_packet *packet, const pa_a
pa_context_unref(c);
}

static void handle_srbchannel_memblock(pa_context *c, pa_memblock *memblock) {
pa_srbchannel *sr;
pa_tagstruct *t;

pa_assert(c);

/* Memblock sanity check */
if (!memblock)
pa_context_fail(c, PA_ERR_PROTOCOL);
else if (pa_memblock_is_read_only(memblock))
pa_context_fail(c, PA_ERR_PROTOCOL);
else if (pa_memblock_is_ours(memblock))
pa_context_fail(c, PA_ERR_PROTOCOL);

/* Create the srbchannel */
c->srb_template.memblock = memblock;
pa_memblock_ref(memblock);
sr = pa_srbchannel_new_from_template(c->mainloop, &c->srb_template);

/* Ack the enable command */
t = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t, PA_COMMAND_ENABLE_SRBCHANNEL);
pa_tagstruct_putu32(t, c->srb_setup_tag);
pa_pstream_send_tagstruct(c->pstream, t);

/* ...and switch over */
pa_pstream_set_srbchannel(c->pstream, sr);
}

static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t offset, pa_seek_mode_t seek, const pa_memchunk *chunk, void *userdata) {
pa_context *c = userdata;
pa_stream *s;
Expand All @@ -343,6 +384,12 @@ static void pstream_memblock_callback(pa_pstream *p, uint32_t channel, int64_t o

pa_context_ref(c);

if (c->srb_template.readfd != -1 && c->srb_template.memblock == NULL) {
handle_srbchannel_memblock(c, chunk->memblock);
pa_context_unref(c);
return;
}

if ((s = pa_hashmap_get(c->record_streams, PA_UINT32_TO_PTR(channel)))) {

if (chunk->memblock) {
Expand Down Expand Up @@ -1362,6 +1409,65 @@ void pa_command_extension(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_t
pa_context_unref(c);
}

static void pa_command_enable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_context *c = userdata;
const int *fds;
int nfd;

pa_assert(pd);
pa_assert(command == PA_COMMAND_ENABLE_SRBCHANNEL);
pa_assert(t);
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);

/* Currently only one srb channel is supported, might change in future versions */
if (c->srb_template.readfd != -1) {
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);

c->srb_template.readfd = fds[0];
c->srb_template.writefd = fds[1];
c->srb_setup_tag = tag;

pa_context_unref(c);
}

static void pa_command_disable_srbchannel(pa_pdispatch *pd, uint32_t command, uint32_t tag, pa_tagstruct *t, void *userdata) {
pa_context *c = userdata;
pa_tagstruct *t2;

pa_assert(pd);
pa_assert(command == PA_COMMAND_DISABLE_SRBCHANNEL);
pa_assert(t);
pa_assert(c);
pa_assert(PA_REFCNT_VALUE(c) >= 1);

pa_pstream_set_srbchannel(c->pstream, NULL);

c->srb_template.readfd = -1;
c->srb_template.writefd = -1;
if (c->srb_template.memblock) {
pa_memblock_unref(c->srb_template.memblock);
c->srb_template.memblock = NULL;
}

/* Send disable command back again */
t2 = pa_tagstruct_new(NULL, 0);
pa_tagstruct_putu32(t2, PA_COMMAND_DISABLE_SRBCHANNEL);
pa_tagstruct_putu32(t2, tag);
pa_pstream_send_tagstruct(c->pstream, t2);
}


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;
Expand Down
3 changes: 3 additions & 0 deletions src/pulse/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ struct pa_context {
pa_pstream *pstream;
pa_pdispatch *pdispatch;

pa_srbchannel_template srb_template;
uint32_t srb_setup_tag;

pa_hashmap *record_streams, *playback_streams;
PA_LLIST_HEAD(pa_stream, streams);
PA_LLIST_HEAD(pa_operation, operations);
Expand Down
5 changes: 5 additions & 0 deletions src/pulsecore/native-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@ enum {
/* Supported since protocol v27 (3.0) */
PA_COMMAND_SET_PORT_LATENCY_OFFSET,

/* Supported since protocol v30 (6.0) */
/* BOTH DIRECTIONS */
PA_COMMAND_ENABLE_SRBCHANNEL,
PA_COMMAND_DISABLE_SRBCHANNEL,

PA_COMMAND_MAX
};

Expand Down

0 comments on commit 1827991

Please sign in to comment.