63 lines
2.0 KiB
Lua
63 lines
2.0 KiB
Lua
-- libmusic: list and play dfpwm music tracks from a directory.
|
|
--
|
|
-- A factory: `local createMusic = require('/apis/libmusic'); local music = createMusic();`
|
|
--
|
|
-- Non-UI logic lives here so the `music` program stays thin and the listing is
|
|
-- unit-testable with an injected `fs`. Dependencies are injectable to keep the
|
|
-- module testable outside the CC runtime (mirrors libccpm/libversion style).
|
|
|
|
local DEFAULT_DIR = '/musics';
|
|
local EXTENSION = '.dfpwm';
|
|
local CHUNK_SIZE = 16 * 1024;
|
|
|
|
local function createMusic(opts)
|
|
opts = opts or {};
|
|
local fsLib = opts.fs or fs;
|
|
local peripheralLib = opts.peripheral or peripheral;
|
|
local osLib = opts.os or os;
|
|
local ioLib = opts.io or io;
|
|
local dir = opts.dir or DEFAULT_DIR;
|
|
|
|
local api = {};
|
|
|
|
-- Returns a sorted list of `{ name = <display>, path = <full path> }` for every
|
|
-- `.dfpwm` file in the music directory; `{}` when the directory is missing.
|
|
function api.listTracks()
|
|
local tracks = {};
|
|
if not fsLib.isDir(dir) then return tracks; end
|
|
for _, entry in ipairs(fsLib.list(dir)) do
|
|
if entry:sub(-#EXTENSION) == EXTENSION then
|
|
tracks[#tracks + 1] = {
|
|
name = entry:sub(1, #entry - #EXTENSION),
|
|
path = dir .. '/' .. entry,
|
|
};
|
|
end
|
|
end
|
|
table.sort(tracks, function(a, b) return a.name < b.name; end);
|
|
return tracks;
|
|
end
|
|
|
|
-- Plays a dfpwm file through the first speaker peripheral, blocking until the
|
|
-- whole track has been queued and drained. Errors if no speaker is attached.
|
|
function api.play(path)
|
|
local speaker = peripheralLib.find('speaker');
|
|
if not speaker then
|
|
error('no speaker attached', 0);
|
|
end
|
|
|
|
local dfpwm = opts.dfpwm or require('cc.audio.dfpwm');
|
|
local decoder = dfpwm.make_decoder();
|
|
|
|
for chunk in ioLib.lines(path, CHUNK_SIZE) do
|
|
local buffer = decoder(chunk);
|
|
while not speaker.playAudio(buffer) do
|
|
osLib.pullEvent('speaker_audio_empty');
|
|
end
|
|
end
|
|
end
|
|
|
|
return api;
|
|
end
|
|
|
|
return createMusic;
|