From 2ed169757154ccbb43035b7ed0f3ffcf2a0e8ef2 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Tue, 7 Jul 2026 19:14:41 +0200 Subject: [PATCH] alarm --- modules/advisor.py | 2 +- modules/web/index.html | 2 +- modules/web/web.js | 47 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/modules/advisor.py b/modules/advisor.py index 58137a0..229c1ca 100644 --- a/modules/advisor.py +++ b/modules/advisor.py @@ -1,7 +1,7 @@ MORNING_START = 5 MORNING_END = 10 DAY_START = 10 -DAY_END = 19 +DAY_END = 20 LATE_NIGHT_START = 0 LATE_NIGHT_END = 5 diff --git a/modules/web/index.html b/modules/web/index.html index cdba49e..9b7046e 100644 --- a/modules/web/index.html +++ b/modules/web/index.html @@ -210,7 +210,7 @@
-
Queue
+
Queue
    diff --git a/modules/web/web.js b/modules/web/web.js index e676f52..968a984 100644 --- a/modules/web/web.js +++ b/modules/web/web.js @@ -2,6 +2,7 @@ let ws = null; let reconnectDelay = 1000; let playlist = []; let queue = []; +let last_q_len = Infinity; let currentTrackPath = ""; let currentTrackIndex = 0; let selectedPlaylistIndex = null; @@ -16,6 +17,9 @@ let lastElapsed = 0; let lastUpdateTime = 0; let currentRealTotal = 1; let pollLockHeld = false; +let alarmEnabled = false; +let alarmFired = false; +let alarmAudioCtx = null; function toggleSection(id) { const pairMap = { @@ -267,6 +271,16 @@ function renderQueue() { }) ul.appendChild(li); }); + + if (alarmEnabled) { + if (queue.length === 0 && !alarmFired && last_q_len > queue.length) { + playAlarmTone(); + alarmFired = true; + } else if (queue.length !== 1) { + alarmFired = false; + } + } + last_q_len = queue.length; updateControls(); } @@ -346,6 +360,39 @@ function updateControls() { document.getElementById("clear-btn").disabled = queue.length === 0; } +function toggleAlarm() { + alarmEnabled = !alarmEnabled; + document.getElementById("alarm-btn").classList.toggle("activated", alarmEnabled); + if (!alarmEnabled) alarmFired = false; +} + +function playAlarmTone() { + if (!alarmAudioCtx) alarmAudioCtx = new (window.AudioContext || window.webkitAudioContext)(); + const ctx = alarmAudioCtx; + const now = ctx.currentTime; + const beeps = 5; + for (let i = 0; i < beeps; i++) { + const osc = ctx.createOscillator(); + const gain = ctx.createGain(); + osc.type = "square"; + osc.frequency.value = 880; + const t = now + i * 0.45; + gain.gain.setValueAtTime(0, t); + gain.gain.linearRampToValueAtTime(1, t + 0.02); + gain.gain.setValueAtTime(1, t + 0.28); + gain.gain.linearRampToValueAtTime(0, t + 0.32); + osc.connect(gain); + gain.connect(ctx.destination); + osc.start(t); + osc.stop(t + 0.35); + } +} + +document.getElementById("alarm-btn").addEventListener("click", e => { + e.stopPropagation(); + toggleAlarm(); +}); + document.getElementById("skip-btn").addEventListener("click", () => wsSend({ action: "skip" })); document.getElementById("skpn-inc").addEventListener("click", () => wsSend({ action: "skipc", add: 1 })); document.getElementById("skpn-dec").addEventListener("click", () => wsSend({ action: "skipc", remove: -1 }));