[pulseaudio-discuss] [PATCH 09/15] node: Delete edges when unlinking a node
Tanu Kaskinen
tanu.kaskinen at linux.intel.com
Thu Feb 13 19:35:54 CET 2014
Nodes need to keep track of the edges that they are part of, so that
a node knows which edges to delete when the node is unlinked.
---
src/pulsecore/edge.c | 33 +++++++++++++++++++++++++++++++++
src/pulsecore/edge.h | 2 ++
src/pulsecore/node.c | 28 ++++++++++++++++++++++++++++
src/pulsecore/node.h | 6 ++++++
4 files changed, 69 insertions(+)
diff --git a/src/pulsecore/edge.c b/src/pulsecore/edge.c
index da40a53..931bee1 100644
--- a/src/pulsecore/edge.c
+++ b/src/pulsecore/edge.c
@@ -32,6 +32,9 @@
#include <pulse/xmalloc.h>
+static int edge_put(pa_edge *edge);
+static void edge_unlink(pa_edge *edge);
+
uint64_t pa_edge_key(uint32_t input_index, uint32_t output_index) {
return ((uint64_t) input_index) << 32 | (uint64_t) output_index;
}
@@ -116,6 +119,8 @@ pa_edge *pa_edge_new(pa_node *input, pa_node *output, int *ret) {
edge->output = output;
edge->string = pa_sprintf_malloc("%s -> %s", input->name, output->name);
+ edge_put(edge);
+
return edge;
fail:
@@ -128,9 +133,37 @@ fail:
return NULL;
}
+static int edge_put(pa_edge *edge) {
+ pa_assert(edge);
+
+ pa_node_add_edge(edge->input, edge);
+ pa_node_add_edge(edge->output, edge);
+
+ pa_log_debug("Created edge %s.", edge->string);
+
+ return 0;
+}
+
+static void edge_unlink(pa_edge *edge) {
+ pa_assert(edge);
+
+ if (edge->unlinked) {
+ pa_log_debug("Unlinking edge %s (already unlinked, this is a no-op).", edge->string);
+ return;
+ }
+
+ edge->unlinked = true;
+
+ pa_log_debug("Unlinking edge %s.", edge->string);
+
+ pa_node_remove_edge(edge->output, edge);
+ pa_node_remove_edge(edge->input, edge);
+}
+
void pa_edge_free(pa_edge *edge) {
pa_assert(edge);
+ edge_unlink(edge);
pa_xfree(edge->string);
pa_xfree(edge);
}
diff --git a/src/pulsecore/edge.h b/src/pulsecore/edge.h
index 880df90..bd5cca1 100644
--- a/src/pulsecore/edge.h
+++ b/src/pulsecore/edge.h
@@ -36,6 +36,8 @@ struct pa_edge {
pa_node *input;
pa_node *output;
char *string;
+
+ bool unlinked;
};
#define PA_MAX_EDGES 1024
diff --git a/src/pulsecore/node.c b/src/pulsecore/node.c
index c0408c2..2475c85 100644
--- a/src/pulsecore/node.c
+++ b/src/pulsecore/node.c
@@ -25,6 +25,7 @@
#endif
#include <pulsecore/core-util.h>
+#include <pulsecore/edge.h>
#include <pulsecore/namereg.h>
#include <pulsecore/strbuf.h>
@@ -145,6 +146,7 @@ pa_node *pa_node_new(pa_core *core, pa_node_new_data *data) {
n->type = data->type;
n->direction = data->direction;
n->monitor_of = data->monitor_of;
+ n->edges = pa_hashmap_new(NULL, NULL);
n->active = data->active;
return n;
@@ -161,6 +163,11 @@ void pa_node_free(pa_node *node) {
pa_node_unlink(node);
+ if (node->edges) {
+ pa_assert(pa_hashmap_isempty(node->edges));
+ pa_hashmap_free(node->edges);
+ }
+
pa_xfree(node->description);
if (node->name) {
@@ -404,6 +411,8 @@ int pa_node_put(pa_node *node, pa_node **requested_connections, unsigned n_reque
}
void pa_node_unlink(pa_node *node) {
+ pa_edge *edge;
+
pa_assert(node);
if (node->unlinked) {
@@ -415,6 +424,11 @@ void pa_node_unlink(pa_node *node) {
pa_log_debug("Unlinking node %s.", node->name);
+ while ((edge = pa_hashmap_steal_first(node->edges))) {
+ pa_log_debug("Deleting edge %s due to unlinking one of its endpoints.", edge->string);
+ pa_core_delete_edge(node->core, edge);
+ }
+
if (node->monitor_of)
node->monitor_of->monitor = NULL;
@@ -425,6 +439,20 @@ void pa_node_unlink(pa_node *node) {
}
+int pa_node_add_edge(pa_node *node, pa_edge *edge) {
+ pa_assert(node);
+ pa_assert(edge);
+
+ return pa_hashmap_put(node->edges, edge, edge);
+}
+
+int pa_node_remove_edge(pa_node *node, pa_edge *edge) {
+ pa_assert(node);
+ pa_assert(edge);
+
+ return pa_hashmap_remove(node->edges, edge) ? 0 : -1;
+}
+
void pa_node_active_changed(pa_node *node, bool new_active) {
pa_assert(node);
diff --git a/src/pulsecore/node.h b/src/pulsecore/node.h
index 1014f16..626ee2f 100644
--- a/src/pulsecore/node.h
+++ b/src/pulsecore/node.h
@@ -23,6 +23,8 @@
USA.
***/
+#include <pulsecore/hashmap.h>
+
typedef struct pa_node_new_data pa_node_new_data;
typedef struct pa_node pa_node;
@@ -69,6 +71,7 @@ struct pa_node {
pa_node *monitor;
pa_node *monitor_of;
+ pa_hashmap *edges; /* pa_edge -> pa_edge (hashmap-as-a-set) */
bool active;
bool unlinked;
@@ -101,6 +104,9 @@ void pa_node_free(pa_node *node);
int pa_node_put(pa_node *node, pa_node **requested_connections, unsigned n_requested_connections);
void pa_node_unlink(pa_node *node);
+int pa_node_add_edge(pa_node *node, pa_edge *edge);
+int pa_node_remove_edge(pa_node *node, pa_edge *edge);
+
/* To be called by the node back end when its active state changes. */
void pa_node_active_changed(pa_node *node, bool new_active);
--
1.8.3.1
More information about the pulseaudio-discuss
mailing list