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
26 void graph_listener_removed(void *py_callable
)
28 BT_ASSERT(py_callable
);
29 Py_DECREF(py_callable
);
32 static bt_graph_listener_func_status
port_added_listener(
33 const void *component
,
34 swig_type_info
*component_swig_type
,
35 bt_component_class_type component_class_type
,
37 swig_type_info
*port_swig_type
,
38 bt_port_type port_type
,
41 PyObject
*py_component_ptr
= NULL
;
42 PyObject
*py_port_ptr
= NULL
;
43 PyObject
*py_res
= NULL
;
44 bt_graph_listener_func_status status
;
46 py_component_ptr
= SWIG_NewPointerObj(SWIG_as_voidptr(component
), component_swig_type
, 0);
47 if (!py_component_ptr
) {
48 BT_LOGF_STR("Failed to create component SWIG pointer object.");
49 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
53 py_port_ptr
= SWIG_NewPointerObj(SWIG_as_voidptr(port
), port_swig_type
, 0);
55 BT_LOGF_STR("Failed to create port SWIG pointer object.");
56 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
60 py_res
= PyObject_CallFunction(py_callable
, "(OiOi)",
61 py_component_ptr
, component_class_type
, py_port_ptr
, port_type
);
63 loge_exception_append_cause(
64 "Graph's port added listener (Python)",
67 status
= __BT_FUNC_STATUS_ERROR
;
71 BT_ASSERT(py_res
== Py_None
);
72 status
= __BT_FUNC_STATUS_OK
;
76 Py_XDECREF(py_port_ptr
);
77 Py_XDECREF(py_component_ptr
);
82 bt_graph_listener_func_status
83 source_component_output_port_added_listener(const bt_component_source
*component_source
,
84 const bt_port_output
*port_output
, void *py_callable
)
86 return port_added_listener(
87 component_source
, SWIGTYPE_p_bt_component_source
, BT_COMPONENT_CLASS_TYPE_SOURCE
,
88 port_output
, SWIGTYPE_p_bt_port_output
, BT_PORT_TYPE_OUTPUT
, py_callable
);
92 bt_graph_listener_func_status
93 filter_component_input_port_added_listener(const bt_component_filter
*component_filter
,
94 const bt_port_input
*port_input
, void *py_callable
)
96 return port_added_listener(
97 component_filter
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
98 port_input
, SWIGTYPE_p_bt_port_input
, BT_PORT_TYPE_INPUT
, py_callable
);
102 bt_graph_listener_func_status
103 filter_component_output_port_added_listener(const bt_component_filter
*component_filter
,
104 const bt_port_output
*port_output
, void *py_callable
)
106 return port_added_listener(
107 component_filter
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
108 port_output
, SWIGTYPE_p_bt_port_output
, BT_PORT_TYPE_OUTPUT
, py_callable
);
112 bt_graph_listener_func_status
113 sink_component_input_port_added_listener(const bt_component_sink
*component_sink
,
114 const bt_port_input
*port_input
, void *py_callable
)
116 return port_added_listener(
117 component_sink
, SWIGTYPE_p_bt_component_sink
, BT_COMPONENT_CLASS_TYPE_SINK
,
118 port_input
, SWIGTYPE_p_bt_port_input
, BT_PORT_TYPE_INPUT
, py_callable
);
122 PyObject
*bt_bt2_graph_add_port_added_listener(struct bt_graph
*graph
,
123 PyObject
*py_callable
)
125 PyObject
*py_listener_ids
= NULL
;
126 PyObject
*py_listener_id
= NULL
;
127 bt_listener_id listener_id
;
128 bt_graph_add_listener_status status
;
129 const char * const module_name
=
130 "graph_add_port_added_listener() (Python)";
133 BT_ASSERT(py_callable
);
136 * Behind the scene, we will be registering 4 different listeners and
137 * return all of their ids.
139 py_listener_ids
= PyTuple_New(4);
140 if (!py_listener_ids
) {
141 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
142 "Failed to allocate one PyTuple.");
146 /* source output port */
147 status
= bt_graph_add_source_component_output_port_added_listener(
148 graph
, source_component_output_port_added_listener
,
149 graph_listener_removed
, py_callable
, &listener_id
);
150 if (status
!= __BT_FUNC_STATUS_OK
) {
152 * bt_graph_add_source_component_output_port_added_listener has
153 * already logged/appended an error cause.
158 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
159 if (!py_listener_id
) {
160 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
161 "Failed to allocate one PyLong.");
165 PyTuple_SET_ITEM(py_listener_ids
, 0, py_listener_id
);
166 py_listener_id
= NULL
;
168 /* filter input port */
169 status
= bt_graph_add_filter_component_input_port_added_listener(
170 graph
, filter_component_input_port_added_listener
,
171 graph_listener_removed
, py_callable
, &listener_id
);
172 if (status
!= __BT_FUNC_STATUS_OK
) {
174 * bt_graph_add_filter_component_input_port_added_listener has
175 * already logged/appended an error cause.
180 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
181 if (!py_listener_id
) {
182 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
183 "Failed to allocate one PyLong.");
187 PyTuple_SET_ITEM(py_listener_ids
, 1, py_listener_id
);
188 py_listener_id
= NULL
;
190 /* filter output port */
191 status
= bt_graph_add_filter_component_output_port_added_listener(
192 graph
, filter_component_output_port_added_listener
,
193 graph_listener_removed
, py_callable
, &listener_id
);
194 if (status
!= __BT_FUNC_STATUS_OK
) {
196 * bt_graph_add_filter_component_output_port_added_listener has
197 * already logged/appended an error cause.
202 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
203 if (!py_listener_id
) {
204 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
205 "Failed to allocate one PyLong.");
209 PyTuple_SET_ITEM(py_listener_ids
, 2, py_listener_id
);
210 py_listener_id
= NULL
;
212 /* sink input port */
213 status
= bt_graph_add_sink_component_input_port_added_listener(
214 graph
, sink_component_input_port_added_listener
,
215 graph_listener_removed
, py_callable
, &listener_id
);
216 if (status
!= __BT_FUNC_STATUS_OK
) {
218 * bt_graph_add_sink_component_input_port_added_listener has
219 * already logged/appended an error cause.
224 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
225 if (!py_listener_id
) {
226 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
227 "Failed to allocate one PyLong.");
231 PyTuple_SET_ITEM(py_listener_ids
, 3, py_listener_id
);
232 py_listener_id
= NULL
;
234 Py_INCREF(py_callable
);
235 Py_INCREF(py_callable
);
236 Py_INCREF(py_callable
);
237 Py_INCREF(py_callable
);
242 Py_XDECREF(py_listener_ids
);
243 py_listener_ids
= Py_None
;
244 Py_INCREF(py_listener_ids
);
247 Py_XDECREF(py_listener_id
);
248 return py_listener_ids
;
252 bt_graph_listener_func_status
ports_connected_listener(
253 const void *upstream_component
,
254 swig_type_info
*upstream_component_swig_type
,
255 bt_component_class_type upstream_component_class_type
,
256 const bt_port_output
*upstream_port
,
257 const void *downstream_component
,
258 swig_type_info
*downstream_component_swig_type
,
259 bt_component_class_type downstream_component_class_type
,
260 const bt_port_input
*downstream_port
,
263 PyObject
*py_upstream_component_ptr
= NULL
;
264 PyObject
*py_upstream_port_ptr
= NULL
;
265 PyObject
*py_downstream_component_ptr
= NULL
;
266 PyObject
*py_downstream_port_ptr
= NULL
;
267 PyObject
*py_res
= NULL
;
268 bt_graph_listener_func_status status
;
270 py_upstream_component_ptr
= SWIG_NewPointerObj(SWIG_as_voidptr(upstream_component
),
271 upstream_component_swig_type
, 0);
272 if (!py_upstream_component_ptr
) {
273 BT_LOGF_STR("Failed to create upstream component SWIG pointer object.");
274 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
278 py_upstream_port_ptr
= SWIG_NewPointerObj(
279 SWIG_as_voidptr(upstream_port
), SWIGTYPE_p_bt_port_output
, 0);
280 if (!py_upstream_port_ptr
) {
281 BT_LOGF_STR("Failed to create upstream port SWIG pointer object.");
282 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
286 py_downstream_component_ptr
= SWIG_NewPointerObj(SWIG_as_voidptr(downstream_component
),
287 downstream_component_swig_type
, 0);
288 if (!py_downstream_component_ptr
) {
289 BT_LOGF_STR("Failed to create downstream component SWIG pointer object.");
290 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
294 py_downstream_port_ptr
= SWIG_NewPointerObj(
295 SWIG_as_voidptr(downstream_port
), SWIGTYPE_p_bt_port_input
, 0);
296 if (!py_downstream_port_ptr
) {
297 BT_LOGF_STR("Failed to create downstream port SWIG pointer object.");
298 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
302 py_res
= PyObject_CallFunction(py_callable
, "(OiOOiO)",
303 py_upstream_component_ptr
, upstream_component_class_type
,
304 py_upstream_port_ptr
,
305 py_downstream_component_ptr
, downstream_component_class_type
,
306 py_downstream_port_ptr
);
308 loge_exception_append_cause(
309 "Graph's port connected listener (Python)",
310 BT_LOG_OUTPUT_LEVEL
);
312 status
= __BT_FUNC_STATUS_ERROR
;
316 BT_ASSERT(py_res
== Py_None
);
317 status
= __BT_FUNC_STATUS_OK
;
320 Py_XDECREF(py_upstream_component_ptr
);
321 Py_XDECREF(py_upstream_port_ptr
);
322 Py_XDECREF(py_downstream_component_ptr
);
323 Py_XDECREF(py_downstream_port_ptr
);
329 bt_graph_listener_func_status
source_filter_component_ports_connected_listener(
330 const bt_component_source
*source_component
,
331 const bt_component_filter
*filter_component
,
332 const bt_port_output
*upstream_port
,
333 const bt_port_input
*downstream_port
, void *py_callable
)
335 return ports_connected_listener(
336 source_component
, SWIGTYPE_p_bt_component_source
, BT_COMPONENT_CLASS_TYPE_SOURCE
,
338 filter_component
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
344 bt_graph_listener_func_status
source_sink_component_ports_connected_listener(
345 const bt_component_source
*source_component
,
346 const bt_component_sink
*sink_component
,
347 const bt_port_output
*upstream_port
,
348 const bt_port_input
*downstream_port
, void *py_callable
)
350 return ports_connected_listener(
351 source_component
, SWIGTYPE_p_bt_component_source
, BT_COMPONENT_CLASS_TYPE_SOURCE
,
353 sink_component
, SWIGTYPE_p_bt_component_sink
, BT_COMPONENT_CLASS_TYPE_SINK
,
359 bt_graph_listener_func_status
filter_filter_component_ports_connected_listener(
360 const bt_component_filter
*filter_component_left
,
361 const bt_component_filter
*filter_component_right
,
362 const bt_port_output
*upstream_port
,
363 const bt_port_input
*downstream_port
, void *py_callable
)
365 return ports_connected_listener(
366 filter_component_left
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
368 filter_component_right
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
374 bt_graph_listener_func_status
filter_sink_component_ports_connected_listener(
375 const bt_component_filter
*filter_component
,
376 const bt_component_sink
*sink_component
,
377 const bt_port_output
*upstream_port
,
378 const bt_port_input
*downstream_port
, void *py_callable
)
380 return ports_connected_listener(
381 filter_component
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
383 sink_component
, SWIGTYPE_p_bt_component_sink
, BT_COMPONENT_CLASS_TYPE_SINK
,
389 PyObject
*bt_bt2_graph_add_ports_connected_listener(struct bt_graph
*graph
,
390 PyObject
*py_callable
)
392 PyObject
*py_listener_ids
= NULL
;
393 PyObject
*py_listener_id
= NULL
;
394 bt_listener_id listener_id
;
395 bt_graph_add_listener_status status
;
396 const char * const module_name
=
397 "graph_add_ports_connected_listener() (Python)";
400 BT_ASSERT(py_callable
);
402 /* Behind the scene, we will be registering 4 different listeners and
403 * return all of their ids. */
404 py_listener_ids
= PyTuple_New(4);
405 if (!py_listener_ids
) {
406 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
407 "Failed to allocate one PyTuple.");
411 /* source -> filter connection */
412 status
= bt_graph_add_source_filter_component_ports_connected_listener(
413 graph
, source_filter_component_ports_connected_listener
,
414 graph_listener_removed
, py_callable
, &listener_id
);
415 if (status
!= __BT_FUNC_STATUS_OK
) {
417 * bt_graph_add_source_filter_component_ports_connected_listener
418 * has already logged/appended an error cause.
423 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
424 if (!py_listener_id
) {
425 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
426 "Failed to allocate one PyLong.");
430 PyTuple_SET_ITEM(py_listener_ids
, 0, py_listener_id
);
431 py_listener_id
= NULL
;
433 /* source -> sink connection */
434 status
= bt_graph_add_source_sink_component_ports_connected_listener(
435 graph
, source_sink_component_ports_connected_listener
,
436 graph_listener_removed
, py_callable
, &listener_id
);
437 if (status
!= __BT_FUNC_STATUS_OK
) {
439 * bt_graph_add_source_sink_component_ports_connected_listener
440 * has already logged/appended an error cause.
445 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
446 if (!py_listener_id
) {
447 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
448 "Failed to allocate one PyLong.");
452 PyTuple_SET_ITEM(py_listener_ids
, 1, py_listener_id
);
453 py_listener_id
= NULL
;
455 /* filter -> filter connection */
456 status
= bt_graph_add_filter_filter_component_ports_connected_listener(
457 graph
, filter_filter_component_ports_connected_listener
,
458 graph_listener_removed
, py_callable
, &listener_id
);
459 if (status
!= __BT_FUNC_STATUS_OK
) {
461 * bt_graph_add_filter_filter_component_ports_connected_listener
462 * has already logged/appended an error cause.
467 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
468 if (!py_listener_id
) {
469 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
470 "Failed to allocate one PyLong.");
474 PyTuple_SET_ITEM(py_listener_ids
, 2, py_listener_id
);
475 py_listener_id
= NULL
;
477 /* filter -> sink connection */
478 status
= bt_graph_add_filter_sink_component_ports_connected_listener(
479 graph
, filter_sink_component_ports_connected_listener
,
480 graph_listener_removed
, py_callable
, &listener_id
);
481 if (status
!= __BT_FUNC_STATUS_OK
) {
483 * bt_graph_add_filter_sink_component_ports_connected_listener
484 * has already logged/appended an error cause.
489 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
490 if (!py_listener_id
) {
491 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
492 "Failed to allocate one PyLong.");
496 PyTuple_SET_ITEM(py_listener_ids
, 3, py_listener_id
);
497 py_listener_id
= NULL
;
499 Py_INCREF(py_callable
);
500 Py_INCREF(py_callable
);
501 Py_INCREF(py_callable
);
502 Py_INCREF(py_callable
);
507 Py_XDECREF(py_listener_ids
);
508 py_listener_ids
= Py_None
;
509 Py_INCREF(py_listener_ids
);
513 Py_XDECREF(py_listener_id
);
514 return py_listener_ids
;
518 bt_graph_add_component_status
519 bt_bt2_graph_add_source_component(
521 const bt_component_class_source
*component_class
,
522 const char *name
, const bt_value
*params
,
523 PyObject
*obj
, bt_logging_level log_level
,
524 const bt_component_source
**component
)
526 return bt_graph_add_source_component_with_initialize_method_data(graph
,
527 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
528 log_level
, component
);
532 bt_graph_add_component_status
533 bt_bt2_graph_add_filter_component(
535 const bt_component_class_filter
*component_class
,
536 const char *name
, const bt_value
*params
,
537 PyObject
*obj
, bt_logging_level log_level
,
538 const bt_component_filter
**component
)
540 return bt_graph_add_filter_component_with_initialize_method_data(graph
,
541 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
542 log_level
, component
);
546 bt_graph_add_component_status
547 bt_bt2_graph_add_sink_component(
549 const bt_component_class_sink
*component_class
,
550 const char *name
, const bt_value
*params
,
551 PyObject
*obj
, bt_logging_level log_level
,
552 const bt_component_sink
**component
)
554 return bt_graph_add_sink_component_with_initialize_method_data(graph
,
555 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
556 log_level
, component
);