· 5 years ago · Jan 07, 2021, 08:06 PM
1-- VARIABLES --
2
3local indexURL = "https://raw.githubusercontent.com/RubenHetKonijn/computronics-songs/main/index.json?cb=" .. os.epoch("utc")
4
5local applicationName = "Musicify"
6local version = 0.2
7
8local args = {...}
9local musicify = {}
10
11local tape = peripheral.find("tape_drive")
12local screenWidth, screenHeight = term.getSize()
13
14local currentSong = 0
15local selection = 0
16local scroll = 0
17
18-- BUSINESS LAYER --
19
20if not tape then
21 print("ERROR: Tapedrive not found")
22end
23
24local handle = http.get(indexURL)
25local indexJSON = handle.readAll()
26handle.close()
27local index = textutils.unserialiseJSON(indexJSON)
28if not index then
29 print("ERROR: The index is malformed.")
30 return
31end
32
33local function getSongID(songname)
34for i in pairs(index.songs) do
35 if index.songs[i].name == songname then
36 return i
37 end
38 end
39end
40
41local function wipe()
42 local k = tape.getSize()
43 tape.stop()
44 tape.seek(-k)
45 tape.stop()
46 tape.seek(-90000)
47 local s = string.rep("\xAA", 8192)
48 for i = 1, k + 8191, 8192 do
49 tape.write(s)
50 end
51 tape.seek(-k)
52 tape.seek(-90000)
53end
54
55local function play(songID)
56 print("Playing " .. getSongID(songID.name) .. " | " .. songID.author .. " - " .. songID.name)
57 wipe()
58 tape.stop()
59 tape.seek(-tape.getSize()) -- go back to the start
60
61 local h = http.get(songID.file, nil, true) -- write in binary mode
62 tape.write(h.readAll()) -- that's it
63 h.close()
64
65 tape.seek(-tape.getSize()) -- back to start again
66
67 tape.setSpeed(songID.speed)
68 while tape.getState() ~= "STOPPED" do
69 sleep(1)
70 end
71 tape.play()
72end
73
74local function update()
75 local s = shell.getRunningProgram()
76 handle = http.get("https://raw.githubusercontent.com/RubenHetKonijn/musicify/main/musicify.lua")
77 if not handle then
78 print("Could not download new version, Please update manually.")
79 else
80 data = handle.readAll()
81 local f = fs.open(s, "w")
82 handle.close()
83 f.write(data)
84 f.close()
85 shell.run(s)
86 return
87 end
88end
89
90if version < index.latestVersion then
91 print("Client outdated, Updating Musicify.") -- Update check
92 update()
93 return
94end
95
96musicify.help = function (arguments)
97 print([[
98Usage: <action> [arguments]
99Actions:
100musicify
101 help -- Displays this message
102 list -- Displays a list of song you can play
103 play <id> -- Plays the specified song by it's ID
104 shuffle [from] [to] -- Starts shuffle mode in the specified range
105 stop -- Stops playback
106 Update -- Updates musicify
107]])
108end
109
110musicify.update = function (arguments)
111 print("Updating musicify, please hold on.")
112 update()
113end
114
115musicify.stop = function (arguments)
116 print("Stopping.")
117 tape.stop()
118end
119
120musicify.list = function (arguments)
121 print("Format: `ID | Author - Name")
122 for i in pairs(index.songs) do
123 print(i .. " | " .. index.songs[i].author .. " - " .. index.songs[i].name)
124 end
125 print("(Use Mildly Better Shell if you want to scroll through the list!)")
126end
127
128musicify.shuffle = function (arguments)
129 local from = arguments[1] or 1
130 local to = arguments[2] or #index.songs
131 if tostring(arguments[1]) and not tonumber(arguments[1]) and arguments[1] then
132 print("Please specify arguments like `musicify shuffle 1 5`")
133 return
134 end
135 while true do
136 print("Currently in shuffle mode, press <CTRL>+T to exit. Use <Enter> to skip songs")
137 local ranNum = math.random(from, to)
138 play(index.songs[ranNum])
139
140 -- Wait till the end of the song
141
142 local function songLengthWait()
143 sleep(index.songs[ranNum].time)
144 end
145
146 local function keyboardWait()
147 while true do
148 local event, key = os.pullEvent("key")
149 if key == keys.enter then
150 print("Skipping!")
151 break
152 end
153 end
154 end
155
156 parallel.waitForAny(songLengthWait,keyboardWait)
157 end
158end
159
160musicify.volume = function (arguments)
161 if not arguments[1] or not tonumber(arguments[1]) or tonumber(arguments[1])>100 or tonumber(arguments[1]) < 1 then
162 print("Please specify a valid volume level between 0-100")
163 return
164 end
165 tape.setVolume(arguments[1] / 100)
166end
167
168musicify.play = function (arguments)
169 if not arguments then
170 print("Resuming playback...")
171 return
172 end
173 if not tonumber(arguments[1]) or not index.songs[tonumber(arguments[1])] then
174 print("Please provide a valid track ID. Use `list` to see all valid track numbers.")
175 return
176 end
177 if not tape.isReady() then
178 print("ERROR: You need to have a tape in the tape drive")
179 return
180 end
181 play(index.songs[tonumber(arguments[1])])
182 tape.play()
183end
184
185musicify.info = function (arguments)
186 print("Current version: " .. version)
187 print("Latest version: " .. index.latestVersion)
188end
189
190musicify.loop = function (arguments)
191 if tostring(arguments[1]) and not tonumber(arguments[1]) then
192 print("ERROR: Please specify a song ID")
193 return
194 end
195 while true do
196 play(index.songs[tonumber(arguments[1])])
197 sleep(index.songs[tonumber(arguments[1])].time)
198 end
199end
200
201command = table.remove(args, 1)
202
203if command == "musicify" then
204 return musify
205elseif not command then
206 -- print("Please provide a valid command. For usage, use `musicify help`.")
207else
208 musicify[command](args)
209end
210
211-- VISUAL LAYER --
212
213local function checkInput()
214 local event, key = os.pullEvent("key")
215
216 if key == 208 and selection < #index.songs then
217 if selection - scroll >= screenHeight -3 then
218 scroll = scroll +1
219 end
220
221 selection = selection +1
222 elseif key == 200 and selection > 0 then
223 if selection - scroll <= 1 and scroll > 0 then
224 scroll = scroll -1
225 end
226
227 selection = selection -1
228 elseif key == 28 then
229 play(index.songs[selection])
230 currentSong = selection
231 end
232end
233
234local function drawHeader()
235 term.setBackgroundColor(colors.black)
236 term.setTextColor(colors.green)
237 term.clear()
238 term.setCursorPos((screenWidth / 2) - (string.len(applicationName) / 2),1)
239
240 print(applicationName)
241end
242
243local function drawMusicList()
244 term.setBackgroundColor(colors.black)
245 term.setTextColor(colors.yellow)
246
247 term.write("Track")
248 term.setCursorPos(screenWidth / 2 - 14, 2)
249 term.write("name")
250 term.setCursorPos(screenWidth / 2 + 6, 2)
251 term.write("Author")
252
253 term.setTextColor(colors.white)
254
255 for i in pairs(index.songs) do
256 if i < screenHeight -2 then
257 term.setCursorPos(1, i +2)
258
259 -- Change the color of the selectoins
260 if selection - scroll == i then
261 term.setBackgroundColor(colors.blue)
262 elseif i + scroll == currentSong then
263 term.setBackgroundColor(colors.green)
264 else
265 term.setBackgroundColor(colors.black)
266 end
267
268 -- if string.len(index.songs[i + scroll].name) < screenWidth then
269 term.write(i + scroll)
270 term.setCursorPos(screenWidth / 2 - 14, i + 2)
271 term.write(index.songs[i + scroll].name)
272 term.setCursorPos(screenWidth / 2 + 6, i + 2)
273 term.write(index.songs[i + scroll].author)
274 -- else
275 -- term.write(string.sub(index.songs[i + scroll].name, 0, screenWidth -4) .. '...')
276 -- end
277 end
278 end
279end
280
281local function drawFooter()
282 term.setBackgroundColor(colors.green)
283 term.setTextColor(colors.black)
284
285 term.setCursorPos(1, screenHeight)
286 term.setBackgroundColor(colors.white)
287
288 -- If this is somehow possible with the tape mod api
289 if currentSong == 0 then
290 term.write("Play")
291 else
292 term.write("Stop")
293 end
294
295 term.setCursorPos(screenWidth / 2 - 4, screenHeight)
296
297 term.write("Shuffle")
298end
299
300local function drawGUI()
301 while true do
302 drawHeader()
303 drawMusicList()
304 drawFooter()
305 checkInput()
306 end
307end
308
309drawGUI()