summaryrefslogtreecommitdiff
path: root/src/pulse
diff options
context:
space:
mode:
authorDavid Henningsson <david.henningsson@canonical.com>2014-04-25 17:23:21 +0200
committerDavid Henningsson <david.henningsson@canonical.com>2014-06-27 14:23:18 +0200
commit1827991548495f1b2c3f44fe45b51901109f791c (patch)
tree56d1a91be015591d42b34763dab7b7b0b0d5b531 /src/pulse
parent4931637f822f23888c7477ad5bbfcf87b337db48 (diff)
Protocol, client: Add commands to enable srbchannel
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>
Diffstat (limited to 'src/pulse')
-rw-r--r--src/pulse/context.c108
-rw-r--r--src/pulse/internal.h3
2 files changed, 110 insertions, 1 deletions
diff --git a/src/pulse/context.c b/src/pulse/context.c
index e1cd900d6..45ed344cf 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -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,
@@ -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);
@@ -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)
@@ -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;
@@ -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;
@@ -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) {
@@ -1362,6 +1409,65 @@ finish:
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;
diff --git a/src/pulse/internal.h b/src/pulse/internal.h
index c5084d5f3..fc2b70243 100644
--- a/src/pulse/internal.h
+++ b/src/pulse/internal.h
@@ -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);