[pulseaudio-discuss] [PATCH 05/30] node: Pass the requested connections to PA_CORE_HOOK_NODE_SET_INITIAL_ROUTING
Tanu Kaskinen
tanu.kaskinen at linux.intel.com
Thu Jan 16 07:02:31 PST 2014
Also allow the hook users to report failure.
---
src/modules/module-experimental-router.c | 40 +++++++++++++++++++++++---------
src/pulsecore/core.h | 32 +++++++++++++++++++++++--
src/pulsecore/node.c | 15 +++++++++++-
src/pulsecore/node.h | 10 ++++++++
4 files changed, 83 insertions(+), 14 deletions(-)
diff --git a/src/modules/module-experimental-router.c b/src/modules/module-experimental-router.c
index fe918bc..594593d 100644
--- a/src/modules/module-experimental-router.c
+++ b/src/modules/module-experimental-router.c
@@ -40,14 +40,26 @@ struct userdata {
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;
+ pa_node_set_initial_routing_hook_data *data = call_data;
+ pa_node *node;
int r;
pa_assert(core);
- pa_assert(node);
+ pa_assert(data);
+
+ if (data->ret_valid)
+ /* Some other router module already applied some policy, we don't want
+ * to override that. */
+ return PA_HOOK_OK;
+
+ node = data->node;
if (node->type != PA_NODE_TYPE_SINK_INPUT && node->type != PA_NODE_TYPE_SOURCE_OUTPUT)
- goto finish;
+ /* We don't set data->ret_valid, because we don't care about nodes that
+ * aren't sink inputs or source outputs. If there is another router
+ * module, it's free to apply its policy, and otherwise pa_node_put()
+ * should apply its fallback policy. */
+ return PA_HOOK_OK;
if (node->type == PA_NODE_TYPE_SINK_INPUT) {
pa_sink_input *sink_input = node->owner;
@@ -60,10 +72,10 @@ static pa_hook_result_t node_set_initial_routing_cb(void *hook_data, void *call_
default_sink = pa_namereg_get_default_sink(core);
- if (!default_sink)
- goto fail;
-
- r = pa_sink_input_set_initial_sink(sink_input, default_sink);
+ if (default_sink)
+ r = pa_sink_input_set_initial_sink(sink_input, default_sink);
+ else
+ r = -PA_ERR_NOENTITY;
} else {
pa_source_output *source_output = node->owner;
pa_source *default_source;
@@ -75,10 +87,10 @@ static pa_hook_result_t node_set_initial_routing_cb(void *hook_data, void *call_
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 (default_source)
+ r = pa_source_output_set_initial_source(source_output, default_source);
+ else
+ r = -PA_ERR_NOENTITY;
}
if (r < 0)
@@ -87,11 +99,17 @@ static pa_hook_result_t node_set_initial_routing_cb(void *hook_data, void *call_
finish:
pa_log_debug("Successfully routed node %s.", node->name);
+ data->ret = 0;
+ data->ret_valid = true;
+
return PA_HOOK_OK;
fail:
pa_log_debug("Failed to route node %s.", node->name);
+ data->ret = r;
+ data->ret_valid = true;
+
return PA_HOOK_OK;
}
diff --git a/src/pulsecore/core.h b/src/pulsecore/core.h
index 78675da..443af48 100644
--- a/src/pulsecore/core.h
+++ b/src/pulsecore/core.h
@@ -159,8 +159,36 @@ typedef enum pa_core_hook {
PA_CORE_HOOK_PORT_AVAILABLE_CHANGED,
PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED,
- /* Fired when a new node is added to the system. Router modules can use
- * this to set the initial routing for the new node. Call data: pa_node. */
+ /* Fired when a new node is added to the system (from pa_node_put()).
+ * Router modules can use this to set the initial routing for the new node.
+ * Call data: pa_node_set_initial_routing_hook_data, details below:
+ *
+ * struct pa_node_set_initial_routing_hook_data {
+ * pa_node *node;
+ * pa_node **requested_connections;
+ * unsigned n_requested_connections;
+ * int ret;
+ * bool ret_valid;
+ * }
+ *
+ * Users of this hook are expected to create zero or more connections
+ * between data.node and other nodes in the system. The requested
+ * connections should usually be taken into account when deciding the
+ * initial routing, but if you really want to ignore those, you're free to
+ * do so. If n_requested_connections is zero, it means "use default" (i.e.
+ * nothing specific was requested). XXX: We might some day need to support
+ * also the "don't connect anywhere" case, so the interpretation of
+ * n_requested_connections == 0 may change in the future...
+ *
+ * ret_valid must be set to true in the hook callback, because if it's
+ * false, pa_node_put() assumes that there are no router modules present so
+ * it will run its own fallback routing algorithm.
+ *
+ * If ret is set to a negative error code, the node creation will fail.
+ * Usually you should report an error if your router module can't create
+ * the requested connections, but you don't have to do that if you think it
+ * makes sense to let the node creation succeed even when the requested
+ * connections couldn't be created. */
PA_CORE_HOOK_NODE_SET_INITIAL_ROUTING,
PA_CORE_HOOK_MAX
diff --git a/src/pulsecore/node.c b/src/pulsecore/node.c
index 790c054..b1dc841 100644
--- a/src/pulsecore/node.c
+++ b/src/pulsecore/node.c
@@ -153,6 +153,14 @@ void pa_node_free(pa_node *node) {
}
int pa_node_put(pa_node *node, pa_node **requested_connections, unsigned n_requested_connections) {
+ pa_node_set_initial_routing_hook_data data = {
+ .node = node,
+ .requested_connections = requested_connections,
+ .n_requested_connections = n_requested_connections,
+ .ret = 0,
+ .ret_valid = false
+ };
+
pa_assert(node);
pa_assert(node->state == PA_NODE_STATE_INIT);
pa_assert(node->owner);
@@ -164,7 +172,12 @@ int pa_node_put(pa_node *node, pa_node **requested_connections, unsigned n_reque
if (node->monitor_of)
node->monitor_of->monitor = node;
- pa_hook_fire(&node->core->hooks[PA_CORE_HOOK_NODE_SET_INITIAL_ROUTING], node);
+ pa_hook_fire(&node->core->hooks[PA_CORE_HOOK_NODE_SET_INITIAL_ROUTING], &data);
+
+ if (data.ret_valid && data.ret < 0) {
+ pa_log_info("Setting initial routing for node %s failed.", node->name);
+ return data.ret;
+ }
pa_log_debug("Created node %s.", node->name);
diff --git a/src/pulsecore/node.h b/src/pulsecore/node.h
index 7366fed..395609e 100644
--- a/src/pulsecore/node.h
+++ b/src/pulsecore/node.h
@@ -77,6 +77,16 @@ struct pa_node {
void *owner;
};
+/* See the documentation of PA_CORE_HOOK_NODE_SET_INITIAL_ROUTING to understand
+ * this struct. */
+typedef struct pa_node_set_initial_routing_hook_data {
+ pa_node *node;
+ pa_node **requested_connections;
+ unsigned n_requested_connections;
+ int ret;
+ bool ret_valid;
+} pa_node_set_initial_routing_hook_data;
+
pa_node_new_data *pa_node_new_data_init(pa_node_new_data *data);
void pa_node_new_data_set_fallback_name_prefix(pa_node_new_data *data, const char *prefix);
void pa_node_new_data_set_description(pa_node_new_data *data, const char *description);
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list