--- PROTOCOL | 10 ++++++ src/Makefile.am | 1 + src/pulse/stream.c | 3 ++ src/pulsecore/edge.h | 27 +++++++++++++++ src/pulsecore/protocol-native.c | 77 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 118 insertions(+) create mode 100644 src/pulsecore/edge.h diff --git a/PROTOCOL b/PROTOCOL index 31307d7..7e7d0f4 100644 --- a/PROTOCOL +++ b/PROTOCOL @@ -381,6 +381,16 @@ description must not be NULL or empty. GET_NODE_INFO_LIST reply parameters are otherwise the same as with GET_NODE_INFO, but the parameter list is repeated for each node. +New fields added to the end of PA_COMMAND_CREATE_PLAYBACK_STREAM and +PA_COMMAND_CREATE_RECORD_STREAM: + uint32_t n_initial_routing_nodes + string node_name [repeated n_initial_routing_nodes times] + +If n_initial_routing_nodes > 0, then the old device parameters, i.e. index and +name, should be set to PA_INVALID_INDEX and NULL, respectively, and also the +direct_on_input field of PA_COMMAND_CREATE_RECORD_STREAM should be set to +PA_INVALID_INDEX. + #### 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/src/Makefile.am b/src/Makefile.am index 8e8f987..7498a65 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -875,6 +875,7 @@ libpulsecore_ at PA_MAJORMINOR@_la_SOURCES = \ pulsecore/core-scache.c pulsecore/core-scache.h \ pulsecore/core-subscribe.c pulsecore/core-subscribe.h \ pulsecore/core.c pulsecore/core.h \ + pulsecore/edge.h \ pulsecore/fdsem.c pulsecore/fdsem.h \ pulsecore/hook-list.c pulsecore/hook-list.h \ pulsecore/ltdl-helper.c pulsecore/ltdl-helper.h \ diff --git a/src/pulse/stream.c b/src/pulse/stream.c index 5c30866..7d77a0e 100644 --- a/src/pulse/stream.c +++ b/src/pulse/stream.c @@ -1373,6 +1373,9 @@ static int create_stream( pa_tagstruct_put_boolean(t, flags & (PA_STREAM_PASSTHROUGH)); } + if (s->context->version >= 30) + pa_tagstruct_putu32(t, 0); /* n_initial_routing_nodes */ + pa_pstream_send_tagstruct(s->context->pstream, t); pa_pdispatch_register_reply(s->context->pdispatch, tag, DEFAULT_TIMEOUT, pa_create_stream_callback, s, NULL); diff --git a/src/pulsecore/edge.h b/src/pulsecore/edge.h new file mode 100644 index 0000000..e7f73ea --- /dev/null +++ b/src/pulsecore/edge.h @@ -0,0 +1,27 @@ +#ifndef fooedgehfoo +#define fooedgehfoo + +/*** + This file is part of PulseAudio. + + Copyright (c) 2014 Intel Corporation + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#define PA_MAX_EDGES 1024 + +#endif diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c index ec8cee7..3434d2b 100644 --- a/src/pulsecore/protocol-native.c +++ b/src/pulsecore/protocol-native.c @@ -36,6 +36,7 @@ #include <pulse/xmalloc.h> #include <pulse/internal.h> +#include <pulsecore/edge.h> #include <pulsecore/native-common.h> #include <pulsecore/packet.h> #include <pulsecore/client.h> @@ -2146,6 +2147,41 @@ static void command_create_playback_stream(pa_pdispatch *pd, uint32_t command, u } } + if (c->version >= 30) { + if (pa_tagstruct_getu32(t, &n_nodes) < 0 || n_nodes > PA_MAX_EDGES) { + pa_log_info("Failed to read n_nodes."); + protocol_error(c); + goto finish; + } + + if (n_nodes > 0) { + if (sink_index != PA_INVALID_INDEX || sink_name) { + pa_log_info("The sink is set, but so are the initial routing nodes. Too confusing."); + protocol_error(c); + goto finish; + } + + nodes = pa_xnew(pa_node *, n_nodes); + + for (i = 0; i < n_nodes; i++) { + const char *node_name; + + if (pa_tagstruct_gets(t, &node_name) < 0 || !node_name) { + pa_log_info("Failed to read node_name."); + protocol_error(c); + goto finish; + } + + nodes[i] = pa_namereg_get(c->protocol->core, node_name, PA_NAMEREG_NODE); + if (!nodes[i]) { + pa_log_info("No such node: %s", node_name); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); + goto finish; + } + } + } + } + if (!pa_tagstruct_eof(t)) { protocol_error(c); goto finish; @@ -2479,12 +2515,53 @@ static void command_create_record_stream(pa_pdispatch *pd, uint32_t command, uin } } + if (c->version >= 30) { + if (pa_tagstruct_getu32(t, &n_nodes) || n_nodes > PA_MAX_EDGES) { + pa_log_info("Failed to read n_nodes."); + protocol_error(c); + goto finish; + } + + if (n_nodes > 0) { + if (source_index != PA_INVALID_INDEX || source_name) { + pa_log_info("The source is set, but so are the initial routing nodes. Too confusing."); + protocol_error(c); + goto finish; + } + + nodes = pa_xnew(pa_node *, n_nodes); + + for (i = 0; i < n_nodes; i++) { + const char *node_name; + + if (pa_tagstruct_gets(t, &node_name) || !node_name) { + pa_log_info("Failed to read node_name."); + protocol_error(c); + goto finish; + } + + nodes[i] = pa_namereg_get(c->protocol->core, node_name, PA_NAMEREG_NODE); + if (!nodes[i]) { + pa_log_info("No such node: %s", node_name); + pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); + goto finish; + } + } + } + } + if (!pa_tagstruct_eof(t)) { protocol_error(c); goto finish; } if (direct_on_input_idx != PA_INVALID_INDEX) { + if (n_nodes > 0) { + pa_log_info("The initial routing nodes are set, but so is direct_on_input_idx. Too confusing."); + pa_pstream_send_error(c->pstream, tag, PA_ERR_INVALID); + goto finish; + } + if (!(direct_on_input = pa_idxset_get_by_index(c->protocol->core->sink_inputs, direct_on_input_idx))) { pa_pstream_send_error(c->pstream, tag, PA_ERR_NOENTITY); goto finish; -- 1.8.3.1