Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- API --------------------------------------------------
- local w, h = term.getSize()
- function printCentered(y, str)
- local x = math.floor((w - string.len(str)) / 2)
- term.setCursorPos(x, y)
- term.clearLine()
- term.write(str)
- end
- function printThird(y, third, str)
- local third_width = w / 3
- -- Centre position of the requested third
- local centre_x = (third - 0.5) * third_width
- local x = math.floor(centre_x - (#str / 2))
- term.setCursorPos(x, y)
- term.write(str)
- end
- function hasValue (tab, val)
- for index, value in ipairs(tab) do
- if value == val then
- return true
- end
- end
- return false
- end
- function printKeys(tab)
- -- Source - https://stackoverflow.com/a/12674376
- -- Posted by lhf
- -- Retrieved 2026-06-11, License - CC BY-SA 3.0
- local keyset={}
- local n=0
- for k,v in pairs(tab) do
- n=n+1
- keyset[n]=k
- end
- print(textutils.serialise(keyset))
- end
- ---------------------------------------------------------
- JUKEBOX_ID = 1
- local dfpwm = require("cc.audio.dfpwm")
- local speaker
- local decoder
- local connected_jukebox_frontend
- local protocol
- local skip_requested = false
- local songs = {}
- local state = {
- current_song = nil,
- queue = {}
- }
- function playSoundFromUrl(url)
- local response, err = http.get(url)
- if not response then
- print("Failed to fetch audio:")
- print(err)
- return
- end
- while true do
- if skip_requested then
- skip_requested = false
- response.close()
- return
- end
- local chunk = response.read(16 * 1024)
- if not chunk then
- break
- end
- local buffer = decoder(chunk)
- while not speaker.playAudio(buffer) do
- os.pullEvent("speaker_audio_empty")
- if skip_requested then
- skip_requested = false
- response.close()
- return
- end
- end
- end
- response.close()
- end
- function playSong(song_id)
- local song = songs[song_id]
- if not song then
- print("Unknown song: " .. tostring(song_id))
- return
- end
- local url =
- "https://raw.githubusercontent.com/dabusmc/jukebox_data/refs/heads/main/sounds/"
- .. song["file_name"]
- print("Streaming: " .. song["display_name"])
- playSoundFromUrl(url)
- end
- local function sendQueueUpdate()
- rednet.send(connected_jukebox_frontend, {
- type = "queue_update",
- current_song = state.current_song,
- queue = state.queue
- }, protocol)
- end
- local function playbackLoop()
- while true do
- if state.current_song == nil and #state.queue > 0 then
- state.current_song = table.remove(state.queue, 1)
- sendQueueUpdate()
- playSong(state.current_song)
- state.current_song = nil
- sendQueueUpdate()
- end
- sleep(0.1)
- end
- end
- local function networkLoop()
- while true do
- local id, message, received_protocol = rednet.receive()
- if received_protocol == protocol then
- if message.action == "queue" then
- table.insert(state.queue, message.song_id)
- sendQueueUpdate()
- elseif message.action == "skip" then
- skip_requested = true
- elseif message.action == "get_state" then
- rednet.send(id, {
- type = "queue_update",
- current_song = state.current_song,
- queue = state.queue
- }, protocol)
- end
- end
- end
- end
- local function gatherSongData()
- local song_list = fs.find("songs/*/*.json")
- for _, song_path in ipairs(song_list) do
- -- Decode data
- local song_file = fs.open(song_path, "r")
- local song_contents = song_file.readAll()
- song_file.close()
- local song_data = textutils.unserializeJSON(song_contents)
- local song_key = song_path
- if string.find(song_key, "songs/") ~= nil then
- song_key = string.sub(song_key, 7, #song_key - 5)
- end
- songs[song_key] = song_data
- end
- end
- function main()
- gatherSongData()
- speaker = peripheral.find("speaker")
- decoder = dfpwm.make_decoder()
- peripheral.find("modem", rednet.open)
- protocol = "jukebox_" .. tostring(JUKEBOX_ID)
- rednet.broadcast("ping", protocol)
- local timer_id = os.startTimer(1)
- connected_jukebox_frontend = nil
- repeat
- local event, p1, p2, p3 = os.pullEvent()
- if event == "rednet_message" then
- local id = p1
- local message = p2
- local received_protocol = p3
- if received_protocol == protocol then
- if message == "pong" then
- connected_jukebox_frontend = id
- end
- end
- elseif event == "timer" and p1 == timer_id then
- rednet.broadcast("ping", protocol)
- timer_id = os.startTimer(1)
- end
- until connected_jukebox_frontend ~= nil
- print("Connected to Computer #" .. tostring(connected_jukebox_frontend))
- parallel.waitForAny(
- playbackLoop,
- networkLoop
- )
- end
- main()
Advertisement
Add Comment
Please, Sign In to add comment