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 void graph_listener_removed(void *py_callable)
113 BT_ASSERT(py_callable);
114 Py_DECREF(py_callable);
117 static bt_graph_listener_func_status port_added_listener(
118 const void *component,
119 swig_type_info *component_swig_type,
120 bt_component_class_type component_class_type,
122 swig_type_info *port_swig_type,
123 bt_port_type port_type,
126 PyObject *py_component_ptr = NULL;
127 PyObject *py_port_ptr = NULL;
128 PyObject *py_res = NULL;
129 bt_graph_listener_func_status status;
131 py_component_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(component), component_swig_type, 0);
132 if (!py_component_ptr) {
133 BT_LOGF_STR("Failed to create component SWIG pointer object.");
134 status = __BT_FUNC_STATUS_MEMORY_ERROR;
138 py_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(port), port_swig_type, 0);
140 BT_LOGF_STR("Failed to create port SWIG pointer object.");
141 status = __BT_FUNC_STATUS_MEMORY_ERROR;
145 py_res = PyObject_CallFunction(py_callable, "(OiOi)",
146 py_component_ptr, component_class_type, py_port_ptr, port_type);
148 loge_exception("Graph's port added listener (Python)",
149 BT_LOG_OUTPUT_LEVEL);
151 status = __BT_FUNC_STATUS_ERROR;
155 BT_ASSERT(py_res == Py_None);
156 status = __BT_FUNC_STATUS_OK;
160 Py_XDECREF(py_port_ptr);
161 Py_XDECREF(py_component_ptr);
166 bt_graph_listener_func_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);
176 bt_graph_listener_func_status
177 filter_component_input_port_added_listener(const bt_component_filter *component_filter,
178 const bt_port_input *port_input, void *py_callable)
180 return port_added_listener(
181 component_filter, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
182 port_input, SWIGTYPE_p_bt_port_input, BT_PORT_TYPE_INPUT, py_callable);
186 bt_graph_listener_func_status
187 filter_component_output_port_added_listener(const bt_component_filter *component_filter,
188 const bt_port_output *port_output, void *py_callable)
190 return port_added_listener(
191 component_filter, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
192 port_output, SWIGTYPE_p_bt_port_output, BT_PORT_TYPE_OUTPUT, py_callable);
196 bt_graph_listener_func_status
197 sink_component_input_port_added_listener(const bt_component_sink *component_sink,
198 const bt_port_input *port_input, void *py_callable)
200 return port_added_listener(
201 component_sink, SWIGTYPE_p_bt_component_sink, BT_COMPONENT_CLASS_TYPE_SINK,
202 port_input, SWIGTYPE_p_bt_port_input, BT_PORT_TYPE_INPUT, py_callable);
206 PyObject *bt_bt2_graph_add_port_added_listener(struct bt_graph *graph,
207 PyObject *py_callable)
209 PyObject *py_listener_ids = NULL;
210 PyObject *py_listener_id = NULL;
211 bt_listener_id listener_id;
212 bt_graph_add_listener_status status;
213 const char * const module_name =
214 "graph_add_port_added_listener() (Python)";
217 BT_ASSERT(py_callable);
220 * Behind the scene, we will be registering 4 different listeners and
221 * return all of their ids.
223 py_listener_ids = PyTuple_New(4);
224 if (!py_listener_ids) {
225 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
226 "Failed to allocate one PyTuple.");
230 /* source output port */
231 status = bt_graph_add_source_component_output_port_added_listener(
232 graph, source_component_output_port_added_listener,
233 graph_listener_removed, py_callable, &listener_id);
234 if (status != __BT_FUNC_STATUS_OK) {
236 * bt_graph_add_source_component_output_port_added_listener has
237 * already logged/appended an error cause.
242 py_listener_id = PyLong_FromUnsignedLongLong(listener_id);
243 if (!py_listener_id) {
244 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
245 "Failed to allocate one PyLong.");
249 PyTuple_SET_ITEM(py_listener_ids, 0, py_listener_id);
250 py_listener_id = NULL;
252 /* filter input port */
253 status = bt_graph_add_filter_component_input_port_added_listener(
254 graph, filter_component_input_port_added_listener,
255 graph_listener_removed, py_callable, &listener_id);
256 if (status != __BT_FUNC_STATUS_OK) {
258 * bt_graph_add_filter_component_input_port_added_listener has
259 * already logged/appended an error cause.
264 py_listener_id = PyLong_FromUnsignedLongLong(listener_id);
265 if (!py_listener_id) {
266 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
267 "Failed to allocate one PyLong.");
271 PyTuple_SET_ITEM(py_listener_ids, 1, py_listener_id);
272 py_listener_id = NULL;
274 /* filter output port */
275 status = bt_graph_add_filter_component_output_port_added_listener(
276 graph, filter_component_output_port_added_listener,
277 graph_listener_removed, py_callable, &listener_id);
278 if (status != __BT_FUNC_STATUS_OK) {
280 * bt_graph_add_filter_component_output_port_added_listener has
281 * already logged/appended an error cause.
286 py_listener_id = PyLong_FromUnsignedLongLong(listener_id);
287 if (!py_listener_id) {
288 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
289 "Failed to allocate one PyLong.");
293 PyTuple_SET_ITEM(py_listener_ids, 2, py_listener_id);
294 py_listener_id = NULL;
296 /* sink input port */
297 status = bt_graph_add_sink_component_input_port_added_listener(
298 graph, sink_component_input_port_added_listener,
299 graph_listener_removed, py_callable, &listener_id);
300 if (status != __BT_FUNC_STATUS_OK) {
302 * bt_graph_add_sink_component_input_port_added_listener has
303 * already logged/appended an error cause.
308 py_listener_id = PyLong_FromUnsignedLongLong(listener_id);
309 if (!py_listener_id) {
310 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
311 "Failed to allocate one PyLong.");
316 PyTuple_SET_ITEM(py_listener_ids, 3, py_listener_id);
317 py_listener_id = NULL;
319 Py_INCREF(py_callable);
320 Py_INCREF(py_callable);
321 Py_INCREF(py_callable);
322 Py_INCREF(py_callable);
327 Py_XDECREF(py_listener_ids);
328 py_listener_ids = Py_None;
329 Py_INCREF(py_listener_ids);
333 Py_XDECREF(py_listener_id);
334 return py_listener_ids;
338 bt_graph_listener_func_status ports_connected_listener(
339 const void *upstream_component,
340 swig_type_info *upstream_component_swig_type,
341 bt_component_class_type upstream_component_class_type,
342 const bt_port_output *upstream_port,
343 const void *downstream_component,
344 swig_type_info *downstream_component_swig_type,
345 bt_component_class_type downstream_component_class_type,
346 const bt_port_input *downstream_port,
349 PyObject *py_upstream_component_ptr = NULL;
350 PyObject *py_upstream_port_ptr = NULL;
351 PyObject *py_downstream_component_ptr = NULL;
352 PyObject *py_downstream_port_ptr = NULL;
353 PyObject *py_res = NULL;
354 bt_graph_listener_func_status status;
356 py_upstream_component_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(upstream_component),
357 upstream_component_swig_type, 0);
358 if (!py_upstream_component_ptr) {
359 BT_LOGF_STR("Failed to create upstream component SWIG pointer object.");
360 status = __BT_FUNC_STATUS_MEMORY_ERROR;
364 py_upstream_port_ptr = SWIG_NewPointerObj(
365 SWIG_as_voidptr(upstream_port), SWIGTYPE_p_bt_port_output, 0);
366 if (!py_upstream_port_ptr) {
367 BT_LOGF_STR("Failed to create upstream port SWIG pointer object.");
368 status = __BT_FUNC_STATUS_MEMORY_ERROR;
372 py_downstream_component_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(downstream_component),
373 downstream_component_swig_type, 0);
374 if (!py_downstream_component_ptr) {
375 BT_LOGF_STR("Failed to create downstream component SWIG pointer object.");
376 status = __BT_FUNC_STATUS_MEMORY_ERROR;
380 py_downstream_port_ptr = SWIG_NewPointerObj(
381 SWIG_as_voidptr(downstream_port), SWIGTYPE_p_bt_port_input, 0);
382 if (!py_downstream_port_ptr) {
383 BT_LOGF_STR("Failed to create downstream port SWIG pointer object.");
384 status = __BT_FUNC_STATUS_MEMORY_ERROR;
388 py_res = PyObject_CallFunction(py_callable, "(OiOOiO)",
389 py_upstream_component_ptr, upstream_component_class_type,
390 py_upstream_port_ptr,
391 py_downstream_component_ptr, downstream_component_class_type,
392 py_downstream_port_ptr);
394 loge_exception("Graph's port connected listener (Python)",
395 BT_LOG_OUTPUT_LEVEL);
397 status = __BT_FUNC_STATUS_ERROR;
401 BT_ASSERT(py_res == Py_None);
402 status = __BT_FUNC_STATUS_OK;
405 Py_XDECREF(py_upstream_component_ptr);
406 Py_XDECREF(py_upstream_port_ptr);
407 Py_XDECREF(py_downstream_component_ptr);
408 Py_XDECREF(py_downstream_port_ptr);
414 bt_graph_listener_func_status source_filter_component_ports_connected_listener(
415 const bt_component_source *source_component,
416 const bt_component_filter *filter_component,
417 const bt_port_output *upstream_port,
418 const bt_port_input *downstream_port, void *py_callable)
420 return ports_connected_listener(
421 source_component, SWIGTYPE_p_bt_component_source, BT_COMPONENT_CLASS_TYPE_SOURCE,
423 filter_component, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
429 bt_graph_listener_func_status source_sink_component_ports_connected_listener(
430 const bt_component_source *source_component,
431 const bt_component_sink *sink_component,
432 const bt_port_output *upstream_port,
433 const bt_port_input *downstream_port, void *py_callable)
435 return ports_connected_listener(
436 source_component, SWIGTYPE_p_bt_component_source, BT_COMPONENT_CLASS_TYPE_SOURCE,
438 sink_component, SWIGTYPE_p_bt_component_sink, BT_COMPONENT_CLASS_TYPE_SINK,
444 bt_graph_listener_func_status filter_filter_component_ports_connected_listener(
445 const bt_component_filter *filter_component_left,
446 const bt_component_filter *filter_component_right,
447 const bt_port_output *upstream_port,
448 const bt_port_input *downstream_port, void *py_callable)
450 return ports_connected_listener(
451 filter_component_left, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
453 filter_component_right, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
459 bt_graph_listener_func_status filter_sink_component_ports_connected_listener(
460 const bt_component_filter *filter_component,
461 const bt_component_sink *sink_component,
462 const bt_port_output *upstream_port,
463 const bt_port_input *downstream_port, void *py_callable)
465 return ports_connected_listener(
466 filter_component, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
468 sink_component, SWIGTYPE_p_bt_component_sink, BT_COMPONENT_CLASS_TYPE_SINK,
474 PyObject *bt_bt2_graph_add_ports_connected_listener(struct bt_graph *graph,
475 PyObject *py_callable)
477 PyObject *py_listener_ids = NULL;
478 PyObject *py_listener_id = NULL;
479 bt_listener_id listener_id;
480 bt_graph_add_listener_status status;
481 const char * const module_name =
482 "graph_add_ports_connected_listener() (Python)";
485 BT_ASSERT(py_callable);
487 /* Behind the scene, we will be registering 4 different listeners and
488 * return all of their ids. */
489 py_listener_ids = PyTuple_New(4);
490 if (!py_listener_ids) {
491 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
492 "Failed to allocate one PyTuple.");
496 /* source -> filter connection */
497 status = bt_graph_add_source_filter_component_ports_connected_listener(
498 graph, source_filter_component_ports_connected_listener,
499 graph_listener_removed, py_callable, &listener_id);
500 if (status != __BT_FUNC_STATUS_OK) {
502 * bt_graph_add_source_filter_component_ports_connected_listener
503 * has already logged/appended an error cause.
508 py_listener_id = PyLong_FromUnsignedLongLong(listener_id);
509 if (!py_listener_id) {
510 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
511 "Failed to allocate one PyLong.");
515 PyTuple_SET_ITEM(py_listener_ids, 0, py_listener_id);
516 py_listener_id = NULL;
518 /* source -> sink connection */
519 status = bt_graph_add_source_sink_component_ports_connected_listener(
520 graph, source_sink_component_ports_connected_listener,
521 graph_listener_removed, py_callable, &listener_id);
522 if (status != __BT_FUNC_STATUS_OK) {
524 * bt_graph_add_source_sink_component_ports_connected_listener
525 * has already logged/appended an error cause.
530 py_listener_id = PyLong_FromUnsignedLongLong(listener_id);
531 if (!py_listener_id) {
532 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
533 "Failed to allocate one PyLong.");
537 PyTuple_SET_ITEM(py_listener_ids, 1, py_listener_id);
538 py_listener_id = NULL;
540 /* filter -> filter connection */
541 status = bt_graph_add_filter_filter_component_ports_connected_listener(
542 graph, filter_filter_component_ports_connected_listener,
543 graph_listener_removed, py_callable, &listener_id);
544 if (status != __BT_FUNC_STATUS_OK) {
546 * bt_graph_add_filter_filter_component_ports_connected_listener
547 * has already logged/appended an error cause.
552 py_listener_id = PyLong_FromUnsignedLongLong(listener_id);
553 if (!py_listener_id) {
554 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
555 "Failed to allocate one PyLong.");
559 PyTuple_SET_ITEM(py_listener_ids, 2, py_listener_id);
560 py_listener_id = NULL;
562 /* filter -> sink connection */
563 status = bt_graph_add_filter_sink_component_ports_connected_listener(
564 graph, filter_sink_component_ports_connected_listener,
565 graph_listener_removed, py_callable, &listener_id);
566 if (status != __BT_FUNC_STATUS_OK) {
568 * bt_graph_add_filter_sink_component_ports_connected_listener
569 * has already logged/appended an error cause.
574 py_listener_id = PyLong_FromUnsignedLongLong(listener_id);
575 if (!py_listener_id) {
576 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name,
577 "Failed to allocate one PyLong.");
581 PyTuple_SET_ITEM(py_listener_ids, 3, py_listener_id);
582 py_listener_id = NULL;
584 Py_INCREF(py_callable);
585 Py_INCREF(py_callable);
586 Py_INCREF(py_callable);
587 Py_INCREF(py_callable);
592 Py_XDECREF(py_listener_ids);
593 py_listener_ids = Py_None;
594 Py_INCREF(py_listener_ids);
598 Py_XDECREF(py_listener_id);
599 return py_listener_ids;
603 PyObject *bt_bt2_graph_add_port_added_listener(struct bt_graph *graph,
604 PyObject *py_callable);
605 PyObject *bt_bt2_graph_add_ports_connected_listener(struct bt_graph *graph,
606 PyObject *py_callable);