initialize
This commit is contained in:
commit
5b23ea99fd
43 changed files with 2336 additions and 0 deletions
98
MusicPlayer/Server/audio_manager.lua
Normal file
98
MusicPlayer/Server/audio_manager.lua
Normal file
|
@ -0,0 +1,98 @@
|
|||
--[[
|
||||
Class to manage ComputerCraft (CC) audio tracks on different disks
|
||||
|
||||
Written by Andrew_7_1
|
||||
]]
|
||||
|
||||
local audio_manager = {}
|
||||
audio_manager.init = function (dirs_file)
|
||||
local self = {}
|
||||
|
||||
-- Load audio directories from file where directories are seperated by newlines"
|
||||
local function load_audio_dirs(file_location)
|
||||
local audio_dirs = {}
|
||||
local file = io.open(file_location, 'r')
|
||||
if file then
|
||||
for line in file:lines() do
|
||||
table.insert(audio_dirs, line)
|
||||
end
|
||||
file:close()
|
||||
end
|
||||
return audio_dirs
|
||||
end
|
||||
local audio_dirs = load_audio_dirs(dirs_file or 'audio_dirs.txt')
|
||||
|
||||
--[[
|
||||
Iterate over all audio directories and load all audio files into a catalogue.
|
||||
Audio files have extensions of .dfpwm and rarely .wav
|
||||
Save them to a table of tables like this:
|
||||
{
|
||||
["filepath"] = absolute file path
|
||||
["length"] = file size / 6000
|
||||
["title"] = file name without extension and path, e.g. "title.dfpwm" -> "title"
|
||||
["extension"] = file extension, e.g. "dfpwm"
|
||||
}
|
||||
]]
|
||||
local function load_audio_catalogue()
|
||||
local audio_catalogue = {}
|
||||
for _, dir in pairs(audio_dirs) do
|
||||
for _, file in pairs(fs.list(dir)) do
|
||||
if file:find('.dfpwm') or file:find('.wav') then
|
||||
local file_path = dir .. '/' .. file
|
||||
local file_size = fs.getSize(file_path)
|
||||
local file_title = file:sub(1, #file - #file:match('.*%.(.*)$'))
|
||||
local file_extension = file:match('.*%.(.*)$')
|
||||
table.insert(audio_catalogue, {
|
||||
["filepath"] = file_path,
|
||||
["length"] = file_size / 6000,
|
||||
["title"] = file_title,
|
||||
["extension"] = file_extension
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
return audio_catalogue
|
||||
end
|
||||
self.audio_catalogue = load_audio_catalogue()
|
||||
|
||||
-- Update audio catalogue
|
||||
function self.update_catalogue()
|
||||
self.audio_catalogue = load_audio_catalogue()
|
||||
end
|
||||
|
||||
function self.get_catalogue()
|
||||
return self.audio_catalogue
|
||||
end
|
||||
|
||||
|
||||
-- Get part of an audio file in the catalogue
|
||||
function self.get_track_chunk(index, starting_second, length)
|
||||
if index > #self.audio_catalogue then
|
||||
return false
|
||||
end
|
||||
local track = self.audio_catalogue[index]
|
||||
|
||||
local file = io.open(track.filepath, 'rb')
|
||||
if not file then
|
||||
return false
|
||||
end
|
||||
|
||||
file:seek('set', starting_second * 6000)
|
||||
local chunk = file:read(length * 6000)
|
||||
file:close()
|
||||
|
||||
return chunk
|
||||
end
|
||||
|
||||
-- More convenient way to get track info than using entire catalogue
|
||||
function self.get_track_details(index)
|
||||
if index > #self.audio_catalogue then
|
||||
return false
|
||||
end
|
||||
return self.audio_catalogue[index]
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
return audio_manager
|
60
MusicPlayer/Server/logger.lua
Normal file
60
MusicPlayer/Server/logger.lua
Normal file
|
@ -0,0 +1,60 @@
|
|||
|
||||
|
||||
local logger = {}
|
||||
logger.init = function(monitor_wrap, scale)
|
||||
local self = {}
|
||||
|
||||
local monitor = monitor_wrap or peripheral.find("monitor")
|
||||
if not monitor then
|
||||
monitor = term
|
||||
else monitor.setTextScale(scale or 0.5)
|
||||
end
|
||||
local log_colours = {
|
||||
['log'] = colours.white,
|
||||
['info'] = colours.lightBlue,
|
||||
['warn'] = colours.yellow,
|
||||
['err'] = colours.red,
|
||||
['success'] = colours.lime
|
||||
}
|
||||
|
||||
local function move_line()
|
||||
monitor.setCursorPos(1, select(2, monitor.getCursorPos()) + 1)
|
||||
if select(2, monitor.getCursorPos()) >= select(2, monitor.getSize()) then
|
||||
monitor.scroll(1)
|
||||
monitor.setCursorPos(1, select(2, monitor.getCursorPos()) - 1)
|
||||
end
|
||||
end
|
||||
|
||||
local function write_msg(message, msg_colour)
|
||||
local time_str = os.date('%Y-%b-%d %H:%M:%S')
|
||||
local msg_formatted = "[" .. time_str .. "] " .. message
|
||||
|
||||
monitor.setTextColour(msg_colour)
|
||||
monitor.write(msg_formatted)
|
||||
move_line()
|
||||
end
|
||||
|
||||
function self.log(msg)
|
||||
write_msg(msg, log_colours['log'])
|
||||
end
|
||||
|
||||
function self.info(msg)
|
||||
write_msg('INFO: ' .. msg, log_colours['info'])
|
||||
end
|
||||
|
||||
function self.warning(msg)
|
||||
write_msg('WARNING: ' .. msg, log_colours['warn'])
|
||||
end
|
||||
|
||||
function self.error(msg)
|
||||
write_msg('ERROR: ' .. msg, log_colours['err'])
|
||||
end
|
||||
|
||||
function self.success(msg)
|
||||
write_msg('SUCCESS: ' .. msg, log_colours['success'])
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
return logger
|
60
MusicPlayer/Server/server.lua
Normal file
60
MusicPlayer/Server/server.lua
Normal file
|
@ -0,0 +1,60 @@
|
|||
--[[
|
||||
Audio server for ComputerCraft (CC)
|
||||
|
||||
Written by Andrew_7_1
|
||||
]]
|
||||
|
||||
local server = {}
|
||||
server.init = function (port, audio_dir)
|
||||
local self = {}
|
||||
|
||||
local logger = require('logger').init()
|
||||
local audio_manager = require('audio_manager').init(audio_dir or 'audio_dirs.txt')
|
||||
|
||||
local port = port or 7101
|
||||
local modem = peripheral.find('modem')
|
||||
if not modem then error('No modem found') end
|
||||
modem.open(port)
|
||||
logger.info('Audio server started on port ' .. port .. ' with audio directories from ' .. audio_dir)
|
||||
|
||||
local message_types = {
|
||||
query = function (replyChannel, msg)
|
||||
modem.transmit(replyChannel, port, {code = 200, audio_catalogue = audio_manager.get_catalogue()})
|
||||
logger.success('Query sent')
|
||||
end,
|
||||
refresh = function (replyChannel, msg)
|
||||
audio_manager.update_catalogue()
|
||||
modem.transmit(replyChannel, port, {code = 200})
|
||||
logger.success('Catalogue updated')
|
||||
end,
|
||||
|
||||
track_info = function (replyChannel, msg)
|
||||
local track = audio_manager.get_track_details(msg.index)
|
||||
if not track then
|
||||
modem.transmit(replyChannel, port, {code = 404})
|
||||
logger.error('Track not found (id: ' .. msg.index .. ')')
|
||||
else
|
||||
modem.transmit(replyChannel, port, {code = 200, track = track})
|
||||
logger.success('Track details sent (id: ' .. msg.index .. ')')
|
||||
end
|
||||
end,
|
||||
track_chunk = function (replyChannel, msg)
|
||||
local track = audio_manager.get_track_chunk(msg.index, msg.starting_second, msg.length)
|
||||
if not track then
|
||||
modem.transmit(replyChannel, port, {code = 404})
|
||||
logger.error('Track not found (id: ' .. msg.index .. ')')
|
||||
else
|
||||
modem.transmit(replyChannel, port, {code = 200, track = track})
|
||||
logger.success('Part of a track sent (id: ' .. msg.index .. ', part:' .. msg.starting_second .. '-' .. msg.starting_second + msg.length .. ')')
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
function self.process_transmission(event, side, channel, replyChannel, message, distance)
|
||||
message_types[message.type](replyChannel, message)
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
return server
|
14
MusicPlayer/Server/startup.lua
Normal file
14
MusicPlayer/Server/startup.lua
Normal file
|
@ -0,0 +1,14 @@
|
|||
local config = {
|
||||
port = 7101,
|
||||
audio_dir = 'audio_dirs.txt'
|
||||
}
|
||||
|
||||
local server = require("server").init(config.port, config.audio_dir)
|
||||
local modem = peripheral.find("modem")
|
||||
if not modem then error("No modem found") end
|
||||
modem.open(config.port)
|
||||
|
||||
while true do
|
||||
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
||||
server.process_transmission(event, side, channel, replyChannel, message, distance)
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue