config: fixup type for demo effect
[staging/agl-audio-plugin.git] / tracker.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 "tracker.h"
23 #include "discover.h"
24 #include "router.h"
25 #include "utils.h"
26
27 struct pa_card_hooks {
28     pa_hook_slot    *put;
29     pa_hook_slot    *unlink;
30     pa_hook_slot    *profchg;
31 };
32
33 struct pa_port_hooks {
34     pa_hook_slot    *avail;
35 };
36
37 struct pa_sink_hooks {
38     pa_hook_slot    *put;
39     pa_hook_slot    *unlink;
40     pa_hook_slot    *portchg;
41 };
42
43 struct pa_source_hooks {
44     pa_hook_slot    *put;
45     pa_hook_slot    *unlink;
46     pa_hook_slot    *portchg;
47 };
48
49 struct pa_sink_input_hooks {
50     pa_hook_slot    *neew;
51     pa_hook_slot    *put;
52     pa_hook_slot    *unlink;
53 };
54
55 struct pa_source_output_hooks {
56     pa_hook_slot    *neew;
57     pa_hook_slot    *put;
58     pa_hook_slot    *unlink;
59 };
60
61 struct agl_tracker {
62     pa_card_hooks           card;
63     pa_port_hooks           port;
64     pa_sink_hooks           sink;
65     pa_source_hooks         source;
66     pa_sink_input_hooks     sink_input;
67     pa_source_output_hooks  source_output;
68 };
69
70
71 static pa_hook_result_t card_put (void *, void *, void *);
72 static pa_hook_result_t card_unlink (void *, void *, void *);
73 static pa_hook_result_t card_profile_changed (void *, void *, void *);
74
75 static pa_hook_result_t port_available_changed (void *, void *, void *);
76
77 static pa_hook_result_t sink_put (void *, void *, void *);
78 static pa_hook_result_t sink_unlink (void *, void *, void *);
79 static pa_hook_result_t sink_port_changed (void *, void *, void *);
80
81 static pa_hook_result_t source_put (void *, void *, void *);
82 static pa_hook_result_t source_unlink (void *, void *, void *);
83 static pa_hook_result_t source_port_changed (void *, void *, void *);
84
85 static pa_hook_result_t sink_input_new (void *, void *, void *);
86 static pa_hook_result_t sink_input_put (void *, void *, void *);
87 static pa_hook_result_t sink_input_unlink (void *, void *, void *);
88
89 static pa_hook_result_t source_output_new (void *, void *, void *);
90 static pa_hook_result_t source_output_put (void *, void *, void *);
91 static pa_hook_result_t source_output_unlink (void *, void *, void *);
92
93
94 agl_tracker *agl_tracker_init (struct userdata *u)
95 {
96         pa_core *core;
97         pa_hook *hooks;
98         agl_tracker *tracker;
99         pa_card_hooks *card;
100         pa_port_hooks *port;
101         pa_sink_hooks *sink;
102         pa_source_hooks *source;
103         pa_sink_input_hooks *sinp;
104         pa_source_output_hooks *sout;
105
106         pa_assert (u);
107         pa_assert_se (core = u->core);
108         pa_assert_se (hooks = core->hooks);
109
110         tracker = pa_xnew0 (agl_tracker, 1);
111         card = &tracker->card;
112         port = &tracker->port;
113         sink = &tracker->sink;
114         source = &tracker->source;
115         sinp = &tracker->sink_input;
116         sout = &tracker->source_output;
117
118          /* card */
119         card->put = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_PUT,
120                                      PA_HOOK_LATE, card_put, u);
121         card->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_UNLINK,
122                                         PA_HOOK_LATE, card_unlink, u);
123         card->profchg = pa_hook_connect (hooks + PA_CORE_HOOK_CARD_PROFILE_CHANGED,
124                                          PA_HOOK_LATE, card_profile_changed, u);
125
126          /* port */
127         port->avail = pa_hook_connect (hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
128                                        PA_HOOK_LATE, port_available_changed, u);
129
130          /* sink */
131         sink->put = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_PUT,
132                                      PA_HOOK_LATE, sink_put, u);
133         sink->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_UNLINK,
134                                         PA_HOOK_LATE, sink_unlink, u);
135         sink->portchg = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_PORT_CHANGED,
136                                          PA_HOOK_LATE, sink_port_changed, u);
137
138          /* source */
139         source->put = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_PUT,
140                                        PA_HOOK_LATE, source_put, u);
141         source->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_UNLINK,
142                                           PA_HOOK_LATE, source_unlink, u);
143         source->portchg = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_PORT_CHANGED,
144                                           PA_HOOK_LATE, source_port_changed, u);
145
146          /* sink-input */
147         sinp->neew = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_NEW,
148                                       PA_HOOK_EARLY, sink_input_new, u);
149         sinp->put = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_PUT,
150                                      PA_HOOK_LATE, sink_input_put, u);
151         sinp->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SINK_INPUT_UNLINK,
152                                         PA_HOOK_LATE, sink_input_unlink, u);
153
154          /* source-output */
155         sout->neew = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_NEW,
156                                       PA_HOOK_EARLY, source_output_new, u);
157         sout->put = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_PUT,
158                                      PA_HOOK_LATE, source_output_put, u);
159         sout->unlink = pa_hook_connect (hooks + PA_CORE_HOOK_SOURCE_OUTPUT_UNLINK,
160                                         PA_HOOK_LATE, source_output_unlink, u);
161
162         return tracker; 
163 }
164
165 void agl_tracker_done (struct userdata *u)
166 {
167         agl_tracker *tracker;   
168         pa_card_hooks *card;
169         pa_port_hooks *port;
170         pa_sink_hooks *sink;
171         pa_source_hooks *source;
172         pa_sink_input_hooks *sinp;
173
174         if (u && (tracker = u->tracker)) {
175
176                 card = &tracker->card;
177                 pa_hook_slot_free (card->put);
178                 pa_hook_slot_free (card->unlink);
179                 pa_hook_slot_free (card->profchg);
180
181                 port = &tracker->port;
182                 pa_hook_slot_free (port->avail);
183
184                 sink = &tracker->sink;
185                 pa_hook_slot_free (sink->put);
186                 pa_hook_slot_free (sink->unlink);
187                 pa_hook_slot_free (sink->portchg);
188
189                 source = &tracker->source;
190                 pa_hook_slot_free (source->put);
191                 pa_hook_slot_free (source->unlink);
192                 pa_hook_slot_free (source->portchg);
193
194                 sinp = &tracker->sink_input;
195                 pa_hook_slot_free (sinp->neew);
196                 pa_hook_slot_free (sinp->put);
197                 pa_hook_slot_free (sinp->unlink);
198
199                 pa_xfree(tracker);
200         
201                 u->tracker = NULL;
202         }
203 }
204
205  /* main logic initialization function */
206 void agl_tracker_synchronize (struct userdata *u)
207 {
208         pa_core *core;
209         pa_card *card;
210         pa_sink *sink;
211         pa_source *source;
212         pa_sink_input *sinp;
213         pa_source_output *sout;
214         uint32_t index;
215
216         pa_assert (u);
217         pa_assert_se (core = u->core);
218
219          /* discover.c : add each valid USB/PCI/Platform ALSA sound card */
220         PA_IDXSET_FOREACH (card, core->cards, index) {
221                 agl_discover_add_card (u, card);
222         }
223
224         PA_IDXSET_FOREACH (sink, core->sinks, index) {
225                 agl_discover_add_sink (u, sink, false);
226         }
227
228         PA_IDXSET_FOREACH (source, core->sources, index) {
229                 agl_discover_add_source (u, source);
230         }
231
232         PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) {
233                 agl_discover_register_sink_input (u, sinp);
234         }
235
236         PA_IDXSET_FOREACH(sout, core->source_outputs, index) {
237                 agl_discover_register_source_output (u, sout);
238         }
239
240         agl_router_make_routing (u);
241 }
242
243
244  /* HOOK IMPLEMENTATIONS */
245 static pa_hook_result_t card_put (void *hook_data,
246                                   void *call_data,
247                                   void *slot_data)
248 {
249         return PA_HOOK_OK;
250 }
251
252 static pa_hook_result_t card_unlink (void *hook_data,
253                                      void *call_data,
254                                      void *slot_data)
255 {
256         return PA_HOOK_OK;
257 }
258
259 static pa_hook_result_t card_profile_changed (void *hook_data,
260                                               void *call_data,
261                                               void *slot_data)
262 {
263         return PA_HOOK_OK;
264 }
265
266 static pa_hook_result_t port_available_changed (void *hook_data,
267                                                 void *call_data,
268                                                 void *slot_data)
269 {
270         return PA_HOOK_OK;
271 }
272
273 static pa_hook_result_t sink_put (void *hook_data,
274                                   void *call_data,
275                                   void *slot_data)
276 {
277         return PA_HOOK_OK;
278 }
279
280 static pa_hook_result_t sink_unlink (void *hook_data,
281                                      void *call_data,
282                                      void *slot_data)
283 {
284         return PA_HOOK_OK;
285 }
286
287 static pa_hook_result_t sink_port_changed (void *hook_data,
288                                            void *call_data,
289                                            void *slot_data)
290 {
291         return PA_HOOK_OK;
292 }
293
294 static pa_hook_result_t source_put (void *hook_data,
295                                     void *call_data,
296                                     void *slot_data)
297 {
298         return PA_HOOK_OK;
299 }
300
301 static pa_hook_result_t source_unlink (void *hook_data,
302                                        void *call_data,
303                                        void *slot_data)
304 {
305         return PA_HOOK_OK;
306 }
307
308 static pa_hook_result_t source_port_changed (void *hook_data,
309                                              void *call_data,
310                                              void *slot_data)
311 {
312         return PA_HOOK_OK;
313 }
314
315 static pa_hook_result_t sink_input_new (void *hook_data,
316                                         void *call_data,
317                                         void *slot_data)
318 {
319         /* main hook, called by each client in its 1st phase */
320         pa_sink_input_new_data *data = (pa_sink_input_new_data *)call_data;
321         struct userdata *u = (struct userdata *)slot_data;
322         bool success;
323
324         success = agl_discover_preroute_sink_input (u, data);
325
326         return success ? PA_HOOK_OK : PA_HOOK_CANCEL;
327 }
328
329 static pa_hook_result_t sink_input_put (void *hook_data,
330                                         void *call_data,
331                                         void *slot_data)
332 {
333         /* called by each client in its 2nd phase */
334         pa_sink_input *sinp = (pa_sink_input *)call_data;
335         struct userdata *u = (struct userdata *)slot_data;
336
337         agl_discover_add_sink_input (u, sinp);
338
339         return PA_HOOK_OK;
340 }
341
342 static pa_hook_result_t sink_input_unlink (void *hook_data,
343                                            void *call_data,
344                                            void *slot_data)
345 {
346         /* called by each client when stopping sound */
347         pa_sink_input *sinp = (pa_sink_input *)call_data;
348         struct userdata *u = (struct userdata *)slot_data;
349
350         agl_discover_remove_sink_input (u, sinp);
351
352         return PA_HOOK_OK;
353 }
354
355 static pa_hook_result_t source_output_new (void *hook_data,
356                                            void *call_data,
357                                            void *slot_data)
358 {
359         return PA_HOOK_OK;
360 }
361
362 static pa_hook_result_t source_output_put (void *hook_data,
363                                            void *call_data,
364                                            void *slot_data)
365 {
366         return PA_HOOK_OK;
367 }
368
369 static pa_hook_result_t source_output_unlink (void *hook_data,
370                                               void *call_data,
371                                               void *slot_data)
372 {
373         return PA_HOOK_OK;
374 }