diff --git a/config/alarms.sample.json b/config/alarms.sample.json index 35a890f..6fee120 100644 --- a/config/alarms.sample.json +++ b/config/alarms.sample.json @@ -9,5 +9,10 @@ "alarm_time": "2330", "alarm_audio": "assets/alarm/sleep.wav", "alarm_image": "assets/img/sleep.png" + }, + { + "alarm_time": "0800", + "alarm_days": ["Sat", "Sun"], + "alarm_image": "assets/img/on_alarm.png" } ] diff --git a/contents_server.py b/contents_server.py index 554d144..d89e8ac 100644 --- a/contents_server.py +++ b/contents_server.py @@ -48,12 +48,22 @@ def _resolve_path(relative: str) -> Path: return p -def _prepare_alarm(entry: dict) -> dict: +def _prepare_alarm(entry: dict, audio_cache: dict[Path, tuple]) -> dict: """Pre-resolve paths and load resources for a single alarm entry.""" - audio_path = find_wav(_resolve_path(entry.get("alarm_audio", "assets/alarm/alarm_test.wav"))) alarm_img_path = _resolve_path(entry.get("alarm_image", "assets/img/on_alarm.png")) - pcm, sr, ch, bits = read_wav(audio_path) img = load_status_image(alarm_img_path) + + pcm = sr = ch = bits = None + raw_audio = entry.get("alarm_audio") + if raw_audio is not None: + audio_path = find_wav(_resolve_path(raw_audio)) + if audio_path in audio_cache: + log.info("Reusing cached audio for %s", audio_path) + pcm, sr, ch, bits = audio_cache[audio_path] + else: + pcm, sr, ch, bits = read_wav(audio_path) + audio_cache[audio_path] = (pcm, sr, ch, bits) + return { "config": entry, "pcm": pcm, "sr": sr, "ch": ch, "bits": bits, @@ -71,7 +81,8 @@ async def handler(ws): img_idle = load_status_image(IMG_DIR / "idle.png") current_img = img_idle - alarms = [_prepare_alarm(entry) for entry in configs] if configs else [] + audio_cache: dict[Path, tuple] = {} + alarms = [_prepare_alarm(entry, audio_cache) for entry in configs] if configs else [] async def alarm_ticker(): nonlocal current_img @@ -91,10 +102,14 @@ async def handler(ws): alarm["config"]["alarm_time"], current_minute) current_img = alarm["img"] await send_status_image(ws, current_img) - await stream_alarm(ws, alarm["pcm"], alarm["sr"], - alarm["ch"], alarm["bits"]) - # let the image persist a bit more - await asyncio.sleep(1) + if alarm["pcm"] is not None: + await stream_alarm(ws, alarm["pcm"], alarm["sr"], + alarm["ch"], alarm["bits"]) + # let the image persist a bit more + await asyncio.sleep(1) + else: + # longer image persistence when no audio + await asyncio.sleep(10) current_img = img_idle await send_status_image(ws, current_img)