murphyif: Free the connect timer when unloading
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / switch.c
1 /*
2  * module-murphy-ivi -- PulseAudio module for providing audio routing support
3  * Copyright (c) 2012, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU Lesser General Public License,
7  * version 2.1, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.
12  * See the GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin St - Fifth Floor, Boston,
17  * MA 02110-1301 USA.
18  *
19  */
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <errno.h>
24
25 #include <pulsecore/pulsecore-config.h>
26 #include <pulsecore/core-util.h>
27 #include <pulsecore/namereg.h>
28
29 #include <pulsecore/card.h>
30 #include <pulsecore/sink.h>
31 #include <pulsecore/device-port.h>
32 #include <pulsecore/source.h>
33 #include <pulsecore/sink-input.h>
34 #include <pulsecore/source-output.h>
35
36 #include "switch.h"
37 #include "node.h"
38 #include "multiplex.h"
39 #include "loopback.h"
40 #include "discover.h"
41 #include "utils.h"
42 #include "classify.h"
43
44 static bool setup_explicit_stream2dev_link(struct userdata *,
45                                                 mir_node *,
46                                                 mir_node *);
47 static bool teardown_explicit_stream2dev_link(struct userdata*, mir_node*,
48                                                    mir_node *);
49
50 static bool setup_default_dev2stream_link(struct userdata *, mir_node *,
51                                                mir_node *);
52 static bool setup_default_stream2dev_link(struct userdata *, mir_node *,
53                                                mir_node *);
54 static bool setup_default_dev2dev_link(struct userdata *,
55                                             mir_node *,
56                                             mir_node *);
57
58 static pa_source *setup_device_input(struct userdata *, mir_node *);
59 static pa_sink   *setup_device_output(struct userdata *, mir_node *);
60
61 static bool set_profile(struct userdata *, mir_node *);
62 static bool set_port(struct userdata *, mir_node *);
63
64
65 bool mir_switch_setup_link(struct userdata *u,
66                                 mir_node *from,
67                                 mir_node *to,
68                                 bool explicit)
69 {
70     pa_core *core;
71
72     pa_assert(u);
73     pa_assert_se((core = u->core));
74     pa_assert(!from || from->direction == mir_input);
75     pa_assert(!to || to->direction == mir_output);
76
77     if (explicit) {
78         /*
79          * links for explic routes
80          */
81         pa_assert(from);
82         pa_assert(to);
83
84         switch (from->implement) {
85
86         case mir_stream:
87             switch (to->implement) {
88
89             case mir_stream:
90                 pa_log_debug("routing to streams is not implemented yet");
91                 break;
92
93             case mir_device:
94                 if (!setup_explicit_stream2dev_link(u, from, to))
95                     return false;
96                 break;
97
98             default:
99                 pa_log("%s: can't setup link: invalid sink node "
100                        "implement", __FILE__);
101                 return false;
102             }
103             break;
104
105         case mir_device:
106             pa_log_debug("input device routing is not implemented yet");
107             break;
108
109         default:
110             pa_log("%s: can't setup link: invalid source node "
111                    "implement", __FILE__);
112             return false;
113         }
114     }
115     else {
116         /*
117          * links for default routes
118          */
119         pa_assert(from || to);
120
121         if (to) {
122             /* default input route */
123             switch (to->implement) {
124
125             case mir_stream:
126                 pa_assert(from);
127                 
128                 switch (from->implement) {
129                 case mir_stream:
130                     pa_log_debug("routing between streams is not implemented");
131                     break;
132
133                 case mir_device:
134                     if (!setup_default_dev2stream_link(u, from, to))
135                         return false;
136                     break;
137
138                 default:
139                     pa_log("%s: can't setup link: invalid source node "
140                            "implement", __FILE__);
141                     return false;
142                 }
143                 break;
144
145             case mir_device:
146                 if (!from)
147                     /* default output preroute */
148                     return setup_device_output(u, to) != NULL;
149                 else {
150                     switch (from->implement) {
151
152                     case mir_stream:
153                         if (!setup_default_stream2dev_link(u, from, to))
154                             return false;
155                         break;
156
157                     case mir_device:
158                         if (!setup_default_dev2dev_link(u, from, to))
159                             return false;
160                         break;
161
162                     default:
163                         pa_log("%s: can't setup link: invalid source node "
164                                "implement", __FILE__);
165                         return false;
166                     }
167                 }
168                 break;
169
170             default:
171                 pa_log("%s: can't setup link: invalid sink node "
172                        "implement", __FILE__);
173                 return false;
174             }
175         }
176         else {
177             /* default input preroute */
178             pa_assert(from && from->implement == mir_device);
179             
180             return setup_device_input(u, from) != NULL;
181         }
182     }
183
184     pa_log_debug("link %s => %s is established", from->amname, to->amname);
185
186     return true;
187 }
188
189 bool mir_switch_teardown_link(struct userdata *u,
190                                    mir_node        *from,
191                                    mir_node        *to)
192 {
193     pa_core *core;
194
195     pa_assert(u);
196     pa_assert(from);
197     pa_assert(to);
198     pa_assert_se((core = u->core));
199     pa_assert(from->direction == mir_input);
200     pa_assert(to->direction == mir_output);
201
202
203     switch (from->implement) {
204
205     case mir_stream:
206         switch (to->implement) {
207             
208         case mir_stream: /* stream -> stream */
209             pa_log_debug("routing to streams is not implemented yet");
210             break;
211             
212         case mir_device: /* stream -> device */
213             if (!teardown_explicit_stream2dev_link(u, from, to))
214                 return false;
215             break;
216             
217         default:
218             pa_log("%s: can't teardown link: invalid sink node "
219                    "implement", __FILE__);
220             return false;
221         }
222         break;
223         
224     case mir_device: /* device -> stream | device->device */
225         pa_log_debug("input device routing is not implemented yet");
226         break;
227         
228     default:
229         pa_log("%s: can't teardown link: invalid source node "
230                "implement", __FILE__);
231         return false;
232     }
233
234     pa_log_debug("link %s => %s is torn down", from->amname, to->amname);
235
236     return true;
237 }
238
239 static bool setup_explicit_stream2dev_link(struct userdata *u,
240                                                 mir_node *from,
241                                                 mir_node *to)
242 {
243     pa_core       *core;
244     pa_sink       *sink;
245     pa_sink_input *sinp;
246     pa_muxnode    *mux;
247
248     pa_assert(u);
249     pa_assert(from);
250     pa_assert(to);
251     pa_assert((core = u->core));
252
253     if (!(sink = setup_device_output(u, to)))
254         return false;
255
256     if (!set_profile(u, from) || !set_port(u, from)) {
257         pa_log("can't route from '%s'", from->amname);
258         return false;
259     }
260
261     if ((mux = from->mux)) {
262         sinp = pa_idxset_get_by_index(core->sink_inputs, mux->defstream_index);
263
264         if (sinp && sinp->sink == sink) {
265             if (!pa_multiplex_remove_default_route(core, mux, true))
266                 return false;
267         }
268         else if (pa_multiplex_duplicate_route(core, mux, NULL, sink)) {
269             pa_log_debug("multiplex route %s => %s already exists",
270                          from->amname, to->amname);
271             return true;
272         }
273         else {
274             if (!pa_multiplex_add_explicit_route(core, mux, sink, from->type))
275                 return false;
276         }
277     }
278     else {
279         if ((sinp = pa_idxset_get_by_index(core->sink_inputs, from->paidx))) {
280             if (sinp->sink == sink)
281                 pa_log_debug("direct route already exists. nothing to do");
282             else {
283                 pa_log_debug("direct route: sink-input.%u -> sink.%u",
284                              sinp->index, sink->index);
285
286                 if (pa_sink_input_move_to(sinp, sink, false) < 0)
287                     return false;
288             }
289         }
290     }
291
292     pa_log_debug("link %s => %s is established", from->amname, to->amname);
293
294     return true;
295 }
296
297
298 static bool teardown_explicit_stream2dev_link(struct userdata *u,
299                                                    mir_node *from,
300                                                    mir_node *to)
301 {
302     pa_core       *core;
303     pa_sink       *sink;
304     pa_sink_input *sinp;
305     pa_muxnode    *mux;
306
307     pa_assert(u);
308     pa_assert(from);
309     pa_assert(to);
310     pa_assert((core = u->core));
311
312     if ((mux = from->mux)) {
313         if (!(sink = pa_idxset_get_by_index(core->sinks, to->paidx))) {
314             pa_log_debug("can't find sink.%u", to->paidx);
315             return false;
316         }
317
318         if (!pa_multiplex_remove_explicit_route(core, mux, sink)) {
319             pa_log_debug("can't remove multiplex route on mux %u", mux->module_index);
320             return false;
321         }
322     }
323     else {
324         if (!(sinp = pa_idxset_get_by_index(core->sink_inputs, from->paidx))) {
325             pa_log_debug("can't find source.%u", from->paidx);
326             return false;
327         }
328
329         if (!(sink = pa_utils_get_null_sink(u))) {
330             pa_log_debug("can't remove direct route: no null sink");
331             return false;
332         }
333
334         if (pa_sink_input_move_to(sinp, sink, false) < 0)
335             return false;
336     }
337
338     pa_log_debug("link %s => %s is torn down", from->amname, to->amname);
339
340     return true;
341 }
342
343
344 static bool setup_default_dev2stream_link(struct userdata *u,
345                                                mir_node *from,
346                                                mir_node *to)
347 {
348     pa_core          *core;
349     pa_source        *source;
350     pa_source_output *sout;
351
352     pa_assert(u);
353     pa_assert(from);
354     pa_assert(to);
355     pa_assert((core = u->core));
356
357     if (!(source = setup_device_input(u, from))) {
358         pa_log_debug("can't route '%s': no source", from->amname);
359         return false;
360     }
361
362     if (to->paidx == PA_IDXSET_INVALID) {
363         pa_log_debug("can't route '%s': no source-output", to->amname);
364         return false;
365     }
366
367     if (!(sout = pa_idxset_get_by_index(core->source_outputs, to->paidx))) {
368         pa_log_debug("can't find sink input for '%s'", to->amname);
369         return false;
370     }
371
372     pa_log_debug("direct route: source.%d -> source->output.%d",
373                  source->index, sout->index);
374
375     if (pa_source_output_move_to(sout, source, false) < 0)
376         return false;
377
378     return true;
379 }
380
381 static bool setup_default_stream2dev_link(struct userdata *u,
382                                                mir_node *from,
383                                                mir_node *to)
384 {
385     pa_core       *core;
386     pa_sink       *sink;
387     pa_sink_input *sinp;
388     pa_muxnode    *mux;
389     int            n;
390
391     pa_assert(u);
392     pa_assert(from);
393     pa_assert(to);
394     pa_assert((core = u->core));
395
396     if (!(sink = setup_device_output(u, to)))
397         return false;
398
399     if (!set_profile(u, from) || !set_port(u, from)) {
400         pa_log("can't route from '%s'", from->amname);
401         return false;
402     }
403
404     if ((mux = from->mux)) {
405         if (mux->defstream_index == PA_IDXSET_INVALID) {
406             if ((n = pa_multiplex_no_of_routes(core, mux)) < 0)
407                 return false;
408             else if (n > 0) {
409                 pa_log_debug("currently mux %u has no default route",
410                              mux->module_index);
411                 return true;
412             }
413             sinp = NULL;
414         }
415         else {
416             sinp = pa_idxset_get_by_index(core->sink_inputs,
417                                           mux->defstream_index);
418         }
419
420         if (!sinp) {
421             /*
422              * we supposed to have a default stream but the sink-input
423              * on the combine side is not existing any more. This can
424              * happen, for instance, if the sink, where it was connected,
425              * died for some reason.
426              */
427             pa_log_debug("supposed to have a default stream on multiplex "
428                          "%u but non was found. Trying to make one",
429                          mux->module_index);
430             if (pa_multiplex_duplicate_route(core, mux, sinp, sink)) {
431                 pa_log_debug("the default stream on mux %u would be a "
432                              "duplicate to an explicit route. "
433                              "Removing it ...", mux->module_index);
434                 mux->defstream_index = PA_IDXSET_INVALID;
435                 return true; /* the routing is a success */
436             }
437
438             if (!pa_multiplex_add_default_route(core, mux,sink, from->type)) {
439                 pa_log_debug("failed to add default route on mux %d",
440                              mux->module_index);
441                 mux->defstream_index = PA_IDXSET_INVALID;
442                 return false;
443             }
444         }
445         else if (pa_multiplex_duplicate_route(core, mux, sinp, sink)) {
446             pa_log_debug("the default stream on mux %u would be a duplicate "
447                          "to an explicit route. Removing it ...",
448                          mux->module_index);
449             return true;        /* the routing is a success */
450         }
451             
452         if (sinp) {
453             pa_log_debug("multiplex route: sink-input.%d -> (sink.%d - "
454                          "sink-input.%d) -> sink.%d", from->paidx,
455                          mux->sink_index, sinp->index, sink->index);
456         }
457         else {
458             pa_log_debug("multiplex route: sink-input.%d -> (sink.%d - "
459                          "sink-input) -> sink.%d", from->paidx,
460                          mux->sink_index, sink->index);
461         }
462
463         if (!pa_multiplex_change_default_route(core, mux, sink))
464             return false;
465     }
466     else {
467         if (from->paidx == PA_IDXSET_INVALID) {
468             pa_log_debug("can't route '%s': no sink-input", to->amname);
469             return false;
470         }
471
472         if (!(sinp = pa_idxset_get_by_index(core->sink_inputs, from->paidx))) {
473             pa_log_debug("can't find sink input for '%s'", from->amname);
474             return false;
475         }
476
477         pa_log_debug("direct route: sink-input.%d -> sink.%d",
478                      sinp->index, sink->index);
479
480         if (pa_sink_input_move_to(sinp, sink, false) < 0)
481             return false;
482     }
483
484     return true;
485 }
486
487 static bool setup_default_dev2dev_link(struct userdata *u,
488                                             mir_node *from,
489                                             mir_node *to)
490 {
491     pa_core       *core;
492     pa_sink       *sink;
493     pa_sink_input *sinp;
494     pa_muxnode    *mux;
495     pa_loopnode   *loop;
496     mir_node_type  type;
497     int            n;
498
499     pa_assert(u);
500     pa_assert(from);
501     pa_assert(to);
502     pa_assert((core = u->core));
503
504     if (!(loop = from->loop)) {
505         pa_log_debug("source is not looped back");
506         return false;
507     }
508
509     if (!(sink = setup_device_output(u, to)))
510         return false;
511
512     if ((mux = from->mux)) {
513         if (mux->defstream_index == PA_IDXSET_INVALID) {
514             if ((n = pa_multiplex_no_of_routes(core, mux)) < 0)
515                 return false;
516             else if (n > 0) {
517                 pa_log_debug("currently mux %u has no default route",
518                              mux->module_index);
519                 return true;
520             }
521             sinp = NULL;
522         }
523         else {
524             sinp = pa_idxset_get_by_index(core->sink_inputs,
525                                           mux->defstream_index);
526         }
527
528         if (!sinp) {
529             /*
530              * we supposed to have a default stream but the sink-input
531              * on the combine side is not existing any more. This can
532              * happen, for instance, if the sink, where it was connected,
533              * died for some reason.
534              */
535             pa_log_debug("supposed to have a default stream on multiplex "
536                          "%u but non was found. Trying to make one",
537                          mux->module_index);
538             if (pa_multiplex_duplicate_route(core, mux, sinp, sink)) {
539                 pa_log_debug("the default stream on mux %u would be a "
540                              "duplicate to an explicit route. "
541                              "Removing it ...", mux->module_index);
542                 mux->defstream_index = PA_IDXSET_INVALID;
543                 return true; /* the routing is a success */
544             }
545
546             type = pa_classify_guess_application_class(from);
547
548             if (!pa_multiplex_add_default_route(core, mux,sink, type)) {
549                 pa_log_debug("failed to add default route on mux %d",
550                              mux->module_index);
551                 mux->defstream_index = PA_IDXSET_INVALID;
552                 return false;
553             }
554         }
555         else if (pa_multiplex_duplicate_route(core, mux, sinp, sink)) {
556             pa_log_debug("the default stream on mux %u would be a duplicate "
557                          "to an explicit route. Removing it ...",
558                          mux->module_index);
559             return true;        /* the routing is a success */
560         }
561             
562         if (sinp) {
563             pa_log_debug("multiplex route: source.%d -> "
564                          "(source-output - sink-input %d) -> (sink.%d - "
565                          "sink-input.%d) -> sink.%d", from->paidx,
566                          loop->sink_input_index,
567                          mux->sink_index, sinp->index, sink->index);
568         }
569         else {
570             pa_log_debug("multiplex route: source.%d -> "
571                          "(source-output - sink-input.%d) -> (sink.%d - "
572                          "sink-input) -> sink.%d", from->paidx,
573                          loop->sink_input_index, 
574                          mux->sink_index, sink->index);
575         }
576
577         if (!pa_multiplex_change_default_route(core, mux, sink))
578             return false;
579     }
580     else {
581         sinp = pa_idxset_get_by_index(core->sink_inputs,
582                                       loop->sink_input_index);
583
584         if (!sinp) {
585             pa_log_debug("can't find looped back sink input for '%s'",
586                          from->amname);
587             return false;
588         }
589
590         pa_log_debug("loopback route: source.%d -> (source-output - "
591                      "sink-input.%d) -> sink.%d",
592                      from->paidx, sinp->index, sink->index);
593
594         if (pa_sink_input_move_to(sinp, sink, false) < 0)
595             return false;
596     }
597
598     return true;
599 }
600
601 static pa_source *setup_device_input(struct userdata *u, mir_node *node)
602 {
603     pa_core *core;
604     pa_source *source;
605     
606     pa_assert(u);
607     pa_assert(node);
608     pa_assert_se((core = u->core));
609
610     if (!set_profile(u, node) || !set_port(u, node)) {
611         pa_log("can't route to '%s'", node->amname);
612         return NULL;
613     }
614
615     if (node->paidx == PA_IDXSET_INVALID) {
616         pa_log_debug("can't route to '%s': no source", node->amname);
617         return NULL;
618     }
619
620     if (!(source = pa_idxset_get_by_index(core->sources, node->paidx))) {
621         pa_log_debug("can't route to '%s': cant find source", node->amname);
622         return NULL;
623     }
624
625     return source;
626 }
627
628
629 static pa_sink *setup_device_output(struct userdata *u, mir_node *node)
630 {
631     pa_core *core;
632     pa_sink *sink;
633
634     pa_assert(u);
635     pa_assert(node);
636     pa_assert_se((core = u->core));
637
638     if (!set_profile(u, node) || !set_port(u, node)) {
639         pa_log("can't route to '%s'", node->amname);
640         return NULL;
641     }
642
643     if (node->paidx == PA_IDXSET_INVALID) {
644         pa_log_debug("can't route to '%s': no sink", node->amname);
645         return NULL;
646     }
647
648     if (!(sink = pa_idxset_get_by_index(core->sinks, node->paidx))) {
649         pa_log_debug("can't route to '%s': cant find sink", node->amname);
650         return NULL;
651     }
652
653     return sink;
654 }
655
656
657 static bool set_profile(struct userdata *u, mir_node *node)
658 {
659     pa_core         *core;
660     pa_card         *card;
661     pa_card_profile *prof;
662
663     pa_assert(u);
664     pa_assert(node);
665     pa_assert_se((core = u->core));
666
667     if (node->implement != mir_device)
668         return true;
669
670     if (node->type == mir_bluetooth_a2dp ||
671         node->type == mir_bluetooth_sco)
672     {
673         card = pa_idxset_get_by_index(core->cards, node->pacard.index);
674
675         if (!card) {
676             pa_log("can't find card for '%s'", node->amname);
677             return false;
678         }
679
680         pa_assert_se(prof = card->active_profile);
681     
682         if (!pa_streq(node->pacard.profile, prof->name)) {
683             pa_log_debug("changing profile '%s' => '%s'",
684                          prof->name, node->pacard.profile);
685
686             if (u->state.profile) {
687                 pa_log("nested profile setting is not allowed. won't change "
688                        "'%s' => '%s'", prof->name, node->pacard.profile);
689                 return false;
690             }
691
692             u->state.profile = node->pacard.profile;
693
694             if ((prof = pa_hashmap_get(card->profiles, node->pacard.profile)) != NULL)
695                 pa_card_set_profile(card, prof, false);
696
697             u->state.profile = NULL;            
698         }
699     }
700
701     return true;
702 }
703
704
705
706 static bool set_port(struct userdata *u, mir_node *node)
707 {
708     pa_core   *core;
709     pa_sink   *sink;
710     pa_source *source;
711     pa_device_port *port;
712     mir_node  *oldnode;
713     void      *data  = NULL;
714     uint32_t   paidx = PA_IDXSET_INVALID;
715
716     pa_assert(u);
717     pa_assert(node);
718     pa_assert(node->paname);
719     pa_assert_se((core = u->core));
720
721     if (node->direction != mir_input && node->direction != mir_output)
722         return false;
723
724     if (node->implement != mir_device)
725         return true;
726
727     if (!node->paport)
728         return true;
729
730     if (node->direction == mir_input) {
731         source = pa_namereg_get(core, node->paname, PA_NAMEREG_SOURCE);
732         
733         if (!(data = source)) {
734             pa_log("can't set port for '%s': source not found",
735                    node->paname);
736             return false;
737         }
738         
739         if ((port = source->active_port) && pa_streq(node->paport, port->name))
740             return true;
741
742         if (pa_source_set_port(source, node->paport, false) < 0)
743             return false;
744
745         paidx = source->index;
746     }
747
748     if (node->direction == mir_output) {
749         sink = pa_namereg_get(core, node->paname, PA_NAMEREG_SINK);
750         
751         if (!(data = sink)) {
752             pa_log("can't set port for '%s': sink not found",
753                    node->paname);
754             return false;
755         }
756
757         if ((port = sink->active_port) && pa_streq(node->paport, port->name))
758             return true;
759
760         if (pa_sink_set_port(sink, node->paport, false) < 0)
761             return false;
762
763         paidx = sink->index;
764     }
765
766     if ((oldnode = pa_discover_remove_node_from_ptr_hash(u, data)))
767         oldnode->paidx = PA_IDXSET_INVALID;
768
769     node->paidx = paidx;
770     pa_discover_add_node_to_ptr_hash(u, data, node);
771
772
773     return true;
774 }
775
776
777
778 /*
779  * Local Variables:
780  * c-basic-offset: 4
781  * indent-tabs-mode: nil
782  * End:
783  *
784  */