167 lines
5.9 KiB
Lua
167 lines
5.9 KiB
Lua
|
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
|