SHARE
TWEET

CC:Tweaked Music Player

JohnDog3112 May 26th, 2020 (edited) 822 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local runMainLoop = true
  2. --binary section updated from https://pastebin.com/pq9LScbp by JILLE_JR
  3. function byte_lsb(handle)
  4.   return handle.read()
  5. end
  6.  
  7. local function int16_lsb(handle)
  8.   return bit32.bor(bit32.lshift(byte_lsb(handle),8), byte_lsb(handle))
  9. end
  10.  
  11. function int16_msb(handle)
  12.   local x = int16_lsb(handle)
  13.   --# for some reason computercraft doesn't like little endian so we convert to big endian
  14.   local y = 0
  15.   y = y + bit32.lshift(bit32.band(x,0x00FF),8)
  16.   y = y + bit32.rshift(bit32.band(x,0xFF00),8)
  17.   return y
  18. end
  19.  
  20. local function int32_lsb(handle)
  21.   return bit32.bor(bit32.lshift(int16_lsb(handle),16),int16_lsb(handle))
  22. end
  23.  
  24. function int32_msb(handle)
  25.   local x = int32_lsb(handle)
  26.   --# again, convert little-endian to big-endian
  27.   local y = 0
  28.   y = y + bit32.lshift(bit32.band(x, 0x000000FF), 24)
  29.   y = y + bit32.rshift(bit32.band(x, 0xFF000000), 24)
  30.   y = y + bit32.lshift(bit32.band(x, 0x0000FF00), 8)
  31.   y = y + bit32.rshift(bit32.band(x, 0x00FF0000), 8)
  32.   return y
  33. end
  34. --end of binary section from JILLE_JR
  35. function bit_string(handle)
  36.   local len = int32_msb(handle)
  37.   local str = ""
  38.   for i=1, len do
  39.     str = str .. string.char(byte_lsb(handle))
  40.   end
  41.   return str
  42. end
  43. function stringSelector(boolean, var1, var2)
  44.   if boolean then
  45.     if type(var1) == "table" then
  46.       local str = ""
  47.       for i=1, #var1 do
  48.         str = str .. var1[i]
  49.       end
  50.       var1 = str
  51.     end
  52.     return var1
  53.   else
  54.     if type(var2) == "table" then
  55.       local str = ""
  56.       for i=1, #var2 do
  57.         str = str .. var2[i]
  58.       end
  59.       var2 = str
  60.     end
  61.     return var2
  62.   end
  63. end
  64. function songDetails(handle)
  65.   local song = {}
  66.   local new = int16_msb(handle)
  67.   if new == 0 then
  68.     song.version = byte_lsb(handle)
  69.     song.fci = byte_lsb(handle)
  70.     if song.version >= 3 then
  71.       song.length = int16_msb(handle)
  72.     else
  73.       song.length = nil
  74.     end
  75.   else
  76.     song.version = 0
  77.     song.length = new
  78.   end
  79.   song.height = int16_msb(handle)
  80.   song.name = bit_string(handle)
  81.   song.author = bit_string(handle)
  82.   song.ogAuthor = bit_string(handle)
  83.   song.description = bit_string(handle)
  84.   song.tempo = int16_msb(handle)/100
  85.   song.autoSave = byte_lsb(handle)
  86.   song.autoSaveDuration = byte_lsb(handle)
  87.   song.timeSignature = byte_lsb(handle)
  88.   song.minutesSpent = int32_msb(handle)
  89.   song.leftClicks = int32_msb(handle)
  90.   song.rightClicks = int32_msb(handle)
  91.   song.blocksAdded = int32_msb(handle)
  92.   song.blocksRemoved = int32_msb(handle)
  93.   song.ogFileName = bit_string(handle)
  94.   song.duration = song.length/song.tempo
  95.   if song.version >= 4 then
  96.     song.loop = byte_lsb(handle)
  97.     song.loopmax = byte_lsb(handle)
  98.     song.loopstart = int16_lsb(handle)
  99.   end
  100.   return song
  101. end
  102.  
  103. function loadSong(handle)
  104.   local song = songDetails(handle)
  105.   song.ticks = {}
  106.   local curTick = -1
  107.   local running1 = true
  108.   while running1 do
  109.     local tickJump = int16_msb(handle)
  110.     curTick = curTick + tickJump
  111.     if tickJump > 0 then
  112.       local tick = {}
  113.       tick.tick = curTick
  114.       tick.layers = {}
  115.       local curLayer = 0
  116.       local running2 = true
  117.       while running2 do
  118.         local layerJump = int16_msb(handle)
  119.         curLayer = curLayer + layerJump
  120.         if layerJump > 0 then
  121.           local layer = {}
  122.           layer.instrument = byte_lsb(handle)
  123.           layer.note = byte_lsb(handle)-33
  124.           layer.layer = curLayer
  125.           if song.version >= 4 then
  126.             layer.vel = byte_lsb(handle)
  127.             layer.pan = byte_lsb(handle)
  128.             layer.pit = int16_msb(handle)
  129.           else
  130.             layer.vel = 100
  131.             layer.pan = 100
  132.             layer.pit = 0
  133.           end
  134.           table.insert(tick.layers,layer)
  135.         else
  136.           running2 = false
  137.         end
  138.       end
  139.       table.insert(song.ticks,tick)
  140.     else
  141.       running1 = false
  142.     end
  143.   end
  144.   if song.length == nil then
  145.     song.length = song.ticks[#song.ticks].tick
  146.   end
  147.   return song
  148. end
  149. local speakers = {}
  150. function loadSpeakers()
  151.   speakers = table.pack(peripheral.find("speaker"))
  152. end
  153. local instruments = {}
  154. instruments[0] = "harp"
  155. instruments[1] = "bass"
  156. instruments[2] = "basedrum"
  157. instruments[3] = "snare"
  158. instruments[4] = "hat"
  159. instruments[5] = "guitar"
  160. instruments[6] = "flute"
  161. instruments[7] = "bell"
  162. instruments[8] = "chime"
  163. instruments[9] = "xylophone"
  164. local progress = 0
  165. volume = 3
  166. function playSong(fileName)
  167.   local handle, err = fs.open(fileName,"rb")
  168.   if not handle then error(err) end
  169.   if #speakers == 0 then loadSpeakers() end
  170.   local song = loadSong(handle)
  171.   handle.close()
  172.   local ticks = song.ticks
  173.   local waitTime = 1/song.tempo
  174.   local startTime = os.clock()
  175.   for i=1, #ticks do
  176.     progress = ticks[i].tick/song.length
  177.     layers = ticks[i].layers
  178.     for j=1, #layers do
  179.       l = layers[j]
  180.       speakers[j%#speakers+1].playNote(instruments[l.instrument],volume,l.note)
  181.     end
  182.     if i ~= #ticks then
  183.       sleep((startTime+waitTime*ticks[i+1].tick)-os.clock())
  184.     end
  185.   end
  186. end
  187. local function round(num)
  188.   if num%1 >= .5 then
  189.     return math.ceil(num)
  190.   else
  191.     return math.floor(num)
  192.   end
  193. end
  194. local songs = {}
  195. local ongoingSong = {}
  196. local nextSong = {}
  197. local paused = false
  198. local shuffle = false
  199. local autoPlay = false
  200. local songProgress = 0
  201. function chooseNextSong()
  202.   if #songs > 0 then
  203.     if autoPlay and ongoingSong.pos ~= nil and nextSong.pos == nil then
  204.       if shuffle then
  205.         local num = round(#songs*math.random())
  206.         nextSong = songs[num]
  207.         nextSong.pos = num
  208.       else
  209.         local num = (ongoingSong.pos)%#songs+1
  210.         nextSong = songs[num]
  211.         nextSong.pos = num
  212.       end
  213.     end
  214.   end
  215. end
  216. function songPlayer()
  217.   local event, command, arg1 = nil, nil, nil
  218.   local runStartingStatement = true
  219.   while true do
  220.     if runStartingStatement then
  221.       if autoPlay and nextSong.pos ~= nil then
  222.         ongoingSong = nextSong
  223.         nextSong = {}
  224.       else
  225.         ongoingSong = {}
  226.         event, command, arg1 = os.pullEvent("song")
  227.       end
  228.     else
  229.       runStartingStatement = true
  230.     end
  231.     if ongoingSong.pos ~= nil or (command == "play" and tonumber(arg1) and arg1 > 0 and arg1 < #songs) then
  232.       if paused then
  233.         paused = false
  234.         os.queueEvent("screen","update","bottomBar")
  235.       end
  236.       if arg1 then
  237.         ongoingSong = songs[arg1]
  238.         ongoingSong.pos = arg1
  239.         nextSong = {}
  240.       end
  241.       chooseNextSong()
  242.       local songPath = ongoingSong.path
  243.       local handle, err = fs.open(songPath,"rb")
  244.       event, command, arg1 = nil, nil, nil
  245.       if not handle then error(err) end
  246.       if #speakers == 0 then loadSpeakers() end
  247.       local song = loadSong(handle)
  248.       handle.close()
  249.       if song.length == nil then
  250.         song.length = song.ticks[#song.ticks].ticks
  251.       end
  252.       local ticks = song.ticks
  253.       local waitTime = 1/song.tempo
  254.       local startTime = os.clock()
  255.       local i = 1
  256.       while i <= #ticks do
  257.         songProgress = ticks[i].tick/song.length
  258.         layers = ticks[i].layers
  259.         for j=1, #layers do
  260.           l = layers[j]
  261.           speakers[j%#speakers+1].playNote(instruments[l.instrument],volume,l.note)
  262.         end
  263.         local timerID = nil
  264.         local pauseStart = nil
  265.         if paused then
  266.           pauseStart = os.clock()
  267.         elseif i ~= #ticks then
  268.           timerID = os.startTimer(startTime+waitTime*ticks[i+1].tick-os.clock())
  269.           --sleep((startTime+waitTime*ticks[i+1].tick)-os.clock())
  270.         end
  271.         local moveOn = false
  272.         while i ~= #ticks and not moveOn do
  273.           event, command, arg1 = os.pullEvent()
  274.           moveOn = true
  275.           if event == "timer" and command == timerID then
  276.           elseif event == "song" then
  277.             if command == "resume" and pauseStart ~= nil then
  278.               startTime = startTime + (os.clock()-pauseStart)
  279.             elseif command == "play" and arg1 ~= nil and songPath ~= nil and songs ~= nil and songs[arg1] ~= nil then
  280.               if songs[arg1].path ~= songPath then
  281.                 i = #ticks+1
  282.                 runStartingStatement = false
  283.               else
  284.                 i = 0
  285.                 startTime = os.clock()
  286.               end
  287.               paused = false
  288.               os.queueEvent("screen", "update", "bottomBar")
  289.             elseif command == "jump" then
  290.               if arg1 > 0 and arg1 <= song.length*arg1 then
  291.                 local pos = math.floor(arg1*song.length)
  292.                 local closestTick = -1
  293.                 local closestTickPos = 0
  294.                 for b=1, #ticks do
  295.                   if closestTick == -1 or math.abs(pos-ticks[b].tick) <= math.abs(pos-closestTick) then
  296.                     closestTick = ticks[b].tick
  297.                     closestTickPos = b
  298.                   else
  299.                     break
  300.                   end
  301.                   if b%100 == 0 then
  302.                     sleep(0.00001)
  303.                   end
  304.                 end
  305.                 i=closestTickPos
  306.                 startTime = os.clock()-(waitTime*closestTick)
  307.               end
  308.               paused = false
  309.               os.queueEvent("screen", "update", "bottomBar")
  310.             end
  311.           else
  312.             moveOn = false
  313.           end
  314.         end
  315.         i = i+1
  316.       end
  317.     end
  318.   end
  319. end
  320. function recursiveFind(dir, key)
  321.   local files = {}
  322.   local directories = {dir}
  323.   local iterations = 0
  324.   while #directories > 0 do
  325.     iterations = iterations + 1
  326.     if iterations%100 == 0 then
  327.       sleep(0.0001)
  328.     end
  329.     local path = table.remove(directories,1)
  330.     local dirFiles = fs.list(path)
  331.     for i, v in pairs(dirFiles) do
  332.       if fs.isDir(path .. "/" .. v) then
  333.         table.insert(directories, path .. v .. "/")
  334.       elseif string.find(v,key) then
  335.         table.insert(files, path .. v)
  336.       end
  337.     end
  338.   end
  339.   return files
  340. end
  341. function retrieveSongs()
  342.   local files = recursiveFind("", ".nbs")
  343.   songs = {}
  344.   for i=1, #files do
  345.     local file, err = fs.open(files[i],"rb")
  346.     if not file then error(err) end
  347.     local tmpSong = songDetails(file)
  348.     file.close()
  349.     local song = {}
  350.     song.author = tmpSong.author
  351.     song.name = tmpSong.name
  352.     if song.name == "" and tmpSong.ogFileName ~= "" then
  353.       song.name = tmpSong.ogFileName
  354.     elseif song.name == "" then
  355.       song.name = files[i]
  356.     end
  357.     song.path = files[i]
  358.     song.duration = math.floor(tmpSong.duration*100)/100
  359.     table.insert(songs,song)
  360.   end
  361. end
  362. screenPrototype = {screen="og"}
  363. function screenPrototype.__init__(baseClass, data)
  364.   self = {}
  365.   for i,v in pairs(data) do
  366.     self[i] = v
  367.   end
  368.   setmetatable(self, {__index=screenPrototype})
  369.   return self
  370. end
  371. setmetatable(screenPrototype, {__call=screenPrototype.__init__})
  372. function screenPrototype:bWrite(str, posX, posY, backColor, frontColor)
  373.   local screen = self
  374.   prevBackColor = screen.getBackgroundColor()
  375.   prevFrontColor = screen.getTextColor()
  376.   if backColor then
  377.     screen.setBackgroundColor(backColor)
  378.   end
  379.   if frontColor then
  380.     screen.setTextColor(frontColor)
  381.   end
  382.   screen.setCursorPos(posX,posY)
  383.   screen.write(str)
  384.   screen.setTextColor(prevFrontColor)
  385.   screen.setBackgroundColor(prevBackColor)
  386. end
  387. function xCenText(str, space)
  388.   return string.rep(" ", math.floor((space-#str)/2)) .. str .. string.rep(" ", math.ceil((space-#str)/2))
  389. end
  390. local songSelectionSpace = 6
  391. local songScreen = {}
  392. function songScreen.drawSongSelector(screen)
  393.   if not screen.name then
  394.     screen = screenPrototype(screen)
  395.   end
  396.   if #songs == 0 then retrieveSongs() end
  397.   local topSong = screen.topSong
  398.   local selectedSong = screen.selectedSong
  399.   local x,y = screen.getSize()
  400.   screen.setBackgroundColor(colors.yellow)
  401.   local lines = y-songSelectionSpace
  402.   screen.setCursorPos(1,1)
  403.   local space = (x-11)/2
  404.   local nameSpace = space + space%1
  405.   local authorSpace = space - space%1
  406.   local durationSpace = 10
  407.   if authorSpace%2 == nameSpace%2 then
  408.     nameSpace = nameSpace + nameSpace%2
  409.     authorSpace = authorSpace - authorSpace%2
  410.   else
  411.     nameSpace = nameSpace - nameSpace%2
  412.     authorSpace = authorSpace - authorSpace%2
  413.     durationSpace = durationSpace+1
  414.   end
  415.   nameStart = 1
  416.   nameEnd = nameSpace+1
  417.   authorStart = nameSpace+1
  418.   authorEnd = authorStart+authorSpace
  419.   durationStart = authorEnd+1
  420.   durationEnd = durationStart+durationSpace
  421.   screen:bWrite(xCenText("Name", nameSpace), nameStart,1)
  422.   screen:bWrite("|", nameSpace,1, colors.red)
  423.   screen:bWrite(xCenText("Author", authorSpace), authorStart,1)
  424.   screen:bWrite("|", nameSpace+1+authorSpace,1, colors.red)
  425.   screen:bWrite(string.rep(" ", x-nameSpace-authorSpace-1-9) .. "Length(s)", durationStart,1)
  426.   screen:bWrite(string.rep("-", nameSpace-1) .. "+" .. string.rep("-",authorSpace) .. "+" .. string.rep("-", durationSpace), 1,2, colors.red)
  427.   local iter = lines-3
  428.   if #songs < iter then iter = #songs end
  429.   for i=topSong, iter+topSong-1 do
  430.     local song = songs[i]
  431.     local yLevel = i-topSong+3
  432.     local backColor = colors.yellow
  433.     local frontColor = colors.white
  434.     if i == selectedSong then
  435.       backColor = colors.white
  436.       frontColor = colors.black
  437.     end
  438.     if #song.name > nameSpace then
  439.       screen:bWrite(string.sub(song.name,1,nameSpace), 1, yLevel, backColor, frontColor)
  440.     else
  441.       screen:bWrite(song.name .. string.rep(" ", nameSpace-#song.name), 1, yLevel, backColor, frontColor)
  442.     end
  443.     screen:bWrite("|", nameSpace,yLevel, colors.red)
  444.     if #song.author > authorSpace then
  445.       screen:bWrite(string.sub(song.author,1,authorSpace), authorStart, yLevel, backColor, frontColor)
  446.     else
  447.       screen:bWrite(song.author .. string.rep(" ", authorSpace-#song.author), authorStart, yLevel, backColor, frontColor)
  448.     end
  449.     screen:bWrite("|", authorEnd,yLevel, colors.red)
  450.     if #tostring(song.duration) > durationSpace then
  451.       screen:bWrite(string.sub(tostring(song.duration),1,durationSpace), durationStart, yLevel, backColor, frontColor)
  452.     else
  453.       screen:bWrite(tostring(song.duration) .. string.rep(" ", durationSpace-#tostring(song.duration)), durationStart, yLevel, backColor, frontColor)
  454.     end
  455.   end
  456.   if #songs < lines then
  457.     for i=#songs+3, lines-1 do
  458.       screen:bWrite(string.rep(" ", nameSpace-1), 1, i)
  459.       screen:bWrite("|", nameSpace,i, colors.red)
  460.       screen:bWrite(string.rep(" ", authorSpace), authorStart,i)
  461.       screen:bWrite("|", nameSpace+1+authorSpace,i, colors.red)
  462.       screen:bWrite(string.rep(" ", durationSpace), durationStart, i)
  463.     end
  464.   end
  465.   screen:bWrite(string.rep("-", nameSpace-1) .. "+" .. string.rep("-",authorSpace) .. "+" .. string.rep("-", durationSpace), 1,lines, colors.red)
  466. end
  467. function songScreen.drawBottomBar(screen)
  468.   if not screen.name then
  469.     screen = screenPrototype(screen)
  470.   end
  471.   local selectedSong = screen.selectedSong
  472.   if #songs == 0 then retrieveSongs() end
  473.   local x,y = screen.getSize()
  474.   local stLine = y-songSelectionSpace+1
  475.   local playingStr = stringSelector(ongoingSong.pos ~= nil, table.pack("Playing: ",ongoingSong.name, " by ",ongoingSong.author), "Playing: ")
  476.   screen:bWrite(string.sub(playingStr,1, x-3) .. string.rep(" ", x-#playingStr-3), 1, stLine, colors.black)
  477.   local nextStr = stringSelector(nextSong.pos ~= nil, table.pack("Next: ",nextSong.name," by ",nextSong.author), "Next: ")
  478.   screen:bWrite(string.sub(nextStr, 1, x-3) .. string.rep(" ", x-#nextStr-3), 1, stLine+1, colors.black)
  479.   if selectedSong > 1 then
  480.     screen:bWrite("/\\", x-1,stLine, colors.blue)
  481.   else
  482.     screen:bWrite("  ", x-1,stLine, colors.blue)
  483.   end
  484.   if selectedSong ~= #songs then
  485.     screen:bWrite("\\/", x-1, stLine+1, colors.blue)
  486.   else
  487.     screen:bWrite("  ", x-1,stLine+1, colors.blue)
  488.   end
  489.   screen:bWrite(">", x-2,stLine,colors.green)
  490.   screen:bWrite(" ", x-2,stLine+1,colors.red)
  491.   local button1Space = math.floor((x-1)/2)
  492.   local button2Space = math.ceil((x-1)/2)
  493.   screen:bWrite(xCenText("Pause",button1Space),1,stLine+2, stringSelector(paused,colors.white,colors.gray), colors.black)
  494.   screen:bWrite(xCenText("shuffle",button2Space),button1Space+2,stLine+2, stringSelector(shuffle,colors.white,colors.gray), colors.black)
  495.   screen:bWrite(xCenText("Auto Play",button1Space),1,stLine+3, stringSelector(autoPlay,colors.white,colors.gray), colors.black)
  496.   screen:bWrite(xCenText("Refresh Songs",button2Space),button1Space+2,stLine+3, colors.blue, colors.white)
  497.   screen:bWrite(xCenText("Random",button1Space),1,stLine+4, colors.blue, colors.white)
  498.   screen:bWrite(xCenText("Configure",button2Space),button1Space+2,stLine+4, colors.blue, colors.white)
  499.  
  500.   bars = math.floor(x*songProgress)
  501.   screen:bWrite(string.rep(" ", bars), 1, y, colors.white)
  502.   screen:bWrite(string.rep(" ", x-bars) .. ">", bars+2, y, colors.black)
  503. end
  504. function songScreen.load(screen)
  505.   screen.setBackgroundColor(colors.black)
  506.   screen.clear()
  507.   songScreen.drawSongSelector(screen)
  508.   songScreen.drawBottomBar(screen)
  509. end
  510. local timerEventID = nil
  511. function songScreen.event(screen, event)
  512.   local update = true
  513.   if event[1] == "timer" and event[2] == timerEventID then
  514.     update = false
  515.     songScreen.drawBottomBar(screen)
  516.   elseif (event[1] == "monitor_touch" and event[2] == screen.name) or (event[1] == "mouse_click" and screen.name == "term") then
  517.     local x,y = screen.getSize()
  518.     local stLine = y-songSelectionSpace+1
  519.     local button1Space = math.floor((x-1)/2)
  520.     local button2Space = math.ceil((x-1)/2)
  521.     local tx = event[3]
  522.     local ty = event[4]
  523.     if ty > 2 and ty < y-songSelectionSpace then
  524.       if ty-2 <= #songs then
  525.         if ty-2+screen.topSong-1 == screen.selectedSong then
  526.           os.queueEvent("song","play",screen.selectedSong)
  527.         else
  528.           screen.selectedSong = ty-2+screen.topSong-1
  529.         end
  530.       end
  531.     elseif screen.selectedSong ~= 1 and ty == stLine and tx >= x-1 then
  532.       screen.selectedSong = screen.selectedSong - 1
  533.       if screen.selectedSong < screen.topSong then
  534.         screen.topSong = screen.selectedSong
  535.       end
  536.     elseif screen.selectedSong < #songs and ty == stLine+1 and tx >= x-1 then
  537.       screen.selectedSong = screen.selectedSong + 1
  538.       if screen.selectedSong >= screen.topSong+(y-songSelectionSpace-3) then
  539.         screen.topSong = screen.topSong + 1
  540.       end
  541.     elseif screen.selectedSong >= 1 and screen.selectedSong <= #songs and ty == stLine and tx == x-2 then
  542.       os.queueEvent("song","play",screen.selectedSong)
  543.     elseif ty == stLine+2 and tx >= 1 and tx <= button1Space then
  544.       paused = not paused
  545.       os.queueEvent("song","resume")
  546.     elseif ty == stLine+2 and tx >= button1Space+2 and tx <= x then
  547.       shuffle = not shuffle
  548.       if autoPlay then
  549.         nextSong = {}
  550.         chooseNextSong()
  551.       end
  552.     elseif ty == stLine+3 and tx >= 1 and tx <= button1Space then
  553.       autoPlay = not autoPlay
  554.       if autoPlay then
  555.         nextSong = {}
  556.         chooseNextSong()
  557.       else
  558.         nextSong = {}
  559.       end
  560.     elseif ty == stLine+3 and tx >= button1Space+2 and tx <= x then
  561.       retrieveSongs()
  562.       os.queueEvent("screen","update")
  563.     elseif ty == stLine+4 and tx >= 1 and tx <= button1Space and (ongoingSong.pos == nil or #songs > 1) then
  564.       nextSong = {}
  565.       local songNum = round(#songs*math.random())
  566.       if ongoingSong.pos ~= nil and #songs > 1 then
  567.         iterations = 0
  568.         while songNum == ongoingSong.pos do
  569.           songNum = round(#songs*math.random())
  570.           iterations = iterations+1
  571.           if iterations > 10 then
  572.             songNum = (orginalSong.pos)%#songs+1
  573.           end
  574.         end
  575.       end
  576.       os.queueEvent("song","play", songNum)
  577.     elseif ty == stLine+4 and tx >= button1Space+2 and tx <= x then
  578.       --configuration
  579.     elseif ty == y then
  580.       update = false
  581.       os.queueEvent("song", "jump",tx/x)
  582.     end
  583.   elseif event[1] == "key" and screen.name == "term" then
  584.     local x,y = screen.getSize()
  585.     if event[2] == keys.up then
  586.       if screen.selectedSong ~= 1 then
  587.         screen.selectedSong = screen.selectedSong - 1
  588.         if screen.selectedSong < screen.topSong then
  589.           screen.topSong = screen.selectedSong
  590.         end
  591.       end
  592.     elseif event[2] == keys.down then
  593.       if screen.selectedSong ~= #songs then
  594.         screen.selectedSong = screen.selectedSong + 1
  595.         if screen.selectedSong > screen.topSong+(y-songSelectionSpace-4) then
  596.           screen.topSong = screen.topSong + 1
  597.         end
  598.       end
  599.     elseif event[2] == keys.enter and screen.selectedSong >= 1 and screen.selectedSong then
  600.       os.queueEvent("song","play",screen.selectedSong)
  601.     elseif event[2] == keys.tab then
  602.       runMainLoop = false
  603.       update = false
  604.     end
  605.   elseif event[1] == "screen" and event[2] == "update" then
  606.     update = false
  607.     if event[3] == "bottomBar" then
  608.       songScreen.drawBottomBar(screen)
  609.     elseif event[3] == "songSelector" then
  610.       songScreen.drawSongSelector(screen)
  611.     else
  612.       songScreen.load(screen)
  613.     end
  614.   else
  615.     update = false
  616.   end
  617.   if update then
  618.     songScreen.load(screen)
  619.   end
  620. end
  621. local screens = {}
  622. for i,v in pairs(peripheral.getNames()) do
  623.   if (peripheral.getType(v) == "monitor") then
  624.     local tScreen = screenPrototype(peripheral.wrap(v))
  625.     tScreen.selectedSong = 1
  626.     tScreen.topSong = 1
  627.     tScreen.name = v
  628.     songScreen.load(tScreen)
  629.     table.insert(screens,tScreen)
  630.   end
  631. end
  632. local tScreen = screenPrototype(term)
  633. tScreen.selectedSong = 1
  634. tScreen.topSong = 1
  635. tScreen.name = "term"
  636. songScreen.load(tScreen)
  637. table.insert(screens,tScreen)
  638. function mainLoop()
  639.   timerEventID = os.startTimer(1)
  640.   while runMainLoop do
  641.     local event = table.pack(os.pullEvent())
  642.     for i=1, #screens do
  643.       songScreen.event(screens[i],event)
  644.     end
  645.     if event[1] == "timer" and event[2] == timerEventID then
  646.       timerEventID = os.startTimer(1)
  647.     end
  648.   end
  649. end
  650. parallel.waitForAny(mainLoop,songPlayer)
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Top