feat(liquidsoap): emit cover_path + up_next in now-playing json

also fix path.extension -> file.extension (path module has no .extension in 2.3.3)
This commit is contained in:
devilreef 2026-04-30 15:04:25 +06:00
parent 68a02ff250
commit 83df3b4602
Signed by: devilreef
SSH key fingerprint: SHA256:UZisRr4iuXx+IhkbZnR655L2RWAT6o2rgbGv5F/6m3Y

View file

@ -17,7 +17,7 @@ def make_deck(dir) =
all = file.ls(dir, recursive=true, absolute=true)
audio_exts = ["flac", "mp3", "opus", "m4a", "wav", "ogg"]
audio = list.filter(
fun(f) -> list.mem(string.case(lower=true, path.extension(leading_dot=false, f)), audio_exts),
fun(f) -> list.mem(string.case(lower=true, file.extension(leading_dot=false, f)), audio_exts),
all
)
files := list.shuffle(audio)
@ -56,20 +56,55 @@ def make_deck(dir) =
{ source = request.dynamic(next_request), peek = peek }
end
def emit_now_playing(station, m) =
# walk up from the audio file to find cover.{jpg,png,webp}.
# falls back to <station>/cover.* (one level above tracks/).
def cover_for(filename) =
def find_in(dir) =
candidates = ["#{dir}/cover.jpg", "#{dir}/cover.png", "#{dir}/cover.webp"]
list.fold(
fun(found, c) -> if found == "" and file.exists(c) then c else found end,
"",
candidates
)
end
album_dir = path.dirname(filename)
c1 = find_in(album_dir)
if c1 != "" then c1 else
tracks_dir = path.dirname(album_dir)
station_root = path.dirname(tracks_dir)
find_in(station_root)
end
end
# build a json object for one upcoming track from its filename.
# reads tags via request.metadata; uses request.duration for length.
def track_meta_json(filename) =
r = request.create(filename)
ignore(request.resolve(r))
m = request.metadata(r)
request.destroy(r)
d = null.get(default=-1., request.duration(filename))
obj = json()
obj.add("title", m["title"])
obj.add("artist", m["artist"])
obj.add("album", m["album"])
obj.add("duration", if d > 0. then string(int_of_float(d)) else "" end)
obj.add("cover_path", cover_for(filename))
obj
end
def emit_now_playing(station, m, upcoming) =
filename = m["filename"]
if filename != "" then
# decoder-reported metadata may be empty; fall back to request.duration which
# reads it directly from the file. -1.0 means unknown.
meta_dur = m["duration"]
dur_str =
if meta_dur != "" then
meta_dur
else
# request.duration returns float? in liquidsoap 2.3 — unwrap with default -1.
d = null.get(default=-1., request.duration(filename))
if d > 0. then string(int_of_float(d)) else "" end
end
payload = json()
payload.add("station", station)
payload.add("artist", m["artist"])
@ -78,7 +113,17 @@ def emit_now_playing(station, m) =
payload.add("filename", filename)
payload.add("duration", dur_str)
payload.add("started_at", string(int_of_float(time())))
file.write(data=payload.stringify(), atomic=true, temp_dir="/now-playing", "/now-playing/#{station}.json")
payload.add("cover_path", cover_for(filename))
up_arr = list.map(track_meta_json, upcoming)
payload.add("up_next", up_arr)
file.write(
data=payload.stringify(),
atomic=true,
temp_dir="/now-playing",
"/now-playing/#{station}.json"
)
end
end