Rename all internal pa_ definitions to agl_
[staging/agl-audio-plugin.git] / switch.c
1 /*
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
6  *
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.
10  *
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.
15  *
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,
19  * MA 02110-1301 USA.
20  *
21  */
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 */
25
26 #include "utils.h"
27 #include "switch.h"
28 #include "node.h"
29
30 bool agl_switch_setup_link (struct userdata *u, agl_node *from, agl_node *to, bool explicit)
31 {
32         pa_core *core;
33         pa_sink *sink;
34         pa_source *source;
35
36         pa_assert (u);
37         pa_assert_se (core = u->core);
38
39         /* EXPLICIT ROUTES/DEFAULT ROUTES */
40
41         /* 1) EXPLICIT ROUTES : "FROM" AND "TO" ARE DEFINED */
42         if (explicit) {
43                 pa_assert (from);
44                 pa_assert (to);
45
46                 switch (from->implement) {
47                         /* STREAM SOURCE */
48                         case agl_stream:
49                         switch (to->implement) {
50                                 /* STREAM TO STREAM : NOT IMPLEMENTED */
51                                 case agl_stream:
52                                         pa_log_debug ("routing to streams not implemented");
53                                         break;
54                                 /* STREAM TO DEVICE : OK */
55                                 case agl_device:
56                                         //if (!setup_explicit_stream2dev_link (u, from, to))
57                                         //      return false;
58                                         break;
59                                 /* DEFAULT */
60                                 default:
61                                         pa_log ("can't setup link: invalid sink node");
62                                         return false;
63                         }
64                         break;
65
66                         /* DEVICE SOURCE : NOT IMPLEMENTED */
67                         case agl_device:
68                                 pa_log_debug("input device routing is not implemented yet");
69                                 break;
70
71                         /* DEFAULT */
72                         default:
73                                 pa_log ("can't setup link: invalid sink node");
74                                 return false;
75                 }
76         }
77
78         /* 2) DEFAULT ROUTES : EITHER ONE OF "FROM" AND "TO" ARE DEFINED */
79         else {
80                 pa_assert (from || to);
81
82                 /* "TO" IS DEFINED */
83                 if (to) {
84                         switch (to->implement) {
85                                 /* STREAM DESTINATION */
86                                 case agl_stream:
87                                 switch (from->implement) {
88                                         /* STREAM TO STREAM : NOT IMPLEMENTED */
89                                         case agl_stream:
90                                                 pa_log_debug ("routing to streams not implemented");
91                                                 break;
92                                         /* DEVICE TO STREAM : OK */
93                                         case agl_device:
94                                                 //if (!setup_default_dev2stream_link(u, from, to))
95                                                 //      return false;
96                                                 break;
97                                         /* DEFAULT */
98                                         default:
99                                                 pa_log ("can't setup link: invalid sink node");
100                                                 return false;
101                                 }
102                                 break;
103
104                                 /* DEVICE DESTINATION */
105                                 case agl_device:
106                                 /* IF THERE IS NO SOURCE : DEFAULT OUTPUT PREROUTE */
107                                 /* if (!from)
108                                         return setup_device_output(u, to) != NULL;
109                                 else { */
110                                 switch (from->implement) {
111                                         /* STREAM TO DEVICE : OK */
112                                         case agl_stream:
113                                                 //if (!setup_default_stream2dev_link (u, from, to))
114                                                 //      return false;
115                                                 break;
116                                         /* DEVICE TO DEVICE : OK */
117                                         case agl_device:
118                                                 //if (!setup_default_dev2dev_link (u, from, to))
119                                                 //      return false;
120                                                 break;
121                                         /* DEFAULT */
122                                         default:
123                                                 pa_log ("can't setup link: invalid source node");
124                                                 return false;
125                                 }
126                                 break;
127                                 /* } */
128
129                                 /* DEFAULT DESTINATION : NULL */
130                                 default:
131                                         pa_log ("can't setup link");
132                                         return false;
133                         }
134                 }
135
136                 /* ONLY "FROM" IS DEFINED */
137                 else {
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");
141                                 return false;
142                         }
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");
147                                 return false;
148                         }
149
150                         sink = agl_utils_get_primary_alsa_sink (u);
151                         source = agl_utils_get_null_source (u, from->nullsink);
152
153                         from->loopnode = agl_loopnode_create (u, AGL_LOOPNODE_SINK, from->index, source->index, sink->index);
154                 }
155         }
156
157         //pa_log_debug ("link %s => %s is established", from->amname, to->amname);
158
159         return true;
160 }
161
162 bool agl_switch_teardown_link (struct userdata *u, agl_node *from, agl_node *to)
163 {
164         pa_core *core;
165
166         pa_assert (u);
167         pa_assert_se (core = u->core);
168
169         pa_assert (from || to);
170
171         /* "TO" IS DEFINED */
172         if (to) {
173
174         }
175         /* ONLY "FROM" IS DEFINED */
176         else {
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");
180                         return false;
181                 }
182                 /* (the rest supposes "from->implement == agl_stream") */
183                 if (from->loopnode)
184                         agl_loopnode_destroy (u, from->loopnode);
185                 if (from->nullsink)
186                         agl_utils_destroy_null_sink (u, from->nullsink);
187         }
188
189         //pa_log_debug("link %s => %s is torn down", from->amname, to->amname);
190
191         return true;
192 }
193
194
195 bool set_port (struct userdata *u, agl_node *node)
196 {
197         pa_core *core;
198         pa_sink *sink;
199         pa_source *source;
200         pa_device_port *port;
201         void *data = NULL;
202         uint32_t paidx = PA_IDXSET_INVALID;
203
204         pa_assert (u);
205         pa_assert (node);
206         pa_assert (node->paname);
207         pa_assert_se (core = u->core);
208
209         if (node->direction != agl_input && node->direction != agl_output)
210                 return false;
211         if (node->implement != agl_device)
212                 return true;
213         if (!node->paport)
214                 return true;
215
216         if (node->direction == agl_input) {
217                 source = pa_namereg_get (core, node->paname, PA_NAMEREG_SOURCE);
218                 if (!source) {
219                         pa_log ("cannot set port for node '%s': source not found", node->paname);
220                         return false;
221                 }
222
223                 port = source->active_port;
224                 /* active port and wanted port already match */
225                 if (pa_streq (node->paport, port->name))
226                         return true;
227
228                 /* ACTIVE CODE */
229                 if (pa_source_set_port (source, node->paport, false) < 0)
230                         return false;
231
232                 data = source;
233                 paidx = source->index;
234         }
235
236         if (node->direction == agl_output) {
237                 sink = pa_namereg_get (core, node->paname, PA_NAMEREG_SINK);
238                 if (!sink) {
239                         pa_log ("cannot set port for node '%s': source not found", node->paname);
240                         return false;
241                 }
242
243                 port = sink->active_port;
244                 /* active port and wanted port already match */
245                 if (pa_streq (node->paport, port->name))
246                         return true;
247
248                 /* ACTIVE CODE */
249                 if (pa_sink_set_port (sink, node->paport, false) < 0)
250                         return false;
251
252                 data = sink;
253                 paidx = sink->index;
254         }
255
256         return true;
257 }