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.");
232 PyTuple_SET_ITEM(py_listener_ids
, 3, py_listener_id
);
233 py_listener_id
= NULL
;
235 Py_INCREF(py_callable
);
236 Py_INCREF(py_callable
);
237 Py_INCREF(py_callable
);
238 Py_INCREF(py_callable
);
243 Py_XDECREF(py_listener_ids
);
244 py_listener_ids
= Py_None
;
245 Py_INCREF(py_listener_ids
);
249 Py_XDECREF(py_listener_id
);
250 return py_listener_ids
;
254 bt_graph_listener_func_status
ports_connected_listener(
255 const void *upstream_component
,
256 swig_type_info
*upstream_component_swig_type
,
257 bt_component_class_type upstream_component_class_type
,
258 const bt_port_output
*upstream_port
,
259 const void *downstream_component
,
260 swig_type_info
*downstream_component_swig_type
,
261 bt_component_class_type downstream_component_class_type
,
262 const bt_port_input
*downstream_port
,
265 PyObject
*py_upstream_component_ptr
= NULL
;
266 PyObject
*py_upstream_port_ptr
= NULL
;
267 PyObject
*py_downstream_component_ptr
= NULL
;
268 PyObject
*py_downstream_port_ptr
= NULL
;
269 PyObject
*py_res
= NULL
;
270 bt_graph_listener_func_status status
;
272 py_upstream_component_ptr
= SWIG_NewPointerObj(SWIG_as_voidptr(upstream_component
),
273 upstream_component_swig_type
, 0);
274 if (!py_upstream_component_ptr
) {
275 BT_LOGF_STR("Failed to create upstream component SWIG pointer object.");
276 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
280 py_upstream_port_ptr
= SWIG_NewPointerObj(
281 SWIG_as_voidptr(upstream_port
), SWIGTYPE_p_bt_port_output
, 0);
282 if (!py_upstream_port_ptr
) {
283 BT_LOGF_STR("Failed to create upstream port SWIG pointer object.");
284 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
288 py_downstream_component_ptr
= SWIG_NewPointerObj(SWIG_as_voidptr(downstream_component
),
289 downstream_component_swig_type
, 0);
290 if (!py_downstream_component_ptr
) {
291 BT_LOGF_STR("Failed to create downstream component SWIG pointer object.");
292 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
296 py_downstream_port_ptr
= SWIG_NewPointerObj(
297 SWIG_as_voidptr(downstream_port
), SWIGTYPE_p_bt_port_input
, 0);
298 if (!py_downstream_port_ptr
) {
299 BT_LOGF_STR("Failed to create downstream port SWIG pointer object.");
300 status
= __BT_FUNC_STATUS_MEMORY_ERROR
;
304 py_res
= PyObject_CallFunction(py_callable
, "(OiOOiO)",
305 py_upstream_component_ptr
, upstream_component_class_type
,
306 py_upstream_port_ptr
,
307 py_downstream_component_ptr
, downstream_component_class_type
,
308 py_downstream_port_ptr
);
310 loge_exception_append_cause(
311 "Graph's port connected listener (Python)",
312 BT_LOG_OUTPUT_LEVEL
);
314 status
= __BT_FUNC_STATUS_ERROR
;
318 BT_ASSERT(py_res
== Py_None
);
319 status
= __BT_FUNC_STATUS_OK
;
322 Py_XDECREF(py_upstream_component_ptr
);
323 Py_XDECREF(py_upstream_port_ptr
);
324 Py_XDECREF(py_downstream_component_ptr
);
325 Py_XDECREF(py_downstream_port_ptr
);
331 bt_graph_listener_func_status
source_filter_component_ports_connected_listener(
332 const bt_component_source
*source_component
,
333 const bt_component_filter
*filter_component
,
334 const bt_port_output
*upstream_port
,
335 const bt_port_input
*downstream_port
, void *py_callable
)
337 return ports_connected_listener(
338 source_component
, SWIGTYPE_p_bt_component_source
, BT_COMPONENT_CLASS_TYPE_SOURCE
,
340 filter_component
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
346 bt_graph_listener_func_status
source_sink_component_ports_connected_listener(
347 const bt_component_source
*source_component
,
348 const bt_component_sink
*sink_component
,
349 const bt_port_output
*upstream_port
,
350 const bt_port_input
*downstream_port
, void *py_callable
)
352 return ports_connected_listener(
353 source_component
, SWIGTYPE_p_bt_component_source
, BT_COMPONENT_CLASS_TYPE_SOURCE
,
355 sink_component
, SWIGTYPE_p_bt_component_sink
, BT_COMPONENT_CLASS_TYPE_SINK
,
361 bt_graph_listener_func_status
filter_filter_component_ports_connected_listener(
362 const bt_component_filter
*filter_component_left
,
363 const bt_component_filter
*filter_component_right
,
364 const bt_port_output
*upstream_port
,
365 const bt_port_input
*downstream_port
, void *py_callable
)
367 return ports_connected_listener(
368 filter_component_left
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
370 filter_component_right
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
376 bt_graph_listener_func_status
filter_sink_component_ports_connected_listener(
377 const bt_component_filter
*filter_component
,
378 const bt_component_sink
*sink_component
,
379 const bt_port_output
*upstream_port
,
380 const bt_port_input
*downstream_port
, void *py_callable
)
382 return ports_connected_listener(
383 filter_component
, SWIGTYPE_p_bt_component_filter
, BT_COMPONENT_CLASS_TYPE_FILTER
,
385 sink_component
, SWIGTYPE_p_bt_component_sink
, BT_COMPONENT_CLASS_TYPE_SINK
,
391 PyObject
*bt_bt2_graph_add_ports_connected_listener(struct bt_graph
*graph
,
392 PyObject
*py_callable
)
394 PyObject
*py_listener_ids
= NULL
;
395 PyObject
*py_listener_id
= NULL
;
396 bt_listener_id listener_id
;
397 bt_graph_add_listener_status status
;
398 const char * const module_name
=
399 "graph_add_ports_connected_listener() (Python)";
402 BT_ASSERT(py_callable
);
404 /* Behind the scene, we will be registering 4 different listeners and
405 * return all of their ids. */
406 py_listener_ids
= PyTuple_New(4);
407 if (!py_listener_ids
) {
408 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
409 "Failed to allocate one PyTuple.");
413 /* source -> filter connection */
414 status
= bt_graph_add_source_filter_component_ports_connected_listener(
415 graph
, source_filter_component_ports_connected_listener
,
416 graph_listener_removed
, py_callable
, &listener_id
);
417 if (status
!= __BT_FUNC_STATUS_OK
) {
419 * bt_graph_add_source_filter_component_ports_connected_listener
420 * has already logged/appended an error cause.
425 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
426 if (!py_listener_id
) {
427 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
428 "Failed to allocate one PyLong.");
432 PyTuple_SET_ITEM(py_listener_ids
, 0, py_listener_id
);
433 py_listener_id
= NULL
;
435 /* source -> sink connection */
436 status
= bt_graph_add_source_sink_component_ports_connected_listener(
437 graph
, source_sink_component_ports_connected_listener
,
438 graph_listener_removed
, py_callable
, &listener_id
);
439 if (status
!= __BT_FUNC_STATUS_OK
) {
441 * bt_graph_add_source_sink_component_ports_connected_listener
442 * has already logged/appended an error cause.
447 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
448 if (!py_listener_id
) {
449 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
450 "Failed to allocate one PyLong.");
454 PyTuple_SET_ITEM(py_listener_ids
, 1, py_listener_id
);
455 py_listener_id
= NULL
;
457 /* filter -> filter connection */
458 status
= bt_graph_add_filter_filter_component_ports_connected_listener(
459 graph
, filter_filter_component_ports_connected_listener
,
460 graph_listener_removed
, py_callable
, &listener_id
);
461 if (status
!= __BT_FUNC_STATUS_OK
) {
463 * bt_graph_add_filter_filter_component_ports_connected_listener
464 * has already logged/appended an error cause.
469 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
470 if (!py_listener_id
) {
471 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
472 "Failed to allocate one PyLong.");
476 PyTuple_SET_ITEM(py_listener_ids
, 2, py_listener_id
);
477 py_listener_id
= NULL
;
479 /* filter -> sink connection */
480 status
= bt_graph_add_filter_sink_component_ports_connected_listener(
481 graph
, filter_sink_component_ports_connected_listener
,
482 graph_listener_removed
, py_callable
, &listener_id
);
483 if (status
!= __BT_FUNC_STATUS_OK
) {
485 * bt_graph_add_filter_sink_component_ports_connected_listener
486 * has already logged/appended an error cause.
491 py_listener_id
= PyLong_FromUnsignedLongLong(listener_id
);
492 if (!py_listener_id
) {
493 BT_CURRENT_THREAD_ERROR_APPEND_CAUSE_FROM_UNKNOWN(module_name
,
494 "Failed to allocate one PyLong.");
498 PyTuple_SET_ITEM(py_listener_ids
, 3, py_listener_id
);
499 py_listener_id
= NULL
;
501 Py_INCREF(py_callable
);
502 Py_INCREF(py_callable
);
503 Py_INCREF(py_callable
);
504 Py_INCREF(py_callable
);
509 Py_XDECREF(py_listener_ids
);
510 py_listener_ids
= Py_None
;
511 Py_INCREF(py_listener_ids
);
515 Py_XDECREF(py_listener_id
);
516 return py_listener_ids
;
520 bt_graph_add_component_status
521 bt_bt2_graph_add_source_component(
523 const bt_component_class_source
*component_class
,
524 const char *name
, const bt_value
*params
,
525 PyObject
*obj
, bt_logging_level log_level
,
526 const bt_component_source
**component
)
528 return bt_graph_add_source_component_with_initialize_method_data(graph
,
529 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
530 log_level
, component
);
534 bt_graph_add_component_status
535 bt_bt2_graph_add_filter_component(
537 const bt_component_class_filter
*component_class
,
538 const char *name
, const bt_value
*params
,
539 PyObject
*obj
, bt_logging_level log_level
,
540 const bt_component_filter
**component
)
542 return bt_graph_add_filter_component_with_initialize_method_data(graph
,
543 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
544 log_level
, component
);
548 bt_graph_add_component_status
549 bt_bt2_graph_add_sink_component(
551 const bt_component_class_sink
*component_class
,
552 const char *name
, const bt_value
*params
,
553 PyObject
*obj
, bt_logging_level log_level
,
554 const bt_component_sink
**component
)
556 return bt_graph_add_sink_component_with_initialize_method_data(graph
,
557 component_class
, name
, params
, obj
== Py_None
? NULL
: obj
,
558 log_level
, component
);