-- speaker_node.lua
local MODE = "ui-mirror-v1"
-- open rednet
local side=nil; for _,s in ipairs(rs.getSides()) do if peripheral.getType(s)=="modem" then side=s break end end
assert(side, "wireless modem required"); if not rednet.isOpen(side) then rednet.open(side) end
-- find speakers
local speakers = { peripheral.find("speaker") }
assert(#speakers>0, "attach a speaker to this node")
-- hello as a speaker client
rednet.broadcast({ op="HELLO", role="speaker" }, MODE)
local make_decoder = require("cc.audio.dfpwm").make_decoder
local decoder = make_decoder()
local volume = 1.0
local function playAll(pcm)
local tasks={}
for i,sp in ipairs(speakers) do
tasks[i]=function()
local name = peripheral.getName(sp)
while not sp.playAudio(pcm, volume) do
repeat until select(2, os.pullEvent("speaker_audio_empty")) == name
end
end
end
pcall(parallel.waitForAll, table.unpack(tasks))
end
while true do
local id,msg,proto = rednet.receive(MODE)
if proto==MODE and type(msg)=="table" then
if msg.op=="HELLO_ACK_SPK" then
-- optional: print("linked to server "..id)
elseif msg.op=="AUDIO_BEGIN" then
decoder = make_decoder() -- reset stream state
volume = tonumber(msg.vol) or volume
elseif msg.op=="AUDIO_PART" and type(msg.data)=="string" then
local pcm = decoder(msg.data) -- incremental decode
playAll(pcm)
elseif msg.op=="AUDIO_END" then
-- no-op
end
end
end
Comments