Bind dedicated Bluetooth PCM directly instead of late-overridden ALSA defaults

This commit is contained in:
firestar5683
2026-09-19 17:15:14 -07:00
parent b04995247d
commit 249eb88b3a
2 changed files with 12 additions and 7 deletions
+7 -4
View File
@@ -6,6 +6,8 @@ import re
import subprocess
import sys
PCM_NAME = 'roadscore_bluetooth'
ADDRESS = re.compile(r'^(?:[0-9A-F]{2}:){5}[0-9A-F]{2}$')
@@ -43,14 +45,15 @@ def prepare_output(directory, *, env=None, reader=real_selection,
raise ValueError('A valid system ALSA configuration file is required')
path=Path(directory).resolve()/'roadscore-bluealsa.conf'
path.parent.mkdir(parents=True, exist_ok=True)
config=f'<{base}>\n\ndefaults.bluealsa.!device "{address}"\ndefaults.bluealsa.!profile "a2dp"\n'
config=(f'<{base}>\n\npcm.{PCM_NAME} {{\n type bluealsa\n device "{address}"\n'
' profile "a2dp"\n hint { show on description "RoadScore selected Bluetooth speaker" }\n}\n')
# Exclusive creation protects existing configuration and keeps the change process-local.
with path.open('x') as handle:
os.chmod(path, 0o600)
handle.write(config)
env['ALSA_CONFIG_PATH']=str(path)
return {'bluetooth_selected':True, 'address':address, 'output_identity':f'bluealsa:{address}',
'profile':'a2dp', 'sample_rate':48000, 'channels':2, 'alsa_config':str(path),
'profile':'a2dp', 'pcm_name':PCM_NAME, 'sample_rate':48000, 'channels':2, 'alsa_config':str(path),
'timing_source':'PortAudio host/backend estimate; not measured acoustic Bluetooth latency',
'physical_latency_ms':None}
@@ -59,8 +62,8 @@ def select_device(devices, metadata):
if not metadata.get('bluetooth_selected'):
return None
matches=[index for index, device in enumerate(devices)
if str(device.get('name', '')).strip().lower()=='bluealsa'
if str(device.get('name', '')).strip().lower()==metadata.get('pcm_name', PCM_NAME)
and device.get('max_output_channels', 0)>=2]
if len(matches)!=1:
raise RuntimeError('Selected Bluetooth speaker requires one stereo BlueALSA output; no speaker fallback')
raise RuntimeError('Selected Bluetooth speaker requires one selected RoadScore Bluetooth PCM; no speaker fallback')
return matches[0]
+5 -3
View File
@@ -13,13 +13,15 @@ class BluetoothOutputTests(unittest.TestCase):
meta=prepare_output(Path(d)/'run',env=env,reader=lambda _:dict(enabled=True,address='aa:bb:cc:dd:ee:ff'),alsa_base=base,loaded_modules={})
text=Path(env['ALSA_CONFIG_PATH']).read_text()
self.assertIn(f'<{base}>',text)
self.assertIn('defaults.bluealsa.!device "AA:BB:CC:DD:EE:FF"',text)
self.assertIn('pcm.roadscore_bluetooth {',text)
self.assertIn('device "AA:BB:CC:DD:EE:FF"',text)
self.assertNotIn('defaults.bluealsa',text)
self.assertEqual(base.read_text(),'system config')
self.assertEqual(env['OPENPILOT_PREFIX'],'replay')
self.assertIsNone(meta['physical_latency_ms'])
self.assertEqual(select_device([{'name':'default','max_output_channels':2},{'name':'bluealsa','max_output_channels':128}],meta),1)
self.assertEqual(select_device([{'name':'default','max_output_channels':2},{'name':'roadscore_bluetooth','max_output_channels':128}],meta),1)
def test_missing_or_ambiguous_bluetooth_does_not_fallback(self):
for devices in [[],[{'name':'default','max_output_channels':2}], [{'name':'bluealsa','max_output_channels':1}], [{'name':'bluealsa','max_output_channels':2}]*2]:
for devices in [[],[{'name':'default','max_output_channels':2}], [{'name':'bluealsa','max_output_channels':128}], [{'name':'roadscore_bluetooth','max_output_channels':1}], [{'name':'roadscore_bluetooth','max_output_channels':2}]*2]:
with self.assertRaises(RuntimeError):select_device(devices,{'bluetooth_selected':True})
def test_disabled_does_not_touch_configuration(self):
env={};self.assertEqual(prepare_output('/unused',env=env,reader=lambda _:dict(enabled=False)),{'bluetooth_selected':False});self.assertEqual(env,{})