2 * module-agl-audio -- PulseAudio module for providing audio routing support
3 * (forked from "module-murphy-ivi" - https://github.com/otcshare )
4 * Copyright (c) 2012, Intel Corporation.
5 * Copyright (c) 2016, IoT.bzh
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU Lesser General Public License,
9 * version 2.1, as published by the Free Software Foundation.
11 * This program is distributed in the hope it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the
18 * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
22 #include <pulsecore/pulsecore-config.h> /* required for headers below */
23 #include <pulsecore/core-util.h> /* requred for "pa_streq" */
24 #include <pulsecore/namereg.h> /* for PA_NAMEREG_SOURCE */
30 bool agl_switch_setup_link (struct userdata *u, agl_node *from, agl_node *to, bool explicit)
37 pa_assert_se (core = u->core);
39 /* EXPLICIT ROUTES/DEFAULT ROUTES */
41 /* 1) EXPLICIT ROUTES : "FROM" AND "TO" ARE DEFINED */
46 switch (from->implement) {
49 switch (to->implement) {
50 /* STREAM TO STREAM : NOT IMPLEMENTED */
52 pa_log_debug ("routing to streams not implemented");
54 /* STREAM TO DEVICE : OK */
56 //if (!setup_explicit_stream2dev_link (u, from, to))
61 pa_log ("can't setup link: invalid sink node");
66 /* DEVICE SOURCE : NOT IMPLEMENTED */
68 pa_log_debug("input device routing is not implemented yet");
73 pa_log ("can't setup link: invalid sink node");
78 /* 2) DEFAULT ROUTES : EITHER ONE OF "FROM" AND "TO" ARE DEFINED */
80 pa_assert (from || to);
84 switch (to->implement) {
85 /* STREAM DESTINATION */
87 switch (from->implement) {
88 /* STREAM TO STREAM : NOT IMPLEMENTED */
90 pa_log_debug ("routing to streams not implemented");
92 /* DEVICE TO STREAM : OK */
94 //if (!setup_default_dev2stream_link(u, from, to))
99 pa_log ("can't setup link: invalid sink node");
104 /* DEVICE DESTINATION */
106 /* IF THERE IS NO SOURCE : DEFAULT OUTPUT PREROUTE */
108 return setup_device_output(u, to) != NULL;
110 switch (from->implement) {
111 /* STREAM TO DEVICE : OK */
113 //if (!setup_default_stream2dev_link (u, from, to))
116 /* DEVICE TO DEVICE : OK */
118 //if (!setup_default_dev2dev_link (u, from, to))
123 pa_log ("can't setup link: invalid source node");
129 /* DEFAULT DESTINATION : NULL */
131 pa_log ("can't setup link");
136 /* ONLY "FROM" IS DEFINED */
138 /* only works with a stream, use default input prerouting */
139 if (from->implement == agl_device) {
140 pa_log_debug ("default routing for a device input is not supported yet");
143 /* (the rest supposes "from->implement == agl_stream") */
144 /* refuse unknown node types for default routing */
145 if (from->type == agl_node_type_unknown) {
146 pa_log_debug ("default routing for unknown node type is refused");
150 sink = pa_utils_get_primary_alsa_sink (u);
151 source = pa_utils_get_null_source (u, from->nullsink);
153 from->loopnode = pa_loopnode_create (u, PA_LOOPNODE_SINK, from->index, source->index, sink->index);
157 //pa_log_debug ("link %s => %s is established", from->amname, to->amname);
162 bool agl_switch_teardown_link (struct userdata *u, agl_node *from, agl_node *to)
167 pa_assert_se (core = u->core);
169 pa_assert (from || to);
171 /* "TO" IS DEFINED */
175 /* ONLY "FROM" IS DEFINED */
177 /* only works with a stream */
178 if (from->implement == agl_device) {
179 pa_log_debug ("default routing for a device input is not supported");
182 /* (the rest supposes "from->implement == agl_stream") */
184 pa_loopnode_destroy (u, from->loopnode);
186 pa_utils_destroy_null_sink (u, from->nullsink);
189 //pa_log_debug("link %s => %s is torn down", from->amname, to->amname);
195 bool set_port (struct userdata *u, agl_node *node)
200 pa_device_port *port;
202 uint32_t paidx = PA_IDXSET_INVALID;
206 pa_assert (node->paname);
207 pa_assert_se (core = u->core);
209 if (node->direction != agl_input && node->direction != agl_output)
211 if (node->implement != agl_device)
216 if (node->direction == agl_input) {
217 source = pa_namereg_get (core, node->paname, PA_NAMEREG_SOURCE);
219 pa_log ("cannot set port for node '%s': source not found", node->paname);
223 port = source->active_port;
224 /* active port and wanted port already match */
225 if (pa_streq (node->paport, port->name))
229 if (pa_source_set_port (source, node->paport, false) < 0)
233 paidx = source->index;
236 if (node->direction == agl_output) {
237 sink = pa_namereg_get (core, node->paname, PA_NAMEREG_SINK);
239 pa_log ("cannot set port for node '%s': source not found", node->paname);
243 port = sink->active_port;
244 /* active port and wanted port already match */
245 if (pa_streq (node->paport, port->name))
249 if (pa_sink_set_port (sink, node->paport, false) < 0)