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