Fix: add missing void param to bt_clock_class_priority_map_create
[babeltrace.git] / bindings / python / bt2 / component.py
CommitLineData
81447b5b
PP
1# The MIT License (MIT)
2#
3# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in
13# all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21# THE SOFTWARE.
22
23from bt2 import native_bt, object, utils
24import bt2.notification_iterator
25import collections.abc
911dec08 26import bt2.values
811644b8
PP
27import traceback
28import bt2.port
40910fbb 29import sys
81447b5b 30import bt2
811644b8
PP
31import os
32
33
34_env_var = os.environ.get('BABELTRACE_PYTHON_BT2_NO_TRACEBACK')
35_NO_PRINT_TRACEBACK = _env_var == '1'
81447b5b
PP
36
37
38# This class wraps a component class pointer. This component class could
39# have been created by Python code, but since we only have the pointer,
40# we can only wrap it in a generic way and lose the original Python
41# class.
42class _GenericComponentClass(object._Object):
43 @property
44 def name(self):
811644b8
PP
45 name = native_bt.component_class_get_name(self._ptr)
46 assert(name is not None)
47 return name
81447b5b
PP
48
49 @property
50 def description(self):
51 return native_bt.component_class_get_description(self._ptr)
52
40910fbb
PP
53 @property
54 def help(self):
55 return native_bt.component_class_get_help(self._ptr)
56
a67681c1
PP
57 def query(self, obj, params=None):
58 return _query(self._ptr, obj, params)
911dec08 59
811644b8
PP
60 def __eq__(self, other):
61 if not isinstance(other, _GenericComponentClass):
62 try:
63 if not issubclass(other, _UserComponent):
64 return False
65 except TypeError:
66 return False
81447b5b 67
811644b8 68 return self.addr == other.addr
81447b5b
PP
69
70
71class _GenericSourceComponentClass(_GenericComponentClass):
72 pass
73
74
75class _GenericFilterComponentClass(_GenericComponentClass):
76 pass
77
78
79class _GenericSinkComponentClass(_GenericComponentClass):
80 pass
81
82
811644b8
PP
83def _handle_component_status(status, gen_error_msg):
84 if status == native_bt.COMPONENT_STATUS_END:
85 raise bt2.Stop
86 elif status == native_bt.COMPONENT_STATUS_AGAIN:
87 raise bt2.TryAgain
88 elif status == native_bt.COMPONENT_STATUS_UNSUPPORTED:
89 raise bt2.UnsupportedFeature
90 elif status == native_bt.COMPONENT_STATUS_REFUSE_PORT_CONNECTION:
91 raise bt2.PortConnectionRefused
92 elif status == native_bt.COMPONENT_STATUS_GRAPH_IS_CANCELED:
93 raise bt2.GraphCanceled
94 elif status < 0:
95 raise bt2.Error(gen_error_msg)
96
97
98class _PortIterator(collections.abc.Iterator):
99 def __init__(self, comp_ports):
100 self._comp_ports = comp_ports
101 self._at = 0
102
103 def __next__(self):
104 if self._at == len(self._comp_ports):
105 raise StopIteration
106
107 comp_ports = self._comp_ports
108 comp_ptr = comp_ports._component._ptr
109 port_ptr = comp_ports._get_port_at_index_fn(comp_ptr, self._at)
110 assert(port_ptr)
111
112 if comp_ports._is_private:
113 port_pub_ptr = native_bt.port_from_private_port(port_ptr)
114 name = native_bt.port_get_name(port_pub_ptr)
115 native_bt.put(port_pub_ptr)
116 else:
117 name = native_bt.port_get_name(port_ptr)
118
119 assert(name is not None)
120 native_bt.put(port_ptr)
121 self._at += 1
122 return name
123
124
125class _ComponentPorts(collections.abc.Mapping):
126 def __init__(self, is_private, component,
127 get_port_by_name_fn, get_port_at_index_fn,
128 get_port_count_fn):
129 self._is_private = is_private
130 self._component = component
131 self._get_port_by_name_fn = get_port_by_name_fn
132 self._get_port_at_index_fn = get_port_at_index_fn
133 self._get_port_count_fn = get_port_count_fn
134
135 def __getitem__(self, key):
136 utils._check_str(key)
137 port_ptr = self._get_port_by_name_fn(self._component._ptr, key)
138
139 if port_ptr is None:
140 raise KeyError(key)
141
142 if self._is_private:
143 return bt2.port._create_private_from_ptr(port_ptr)
144 else:
145 return bt2.port._create_from_ptr(port_ptr)
146
147 def __len__(self):
148 if self._is_private:
149 pub_ptr = native_bt.component_from_private_component(self._component._ptr)
150 count = self._get_port_count_fn(pub_ptr)
151 native_bt.put(pub_ptr)
152 else:
153 count = self._get_port_count_fn(self._component._ptr)
154
155 assert(count >= 0)
156 return count
157
158 def __iter__(self):
159 return _PortIterator(self)
160
161
81447b5b
PP
162# This class holds the methods which are common to both generic
163# component objects and Python user component objects. They use the
164# internal native _ptr, however it was set, to call native API
165# functions.
811644b8 166class _Component:
81447b5b
PP
167 @property
168 def name(self):
811644b8
PP
169 name = native_bt.component_get_name(self._ptr)
170 assert(name is not None)
171 return name
172
173 @property
174 def graph(self):
175 ptr = native_bt.component_get_graph(self._ptr)
176 assert(ptr)
177 return bt2.Graph._create_from_ptr(ptr)
81447b5b
PP
178
179 @property
180 def component_class(self):
181 cc_ptr = native_bt.component_get_class(self._ptr)
811644b8 182 assert(cc_ptr)
81447b5b
PP
183 return _create_generic_component_class_from_ptr(cc_ptr)
184
811644b8
PP
185 def __eq__(self, other):
186 if not hasattr(other, 'addr'):
187 return False
81447b5b 188
811644b8 189 return self.addr == other.addr
81447b5b 190
81447b5b 191
811644b8
PP
192class _SourceComponent(_Component):
193 pass
81447b5b 194
81447b5b 195
811644b8
PP
196class _FilterComponent(_Component):
197 pass
81447b5b 198
81447b5b 199
811644b8
PP
200class _SinkComponent(_Component):
201 pass
81447b5b
PP
202
203
204# This is analogous to _GenericSourceComponentClass, but for source
205# component objects.
811644b8
PP
206class _GenericSourceComponent(object._Object, _SourceComponent):
207 @property
208 def output_ports(self):
209 return _ComponentPorts(False, self,
210 native_bt.component_source_get_output_port_by_name,
211 native_bt.component_source_get_output_port_by_index,
212 native_bt.component_source_get_output_port_count)
81447b5b
PP
213
214
215# This is analogous to _GenericFilterComponentClass, but for filter
216# component objects.
811644b8
PP
217class _GenericFilterComponent(object._Object, _FilterComponent):
218 @property
219 def output_ports(self):
220 return _ComponentPorts(False, self,
221 native_bt.component_filter_get_output_port_by_name,
222 native_bt.component_filter_get_output_port_by_index,
223 native_bt.component_filter_get_output_port_count)
224
225 @property
226 def input_ports(self):
227 return _ComponentPorts(False, self,
228 native_bt.component_filter_get_input_port_by_name,
229 native_bt.component_filter_get_input_port_by_index,
230 native_bt.component_filter_get_input_port_count)
81447b5b
PP
231
232
233# This is analogous to _GenericSinkComponentClass, but for sink
234# component objects.
811644b8
PP
235class _GenericSinkComponent(object._Object, _SinkComponent):
236 @property
237 def input_ports(self):
238 return _ComponentPorts(False, self,
239 native_bt.component_sink_get_input_port_by_name,
240 native_bt.component_sink_get_input_port_by_index,
241 native_bt.component_sink_get_input_port_count)
81447b5b
PP
242
243
811644b8 244_COMP_CLS_TYPE_TO_GENERIC_COMP_PYCLS = {
81447b5b
PP
245 native_bt.COMPONENT_CLASS_TYPE_SOURCE: _GenericSourceComponent,
246 native_bt.COMPONENT_CLASS_TYPE_FILTER: _GenericFilterComponent,
247 native_bt.COMPONENT_CLASS_TYPE_SINK: _GenericSinkComponent,
248}
249
250
811644b8 251_COMP_CLS_TYPE_TO_GENERIC_COMP_CLS_PYCLS = {
81447b5b
PP
252 native_bt.COMPONENT_CLASS_TYPE_SOURCE: _GenericSourceComponentClass,
253 native_bt.COMPONENT_CLASS_TYPE_FILTER: _GenericFilterComponentClass,
254 native_bt.COMPONENT_CLASS_TYPE_SINK: _GenericSinkComponentClass,
255}
256
257
258def _create_generic_component_from_ptr(ptr):
259 comp_cls_type = native_bt.component_get_class_type(ptr)
811644b8 260 return _COMP_CLS_TYPE_TO_GENERIC_COMP_PYCLS[comp_cls_type]._create_from_ptr(ptr)
81447b5b
PP
261
262
263def _create_generic_component_class_from_ptr(ptr):
264 comp_cls_type = native_bt.component_class_get_type(ptr)
811644b8 265 return _COMP_CLS_TYPE_TO_GENERIC_COMP_CLS_PYCLS[comp_cls_type]._create_from_ptr(ptr)
81447b5b
PP
266
267
40910fbb
PP
268def _trim_docstring(docstring):
269 lines = docstring.expandtabs().splitlines()
270 indent = sys.maxsize
271
272 for line in lines[1:]:
273 stripped = line.lstrip()
274
275 if stripped:
276 indent = min(indent, len(line) - len(stripped))
277
278 trimmed = [lines[0].strip()]
279
280 if indent < sys.maxsize:
281 for line in lines[1:]:
282 trimmed.append(line[indent:].rstrip())
283
284 while trimmed and not trimmed[-1]:
285 trimmed.pop()
286
287 while trimmed and not trimmed[0]:
288 trimmed.pop(0)
289
290 return '\n'.join(trimmed)
291
292
a67681c1
PP
293def _query(comp_cls_ptr, obj, params):
294 utils._check_str(obj)
911dec08
PP
295
296 if params is None:
297 params_ptr = native_bt.value_null
298 else:
299 params = bt2.create_value(params)
300 params_ptr = params._ptr
301
a67681c1 302 results_ptr = native_bt.component_class_query(comp_cls_ptr, obj,
811644b8 303 params_ptr)
911dec08
PP
304
305 if results_ptr is None:
a67681c1 306 raise bt2.Error('cannot query info with object "{}"'.format(obj))
911dec08 307
911dec08
PP
308 return bt2.values._create_from_ptr(results_ptr)
309
310
81447b5b
PP
311# Metaclass for component classes defined by Python code.
312#
313# The Python user can create a standard Python class which inherits one
811644b8
PP
314# of the three base classes (_UserSourceComponent, _UserFilterComponent,
315# or _UserSinkComponent). Those base classes set this class
81447b5b
PP
316# (_UserComponentType) as their metaclass.
317#
318# Once the body of a user-defined component class is executed, this
319# metaclass is used to create and initialize the class. The metaclass
320# creates a native BT component class of the corresponding type and
321# associates it with this user-defined class. The metaclass also defines
322# class methods like the `name` and `description` properties to match
323# the _GenericComponentClass interface.
324#
325# The component class name which is used is either:
326#
327# * The `name` parameter of the class:
328#
329# class MySink(bt2.SinkComponent, name='my-custom-sink'):
330# ...
331#
332# * If the `name` class parameter is not used: the name of the class
333# itself (`MySink` in the example above).
334#
335# The component class description which is used is the user-defined
336# class's docstring:
337#
338# class MySink(bt2.SinkComponent):
339# 'Description goes here'
340# ...
341#
342# A user-defined Python component class can have an __init__() method
343# which must at least accept the `params` and `name` arguments:
344#
345# def __init__(self, params, name, something_else):
346# ...
347#
811644b8 348# The user-defined component class can also have a _finalize() method
81447b5b 349# (do NOT use __del__()) to be notified when the component object is
811644b8 350# finalized.
81447b5b
PP
351#
352# User-defined source and filter component classes must use the
353# `notification_iterator_class` class parameter to specify the
354# notification iterator class to use for this component class:
355#
811644b8 356# class MyNotificationIterator(bt2._UserNotificationIterator):
81447b5b
PP
357# ...
358#
811644b8 359# class MySource(bt2._UserSourceComponent,
81447b5b
PP
360# notification_iterator_class=MyNotificationIterator):
361# ...
362#
363# This notification iterator class must inherit
811644b8 364# bt2._UserNotificationIterator, and it must define the _get() and
81447b5b
PP
365# _next() methods. The notification iterator class can also define an
366# __init__() method: this method has access to the original Python
367# component object which was used to create it as the `component`
811644b8
PP
368# property. The notification iterator class can also define a
369# _finalize() method (again, do NOT use __del__()): this is called when
370# the notification iterator is (really) destroyed.
81447b5b
PP
371#
372# When the user-defined class is destroyed, this metaclass's __del__()
373# method is called: the native BT component class pointer is put (not
374# needed anymore, at least not by any Python code since all references
375# are dropped for __del__() to be called).
376class _UserComponentType(type):
377 # __new__() is used to catch custom class parameters
378 def __new__(meta_cls, class_name, bases, attrs, **kwargs):
379 return super().__new__(meta_cls, class_name, bases, attrs)
380
381 def __init__(cls, class_name, bases, namespace, **kwargs):
382 super().__init__(class_name, bases, namespace)
383
384 # skip our own bases; they are never directly instantiated by the user
811644b8
PP
385 own_bases = (
386 '_UserComponent',
387 '_UserFilterSinkComponent',
388 '_UserSourceComponent',
389 '_UserFilterComponent',
390 '_UserSinkComponent',
391 )
392
393 if class_name in own_bases:
81447b5b
PP
394 return
395
396 comp_cls_name = kwargs.get('name', class_name)
811644b8 397 utils._check_str(comp_cls_name)
40910fbb
PP
398 comp_cls_descr = None
399 comp_cls_help = None
400
401 if hasattr(cls, '__doc__') and cls.__doc__ is not None:
811644b8 402 utils._check_str(cls.__doc__)
40910fbb
PP
403 docstring = _trim_docstring(cls.__doc__)
404 lines = docstring.splitlines()
405
406 if len(lines) >= 1:
407 comp_cls_descr = lines[0]
408
409 if len(lines) >= 3:
410 comp_cls_help = '\n'.join(lines[2:])
411
81447b5b
PP
412 iter_cls = kwargs.get('notification_iterator_class')
413
811644b8 414 if _UserSourceComponent in bases:
81447b5b 415 _UserComponentType._set_iterator_class(cls, iter_cls)
81447b5b
PP
416 cc_ptr = native_bt.py3_component_class_source_create(cls,
417 comp_cls_name,
418 comp_cls_descr,
811644b8
PP
419 comp_cls_help)
420 elif _UserFilterComponent in bases:
81447b5b 421 _UserComponentType._set_iterator_class(cls, iter_cls)
81447b5b
PP
422 cc_ptr = native_bt.py3_component_class_filter_create(cls,
423 comp_cls_name,
424 comp_cls_descr,
811644b8
PP
425 comp_cls_help)
426 elif _UserSinkComponent in bases:
81447b5b 427 if not hasattr(cls, '_consume'):
811644b8 428 raise bt2.IncompleteUserClass("cannot create component class '{}': missing a _consume() method".format(class_name))
81447b5b
PP
429
430 cc_ptr = native_bt.py3_component_class_sink_create(cls,
431 comp_cls_name,
40910fbb
PP
432 comp_cls_descr,
433 comp_cls_help)
81447b5b 434 else:
811644b8 435 raise bt2.IncompleteUserClass("cannot find a known component class base in the bases of '{}'".format(class_name))
81447b5b
PP
436
437 if cc_ptr is None:
438 raise bt2.CreationError("cannot create component class '{}'".format(class_name))
439
440 cls._cc_ptr = cc_ptr
441
811644b8
PP
442 def _init_from_native(cls, comp_ptr, params_ptr):
443 # create instance, not user-initialized yet
81447b5b
PP
444 self = cls.__new__(cls)
445
811644b8
PP
446 # pointer to native private component object (weak/borrowed)
447 self._ptr = comp_ptr
81447b5b 448
811644b8
PP
449 # call user's __init__() method
450 if params_ptr is not None:
451 native_bt.get(params_ptr)
452 params = bt2.values._create_from_ptr(params_ptr)
453 else:
454 params = None
81447b5b 455
811644b8 456 self.__init__(params)
81447b5b
PP
457 return self
458
811644b8
PP
459 def __call__(cls, *args, **kwargs):
460 raise bt2.Error('cannot directly instantiate a user component from a Python module')
81447b5b
PP
461
462 @staticmethod
463 def _set_iterator_class(cls, iter_cls):
464 if iter_cls is None:
811644b8 465 raise bt2.IncompleteUserClass("cannot create component class '{}': missing notification iterator class".format(cls.__name__))
81447b5b 466
811644b8
PP
467 if not issubclass(iter_cls, bt2.notification_iterator._UserNotificationIterator):
468 raise bt2.IncompleteUserClass("cannot create component class '{}': notification iterator class does not inherit bt2._UserNotificationIterator".format(cls.__name__))
81447b5b 469
811644b8
PP
470 if not hasattr(iter_cls, '__next__'):
471 raise bt2.IncompleteUserClass("cannot create component class '{}': notification iterator class is missing a __next__() method".format(cls.__name__))
81447b5b
PP
472
473 cls._iter_cls = iter_cls
474
475 @property
476 def name(cls):
477 return native_bt.component_class_get_name(cls._cc_ptr)
478
479 @property
480 def description(cls):
481 return native_bt.component_class_get_description(cls._cc_ptr)
482
40910fbb
PP
483 @property
484 def help(cls):
485 return native_bt.component_class_get_help(cls._cc_ptr)
486
81447b5b
PP
487 @property
488 def addr(cls):
489 return int(cls._cc_ptr)
490
811644b8
PP
491 def query(cls, obj, params=None):
492 return _query(cls._cc_ptr, obj, params)
911dec08 493
811644b8 494 def _query_from_native(cls, obj, params_ptr):
911dec08 495 # this can raise, in which case the native call to
a67681c1 496 # bt_component_class_query() returns NULL
811644b8
PP
497 if params_ptr is not None:
498 native_bt.get(params_ptr)
499 params = bt2.values._create_from_ptr(params_ptr)
500 else:
501 params = None
502
503 try:
504 results = cls._query(obj, params)
505 except:
506 if not _NO_PRINT_TRACEBACK:
507 traceback.print_exc()
508
509 return
510
511 if results is NotImplemented:
512 return results
513
514 try:
515 results = bt2.create_value(results)
516 except:
517 if not _NO_PRINT_TRACEBACK:
518 traceback.print_exc()
519
520 return
911dec08
PP
521
522 if results is None:
523 results_addr = int(native_bt.value_null)
524 else:
811644b8
PP
525 # return new reference
526 results._get()
911dec08 527 results_addr = int(results._ptr)
911dec08
PP
528
529 return results_addr
530
811644b8
PP
531 @classmethod
532 def _query(cls, obj, params):
911dec08 533 # BT catches this and returns NULL to the user
811644b8
PP
534 return NotImplemented
535
536 def __eq__(self, other):
537 if not hasattr(other, 'addr'):
538 return False
539
540 return self.addr == other.addr
911dec08 541
81447b5b
PP
542 def __del__(cls):
543 if hasattr(cls, '_cc_ptr'):
544 native_bt.put(cls._cc_ptr)
545
546
811644b8
PP
547class _UserComponent(metaclass=_UserComponentType):
548 @property
549 def name(self):
550 pub_ptr = native_bt.component_from_private_component(self._ptr)
551 name = native_bt.component_get_name(pub_ptr)
552 native_bt.put(pub_ptr)
553 assert(name is not None)
554 return name
81447b5b 555
811644b8
PP
556 @property
557 def graph(self):
558 pub_ptr = native_bt.component_from_private_component(self._ptr)
559 ptr = native_bt.component_get_graph(pub_ptr)
560 native_bt.put(pub_ptr)
561 assert(ptr)
562 return bt2.Graph._create_from_ptr(ptr)
81447b5b 563
811644b8
PP
564 @property
565 def component_class(self):
566 pub_ptr = native_bt.component_from_private_component(self._ptr)
567 cc_ptr = native_bt.component_get_class(pub_ptr)
568 native_bt.put(pub_ptr)
569 assert(cc_ptr)
570 return _create_generic_component_class_from_ptr(cc_ptr)
81447b5b 571
81447b5b
PP
572 @property
573 def addr(self):
574 return int(self._ptr)
575
811644b8 576 def __init__(self, params=None):
81447b5b
PP
577 pass
578
811644b8 579 def _finalize(self):
81447b5b
PP
580 pass
581
811644b8
PP
582 def _accept_port_connection(self, port, other_port):
583 return True
81447b5b 584
811644b8
PP
585 def _accept_port_connection_from_native(self, port_ptr, other_port_ptr):
586 native_bt.get(port_ptr)
587 native_bt.get(other_port_ptr)
588 port = bt2.port._create_private_from_ptr(port_ptr)
589 other_port = bt2.port._create_from_ptr(other_port_ptr)
590 res = self._accept_port_connection(port, other_port_ptr)
81447b5b 591
811644b8
PP
592 if type(res) is not bool:
593 raise TypeError("'{}' is not a 'bool' object")
81447b5b 594
811644b8 595 return res
81447b5b 596
811644b8
PP
597 def _port_connected(self, port, other_port):
598 pass
81447b5b 599
811644b8
PP
600 def _port_connected_from_native(self, port_ptr, other_port_ptr):
601 native_bt.get(port_ptr)
602 native_bt.get(other_port_ptr)
603 port = bt2.port._create_private_from_ptr(port_ptr)
604 other_port = bt2.port._create_from_ptr(other_port_ptr)
81447b5b 605
811644b8
PP
606 try:
607 self._port_connected(port, other_port_ptr)
608 except:
609 if not _NO_PRINT_TRACEBACK:
610 traceback.print_exc()
81447b5b 611
811644b8 612 def _port_disconnected(self, port):
81447b5b
PP
613 pass
614
811644b8
PP
615 def _port_disconnected_from_native(self, port_ptr):
616 native_bt.get(port_ptr)
617 port = bt2.port._create_private_from_ptr(port_ptr)
81447b5b 618
811644b8
PP
619 try:
620 self._port_disconnected(port)
621 except:
622 if not _NO_PRINT_TRACEBACK:
623 traceback.print_exc()
81447b5b 624
81447b5b 625
811644b8 626class _UserSourceComponent(_UserComponent, _SourceComponent):
81447b5b 627 @property
811644b8
PP
628 def _output_ports(self):
629 return _ComponentPorts(True, self,
630 native_bt.private_component_source_get_output_private_port_by_name,
631 native_bt.private_component_source_get_output_private_port_by_index,
632 native_bt.component_source_get_output_port_count)
633
634 def _add_output_port(self, name):
635 utils._check_str(name)
636 fn = native_bt.private_component_source_add_output_private_port
637 comp_status, priv_port_ptr = fn(self._ptr, name, None)
638 _handle_component_status(comp_status,
639 'cannot add output port to source component object')
640 assert(priv_port_ptr)
641 return bt2.port._create_private_from_ptr(priv_port_ptr)
642
643
644class _UserFilterComponent(_UserComponent, _FilterComponent):
645 @property
646 def _output_ports(self):
647 return _ComponentPorts(True, self,
648 native_bt.private_component_filter_get_output_private_port_by_name,
649 native_bt.private_component_filter_get_output_private_port_by_index,
650 native_bt.component_filter_get_output_port_count)
81447b5b 651
811644b8
PP
652 @property
653 def _input_ports(self):
654 return _ComponentPorts(True, self,
655 native_bt.private_component_filter_get_input_private_port_by_name,
656 native_bt.private_component_filter_get_input_private_port_by_index,
657 native_bt.component_filter_get_input_port_count)
658
659 def _add_output_port(self, name):
660 utils._check_str(name)
661 fn = native_bt.private_component_filter_add_output_private_port
662 comp_status, priv_port_ptr = fn(self._ptr, name, None)
663 _handle_component_status(comp_status,
664 'cannot add output port to filter component object')
665 assert(priv_port_ptr)
666 return bt2.port._create_private_from_ptr(priv_port_ptr)
667
668 def _add_input_port(self, name):
669 utils._check_str(name)
670 fn = native_bt.private_component_filter_add_input_private_port
671 comp_status, priv_port_ptr = fn(self._ptr, name, None)
672 _handle_component_status(comp_status,
673 'cannot add input port to filter component object')
674 assert(priv_port_ptr)
675 return bt2.port._create_private_from_ptr(priv_port_ptr)
676
677
678class _UserSinkComponent(_UserComponent, _SinkComponent):
679 @property
680 def _input_ports(self):
681 return _ComponentPorts(True, self,
682 native_bt.private_component_sink_get_input_private_port_by_name,
683 native_bt.private_component_sink_get_input_private_port_by_index,
684 native_bt.component_sink_get_input_port_count)
685
686 def _add_input_port(self, name):
687 utils._check_str(name)
688 fn = native_bt.private_component_sink_add_input_private_port
689 comp_status, priv_port_ptr = fn(self._ptr, name, None)
690 _handle_component_status(comp_status,
691 'cannot add input port to sink component object')
692 assert(priv_port_ptr)
693 return bt2.port._create_private_from_ptr(priv_port_ptr)
This page took 0.058167 seconds and 4 git commands to generate.