mirror of
https://github.com/got-feedBack/feedBack.git
synced 2026-08-10 18:59:56 +00:00
feat(core): consume song_timeline tempos + time_signatures + per-chart tempos (feedpak 1.2.0) (#529)
feedpak 1.2.0 added song-level `tempos` + `time_signatures` to song_timeline.json
and a per-chart `tempos` override on arrangements (§6.10). Core stored the raw
song_timeline dict but never consumed the maps, and didn't read per-chart tempos.
- song.py: shared `sanitize_tempos([{time,bpm}])` (finite non-bool time, finite
bpm>0, sorted); `Arrangement.tempos` field wired through arrangement_to_wire
(omitted when None/empty per §6.10) / arrangement_from_wire.
- sloppak.py: `_sanitize_time_signatures([{time,ts:[num,den]}])`;
LoadedSloppak.tempos / .time_signatures, loaded from song_timeline.json
INDEPENDENTLY of beats/sections (all are optional in 1.2.0).
- server.py: stream `tempos` + `time_signatures` highway-WS messages; the active
arrangement's per-chart `tempos` overrides the song-level map for that chart.
Renderer/UI surfacing is a thin follow-up; this lands the data plumbing.
Codex-reviewed: clean (no findings). +9 tests (sanitizers, per-chart wire
round-trip + omit-when-absent, song-level load/sanitize/absent + maps-without-
beats). 90 song/sloppak tests pass. (Pre-existing unrelated failure:
test_diagnostics_redact, fails on clean main too.)
Closes #526. Part of got-feedback/feedback#334.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
e64378da78
commit
587fbbea81
@@ -7032,6 +7032,20 @@ async def highway_ws(websocket: WebSocket, filename: str, arrangement: int = -1,
|
||||
"data": loaded_slop.keys.get("events") or [],
|
||||
})
|
||||
|
||||
# Song-level tempo + time-signature maps (song_timeline, feedpak 1.2.0),
|
||||
# plus the per-chart tempo override (§6.10): the active arrangement's own
|
||||
# `tempos` wins over the song-level map for this chart. Both are
|
||||
# pre-sanitized by the loader / arrangement_from_wire, so they stream
|
||||
# directly. Consumers read these rather than the file.
|
||||
_song_tempos = loaded_slop.tempos if (is_slop and loaded_slop is not None) else None
|
||||
_tempos_out = getattr(arr, "tempos", None) or _song_tempos
|
||||
if _tempos_out:
|
||||
await websocket.send_json({"type": "tempos", "data": _tempos_out})
|
||||
_time_sigs = (loaded_slop.time_signatures
|
||||
if (is_slop and loaded_slop is not None) else None)
|
||||
if _time_sigs:
|
||||
await websocket.send_json({"type": "time_signatures", "data": _time_sigs})
|
||||
|
||||
# Send notation data when the sloppak ships it for the active arrangement.
|
||||
# Slots after sections (cursor sync depends on beats, which precede sections)
|
||||
# and before anchors — per docs/sloppak-spec.md §5.3.
|
||||
|
||||
Reference in New Issue
Block a user