Commit | Line | Data |
---|---|---|
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 | ||
23 | from bt2 import native_bt, object, utils | |
24 | import bt2.notification_iterator | |
25 | import collections.abc | |
911dec08 | 26 | import bt2.values |
40910fbb | 27 | import sys |
81447b5b PP |
28 | import bt2 |
29 | ||
30 | ||
31 | # This class wraps a component class pointer. This component class could | |
32 | # have been created by Python code, but since we only have the pointer, | |
33 | # we can only wrap it in a generic way and lose the original Python | |
34 | # class. | |
35 | class _GenericComponentClass(object._Object): | |
36 | @property | |
37 | def name(self): | |
38 | return native_bt.component_class_get_name(self._ptr) | |
39 | ||
40 | @property | |
41 | def description(self): | |
42 | return native_bt.component_class_get_description(self._ptr) | |
43 | ||
40910fbb PP |
44 | @property |
45 | def help(self): | |
46 | return native_bt.component_class_get_help(self._ptr) | |
47 | ||
911dec08 PP |
48 | def query_info(self, action, params=None): |
49 | return _query_info(self._ptr, action, params) | |
50 | ||
81447b5b PP |
51 | def __call__(self, params=None, name=None): |
52 | params = bt2.create_value(params) | |
53 | comp_ptr = native_bt.component_create_with_init_method_data(self._ptr, | |
54 | name, | |
55 | params._ptr, | |
56 | None) | |
57 | ||
58 | if comp_ptr is None: | |
59 | raise bt2.CreationError('cannot create component object') | |
60 | ||
61 | return _create_generic_component_from_ptr(comp_ptr) | |
62 | ||
63 | ||
64 | class _GenericSourceComponentClass(_GenericComponentClass): | |
65 | pass | |
66 | ||
67 | ||
68 | class _GenericFilterComponentClass(_GenericComponentClass): | |
69 | pass | |
70 | ||
71 | ||
72 | class _GenericSinkComponentClass(_GenericComponentClass): | |
73 | pass | |
74 | ||
75 | ||
76 | # This class holds the methods which are common to both generic | |
77 | # component objects and Python user component objects. They use the | |
78 | # internal native _ptr, however it was set, to call native API | |
79 | # functions. | |
80 | class _CommonComponentMethods: | |
81 | @property | |
82 | def name(self): | |
83 | return native_bt.component_get_name(self._ptr) | |
84 | ||
85 | @property | |
86 | def component_class(self): | |
87 | cc_ptr = native_bt.component_get_class(self._ptr) | |
88 | utils._handle_ptr(cc_ptr, "cannot get component object's class object") | |
89 | return _create_generic_component_class_from_ptr(cc_ptr) | |
90 | ||
91 | def _handle_status(self, status, gen_error_msg): | |
92 | if status == native_bt.COMPONENT_STATUS_END: | |
93 | raise bt2.Stop | |
94 | elif status == native_bt.COMPONENT_STATUS_AGAIN: | |
95 | raise bt2.TryAgain | |
96 | elif status == native_bt.COMPONENT_STATUS_UNSUPPORTED: | |
97 | raise bt2.UnsupportedFeature | |
98 | elif status < 0: | |
99 | raise bt2.Error(gen_error_msg) | |
100 | ||
101 | ||
102 | class _CommonSourceComponentMethods(_CommonComponentMethods): | |
103 | def create_notification_iterator(self): | |
104 | iter_ptr = native_bt.component_source_create_notification_iterator_with_init_method_data(self._ptr, None) | |
105 | ||
106 | if iter_ptr is None: | |
107 | raise bt2.CreationError('cannot create notification iterator object') | |
108 | ||
109 | return bt2.notification_iterator._GenericNotificationIterator._create_from_ptr(iter_ptr) | |
110 | ||
111 | ||
112 | class _CommonFilterComponentMethods(_CommonComponentMethods): | |
113 | def create_notification_iterator(self): | |
114 | iter_ptr = native_bt.component_filter_create_notification_iterator_with_init_method_data(self._ptr, None) | |
115 | ||
116 | if iter_ptr is None: | |
117 | raise bt2.CreationError('cannot create notification iterator object') | |
118 | ||
119 | return bt2.notification_iterator._GenericNotificationIterator._create_from_ptr(iter_ptr) | |
120 | ||
121 | def add_notification_iterator(self, notif_iter): | |
122 | utils._check_type(notif_iter, bt2.notification_iterator._GenericNotificationIteratorMethods) | |
123 | status = native_bt.component_filter_add_iterator(self._ptr, notif_iter._ptr) | |
124 | self._handle_status(status, 'unexpected error: cannot add notification iterator to filter component object') | |
125 | ||
126 | ||
127 | class _CommonSinkComponentMethods(_CommonComponentMethods): | |
128 | def add_notification_iterator(self, notif_iter): | |
129 | utils._check_type(notif_iter, bt2.notification_iterator._GenericNotificationIteratorMethods) | |
130 | status = native_bt.component_sink_add_iterator(self._ptr, notif_iter._ptr) | |
131 | self._handle_status(status, 'unexpected error: cannot add notification iterator to sink component object') | |
132 | ||
133 | def consume(self): | |
134 | status = native_bt.component_sink_consume(self._ptr) | |
135 | self._handle_status(status, 'unexpected error: cannot consume sink component object') | |
136 | ||
137 | ||
138 | # This is analogous to _GenericSourceComponentClass, but for source | |
139 | # component objects. | |
140 | class _GenericSourceComponent(object._Object, _CommonSourceComponentMethods): | |
141 | pass | |
142 | ||
143 | ||
144 | # This is analogous to _GenericFilterComponentClass, but for filter | |
145 | # component objects. | |
146 | class _GenericFilterComponent(object._Object, _CommonFilterComponentMethods): | |
147 | pass | |
148 | ||
149 | ||
150 | # This is analogous to _GenericSinkComponentClass, but for sink | |
151 | # component objects. | |
152 | class _GenericSinkComponent(object._Object, _CommonSinkComponentMethods): | |
153 | pass | |
154 | ||
155 | ||
156 | _COMP_CLS_TYPE_TO_GENERIC_COMP_CLS = { | |
157 | native_bt.COMPONENT_CLASS_TYPE_SOURCE: _GenericSourceComponent, | |
158 | native_bt.COMPONENT_CLASS_TYPE_FILTER: _GenericFilterComponent, | |
159 | native_bt.COMPONENT_CLASS_TYPE_SINK: _GenericSinkComponent, | |
160 | } | |
161 | ||
162 | ||
163 | _COMP_CLS_TYPE_TO_GENERIC_COMP_CLS_CLS = { | |
164 | native_bt.COMPONENT_CLASS_TYPE_SOURCE: _GenericSourceComponentClass, | |
165 | native_bt.COMPONENT_CLASS_TYPE_FILTER: _GenericFilterComponentClass, | |
166 | native_bt.COMPONENT_CLASS_TYPE_SINK: _GenericSinkComponentClass, | |
167 | } | |
168 | ||
169 | ||
170 | def _create_generic_component_from_ptr(ptr): | |
171 | comp_cls_type = native_bt.component_get_class_type(ptr) | |
172 | return _COMP_CLS_TYPE_TO_GENERIC_COMP_CLS[comp_cls_type]._create_from_ptr(ptr) | |
173 | ||
174 | ||
175 | def _create_generic_component_class_from_ptr(ptr): | |
176 | comp_cls_type = native_bt.component_class_get_type(ptr) | |
177 | return _COMP_CLS_TYPE_TO_GENERIC_COMP_CLS_CLS[comp_cls_type]._create_from_ptr(ptr) | |
178 | ||
179 | ||
40910fbb PP |
180 | def _trim_docstring(docstring): |
181 | lines = docstring.expandtabs().splitlines() | |
182 | indent = sys.maxsize | |
183 | ||
184 | for line in lines[1:]: | |
185 | stripped = line.lstrip() | |
186 | ||
187 | if stripped: | |
188 | indent = min(indent, len(line) - len(stripped)) | |
189 | ||
190 | trimmed = [lines[0].strip()] | |
191 | ||
192 | if indent < sys.maxsize: | |
193 | for line in lines[1:]: | |
194 | trimmed.append(line[indent:].rstrip()) | |
195 | ||
196 | while trimmed and not trimmed[-1]: | |
197 | trimmed.pop() | |
198 | ||
199 | while trimmed and not trimmed[0]: | |
200 | trimmed.pop(0) | |
201 | ||
202 | return '\n'.join(trimmed) | |
203 | ||
204 | ||
911dec08 PP |
205 | def _query_info(comp_cls_ptr, action, params): |
206 | utils._check_str(action) | |
207 | ||
208 | if params is None: | |
209 | params_ptr = native_bt.value_null | |
210 | else: | |
211 | params = bt2.create_value(params) | |
212 | params_ptr = params._ptr | |
213 | ||
214 | results_ptr = native_bt.component_class_query_info(comp_cls_ptr, action, | |
215 | params_ptr) | |
216 | ||
217 | if results_ptr is None: | |
218 | raise bt2.Error('cannot query info with action "{}"'.format(action)) | |
219 | ||
220 | if results_ptr == native_bt.value_null: | |
221 | return | |
222 | ||
223 | return bt2.values._create_from_ptr(results_ptr) | |
224 | ||
225 | ||
81447b5b PP |
226 | # Metaclass for component classes defined by Python code. |
227 | # | |
228 | # The Python user can create a standard Python class which inherits one | |
229 | # of the three base classes (UserSourceComponent, UserFilterComponent, | |
230 | # or UserSinkComponent). Those base classes set this class | |
231 | # (_UserComponentType) as their metaclass. | |
232 | # | |
233 | # Once the body of a user-defined component class is executed, this | |
234 | # metaclass is used to create and initialize the class. The metaclass | |
235 | # creates a native BT component class of the corresponding type and | |
236 | # associates it with this user-defined class. The metaclass also defines | |
237 | # class methods like the `name` and `description` properties to match | |
238 | # the _GenericComponentClass interface. | |
239 | # | |
240 | # The component class name which is used is either: | |
241 | # | |
242 | # * The `name` parameter of the class: | |
243 | # | |
244 | # class MySink(bt2.SinkComponent, name='my-custom-sink'): | |
245 | # ... | |
246 | # | |
247 | # * If the `name` class parameter is not used: the name of the class | |
248 | # itself (`MySink` in the example above). | |
249 | # | |
250 | # The component class description which is used is the user-defined | |
251 | # class's docstring: | |
252 | # | |
253 | # class MySink(bt2.SinkComponent): | |
254 | # 'Description goes here' | |
255 | # ... | |
256 | # | |
257 | # A user-defined Python component class can have an __init__() method | |
258 | # which must at least accept the `params` and `name` arguments: | |
259 | # | |
260 | # def __init__(self, params, name, something_else): | |
261 | # ... | |
262 | # | |
263 | # The user-defined component class can also have a _destroy() method | |
264 | # (do NOT use __del__()) to be notified when the component object is | |
265 | # (really) destroyed. | |
266 | # | |
267 | # User-defined source and filter component classes must use the | |
268 | # `notification_iterator_class` class parameter to specify the | |
269 | # notification iterator class to use for this component class: | |
270 | # | |
271 | # class MyNotificationIterator(bt2.UserNotificationIterator): | |
272 | # ... | |
273 | # | |
274 | # class MySource(bt2.UserSourceComponent, | |
275 | # notification_iterator_class=MyNotificationIterator): | |
276 | # ... | |
277 | # | |
278 | # This notification iterator class must inherit | |
279 | # bt2.UserNotificationIterator, and it must define the _get() and | |
280 | # _next() methods. The notification iterator class can also define an | |
281 | # __init__() method: this method has access to the original Python | |
282 | # component object which was used to create it as the `component` | |
283 | # property. The notification iterator class can also define a _destroy() | |
284 | # method (again, do NOT use __del__()): this is called when the | |
285 | # notification iterator is (really) destroyed. | |
286 | # | |
287 | # When the user-defined class is destroyed, this metaclass's __del__() | |
288 | # method is called: the native BT component class pointer is put (not | |
289 | # needed anymore, at least not by any Python code since all references | |
290 | # are dropped for __del__() to be called). | |
291 | class _UserComponentType(type): | |
292 | # __new__() is used to catch custom class parameters | |
293 | def __new__(meta_cls, class_name, bases, attrs, **kwargs): | |
294 | return super().__new__(meta_cls, class_name, bases, attrs) | |
295 | ||
296 | def __init__(cls, class_name, bases, namespace, **kwargs): | |
297 | super().__init__(class_name, bases, namespace) | |
298 | ||
299 | # skip our own bases; they are never directly instantiated by the user | |
300 | if class_name in ('_UserComponent', 'UserSourceComponent', 'UserFilterComponent', 'UserSinkComponent'): | |
301 | return | |
302 | ||
303 | comp_cls_name = kwargs.get('name', class_name) | |
40910fbb PP |
304 | comp_cls_descr = None |
305 | comp_cls_help = None | |
306 | ||
307 | if hasattr(cls, '__doc__') and cls.__doc__ is not None: | |
308 | docstring = _trim_docstring(cls.__doc__) | |
309 | lines = docstring.splitlines() | |
310 | ||
311 | if len(lines) >= 1: | |
312 | comp_cls_descr = lines[0] | |
313 | ||
314 | if len(lines) >= 3: | |
315 | comp_cls_help = '\n'.join(lines[2:]) | |
316 | ||
81447b5b PP |
317 | iter_cls = kwargs.get('notification_iterator_class') |
318 | ||
319 | if UserSourceComponent in bases: | |
320 | _UserComponentType._set_iterator_class(cls, iter_cls) | |
321 | has_seek_time = _UserComponentType._has_seek_to_time_method(cls._iter_cls) | |
322 | cc_ptr = native_bt.py3_component_class_source_create(cls, | |
323 | comp_cls_name, | |
324 | comp_cls_descr, | |
40910fbb | 325 | comp_cls_help, |
81447b5b PP |
326 | has_seek_time) |
327 | elif UserFilterComponent in bases: | |
328 | _UserComponentType._set_iterator_class(cls, iter_cls) | |
329 | has_seek_time = _UserComponentType._has_seek_to_time_method(cls._iter_cls) | |
330 | cc_ptr = native_bt.py3_component_class_filter_create(cls, | |
331 | comp_cls_name, | |
332 | comp_cls_descr, | |
40910fbb | 333 | comp_cls_help, |
81447b5b PP |
334 | has_seek_time) |
335 | elif UserSinkComponent in bases: | |
336 | if not hasattr(cls, '_consume'): | |
337 | raise bt2.IncompleteUserClassError("cannot create component class '{}': missing a _consume() method".format(class_name)) | |
338 | ||
339 | cc_ptr = native_bt.py3_component_class_sink_create(cls, | |
340 | comp_cls_name, | |
40910fbb PP |
341 | comp_cls_descr, |
342 | comp_cls_help) | |
81447b5b PP |
343 | else: |
344 | raise bt2.IncompleteUserClassError("cannot find a known component class base in the bases of '{}'".format(class_name)) | |
345 | ||
346 | if cc_ptr is None: | |
347 | raise bt2.CreationError("cannot create component class '{}'".format(class_name)) | |
348 | ||
349 | cls._cc_ptr = cc_ptr | |
350 | ||
351 | def __call__(cls, *args, **kwargs): | |
352 | # create instance | |
353 | self = cls.__new__(cls) | |
354 | ||
355 | # assign native component pointer received from caller | |
356 | self._ptr = kwargs.get('__comp_ptr') | |
357 | name = kwargs.get('name') | |
358 | ||
359 | if self._ptr is None: | |
360 | # called from Python code | |
361 | self._belongs_to_native_component = False | |
362 | ||
363 | # py3_component_create() will call self.__init__() with the | |
364 | # desired arguments and keyword arguments. This is needed | |
365 | # because functions such as | |
366 | # bt_component_sink_set_minimum_input_count() can only be | |
367 | # called _during_ the bt_component_create() call (in | |
368 | # Python words: during self.__init__()). | |
369 | # | |
370 | # The arguments and keyword arguments to use for | |
371 | # self.__init__() are put in the object itself to find them | |
372 | # from the bt_component_create() function. | |
373 | self._init_args = args | |
374 | self._init_kwargs = kwargs | |
375 | native_bt.py3_component_create(cls._cc_ptr, self, name) | |
376 | ||
377 | # At this point, self._ptr should be set to non-None. If | |
378 | # it's not, an error occured during the | |
379 | # native_bt.py3_component_create() call. We consider this a | |
380 | # creation error. | |
381 | if self._ptr is None: | |
382 | raise bt2.CreationError("cannot create component object from component class '{}'".format(cls.__name__)) | |
383 | else: | |
384 | # Called from non-Python code (within | |
385 | # bt_component_create()): call __init__() here, after | |
386 | # removing the __comp_ptr keyword argument which is just for | |
387 | # this __call__() method. | |
388 | self._belongs_to_native_component = True | |
389 | del kwargs['__comp_ptr'] | |
390 | ||
391 | # inject `name` into the keyword arguments | |
392 | kwargs['name'] = self.name | |
393 | self.__init__(*args, **kwargs) | |
394 | ||
395 | return self | |
396 | ||
397 | @staticmethod | |
398 | def _has_seek_to_time_method(iter_cls): | |
399 | return hasattr(iter_cls, '_seek_to_time') | |
400 | ||
401 | @staticmethod | |
402 | def _set_iterator_class(cls, iter_cls): | |
403 | if iter_cls is None: | |
404 | raise bt2.IncompleteUserClassError("cannot create component class '{}': missing notification iterator class".format(cls.__name__)) | |
405 | ||
406 | if not issubclass(iter_cls, bt2.notification_iterator.UserNotificationIterator): | |
407 | raise bt2.IncompleteUserClassError("cannot create component class '{}': notification iterator class does not inherit bt2.UserNotificationIterator".format(cls.__name__)) | |
408 | ||
409 | if not hasattr(iter_cls, '_get'): | |
410 | raise bt2.IncompleteUserClassError("cannot create component class '{}': notification iterator class is missing a _get() method".format(cls.__name__)) | |
411 | ||
412 | if not hasattr(iter_cls, '_next'): | |
413 | raise bt2.IncompleteUserClassError("cannot create component class '{}': notification iterator class is missing a _next() method".format(cls.__name__)) | |
414 | ||
415 | cls._iter_cls = iter_cls | |
416 | ||
417 | @property | |
418 | def name(cls): | |
419 | return native_bt.component_class_get_name(cls._cc_ptr) | |
420 | ||
421 | @property | |
422 | def description(cls): | |
423 | return native_bt.component_class_get_description(cls._cc_ptr) | |
424 | ||
40910fbb PP |
425 | @property |
426 | def help(cls): | |
427 | return native_bt.component_class_get_help(cls._cc_ptr) | |
428 | ||
81447b5b PP |
429 | @property |
430 | def addr(cls): | |
431 | return int(cls._cc_ptr) | |
432 | ||
911dec08 PP |
433 | def query_info(cls, action, params=None): |
434 | return _query_info(cls._cc_ptr, action, params) | |
435 | ||
436 | def _query_info_from_bt(cls, action, params): | |
437 | # this can raise, in which case the native call to | |
438 | # bt_component_class_query_info() returns NULL | |
439 | results = cls._query_info(action, params) | |
440 | results = bt2.create_value(results) | |
441 | ||
442 | if results is None: | |
443 | results_addr = int(native_bt.value_null) | |
444 | else: | |
445 | # steal the underlying native value object for the caller | |
446 | results_addr = int(results._ptr) | |
447 | results._ptr = None | |
448 | ||
449 | return results_addr | |
450 | ||
451 | @staticmethod | |
452 | def _query_info(action, params): | |
453 | # BT catches this and returns NULL to the user | |
454 | raise NotImplementedError | |
455 | ||
81447b5b PP |
456 | def __del__(cls): |
457 | if hasattr(cls, '_cc_ptr'): | |
458 | native_bt.put(cls._cc_ptr) | |
459 | ||
460 | ||
461 | class _ComponentInputNotificationIterators(collections.abc.Sequence): | |
462 | def __init__(self, comp, count_func, get_func): | |
463 | self._comp = comp | |
464 | self._count_func = count_func | |
465 | self._get_func = get_func | |
466 | ||
467 | def __len__(self): | |
468 | status, count = self._count_func(self._comp._ptr) | |
469 | utils._handle_ret(status, "cannot get component object's input notification iterator count") | |
470 | return count | |
471 | ||
472 | def __getitem__(self, index): | |
473 | utils._check_uint64(index) | |
474 | ||
475 | if index >= len(self): | |
476 | raise IndexError | |
477 | ||
478 | notif_iter_ptr = self._get_func(self._comp._ptr, index) | |
479 | utils._handle_ptr(notif_iter_ptr, "cannot get component object's input notification iterator") | |
480 | return bt2.notification_iterator._GenericNotificationIterator._create_from_ptr(notif_iter_ptr) | |
481 | ||
482 | ||
483 | class _UserComponent(metaclass=_UserComponentType): | |
484 | @property | |
485 | def addr(self): | |
486 | return int(self._ptr) | |
487 | ||
488 | def __init__(self, *args, **kwargs): | |
489 | pass | |
490 | ||
491 | def _destroy(self): | |
492 | pass | |
493 | ||
494 | def __del__(self): | |
495 | if not self._belongs_to_native_component: | |
496 | self._belongs_to_native_component = True | |
497 | native_bt.py3_component_on_del(self) | |
498 | native_bt.put(self._ptr) | |
499 | ||
500 | ||
501 | class UserSourceComponent(_UserComponent, _CommonSourceComponentMethods): | |
502 | pass | |
503 | ||
504 | ||
505 | class UserFilterComponent(_UserComponent, _CommonFilterComponentMethods): | |
506 | def _set_minimum_input_notification_iterator_count(self, count): | |
507 | utils._check_uint64(count) | |
508 | status = native_bt.component_filter_set_minimum_input_count(self._ptr, count) | |
509 | self._handle_status(status, "unexpected error: cannot set filter component object's minimum input notification iterator count") | |
510 | ||
511 | _minimum_input_notification_iterator_count = property(fset=_set_minimum_input_notification_iterator_count) | |
512 | ||
513 | def _set_maximum_input_notification_iterator_count(self, count): | |
514 | utils._check_uint64(count) | |
515 | status = native_bt.component_filter_set_maximum_input_count(self._ptr, count) | |
516 | self._handle_status(status, "unexpected error: cannot set filter component object's maximum input notification iterator count") | |
517 | ||
518 | _maximum_input_notification_iterator_count = property(fset=_set_maximum_input_notification_iterator_count) | |
519 | ||
520 | @property | |
521 | def _input_notification_iterators(self): | |
522 | return _ComponentInputNotificationIterators(self, | |
523 | native_bt.component_filter_get_input_count, | |
524 | native_bt.component_filter_get_input_iterator_private) | |
525 | ||
526 | def _add_iterator_from_bt(self, notif_iter_ptr): | |
527 | notif_iter = bt2.notification_iterator._GenericNotificationIterator._create_from_ptr(notif_iter_ptr) | |
528 | self._add_notification_iterator(notif_iter) | |
529 | ||
530 | def _add_notification_iterator(self, notif_iter): | |
531 | pass | |
532 | ||
533 | ||
534 | class UserSinkComponent(_UserComponent, _CommonSinkComponentMethods): | |
535 | def _set_minimum_input_notification_iterator_count(self, count): | |
536 | utils._check_uint64(count) | |
537 | status = native_bt.component_sink_set_minimum_input_count(self._ptr, count) | |
538 | self._handle_status(status, "unexpected error: cannot set sink component object's minimum input notification iterator count") | |
539 | ||
540 | _minimum_input_notification_iterator_count = property(fset=_set_minimum_input_notification_iterator_count) | |
541 | ||
542 | def _set_maximum_input_notification_iterator_count(self, count): | |
543 | utils._check_uint64(count) | |
544 | status = native_bt.component_sink_set_maximum_input_count(self._ptr, count) | |
545 | self._handle_status(status, "unexpected error: cannot set sink component object's maximum input notification iterator count") | |
546 | ||
547 | _maximum_input_notification_iterator_count = property(fset=_set_maximum_input_notification_iterator_count) | |
548 | ||
549 | @property | |
550 | def _input_notification_iterators(self): | |
551 | return _ComponentInputNotificationIterators(self, | |
552 | native_bt.component_sink_get_input_count, | |
553 | native_bt.component_sink_get_input_iterator_private) | |
554 | ||
555 | def _add_iterator_from_bt(self, notif_iter_ptr): | |
556 | notif_iter = bt2.notification_iterator._GenericNotificationIterator._create_from_ptr(notif_iter_ptr) | |
557 | self._add_notification_iterator(notif_iter) | |
558 | ||
559 | def _add_notification_iterator(self, notif_iter): | |
560 | pass |