From 7fc372f18d03f33a767c7c4f7d257acbb7dfabfa Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Thu, 2 Jul 2026 23:56:32 +0800 Subject: [PATCH] stream: show a history of aired tracks (/history) Co-Authored-By: Claude Opus 4.8 --- stream/index.html | 41 +++++++++++++++++++++++++++++++++++++++-- stream/radio.liq | 25 +++++++++++++++++++++++-- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/stream/index.html b/stream/index.html index 690ed52..bbba469 100644 --- a/stream/index.html +++ b/stream/index.html @@ -51,6 +51,14 @@ } .actions button:hover, .actions a:hover { background: rgba(155,140,255,.3); } .actions button:disabled { opacity: .5; cursor: default; } + .history { margin-top: 1.75rem; text-align: left; } + .history h2 { font-size: .7rem; letter-spacing: .2em; text-transform: uppercase; + color: #7d768f; margin: 0 0 .4rem; font-weight: 600; } + .history ul { list-style: none; margin: 0; padding: 0; } + .history li { padding: .45rem 0; border-top: 1px solid rgba(255,255,255,.06); } + .history .h-title { color: #e8e4f2; font-size: .92rem; } + .history .h-artist { color: #8b849c; font-size: .8rem; margin-top: .1rem; } + .history .empty { color: #6b6480; font-size: .85rem; padding: .45rem 0; } .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; background: #4ade80; margin-right: .4rem; vertical-align: middle; box-shadow: 0 0 0 0 rgba(74,222,128,.6); animation: pulse 2s infinite; } @@ -75,6 +83,10 @@ +
+

Historique

+
    +
    diff --git a/stream/radio.liq b/stream/radio.liq index 6d83aa1..4913280 100644 --- a/stream/radio.liq +++ b/stream/radio.liq @@ -81,9 +81,24 @@ radio = crossfade(duration=3.0, fade_in=3.0, fade_out=3.0, radio) radio = mksafe(radio) # --- Métadonnées « en cours de lecture » ----------------------------------- -# On mémorise les dernières métadonnées vues sur le flux réellement diffusé. +# On mémorise les dernières métadonnées vues sur le flux réellement diffusé, +# ainsi qu'un historique borné des titres passés à l'antenne (le plus récent +# en tête). L'historique reflète ce qui a vraiment été diffusé. now_playing = ref([]) -radio.on_metadata(synchronous=false, fun(m) -> now_playing := m) +history = ref([]) +history_max = 25 +radio.on_metadata( + synchronous=false, + fun(m) -> begin + now_playing := m + entry = {title=m["title"], artist=m["artist"]} + head = list.hd(default={title="", artist=""}, history()) + is_dup = head.title == entry.title and head.artist == entry.artist + if not is_dup and (entry.title != "" or entry.artist != "") then + history := list.prefix(history_max, list.add(entry, history())) + end + end +) # --- Sortie : flux MP3 sur http://:8000/radio.mp3 --- output.harbor( @@ -112,6 +127,12 @@ harbor.http.register( end ) +# Historique des titres passés (le plus récent en tête, morceau courant inclus). +harbor.http.register( + port=8000, method="GET", "/history", + fun(_, resp) -> resp.json(history()) +) + # Passer au morceau suivant : on saute le morceau en cours sur la source # diffusée. request.dynamic a déjà préchargé le suivant, donc l'enchaînement # est immédiat (le prochain /next est demandé au daemon dans la foulée).