settings.define("mplayer.colors.bg", { description = "Background color in media player", default = 0x131313, -- #131313 type = number }) settings.define("mplayer.colors.fg", { description = "Text color in media player", default = 0xEFEFEF, -- #EFEFEF type = number }) settings.define("mplayer.colors.cursor", { description = "Color of the cursor", default = 0x8080EF, -- #8080EF type = number }) settings.define("mplayer.colors.current", { description = "Color of the currently playing song", default = 0xEFEF80, -- #EFEF80 type = number }) settings.define("mplayer.colors.status", { description = "Color of the statusbar", default = 0x80EF80, -- #80EF80 type = number }) local mplayer = { colors = { bg = colors.black, fg = colors.white, cursor = colors.blue, current = colors.yellow, status = colors.lime }, songs = {}, scroll = 0, cursor = 1, pos = 0, size = 360000 * 64, state = "PLAYING", currentSong = 0, statusLineScroll = 0, highlightedLineScroll = 0, } local function centerText(y, bg, fg, txt) local w, _ = term.getSize() local x = math.max(1, math.floor((w - #txt) / 2)) term.setCursorPos(x, y) term.setBackgroundColor(bg) term.setTextColor(fg) term.clearLine() term.write(txt) end local function time2str(ti) ti = math.floor(ti) local m, s = math.floor(ti / 60), ti % 60 return string.format("%02d:%02d", m, s) end local function setupTerminal() for k, v in pairs(mplayer.colors) do term.setPaletteColor(v, settings.get("mplayer.colors." .. k)) end term.setCursorPos(1, 1) term.setBackgroundColor(mplayer.colors.bg) term.setTextColor(mplayer.colors.fg) term.clear() end local function read32(fp) local v = 0 for i = 1, 4 do local b = string.byte(fp:read(1), 1) v = bit32.bor(bit32.lshift(v, 8), b) end return v end local fp = io.open("noita.dfpwm", "rb") if fp ~= nil then for i = 1, 24 do mplayer.songs[i] = {} mplayer.songs[i].offset = read32(fp) mplayer.songs[i].length = read32(fp) local title = fp:read(117) local zero = math.min(64, title:find("\x00") or 0) mplayer.songs[i].title = title:sub(1, zero) end fp:close() end setupTerminal() local tw, th = term.getSize() parallel.waitForAny( function() term.setCursorPos(1, 1) term.clear() print(" 0123456789abcdef") term.write("0 ") for i = 1, 255 do if (i % 16) == 0 then term.write(string.format("%x ", i / 16)) end term.write(string.char(i)) if (i % 16) == 15 then print() end end while true do -- Top bar -- Songs list for i = 1, th - 3 do end local title, time, duration = "Whatever is on the tape", mplayer.pos / 6000, mplayer.size / 6000 if mplayer.currentSong ~= 0 then local song = mplayer.songs[mplayer.currentSong] time = (mplayer.pos - song.offset) / 6000 duration = song.length / 6000 title = song.title end -- Statusline term.setCursorPos(1, th) term.clearLine() term.setTextColor(mplayer.colors.status) term.write("Playing: ") -- 9 characters -- Progressbar local lw = math.floor(tw * time / duration) term.setCursorPos(1, th - 1) term.setTextColor(mplayer.colors.current) term.clearLine() term.write(string.rep("=", lw)) term.write(">") term.setTextColor(mplayer.colors.cursor) term.write(string.rep("-", tw - lw - 1)) -- Statusline text term.setCursorPos(10, th) local timeString = string.format("[%s:%s]", time2str(time), time2str(duration)) local w = tw - #timeString - 10 -- "Playing: " plus extra space term.setTextColor(mplayer.colors.current) if #title <= w then term.write(title) else local off = (mplayer.statusLineScroll % (#title + 5)) + 1 local txt = title .. " ::: " .. title term.write(txt:sub(off, off + w - 1)) end term.setTextColor(mplayer.colors.status) term.setCursorPos(tw - #timeString + 1, th) term.write(timeString) os.sleep(0.1) end end, function() local pretty = require("cc.pretty") while true do local _evd = { os.pullEvent() } local ev, evd = table.remove(_evd, 1), _evd if ev == "key_up" and evd[1] == keys.q then break elseif ev == "key" and evd[1] == keys.f then mplayer.pos = mplayer.pos + 3000 elseif ev == "key" and evd[1] == keys.b then mplayer.pos = mplayer.pos - 3000 elseif ev == "mouse_scroll" then local dir, x, y = table.unpack(evd) elseif ev == "song_change" then mplayer.statusLineScroll = 0 elseif ev ~= "timer" then local m = term.redirect(term.native()) io.write(ev .. " ") pretty.print(pretty.pretty(evd)) term.redirect(m) end end end, function() while true do mplayer.statusLineScroll = mplayer.statusLineScroll + 1 os.sleep(0.5) end end, function() local oldSong = nil while true do if mplayer.pos < mplayer.size then mplayer.pos = mplayer.pos + 600 end mplayer.currentSong = 0 for i, song in ipairs(mplayer.songs) do if mplayer.pos >= song.offset and mplayer.pos < (song.offset + song.length) then mplayer.currentSong = i end end if oldSong ~= mplayer.currentSong then os.queueEvent("song_change") oldSong = mplayer.currentSong end os.sleep(0.1) end end )