Advertisement
HappySunChild

MP3 Player

Jul 8th, 2022 (edited)
1,091
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.33 KB | None | 0 0
  1. ---@diagnostic disable: undefined-field, need-check-nil
  2.  
  3. local speaker = peripheral.find("speaker")
  4. local dfpwm = require("cc.audio.dfpwm") -- This requires CC:Tweaked 100 or higher because of this module
  5.  
  6. term.clear()
  7. term.setCursorPos(1, 1)
  8.  
  9. local w, h = term.getSize()
  10.  
  11. local volume = 1
  12. local pitch = 1
  13.  
  14. local RECORDS = {
  15.     { "11", colors.brown },
  16.     { "13", colors.red },
  17.     { "blocks", colors.orange },
  18.     { "cat", colors.yellow },
  19.     { "chirp", colors.lime },
  20.     { "far", colors.green },
  21.     { "mall", colors.cyan },
  22.     { "mellohi", colors.lightBlue },
  23.     { "pigstep", colors.blue },
  24.     { "stal", colors.purple },
  25.     { "strad", colors.magenta },
  26.     { "wait", colors.pink },
  27.     { "ward", colors.red }
  28. }
  29.  
  30. local MENU = {
  31.     { "RECORDS", colors.red },
  32.     { "CUSTOM RECORDS", colors.orange },
  33.     { "DFPWM FILES", colors.yellow },
  34.     { "SAVES", colors.lime },
  35.     { "ADD RECORD", colors.green },
  36.     { "ADD DFPWM", colors.cyan },
  37.     { "ADD SAVE", colors.blue },
  38.     { "REMOVE ALL SAVES", colors.lightBlue },
  39.     { "VOLUME", colors.purple },
  40.     { "PITCH", colors.magenta },
  41.     { "STOP", colors.pink },
  42.     { "EXIT", colors.red },
  43.     { "UPDATE", colors.brown }
  44. }
  45.  
  46. function colors.random()
  47.     local rand = math.random(1, 16)
  48.     local c = colors.white
  49.     local cols = {}
  50.  
  51.     for i, color in pairs(colors) do
  52.         if type(color) == "number" then
  53.             table.insert(cols, color)
  54.         end
  55.     end
  56.  
  57.     return cols[rand]
  58. end -- get random color function
  59.  
  60. local function isValidId(id)
  61.     local success = pcall(function()
  62.         speaker.playSound(id, 0, 0)
  63.         speaker.stop()
  64.     end)
  65.  
  66.     return success
  67. end
  68.  
  69. local function promptInput(promptText)
  70.     term.write(promptText)
  71.     return read()
  72. end
  73.  
  74. local function printcenter(y, text, color)
  75.     local x = math.floor((w - string.len(text)) / 2)
  76.  
  77.     term.setTextColor(tonumber(color) or colors.white)
  78.     term.setCursorPos(x, y)
  79.     term.clearLine()
  80.     term.write(text)
  81. end
  82.  
  83. local function playSound(sound_jsonid, l_pitch, l_volume)
  84.     if sound_jsonid and sound_jsonid ~= nil then
  85.         speaker.playSound(sound_jsonid, tonumber(l_volume) or tonumber(volume), tonumber(l_pitch) or tonumber(pitch))
  86.     end
  87. end
  88.  
  89. -- custom json id sound functions
  90.  
  91. local function createSaveFile()
  92.     if not fs.exists("saved.txt") then
  93.         local file = fs.open("saved.txt", "w")
  94.         file.write("")
  95.         file.close()
  96.  
  97.         local file = fs.open("records.save", "w")
  98.         file.write("")
  99.         file.close()
  100.  
  101.         return true
  102.     else
  103.         return false
  104.     end
  105. end
  106.  
  107. local function clearSaveFile()
  108.     if fs.exists("saved.txt") then
  109.         local file = fs.open("saved.txt", "w")
  110.         file.write("")
  111.         file.close()
  112.  
  113.         return true
  114.     else
  115.         createSaveFile()
  116.  
  117.         return false
  118.     end
  119. end
  120.  
  121. local function addToSaveFile(saveElement)
  122.     if fs.exists("saved.txt") then
  123.         local id, name, color = saveElement[1], saveElement[2], saveElement[3]
  124.  
  125.         if color == colors.black then
  126.             color = colors.white
  127.         end
  128.  
  129.         local file = fs.open("saved.txt", "a")
  130.         file.write(name .. "\n" .. color .. "\n" .. id .. "\n\n")
  131.         file.close()
  132.  
  133.         return true
  134.     else
  135.         createSaveFile()
  136.  
  137.         return false
  138.     end
  139. end
  140.  
  141. local function getSaved()
  142.     if fs.exists("saved.txt") then
  143.         local file = fs.open("saved.txt", "r")
  144.         local saved = {}
  145.  
  146.         local i = 1
  147.         repeat
  148.             local name = file.readLine()
  149.             local color = file.readLine()
  150.             local id = file.readLine()
  151.             file.readLine()
  152.  
  153.             if id then
  154.                 saved[i] = { name, color, id }
  155.             end
  156.             i = i + 1
  157.         until id == nil or name == nil or color == nil
  158.  
  159.         file.close()
  160.         return saved
  161.     else
  162.         createSaveFile()
  163.  
  164.         return false
  165.     end
  166. end
  167.  
  168. -- custom dfpwm file sounds functions
  169.  
  170. local function createCustomSavesDir()
  171.     if not fs.exists("custom") then
  172.         fs.makeDir("custom")
  173.     end
  174. end
  175.  
  176. local function getCustomDFPWM()
  177.     if fs.exists("custom") then
  178.         local saved = fs.list("custom")
  179.  
  180.         for i, file in pairs(saved) do
  181.             saved[i] = { file, colors.random() }
  182.         end
  183.  
  184.         return saved
  185.     else
  186.         createCustomSavesDir()
  187.     end
  188. end
  189.  
  190. local function playCustomAudio(path)
  191.     local decoder = dfpwm.make_decoder()
  192.  
  193.     for input in io.lines("custom/" .. path, 16 * 1024) do
  194.         local decoded = decoder(input)
  195.  
  196.         for i, amp in pairs(decoded) do
  197.             decoded[i] = math.min(math.max(decoded[i] * tonumber(volume), -127), 127)
  198.  
  199.             if math.abs(decoded[i]) < 2 then
  200.                 decoded[i] = decoded[i] / 2
  201.             end
  202.         end
  203.  
  204.         while not speaker.playAudio(decoded, tonumber(volume)) do
  205.             os.pullEvent("speaker_audio_empty")
  206.         end
  207.     end
  208. end
  209.  
  210. local function downloadDFPWM(link, name) -- you will need to change your config to download most DFPWM files
  211.     if link and name then
  212.         if not fs.exists("custom/" .. name) and http.checkURL(link) then
  213.             shell.run(string.format("wget %s custom/%s", link, name)) -- wget, weburl, filename
  214.         end
  215.     end
  216. end
  217.  
  218. -- custom records file functions
  219.  
  220. local function getCustomRecords()
  221.     if fs.exists("records.save") then
  222.         local records = {}
  223.  
  224.         local file = fs.open("records.save", "r")
  225.         local index = 1
  226.  
  227.         repeat
  228.             local name = file.readLine()
  229.             local id = file.readLine()
  230.             local color = file.readLine()
  231.             local author = file.readLine()
  232.             file.readLine() -- increment empty line
  233.  
  234.             if id then
  235.                 records[index] = { name = name, author = author, color = color, id = id }
  236.             end
  237.             index = index + 1
  238.         until name == nil or id == nil or color == nil or author == nil
  239.  
  240.         file.close()
  241.  
  242.         return records
  243.     end
  244. end
  245.  
  246. local function addCustomRecord(id, name, author, color)
  247.     if fs.exists("records.save") then
  248.         if color == "black" then
  249.             color = "white"
  250.         end
  251.  
  252.         local file = fs.open("records.save", "a")
  253.         file.write(name .. "\n" .. id .. "\n" .. color .. "\n" .. author .. "\n\n")
  254.         file.close()
  255.  
  256.         return true
  257.     else
  258.         return false
  259.     end
  260. end
  261.  
  262. local function formatData(data)
  263.     local newData = {}
  264.  
  265.     for i, save in pairs(data) do
  266.         local name = save.name
  267.  
  268.         if save.author and string.len(save.author) > 2 then
  269.             name = string.format("%s - %s", save.name, save.author)
  270.         end
  271.  
  272.         newData[i] = { name, colors[save.color] or colors.random() }
  273.     end
  274.  
  275.     return newData
  276. end
  277.  
  278. -- ex list element; {text, color}
  279.  
  280. local function optionSelect(list, default, yoff, toptext, topcolor, exitkey, breakOnSelect, callback, keycallback)
  281.     printcenter(1, toptext, topcolor)
  282.  
  283.     if exitkey then
  284.         printcenter(h - 1, "press " .. exitkey .. " to exit.")
  285.     end
  286.  
  287.     local currentSelected = math.min(default, #list) or 1
  288.     local lastSelected = math.min(default, #list) or 1
  289.  
  290.     for i, element in pairs(list) do
  291.         local text, color = element[1], element[2]
  292.  
  293.         printcenter(i + yoff, i == currentSelected and "> " .. text .. " <" or text,
  294.             i == currentSelected and colors.white or color)
  295.     end
  296.  
  297.     while true do
  298.         local _, keycode = os.pullEvent("key")
  299.         local key = keys.getName(keycode) or "null"
  300.  
  301.         lastSelected = currentSelected
  302.  
  303.         if key == "down" then
  304.             currentSelected = currentSelected + 1
  305.  
  306.             if currentSelected > #list then
  307.                 currentSelected = 1
  308.             end
  309.         elseif key == "up" then
  310.             currentSelected = currentSelected - 1
  311.  
  312.             if currentSelected < 1 then
  313.                 currentSelected = #list
  314.             end
  315.         end
  316.  
  317.         if key == "down" or key == "up" then
  318.             local currentElement = list[currentSelected]
  319.             local lastElement = list[lastSelected]
  320.             if lastElement and currentElement then
  321.                 local cname, _ = currentElement[1], currentElement[2]
  322.                 local lname, lcolor = lastElement[1], lastElement[2]
  323.  
  324.                 printcenter(currentSelected + yoff, "> " .. cname .. " <", colors.white)
  325.                 printcenter(lastSelected + yoff, lname, lcolor)
  326.             end
  327.         end
  328.  
  329.         if key == "enter" then
  330.             playSound("block.lever.click", 1, 0.3)
  331.             sleep(0.2)
  332.             callback(currentSelected, list[currentSelected])
  333.  
  334.             if breakOnSelect then
  335.                 break
  336.             end
  337.         end
  338.  
  339.         if key == exitkey then
  340.             term.clear()
  341.             break
  342.         end
  343.  
  344.         if keycallback then
  345.             pcall(keycallback, key)
  346.         end
  347.     end
  348. end
  349.  
  350. local menuCurrent = 1
  351. local savedCurrent = 1
  352.  
  353. local active = true
  354.  
  355. while active do
  356.     optionSelect(MENU, menuCurrent, 2, "Menu Options", colors.pink, nil, true, function(selected, element)
  357.         local button = element[1]
  358.         menuCurrent = selected
  359.  
  360.         if button == "RECORDS" then
  361.             optionSelect(RECORDS, 1, 2, "All Records", colors.green, "x", false, function(selected, element)
  362.                 playSound("music_disc." .. element[1])
  363.             end)
  364.         elseif button == "SAVES" then
  365.             if not fs.exists("saved.txt") then
  366.                 createSaveFile()
  367.             end
  368.  
  369.             local saved = getSaved()
  370.  
  371.             term.clear()
  372.             term.setCursorPos(1, 1)
  373.  
  374.             if #saved == 0 then
  375.                 printcenter(13, "No saves detected", colors.red)
  376.                 printcenter(19, "press any key to exit.")
  377.             end
  378.  
  379.             if saved ~= nil and #saved > 0 then
  380.                 optionSelect(saved, 1, 2, "All Saves", colors.lime, "x", false, function(selected, element)
  381.                     playSound(element[3])
  382.                 end)
  383.             end
  384.  
  385.             if #saved == 0 then
  386.                 os.pullEvent("key")
  387.  
  388.                 term.clear()
  389.             end
  390.         elseif button == "ADD SAVE" then
  391.             term.clear()
  392.             term.setCursorPos(1, 1)
  393.             term.setTextColor(colors.yellow)
  394.  
  395.             local id = promptInput("Input json id: ")
  396.             local name = promptInput("Input name: ")
  397.  
  398.             if isValidId(id) then
  399.                 term.clear()
  400.  
  401.                 printcenter(5, "Saved", colors.lime)
  402.                 printcenter(6, id, colors.green)
  403.                 printcenter(7, "as", colors.lime)
  404.                 printcenter(8, name, colors.green)
  405.  
  406.                 addToSaveFile({ id, name, colors.random() })
  407.  
  408.                 speaker.playNote("bit", 1, 16)
  409.                 sleep(0.15)
  410.                 speaker.playNote("bit", 2, 20)
  411.                 sleep(0.1)
  412.                 speaker.playNote("bit", 2, 24)
  413.  
  414.                 sleep(1)
  415.             else
  416.                 term.clear()
  417.  
  418.                 printcenter(6, "not a valid id!", colors.red)
  419.  
  420.                 speaker.playNote("bit", 2, 0.05)
  421.                 sleep(0.2)
  422.                 speaker.playNote("bit", 2, 0.05)
  423.  
  424.                 sleep(1)
  425.             end
  426.         elseif button == "VOLUME" then
  427.             term.clear()
  428.             term.setCursorPos(1, 1)
  429.             term.setTextColor(colors.yellow)
  430.  
  431.             volume = promptInput("Input volume: ")
  432.         elseif button == "PITCH" then
  433.             term.clear()
  434.             term.setCursorPos(1, 1)
  435.             term.setTextColor(colors.yellow)
  436.  
  437.             pitch = promptInput("Input pitch: ")
  438.         elseif button == "STOP" then
  439.             speaker.stop()
  440.         elseif button == "REMOVE ALL SAVES" then
  441.             term.clear()
  442.             optionSelect({ { "Yes", colors.green }, { "No", colors.red } }, 1, 3, "Are you sure?", colors.blue, nil, true
  443.                 , function(selected, element)
  444.                 if selected == 1 then
  445.                     clearSaveFile()
  446.  
  447.                     term.clear()
  448.                     printcenter(7, "Wiped Save File", colors.red)
  449.  
  450.                     speaker.playNote("bit", 2, 24)
  451.                     sleep(0.1)
  452.                     speaker.playNote("bit", 2, 20)
  453.                     sleep(0.11)
  454.                     speaker.playNote("bit", 1, 16)
  455.  
  456.                     sleep(1)
  457.                 end
  458.             end)
  459.         elseif button == "DFPWM FILES" then
  460.             if not fs.exists("custom") then
  461.                 createCustomSavesDir()
  462.             end
  463.  
  464.             local saved = getCustomDFPWM()
  465.  
  466.             term.clear()
  467.             term.setCursorPos(1, 1)
  468.  
  469.             if #saved == 0 then
  470.                 printcenter(9, " No custom audios detected", colors.red)
  471.                 printcenter(10, "inside directory", colors.red)
  472.                 printcenter(18, "press any key to exit.")
  473.  
  474.                 os.pullEvent("key")
  475.                 term.clear()
  476.             end
  477.  
  478.             if #saved > 0 then
  479.                 optionSelect(saved, 1, 2, "All Custom Saves", colors.purple, "x", false, function(selected, element)
  480.                     playCustomAudio(element[1])
  481.                 end)
  482.             end
  483.         elseif button == "CUSTOM RECORDS" then
  484.             if not fs.exists("records.save") then
  485.                 createSaveFile()
  486.             end
  487.  
  488.             term.clear()
  489.             term.setCursorPos(1, 1)
  490.  
  491.             local saved = getCustomRecords()
  492.  
  493.             if #saved == 0 then
  494.                 printcenter(13, "No saved detected", colors.red)
  495.                 printcenter(19, "press any key to exit.")
  496.  
  497.                 os.pullEvent()
  498.                 term.clear()
  499.             else
  500.                 optionSelect(formatData(saved), 1, 2, "Custom Records", colors.purple, "x", false,
  501.                     function(selected)
  502.                         playSound(saved[selected].id)
  503.                     end)
  504.             end
  505.         elseif button == "ADD RECORD" then
  506.             if not fs.exists("records.save") then
  507.                 createSaveFile()
  508.             end
  509.  
  510.             term.clear()
  511.             term.setCursorPos(1, 1)
  512.             term.setTextColor(colors.yellow)
  513.  
  514.             local id = promptInput("Id: ")
  515.             local name = promptInput("Name: ")
  516.             local author = promptInput("Author (optional): ")
  517.             local color = promptInput("Color (optional): ")
  518.  
  519.             if isValidId(id) then
  520.                 term.clear()
  521.  
  522.                 printcenter(6, "Added Record", colors.green)
  523.                 printcenter(7, "Check \"CUSTOM RECORDS\"", colors.green)
  524.  
  525.                 addCustomRecord(id, name, author, color)
  526.  
  527.                 speaker.playNote("bit", 1, 16)
  528.                 sleep(0.15)
  529.                 speaker.playNote("bit", 2, 20)
  530.                 sleep(0.1)
  531.                 speaker.playNote("bit", 2, 24)
  532.  
  533.                 sleep(1)
  534.             end
  535.         elseif button == "ADD DFPWM" then
  536.             term.clear()
  537.             term.setCursorPos(1, 1)
  538.             term.setTextColor(colors.yellow)
  539.  
  540.             local link = promptInput("Link:")
  541.             local name = promptInput("Name: ")
  542.  
  543.             if link and name then
  544.                 downloadDFPWM(link, name)
  545.  
  546.                 term.clear()
  547.  
  548.                 printcenter(6, "Added DFPWM", colors.green)
  549.                 printcenter(7, "Check \"DFPWM FILES\"", colors.green)
  550.  
  551.                 speaker.playNote("bit", 1, 16)
  552.                 sleep(0.15)
  553.                 speaker.playNote("bit", 2, 20)
  554.                 sleep(0.1)
  555.                 speaker.playNote("bit", 2, 24)
  556.  
  557.                 sleep(1)
  558.             end
  559.         elseif selected == #MENU - 1 then
  560.             term.clear()
  561.             term.setCursorPos(1, 1)
  562.  
  563.             active = false
  564.         elseif button == "UPDATE" then
  565.             if fs.exists("player") then
  566.                 fs.delete("player")
  567.             end
  568.  
  569.             shell.run("pastebin get jw8AMtSS player")
  570.  
  571.             term.clear()
  572.             term.setCursorPos(1, 1)
  573.  
  574.             printcenter(7, "Updating...", colors.green)
  575.             printcenter(8, "Your saves will", colors.green)
  576.             printcenter(9, "stay.", colors.green)
  577.  
  578.             sleep(1.5)
  579.  
  580.             term.clear()
  581.             term.setCursorPos(1, 1)
  582.  
  583.             active = false
  584.         end
  585.     end)
  586. end
  587.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement