1 # The MIT License (MIT)
3 # Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
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:
12 # The above copyright notice and this permission notice shall be included in
13 # all copies or substantial portions of the Software.
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
23 from bt2
import native_bt
, object, utils
24 import bt2
.clock_snapshot
33 def _create_from_ptr(ptr
):
34 msg_type
= native_bt
.message_get_type(ptr
)
37 if msg_type
not in _MESSAGE_TYPE_TO_CLS
:
38 raise bt2
.Error('unknown message type: {}'.format(msg_type
))
40 return _MESSAGE_TYPE_TO_CLS
[msg_type
]._create
_from
_ptr
(ptr
)
43 def _msg_types_from_msg_classes(message_types
):
44 if message_types
is None:
47 for msg_cls
in message_types
:
48 if msg_cls
not in _MESSAGE_TYPE_TO_CLS
.values():
49 raise ValueError("'{}' is not a message class".format(msg_cls
))
51 msg_types
= [msg_cls
._TYPE
for msg_cls
in message_types
]
56 class _Message(object._SharedObject
):
57 _get_ref
= staticmethod(native_bt
.message_get_ref
)
58 _put_ref
= staticmethod(native_bt
.message_put_ref
)
61 class _CopyableMessage(_Message
):
63 return self
._copy
(lambda obj
: obj
)
65 def __deepcopy__(self
, memo
):
66 cpy
= self
._copy
(copy
.deepcopy
)
71 class _EventMessage(_CopyableMessage
):
72 _TYPE
= native_bt
.MESSAGE_TYPE_EVENT
76 event_ptr
= native_bt
.message_event_borrow_event(self
._ptr
)
77 assert event_ptr
is not None
78 return bt2
.event
._Event
._create
_from
_ptr
_and
_get
_ref
(
79 event_ptr
, self
._ptr
, self
._get
_ref
, self
._put
_ref
)
82 def default_clock_snapshot(self
):
83 if self
.event
.event_class
.stream_class
.default_clock_class
is None:
86 snapshot_ptr
= native_bt
.message_event_borrow_default_clock_snapshot_const(self
._ptr
)
88 return bt2
.clock_snapshot
._ClockSnapshot
._create
_from
_ptr
_and
_get
_ref
(
89 snapshot_ptr
, self
._ptr
, self
._get
_ref
, self
._put
_ref
)
92 def clock_class_priority_map(self
):
93 cc_prio_map_ptr
= native_bt
.message_event_get_clock_class_priority_map(self
._ptr
)
94 assert(cc_prio_map_ptr
)
95 return bt2
.clock_class_priority_map
.ClockClassPriorityMap
._create
_from
_ptr
(cc_prio_map_ptr
)
97 def __eq__(self
, other
):
98 if type(other
) is not type(self
):
101 if self
.addr
== other
.addr
:
106 self
.clock_class_priority_map
,
110 other
.clock_class_priority_map
,
112 return self_props
== other_props
114 def _copy(self
, copy_func
):
115 # We can always use references here because those properties are
116 # frozen anyway if they are part of a message. Since the
117 # user cannot modify them after copying the message, it's
118 # useless to copy/deep-copy them.
119 return EventMessage(self
.event
, self
.clock_class_priority_map
)
122 class _PacketBeginningMessage(_CopyableMessage
):
123 _TYPE
= native_bt
.MESSAGE_TYPE_PACKET_BEGINNING
127 packet_ptr
= native_bt
.message_packet_begin_get_packet(self
._ptr
)
129 return bt2
.packet
._Packet
._create
_from
_ptr
(packet_ptr
)
131 def __eq__(self
, other
):
132 if type(other
) is not type(self
):
135 if self
.addr
== other
.addr
:
138 return self
.packet
== other
.packet
140 def _copy(self
, copy_func
):
141 # We can always use references here because those properties are
142 # frozen anyway if they are part of a message. Since the
143 # user cannot modify them after copying the message, it's
144 # useless to copy/deep-copy them.
145 return PacketBeginningMessage(self
.packet
)
148 class _PacketEndMessage(_CopyableMessage
):
149 _TYPE
= native_bt
.MESSAGE_TYPE_PACKET_END
153 packet_ptr
= native_bt
.message_packet_end_get_packet(self
._ptr
)
155 return bt2
.packet
._Packet
._create
_from
_ptr
(packet_ptr
)
157 def __eq__(self
, other
):
158 if type(other
) is not type(self
):
161 if self
.addr
== other
.addr
:
164 return self
.packet
== other
.packet
166 def _copy(self
, copy_func
):
167 # We can always use references here because those properties are
168 # frozen anyway if they are part of a message. Since the
169 # user cannot modify them after copying the message, it's
170 # useless to copy/deep-copy them.
171 return PacketEndMessage(self
.packet
)
174 class _StreamBeginningMessage(_CopyableMessage
):
175 _TYPE
= native_bt
.MESSAGE_TYPE_STREAM_BEGINNING
179 stream_ptr
= native_bt
.message_stream_begin_get_stream(self
._ptr
)
181 return bt2
.stream
._create
_from
_ptr
(stream_ptr
)
183 def __eq__(self
, other
):
184 if type(other
) is not type(self
):
187 if self
.addr
== other
.addr
:
190 return self
.stream
== other
.stream
192 def _copy(self
, copy_func
):
193 # We can always use references here because those properties are
194 # frozen anyway if they are part of a message. Since the
195 # user cannot modify them after copying the message, it's
196 # useless to copy/deep-copy them.
197 return StreamBeginningMessage(self
.stream
)
200 class _StreamEndMessage(_CopyableMessage
):
201 _TYPE
= native_bt
.MESSAGE_TYPE_STREAM_END
205 stream_ptr
= native_bt
.message_stream_end_get_stream(self
._ptr
)
207 return bt2
.stream
._create
_from
_ptr
(stream_ptr
)
209 def __eq__(self
, other
):
210 if type(other
) is not type(self
):
213 if self
.addr
== other
.addr
:
216 return self
.stream
== other
.stream
218 def _copy(self
, copy_func
):
219 # We can always use references here because those properties are
220 # frozen anyway if they are part of a message. Since the
221 # user cannot modify them after copying the message, it's
222 # useless to copy/deep-copy them.
223 return StreamEndMessage(self
.stream
)
226 class _InactivityMessageClockSnapshotsIterator(collections
.abc
.Iterator
):
227 def __init__(self
, msg_clock_snapshots
):
228 self
._msg
_clock
_snapshots
= msg_clock_snapshots
229 self
._clock
_classes
= list(msg_clock_snapshots
._msg
.clock_class_priority_map
)
233 if self
._at
== len(self
._clock
_classes
):
237 return self
._clock
_classes
[at
]
240 class _InactivityMessageClockSnapshots(collections
.abc
.Mapping
):
241 def __init__(self
, msg
):
244 def __getitem__(self
, clock_class
):
245 utils
._check
_type
(clock_class
, bt2
.ClockClass
)
246 clock_snapshot_ptr
= native_bt
.message_inactivity_get_clock_snapshot(self
._msg
._ptr
,
249 if clock_snapshot_ptr
is None:
252 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
253 return clock_snapshot
255 def add(self
, clock_snapshot
):
256 utils
._check
_type
(clock_snapshot
, bt2
.clock_snapshot
._ClockSnapshot
)
257 ret
= native_bt
.message_inactivity_set_clock_snapshot(self
._msg
._ptr
,
259 utils
._handle
_ret
(ret
, "cannot set inactivity message object's clock value")
262 return len(self
._msg
.clock_class_priority_map
)
265 return _InactivityMessageClockSnapshotsIterator(self
)
268 class InactivityMessage(_CopyableMessage
):
269 _TYPE
= native_bt
.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
271 def __init__(self
, cc_prio_map
=None):
272 if cc_prio_map
is not None:
273 utils
._check
_type
(cc_prio_map
, bt2
.clock_class_priority_map
.ClockClassPriorityMap
)
274 cc_prio_map_ptr
= cc_prio_map
._ptr
276 cc_prio_map_ptr
= None
278 ptr
= native_bt
.message_inactivity_create(cc_prio_map_ptr
)
281 raise bt2
.CreationError('cannot create inactivity message object')
283 super().__init
__(ptr
)
286 def clock_class_priority_map(self
):
287 cc_prio_map_ptr
= native_bt
.message_inactivity_get_clock_class_priority_map(self
._ptr
)
288 assert(cc_prio_map_ptr
)
289 return bt2
.clock_class_priority_map
.ClockClassPriorityMap
._create
_from
_ptr
(cc_prio_map_ptr
)
292 def clock_snapshots(self
):
293 return _InactivityMessageClockSnapshots(self
)
295 def _get_clock_snapshots(self
):
298 for clock_class
, clock_snapshot
in self
.clock_snapshots
.items():
299 if clock_snapshot
is None:
302 clock_snapshots
[clock_class
] = clock_snapshot
304 return clock_snapshots
306 def __eq__(self
, other
):
307 if type(other
) is not type(self
):
310 if self
.addr
== other
.addr
:
314 self
.clock_class_priority_map
,
315 self
._get
_clock
_snapshots
(),
318 other
.clock_class_priority_map
,
319 other
._get
_clock
_snapshots
(),
321 return self_props
== other_props
324 cpy
= InactivityMessage(self
.clock_class_priority_map
)
326 for clock_class
, clock_snapshot
in self
.clock_snapshots
.items():
327 if clock_snapshot
is None:
330 cpy
.clock_snapshots
.add(clock_snapshot
)
334 def __deepcopy__(self
, memo
):
335 cc_prio_map_cpy
= copy
.deepcopy(self
.clock_class_priority_map
)
336 cpy
= InactivityMessage(cc_prio_map_cpy
)
339 for orig_clock_class
in self
.clock_class_priority_map
:
340 orig_clock_snapshot
= self
.clock_snapshot(orig_clock_class
)
342 if orig_clock_snapshot
is None:
345 # find equivalent, copied clock class in CC priority map copy
346 for cpy_clock_class
in cc_prio_map_cpy
:
347 if cpy_clock_class
== orig_clock_class
:
350 # create copy of clock value from copied clock class
351 clock_snapshot_cpy
= cpy_clock_class(orig_clock_snapshot
.cycles
)
353 # set copied clock value in message copy
354 cpy
.clock_snapshots
.add(clock_snapshot_cpy
)
360 class _DiscardedElementsMessage(_Message
):
361 def __eq__(self
, other
):
362 if type(other
) is not type(self
):
365 if self
.addr
== other
.addr
:
371 self
.beginning_clock_snapshot
,
372 self
.end_clock_snapshot
,
377 other
.beginning_clock_snapshot
,
378 other
.end_clock_snapshot
,
380 return self_props
== other_props
383 class _DiscardedPacketsMessage(_DiscardedElementsMessage
):
384 _TYPE
= native_bt
.MESSAGE_TYPE_DISCARDED_PACKETS
388 count
= native_bt
.message_discarded_packets_get_count(self
._ptr
)
394 stream_ptr
= native_bt
.message_discarded_packets_get_stream(self
._ptr
)
396 return bt2
.stream
._create
_from
_ptr
(stream_ptr
)
399 def beginning_clock_snapshot(self
):
400 clock_snapshot_ptr
= native_bt
.message_discarded_packets_get_begin_clock_snapshot(self
._ptr
)
402 if clock_snapshot_ptr
is None:
405 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
406 return clock_snapshot
409 def end_clock_snapshot(self
):
410 clock_snapshot_ptr
= native_bt
.message_discarded_packets_get_end_clock_snapshot(self
._ptr
)
412 if clock_snapshot_ptr
is None:
415 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
416 return clock_snapshot
419 class _DiscardedEventsMessage(_DiscardedElementsMessage
):
420 _TYPE
= native_bt
.MESSAGE_TYPE_DISCARDED_EVENTS
424 count
= native_bt
.message_discarded_events_get_count(self
._ptr
)
430 stream_ptr
= native_bt
.message_discarded_events_get_stream(self
._ptr
)
432 return bt2
.stream
._create
_from
_ptr
(stream_ptr
)
435 def beginning_clock_snapshot(self
):
436 clock_snapshot_ptr
= native_bt
.message_discarded_events_get_begin_clock_snapshot(self
._ptr
)
438 if clock_snapshot_ptr
is None:
441 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
442 return clock_snapshot
445 def end_clock_snapshot(self
):
446 clock_snapshot_ptr
= native_bt
.message_discarded_events_get_end_clock_snapshot(self
._ptr
)
448 if clock_snapshot_ptr
is None:
451 clock_snapshot
= bt2
.clock_snapshot
._create
_clock
_snapshot
_from
_ptr
(clock_snapshot_ptr
)
452 return clock_snapshot
455 _MESSAGE_TYPE_TO_CLS
= {
456 native_bt
.MESSAGE_TYPE_EVENT
: _EventMessage
,
457 native_bt
.MESSAGE_TYPE_PACKET_BEGINNING
: _PacketBeginningMessage
,
458 native_bt
.MESSAGE_TYPE_PACKET_END
: _PacketEndMessage
,
459 native_bt
.MESSAGE_TYPE_STREAM_BEGINNING
: _StreamBeginningMessage
,
460 native_bt
.MESSAGE_TYPE_STREAM_END
: _StreamEndMessage
,
461 native_bt
.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
: InactivityMessage
,
462 native_bt
.MESSAGE_TYPE_DISCARDED_PACKETS
: _DiscardedPacketsMessage
,
463 native_bt
.MESSAGE_TYPE_DISCARDED_EVENTS
: _DiscardedEventsMessage
,