robathome icon

MC_jukebox - Speaker node

robathome | PRO | 10/27/25 06:13:30 PM UTC | 0 ⭐ | 558 👁️ | Never ⏰ | []
text |

1.49 KB

|

None

|

0 👍

/

0 👎

-- 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