44941e19d732898028a673c20c61dbce18f59a0e
[babeltrace.git] / src / bindings / python / bt2 / bt2 / native_bt_graph.i.h
1 /*
2 * The MIT License (MIT)
3 *
4 * Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
5 *
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:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
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
22 * THE SOFTWARE.
23 */
24
25 static
26 void graph_listener_removed(void *py_callable)
27 {
28 BT_ASSERT(py_callable);
29 Py_DECREF(py_callable);
30 }
31
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,
36 const void *port,
37 swig_type_info *port_swig_type,
38 bt_port_type port_type,
39 void *py_callable)
40 {
41 PyObject *py_component_ptr = NULL;
42 PyObject *py_port_ptr = NULL;
43 PyObject *py_res = NULL;
44 bt_graph_listener_func_status status;
45
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;
50 goto end;
51 }
52
53 py_port_ptr = SWIG_NewPointerObj(SWIG_as_voidptr(port), port_swig_type, 0);
54 if (!py_port_ptr) {
55 BT_LOGF_STR("Failed to create port SWIG pointer object.");
56 status = __BT_FUNC_STATUS_MEMORY_ERROR;
57 goto end;
58 }
59
60 py_res = PyObject_CallFunction(py_callable, "(OiOi)",
61 py_component_ptr, component_class_type, py_port_ptr, port_type);
62 if (!py_res) {
63 loge_exception_append_cause(
64 "Graph's port added listener (Python)",
65 BT_LOG_OUTPUT_LEVEL);
66 PyErr_Clear();
67 status = __BT_FUNC_STATUS_ERROR;
68 goto end;
69 }
70
71 BT_ASSERT(py_res == Py_None);
72 status = __BT_FUNC_STATUS_OK;
73
74 end:
75 Py_XDECREF(py_res);
76 Py_XDECREF(py_port_ptr);
77 Py_XDECREF(py_component_ptr);
78 return status;
79 }
80
81 static
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)
85 {
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);
89 }
90
91 static
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)
95 {
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);
99 }
100
101 static
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)
105 {
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);
109 }
110
111 static
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)
115 {
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);
119 }
120
121 static
122 PyObject *bt_bt2_graph_add_port_added_listener(struct bt_graph *graph,
123 PyObject *py_callable)
124 {
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)";
131
132 BT_ASSERT(graph);
133 BT_ASSERT(py_callable);
134
135 /*
136 * Behind the scene, we will be registering 4 different listeners and
137 * return all of their ids.
138 */
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.");
143 goto error;
144 }
145
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) {
151 /*
152 * bt_graph_add_source_component_output_port_added_listener has
153 * already logged/appended an error cause.
154 */
155 goto error;
156 }
157
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.");
162 goto error;
163 }
164
165 PyTuple_SET_ITEM(py_listener_ids, 0, py_listener_id);
166 py_listener_id = NULL;
167
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) {
173 /*
174 * bt_graph_add_filter_component_input_port_added_listener has
175 * already logged/appended an error cause.
176 */
177 goto error;
178 }
179
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.");
184 goto error;
185 }
186
187 PyTuple_SET_ITEM(py_listener_ids, 1, py_listener_id);
188 py_listener_id = NULL;
189
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) {
195 /*
196 * bt_graph_add_filter_component_output_port_added_listener has
197 * already logged/appended an error cause.
198 */
199 goto error;
200 }
201
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.");
206 goto error;
207 }
208
209 PyTuple_SET_ITEM(py_listener_ids, 2, py_listener_id);
210 py_listener_id = NULL;
211
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) {
217 /*
218 * bt_graph_add_sink_component_input_port_added_listener has
219 * already logged/appended an error cause.
220 */
221 goto error;
222 }
223
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.");
228 goto error;
229 }
230
231
232 PyTuple_SET_ITEM(py_listener_ids, 3, py_listener_id);
233 py_listener_id = NULL;
234
235 Py_INCREF(py_callable);
236 Py_INCREF(py_callable);
237 Py_INCREF(py_callable);
238 Py_INCREF(py_callable);
239
240 goto end;
241
242 error:
243 Py_XDECREF(py_listener_ids);
244 py_listener_ids = Py_None;
245 Py_INCREF(py_listener_ids);
246
247 end:
248
249 Py_XDECREF(py_listener_id);
250 return py_listener_ids;
251 }
252
253 static
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,
263 void *py_callable)
264 {
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;
271
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;
277 goto end;
278 }
279
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;
285 goto end;
286 }
287
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;
293 goto end;
294 }
295
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;
301 goto end;
302 }
303
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);
309 if (!py_res) {
310 loge_exception_append_cause(
311 "Graph's port connected listener (Python)",
312 BT_LOG_OUTPUT_LEVEL);
313 PyErr_Clear();
314 status = __BT_FUNC_STATUS_ERROR;
315 goto end;
316 }
317
318 BT_ASSERT(py_res == Py_None);
319 status = __BT_FUNC_STATUS_OK;
320
321 end:
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);
326 Py_XDECREF(py_res);
327 return status;
328 }
329
330 static
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)
336 {
337 return ports_connected_listener(
338 source_component, SWIGTYPE_p_bt_component_source, BT_COMPONENT_CLASS_TYPE_SOURCE,
339 upstream_port,
340 filter_component, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
341 downstream_port,
342 py_callable);
343 }
344
345 static
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)
351 {
352 return ports_connected_listener(
353 source_component, SWIGTYPE_p_bt_component_source, BT_COMPONENT_CLASS_TYPE_SOURCE,
354 upstream_port,
355 sink_component, SWIGTYPE_p_bt_component_sink, BT_COMPONENT_CLASS_TYPE_SINK,
356 downstream_port,
357 py_callable);
358 }
359
360 static
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)
366 {
367 return ports_connected_listener(
368 filter_component_left, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
369 upstream_port,
370 filter_component_right, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
371 downstream_port,
372 py_callable);
373 }
374
375 static
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)
381 {
382 return ports_connected_listener(
383 filter_component, SWIGTYPE_p_bt_component_filter, BT_COMPONENT_CLASS_TYPE_FILTER,
384 upstream_port,
385 sink_component, SWIGTYPE_p_bt_component_sink, BT_COMPONENT_CLASS_TYPE_SINK,
386 downstream_port,
387 py_callable);
388 }
389
390 static
391 PyObject *bt_bt2_graph_add_ports_connected_listener(struct bt_graph *graph,
392 PyObject *py_callable)
393 {
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)";
400
401 BT_ASSERT(graph);
402 BT_ASSERT(py_callable);
403
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.");
410 goto error;
411 }
412
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) {
418 /*
419 * bt_graph_add_source_filter_component_ports_connected_listener
420 * has already logged/appended an error cause.
421 */
422 goto error;
423 }
424
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.");
429 goto error;
430 }
431
432 PyTuple_SET_ITEM(py_listener_ids, 0, py_listener_id);
433 py_listener_id = NULL;
434
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) {
440 /*
441 * bt_graph_add_source_sink_component_ports_connected_listener
442 * has already logged/appended an error cause.
443 */
444 goto error;
445 }
446
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.");
451 goto error;
452 }
453
454 PyTuple_SET_ITEM(py_listener_ids, 1, py_listener_id);
455 py_listener_id = NULL;
456
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) {
462 /*
463 * bt_graph_add_filter_filter_component_ports_connected_listener
464 * has already logged/appended an error cause.
465 */
466 goto error;
467 }
468
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.");
473 goto error;
474 }
475
476 PyTuple_SET_ITEM(py_listener_ids, 2, py_listener_id);
477 py_listener_id = NULL;
478
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) {
484 /*
485 * bt_graph_add_filter_sink_component_ports_connected_listener
486 * has already logged/appended an error cause.
487 */
488 goto error;
489 }
490
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.");
495 goto error;
496 }
497
498 PyTuple_SET_ITEM(py_listener_ids, 3, py_listener_id);
499 py_listener_id = NULL;
500
501 Py_INCREF(py_callable);
502 Py_INCREF(py_callable);
503 Py_INCREF(py_callable);
504 Py_INCREF(py_callable);
505
506 goto end;
507
508 error:
509 Py_XDECREF(py_listener_ids);
510 py_listener_ids = Py_None;
511 Py_INCREF(py_listener_ids);
512
513 end:
514
515 Py_XDECREF(py_listener_id);
516 return py_listener_ids;
517 }
518
519 static
520 bt_graph_add_component_status
521 bt_bt2_graph_add_source_component(
522 bt_graph *graph,
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)
527 {
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);
531 }
532
533 static
534 bt_graph_add_component_status
535 bt_bt2_graph_add_filter_component(
536 bt_graph *graph,
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)
541 {
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);
545 }
546
547 static
548 bt_graph_add_component_status
549 bt_bt2_graph_add_sink_component(
550 bt_graph *graph,
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)
555 {
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);
559 }
This page took 0.039027 seconds and 3 git commands to generate.