add support for multiple concurrent broadcasts

This commit is contained in:
Gilles Boccon-Gibod
2025-12-05 10:54:23 -05:00
parent b4261548e8
commit 32bb7cdaf3
10 changed files with 868 additions and 512 deletions

View File

@@ -546,5 +546,6 @@ class SoundDeviceAudioInput(ThreadedAudioInput):
return bytes(pcm_buffer)
def _close(self):
self._stream.stop()
self._stream = None
if self._stream:
self._stream.stop()
self._stream = None

View File

@@ -864,8 +864,8 @@ class PeriodicAdvertisingSync(utils.EventEmitter):
EVENT_STATE_CHANGE = "state_change"
EVENT_ESTABLISHMENT = "establishment"
EVENT_ESTABLISHMENT_ERROR = "establishment_error"
EVENT_CANCELLATION = "cancellation"
EVENT_ERROR = "error"
EVENT_LOSS = "loss"
EVENT_PERIODIC_ADVERTISEMENT = "periodic_advertisement"
EVENT_BIGINFO_ADVERTISEMENT = "biginfo_advertisement"
@@ -998,7 +998,7 @@ class PeriodicAdvertisingSync(utils.EventEmitter):
return
self.state = self.State.ERROR
self.emit(self.EVENT_ERROR)
self.emit(self.EVENT_ESTABLISHMENT_ERROR)
def on_loss(self):
self.state = self.State.LOST

View File

@@ -207,22 +207,44 @@ def metadata(
HCI_VENDOR_OGF = 0x3F
# HCI Version
HCI_VERSION_BLUETOOTH_CORE_1_0B = 0
HCI_VERSION_BLUETOOTH_CORE_1_1 = 1
HCI_VERSION_BLUETOOTH_CORE_1_2 = 2
HCI_VERSION_BLUETOOTH_CORE_2_0_EDR = 3
HCI_VERSION_BLUETOOTH_CORE_2_1_EDR = 4
HCI_VERSION_BLUETOOTH_CORE_3_0_HS = 5
HCI_VERSION_BLUETOOTH_CORE_4_0 = 6
HCI_VERSION_BLUETOOTH_CORE_4_1 = 7
HCI_VERSION_BLUETOOTH_CORE_4_2 = 8
HCI_VERSION_BLUETOOTH_CORE_5_0 = 9
HCI_VERSION_BLUETOOTH_CORE_5_1 = 10
HCI_VERSION_BLUETOOTH_CORE_5_2 = 11
HCI_VERSION_BLUETOOTH_CORE_5_3 = 12
HCI_VERSION_BLUETOOTH_CORE_5_4 = 13
HCI_VERSION_BLUETOOTH_CORE_6_0 = 14
# Specification Version
class SpecificationVersion(utils.OpenIntEnum):
BLUETOOTH_CORE_1_0B = 0
BLUETOOTH_CORE_1_1 = 1
BLUETOOTH_CORE_1_2 = 2
BLUETOOTH_CORE_2_0_EDR = 3
BLUETOOTH_CORE_2_1_EDR = 4
BLUETOOTH_CORE_3_0_HS = 5
BLUETOOTH_CORE_4_0 = 6
BLUETOOTH_CORE_4_1 = 7
BLUETOOTH_CORE_4_2 = 8
BLUETOOTH_CORE_5_0 = 9
BLUETOOTH_CORE_5_1 = 10
BLUETOOTH_CORE_5_2 = 11
BLUETOOTH_CORE_5_3 = 12
BLUETOOTH_CORE_5_4 = 13
BLUETOOTH_CORE_6_0 = 14
BLUETOOTH_CORE_6_1 = 15
BLUETOOTH_CORE_6_2 = 16
# For backwards compatibility only
HCI_VERSION_BLUETOOTH_CORE_1_0B = SpecificationVersion.BLUETOOTH_CORE_1_0B
HCI_VERSION_BLUETOOTH_CORE_1_1 = SpecificationVersion.BLUETOOTH_CORE_1_1
HCI_VERSION_BLUETOOTH_CORE_1_2 = SpecificationVersion.BLUETOOTH_CORE_1_2
HCI_VERSION_BLUETOOTH_CORE_2_0_EDR = SpecificationVersion.BLUETOOTH_CORE_2_0_EDR
HCI_VERSION_BLUETOOTH_CORE_2_1_EDR = SpecificationVersion.BLUETOOTH_CORE_2_1_EDR
HCI_VERSION_BLUETOOTH_CORE_3_0_HS = SpecificationVersion.BLUETOOTH_CORE_3_0_HS
HCI_VERSION_BLUETOOTH_CORE_4_0 = SpecificationVersion.BLUETOOTH_CORE_4_0
HCI_VERSION_BLUETOOTH_CORE_4_1 = SpecificationVersion.BLUETOOTH_CORE_4_1
HCI_VERSION_BLUETOOTH_CORE_4_2 = SpecificationVersion.BLUETOOTH_CORE_4_2
HCI_VERSION_BLUETOOTH_CORE_5_0 = SpecificationVersion.BLUETOOTH_CORE_5_0
HCI_VERSION_BLUETOOTH_CORE_5_1 = SpecificationVersion.BLUETOOTH_CORE_5_1
HCI_VERSION_BLUETOOTH_CORE_5_2 = SpecificationVersion.BLUETOOTH_CORE_5_2
HCI_VERSION_BLUETOOTH_CORE_5_3 = SpecificationVersion.BLUETOOTH_CORE_5_3
HCI_VERSION_BLUETOOTH_CORE_5_4 = SpecificationVersion.BLUETOOTH_CORE_5_4
HCI_VERSION_BLUETOOTH_CORE_6_0 = SpecificationVersion.BLUETOOTH_CORE_6_0
HCI_VERSION_BLUETOOTH_CORE_6_1 = SpecificationVersion.BLUETOOTH_CORE_6_1
HCI_VERSION_BLUETOOTH_CORE_6_2 = SpecificationVersion.BLUETOOTH_CORE_6_2
HCI_VERSION_NAMES = {
HCI_VERSION_BLUETOOTH_CORE_1_0B: 'HCI_VERSION_BLUETOOTH_CORE_1_0B',
@@ -240,9 +262,10 @@ HCI_VERSION_NAMES = {
HCI_VERSION_BLUETOOTH_CORE_5_3: 'HCI_VERSION_BLUETOOTH_CORE_5_3',
HCI_VERSION_BLUETOOTH_CORE_5_4: 'HCI_VERSION_BLUETOOTH_CORE_5_4',
HCI_VERSION_BLUETOOTH_CORE_6_0: 'HCI_VERSION_BLUETOOTH_CORE_6_0',
HCI_VERSION_BLUETOOTH_CORE_6_1: 'HCI_VERSION_BLUETOOTH_CORE_6_1',
HCI_VERSION_BLUETOOTH_CORE_6_2: 'HCI_VERSION_BLUETOOTH_CORE_6_2',
}
# LMP Version
LMP_VERSION_NAMES = HCI_VERSION_NAMES
# HCI Packet types

View File

@@ -338,7 +338,12 @@ class BroadcastAudioScanService(gatt.TemplateService):
b"12", # TEST
)
super().__init__([self.battery_level_characteristic])
super().__init__(
[
self.broadcast_audio_scan_control_point_characteristic,
self.broadcast_receive_state_characteristic,
]
)
def on_broadcast_audio_scan_control_point_write(
self, connection: device.Connection, value: bytes

View File

@@ -22,6 +22,7 @@ import enum
from typing_extensions import Self
from bumble import core, data_types, gatt
from bumble.profiles import le_audio
@@ -46,3 +47,18 @@ class PublicBroadcastAnnouncement:
return cls(
features=features, metadata=le_audio.Metadata.from_bytes(metadata_ltv)
)
def get_advertising_data(self) -> bytes:
return bytes(
core.AdvertisingData(
[
data_types.ServiceData16BitUUID(
gatt.GATT_PUBLIC_BROADCAST_ANNOUNCEMENT_SERVICE, bytes(self)
)
]
)
)
def __bytes__(self) -> bytes:
metadata_bytes = bytes(self.metadata)
return bytes([self.features, len(metadata_bytes)]) + metadata_bytes