diff options
author | David Henningsson <david.henningsson@canonical.com> | 2014-04-25 17:23:21 +0200 |
---|---|---|
committer | David Henningsson <david.henningsson@canonical.com> | 2014-06-27 14:23:18 +0200 |
commit | 1827991548495f1b2c3f44fe45b51901109f791c (patch) | |
tree | 56d1a91be015591d42b34763dab7b7b0b0d5b531 /src/pulse | |
parent | 4931637f822f23888c7477ad5bbfcf87b337db48 (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.c | 108 | ||||
-rw-r--r-- | src/pulse/internal.h | 3 |
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); |