local api = {} api.symbols = { audio_controls = { play = "\16", pause = "\19", forward = "\16", backward = "\17", full_back = "\171" }, app_controls = { up = "\30", down = "\31", download = "\25", play = "\16" }, misc = { music = "\15", } } -- Draw a spinner loop at a specified position. Useful for waitForAny. function api.spinner_loop(x, y, spin_monitor) local spin_chars = { "\139", "\138", "\142", "\140", "\141", "\133", "\135", "\131" } local index = 1 while true do spin_monitor.setCursorPos(x, y) spin_monitor.write(spin_chars[index]) index = index + 1 if index > #spin_chars then index = index - #spin_chars end sleep(0.1) end end --[[ Function to create simple progress bars of any length. size - length of the bar in pixels, taken, max - ratio of the bar that should be full. There is an ability to set custom symbols for full and empty pixels, however it is not necessary and by default the program uses '#' and '.' for these ]] function api.make_progressbar(size, taken, max, char_full, char_empty) --[[ Maths behind the function are quite simple: taken/max = x/size taken * size = x * max x = taken * size / max ]] local full_symbol, empty_symbol = char_full or '#', char_empty or '.' size = size - 2 -- make space for "[" and "]" local progress = math.floor(size * taken / max) local hash = (full_symbol):rep(progress) local dots = (empty_symbol):rep(size - progress) return ("[" .. hash .. dots .. "]") end local function seconds_to_string(seconds) -- int to mm:ss local minutes = math.floor(seconds / 60) local seconds = seconds - minutes * 60 return string.format("%02d:%02d", minutes, seconds) end function api.draw_audio_bar(x, y, progress_seconds, track_info, is_paused, monitor) --[[ Example: | Among us soundtrack lol | | [<] [####........[<]............] [>] | | 12:43/14:31 | ]] local x_max, y_max = monitor.getSize() -- Title monitor.setCursorPos(x, y) local title = track_info.title if #title > x_max - 2 then title = title:sub(1, x_max - 4) .. ".." end monitor.write((' '):rep(math.floor((x_max - #title) / 2)) .. title .. (' '):rep(math.ceil((x_max - #title) / 2))) -- Progress bar monitor.setCursorPos(x, y + 1) local progress_bar = api.make_progressbar(x_max - 16, progress_seconds, track_info.length) --monitor.blit(' ' .. seconds_to_string(progress_seconds) .. ' ' .. progress_bar .. ' ' .. seconds_to_string(track_info.length), 'f00000f0' .. ('3'):rep(x_max - 16) .. '0f00000f', ('f'):rep(x_max)) monitor.write(' ' .. seconds_to_string(progress_seconds) .. ' ' .. progress_bar .. ' ' .. seconds_to_string(track_info.length)) -- Controls local controls = { api.symbols.audio_controls.backward, is_paused and api.symbols.audio_controls.play or api.symbols.audio_controls.pause, api.symbols.audio_controls.forward } for i, control in ipairs(controls) do monitor.setCursorPos(x + math.floor((x_max - 11) / 2) + (i - 1) * 4, y + 1) monitor.write('[' .. control .. ']') end end -- Copy of draw_audio_bar, but for when no track is played - just a blank bar. function api.draw_track_list(x, y, audio_catalogue, start_index, height, monitor) height = height or select(2, monitor.getSize()) local x_max, y_max = monitor.getSize() --[[ top bar: "[X] 21:00:01 Tue 12" -button to close the app -time and date bottom bar: "[up_btn] [down_btn] Showing [current_max_index - list_size]-[current_max_index] of [#audio_catalogue] | [REFRESH]" -buttons to go up and down the list -current index and total number of tracks -button to refresh the list list items: "[index] [title] [length] [play_btn] [download_btn]" -index - number of the track in the list -title - title of the track -length - length of the track -play_btn - button to play the track -download_btn - button to download the track (not implemented yet) ]] -- top bar monitor.setCursorPos(x, y) local current_time = os.date("%H:%M:%S %b %d") local exit_btn = "[X]" monitor.blit(' ' .. exit_btn .. ' ' ..current_time, 'f0e0f00000000f000f00', 'ffffffffffffffffffff') -- bottom bar monitor.setCursorPos(x, y + height - 1) local bottom_btns = '[' .. api.symbols.app_controls.up .. '] [' .. api.symbols.app_controls.down .. ']' local showing = 'Showing ' .. tostring(start_index) .. '-' .. tostring(start_index + height - 2) .. ' of ' .. tostring(#audio_catalogue) local refresh_btn = '[REFRESH]' monitor.blit(' ' .. bottom_btns .. ' ' .. showing .. ' | ' .. refresh_btn, 'f0e0f0b0f' .. ('0'):rep(#showing) .. "f0f033333330", ('f'):rep(#bottom_btns + #showing + #refresh_btn + 5)) -- monitor.write(' ' .. bottom_btns .. ' ' .. showing .. ' | ' .. refresh_btn) -- list items -- i should be current_max_index - height - 2 or 1 if current_max_index - height - 2 < 1 for i = start_index, math.min(start_index + height - 2, #audio_catalogue) do if (y + 1 + i >= y + height - 1) or i > #audio_catalogue then break end local track = audio_catalogue[i] local index = tostring(i) local title = track.title local length = seconds_to_string(track.length) local play_btn = api.symbols.audio_controls.play local download_btn = api.symbols.app_controls.download local list_item = ' ' .. index .. ' ' .. title .. ' ' .. length .. ' ' .. play_btn .. ' ' .. download_btn monitor.setCursorPos(x, y + 1 + i) monitor.write(list_item) end end return api