With this patch, when you call bt_graph_add_*_listener(), you can also
provide a "remove listener" which is called when the added listener is
removed when the graph object is destroyed. This is useful when you
dynamically allocate data only for the listener to add and you are not
the only owner of the graph object: the remove listener is where to
free/release this data.
Existing CLIs and tests are modified to match this change.
Signed-off-by: Philippe Proulx <eeppeliteloop@gmail.com>
Signed-off-by: Jérémie Galarneau <jeremie.galarneau@efficios.com>
the_graph = ctx->graph;
ret = bt_graph_add_port_added_listener(ctx->graph,
the_graph = ctx->graph;
ret = bt_graph_add_port_added_listener(ctx->graph,
- graph_port_added_listener, ctx);
+ graph_port_added_listener, NULL, ctx);
if (ret < 0) {
BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
goto error;
}
ret = bt_graph_add_port_removed_listener(ctx->graph,
if (ret < 0) {
BT_LOGE_STR("Cannot add \"port added\" listener to graph.");
goto error;
}
ret = bt_graph_add_port_removed_listener(ctx->graph,
- graph_port_removed_listener, ctx);
+ graph_port_removed_listener, NULL, ctx);
if (ret < 0) {
BT_LOGE_STR("Cannot add \"port removed\" listener to graph.");
goto error;
}
ret = bt_graph_add_ports_connected_listener(ctx->graph,
if (ret < 0) {
BT_LOGE_STR("Cannot add \"port removed\" listener to graph.");
goto error;
}
ret = bt_graph_add_ports_connected_listener(ctx->graph,
- graph_ports_connected_listener, ctx);
+ graph_ports_connected_listener, NULL, ctx);
if (ret < 0) {
BT_LOGE_STR("Cannot add \"ports connected\" listener to graph.");
goto error;
}
ret = bt_graph_add_ports_disconnected_listener(ctx->graph,
if (ret < 0) {
BT_LOGE_STR("Cannot add \"ports connected\" listener to graph.");
goto error;
}
ret = bt_graph_add_ports_disconnected_listener(ctx->graph,
- graph_ports_disconnected_listener, ctx);
+ graph_ports_disconnected_listener, NULL, ctx);
if (ret < 0) {
BT_LOGE_STR("Cannot add \"ports disconnected\" listener to graph.");
goto error;
if (ret < 0) {
BT_LOGE_STR("Cannot add \"ports disconnected\" listener to graph.");
goto error;
GQueue *sinks_to_consume;
bt_bool canceled;
GQueue *sinks_to_consume;
bt_bool canceled;
+ bt_bool in_remove_listener;
struct {
GArray *port_added;
struct {
GArray *port_added;
struct bt_component *downstream_component,
struct bt_port *upstream_port, struct bt_port *downstream_port,
void *data);
struct bt_component *downstream_component,
struct bt_port *upstream_port, struct bt_port *downstream_port,
void *data);
+typedef void (* bt_graph_listener_removed)(void *data);
extern struct bt_graph *bt_graph_create(void);
extern struct bt_graph *bt_graph_create(void);
extern enum bt_graph_status bt_graph_consume(struct bt_graph *graph);
extern int bt_graph_add_port_added_listener(struct bt_graph *graph,
extern enum bt_graph_status bt_graph_consume(struct bt_graph *graph);
extern int bt_graph_add_port_added_listener(struct bt_graph *graph,
- bt_graph_port_added_listener listener, void *data);
+ bt_graph_port_added_listener listener,
+ bt_graph_listener_removed listener_removed, void *data);
extern int bt_graph_add_port_removed_listener(struct bt_graph *graph,
extern int bt_graph_add_port_removed_listener(struct bt_graph *graph,
- bt_graph_port_removed_listener listener, void *data);
+ bt_graph_port_removed_listener listener,
+ bt_graph_listener_removed listener_removed, void *data);
extern int bt_graph_add_ports_connected_listener(struct bt_graph *graph,
extern int bt_graph_add_ports_connected_listener(struct bt_graph *graph,
- bt_graph_ports_connected_listener listener, void *data);
+ bt_graph_ports_connected_listener listener,
+ bt_graph_listener_removed listener_removed, void *data);
extern int bt_graph_add_ports_disconnected_listener(struct bt_graph *graph,
extern int bt_graph_add_ports_disconnected_listener(struct bt_graph *graph,
- bt_graph_ports_disconnected_listener listener, void *data);
+ bt_graph_ports_disconnected_listener listener,
+ bt_graph_listener_removed listener_removed, void *data);
extern enum bt_graph_status bt_graph_cancel(struct bt_graph *graph);
extern bt_bool bt_graph_is_canceled(struct bt_graph *graph);
extern enum bt_graph_status bt_graph_cancel(struct bt_graph *graph);
extern bt_bool bt_graph_is_canceled(struct bt_graph *graph);
struct bt_graph_listener {
void *func;
struct bt_graph_listener {
void *func;
+ bt_graph_listener_removed removed;
+static
+int init_listeners_array(GArray **listeners)
+{
+ int ret = 0;
+
+ assert(listeners);
+ *listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_graph_listener));
+ if (!*listeners) {
+ BT_LOGE_STR("Failed to allocate one GArray.");
+ ret = -1;
+ goto end;
+ }
+
+end:
+ return ret;
+}
+
+static
+void call_remove_listeners(GArray *listeners)
+{
+ size_t i;
+
+ for (i = 0; i < listeners->len; i++) {
+ struct bt_graph_listener listener =
+ g_array_index(listeners, struct bt_graph_listener, i);
+
+ if (listener.removed) {
+ listener.removed(listener.data);
+ }
+ }
+}
+
static
void bt_graph_destroy(struct bt_object *obj)
{
static
void bt_graph_destroy(struct bt_object *obj)
{
*/
(void) bt_graph_cancel(graph);
*/
(void) bt_graph_cancel(graph);
+ /* Call all remove listeners */
+ call_remove_listeners(graph->listeners.port_added);
+ call_remove_listeners(graph->listeners.port_removed);
+ call_remove_listeners(graph->listeners.ports_connected);
+ call_remove_listeners(graph->listeners.ports_disconnected);
+
if (graph->connections) {
BT_LOGD_STR("Destroying connections.");
g_ptr_array_free(graph->connections, TRUE);
if (graph->connections) {
BT_LOGD_STR("Destroying connections.");
g_ptr_array_free(graph->connections, TRUE);
-static
-int init_listeners_array(GArray **listeners)
-{
- int ret = 0;
-
- assert(listeners);
- *listeners = g_array_new(FALSE, TRUE, sizeof(struct bt_graph_listener));
- if (!*listeners) {
- BT_LOGE_STR("Failed to allocate one GArray.");
- ret = -1;
- goto end;
- }
-
-end:
- return ret;
-}
-
struct bt_graph *bt_graph_create(void)
{
struct bt_graph *graph;
struct bt_graph *bt_graph_create(void)
{
struct bt_graph *graph;
-int add_listener(GArray *listeners, void *func, void *data)
+int add_listener(GArray *listeners, void *func, void *removed, void *data)
{
struct bt_graph_listener listener = {
.func = func,
{
struct bt_graph_listener listener = {
.func = func,
int bt_graph_add_port_added_listener(
struct bt_graph *graph,
int bt_graph_add_port_added_listener(
struct bt_graph *graph,
- bt_graph_port_added_listener listener, void *data)
+ bt_graph_port_added_listener listener,
+ bt_graph_listener_removed listener_removed, void *data)
+ if (graph->in_remove_listener) {
+ BT_LOGW("Cannot call this function during the execution of a remove listener: "
+ "addr=%p", graph);
+ ret = -1;
+ goto end;
+ }
+
if (!listener) {
BT_LOGW_STR("Invalid parameter: listener is NULL.");
ret = -1;
goto end;
}
if (!listener) {
BT_LOGW_STR("Invalid parameter: listener is NULL.");
ret = -1;
goto end;
}
- ret = add_listener(graph->listeners.port_added, listener, data);
+ ret = add_listener(graph->listeners.port_added, listener,
+ listener_removed, data);
BT_LOGV("Added \"port added\" listener to graph: "
"graph-addr=%p, listener-addr=%p, pos=%d",
graph, listener, ret);
BT_LOGV("Added \"port added\" listener to graph: "
"graph-addr=%p, listener-addr=%p, pos=%d",
graph, listener, ret);
int bt_graph_add_port_removed_listener(
struct bt_graph *graph,
int bt_graph_add_port_removed_listener(
struct bt_graph *graph,
- bt_graph_port_removed_listener listener, void *data)
+ bt_graph_port_removed_listener listener,
+ bt_graph_listener_removed listener_removed, void *data)
+ if (graph->in_remove_listener) {
+ BT_LOGW("Cannot call this function during the execution of a remove listener: "
+ "addr=%p", graph);
+ ret = -1;
+ goto end;
+ }
+
if (!listener) {
BT_LOGW_STR("Invalid parameter: listener is NULL.");
ret = -1;
goto end;
}
if (!listener) {
BT_LOGW_STR("Invalid parameter: listener is NULL.");
ret = -1;
goto end;
}
- ret = add_listener(graph->listeners.port_removed, listener, data);
+ ret = add_listener(graph->listeners.port_removed, listener,
+ listener_removed, data);
BT_LOGV("Added \"port removed\" listener to graph: "
"graph-addr=%p, listener-addr=%p, pos=%d",
graph, listener, ret);
BT_LOGV("Added \"port removed\" listener to graph: "
"graph-addr=%p, listener-addr=%p, pos=%d",
graph, listener, ret);
int bt_graph_add_ports_connected_listener(
struct bt_graph *graph,
int bt_graph_add_ports_connected_listener(
struct bt_graph *graph,
- bt_graph_ports_connected_listener listener, void *data)
+ bt_graph_ports_connected_listener listener,
+ bt_graph_listener_removed listener_removed, void *data)
+ if (graph->in_remove_listener) {
+ BT_LOGW("Cannot call this function during the execution of a remove listener: "
+ "addr=%p", graph);
+ ret = -1;
+ goto end;
+ }
+
if (!listener) {
BT_LOGW_STR("Invalid parameter: listener is NULL.");
ret = -1;
goto end;
}
if (!listener) {
BT_LOGW_STR("Invalid parameter: listener is NULL.");
ret = -1;
goto end;
}
- ret = add_listener(graph->listeners.ports_connected, listener, data);
+ ret = add_listener(graph->listeners.ports_connected, listener,
+ listener_removed, data);
BT_LOGV("Added \"port connected\" listener to graph: "
"graph-addr=%p, listener-addr=%p, pos=%d",
graph, listener, ret);
BT_LOGV("Added \"port connected\" listener to graph: "
"graph-addr=%p, listener-addr=%p, pos=%d",
graph, listener, ret);
int bt_graph_add_ports_disconnected_listener(
struct bt_graph *graph,
int bt_graph_add_ports_disconnected_listener(
struct bt_graph *graph,
- bt_graph_ports_disconnected_listener listener, void *data)
+ bt_graph_ports_disconnected_listener listener,
+ bt_graph_listener_removed listener_removed, void *data)
+ if (graph->in_remove_listener) {
+ BT_LOGW("Cannot call this function during the execution of a remove listener: "
+ "addr=%p", graph);
+ ret = -1;
+ goto end;
+ }
+
if (!listener) {
BT_LOGW_STR("Invalid parameter: listener is NULL.");
ret = -1;
goto end;
}
if (!listener) {
BT_LOGW_STR("Invalid parameter: listener is NULL.");
ret = -1;
goto end;
}
- ret = add_listener(graph->listeners.ports_disconnected, listener, data);
+ ret = add_listener(graph->listeners.ports_disconnected, listener,
+ listener_removed, data);
BT_LOGV("Added \"port disconnected\" listener to graph: "
"graph-addr=%p, listener-addr=%p, pos=%d",
graph, listener, ret);
BT_LOGV("Added \"port disconnected\" listener to graph: "
"graph-addr=%p, listener-addr=%p, pos=%d",
graph, listener, ret);
- ret = bt_graph_add_port_added_listener(graph, graph_port_added, NULL);
+ ret = bt_graph_add_port_added_listener(graph, graph_port_added, NULL,
+ NULL);
assert(ret >= 0);
ret = bt_graph_add_port_removed_listener(graph, graph_port_removed,
assert(ret >= 0);
ret = bt_graph_add_port_removed_listener(graph, graph_port_removed,
- ret = bt_graph_add_ports_connected_listener(graph, graph_ports_connected,
- NULL);
+ ret = bt_graph_add_ports_connected_listener(graph,
+ graph_ports_connected, NULL, NULL);
assert(ret >= 0);
ret = bt_graph_add_ports_disconnected_listener(graph,
assert(ret >= 0);
ret = bt_graph_add_ports_disconnected_listener(graph,
- graph_ports_disconnected, NULL);
+ graph_ports_disconnected, NULL, NULL);
assert(ret >= 0);
return graph;
}
assert(ret >= 0);
return graph;
}
graph_listener_data.muxer = muxer_comp;
graph_listener_data.sink = sink_comp;
ret = bt_graph_add_port_added_listener(graph,
graph_listener_data.muxer = muxer_comp;
graph_listener_data.sink = sink_comp;
ret = bt_graph_add_port_added_listener(graph,
- graph_port_added_listener_connect_to_avail_muxer_port,
+ graph_port_added_listener_connect_to_avail_muxer_port, NULL,
&graph_listener_data);
assert(ret >= 0);
&graph_listener_data);
assert(ret >= 0);
graph_listener_data.muxer = muxer_comp;
graph_listener_data.sink = sink_comp;
ret = bt_graph_add_port_added_listener(graph,
graph_listener_data.muxer = muxer_comp;
graph_listener_data.sink = sink_comp;
ret = bt_graph_add_port_added_listener(graph,
- graph_port_added_listener_connect_to_avail_muxer_port,
+ graph_port_added_listener_connect_to_avail_muxer_port, NULL,
&graph_listener_data);
assert(ret >= 0);
&graph_listener_data);
assert(ret >= 0);