routing: routing of multiplexed streams + initial synchronisation
[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     pa_utils_new_stamp();
167
168     PA_IDXSET_FOREACH(card, core->cards, index) {
169         pa_discover_add_card(u, card);
170     }
171
172     PA_IDXSET_FOREACH(sink, core->sinks, index) {
173         pa_discover_add_sink(u, sink, FALSE);
174     }
175
176     PA_IDXSET_FOREACH(source, core->sources, index) {
177         pa_discover_add_source(u, source);
178     }
179
180     /* Hmm... we should first collect all sink-inputs, assign
181        priority to them, sort them, and call pa_discover_register_sink_input()
182        in reverse priority order. Until than we may experience sound leaks
183        unnecessary profile changes etc ... */
184
185     PA_IDXSET_FOREACH(sinp, core->sink_inputs, index) {
186         pa_discover_register_sink_input(u, sinp);
187     }
188
189     mir_router_make_routing(u);
190 }
191
192
193 static pa_hook_result_t card_put(void *hook_data,
194                                  void *call_data,
195                                  void *slot_data)
196 {
197     pa_card *card = (pa_card *)call_data;
198     struct userdata *u = (struct userdata *)slot_data;
199
200     pa_assert(u);
201     pa_assert(card);
202
203     pa_utils_new_stamp();
204     pa_discover_add_card(u, card);
205
206     return PA_HOOK_OK;
207 }
208
209 static pa_hook_result_t card_unlink(void *hook_data,
210                                     void *call_data,
211                                     void *slot_data)
212 {
213     pa_card  *card = (pa_card *)call_data;
214     struct userdata *u = (struct userdata *)slot_data;
215     char buf[4096];
216
217     pa_assert(u);
218     pa_assert(card);
219
220     pa_discover_remove_card(u, card);
221
222     mir_router_print_rtgroups(u, buf, sizeof(buf));
223     pa_log_debug("%s", buf);
224
225     mir_router_make_routing(u);
226
227     return PA_HOOK_OK;
228 }
229
230
231 static pa_hook_result_t card_profile_changed(void *hook_data,
232                                              void *call_data,
233                                              void *slot_data)
234 {
235     pa_card  *card = (pa_card *)call_data;
236     struct userdata *u = (struct userdata *)slot_data;
237
238     pa_assert(u);
239     pa_assert(card);
240
241     pa_utils_new_stamp();
242     pa_discover_profile_changed(u, card);
243
244     return PA_HOOK_OK;
245 }
246
247
248 static pa_hook_result_t sink_put(void *hook_data,
249                                  void *call_data,
250                                  void *slot_data)
251 {
252     pa_sink *sink = (pa_sink *)call_data;
253     struct userdata *u = (struct userdata *)slot_data;
254
255     pa_assert(u);
256     pa_assert(sink);
257
258     pa_utils_new_stamp();
259     pa_discover_add_sink(u, sink, TRUE);
260
261     return PA_HOOK_OK;
262 }
263
264
265 static pa_hook_result_t sink_unlink(void *hook_data,
266                                     void *call_data,
267                                     void *slot_data)
268 {
269     pa_sink *sink = (pa_sink *)call_data;
270     struct userdata *u = (struct userdata *)slot_data;
271
272     pa_assert(u);
273     pa_assert(sink);
274
275     pa_discover_remove_sink(u, sink);
276
277     return PA_HOOK_OK;
278 }
279
280
281 static pa_hook_result_t sink_port_changed(void *hook_data,
282                                           void *call_data,
283                                           void *slot_data)
284 {
285     pa_sink *sink = (pa_sink *)call_data;
286     struct userdata *u = (struct userdata *)slot_data;
287
288     pa_assert(u);
289     pa_assert(sink);
290
291     return PA_HOOK_OK;
292 }
293
294 static pa_hook_result_t sink_port_available_changed(void *hook_data,
295                                                     void *call_data,
296                                                     void *slot_data)
297 {
298     pa_sink *sink = (pa_sink *)call_data;
299     struct userdata *u = (struct userdata *)slot_data;
300
301     pa_assert(u);
302     pa_assert(sink);
303
304     return PA_HOOK_OK;
305 }
306
307
308 static pa_hook_result_t source_put(void *hook_data,
309                                    void *call_data,
310                                    void *slot_data)
311 {
312     pa_source *source = (pa_source *)call_data;
313     struct userdata *u = (struct userdata *)slot_data;
314
315     pa_assert(u);
316     pa_assert(source);
317
318     pa_utils_new_stamp();
319     pa_discover_add_source(u, source);
320
321     return PA_HOOK_OK;
322 }
323
324
325 static pa_hook_result_t source_unlink(void *hook_data,
326                                       void *call_data,
327                                       void *slot_data)
328 {
329     pa_source *source = (pa_source *)call_data;
330     struct userdata *u = (struct userdata *)slot_data;
331
332     pa_assert(u);
333     pa_assert(source);
334
335     pa_discover_remove_source(u, source);
336
337     return PA_HOOK_OK;
338 }
339
340
341 static pa_hook_result_t source_port_changed(void *hook_data,
342                                             void *call_data,
343                                             void *slot_data)
344 {
345     pa_source *source = (pa_source *)call_data;
346     struct userdata *u = (struct userdata *)slot_data;
347
348     pa_assert(u);
349     pa_assert(source);
350
351     return PA_HOOK_OK;
352 }
353
354 static pa_hook_result_t source_port_available_changed(void *hook_data,
355                                                       void *call_data,
356                                                       void *slot_data)
357 {
358     pa_source *source = (pa_source *)call_data;
359     struct userdata *u = (struct userdata *)slot_data;
360
361     pa_assert(u);
362     pa_assert(source);
363
364     return PA_HOOK_OK;
365 }
366
367
368
369 static pa_hook_result_t sink_input_new(void *hook_data,
370                                        void *call_data,
371                                        void *slot_data)
372 {
373     pa_sink_input_new_data *data = (pa_sink_input_new_data *)call_data;
374     struct userdata *u = (struct userdata *)slot_data;
375
376     pa_assert(u);
377     pa_assert(data);
378
379     pa_utils_new_stamp();
380     pa_discover_preroute_sink_input(u, data);
381
382     return PA_HOOK_OK;
383 }
384
385 static pa_hook_result_t sink_input_put(void *hook_data,
386                                        void *call_data,
387                                        void *slot_data)
388 {
389     pa_sink_input *sinp = (pa_sink_input *)call_data;
390     struct userdata *u = (struct userdata *)slot_data;
391
392     pa_assert(u);
393     pa_assert(sinp);
394
395     pa_utils_new_stamp();
396     pa_discover_add_sink_input(u, sinp);
397
398     return PA_HOOK_OK;
399 }
400
401
402 static pa_hook_result_t sink_input_unlink(void *hook_data,
403                                           void *call_data,
404                                           void *slot_data)
405 {
406     struct pa_sink_input *sinp = (pa_sink_input *)call_data;
407     struct userdata *u = (struct userdata *)slot_data;
408
409     pa_assert(u);
410     pa_assert(sinp);
411
412     pa_discover_remove_sink_input(u, sinp);
413
414     return PA_HOOK_OK;
415 }
416
417
418 /*
419  * Local Variables:
420  * c-basic-offset: 4
421  * indent-tabs-mode: nil
422  * End:
423  *
424  */
425