Skip to content

v0.17.2

Choose a tag to compare

@github-actions github-actions released this 25 Oct 14:58
· 63 commits to main since this release
75553c6

Upgrade note: a lighting show with an invalid color: or level value now fails to parse instead
of silently dropping it (#538). Run validate_lighting over your shows before upgrading.

Fixed

  • Quieter lint on padding cues and beat-rounded endings (#541): replace-overlap no longer
    reports a later effect that restates the one it overlaps -- the same effect with the same
    parameters, not fading in -- since nothing changes on stage; padding and anchor cues were most of
    that warning's output on real shows. past-end-of-song now lets an effect run up to one engine
    frame (25ms) past the audio before reporting it, so a last effect sized in beats that ends a few
    milliseconds late is not flagged.
  • An invalid color is a parse error, not silently dropped (#538): a color: value that did
    not parse was discarded without a word -- a static set no colour and rendered as if it were not
    there, a cycle ran on its other colours -- and validate_lighting reported the show clean. It
    is now a parse error naming the value. The same goes for a level that is not a number or a
    percentage (dimmer/intensity and colour channels on static, pulse levels, dimmer start
    and end, rainbow saturation and brightness), which used to leave the effect at its default.
    Every effect parse error now also names its line.
  • An effect lasts to its own end, not a microsecond short (#536): an effect was retired once
    it was within a microsecond of its end, so one ending on the downbeat the next cue starts on left
    the rig dark for that microsecond, and evaluate_show reported dark there while the effect's own
    duration said it was still running. Effects now end exactly at their end.
  • Back-to-back steps meet exactly; no nanosecond dark windows (#534): an effect lasting to
    the next downbeat ended at its rounded start plus its rounded length, a nanosecond off the next
    cue, and looped sequences crept a nanosecond later every pass. analyze_show reported each gap
    as a dark window -- 37 in Battle Scarred, about 200 across the Isenmor set -- burying any real
    one. Beat durations are now positions, like measure durations, snapped to a millionth of a beat
    so the end lands exactly on the next cue; loop lengths are snapped the same way. analyze_show
    and the replace-overlap lint ignore anything shorter than a millisecond.
  • A random chase is random on every lap (#532): pattern: random shuffled the fixtures once
    per effect and repeated that order on every lap, so the same brick lit on the same beat every
    bar -- a fixed loop, not a sparkle. Each lap is now a fresh shuffle, seeded by the cue time and
    the lap so a given moment always renders the same way, and a lap never starts on the fixture the
    previous one ended on.
  • hold_time in measures is as long as duration in measures: a hold_time counted
    "playback measures" on its own path, stepping through tempo changes at their unshifted bars and
    ignoring gradual transitions, so in an offset show or a ramp it disagreed with the same length
    written as duration and with the cue grid. It is now resolved exactly as duration is.
  • Durations inside a sequence follow the tempo the sequence plays at (#529): a sequence's cue
    times were rescaled to the tempo where it is expanded, but its effects' beats / measures
    durations stayed resolved at the tempo the sequence was parsed at. In Esaweg (110 BPM at the top,
    sequences played at 160) the verse's 8measures chases lasted 17.4 s instead of 12 s and
    overlapped the next half, and half-beat flashes ran 40% long. Musical durations are now kept as
    written and resolved again when the sequence is expanded, at the expanded cue's time and offset;
    durations in seconds are left as they are.
  • A measure-long effect inside a tempo ramp lasts the whole bar (#526): measures durations
    were integrated as step changes, ignoring gradual transitions, so duration: 1measure on the
    downbeat of a ritardando bar ended at the pre-ramp tempo -- 0.6 s short in Jotunheim, a blackout
    before the final chord -- while the next bar's cue fired where the ramp put it. A measure
    duration is now the measure position at its start plus the count, converted back through the
    same walk cue positions use, so durations and cue times agree inside ramps.
  • offset shifts the tempo that beats / measures speeds run at (#525): an offset N measures moved cue times, but the engine read tempo-aware speeds and frequencies against the
    unshifted tempo map, so a beat-based chase changed tempo N measures early -- Esaweg's chase ran
    at 160 for a bar before the music did. Each effect now carries its cue's offset, and its rate is
    read against the tempo map shifted by it. A beats / measures rate is also taken from the tempo
    at the instant rather than the length of the next N beats, which blended in an upcoming tempo
    change for N beats before it.
  • A profile update no longer wipes the sections it does not mention (#523): a whole-profile
    update -- MCP and gRPC update_profile, and the web UI's profile saves -- deserialized the body
    on its own, so every section it left out came back empty. Adding a controller that way wrote
    trigger: ~, status_events: ~ and notifications: ~, and the audio trigger silently
    stopped. A section the body omits now keeps its current value and one sent as null is
    removed; the web UI sends null when a section or the hostname is removed. A profile update
    that empties a populated section is logged as a warning.
  • A strobe no longer keeps strobing after it ends: the engine only wrote the channels an
    effect drove that frame, and DMX holds whatever it was last sent, so when a hardware strobe
    expired, was cleared, or was cut off by the next song, the fixture's strobe channel stayed at
    its last rate. The next look strobed in hardware until something drove the strobe again — an
    Esaweg ending at 10 Hz strobed straight through the gap and into the following song. A strobe
    channel driven on one frame and not the next is now sent off.
  • write_song_lighting puts every new show under lighting/ (#516): a song with an old,
    unreferenced show.light beside its song.yaml had the new show written over that stray at
    the song root, while every other new show went to <song>/lighting/. An unreferenced
    root-level file in a directory-layout song is no longer reused; referenced files, drafts under
    lighting/, and the flat-layout pre-created file still are.
  • 12/8 click tracks report the tempo the show is written in (#515): song_details counted
    one beat per click, so a 12/8 song clicked on the dotted quarter reported 112 for a 169 tempo
    block, and a bar of eighth clicks showed up as its own 240 BPM segment. When the song or one of
    its shows declares a meter, each bar's clicks are now read against that bar's length, giving
    quarter-note BPM (bpm_unit: "quarter"; "click" when there is no meter to read against). A
    short, jittery stretch at a section change is folded into the neighbour whose tempo it is
    nearer rather than the longer one, so the change is reported on the bar it happens.
  • A fading replace static crossfades with the bed instead of dipping to black (#521): an
    up_time / down_time on a replace static scaled the static's own colour toward zero and
    then replaced the layers beneath with it, so a lift over a coloured bed went bed → black →
    colour → black → bed. A partial replace now moves from the value beneath toward its colour by
    the fade amount; over nothing it still fades from black, and screen / multiply / add /
    overlay statics fade their own contribution as before.
  • A chase lifts the bed instead of blacking it out when the blend says so (#518): on an
    RGB-only fixture the chase wrote its mask into a multiplier whatever the blend_mode, so a
    screen, add or overlay chase lit one fixture and sent every other one to zero — the
    documented pass-through never happened. The lifting modes now write the mask into the colour
    channels: the active fixture brightens toward white, the inactive ones keep the bed. multiply
    and replace still gate (the classic running light). overlay is treated as screen, since
    with a zero mask it would darken a dim bed, which no chase means.
  • A looping song's lights no longer thrash after the first pass (#517): the DMX loop restarted
    its timeline the moment the last cue fired and measured song time from a clock that kept
    counting across passes, so a show whose cues sit near the top restarted ~40 times a second
    from the loop point on. Passes now restart on the audio's own boundaries and count song time
    from their start.
  • repeats: N followed by a comment parses (#514): the number rule admitted implicit
    whitespace, which includes comments, so the comment became part of the count.
  • Writing a file another user owns no longer fails on the mode (#513): the in-place rewrite
    re-applied the destination's own mode, which fchmod refuses to a non-owner. The mode is left
    alone when it already matches, and a refused change is logged rather than failing the write.
  • Named playlists resolve without playlists_dir (#512): read_playlist and
    write_playlist with a name now default to playlists/ beside the config, as the loader
    already did, instead of refusing.