2 * module-murphy-ivi -- PulseAudio module for providing audio routing support
3 * Copyright (c) 2012, Intel Corporation.
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.
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.
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,
24 #include <pulsecore/pulsecore-config.h>
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>
39 const char *media_role;
44 static int get_latency(const char *);
47 pa_loopback *pa_loopback_init(void)
49 pa_loopback *loopback = pa_xnew0(pa_loopback, 1);
55 void pa_loopback_done(pa_loopback *loopback, pa_core *core)
57 pa_loopnode *loop, *n;
59 PA_LLIST_FOREACH_SAFE(loop,n, loopback->loopnodes) {
60 pa_module_unload_by_index(core, loop->module_index, false);
66 pa_loopnode *pa_loopback_create(pa_loopback *loopback,
68 pa_loopback_type type,
70 uint32_t source_index,
72 const char *media_role,
73 uint32_t resource_priority,
74 uint32_t resource_set_flags,
75 uint32_t resource_audio_flags)
77 static char *modnam = "module-loopback";
83 pa_sink_input *sink_input;
84 pa_source_output *source_output;
89 pa_assert(media_role);
90 pa_assert(type == PA_LOOPBACK_SOURCE || type == PA_LOOPBACK_SINK);
92 if (!(source = pa_idxset_get_by_index(core->sources, source_index))) {
93 pa_log_debug("can't find source (index %u) for loopback",source_index);
97 if (!(sink = pa_idxset_get_by_index(core->sinks, sink_index))) {
98 pa_log_debug("can't find the primary sink (index %u) for loopback",
104 if (type == PA_LOOPBACK_SOURCE) {
105 snprintf(args, sizeof(args), "source=\"%s\" sink=\"%s\" "
107 "sink_input_properties=\"%s=%s %s=%u %s=%u %s=%u %s=%u\" "
108 "source_output_properties=\"%s=%s %s=%u\"",
109 source->name, sink->name,
110 get_latency(media_role),
111 PA_PROP_MEDIA_ROLE, media_role,
112 PA_PROP_NODE_INDEX, node_index,
113 PA_PROP_RESOURCE_PRIORITY, resource_priority,
114 PA_PROP_RESOURCE_SET_FLAGS, resource_set_flags,
115 PA_PROP_RESOURCE_AUDIO_FLAGS, resource_audio_flags,
116 PA_PROP_MEDIA_ROLE, media_role,
117 PA_PROP_NODE_INDEX, node_index);
120 snprintf(args, sizeof(args), "source=\"%s\" sink=\"%s\" "
122 "sink_input_properties=\"%s=%s %s=%u\" "
123 "source_output_properties=\"%s=%s %s=%u %s=%u %s=%u %s=%u\"",
124 source->name, sink->name,
125 get_latency(media_role),
126 PA_PROP_MEDIA_ROLE, media_role,
127 PA_PROP_NODE_INDEX, node_index,
128 PA_PROP_MEDIA_ROLE, media_role,
129 PA_PROP_NODE_INDEX, node_index,
130 PA_PROP_RESOURCE_PRIORITY, resource_priority,
131 PA_PROP_RESOURCE_SET_FLAGS, resource_set_flags,
132 PA_PROP_RESOURCE_AUDIO_FLAGS, resource_audio_flags);
135 pa_log_debug("loading %s %s", modnam, args);
137 if (!(module = pa_module_load(core, modnam, args))) {
138 pa_log("failed to load module '%s %s'. can't loopback", modnam, args);
142 PA_IDXSET_FOREACH(sink_input, core->sink_inputs, idx) {
143 if (sink_input->module == module)
147 PA_IDXSET_FOREACH(source_output, core->source_outputs, idx) {
148 if (source_output->module == module)
152 if (!sink_input || !source_output) {
154 pa_log("can't find output stream of loopback module (index %u)",
157 if (!source_output) {
158 pa_log("can't find input stream of loopback module (index %u)",
161 pa_module_unload(core, module, false);
165 pa_assert(sink_input->index != PA_IDXSET_INVALID);
166 pa_assert(source_output->index != PA_IDXSET_INVALID);
168 loop = pa_xnew0(pa_loopnode, 1);
169 loop->module_index = module->index;
170 loop->node_index = node_index;
171 loop->sink_input_index = sink_input->index;
172 loop->source_output_index = source_output->index;
174 PA_LLIST_PREPEND(pa_loopnode, loopback->loopnodes, loop);
176 pa_log_debug("loopback succesfully loaded. Module index %u",module->index);
182 void pa_loopback_destroy(pa_loopback *loopback,
190 PA_LLIST_REMOVE(pa_loopnode, loopback->loopnodes, loop);
191 pa_module_unload_by_index(core, loop->module_index, false);
196 uint32_t pa_loopback_get_sink_index(pa_core *core, pa_loopnode *loop)
198 pa_sink_input *sink_input;
204 sink_input = pa_idxset_get_by_index(core->sink_inputs,
205 loop->sink_input_index);
207 if (sink_input && (sink = sink_input->sink))
210 return PA_IDXSET_INVALID;
213 int pa_loopback_print(pa_loopnode *loop, char *buf, int len)
223 p += snprintf(p, e-p, "<not set>");
225 p += snprintf(p, e-p, "module %u, sink_input %u",
226 loop->module_index, loop->sink_input_index);
232 static int get_latency(const char *media_role)
234 static latency_def latencies[] = {
242 pa_assert(media_role);
244 for (l = latencies; l->media_role; l++) {
245 if (pa_streq(media_role, l->media_role))
256 * indent-tabs-mode: nil