2 * The MIT License (MIT)
4 * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 /* Output argument typemap for connection output (always appends) */
26 %typemap(in, numinputs=0)
27 (const bt_connection **)
28 (bt_connection *temp_conn = NULL) {
33 (const bt_connection **) {
35 /* SWIG_Python_AppendOutput() steals the created object */
36 $result = SWIG_Python_AppendOutput($result,
37 SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
38 SWIGTYPE_p_bt_connection, 0));
40 /* SWIG_Python_AppendOutput() steals Py_None */
42 $result = SWIG_Python_AppendOutput($result, Py_None);
46 /* Output argument typemap for component output (always appends) */
47 %typemap(in, numinputs=0)
48 (const bt_component_source **)
49 (bt_component_source *temp_comp = NULL) {
53 %typemap(in, numinputs=0)
54 (const bt_component_filter **)
55 (bt_component_filter *temp_comp = NULL) {
59 %typemap(in, numinputs=0)
60 (const bt_component_sink **)
61 (bt_component_sink *temp_comp = NULL) {
65 %typemap(argout) (const bt_component_source **) {
67 /* SWIG_Python_AppendOutput() steals the created object */
68 $result = SWIG_Python_AppendOutput($result,
69 SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
70 SWIGTYPE_p_bt_component_source, 0));
72 /* SWIG_Python_AppendOutput() steals Py_None */
74 $result = SWIG_Python_AppendOutput($result, Py_None);
78 %typemap(argout) (const bt_component_filter **) {
80 /* SWIG_Python_AppendOutput() steals the created object */
81 $result = SWIG_Python_AppendOutput($result,
82 SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
83 SWIGTYPE_p_bt_component_filter, 0));
85 /* SWIG_Python_AppendOutput() steals Py_None */
87 $result = SWIG_Python_AppendOutput($result, Py_None);
91 %typemap(argout) (const bt_component_sink **) {
93 /* SWIG_Python_AppendOutput() steals the created object */
94 $result = SWIG_Python_AppendOutput($result,
95 SWIG_NewPointerObj(SWIG_as_voidptr(*$1),
96 SWIGTYPE_p_bt_component_sink, 0));
98 /* SWIG_Python_AppendOutput() steals Py_None */
100 $result = SWIG_Python_AppendOutput($result, Py_None);
104 %include <babeltrace2/graph/graph-const.h>
105 %include <babeltrace2/graph/graph.h>
107 /* Helper functions for Python */
111 static void graph_listener_removed(void *py_callable)
113 BT_ASSERT(py_callable);
114 Py_DECREF(py_callable);
117 static bt_graph_listener_status
119 const void *component,
120 swig_type_info *component_swig_type,
121 bt_component_class_type component_class_type,
123 swig_type_info *port_swig_type,
124 bt_port_type port_type,
127 PyObject *py_component_ptr = NULL;
128 PyObject *py_port_ptr = NULL;
129 PyObject *py_res = NULL;
130 bt_graph_listener_status status;
132 py_component_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(component), component_swig_type, 0);
133 if (!py_component_ptr) {
134 BT_LOGF_STR("Failed to create component SWIG pointer object.");
135 status = BT_GRAPH_LISTENER_STATUS_NOMEM;
139 py_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(port), port_swig_type, 0);
141 BT_LOGF_STR("Failed to create port SWIG pointer object.");
142 status = BT_GRAPH_LISTENER_STATUS_NOMEM;
146 py_res = PyObject_CallFunction(py_callable, "(OiOi)",
147 py_component_ptr, component_class_type, py_port_ptr, port_type);
149 bt2_py_loge_exception();
151 status = BT_GRAPH_LISTENER_STATUS_ERROR;
155 BT_ASSERT(py_res == Py_None);
156 status = BT_GRAPH_LISTENER_STATUS_OK;
160 Py_XDECREF(py_port_ptr);
161 Py_XDECREF(py_component_ptr);
166 static bt_graph_listener_status
167 source_component_output_port_added_listener(const bt_component_source *component_source,
168 const bt_port_output *port_output, void *py_callable)
170 return port_added_listener(
171 component_source, SWIGTYPE_p_bt_component_source, BT_COMPONENT_CLASS_TYPE_SOURCE,
172 port_output, SWIGTYPE_p_bt_port_output, BT_PORT_TYPE_OUTPUT, py_callable);
175 static bt_graph_listener_status
176 filter_component_input_port_added_listener(const bt_component_filter *component_filter,
177 const bt_port_input *port_input, void *py_callable)
179 return port_added_listener(
180 component_filter, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
181 port_input, SWIGTYPE_p_bt_port_input, BT_PORT_TYPE_INPUT, py_callable);
184 static bt_graph_listener_status
185 filter_component_output_port_added_listener(const bt_component_filter *component_filter,
186 const bt_port_output *port_output, void *py_callable)
188 return port_added_listener(
189 component_filter, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
190 port_output, SWIGTYPE_p_bt_port_output, BT_PORT_TYPE_OUTPUT, py_callable);
193 static bt_graph_listener_status
194 sink_component_input_port_added_listener(const bt_component_sink *component_sink,
195 const bt_port_input *port_input, void *py_callable)
197 return port_added_listener(
198 component_sink, SWIGTYPE_p_bt_component_sink, BT_COMPONENT_CLASS_TYPE_SINK,
199 port_input, SWIGTYPE_p_bt_port_input, BT_PORT_TYPE_INPUT, py_callable);
203 bt_py3_graph_add_port_added_listener(struct bt_graph *graph,
204 PyObject *py_callable)
206 PyObject *py_listener_ids = NULL;
207 PyObject *py_listener_id = NULL;
209 bt_graph_status status;
212 BT_ASSERT(py_callable);
215 * Behind the scene, we will be registering 4 different listeners and
216 * return all of their ids.
218 py_listener_ids = PyTuple_New(4);
219 if (!py_listener_ids) {
223 /* source output port */
224 status = bt_graph_add_source_component_output_port_added_listener(
225 graph, source_component_output_port_added_listener,
226 graph_listener_removed, py_callable, &listener_id);
227 if (status != BT_GRAPH_STATUS_OK) {
231 py_listener_id = PyLong_FromLong(listener_id);
232 if (!py_listener_id) {
236 PyTuple_SET_ITEM(py_listener_ids, 0, py_listener_id);
237 py_listener_id = NULL;
239 /* filter input port */
240 status = bt_graph_add_filter_component_input_port_added_listener(
241 graph, filter_component_input_port_added_listener,
242 graph_listener_removed, py_callable, &listener_id);
243 if (status != BT_GRAPH_STATUS_OK) {
247 py_listener_id = PyLong_FromLong(listener_id);
248 if (!py_listener_id) {
252 PyTuple_SET_ITEM(py_listener_ids, 1, py_listener_id);
253 py_listener_id = NULL;
255 /* filter output port */
256 status = bt_graph_add_filter_component_output_port_added_listener(
257 graph, filter_component_output_port_added_listener,
258 graph_listener_removed, py_callable, &listener_id);
259 if (status != BT_GRAPH_STATUS_OK) {
263 py_listener_id = PyLong_FromLong(listener_id);
264 if (!py_listener_id) {
268 PyTuple_SET_ITEM(py_listener_ids, 2, py_listener_id);
269 py_listener_id = NULL;
271 /* sink input port */
272 status = bt_graph_add_sink_component_input_port_added_listener(
273 graph, sink_component_input_port_added_listener,
274 graph_listener_removed, py_callable, &listener_id);
275 if (status != BT_GRAPH_STATUS_OK) {
279 py_listener_id = PyLong_FromLong(listener_id);
280 if (!py_listener_id) {
285 PyTuple_SET_ITEM(py_listener_ids, 3, py_listener_id);
286 py_listener_id = NULL;
288 Py_INCREF(py_callable);
289 Py_INCREF(py_callable);
290 Py_INCREF(py_callable);
291 Py_INCREF(py_callable);
296 Py_XDECREF(py_listener_ids);
297 py_listener_ids = Py_None;
298 Py_INCREF(py_listener_ids);
302 Py_XDECREF(py_listener_id);
303 return py_listener_ids;
306 static bt_graph_listener_status
307 ports_connected_listener(
308 const void *upstream_component,
309 swig_type_info *upstream_component_swig_type,
310 bt_component_class_type upstream_component_class_type,
311 const bt_port_output *upstream_port,
312 const void *downstream_component,
313 swig_type_info *downstream_component_swig_type,
314 bt_component_class_type downstream_component_class_type,
315 const bt_port_input *downstream_port,
318 PyObject *py_upstream_component_ptr = NULL;
319 PyObject *py_upstream_port_ptr = NULL;
320 PyObject *py_downstream_component_ptr = NULL;
321 PyObject *py_downstream_port_ptr = NULL;
322 PyObject *py_res = NULL;
323 bt_graph_listener_status status;
325 py_upstream_component_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(upstream_component),
326 upstream_component_swig_type, 0);
327 if (!py_upstream_component_ptr) {
328 BT_LOGF_STR("Failed to create upstream component SWIG pointer object.");
329 status = BT_GRAPH_LISTENER_STATUS_NOMEM;
333 py_upstream_port_ptr = SWIG_NewPointerObj(
334 SWIG_as_voidptr(upstream_port), SWIGTYPE_p_bt_port_output, 0);
335 if (!py_upstream_port_ptr) {
336 BT_LOGF_STR("Failed to create upstream port SWIG pointer object.");
337 status = BT_GRAPH_LISTENER_STATUS_NOMEM;
341 py_downstream_component_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(downstream_component),
342 downstream_component_swig_type, 0);
343 if (!py_downstream_component_ptr) {
344 BT_LOGF_STR("Failed to create downstream component SWIG pointer object.");
345 status = BT_GRAPH_LISTENER_STATUS_NOMEM;
349 py_downstream_port_ptr = SWIG_NewPointerObj(
350 SWIG_as_voidptr(downstream_port), SWIGTYPE_p_bt_port_input, 0);
351 if (!py_downstream_port_ptr) {
352 BT_LOGF_STR("Failed to create downstream port SWIG pointer object.");
353 status = BT_GRAPH_LISTENER_STATUS_NOMEM;
357 py_res = PyObject_CallFunction(py_callable, "(OiOOiO)",
358 py_upstream_component_ptr, upstream_component_class_type,
359 py_upstream_port_ptr,
360 py_downstream_component_ptr, downstream_component_class_type,
361 py_downstream_port_ptr);
363 bt2_py_loge_exception();
365 status = BT_GRAPH_LISTENER_STATUS_ERROR;
369 BT_ASSERT(py_res == Py_None);
370 status = BT_GRAPH_LISTENER_STATUS_OK;
373 Py_XDECREF(py_upstream_component_ptr);
374 Py_XDECREF(py_upstream_port_ptr);
375 Py_XDECREF(py_downstream_component_ptr);
376 Py_XDECREF(py_downstream_port_ptr);
382 static bt_graph_listener_status
383 source_filter_component_ports_connected_listener(
384 const bt_component_source *source_component,
385 const bt_component_filter *filter_component,
386 const bt_port_output *upstream_port,
387 const bt_port_input *downstream_port, void *py_callable)
389 return ports_connected_listener(
390 source_component, SWIGTYPE_p_bt_component_source, BT_COMPONENT_CLASS_TYPE_SOURCE,
392 filter_component, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
397 static bt_graph_listener_status
398 source_sink_component_ports_connected_listener(
399 const bt_component_source *source_component,
400 const bt_component_sink *sink_component,
401 const bt_port_output *upstream_port,
402 const bt_port_input *downstream_port, void *py_callable)
404 return ports_connected_listener(
405 source_component, SWIGTYPE_p_bt_component_source, BT_COMPONENT_CLASS_TYPE_SOURCE,
407 sink_component, SWIGTYPE_p_bt_component_sink, BT_COMPONENT_CLASS_TYPE_SINK,
412 static bt_graph_listener_status
413 filter_filter_component_ports_connected_listener(
414 const bt_component_filter *filter_component_left,
415 const bt_component_filter *filter_component_right,
416 const bt_port_output *upstream_port,
417 const bt_port_input *downstream_port, void *py_callable)
419 return ports_connected_listener(
420 filter_component_left, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
422 filter_component_right, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
427 static bt_graph_listener_status
428 filter_sink_component_ports_connected_listener(
429 const bt_component_filter *filter_component,
430 const bt_component_sink *sink_component,
431 const bt_port_output *upstream_port,
432 const bt_port_input *downstream_port, void *py_callable)
434 return ports_connected_listener(
435 filter_component, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
437 sink_component, SWIGTYPE_p_bt_component_sink, BT_COMPONENT_CLASS_TYPE_SINK,
443 bt_py3_graph_add_ports_connected_listener(struct bt_graph *graph,
444 PyObject *py_callable)
446 PyObject *py_listener_ids = NULL;
447 PyObject *py_listener_id = NULL;
449 bt_graph_status status;
452 BT_ASSERT(py_callable);
454 /* Behind the scene, we will be registering 4 different listeners and
455 * return all of their ids. */
456 py_listener_ids = PyTuple_New(4);
457 if (!py_listener_ids) {
461 /* source -> filter connection */
462 status = bt_graph_add_source_filter_component_ports_connected_listener(
463 graph, source_filter_component_ports_connected_listener,
464 graph_listener_removed, py_callable, &listener_id);
465 if (status != BT_GRAPH_STATUS_OK) {
469 py_listener_id = PyLong_FromLong(listener_id);
470 if (!py_listener_id) {
474 PyTuple_SET_ITEM(py_listener_ids, 0, py_listener_id);
475 py_listener_id = NULL;
477 /* source -> sink connection */
478 status = bt_graph_add_source_sink_component_ports_connected_listener(
479 graph, source_sink_component_ports_connected_listener,
480 graph_listener_removed, py_callable, &listener_id);
481 if (status != BT_GRAPH_STATUS_OK) {
485 py_listener_id = PyLong_FromLong(listener_id);
486 if (!py_listener_id) {
490 PyTuple_SET_ITEM(py_listener_ids, 1, py_listener_id);
491 py_listener_id = NULL;
493 /* filter -> filter connection */
494 status = bt_graph_add_filter_filter_component_ports_connected_listener(
495 graph, filter_filter_component_ports_connected_listener,
496 graph_listener_removed, py_callable, &listener_id);
497 if (status != BT_GRAPH_STATUS_OK) {
501 py_listener_id = PyLong_FromLong(listener_id);
502 if (!py_listener_id) {
506 PyTuple_SET_ITEM(py_listener_ids, 2, py_listener_id);
507 py_listener_id = NULL;
509 /* filter -> sink connection */
510 status = bt_graph_add_filter_sink_component_ports_connected_listener(
511 graph, filter_sink_component_ports_connected_listener,
512 graph_listener_removed, py_callable, &listener_id);
513 if (status != BT_GRAPH_STATUS_OK) {
517 py_listener_id = PyLong_FromLong(listener_id);
518 if (!py_listener_id) {
522 PyTuple_SET_ITEM(py_listener_ids, 3, py_listener_id);
523 py_listener_id = NULL;
525 Py_INCREF(py_callable);
526 Py_INCREF(py_callable);
527 Py_INCREF(py_callable);
528 Py_INCREF(py_callable);
533 Py_XDECREF(py_listener_ids);
534 py_listener_ids = Py_None;
535 Py_INCREF(py_listener_ids);
539 Py_XDECREF(py_listener_id);
540 return py_listener_ids;
545 PyObject *bt_py3_graph_add_port_added_listener(struct bt_graph *graph,
546 PyObject *py_callable);
547 PyObject *bt_py3_graph_add_ports_connected_listener(struct bt_graph *graph,
548 PyObject *py_callable);