bumble 0.0.209__py3-none-any.whl → 0.0.210__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. bumble/_version.py +2 -2
  2. bumble/a2dp.py +7 -7
  3. bumble/apps/auracast.py +37 -29
  4. bumble/apps/bench.py +9 -7
  5. bumble/apps/console.py +1 -1
  6. bumble/apps/lea_unicast/app.py +6 -2
  7. bumble/apps/pair.py +4 -3
  8. bumble/apps/player/player.py +3 -3
  9. bumble/apps/rfcomm_bridge.py +1 -1
  10. bumble/apps/speaker/speaker.py +4 -2
  11. bumble/att.py +2 -3
  12. bumble/avc.py +5 -5
  13. bumble/avdtp.py +9 -10
  14. bumble/avrcp.py +18 -19
  15. bumble/bridge.py +2 -2
  16. bumble/controller.py +6 -7
  17. bumble/core.py +56 -56
  18. bumble/device.py +169 -137
  19. bumble/drivers/__init__.py +2 -2
  20. bumble/gap.py +1 -1
  21. bumble/gatt_adapters.py +3 -3
  22. bumble/gatt_client.py +27 -21
  23. bumble/gatt_server.py +9 -10
  24. bumble/hci.py +34 -20
  25. bumble/hfp.py +3 -3
  26. bumble/hid.py +4 -3
  27. bumble/host.py +22 -16
  28. bumble/keys.py +3 -3
  29. bumble/l2cap.py +19 -17
  30. bumble/link.py +3 -4
  31. bumble/pairing.py +3 -3
  32. bumble/pandora/__init__.py +5 -5
  33. bumble/pandora/host.py +18 -12
  34. bumble/pandora/l2cap.py +2 -2
  35. bumble/pandora/security.py +15 -16
  36. bumble/profiles/aics.py +6 -6
  37. bumble/profiles/ancs.py +9 -10
  38. bumble/profiles/ascs.py +17 -10
  39. bumble/profiles/asha.py +5 -5
  40. bumble/profiles/bass.py +1 -1
  41. bumble/profiles/csip.py +10 -10
  42. bumble/profiles/gatt_service.py +12 -12
  43. bumble/profiles/hap.py +16 -16
  44. bumble/profiles/mcp.py +26 -24
  45. bumble/profiles/pacs.py +6 -6
  46. bumble/profiles/pbp.py +1 -1
  47. bumble/profiles/vcs.py +6 -4
  48. bumble/profiles/vocs.py +3 -3
  49. bumble/rfcomm.py +8 -8
  50. bumble/sdp.py +1 -1
  51. bumble/smp.py +36 -30
  52. bumble/transport/__init__.py +24 -19
  53. bumble/transport/android_emulator.py +8 -4
  54. bumble/transport/android_netsim.py +8 -5
  55. bumble/transport/common.py +5 -1
  56. bumble/transport/file.py +1 -1
  57. bumble/transport/hci_socket.py +1 -1
  58. bumble/transport/pty.py +1 -1
  59. bumble/transport/pyusb.py +3 -3
  60. bumble/transport/serial.py +1 -1
  61. bumble/transport/tcp_client.py +1 -1
  62. bumble/transport/tcp_server.py +1 -1
  63. bumble/transport/udp.py +1 -1
  64. bumble/transport/unix.py +1 -1
  65. bumble/transport/vhci.py +2 -2
  66. bumble/transport/ws_client.py +6 -1
  67. bumble/transport/ws_server.py +1 -1
  68. bumble/utils.py +89 -76
  69. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/METADATA +3 -2
  70. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/RECORD +74 -74
  71. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/WHEEL +1 -1
  72. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/entry_points.txt +0 -0
  73. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info/licenses}/LICENSE +0 -0
  74. {bumble-0.0.209.dist-info → bumble-0.0.210.dist-info}/top_level.txt +0 -0
bumble/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.0.209'
21
- __version_tuple__ = version_tuple = (0, 0, 209)
20
+ __version__ = version = '0.0.210'
21
+ __version_tuple__ = version_tuple = (0, 0, 210)
bumble/a2dp.py CHANGED
@@ -26,9 +26,9 @@ from typing import Awaitable, Callable
26
26
  from typing_extensions import ClassVar, Self
27
27
 
28
28
 
29
- from .codecs import AacAudioRtpPacket
30
- from .company_ids import COMPANY_IDENTIFIERS
31
- from .sdp import (
29
+ from bumble.codecs import AacAudioRtpPacket
30
+ from bumble.company_ids import COMPANY_IDENTIFIERS
31
+ from bumble.sdp import (
32
32
  DataElement,
33
33
  ServiceAttribute,
34
34
  SDP_PUBLIC_BROWSE_ROOT,
@@ -38,7 +38,7 @@ from .sdp import (
38
38
  SDP_PROTOCOL_DESCRIPTOR_LIST_ATTRIBUTE_ID,
39
39
  SDP_BLUETOOTH_PROFILE_DESCRIPTOR_LIST_ATTRIBUTE_ID,
40
40
  )
41
- from .core import (
41
+ from bumble.core import (
42
42
  BT_L2CAP_PROTOCOL_ID,
43
43
  BT_AUDIO_SOURCE_SERVICE,
44
44
  BT_AUDIO_SINK_SERVICE,
@@ -46,7 +46,7 @@ from .core import (
46
46
  BT_ADVANCED_AUDIO_DISTRIBUTION_SERVICE,
47
47
  name_or_number,
48
48
  )
49
- from .rtp import MediaPacket
49
+ from bumble.rtp import MediaPacket
50
50
 
51
51
 
52
52
  # -----------------------------------------------------------------------------
@@ -155,7 +155,7 @@ def flags_to_list(flags, values):
155
155
  # -----------------------------------------------------------------------------
156
156
  def make_audio_source_service_sdp_records(service_record_handle, version=(1, 3)):
157
157
  # pylint: disable=import-outside-toplevel
158
- from .avdtp import AVDTP_PSM
158
+ from bumble.avdtp import AVDTP_PSM
159
159
 
160
160
  version_int = version[0] << 8 | version[1]
161
161
  return [
@@ -209,7 +209,7 @@ def make_audio_source_service_sdp_records(service_record_handle, version=(1, 3))
209
209
  # -----------------------------------------------------------------------------
210
210
  def make_audio_sink_service_sdp_records(service_record_handle, version=(1, 3)):
211
211
  # pylint: disable=import-outside-toplevel
212
- from .avdtp import AVDTP_PSM
212
+ from bumble.avdtp import AVDTP_PSM
213
213
 
214
214
  version_int = version[0] << 8 | version[1]
215
215
  return [
bumble/apps/auracast.py CHANGED
@@ -18,7 +18,6 @@
18
18
  from __future__ import annotations
19
19
 
20
20
  import asyncio
21
- import asyncio.subprocess
22
21
  import collections
23
22
  import contextlib
24
23
  import dataclasses
@@ -36,7 +35,6 @@ from typing import (
36
35
  )
37
36
 
38
37
  import click
39
- import pyee
40
38
 
41
39
  try:
42
40
  import lc3 # type: ignore # pylint: disable=E0401
@@ -99,12 +97,31 @@ def codec_config_string(
99
97
  return '\n'.join(indent + line for line in lines)
100
98
 
101
99
 
100
+ def broadcast_code_bytes(broadcast_code: str) -> bytes:
101
+ """
102
+ Convert a broadcast code string to a 16-byte value.
103
+
104
+ If `broadcast_code` is `0x` followed by 32 hex characters, it is interpreted as a
105
+ raw 16-byte raw broadcast code in big-endian byte order.
106
+ Otherwise, `broadcast_code` is converted to a 16-byte value as specified in
107
+ BLUETOOTH CORE SPECIFICATION Version 6.0 | Vol 3, Part C , section 3.2.6.3
108
+ """
109
+ if broadcast_code.startswith("0x") and len(broadcast_code) == 34:
110
+ return bytes.fromhex(broadcast_code[2:])[::-1]
111
+
112
+ broadcast_code_utf8 = broadcast_code.encode("utf-8")
113
+ if len(broadcast_code_utf8) > 16:
114
+ raise ValueError("broadcast code must be <= 16 bytes in utf-8 encoding")
115
+ padding = bytes(16 - len(broadcast_code_utf8))
116
+ return broadcast_code_utf8 + padding
117
+
118
+
102
119
  # -----------------------------------------------------------------------------
103
120
  # Scan For Broadcasts
104
121
  # -----------------------------------------------------------------------------
105
- class BroadcastScanner(pyee.EventEmitter):
122
+ class BroadcastScanner(bumble.utils.EventEmitter):
106
123
  @dataclasses.dataclass
107
- class Broadcast(pyee.EventEmitter):
124
+ class Broadcast(bumble.utils.EventEmitter):
108
125
  name: str | None
109
126
  sync: bumble.device.PeriodicAdvertisingSync
110
127
  broadcast_id: int
@@ -234,22 +251,14 @@ class BroadcastScanner(pyee.EventEmitter):
234
251
 
235
252
  if self.biginfo:
236
253
  print(color(' BIG:', 'cyan'))
237
- print(
238
- color(' Number of BIS:', 'magenta'),
239
- self.biginfo.num_bis,
240
- )
241
- print(
242
- color(' PHY: ', 'magenta'),
243
- self.biginfo.phy.name,
244
- )
245
- print(
246
- color(' Framed: ', 'magenta'),
247
- self.biginfo.framed,
248
- )
249
- print(
250
- color(' Encrypted: ', 'magenta'),
251
- self.biginfo.encrypted,
252
- )
254
+ print(color(' Number of BIS:', 'magenta'), self.biginfo.num_bis)
255
+ print(color(' ISO Interval: ', 'magenta'), self.biginfo.iso_interval)
256
+ print(color(' Max PDU: ', 'magenta'), self.biginfo.max_pdu)
257
+ print(color(' SDU Interval: ', 'magenta'), self.biginfo.sdu_interval)
258
+ print(color(' Max SDU: ', 'magenta'), self.biginfo.max_sdu)
259
+ print(color(' PHY: ', 'magenta'), self.biginfo.phy.name)
260
+ print(color(' Framed: ', 'magenta'), self.biginfo.framed)
261
+ print(color(' Encrypted: ', 'magenta'), self.biginfo.encrypted)
253
262
 
254
263
  def on_sync_establishment(self) -> None:
255
264
  self.emit('sync_establishment')
@@ -365,7 +374,7 @@ class BroadcastScanner(pyee.EventEmitter):
365
374
  self.emit('broadcast_loss', broadcast)
366
375
 
367
376
 
368
- class PrintingBroadcastScanner(pyee.EventEmitter):
377
+ class PrintingBroadcastScanner(bumble.utils.EventEmitter):
369
378
  def __init__(
370
379
  self, device: bumble.device.Device, filter_duplicates: bool, sync_timeout: float
371
380
  ) -> None:
@@ -702,14 +711,13 @@ async def run_receive(
702
711
 
703
712
  def on_change() -> None:
704
713
  if (
705
- broadcast.basic_audio_announcement
706
- and not basic_audio_announcement_scanned.is_set()
707
- ):
714
+ broadcast.basic_audio_announcement and broadcast.biginfo
715
+ ) and not basic_audio_announcement_scanned.is_set():
708
716
  basic_audio_announcement_scanned.set()
709
717
 
710
718
  broadcast.on('change', on_change)
711
- if not broadcast.basic_audio_announcement:
712
- print('Wait for Basic Audio Announcement...')
719
+ if not broadcast.basic_audio_announcement or not broadcast.biginfo:
720
+ print('Wait for Basic Audio Announcement and BIG Info...')
713
721
  await basic_audio_announcement_scanned.wait()
714
722
  print('Basic Audio Announcement found')
715
723
  broadcast.print()
@@ -730,7 +738,7 @@ async def run_receive(
730
738
  big_sync_timeout=0x4000,
731
739
  bis=[bis.index for bis in subgroup.bis],
732
740
  broadcast_code=(
733
- bytes.fromhex(broadcast_code) if broadcast_code else None
741
+ broadcast_code_bytes(broadcast_code) if broadcast_code else None
734
742
  ),
735
743
  ),
736
744
  )
@@ -944,7 +952,7 @@ async def run_transmit(
944
952
  max_transport_latency=65,
945
953
  rtn=4,
946
954
  broadcast_code=(
947
- bytes.fromhex(broadcast_code) if broadcast_code else None
955
+ broadcast_code_bytes(broadcast_code) if broadcast_code else None
948
956
  ),
949
957
  ),
950
958
  )
@@ -1088,7 +1096,7 @@ def pair(ctx, transport, address):
1088
1096
  '--broadcast-code',
1089
1097
  metavar='BROADCAST_CODE',
1090
1098
  type=str,
1091
- help='Broadcast encryption code in hex format',
1099
+ help='Broadcast encryption code (string or raw hex format prefixed with 0x)',
1092
1100
  )
1093
1101
  @click.option(
1094
1102
  '--sync-timeout',
bumble/apps/bench.py CHANGED
@@ -28,8 +28,7 @@ import click
28
28
 
29
29
  from bumble import l2cap
30
30
  from bumble.core import (
31
- BT_BR_EDR_TRANSPORT,
32
- BT_LE_TRANSPORT,
31
+ PhysicalTransport,
33
32
  BT_L2CAP_PROTOCOL_ID,
34
33
  BT_RFCOMM_PROTOCOL_ID,
35
34
  UUID,
@@ -42,8 +41,7 @@ from bumble.hci import (
42
41
  HCI_LE_1M_PHY,
43
42
  HCI_LE_2M_PHY,
44
43
  HCI_LE_CODED_PHY,
45
- HCI_CENTRAL_ROLE,
46
- HCI_PERIPHERAL_ROLE,
44
+ Role,
47
45
  HCI_Constant,
48
46
  HCI_Error,
49
47
  HCI_StatusError,
@@ -113,7 +111,7 @@ def print_connection_phy(phy):
113
111
 
114
112
  def print_connection(connection):
115
113
  params = []
116
- if connection.transport == BT_LE_TRANSPORT:
114
+ if connection.transport == PhysicalTransport.LE:
117
115
  params.append(
118
116
  'DL=('
119
117
  f'TX:{connection.data_length[0]}/{connection.data_length[1]},'
@@ -189,7 +187,7 @@ def log_stats(title, stats, precision=2):
189
187
 
190
188
 
191
189
  async def switch_roles(connection, role):
192
- target_role = HCI_CENTRAL_ROLE if role == "central" else HCI_PERIPHERAL_ROLE
190
+ target_role = Role.CENTRAL if role == "central" else Role.PERIPHERAL
193
191
  if connection.role != target_role:
194
192
  logging.info(f'{color("### Switching roles to:", "cyan")} {role}')
195
193
  try:
@@ -1275,7 +1273,11 @@ class Central(Connection.Listener):
1275
1273
  self.connection = await self.device.connect(
1276
1274
  self.peripheral_address,
1277
1275
  connection_parameters_preferences=self.connection_parameter_preferences,
1278
- transport=BT_BR_EDR_TRANSPORT if self.classic else BT_LE_TRANSPORT,
1276
+ transport=(
1277
+ PhysicalTransport.BR_EDR
1278
+ if self.classic
1279
+ else PhysicalTransport.LE
1280
+ ),
1279
1281
  )
1280
1282
  except CommandTimeoutError:
1281
1283
  logging.info(color('!!! Connection timed out', 'red'))
bumble/apps/console.py CHANGED
@@ -55,7 +55,7 @@ from prompt_toolkit.layout import (
55
55
  from bumble import __version__
56
56
  import bumble.core
57
57
  from bumble import colors
58
- from bumble.core import UUID, AdvertisingData, BT_LE_TRANSPORT
58
+ from bumble.core import UUID, AdvertisingData, PhysicalTransport
59
59
  from bumble.device import (
60
60
  ConnectionParametersPreferences,
61
61
  ConnectionPHY,
@@ -37,6 +37,7 @@ import click
37
37
  import aiohttp.web
38
38
 
39
39
  import bumble
40
+ from bumble import utils
40
41
  from bumble.core import AdvertisingData
41
42
  from bumble.colors import color
42
43
  from bumble.device import Device, DeviceConfiguration, AdvertisingParameters, CisLink
@@ -359,7 +360,9 @@ class Speaker:
359
360
  pcm = decoder.decode(
360
361
  pdu.iso_sdu_fragment, bit_depth=DEFAULT_PCM_BYTES_PER_SAMPLE * 8
361
362
  )
362
- self.device.abort_on('disconnection', self.ui_server.send_audio(pcm))
363
+ utils.cancel_on_event(
364
+ self.device, 'disconnection', self.ui_server.send_audio(pcm)
365
+ )
363
366
 
364
367
  def on_ase_state_change(ase: ascs.AseStateMachine) -> None:
365
368
  codec_config = ase.codec_specific_configuration
@@ -373,7 +376,8 @@ class Speaker:
373
376
  or codec_config.codec_frames_per_sdu is None
374
377
  ):
375
378
  return
376
- ase.cis_link.abort_on(
379
+ utils.cancel_on_event(
380
+ ase.cis_link,
377
381
  'disconnection',
378
382
  lc3_source_task(
379
383
  filename=self.lc3_input_file_path,
bumble/apps/pair.py CHANGED
@@ -31,8 +31,7 @@ from bumble.keys import JsonKeyStore
31
31
  from bumble.core import (
32
32
  AdvertisingData,
33
33
  ProtocolError,
34
- BT_LE_TRANSPORT,
35
- BT_BR_EDR_TRANSPORT,
34
+ PhysicalTransport,
36
35
  )
37
36
  from bumble.gatt import (
38
37
  GATT_DEVICE_NAME_CHARACTERISTIC,
@@ -422,7 +421,9 @@ async def pair(
422
421
  print(color(f'=== Connecting to {address_or_name}...', 'green'))
423
422
  connection = await device.connect(
424
423
  address_or_name,
425
- transport=BT_LE_TRANSPORT if mode == 'le' else BT_BR_EDR_TRANSPORT,
424
+ transport=(
425
+ PhysicalTransport.LE if mode == 'le' else PhysicalTransport.BR_EDR
426
+ ),
426
427
  )
427
428
 
428
429
  if not request:
@@ -56,7 +56,7 @@ from bumble.core import (
56
56
  AdvertisingData,
57
57
  ConnectionError as BumbleConnectionError,
58
58
  DeviceClass,
59
- BT_BR_EDR_TRANSPORT,
59
+ PhysicalTransport,
60
60
  )
61
61
  from bumble.device import Connection, Device, DeviceConfiguration
62
62
  from bumble.hci import Address, HCI_CONNECTION_ALREADY_EXISTS_ERROR, HCI_Constant
@@ -286,7 +286,7 @@ class Player:
286
286
 
287
287
  async def connect(self, device: Device, address: str) -> Connection:
288
288
  print(color(f"Connecting to {address}...", "green"))
289
- connection = await device.connect(address, transport=BT_BR_EDR_TRANSPORT)
289
+ connection = await device.connect(address, transport=PhysicalTransport.BR_EDR)
290
290
 
291
291
  # Request authentication
292
292
  if self.authenticate:
@@ -402,7 +402,7 @@ class Player:
402
402
 
403
403
  async def pair(self, device: Device, address: str) -> None:
404
404
  print(color(f"Connecting to {address}...", "green"))
405
- connection = await device.connect(address, transport=BT_BR_EDR_TRANSPORT)
405
+ connection = await device.connect(address, transport=PhysicalTransport.BR_EDR)
406
406
 
407
407
  print(color("Pairing...", "magenta"))
408
408
  await connection.authenticate()
@@ -271,7 +271,7 @@ class ClientBridge:
271
271
  print(color(f"@@@ Connecting to Bluetooth {self.address}", "blue"))
272
272
  assert self.device
273
273
  self.connection = await self.device.connect(
274
- self.address, transport=core.BT_BR_EDR_TRANSPORT
274
+ self.address, transport=core.PhysicalTransport.BR_EDR
275
275
  )
276
276
  print(color(f"@@@ Bluetooth connection: {self.connection}", "blue"))
277
277
  self.connection.on("disconnection", self.on_disconnection)
@@ -34,7 +34,7 @@ from aiohttp import web
34
34
 
35
35
  import bumble
36
36
  from bumble.colors import color
37
- from bumble.core import BT_BR_EDR_TRANSPORT, CommandTimeoutError
37
+ from bumble.core import PhysicalTransport, CommandTimeoutError
38
38
  from bumble.device import Connection, Device, DeviceConfiguration
39
39
  from bumble.hci import HCI_StatusError
40
40
  from bumble.pairing import PairingConfig
@@ -568,7 +568,9 @@ class Speaker:
568
568
  async def connect(self, address):
569
569
  # Connect to the source
570
570
  print(f'=== Connecting to {address}...')
571
- connection = await self.device.connect(address, transport=BT_BR_EDR_TRANSPORT)
571
+ connection = await self.device.connect(
572
+ address, transport=PhysicalTransport.BR_EDR
573
+ )
572
574
  print(f'=== Connected to {connection.peer_address}')
573
575
 
574
576
  # Request authentication
bumble/att.py CHANGED
@@ -41,7 +41,6 @@ from typing import (
41
41
  TYPE_CHECKING,
42
42
  )
43
43
 
44
- from pyee import EventEmitter
45
44
 
46
45
  from bumble import utils
47
46
  from bumble.core import UUID, name_or_number, InvalidOperationError, ProtocolError
@@ -798,7 +797,7 @@ class AttributeValue(Generic[_T]):
798
797
 
799
798
 
800
799
  # -----------------------------------------------------------------------------
801
- class Attribute(EventEmitter, Generic[_T]):
800
+ class Attribute(utils.EventEmitter, Generic[_T]):
802
801
  class Permissions(enum.IntFlag):
803
802
  READABLE = 0x01
804
803
  WRITEABLE = 0x02
@@ -845,7 +844,7 @@ class Attribute(EventEmitter, Generic[_T]):
845
844
  permissions: Union[str, Attribute.Permissions],
846
845
  value: Union[AttributeValue[_T], _T, None] = None,
847
846
  ) -> None:
848
- EventEmitter.__init__(self)
847
+ utils.EventEmitter.__init__(self)
849
848
  self.handle = 0
850
849
  self.end_group_handle = 0
851
850
  if isinstance(permissions, str):
bumble/avc.py CHANGED
@@ -21,7 +21,7 @@ import struct
21
21
  from typing import Dict, Type, Union, Tuple
22
22
 
23
23
  from bumble import core
24
- from bumble.utils import OpenIntEnum
24
+ from bumble import utils
25
25
 
26
26
 
27
27
  # -----------------------------------------------------------------------------
@@ -43,7 +43,7 @@ class Frame:
43
43
  EXTENDED = 0x1E
44
44
  UNIT = 0x1F
45
45
 
46
- class OperationCode(OpenIntEnum):
46
+ class OperationCode(utils.OpenIntEnum):
47
47
  # 0x00 - 0x0F: Unit and subunit commands
48
48
  VENDOR_DEPENDENT = 0x00
49
49
  RESERVE = 0x01
@@ -204,7 +204,7 @@ class Frame:
204
204
 
205
205
  # -----------------------------------------------------------------------------
206
206
  class CommandFrame(Frame):
207
- class CommandType(OpenIntEnum):
207
+ class CommandType(utils.OpenIntEnum):
208
208
  # AV/C Digital Interface Command Set General Specification Version 4.1
209
209
  # Table 7.1
210
210
  CONTROL = 0x00
@@ -240,7 +240,7 @@ class CommandFrame(Frame):
240
240
 
241
241
  # -----------------------------------------------------------------------------
242
242
  class ResponseFrame(Frame):
243
- class ResponseCode(OpenIntEnum):
243
+ class ResponseCode(utils.OpenIntEnum):
244
244
  # AV/C Digital Interface Command Set General Specification Version 4.1
245
245
  # Table 7.2
246
246
  NOT_IMPLEMENTED = 0x08
@@ -368,7 +368,7 @@ class PassThroughFrame:
368
368
  PRESSED = 0
369
369
  RELEASED = 1
370
370
 
371
- class OperationId(OpenIntEnum):
371
+ class OperationId(utils.OpenIntEnum):
372
372
  SELECT = 0x00
373
373
  UP = 0x01
374
374
  DOWN = 0x01
bumble/avdtp.py CHANGED
@@ -37,16 +37,15 @@ from typing import (
37
37
  cast,
38
38
  )
39
39
 
40
- from pyee import EventEmitter
41
40
 
42
- from .core import (
41
+ from bumble.core import (
43
42
  BT_ADVANCED_AUDIO_DISTRIBUTION_SERVICE,
44
43
  InvalidStateError,
45
44
  ProtocolError,
46
45
  InvalidArgumentError,
47
46
  name_or_number,
48
47
  )
49
- from .a2dp import (
48
+ from bumble.a2dp import (
50
49
  A2DP_CODEC_TYPE_NAMES,
51
50
  A2DP_MPEG_2_4_AAC_CODEC_TYPE,
52
51
  A2DP_NON_A2DP_CODEC_TYPE,
@@ -56,9 +55,9 @@ from .a2dp import (
56
55
  SbcMediaCodecInformation,
57
56
  VendorSpecificMediaCodecInformation,
58
57
  )
59
- from .rtp import MediaPacket
60
- from . import sdp, device, l2cap
61
- from .colors import color
58
+ from bumble.rtp import MediaPacket
59
+ from bumble import sdp, device, l2cap, utils
60
+ from bumble.colors import color
62
61
 
63
62
 
64
63
  # -----------------------------------------------------------------------------
@@ -1194,7 +1193,7 @@ class DelayReport_Reject(Simple_Reject):
1194
1193
 
1195
1194
 
1196
1195
  # -----------------------------------------------------------------------------
1197
- class Protocol(EventEmitter):
1196
+ class Protocol(utils.EventEmitter):
1198
1197
  local_endpoints: List[LocalStreamEndPoint]
1199
1198
  remote_endpoints: Dict[int, DiscoveredStreamEndPoint]
1200
1199
  streams: Dict[int, Stream]
@@ -1680,7 +1679,7 @@ class Protocol(EventEmitter):
1680
1679
 
1681
1680
 
1682
1681
  # -----------------------------------------------------------------------------
1683
- class Listener(EventEmitter):
1682
+ class Listener(utils.EventEmitter):
1684
1683
  servers: Dict[int, Protocol]
1685
1684
 
1686
1685
  @staticmethod
@@ -2063,7 +2062,7 @@ class DiscoveredStreamEndPoint(StreamEndPoint, StreamEndPointProxy):
2063
2062
 
2064
2063
 
2065
2064
  # -----------------------------------------------------------------------------
2066
- class LocalStreamEndPoint(StreamEndPoint, EventEmitter):
2065
+ class LocalStreamEndPoint(StreamEndPoint, utils.EventEmitter):
2067
2066
  stream: Optional[Stream]
2068
2067
 
2069
2068
  def __init__(
@@ -2076,7 +2075,7 @@ class LocalStreamEndPoint(StreamEndPoint, EventEmitter):
2076
2075
  configuration: Optional[Iterable[ServiceCapabilities]] = None,
2077
2076
  ):
2078
2077
  StreamEndPoint.__init__(self, seid, media_type, tsep, 0, capabilities)
2079
- EventEmitter.__init__(self)
2078
+ utils.EventEmitter.__init__(self)
2080
2079
  self.protocol = protocol
2081
2080
  self.configuration = configuration if configuration is not None else []
2082
2081
  self.stream = None
bumble/avrcp.py CHANGED
@@ -38,7 +38,6 @@ from typing import (
38
38
  Union,
39
39
  )
40
40
 
41
- import pyee
42
41
 
43
42
  from bumble.colors import color
44
43
  from bumble.device import Device, Connection
@@ -53,7 +52,7 @@ from bumble.sdp import (
53
52
  DataElement,
54
53
  ServiceAttribute,
55
54
  )
56
- from bumble.utils import AsyncRunner, OpenIntEnum
55
+ from bumble import utils
57
56
  from bumble.core import (
58
57
  InvalidArgumentError,
59
58
  ProtocolError,
@@ -307,7 +306,7 @@ class Command:
307
306
 
308
307
  # -----------------------------------------------------------------------------
309
308
  class GetCapabilitiesCommand(Command):
310
- class CapabilityId(OpenIntEnum):
309
+ class CapabilityId(utils.OpenIntEnum):
311
310
  COMPANY_ID = 0x02
312
311
  EVENTS_SUPPORTED = 0x03
313
312
 
@@ -637,7 +636,7 @@ class RegisterNotificationResponse(Response):
637
636
 
638
637
 
639
638
  # -----------------------------------------------------------------------------
640
- class EventId(OpenIntEnum):
639
+ class EventId(utils.OpenIntEnum):
641
640
  PLAYBACK_STATUS_CHANGED = 0x01
642
641
  TRACK_CHANGED = 0x02
643
642
  TRACK_REACHED_END = 0x03
@@ -657,12 +656,12 @@ class EventId(OpenIntEnum):
657
656
 
658
657
 
659
658
  # -----------------------------------------------------------------------------
660
- class CharacterSetId(OpenIntEnum):
659
+ class CharacterSetId(utils.OpenIntEnum):
661
660
  UTF_8 = 0x06
662
661
 
663
662
 
664
663
  # -----------------------------------------------------------------------------
665
- class MediaAttributeId(OpenIntEnum):
664
+ class MediaAttributeId(utils.OpenIntEnum):
666
665
  TITLE = 0x01
667
666
  ARTIST_NAME = 0x02
668
667
  ALBUM_NAME = 0x03
@@ -682,7 +681,7 @@ class MediaAttribute:
682
681
 
683
682
 
684
683
  # -----------------------------------------------------------------------------
685
- class PlayStatus(OpenIntEnum):
684
+ class PlayStatus(utils.OpenIntEnum):
686
685
  STOPPED = 0x00
687
686
  PLAYING = 0x01
688
687
  PAUSED = 0x02
@@ -701,33 +700,33 @@ class SongAndPlayStatus:
701
700
 
702
701
  # -----------------------------------------------------------------------------
703
702
  class ApplicationSetting:
704
- class AttributeId(OpenIntEnum):
703
+ class AttributeId(utils.OpenIntEnum):
705
704
  EQUALIZER_ON_OFF = 0x01
706
705
  REPEAT_MODE = 0x02
707
706
  SHUFFLE_ON_OFF = 0x03
708
707
  SCAN_ON_OFF = 0x04
709
708
 
710
- class EqualizerOnOffStatus(OpenIntEnum):
709
+ class EqualizerOnOffStatus(utils.OpenIntEnum):
711
710
  OFF = 0x01
712
711
  ON = 0x02
713
712
 
714
- class RepeatModeStatus(OpenIntEnum):
713
+ class RepeatModeStatus(utils.OpenIntEnum):
715
714
  OFF = 0x01
716
715
  SINGLE_TRACK_REPEAT = 0x02
717
716
  ALL_TRACK_REPEAT = 0x03
718
717
  GROUP_REPEAT = 0x04
719
718
 
720
- class ShuffleOnOffStatus(OpenIntEnum):
719
+ class ShuffleOnOffStatus(utils.OpenIntEnum):
721
720
  OFF = 0x01
722
721
  ALL_TRACKS_SHUFFLE = 0x02
723
722
  GROUP_SHUFFLE = 0x03
724
723
 
725
- class ScanOnOffStatus(OpenIntEnum):
724
+ class ScanOnOffStatus(utils.OpenIntEnum):
726
725
  OFF = 0x01
727
726
  ALL_TRACKS_SCAN = 0x02
728
727
  GROUP_SCAN = 0x03
729
728
 
730
- class GenericValue(OpenIntEnum):
729
+ class GenericValue(utils.OpenIntEnum):
731
730
  pass
732
731
 
733
732
 
@@ -816,7 +815,7 @@ class PlayerApplicationSettingChangedEvent(Event):
816
815
  @dataclass
817
816
  class Setting:
818
817
  attribute_id: ApplicationSetting.AttributeId
819
- value_id: OpenIntEnum
818
+ value_id: utils.OpenIntEnum
820
819
 
821
820
  player_application_settings: List[Setting]
822
821
 
@@ -824,7 +823,7 @@ class PlayerApplicationSettingChangedEvent(Event):
824
823
  def from_bytes(cls, pdu: bytes) -> PlayerApplicationSettingChangedEvent:
825
824
  def setting(attribute_id_int: int, value_id_int: int):
826
825
  attribute_id = ApplicationSetting.AttributeId(attribute_id_int)
827
- value_id: OpenIntEnum
826
+ value_id: utils.OpenIntEnum
828
827
  if attribute_id == ApplicationSetting.AttributeId.EQUALIZER_ON_OFF:
829
828
  value_id = ApplicationSetting.EqualizerOnOffStatus(value_id_int)
830
829
  elif attribute_id == ApplicationSetting.AttributeId.REPEAT_MODE:
@@ -994,7 +993,7 @@ class Delegate:
994
993
 
995
994
 
996
995
  # -----------------------------------------------------------------------------
997
- class Protocol(pyee.EventEmitter):
996
+ class Protocol(utils.EventEmitter):
998
997
  """AVRCP Controller and Target protocol."""
999
998
 
1000
999
  class PacketType(enum.IntEnum):
@@ -1003,7 +1002,7 @@ class Protocol(pyee.EventEmitter):
1003
1002
  CONTINUE = 0b10
1004
1003
  END = 0b11
1005
1004
 
1006
- class PduId(OpenIntEnum):
1005
+ class PduId(utils.OpenIntEnum):
1007
1006
  GET_CAPABILITIES = 0x10
1008
1007
  LIST_PLAYER_APPLICATION_SETTING_ATTRIBUTES = 0x11
1009
1008
  LIST_PLAYER_APPLICATION_SETTING_VALUES = 0x12
@@ -1024,7 +1023,7 @@ class Protocol(pyee.EventEmitter):
1024
1023
  GET_FOLDER_ITEMS = 0x71
1025
1024
  GET_TOTAL_NUMBER_OF_ITEMS = 0x75
1026
1025
 
1027
- class StatusCode(OpenIntEnum):
1026
+ class StatusCode(utils.OpenIntEnum):
1028
1027
  INVALID_COMMAND = 0x00
1029
1028
  INVALID_PARAMETER = 0x01
1030
1029
  PARAMETER_CONTENT_ERROR = 0x02
@@ -1466,7 +1465,7 @@ class Protocol(pyee.EventEmitter):
1466
1465
  if self.avctp_protocol is not None:
1467
1466
  # TODO: find a better strategy instead of just closing
1468
1467
  logger.warning("AVCTP protocol already active, closing connection")
1469
- AsyncRunner.spawn(l2cap_channel.disconnect())
1468
+ utils.AsyncRunner.spawn(l2cap_channel.disconnect())
1470
1469
  return
1471
1470
 
1472
1471
  self.avctp_protocol = avctp.Protocol(l2cap_channel)
bumble/bridge.py CHANGED
@@ -17,8 +17,8 @@
17
17
  # -----------------------------------------------------------------------------
18
18
  import logging
19
19
 
20
- from .hci import HCI_Packet
21
- from .helpers import PacketTracer
20
+ from bumble.hci import HCI_Packet
21
+ from bumble.helpers import PacketTracer
22
22
 
23
23
  # -----------------------------------------------------------------------------
24
24
  # Logging