calssification: more heuristics to guess bluetooth device classes
[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 struct userdata;
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                                 const char    *media_role)
63 {
64     static char *modnam = "module-loopback";
65
66     pa_loopnode     *loop;
67     pa_source       *source;
68     pa_sink         *sink;
69     pa_module       *module;
70     pa_sink_input   *sink_input;
71     char             args[512];
72     uint32_t         idx;
73
74     pa_assert(core);
75
76     if (!(source = pa_idxset_get_by_index(core->sources, source_index))) {
77         pa_log_debug("can't find source (index %u) for loopback",source_index);
78         return NULL;
79     }
80
81     if (!(sink = pa_idxset_get_by_index(core->sinks, sink_index))) {
82         pa_log_debug("can't find the primary sink (index %u) for loopback",
83                      sink_index);
84         return NULL;
85     }
86
87     if (!media_role)
88         media_role = "music";
89
90     snprintf(args, sizeof(args), "source=\"%s\" sink=\"%s\" "
91              "sink_input_properties=%s=\"%s\"",
92              source->name, sink->name,
93              PA_PROP_MEDIA_ROLE, media_role);
94
95     pa_log_debug("loading %s %s", modnam, args);
96
97     if (!(module = pa_module_load(core, modnam, args))) {
98         pa_log("failed to load module '%s %s'. can't loopback", modnam, args);
99         return NULL;
100     }
101
102     PA_IDXSET_FOREACH(sink_input, core->sink_inputs, idx) {
103         if (sink_input->module == module)
104             break;
105     }
106
107     if (!sink_input) {
108         pa_log("can't find output stream of loopback module (index %u)",
109                module->index);
110         pa_module_unload(core, module, FALSE);
111         return NULL;
112     }
113
114     pa_assert(sink_input->index != PA_IDXSET_INVALID);
115
116     loop = pa_xnew0(pa_loopnode, 1);
117     loop->module_index = module->index;
118     loop->sink_input_index = sink_input->index;
119
120     PA_LLIST_PREPEND(pa_loopnode, loopback->loopnodes, loop);
121
122     pa_log_debug("loopback succesfully loaded. Module index %u",module->index);
123
124     return loop;
125 }
126
127
128 void pa_loopback_destroy(pa_loopback *loopback,
129                          pa_core     *core,
130                          pa_loopnode *loop)
131 {
132     pa_assert(loopback);
133     pa_assert(core);
134
135     if (loop) {
136         PA_LLIST_REMOVE(pa_loopnode, loopback->loopnodes, loop);
137         pa_module_unload_by_index(core, loop->module_index, FALSE);
138         pa_xfree(loop);
139     }
140 }
141
142 uint32_t pa_loopback_get_sink_index(pa_core *core, pa_loopnode *loop)
143 {
144     pa_sink_input *sink_input;
145     pa_sink *sink;
146
147     pa_assert(core);
148     pa_assert(loop);
149
150     sink_input = pa_idxset_get_by_index(core->sink_inputs,
151                                         loop->sink_input_index);
152
153     if (sink_input && (sink = sink_input->sink))
154         return sink->index;
155
156     return PA_IDXSET_INVALID;
157 }
158
159 int pa_loopback_print(pa_loopnode *loop, char *buf, int len)
160 {
161     char *p, *e;
162
163     pa_assert(buf);
164     pa_assert(len > 0);
165
166     e = (p = buf) + len;
167
168     if (!loop)
169         p += snprintf(p, e-p, "<not set>");
170     else {
171         p += snprintf(p, e-p, "module %u, sink_input %u",
172                       loop->module_index, loop->sink_input_index);
173     }
174     
175     return p - buf;
176 }
177
178
179 /*
180  * Local Variables:
181  * c-basic-offset: 4
182  * indent-tabs-mode: nil
183  * End:
184  *
185  */
186