The experimental router will be used as a tool for exercising new routing functionality in the core. Another goal is to evolve the module into a Murphy module - it's expected that the module will gain features that are only used in the Murphy module. A rename to module-murphy should happen at some point. This first version just routes streams to the default sink/source when the streams are created. --- src/Makefile.am | 8 ++ src/modules/module-experimental-router.c | 122 +++++++++++++++++++++++++++++++ 2 files changed, 130 insertions(+) create mode 100644 src/modules/module-experimental-router.c diff --git a/src/Makefile.am b/src/Makefile.am index 168415e..e09d48a 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1074,6 +1074,7 @@ endif modlibexec_LTLIBRARIES += \ module-cli.la \ module-cli-protocol-tcp.la \ + module-experimental-router.la \ module-simple-protocol-tcp.la \ module-null-sink.la \ module-null-source.la \ @@ -1357,6 +1358,7 @@ SYMDEF_FILES = \ module-cli-symdef.h \ module-cli-protocol-tcp-symdef.h \ module-cli-protocol-unix-symdef.h \ + module-experimental-router-symdef.h \ module-pipe-sink-symdef.h \ module-pipe-source-symdef.h \ module-simple-protocol-tcp-symdef.h \ @@ -1915,6 +1917,12 @@ module_intended_roles_la_LDFLAGS = $(MODULE_LDFLAGS) module_intended_roles_la_LIBADD = $(MODULE_LIBADD) module_intended_roles_la_CFLAGS = $(AM_CFLAGS) +# An experimental router module +module_experimental_router_la_SOURCES = modules/module-experimental-router.c +module_experimental_router_la_LDFLAGS = $(MODULE_LDFLAGS) +module_experimental_router_la_LIBADD = $(MODULE_LIBADD) +module_experimental_router_la_CFLAGS = $(AM_CFLAGS) + # Suspend-on-idle module module_suspend_on_idle_la_SOURCES = modules/module-suspend-on-idle.c module_suspend_on_idle_la_LDFLAGS = $(MODULE_LDFLAGS) diff --git a/src/modules/module-experimental-router.c b/src/modules/module-experimental-router.c new file mode 100644 index 0000000..fe918bc --- /dev/null +++ b/src/modules/module-experimental-router.c @@ -0,0 +1,122 @@ +/*** + This file is part of PulseAudio. + + Copyright 2013 Intel Corporation + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + USA. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "module-experimental-router-symdef.h" + +#include <pulsecore/i18n.h> +#include <pulsecore/module.h> +#include <pulsecore/namereg.h> + +PA_MODULE_AUTHOR("Tanu Kaskinen"); +PA_MODULE_DESCRIPTION(_("An experimental router module")); +PA_MODULE_VERSION(PACKAGE_VERSION); +PA_MODULE_LOAD_ONCE(true); + +struct userdata { + pa_hook_slot *node_set_initial_routing_slot; +}; + +static pa_hook_result_t node_set_initial_routing_cb(void *hook_data, void *call_data, void *userdata) { + pa_core *core = hook_data; + pa_node *node = call_data; + int r; + + pa_assert(core); + pa_assert(node); + + if (node->type != PA_NODE_TYPE_SINK_INPUT && node->type != PA_NODE_TYPE_SOURCE_OUTPUT) + goto finish; + + if (node->type == PA_NODE_TYPE_SINK_INPUT) { + pa_sink_input *sink_input = node->owner; + pa_sink *default_sink; + + pa_assert(sink_input->state == PA_SINK_INPUT_INIT); + + if (sink_input->sink) + goto finish; + + default_sink = pa_namereg_get_default_sink(core); + + if (!default_sink) + goto fail; + + r = pa_sink_input_set_initial_sink(sink_input, default_sink); + } else { + pa_source_output *source_output = node->owner; + pa_source *default_source; + + pa_assert(source_output->state == PA_SOURCE_OUTPUT_INIT); + + if (source_output->source) + goto finish; + + default_source = pa_namereg_get_default_source(core); + + if (!default_source) + goto fail; + + r = pa_source_output_set_initial_source(source_output, default_source); + } + + if (r < 0) + goto fail; + +finish: + pa_log_debug("Successfully routed node %s.", node->name); + + return PA_HOOK_OK; + +fail: + pa_log_debug("Failed to route node %s.", node->name); + + return PA_HOOK_OK; +} + +int pa__init(pa_module *module) { + struct userdata *u; + + pa_assert(module); + + module->userdata = u = pa_xnew0(struct userdata, 1); + u->node_set_initial_routing_slot = pa_hook_connect(&module->core->hooks[PA_CORE_HOOK_NODE_SET_INITIAL_ROUTING], + PA_HOOK_NORMAL, node_set_initial_routing_cb, u); + + return 0; +} + +void pa__done(pa_module *module) { + struct userdata *u; + + pa_assert(module); + + if (!(u = module->userdata)) + return; + + if (u->node_set_initial_routing_slot) + pa_hook_slot_free(u->node_set_initial_routing_slot); + + pa_xfree(u); +} -- 1.8.3.1