routing: explicit routing in module-murphy-ivi
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / tracker.c
1 #include <pulsecore/pulsecore-config.h>
2
3 #include <pulse/def.h>
4 #include <pulsecore/card.h>
5
6 #include "tracker.h"
7 #include "utils.h"
8 #include "discover.h"
9 #include "router.h"
10 #include "node.h"
11
12
13 static pa_hook_result_t card_put(void *, void *, void *);
14 static pa_hook_result_t card_unlink(void *, void *, void *);
15 static pa_hook_result_t card_profile_changed(void *, void *, void *);
16
17 static pa_hook_result_t sink_put(void *, void *, void *);
18 static pa_hook_result_t sink_unlink(void *, void *, void *);
19 static pa_hook_result_t sink_port_changed(void *, void *, void *);
20 static pa_hook_result_t sink_port_available_changed(void *, void *, void *);
21
22 static pa_hook_result_t source_put(void *, void *, void *);
23 static pa_hook_result_t source_unlink(void *, void *, void *);
24 static pa_hook_result_t source_port_changed(void *, void *, void *);
25 static pa_hook_result_t source_port_available_changed(void *, void *, void *);
26
27 static pa_hook_result_t sink_input_new(void *, void *, void *);
28 static pa_hook_result_t sink_input_put(void *, void *, void *);
29 static pa_hook_result_t sink_input_unlink(void *, void *, void *);
30
31
32 pa_tracker *pa_tracker_init(struct userdata *u)
33 {
34     pa_core             *core;
35     pa_hook             *hooks;
36     pa_tracker          *tracker;
37     pa_card_hooks       *card;
38     pa_sink_hooks       *sink;
39     pa_source_hooks     *source;
40     pa_sink_input_hooks *sinp;
41
42     pa_assert(u);
43     pa_assert_se((core = u->core));
44     pa_assert_se((hooks = core->hooks));
45
46     tracker = pa_xnew0(pa_tracker, 1);
47     card   = &tracker->card;
48     sink   = &tracker->sink;
49     source = &tracker->source;
50     sinp   = &tracker->sink_input;
51
52     /* card */
53     card->put     = pa_hook_connect(
54                         hooks + PA_CORE_HOOK_CARD_PUT,
55                         PA_HOOK_LATE, card_put, u
56                     );
57     card->unlink  = pa_hook_connect(
58                         hooks + PA_CORE_HOOK_CARD_UNLINK,
59                         PA_HOOK_LATE, card_unlink, u
60                     );
61     card->profchg = pa_hook_connect(
62                         hooks + PA_CORE_HOOK_CARD_PROFILE_CHANGED,
63                         PA_HOOK_LATE, card_profile_changed, u
64                     );
65     /* sink */
66     sink->put       = pa_hook_connect(
67                           hooks + PA_CORE_HOOK_SINK_PUT,
68                           PA_HOOK_LATE, sink_put, u
69                       );
70     sink->unlink    = pa_hook_connect(
71                           hooks + PA_CORE_HOOK_SINK_UNLINK,
72                           PA_HOOK_LATE, sink_unlink, u
73                       );
74     sink->portchg   = pa_hook_connect(
75                           hooks + PA_CORE_HOOK_SINK_PORT_CHANGED,
76                           PA_HOOK_LATE, sink_port_changed, u
77                       );
78     sink->portavail = pa_hook_connect(
79                           hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
80                           PA_HOOK_LATE, sink_port_available_changed, u
81                       );    
82     /* source */
83     source->put       = pa_hook_connect(
84                             hooks + PA_CORE_HOOK_SOURCE_PUT,
85                             PA_HOOK_LATE, source_put, u
86                         );
87     source->unlink    = pa_hook_connect(
88                             hooks + PA_CORE_HOOK_SOURCE_UNLINK,
89                             PA_HOOK_LATE, source_unlink, u
90                         );
91     source->portchg   = pa_hook_connect(
92                             hooks + PA_CORE_HOOK_SOURCE_PORT_CHANGED,
93                             PA_HOOK_LATE, source_port_changed, u
94                         );
95     source->portavail = pa_hook_connect(
96                             hooks + PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
97                             PA_HOOK_LATE, source_port_available_changed, u
98                         );
99     /* sink-input */
100     sinp->neew   = pa_hook_connect(
101                        hooks + PA_CORE_HOOK_SINK_INPUT_NEW,
102                        PA_HOOK_EARLY, sink_input_new, u
103                    );
104     sinp->put    = pa_hook_connect(
105                        hooks + PA_CORE_HOOK_SINK_INPUT_PUT,
106                        PA_HOOK_LATE, sink_input_put, u
107                    );
108     sinp->unlink = pa_hook_connect(
109                        hooks + PA_CORE_HOOK_SINK_INPUT_UNLINK,
110                        PA_HOOK_LATE, sink_input_unlink, u
111                    );
112     
113     return tracker;
114 }
115
116 void pa_tracker_done(struct userdata *u)
117 {
118     pa_tracker          *tracker;
119     pa_card_hooks       *card;
120     pa_sink_hooks       *sink;
121     pa_source_hooks     *source;
122     pa_sink_input_hooks *sinp;
123
124     if (u && (tracker = u->tracker)) {
125
126         card = &tracker->card;
127         pa_hook_slot_free(card->put);
128         pa_hook_slot_free(card->unlink);
129         pa_hook_slot_free(card->profchg);
130         
131         sink = &tracker->sink;
132         pa_hook_slot_free(sink->put);
133         pa_hook_slot_free(sink->unlink);
134         pa_hook_slot_free(sink->portchg);
135         pa_hook_slot_free(sink->portavail);
136         
137         source = &tracker->source;
138         pa_hook_slot_free(source->put);
139         pa_hook_slot_free(source->unlink);
140         pa_hook_slot_free(source->portchg);
141         pa_hook_slot_free(source->portavail);
142         
143         sinp = &tracker->sink_input;
144         pa_hook_slot_free(sinp->neew);
145         pa_hook_slot_free(sinp->put);
146         pa_hook_slot_free(sinp->unlink);
147
148         pa_xfree(tracker);
149         
150         u->tracker = NULL;
151     }
152 }
153
154 void pa_tracker_synchronize(struct userdata *u)
155 {
156     pa_core       *core;
157     pa_card       *card;
158     pa_sink       *sink;
159     pa_source     *source;
160     pa_sink_input *sinp;
161     uint32_t       index;
162
163     pa_assert(u);
164     pa_assert_se((core = u->core));
165
166
167     PA_IDXSET_FOREACH(card, core->cards, index) {
168         pa_discover_add_card(u, card);
169     }
170
171     PA_IDXSET_FOREACH(sink, core->sinks, index) {
172         pa_discover_add_sink(u, sink, FALSE);
173     }
174
175     PA_IDXSET_FOREACH(source, core->sources, index) {
176         pa_discover_add_source(u, source);
177     }
178
179     /* Hmm... we should first collect all sink-inputs, assign
180        priority to them, sort them, and call pa_discover_register_sink_input()
181        in reverse priority order. Until than we may experience sound leaks
182        unnecessary profile changes etc ... */
183
184     PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) {
185         pa_discover_register_sink_input(u, sinp);
186     }
187
188     mir_router_make_routing(u);
189 }
190
191
192 static pa_hook_result_t card_put(void *hook_data,
193                                  void *call_data,
194                                  void *slot_data)
195 {
196     pa_card *card = (pa_card *)call_data;
197     struct userdata *u = (struct userdata *)slot_data;
198
199     pa_assert(u);
200     pa_assert(card);
201
202     pa_discover_add_card(u, card);
203
204     return PA_HOOK_OK;
205 }
206
207 static pa_hook_result_t card_unlink(void *hook_data,
208                                     void *call_data,
209                                     void *slot_data)
210 {
211     pa_card  *card = (pa_card *)call_data;
212     struct userdata *u = (struct userdata *)slot_data;
213     char buf[4096];
214
215     pa_assert(u);
216     pa_assert(card);
217
218     pa_discover_remove_card(u, card);
219
220     mir_router_print_rtgroups(u, buf, sizeof(buf));
221     pa_log_debug("%s", buf);
222
223     mir_router_make_routing(u);
224
225     return PA_HOOK_OK;
226 }
227
228
229 static pa_hook_result_t card_profile_changed(void *hook_data,
230                                              void *call_data,
231                                              void *slot_data)
232 {
233     pa_card  *card = (pa_card *)call_data;
234     struct userdata *u = (struct userdata *)slot_data;
235
236     pa_assert(u);
237     pa_assert(card);
238
239     pa_discover_profile_changed(u, card);
240
241     return PA_HOOK_OK;
242 }
243
244
245 static pa_hook_result_t sink_put(void *hook_data,
246                                  void *call_data,
247                                  void *slot_data)
248 {
249     pa_sink *sink = (pa_sink *)call_data;
250     struct userdata *u = (struct userdata *)slot_data;
251
252     pa_assert(u);
253     pa_assert(sink);
254
255     pa_discover_add_sink(u, sink, TRUE);
256
257     return PA_HOOK_OK;
258 }
259
260
261 static pa_hook_result_t sink_unlink(void *hook_data,
262                                     void *call_data,
263                                     void *slot_data)
264 {
265     pa_sink *sink = (pa_sink *)call_data;
266     struct userdata *u = (struct userdata *)slot_data;
267
268     pa_assert(u);
269     pa_assert(sink);
270
271     pa_discover_remove_sink(u, sink);
272
273     return PA_HOOK_OK;
274 }
275
276
277 static pa_hook_result_t sink_port_changed(void *hook_data,
278                                           void *call_data,
279                                           void *slot_data)
280 {
281     pa_sink *sink = (pa_sink *)call_data;
282     struct userdata *u = (struct userdata *)slot_data;
283
284     pa_assert(u);
285     pa_assert(sink);
286
287     return PA_HOOK_OK;
288 }
289
290 static pa_hook_result_t sink_port_available_changed(void *hook_data,
291                                                     void *call_data,
292                                                     void *slot_data)
293 {
294     pa_sink *sink = (pa_sink *)call_data;
295     struct userdata *u = (struct userdata *)slot_data;
296
297     pa_assert(u);
298     pa_assert(sink);
299
300     return PA_HOOK_OK;
301 }
302
303
304 static pa_hook_result_t source_put(void *hook_data,
305                                    void *call_data,
306                                    void *slot_data)
307 {
308     pa_source *source = (pa_source *)call_data;
309     struct userdata *u = (struct userdata *)slot_data;
310
311     pa_assert(u);
312     pa_assert(source);
313
314     pa_discover_add_source(u, source);
315
316     return PA_HOOK_OK;
317 }
318
319
320 static pa_hook_result_t source_unlink(void *hook_data,
321                                       void *call_data,
322                                       void *slot_data)
323 {
324     pa_source *source = (pa_source *)call_data;
325     struct userdata *u = (struct userdata *)slot_data;
326
327     pa_assert(u);
328     pa_assert(source);
329
330     pa_discover_remove_source(u, source);
331
332     return PA_HOOK_OK;
333 }
334
335
336 static pa_hook_result_t source_port_changed(void *hook_data,
337                                             void *call_data,
338                                             void *slot_data)
339 {
340     pa_source *source = (pa_source *)call_data;
341     struct userdata *u = (struct userdata *)slot_data;
342
343     pa_assert(u);
344     pa_assert(source);
345
346     return PA_HOOK_OK;
347 }
348
349 static pa_hook_result_t source_port_available_changed(void *hook_data,
350                                                       void *call_data,
351                                                       void *slot_data)
352 {
353     pa_source *source = (pa_source *)call_data;
354     struct userdata *u = (struct userdata *)slot_data;
355
356     pa_assert(u);
357     pa_assert(source);
358
359     return PA_HOOK_OK;
360 }
361
362
363
364 static pa_hook_result_t sink_input_new(void *hook_data,
365                                        void *call_data,
366                                        void *slot_data)
367 {
368     pa_sink_input_new_data *data = (pa_sink_input_new_data *)call_data;
369     struct userdata *u = (struct userdata *)slot_data;
370
371     pa_assert(u);
372     pa_assert(data);
373
374     pa_discover_preroute_sink_input(u, data);
375
376     return PA_HOOK_OK;
377 }
378
379 static pa_hook_result_t sink_input_put(void *hook_data,
380                                        void *call_data,
381                                        void *slot_data)
382 {
383     pa_sink_input *sinp = (pa_sink_input *)call_data;
384     struct userdata *u = (struct userdata *)slot_data;
385
386     pa_assert(u);
387     pa_assert(sinp);
388
389     pa_discover_add_sink_input(u, sinp);
390
391     return PA_HOOK_OK;
392 }
393
394
395 static pa_hook_result_t sink_input_unlink(void *hook_data,
396                                           void *call_data,
397                                           void *slot_data)
398 {
399     struct pa_sink_input *sinp = (pa_sink_input *)call_data;
400     struct userdata *u = (struct userdata *)slot_data;
401
402     pa_assert(u);
403     pa_assert(sinp);
404
405     pa_discover_remove_sink_input(u, sinp);
406
407     return PA_HOOK_OK;
408 }
409
410
411 /*
412  * Local Variables:
413  * c-basic-offset: 4
414  * indent-tabs-mode: nil
415  * End:
416  *
417  */
418