routing: add loopback support to nodes
[profile/ivi/pulseaudio-module-murphy-ivi.git] / murphy / loopback.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 <strings.h>
23
24 #include <pulsecore/pulsecore-config.h>
25
26 #include <pulse/def.h>
27 #include <pulsecore/thread.h>
28 #include <pulsecore/strlist.h>
29 #include <pulsecore/time-smoother.h>
30 #include <pulsecore/sink.h>
31 #include <pulsecore/sink-input.h>
32
33 #include <combine/userdata.h>
34
35 #include "loopback.h"
36 #include "utils.h"
37
38
39 pa_loopback *pa_loopback_init(void)
40 {
41     pa_loopback *loopback = pa_xnew0(pa_loopback, 1);
42
43     return loopback;
44 }
45
46
47 void pa_loopback_done(pa_loopback *loopback, pa_core *core)
48 {
49     pa_loopnode *loop, *n;
50
51     PA_LLIST_FOREACH_SAFE(loop,n, loopback->loopnodes) {
52         pa_module_unload_by_index(core, loop->module_index, FALSE);
53     }
54 }
55
56
57
58 pa_loopnode *pa_loopback_create(pa_loopback   *loopback,
59                                 pa_core       *core,
60                                 uint32_t       source_index,
61                                 uint32_t       sink_index)
62 {
63     static char *modnam = "module-loopback";
64
65     pa_loopnode     *loop;
66     pa_source       *source;
67     pa_sink         *sink;
68     pa_module       *module;
69     pa_sink_input   *sink_input;
70     char             args[512];
71     uint32_t         idx;
72
73     pa_assert(core);
74
75     if (!(source = pa_idxset_get_by_index(core->sources, source_index))) {
76         pa_log_debug("can't find source (index %u) for loopback",source_index);
77         return NULL;
78     }
79
80     if (!(sink = pa_idxset_get_by_index(core->sinks, sink_index))) {
81         pa_log_debug("can't find the primary sink (index %u) for loopback",
82                      sink_index);
83         return NULL;
84     }
85
86     snprintf(args, sizeof(args), "source=\"%s\" sink=\"%s\"",
87              source->name, sink->name);
88
89     if (!(module = pa_module_load(core, modnam, args))) {
90         pa_log("failed to load module '%s %s'. can't loopback", modnam, args);
91         return NULL;
92     }
93
94     PA_IDXSET_FOREACH(sink_input, core->sink_inputs, idx) {
95         if (sink_input->module == module)
96             break;
97     }
98
99     if (!sink_input) {
100         pa_log("can't find output stream of loopback module (index %u)",
101                module->index);
102         pa_module_unload(core, module, FALSE);
103         return NULL;
104     }
105
106     pa_assert(sink_input->index != PA_IDXSET_INVALID);
107
108     loop = pa_xnew0(pa_loopnode, 1);
109     loop->module_index = module->index;
110     loop->sink_input_index = sink_input->index;
111
112     PA_LLIST_PREPEND(pa_loopnode, loopback->loopnodes, loop);
113
114     pa_log_debug("loopback succesfully loaded. Module index %u",module->index);
115
116     return loop;
117 }
118
119
120 void pa_loopback_destroy(pa_loopback *loopback,
121                          pa_core     *core,
122                          pa_loopnode *loop)
123 {
124     pa_assert(loopback);
125     pa_assert(core);
126
127     if (loop) {
128         PA_LLIST_REMOVE(pa_loopnode, loopback->loopnodes, loop);
129         pa_module_unload_by_index(core, loop->module_index, FALSE);
130         pa_xfree(loop);
131     }
132 }
133
134
135
136 int pa_loopback_print(pa_loopnode *loop, char *buf, int len)
137 {
138     char *p, *e;
139
140     pa_assert(buf);
141     pa_assert(len > 0);
142
143     e = (p = buf) + len;
144
145     if (!loop)
146         p += snprintf(p, e-p, "<not set>");
147     else {
148         p += snprintf(p, e-p, "module %u, sink_input %u",
149                       loop->module_index, loop->sink_input_index);
150     }
151     
152     return p - buf;
153 }
154
155
156 /*
157  * Local Variables:
158  * c-basic-offset: 4
159  * indent-tabs-mode: nil
160  * End:
161  *
162  */
163