diff --git a/station_broadcast-warning.lua b/station_broadcast-warning.lua index de4f881..8944108 100644 --- a/station_broadcast-warning.lua +++ b/station_broadcast-warning.lua @@ -61,6 +61,7 @@ local function playDfpwmFile(path, volume) for _, sp in ipairs(speakers) do pending[peripheral.getName(sp)] = sp end + local maxAttempts = 20 while next(pending) do for name, sp in pairs(pending) do if sp.playAudio(samples, volume) then @@ -68,6 +69,10 @@ local function playDfpwmFile(path, volume) end end if next(pending) then + maxAttempts = maxAttempts - 1 + if maxAttempts <= 0 then + break + end local timerId = os.startTimer(0.05) while true do local ev = { os.pullEvent() } diff --git a/station_broadcast.lua b/station_broadcast.lua index 968ba68..372e1c6 100644 --- a/station_broadcast.lua +++ b/station_broadcast.lua @@ -1,6 +1,6 @@ -- 1. Configuration & Constants -local APP_VERSION_TEXT = "v1.0.66" +local APP_VERSION_TEXT = "v1.0.67" local CONFIG = { CLOUD_URL = "ws://stabadmin.fse-media.group", @@ -1216,12 +1216,17 @@ local function waitForNativeSpeakersEmpty(speakers, playSeq) if name then waiting[name] = true end end + local timerId = os.startTimer(2.0) -- Maximum 2 seconds wait for empty while next(waiting) do if shouldStop(playSeq) then return false end local ev = { os.pullEvent() } if ev[1] == "audio_interrupt" and tonumber(ev[2]) and tonumber(ev[2]) >= playSeq then return false end + if ev[1] == "timer" and ev[2] == timerId then + Utils.log("WARN", "Timeout waiting for native speakers to empty") + break + end if ev[1] == "speaker_audio_empty" and ev[2] and waiting[ev[2]] then waiting[ev[2]] = nil end @@ -1284,6 +1289,7 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain) end local usedNativePath = false + local maxAttempts = 20 while next(pending) do if shouldStop(playSeq) then return false end for name, sp in pairs(pending) do @@ -1299,6 +1305,11 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain) end end if next(pending) then + maxAttempts = maxAttempts - 1 + if maxAttempts <= 0 then + Utils.log("WARN", "Speaker buffer full or failed, skipping chunk") + break + end local timerId = os.startTimer(0.05) while true do local ev = { os.pullEvent() } @@ -1319,6 +1330,7 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain) local controller = Peripherals.speakers[1] if controller and type(controller.playAudioAll) == "function" then Utils.log("WARN", "Falling back to controller.playAudioAll for decoded samples") + local maxAttempts = 20 while true do if shouldStop(playSeq) then return false end local ok = false @@ -1326,6 +1338,11 @@ local function playChunkOnSpeakers(samples, volume, playSeq, waitForDrain) ok = controller.playAudioAll(samples, volume) end) if ok then break end + maxAttempts = maxAttempts - 1 + if maxAttempts <= 0 then + Utils.log("WARN", "Controller buffer full or failed, skipping chunk") + break + end local timerId = os.startTimer(0.05) while true do local ev = { os.pullEvent() } @@ -1765,7 +1782,7 @@ function Audio.playDfpwmItem(item) if chunk == nil then break end if type(chunk) == "string" and #chunk > 0 then local samples = decoder(chunk) - if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq) then + if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq, false) then break end end @@ -1826,7 +1843,7 @@ function Audio.playPcmItem(item) if chunk == nil then break end if type(chunk) == "string" and #chunk > 0 then local samples = decodePcmS8Chunk(chunk) - if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq) then + if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq, false) then Audio.stop("current") break end @@ -1888,7 +1905,7 @@ function Audio.playPcmS16LEItem(item) if chunk == nil then break end if type(chunk) == "string" and #chunk > 0 then local samples = decodePcmS16LEChunk(chunk) - if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq) then + if samples and not playChunkOnSpeakers(samples, CONFIG.AUDIO_VOLUME, playSeq, false) then Audio.stop("current") break end