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)
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))
58 sink = agl_utils_get_alsa_sink (u, to->paname);
60 pa_log("sink output not found!!!!");
61 sink = agl_utils_get_primary_alsa_sink (u);
64 source = agl_utils_get_null_source (u, from->nullsink);
65 from->loopnode = agl_loopnode_create (u, AGL_LOOPNODE_SINK, from->index, source->index, sink->index);
69 pa_log ("can't setup link: invalid sink node");
74 /* DEVICE SOURCE : NOT IMPLEMENTED */
76 pa_log_debug("input device routing is not implemented yet");
81 pa_log ("can't setup link: invalid sink node");
86 /* 2) DEFAULT ROUTES : EITHER ONE OF "FROM" AND "TO" ARE DEFINED */
88 pa_assert (from || to);
92 switch (to->implement) {
93 /* STREAM DESTINATION */
95 switch (from->implement) {
96 /* STREAM TO STREAM : NOT IMPLEMENTED */
98 pa_log_debug ("routing to streams not implemented");
100 /* DEVICE TO STREAM : OK */
102 //if (!setup_default_dev2stream_link(u, from, to))
107 pa_log ("can't setup link: invalid sink node");
112 /* DEVICE DESTINATION */
114 switch (from->implement) {
115 /* STREAM TO DEVICE : OK */
117 sink = agl_utils_get_alsa_sink (u, to->paname);
119 source = agl_utils_get_null_source (u, from->nullsink);
121 from->loopnode = agl_loopnode_create (u, AGL_LOOPNODE_SINK, from->index, source->index, sink->index);
123 /* DEVICE TO DEVICE : OK */
125 //if (!setup_default_dev2dev_link (u, from, to))
130 pa_log ("can't setup link: invalid source node");
136 /* DEFAULT DESTINATION : NULL */
138 pa_log ("can't setup link");
143 /* ONLY "FROM" IS DEFINED */
145 /* only works with a stream, use default input prerouting */
146 if (from->implement == agl_device) {
147 pa_log_debug ("default routing for a device input is not supported yet");
150 /* (the rest supposes "from->implement == agl_stream") */
151 /* refuse unknown node types for default routing */
152 if (from->type == agl_node_type_unknown) {
153 pa_log_debug ("default routing for unknown node type is refused");
157 sink = agl_utils_get_primary_alsa_sink (u);
158 source = agl_utils_get_null_source (u, from->nullsink);
159 from->loopnode = agl_loopnode_create (u, AGL_LOOPNODE_SINK, from->index, source->index, sink->index);
163 //pa_log_debug ("link %s => %s is established", from->amname, to->amname);
168 bool agl_switch_teardown_link (struct userdata *u, agl_node *from, agl_node *to)
173 pa_assert_se (core = u->core);
175 pa_assert (from || to);
177 /* "TO" IS DEFINED */
181 /* ONLY "FROM" IS DEFINED */
183 /* only works with a stream */
184 if (from->implement == agl_device) {
185 pa_log_debug ("default routing for a device input is not supported");
188 /* (the rest supposes "from->implement == agl_stream") */
190 agl_loopnode_destroy (u, from->loopnode);
192 agl_utils_destroy_null_sink (u, from->nullsink);
195 //pa_log_debug("link %s => %s is torn down", from->amname, to->amname);
201 bool set_port (struct userdata *u, agl_node *node)
206 pa_device_port *port;
208 uint32_t paidx = PA_IDXSET_INVALID;
212 pa_assert (node->paname);
213 pa_assert_se (core = u->core);
215 if (node->direction != agl_input && node->direction != agl_output)
217 if (node->implement != agl_device)
222 if (node->direction == agl_input) {
223 source = pa_namereg_get (core, node->paname, PA_NAMEREG_SOURCE);
225 pa_log ("cannot set port for node '%s': source not found", node->paname);
229 port = source->active_port;
230 /* active port and wanted port already match */
231 if (pa_streq (node->paport, port->name))
235 if (pa_source_set_port (source, node->paport, false) < 0)
239 paidx = source->index;
242 if (node->direction == agl_output) {
243 sink = pa_namereg_get (core, node->paname, PA_NAMEREG_SINK);
245 pa_log ("cannot set port for node '%s': source not found", node->paname);
249 port = sink->active_port;
250 /* active port and wanted port already match */
251 if (pa_streq (node->paport, port->name))
255 if (pa_sink_set_port (sink, node->paport, false) < 0)