fix demo autostart

This commit is contained in:
2025-11-19 09:34:56 +01:00
parent 1b744d52d8
commit 690d31559b

View File

@@ -263,6 +263,7 @@ async def init_radio(transport: str, conf: auracast_config.AuracastConfigGroup,
'demo_total_streams': demo_count,
'demo_stream_type': demo_type,
'is_streaming': auto_started,
'demo_sources': [str(b.audio_source) for b in conf.bigs if isinstance(b.audio_source, str) and b.audio_source.startswith('file:')],
}
return mc, persisted
except HTTPException:
@@ -332,6 +333,8 @@ async def _autostart_from_settings():
settings1 = load_stream_settings() or {}
settings2 = load_stream_settings2() or {}
log.info("[AUTOSTART] Starting autostart check: primary_ts=%s secondary_ts=%s", settings1.get('timestamp'), settings2.get('timestamp'))
async def do_primary():
global multicaster1, global_config_group
settings = settings1
@@ -350,14 +353,96 @@ async def _autostart_from_settings():
original_ts = settings.get('timestamp')
previously_streaming = bool(settings.get('is_streaming'))
if not previously_streaming or not input_device_name or rate is None or octets is None:
log.info(
"[AUTOSTART][PRIMARY] loaded settings: previously_streaming=%s audio_mode=%s rate=%s octets=%s pres_delay=%s rtn=%s immediate_rendering=%s assisted_listening_stream=%s demo_sources=%s",
previously_streaming,
audio_mode,
rate,
octets,
pres_delay,
saved_rtn,
immediate_rendering,
assisted_listening_stream,
(settings.get('demo_sources') or []),
)
if not previously_streaming:
log.info("[AUTOSTART][PRIMARY] Skipping autostart: is_streaming flag was False in persisted settings")
return
if audio_mode == 'Demo':
demo_sources = settings.get('demo_sources') or []
if not demo_sources or rate is None or octets is None:
log.warning(
"[AUTOSTART][PRIMARY] Demo autostart aborted: demo_sources_present=%s rate=%s octets=%s",
bool(demo_sources),
rate,
octets,
)
return
bigs = []
for i, src in enumerate(demo_sources):
name = channel_names[i] if i < len(channel_names) else f"Broadcast{i}"
pinfo = program_info[i] if isinstance(program_info, list) and i < len(program_info) else (program_info[0] if isinstance(program_info, list) and program_info else program_info)
lang = languages[i] if i < len(languages) else (languages[0] if languages else "deu")
bigs.append(
auracast_config.AuracastBigConfig(
code=stream_password,
name=name,
program_info=pinfo,
language=lang,
audio_source=src,
iso_que_len=1,
sampling_frequency=rate,
octets_per_frame=octets,
)
)
log.info(
"[AUTOSTART][PRIMARY] Building demo config for %d streams, rate=%s, octets=%s",
len(bigs),
rate,
octets,
)
conf = auracast_config.AuracastConfigGroup(
auracast_sampling_rate_hz=rate,
octets_per_frame=octets,
transport=TRANSPORT1,
immediate_rendering=immediate_rendering,
assisted_listening_stream=assisted_listening_stream,
presentation_delay_us=pres_delay if pres_delay is not None else 40000,
bigs=bigs,
)
conf.qos_config = auracast_config.AuracastQoSConfig(
iso_int_multiple_10ms=1,
number_of_retransmissions=int(saved_rtn) if saved_rtn is not None else 1,
max_transport_latency_ms=(int(saved_rtn) * 10 + 3) if saved_rtn is not None else 13,
)
log.info("[AUTOSTART][PRIMARY] Scheduling demo init_radio in 2s")
await asyncio.sleep(2)
async with _stream_lock:
log.info("[AUTOSTART][PRIMARY] Calling init_radio for demo autostart")
mc, persisted = await init_radio(TRANSPORT1, conf, multicaster1)
multicaster1 = mc
global_config_group = conf
save_settings(persisted, secondary=False)
log.info("[AUTOSTART][PRIMARY] Demo autostart completed; settings persisted with is_streaming=%s", persisted.get('is_streaming'))
return
if not input_device_name or rate is None or octets is None:
log.info(
"[AUTOSTART][PRIMARY] Skipping device-based autostart: input_device=%s rate=%s octets=%s",
input_device_name,
rate,
octets,
)
return
current = await _status_primary()
if current.get('is_streaming'):
log.info("[AUTOSTART][PRIMARY] Skipping device-based autostart: stream already running")
return
while True:
current = await _status_primary()
if current.get('is_streaming'):
log.info("[AUTOSTART][PRIMARY] Aborting wait loop: stream started externally")
return
current_settings = load_stream_settings() or {}
if current_settings.get('timestamp') != original_ts:
@@ -365,11 +450,13 @@ async def _autostart_from_settings():
current_settings.get('input_device') != input_device_name or
current_settings.get('audio_mode') != audio_mode
):
log.info("[AUTOSTART][PRIMARY] Aborting wait loop: settings changed (audio_mode/input_device)")
return
usb = [d for _, d in get_alsa_usb_inputs()]
net = [d for _, d in get_network_pw_inputs()]
names = {d.get('name') for d in usb} | {d.get('name') for d in net}
if input_device_name in names:
log.info("[AUTOSTART][PRIMARY] Device '%s' detected, starting autostart", input_device_name)
bigs = [
auracast_config.AuracastBigConfig(
code=stream_password,
@@ -396,12 +483,15 @@ async def _autostart_from_settings():
number_of_retransmissions=int(saved_rtn),
max_transport_latency_ms=int(saved_rtn) * 10 + 3,
)
log.info("[AUTOSTART][PRIMARY] Scheduling device init_radio in 2s")
await asyncio.sleep(2)
async with _stream_lock:
log.info("[AUTOSTART][PRIMARY] Calling init_radio for device autostart")
mc, persisted = await init_radio(TRANSPORT1, conf, multicaster1)
multicaster1 = mc
global_config_group = conf
save_settings(persisted, secondary=False)
log.info("[AUTOSTART][PRIMARY] Device autostart completed; settings persisted with is_streaming=%s", persisted.get('is_streaming'))
return
await asyncio.sleep(2)
@@ -422,12 +512,83 @@ async def _autostart_from_settings():
stream_password = settings.get('stream_password')
original_ts = settings.get('timestamp')
previously_streaming = bool(settings.get('is_streaming'))
if not previously_streaming or not input_device_name or rate is None or octets is None:
log.info(
"[AUTOSTART][SECONDARY] loaded settings: previously_streaming=%s audio_mode=%s rate=%s octets=%s pres_delay=%s rtn=%s immediate_rendering=%s assisted_listening_stream=%s demo_sources=%s",
previously_streaming,
audio_mode,
rate,
octets,
pres_delay,
saved_rtn,
immediate_rendering,
assisted_listening_stream,
(settings.get('demo_sources') or []),
)
if not previously_streaming:
log.info("[AUTOSTART][SECONDARY] Skipping autostart: is_streaming flag was False in persisted settings")
return
if audio_mode == 'Demo':
demo_sources = settings.get('demo_sources') or []
if not demo_sources or rate is None or octets is None:
log.warning(
"[AUTOSTART][SECONDARY] Demo autostart aborted: demo_sources_present=%s rate=%s octets=%s",
bool(demo_sources),
rate,
octets,
)
return
bigs = []
for i, src in enumerate(demo_sources):
name = channel_names[i] if i < len(channel_names) else f"Broadcast{i}"
pinfo = program_info[i] if isinstance(program_info, list) and i < len(program_info) else (program_info[0] if isinstance(program_info, list) and program_info else program_info)
lang = languages[i] if i < len(languages) else (languages[0] if languages else "deu")
bigs.append(
auracast_config.AuracastBigConfig(
code=stream_password,
name=name,
program_info=pinfo,
language=lang,
audio_source=src,
iso_que_len=1,
sampling_frequency=rate,
octets_per_frame=octets,
)
)
conf = auracast_config.AuracastConfigGroup(
auracast_sampling_rate_hz=rate,
octets_per_frame=octets,
transport=TRANSPORT2,
immediate_rendering=immediate_rendering,
assisted_listening_stream=assisted_listening_stream,
presentation_delay_us=pres_delay if pres_delay is not None else 40000,
bigs=bigs,
)
conf.qos_config = auracast_config.AuracastQoSConfig(
iso_int_multiple_10ms=1,
number_of_retransmissions=int(saved_rtn) if saved_rtn is not None else 1,
max_transport_latency_ms=(int(saved_rtn) * 10 + 3) if saved_rtn is not None else 13,
)
log.info("[AUTOSTART][SECONDARY] Scheduling demo init_radio in 2s")
await asyncio.sleep(2)
async with _stream_lock:
log.info("[AUTOSTART][SECONDARY] Calling init_radio for demo autostart")
mc, persisted = await init_radio(TRANSPORT2, conf, multicaster2)
multicaster2 = mc
save_settings(persisted, secondary=True)
log.info("[AUTOSTART][SECONDARY] Demo autostart completed; settings persisted with is_streaming=%s", persisted.get('is_streaming'))
return
if not input_device_name or rate is None or octets is None:
log.info(
"[AUTOSTART][SECONDARY] Skipping device-based autostart: input_device=%s rate=%s octets=%s",
input_device_name,
rate,
octets,
)
return
if multicaster2 is not None:
try:
if multicaster2.get_status().get('is_streaming'):
log.info("[AUTOSTART][SECONDARY] Skipping device-based autostart: stream already running")
return
except Exception:
pass
@@ -435,6 +596,7 @@ async def _autostart_from_settings():
if multicaster2 is not None:
try:
if multicaster2.get_status().get('is_streaming'):
log.info("[AUTOSTART][SECONDARY] Aborting wait loop: stream started externally")
return
except Exception:
pass
@@ -475,11 +637,14 @@ async def _autostart_from_settings():
number_of_retransmissions=int(saved_rtn),
max_transport_latency_ms=int(saved_rtn) * 10 + 3,
)
log.info("[AUTOSTART][SECONDARY] Scheduling device init_radio in 2s")
await asyncio.sleep(2)
async with _stream_lock:
log.info("[AUTOSTART][SECONDARY] Calling init_radio for device autostart")
mc, persisted = await init_radio(TRANSPORT2, conf, multicaster2)
multicaster2 = mc
save_settings(persisted, secondary=True)
log.info("[AUTOSTART][SECONDARY] Device autostart completed; settings persisted with is_streaming=%s", persisted.get('is_streaming'))
return
await asyncio.sleep(2)
@@ -489,11 +654,12 @@ async def _autostart_from_settings():
@app.on_event("startup")
async def _startup_autostart_event():
# Spawn the autostart task without blocking startup
log.info("Refreshing PipeWire device cache.")
log.info("[STARTUP] Auracast multicast server startup: initializing settings cache, I2C, and PipeWire cache")
# Hydrate settings cache once to avoid disk I/O during /status
_init_settings_cache_from_disk()
await _init_i2c_on_startup()
refresh_pw_cache()
log.info("[STARTUP] Scheduling autostart task")
asyncio.create_task(_autostart_from_settings())
@app.get("/audio_inputs_pw_usb")