feat(liquidsoap): deck-shuffle playlist with peek-ahead

This commit is contained in:
devilreef 2026-04-30 14:56:38 +06:00
parent f6ce00a6b1
commit fcb783ffca
Signed by: devilreef
SSH key fingerprint: SHA256:UZisRr4iuXx+IhkbZnR655L2RWAT6o2rgbGv5F/6m3Y

View file

@ -6,6 +6,46 @@ settings.log.level.set(3)
source_pw = environment.get(default="", "SOURCE_PW")
# deck-shuffle: full shuffle once, hand out in order, reshuffle on exhaustion.
# returns a record with .source (request.dynamic) and .peek (returns next N filenames).
def make_deck(dir) =
files = ref([])
cursor = ref(0)
def reload_and_shuffle() =
files := list.shuffle(file.ls(dir, recursive=true, absolute=true))
cursor := 0
end
def next_file() =
if !cursor >= list.length(!files) then reload_and_shuffle() end
f = list.nth(default="", !files, !cursor)
cursor := !cursor + 1
f
end
def next_request() =
f = next_file()
if f == "" then null() else request.create(f) end
end
def peek(n) =
needed = !cursor + n
if needed > list.length(!files) and list.length(!files) > 0 then
# would exhaust the deck during peek; not worth pre-reshuffling.
# return whatever's left, the caller pads.
()
end
list.init(
min(n, list.length(!files) - !cursor),
fun(i) -> list.nth(default="", !files, !cursor + i)
)
end
reload_and_shuffle()
{ source = request.dynamic(next_request), peek = peek }
end
def emit_now_playing(station, m) =
filename = m["filename"]
if filename != "" then
@ -68,13 +108,10 @@ def append_history(station, m) =
end
# === station: minecraft ===
minecraft = playlist(
reload_mode="watch",
mode="randomize",
"/library/minecraft/tracks"
)
minecraft_deck = make_deck("/library/minecraft/tracks")
minecraft = minecraft_deck.source
minecraft.on_track(fun (m) -> begin
emit_now_playing("minecraft", m)
emit_now_playing("minecraft", m, minecraft_deck.peek(4))
append_history("minecraft", m)
end)
minecraft = crossfade(minecraft)