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_clear(
64 "Graph's port added listener (Python)",
66 status
= __BT_FUNC_STATUS_ERROR
;
70 BT_ASSERT(py_res
== Py_None
);
71 status
= __BT_FUNC_STATUS_OK
;
75 Py_XDECREF(py_port_ptr
);
76 Py_XDECREF(py_component_ptr
);
81 bt_graph_listener_func_status
82 source_component_output_port_added_listener(const bt_component_source
*component_source
,
83 const bt_port_output
*port_output
, void *py_callable
)
85 return port_added_listener(
86 component_source
, SWIGTYPE_p_bt_component_source
, BT_COMPONENT_CLASS_TYPE_SOURCE
,
87 port_output
, SWIGTYPE_p_bt_port_output
, BT_PORT_TYPE_OUTPUT
, py_callable
);
91 bt_graph_listener_func_status
92 filter_component_input_port_added_listener(const bt_component_filter
*component_filter
,
93 const bt_port_input
*port_input
, void *py_callable
)
95 return port_added_listener(
96 component_filter
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
97 port_input
, SWIGTYPE_p_bt_port_input
, BT_PORT_TYPE_INPUT
, py_callable
);
101 bt_graph_listener_func_status
102 filter_component_output_port_added_listener(const bt_component_filter
*component_filter
,
103 const bt_port_output
*port_output
, void *py_callable
)
105 return port_added_listener(
106 component_filter
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
107 port_output
, SWIGTYPE_p_bt_port_output
, BT_PORT_TYPE_OUTPUT
, py_callable
);
111 bt_graph_listener_func_status
112 sink_component_input_port_added_listener(const bt_component_sink
*component_sink
,
113 const bt_port_input
*port_input
, void *py_callable
)
115 return port_added_listener(
116 component_sink
, SWIGTYPE_p_bt_component_sink
, BT_COMPONENT_CLASS_TYPE_SINK
,
117 port_input
, SWIGTYPE_p_bt_port_input
, BT_PORT_TYPE_INPUT
, py_callable
);
121 PyObject
*bt_bt2_graph_add_port_added_listener(struct bt_graph
*graph
,
122 PyObject
*py_callable
)
124 PyObject
*py_listener_ids
= NULL
;
125 PyObject
*py_listener_id
= NULL
;
126 bt_listener_id listener_id
;
127 bt_graph_add_listener_status status
;
128 const char * const module_name
=
129 "graph_add_port_added_listener() (Python)";
132 BT_ASSERT(py_callable
);
135 * Behind the scene, we will be registering 4 different listeners and
136 * return all of their ids.
138 py_listener_ids
= PyTuple_New(4);
139 if (!py_listener_ids
) {
140 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
141 "Failed to allocate one PyTuple.");
145 /* source output port */
146 status
= bt_graph_add_source_component_output_port_added_listener(
147 graph
, source_component_output_port_added_listener
,
148 graph_listener_removed
, py_callable
, &listener_id
);
149 if (status
!= __BT_FUNC_STATUS_OK
) {
151 * bt_graph_add_source_component_output_port_added_listener has
152 * already logged/appended an error cause.
157 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
158 if (!py_listener_id
) {
159 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
160 "Failed to allocate one PyLong.");
164 PyTuple_SET_ITEM(py_listener_ids
, 0, py_listener_id
);
165 py_listener_id
= NULL
;
167 /* filter input port */
168 status
= bt_graph_add_filter_component_input_port_added_listener(
169 graph
, filter_component_input_port_added_listener
,
170 graph_listener_removed
, py_callable
, &listener_id
);
171 if (status
!= __BT_FUNC_STATUS_OK
) {
173 * bt_graph_add_filter_component_input_port_added_listener has
174 * already logged/appended an error cause.
179 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
180 if (!py_listener_id
) {
181 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
182 "Failed to allocate one PyLong.");
186 PyTuple_SET_ITEM(py_listener_ids
, 1, py_listener_id
);
187 py_listener_id
= NULL
;
189 /* filter output port */
190 status
= bt_graph_add_filter_component_output_port_added_listener(
191 graph
, filter_component_output_port_added_listener
,
192 graph_listener_removed
, py_callable
, &listener_id
);
193 if (status
!= __BT_FUNC_STATUS_OK
) {
195 * bt_graph_add_filter_component_output_port_added_listener has
196 * already logged/appended an error cause.
201 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
202 if (!py_listener_id
) {
203 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
204 "Failed to allocate one PyLong.");
208 PyTuple_SET_ITEM(py_listener_ids
, 2, py_listener_id
);
209 py_listener_id
= NULL
;
211 /* sink input port */
212 status
= bt_graph_add_sink_component_input_port_added_listener(
213 graph
, sink_component_input_port_added_listener
,
214 graph_listener_removed
, py_callable
, &listener_id
);
215 if (status
!= __BT_FUNC_STATUS_OK
) {
217 * bt_graph_add_sink_component_input_port_added_listener has
218 * already logged/appended an error cause.
223 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
224 if (!py_listener_id
) {
225 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
226 "Failed to allocate one PyLong.");
230 PyTuple_SET_ITEM(py_listener_ids
, 3, py_listener_id
);
231 py_listener_id
= NULL
;
233 Py_INCREF(py_callable
);
234 Py_INCREF(py_callable
);
235 Py_INCREF(py_callable
);
236 Py_INCREF(py_callable
);
241 Py_XDECREF(py_listener_ids
);
242 py_listener_ids
= Py_None
;
243 Py_INCREF(py_listener_ids
);
246 Py_XDECREF(py_listener_id
);
247 return py_listener_ids
;
251 bt_graph_listener_func_status
ports_connected_listener(
252 const void *upstream_component
,
253 swig_type_info
*upstream_component_swig_type
,
254 bt_component_class_type upstream_component_class_type
,
255 const bt_port_output
*upstream_port
,
256 const void *downstream_component
,
257 swig_type_info
*downstream_component_swig_type
,
258 bt_component_class_type downstream_component_class_type
,
259 const bt_port_input
*downstream_port
,
262 PyObject
*py_upstream_component_ptr
= NULL
;
263 PyObject
*py_upstream_port_ptr
= NULL
;
264 PyObject
*py_downstream_component_ptr
= NULL
;
265 PyObject
*py_downstream_port_ptr
= NULL
;
266 PyObject
*py_res
= NULL
;
267 bt_graph_listener_func_status status
;
269 py_upstream_component_ptr
= SWIG_NewPointerObj(SWIG_as_voidptr(upstream_component
),
270 upstream_component_swig_type
, 0);
271 if (!py_upstream_component_ptr
) {
272 BT_LOGF_STR("Failed to create upstream component SWIG pointer object.");
273 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
277 py_upstream_port_ptr
= SWIG_NewPointerObj(
278 SWIG_as_voidptr(upstream_port
), SWIGTYPE_p_bt_port_output
, 0);
279 if (!py_upstream_port_ptr
) {
280 BT_LOGF_STR("Failed to create upstream port SWIG pointer object.");
281 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
285 py_downstream_component_ptr
= SWIG_NewPointerObj(SWIG_as_voidptr(downstream_component
),
286 downstream_component_swig_type
, 0);
287 if (!py_downstream_component_ptr
) {
288 BT_LOGF_STR("Failed to create downstream component SWIG pointer object.");
289 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
293 py_downstream_port_ptr
= SWIG_NewPointerObj(
294 SWIG_as_voidptr(downstream_port
), SWIGTYPE_p_bt_port_input
, 0);
295 if (!py_downstream_port_ptr
) {
296 BT_LOGF_STR("Failed to create downstream port SWIG pointer object.");
297 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
301 py_res
= PyObject_CallFunction(py_callable
, "(OiOOiO)",
302 py_upstream_component_ptr
, upstream_component_class_type
,
303 py_upstream_port_ptr
,
304 py_downstream_component_ptr
, downstream_component_class_type
,
305 py_downstream_port_ptr
);
307 loge_exception_append_cause_clear(
308 "Graph's port connected listener (Python)",
309 BT_LOG_OUTPUT_LEVEL
);
310 status
= __BT_FUNC_STATUS_ERROR
;
314 BT_ASSERT(py_res
== Py_None
);
315 status
= __BT_FUNC_STATUS_OK
;
318 Py_XDECREF(py_upstream_component_ptr
);
319 Py_XDECREF(py_upstream_port_ptr
);
320 Py_XDECREF(py_downstream_component_ptr
);
321 Py_XDECREF(py_downstream_port_ptr
);
327 bt_graph_listener_func_status
source_filter_component_ports_connected_listener(
328 const bt_component_source
*source_component
,
329 const bt_component_filter
*filter_component
,
330 const bt_port_output
*upstream_port
,
331 const bt_port_input
*downstream_port
, void *py_callable
)
333 return ports_connected_listener(
334 source_component
, SWIGTYPE_p_bt_component_source
, BT_COMPONENT_CLASS_TYPE_SOURCE
,
336 filter_component
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
342 bt_graph_listener_func_status
source_sink_component_ports_connected_listener(
343 const bt_component_source
*source_component
,
344 const bt_component_sink
*sink_component
,
345 const bt_port_output
*upstream_port
,
346 const bt_port_input
*downstream_port
, void *py_callable
)
348 return ports_connected_listener(
349 source_component
, SWIGTYPE_p_bt_component_source
, BT_COMPONENT_CLASS_TYPE_SOURCE
,
351 sink_component
, SWIGTYPE_p_bt_component_sink
, BT_COMPONENT_CLASS_TYPE_SINK
,
357 bt_graph_listener_func_status
filter_filter_component_ports_connected_listener(
358 const bt_component_filter
*filter_component_left
,
359 const bt_component_filter
*filter_component_right
,
360 const bt_port_output
*upstream_port
,
361 const bt_port_input
*downstream_port
, void *py_callable
)
363 return ports_connected_listener(
364 filter_component_left
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
366 filter_component_right
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
372 bt_graph_listener_func_status
filter_sink_component_ports_connected_listener(
373 const bt_component_filter
*filter_component
,
374 const bt_component_sink
*sink_component
,
375 const bt_port_output
*upstream_port
,
376 const bt_port_input
*downstream_port
, void *py_callable
)
378 return ports_connected_listener(
379 filter_component
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
381 sink_component
, SWIGTYPE_p_bt_component_sink
, BT_COMPONENT_CLASS_TYPE_SINK
,
387 PyObject
*bt_bt2_graph_add_ports_connected_listener(struct bt_graph
*graph
,
388 PyObject
*py_callable
)
390 PyObject
*py_listener_ids
= NULL
;
391 PyObject
*py_listener_id
= NULL
;
392 bt_listener_id listener_id
;
393 bt_graph_add_listener_status status
;
394 const char * const module_name
=
395 "graph_add_ports_connected_listener() (Python)";
398 BT_ASSERT(py_callable
);
400 /* Behind the scene, we will be registering 4 different listeners and
401 * return all of their ids. */
402 py_listener_ids
= PyTuple_New(4);
403 if (!py_listener_ids
) {
404 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
405 "Failed to allocate one PyTuple.");
409 /* source -> filter connection */
410 status
= bt_graph_add_source_filter_component_ports_connected_listener(
411 graph
, source_filter_component_ports_connected_listener
,
412 graph_listener_removed
, py_callable
, &listener_id
);
413 if (status
!= __BT_FUNC_STATUS_OK
) {
415 * bt_graph_add_source_filter_component_ports_connected_listener
416 * has already logged/appended an error cause.
421 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
422 if (!py_listener_id
) {
423 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
424 "Failed to allocate one PyLong.");
428 PyTuple_SET_ITEM(py_listener_ids
, 0, py_listener_id
);
429 py_listener_id
= NULL
;
431 /* source -> sink connection */
432 status
= bt_graph_add_source_sink_component_ports_connected_listener(
433 graph
, source_sink_component_ports_connected_listener
,
434 graph_listener_removed
, py_callable
, &listener_id
);
435 if (status
!= __BT_FUNC_STATUS_OK
) {
437 * bt_graph_add_source_sink_component_ports_connected_listener
438 * has already logged/appended an error cause.
443 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
444 if (!py_listener_id
) {
445 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
446 "Failed to allocate one PyLong.");
450 PyTuple_SET_ITEM(py_listener_ids
, 1, py_listener_id
);
451 py_listener_id
= NULL
;
453 /* filter -> filter connection */
454 status
= bt_graph_add_filter_filter_component_ports_connected_listener(
455 graph
, filter_filter_component_ports_connected_listener
,
456 graph_listener_removed
, py_callable
, &listener_id
);
457 if (status
!= __BT_FUNC_STATUS_OK
) {
459 * bt_graph_add_filter_filter_component_ports_connected_listener
460 * has already logged/appended an error cause.
465 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
466 if (!py_listener_id
) {
467 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
468 "Failed to allocate one PyLong.");
472 PyTuple_SET_ITEM(py_listener_ids
, 2, py_listener_id
);
473 py_listener_id
= NULL
;
475 /* filter -> sink connection */
476 status
= bt_graph_add_filter_sink_component_ports_connected_listener(
477 graph
, filter_sink_component_ports_connected_listener
,
478 graph_listener_removed
, py_callable
, &listener_id
);
479 if (status
!= __BT_FUNC_STATUS_OK
) {
481 * bt_graph_add_filter_sink_component_ports_connected_listener
482 * has already logged/appended an error cause.
487 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
488 if (!py_listener_id
) {
489 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
490 "Failed to allocate one PyLong.");
494 PyTuple_SET_ITEM(py_listener_ids
, 3, py_listener_id
);
495 py_listener_id
= NULL
;
497 Py_INCREF(py_callable
);
498 Py_INCREF(py_callable
);
499 Py_INCREF(py_callable
);
500 Py_INCREF(py_callable
);
505 Py_XDECREF(py_listener_ids
);
506 py_listener_ids
= Py_None
;
507 Py_INCREF(py_listener_ids
);
511 Py_XDECREF(py_listener_id
);
512 return py_listener_ids
;
516 bt_graph_add_component_status
517 bt_bt2_graph_add_source_component(
519 const bt_component_class_source
*component_class
,
520 const char *name
, const bt_value
*params
,
521 PyObject
*obj
, bt_logging_level log_level
,
522 const bt_component_source
**component
)
524 return bt_graph_add_source_component_with_initialize_method_data(graph
,
525 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
526 log_level
, component
);
530 bt_graph_add_component_status
531 bt_bt2_graph_add_filter_component(
533 const bt_component_class_filter
*component_class
,
534 const char *name
, const bt_value
*params
,
535 PyObject
*obj
, bt_logging_level log_level
,
536 const bt_component_filter
**component
)
538 return bt_graph_add_filter_component_with_initialize_method_data(graph
,
539 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
540 log_level
, component
);
544 bt_graph_add_component_status
545 bt_bt2_graph_add_sink_component(
547 const bt_component_class_sink
*component_class
,
548 const char *name
, const bt_value
*params
,
549 PyObject
*obj
, bt_logging_level log_level
,
550 const bt_component_sink
**component
)
552 return bt_graph_add_sink_component_with_initialize_method_data(graph
,
553 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
554 log_level
, component
);