From a65cc61ccd9f6be4306c251f9e13ed0d6f79920e 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 | 66 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/stream/radio.liq b/stream/radio.liq index 5efec84..3f4ab38 100644 --- a/stream/radio.liq +++ b/stream/radio.liq @@ -78,10 +78,68 @@ 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. +# ATTENTION : playlist explore récursivement les sous-dossiers. Pour la rotation +# par défaut on ne veut QUE les fichiers directement dans /jingles ; les +# sous-dossiers spéciaux (midi, gouter, moment) sont gérés à part. On +# filtre donc sur le dossier parent en plus du test audio habituel. +def jingle_top_level(r) = + audio_only(r) and path.dirname(request.uri(r)) == "/jingles" +end jingles = playlist( - mode="randomize", reload_mode="watch", check_next=audio_only, "/jingles" + mode="randomize", reload_mode="watch", check_next=jingle_top_level, "/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_moment), + make_special_slot(16, 30, jingles_gouter), + make_special_slot(21, 0, jingles_moment), +] + # 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 +159,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