Commit | Line | Data |
---|---|---|
811644b8 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.connection | |
25 | import bt2.component | |
26 | import functools | |
27 | import bt2.port | |
e874da19 | 28 | import bt2.logging |
811644b8 PP |
29 | import bt2 |
30 | ||
31 | ||
5f25509b SM |
32 | def _graph_port_added_listener_from_native(user_listener, |
33 | component_ptr, component_type, | |
34 | port_ptr, port_type): | |
35 | component = bt2.component._create_component_from_ptr_and_get_ref(component_ptr, component_type) | |
36 | port = bt2.port._create_from_ptr_and_get_ref(port_ptr, port_type) | |
37 | user_listener(component, port) | |
811644b8 PP |
38 | |
39 | ||
40 | def _graph_ports_connected_listener_from_native(user_listener, | |
5f25509b | 41 | upstream_component_ptr, upstream_component_type, |
811644b8 | 42 | upstream_port_ptr, |
5f25509b | 43 | downstream_component_ptr, downstream_component_type, |
811644b8 | 44 | downstream_port_ptr): |
5f25509b SM |
45 | upstream_component = bt2.component._create_component_from_ptr_and_get_ref( |
46 | upstream_component_ptr, upstream_component_type) | |
47 | upstream_port = bt2.port._create_from_ptr_and_get_ref( | |
48 | upstream_port_ptr, native_bt.PORT_TYPE_OUTPUT) | |
49 | downstream_component = bt2.component._create_component_from_ptr_and_get_ref( | |
50 | downstream_component_ptr, downstream_component_type) | |
51 | downstream_port = bt2.port._create_from_ptr_and_get_ref( | |
52 | downstream_port_ptr, native_bt.PORT_TYPE_INPUT) | |
53 | user_listener(upstream_component, upstream_port, downstream_component, downstream_port) | |
811644b8 PP |
54 | |
55 | ||
78288f58 | 56 | class Graph(object._SharedObject): |
2f16a6a2 PP |
57 | _get_ref = staticmethod(native_bt.graph_get_ref) |
58 | _put_ref = staticmethod(native_bt.graph_put_ref) | |
601c0026 | 59 | |
811644b8 PP |
60 | def __init__(self): |
61 | ptr = native_bt.graph_create() | |
62 | ||
63 | if ptr is None: | |
64 | raise bt2.CreationError('cannot create graph object') | |
65 | ||
66 | super().__init__(ptr) | |
67 | ||
811644b8 | 68 | |
e874da19 PP |
69 | def add_component(self, component_class, name, params=None, |
70 | logging_level=bt2.logging.LoggingLevel.NONE): | |
5f25509b SM |
71 | if isinstance(component_class, bt2.component._GenericSourceComponentClass): |
72 | cc_ptr = component_class._ptr | |
894a8df5 SM |
73 | add_fn = native_bt.graph_add_source_component |
74 | cc_type = native_bt.COMPONENT_CLASS_TYPE_SOURCE | |
5f25509b SM |
75 | elif isinstance(component_class, bt2.component._GenericFilterComponentClass): |
76 | cc_ptr = component_class._ptr | |
894a8df5 SM |
77 | add_fn = native_bt.graph_add_filter_component |
78 | cc_type = native_bt.COMPONENT_CLASS_TYPE_FILTER | |
5f25509b SM |
79 | elif isinstance(component_class, bt2.component._GenericSinkComponentClass): |
80 | cc_ptr = component_class._ptr | |
81 | add_fn = native_bt.graph_add_sink_component | |
82 | cc_type = native_bt.COMPONENT_CLASS_TYPE_SINK | |
83 | elif issubclass(component_class, bt2.component._UserSourceComponent): | |
85906b6b | 84 | cc_ptr = component_class._bt_cc_ptr |
5f25509b SM |
85 | add_fn = native_bt.graph_add_source_component |
86 | cc_type = native_bt.COMPONENT_CLASS_TYPE_SOURCE | |
894a8df5 | 87 | elif issubclass(component_class, bt2.component._UserSinkComponent): |
85906b6b | 88 | cc_ptr = component_class._bt_cc_ptr |
894a8df5 SM |
89 | add_fn = native_bt.graph_add_sink_component |
90 | cc_type = native_bt.COMPONENT_CLASS_TYPE_SINK | |
5f25509b | 91 | elif issubclass(component_class, bt2.component._UserFilterComponent): |
85906b6b | 92 | cc_ptr = component_class._bt_cc_ptr |
5f25509b SM |
93 | add_fn = native_bt.graph_add_filter_component |
94 | cc_type = native_bt.COMPONENT_CLASS_TYPE_FILTER | |
811644b8 | 95 | else: |
894a8df5 | 96 | raise TypeError("'{}' is not a component class".format( |
601c0026 | 97 | component_class.__class__.__name__)) |
811644b8 PP |
98 | |
99 | utils._check_str(name) | |
e874da19 | 100 | utils._check_log_level(logging_level) |
811644b8 PP |
101 | params = bt2.create_value(params) |
102 | ||
601c0026 | 103 | params_ptr = params._ptr if params is not None else None |
811644b8 | 104 | |
e874da19 PP |
105 | status, comp_ptr = add_fn(self._ptr, cc_ptr, name, |
106 | params_ptr, logging_level) | |
d24d5663 | 107 | utils._handle_func_status(status, 'cannot add component to graph') |
894a8df5 SM |
108 | assert comp_ptr |
109 | return bt2.component._create_component_from_ptr(comp_ptr, cc_type) | |
811644b8 PP |
110 | |
111 | def connect_ports(self, upstream_port, downstream_port): | |
112 | utils._check_type(upstream_port, bt2.port._OutputPort) | |
113 | utils._check_type(downstream_port, bt2.port._InputPort) | |
114 | status, conn_ptr = native_bt.graph_connect_ports(self._ptr, | |
115 | upstream_port._ptr, | |
116 | downstream_port._ptr) | |
d24d5663 PP |
117 | utils._handle_func_status(status, |
118 | 'cannot connect component ports within graph') | |
811644b8 PP |
119 | assert(conn_ptr) |
120 | return bt2.connection._Connection._create_from_ptr(conn_ptr) | |
121 | ||
5f25509b SM |
122 | def add_port_added_listener(self, listener): |
123 | if not callable(listener): | |
811644b8 PP |
124 | raise TypeError("'listener' parameter is not callable") |
125 | ||
d24d5663 | 126 | fn = native_bt.bt2_graph_add_port_added_listener |
5f25509b SM |
127 | listener_from_native = functools.partial(_graph_port_added_listener_from_native, |
128 | listener) | |
811644b8 | 129 | |
5f25509b SM |
130 | listener_ids = fn(self._ptr, listener_from_native) |
131 | if listener_ids is None: | |
132 | utils._raise_bt2_error('cannot add listener to graph object') | |
133 | return bt2._ListenerHandle(listener_ids, self) | |
134 | ||
135 | def add_ports_connected_listener(self, listener): | |
136 | if not callable(listener): | |
137 | raise TypeError("'listener' parameter is not callable") | |
138 | ||
d24d5663 | 139 | fn = native_bt.bt2_graph_add_ports_connected_listener |
5f25509b SM |
140 | listener_from_native = functools.partial(_graph_ports_connected_listener_from_native, |
141 | listener) | |
142 | ||
143 | listener_ids = fn(self._ptr, listener_from_native) | |
144 | if listener_ids is None: | |
145 | utils._raise_bt2_error('cannot add listener to graph object') | |
146 | return bt2._ListenerHandle(listener_ids, self) | |
811644b8 PP |
147 | |
148 | def run(self): | |
149 | status = native_bt.graph_run(self._ptr) | |
150 | ||
d24d5663 PP |
151 | try: |
152 | utils._handle_func_status(status, | |
153 | 'graph object stopped running because of an unexpected error') | |
154 | except bt2.Stop: | |
155 | # done | |
811644b8 | 156 | return |
d24d5663 PP |
157 | except Exception: |
158 | raise | |
811644b8 PP |
159 | |
160 | def cancel(self): | |
161 | status = native_bt.graph_cancel(self._ptr) | |
d24d5663 | 162 | utils._handle_func_status(status, 'cannot cancel graph object') |
811644b8 PP |
163 | |
164 | @property | |
165 | def is_canceled(self): | |
166 | is_canceled = native_bt.graph_is_canceled(self._ptr) | |
167 | assert(is_canceled >= 0) | |
168 | return is_canceled > 0 | |
169 | ||
2ae9f48c SM |
170 | def create_output_port_message_iterator(self, output_port): |
171 | utils._check_type(output_port, bt2.port._OutputPort) | |
172 | msg_iter_ptr = native_bt.port_output_message_iterator_create(self._ptr, output_port._ptr) | |
173 | ||
174 | if msg_iter_ptr is None: | |
175 | raise bt2.CreationError('cannot create output port message iterator') | |
176 | ||
177 | return bt2.message_iterator._OutputPortMessageIterator(msg_iter_ptr) |