From 32fae3dbbae715c4c6c69a879c9780f23efe2490 Mon Sep 17 00:00:00 2001 From: Pierre-Olivier Mercier Date: Fri, 3 Jul 2026 12:45:57 +0800 Subject: [PATCH] stream: play a scheduled jingle right after key times of day Adds special jingle folders (midi, gouter, bisous) that take priority over the default jingle rotation once per day, briefly after 11h00, 15h00, 16h30 and 21h00. Co-Authored-By: Claude Opus 4.8 --- stream/radio.liq | 60 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/stream/radio.liq b/stream/radio.liq index 5efec84..a738352 100644 --- a/stream/radio.liq +++ b/stream/radio.liq @@ -78,10 +78,64 @@ music = fallback(track_sensitive=true, [main, backup]) # reload_mode="watch" : un jingle ajouté/retiré est pris en compte à chaud. # Dossier vide → source jamais prête → le switch retombe simplement sur la # musique, sans jingle et sans plantage. +# file.ls (utilisé en interne par playlist pour lister un dossier) n'est pas +# récursif par défaut : les sous-dossiers spéciaux ci-dessous n'entrent donc +# pas dans la rotation par défaut. jingles = playlist( mode="randomize", reload_mode="watch", check_next=audio_only, "/jingles" ) +# Jingles spéciaux, joués une seule fois juste après une heure donnée (au +# prochain jingle qui suit ce moment), plutôt que le jingle par défaut. +jingles_midi = playlist( + mode="randomize", reload_mode="watch", check_next=audio_only, "/jingles/midi" +) +jingles_gouter = playlist( + mode="randomize", reload_mode="watch", check_next=audio_only, "/jingles/gouter" +) +jingles_moment = playlist( + mode="randomize", reload_mode="watch", check_next=audio_only, "/jingles/moment" +) + +# Fenêtre (en minutes) après l'heure cible pendant laquelle le jingle spécial +# reste éligible : assez courte pour rester "juste après", assez large pour +# laisser passer au moins une occasion de jingle (toutes les ~2 chansons). +special_jingle_window = 10 + +# Identifiant du jour courant (année * 366 + jour de l'année), pour ne +# déclencher chaque créneau spécial qu'une seule fois par jour. +def day_key() = + t = time.local() + t.year * 1000 + t.year_day +end + +# Construit un couple (prédicat, source) pour le switch : le prédicat devient +# vrai une seule fois par jour, à partir de hour:minute et pendant +# special_jingle_window minutes. +def make_special_slot(hour, minute, jingle_source) = + last_day = ref(-1) + slot_minutes = hour * 60 + minute + def due() = + t = time.local() + now_minutes = t.hour * 60 + t.min + in_window = now_minutes >= slot_minutes and now_minutes < slot_minutes + special_jingle_window + if in_window and last_day() != day_key() then + last_day := day_key() + true + else + false + end + end + (due, jingle_source) +end + +special_jingle_slots = [ + make_special_slot(11, 0, jingles_midi), + make_special_slot(15, 0, jingles_bisous), + make_special_slot(16, 30, jingles_gouter), + make_special_slot(21, 0, jingles_bisous), +] + # On compte les morceaux de musique réellement diffusés : on_track ne se # déclenche que sur la source effectivement tirée par le switch (les sources # non sélectionnées ne sont pas consommées), donc les jingles ne comptent pas. @@ -101,10 +155,12 @@ end # switch track_sensitive : la décision est prise aux frontières de morceaux, on # ne coupe donc jamais un titre. Si les jingles ne sont pas prêts (dossier vide), -# le switch enchaîne directement sur la musique. +# le switch enchaîne directement sur la musique. Les créneaux spéciaux sont +# testés en premier : un jingle "juste après" une heure donnée prend le pas sur +# le cycle normal des 2 chansons, une seule fois par jour. radio = switch( track_sensitive=true, - [(time_for_jingle, jingles), ({true}, music)] + list.append(special_jingle_slots, [(time_for_jingle, jingles), ({true}, music)]) ) # Transition douce entre les morceaux : fondu enchaîné de 3 s. La fin du