5 #include <pulsecore/pulsecore-config.h>
8 #include <pulsecore/thread.h>
9 #include <pulsecore/strlist.h>
10 #include <pulsecore/time-smoother.h>
11 #include <pulsecore/sink.h>
12 #include <pulsecore/sink-input.h>
14 #include <combine/userdata.h>
16 #include "multiplex.h"
19 #ifndef DEFAULT_RESAMPLER
20 #define DEFAULT_RESAMPLER "speex-float-3"
24 pa_multiplex *pa_multiplex_init(void)
26 pa_multiplex *multiplex = pa_xnew0(pa_multiplex, 1);
32 void pa_multiplex_done(pa_multiplex *multiplex, pa_core *core)
36 PA_LLIST_FOREACH_SAFE(mux,n, multiplex->muxnodes) {
37 pa_module_unload_by_index(core, mux->module_index, FALSE);
43 pa_muxnode *pa_multiplex_create(pa_multiplex *multiplex,
46 pa_channel_map *chmap,
47 const char *resampler,
50 static char *modnam = "module-combine-sink";
52 struct userdata *u; /* combine's userdata! */
64 resampler = DEFAULT_RESAMPLER;
66 if (!(sink = pa_idxset_get_by_index(core->sinks, sink_index))) {
67 pa_log_debug("can't find the primary sink (index %u) for multiplexer",
72 snprintf(args, sizeof(args), "slaves=\"%s\" resample_method=\"%s\" "
73 "channels=%u", sink->name, resampler, chmap->channels);
75 if (!(module = pa_module_load(core, modnam, args))) {
76 pa_log("failed to load module '%s %s'. can't multiplex", modnam, args);
80 pa_assert_se((u = module->userdata));
83 u->no_reattach = TRUE;
85 mux = pa_xnew0(pa_muxnode, 1);
86 mux->module_index = module->index;
87 mux->sink_index = u->sink->index;
88 mux->defstream_index = PA_IDXSET_INVALID;
90 PA_LLIST_PREPEND(pa_muxnode, multiplex->muxnodes, mux);
92 if (!(o = pa_idxset_first(u->outputs, &idx)))
93 pa_log("can't find default multiplexer stream");
95 if ((sinp = o->sink_input)) {
96 pa_utils_set_stream_routing_properties(sinp->proplist, type, NULL);
97 mux->defstream_index = sinp->index;
101 pa_log_debug("multiplexer succesfully loaded");
107 void pa_multiplex_destroy(pa_multiplex *multiplex,
111 pa_assert(multiplex);
115 PA_LLIST_REMOVE(pa_muxnode, multiplex->muxnodes, mux);
116 pa_module_unload_by_index(core, mux->module_index, FALSE);
122 pa_muxnode *pa_multiplex_find(pa_multiplex *multiplex, uint32_t sink_index)
126 PA_LLIST_FOREACH(mux, multiplex->muxnodes) {
127 if (sink_index == mux->sink_index) {
128 pa_log_debug("muxnode found for sink %u", sink_index);
133 pa_log_debug("can't find muxnode for sink %u", sink_index);
139 pa_bool_t pa_multiplex_add_default_route(pa_core *core,
146 struct userdata *u; /* combine's userdata! */
152 if (!(module = pa_idxset_get_by_index(core->modules, mux->module_index)))
153 pa_log("module %u is gone", mux->module_index);
155 pa_assert_se((u = module->userdata));
157 if (sink == u->sink) {
158 pa_log("%s: mux %d refuses to make a loopback to itself",
159 __FILE__, mux->module_index);
162 pa_log_debug("adding default route to mux %u", mux->module_index);
164 if (!(sinp = u->add_slave(u, sink))) {
165 pa_log("failed to add new slave to mux %u", mux->module_index);
169 pa_utils_set_stream_routing_properties(sinp->proplist, type, NULL);
170 mux->defstream_index = sinp->index;
179 pa_bool_t pa_multiplex_remove_default_route(pa_core *core,
181 pa_bool_t transfer_to_explicit)
186 struct userdata *u; /* combine's userdata! */
191 if (!(module = pa_idxset_get_by_index(core->modules, mux->module_index)))
192 pa_log("module %u is gone", mux->module_index);
193 else if ((idx = mux->defstream_index) == PA_IDXSET_INVALID)
194 pa_log_debug("mux %u do not have default stream", mux->module_index);
195 else if (!(sinp = pa_idxset_get_by_index(core->sink_inputs, idx)))
196 pa_log("can't remove default route: sink-input %u is gone", idx);
198 pa_assert_se((u = module->userdata));
199 mux->defstream_index = PA_IDXSET_INVALID;
201 if (transfer_to_explicit) {
202 pa_log_debug("converting default route sink-input.%u -> sink.%u "
203 "to explicit", sinp->index, sinp->sink->index);
204 pa_utils_set_stream_routing_method_property(sinp->proplist, TRUE);
208 u->remove_slave(u, sinp, NULL);
215 pa_bool_t pa_multiplex_change_default_route(pa_core *core,
222 struct userdata *u; /* combine's userdata! */
228 if (!(module = pa_idxset_get_by_index(core->modules, mux->module_index)))
229 pa_log("module %u is gone", mux->module_index);
230 else if ((idx = mux->defstream_index) == PA_IDXSET_INVALID)
231 pa_log_debug("mux %u do not have default stream", mux->module_index);
232 else if (!(sinp = pa_idxset_get_by_index(core->sink_inputs, idx)))
233 pa_log("can't remove default route: sink-input %u is gone", idx);
235 pa_assert_se((u = module->userdata));
236 if (!u->move_slave(u, sinp, sink))
237 pa_log_debug("failed to move default stream on mux %u", mux->module_index);
239 pa_log_debug("default stream was successfully moved on mux %u",
249 pa_bool_t pa_multiplex_add_explicit_route(pa_core *core,
256 struct userdata *u; /* combine's userdata! */
262 if (!(module = pa_idxset_get_by_index(core->modules, mux->module_index)))
263 pa_log("module %u is gone", mux->module_index);
265 pa_assert_se((u = module->userdata));
267 if (sink == u->sink) {
268 pa_log("%s: mux %d refuses to make a loopback to itself",
269 __FILE__, mux->module_index);
272 pa_log_debug("adding explicit route to mux %u", mux->module_index);
274 if (!(sinp = u->add_slave(u, sink))) {
275 pa_log("failed to add new slave to mux %u", mux->module_index);
279 pa_utils_set_stream_routing_properties(sinp->proplist, type, sink);
289 pa_bool_t pa_multiplex_remove_explicit_route(pa_core *core,
295 struct userdata *u; /* combine's userdata! */
301 if (!(module = pa_idxset_get_by_index(core->modules, mux->module_index)))
302 pa_log("module %u is gone", mux->module_index);
304 pa_assert_se((u = module->userdata));
306 u->remove_slave(u, NULL, sink);
308 pa_log_debug("link to sink.%u removed", sink->index);
317 pa_bool_t pa_multiplex_duplicate_route(pa_core *core,
323 struct userdata *u; /* combine's userdata! */
332 pa_log_debug("check for duplicate route on mux %u",
335 if (!(module = pa_idxset_get_by_index(core->modules,mux->module_index)))
336 pa_log("module %u is gone", mux->module_index);
338 pa_assert_se((u = module->userdata));
340 PA_IDXSET_FOREACH(o, u->outputs, idx) {
341 if (!(i = o->sink_input))
343 if (sinp && i == sinp)
345 if (i->sink == sink) {
346 pa_log_debug("route sink-input.%u -> sink.%u is a duplicate",
347 i->index, sink->index);
353 pa_log_debug("no duplicate route found to sink.%u", sink->index);
355 pa_log_debug("no duplicate found for route sink-input.%u -> "
356 "sink.%u", sinp->index, sink->index);
364 int pa_multiplex_print(pa_muxnode *mux, char *buf, int len)
374 p += snprintf(p, e-p, "<not set>");
376 p += snprintf(p, e-p, "module %u, sink %u, default stream %u",
377 mux->module_index, mux->sink_index,mux->defstream_index);
387 * indent-tabs-mode: nil