Advertisement
JohnDog3112

CC:Tweaked Music Player

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