Commit Graph
5 Commits
Author SHA1 Message Date
Esa Kataja 8f670cf7db Engrave window: bar numbers, and two silent LilyPond faults
A system can now be given the measure it starts at, in a First bar field
beside key and time. Per slice, since it is the one thing about a
replacement that cannot be inherited from the song. Bar numbering is a
Score property, so it is set once on the first staff, and made visible
only at a line beginning — that vector is fussy: #(#f #t #t) also prints
a number mid-system and #(#f #t #f) prints the second bar's rather than
the first's. It travels in the bundle's engraving object as `bar`.

Two things LilyPond 2.24 was quietly refusing to draw:

`\bar ":|"` and the other old repeat names produce nothing at all — no
error, no warning, exit status 0, just a missing repeat that you find on
the tablet. Every book and forum answer still uses them, so translate
them to the modern spellings.

`\clef treble_8` unquoted is not an octavated clef either. It parses as a
plain treble plus a stray "8" markup that lands under the first note, and
the staff then reads an octave off — a tenor line engraved at soprano
pitch. Quote it.

The source pane, which is where either of those would have been visible,
is now a collapsed section at the bottom rather than a permanent slab. It
uses the panel's own disclosure helper, lifted out of Editor so both can
call it.
2026-07-29 13:44:42 +03:00
Esa Kataja cf1344c5bf Carry a re-engraved slice's notation in the bundle
A replaced slice shipped as pixels only, so the LilyPond behind it died
with the project file — and a project is spent once exported. Correcting
one wrong note meant retyping the system.

Slices gain an optional `engraving` object: the language, key, time and
one entry per voice holding the notes and lyrics verbatim. Structured per
staff rather than one blob of source, because that is what both a later
edit and a MIDI render want; song-level key and time are resolved per
slice so reading one needs no context from its neighbours.

Additive and ignorable, so the format stays at version 1.
2026-07-29 11:42:44 +03:00
Esa Kataja b8d93cee47 Specify the Score Bundle Format, and make tempo an integer
The bundle is documented as a standalone format rather than as a note
between two programs: producers and consumers are generic, the marker
vocabulary is defined musically rather than by what a viewer does with
it, and image properties are stated as guarantees with the reasoning
where it is not obvious. Anything that reads scores can implement it
without knowing this tool exists.

Taking that view changed the substance in three places. Marker types now
carry their musical meaning rather than a UI mapping. The rule against
re-importing became a statement about identity - indices mean something
only within one bundle, so two bundles of a piece are independent
documents. And forward-compatibility rules were added, which a protocol
needs and a handover note did not: ignore unknown fields and marker
types, refuse an unknown version.

Tempo is now an integer, beats per minute, exported as a JSON number and
omitted when blank; the editor accepts digits only. A figure can drive a
metronome or a click track where a verbal marking cannot, and readers do
not agree on what Andante means. This needs the consumer's column
changed from free-form text, which the format document flags.

Every figure in the document comes from a real export.
2026-07-29 09:22:43 +03:00
Esa Kataja 97c8e8a709 Add LilyPond slice replacement with a structured engrave window
Re-engraving is a rescue path for the handful of systems a scan cannot
deliver, so the window is an editing surface rather than an automation
project. Three full-width rows - the scanned system, the render, the
form - because a system is wide and short and the job is comparing one
against the other bar by bar. The render is shown scaled to the scan's
staff height, which is what export does anyway, so it previews the real
thing.

A form rather than a text box. Key and time are slice-level, clef,
notes and lyrics per voice: every staff in a system carries the same key
signature, and Kaipaava proves it across five-staff and two-staff
systems alike. Notes and lyrics stay raw LilyPond, so slurs, dynamics,
tuplets and the laissezVibrer/repeatTie idiom for ties crossing into the
next slice all work untouched.

Notes are entered in \relative mode, referenced to the middle of each
clef's staff, so a part needs no octave marks at all in the common case.

The time signature is used for spacing and bar checks but not printed:
the printed score repeats the key at every system and the time only at
the first, so a re-engraved middle slice showing one would stand out.

Seeded from what can be known reliably. Voice count comes from counting
staves in the slice; key, time and clefs are inherited from the song,
because the slices being re-engraved are the illegible ones and reading
a key signature off them is exactly the measurement that fails. After
the first replacement in a song only the notes need typing.

Staff counting needed two corrections against the corpus: compare gaps
against line spacing rather than staff height, since adjacent staves can
sit closer together than one staff is tall; and require five lines in a
group, since Engel's 'uh______' lyric extenders are long horizontal runs
too and each counted as a staff. Kaipaava now reads 2,2,2,2,5 on page 1,
Ketun 6, Engel 4.

Also in this change:

- Title is required for export, every other metadata field optional,
  enforced in bundle.write so the CLI and the editor both get it. Tempo
  added; noteman already has a free-form column for it.
- The panel is a splitter rather than a fixed width, sections collapse
  under bold grey disclosure headers, and it scrolls.
- A re-engraved slice is washed amber with an ENGRAVED badge, and
  markers get badges too. Thin coloured text was invisible against a
  scan.

Closes #31
Closes #32
Closes #33
Closes #34
2026-07-29 01:29:43 +03:00
Esa Kataja ff1cc6740e Add markers: placement, labels and click-to-pick jump targets
Markers are stored per (page, slot), parallel to the discard flags, so
adding or removing a cut keeps them aligned with their slices. On a
split they stay with the upper half: a marker sits on a printed symbol
and nothing can say which side that symbol landed on, so predictable
beats clever.

Jump targets are chosen by clicking the slice rather than from the
thumbnail strip the plan called for. Less code, and it reads the score
instead of a list of thumbnails - which is what you want when hunting
for the Coda sign. Any page; PageUp/PageDown while picking.

Export resolves (page, slot) to the bundle's array index, the only
cross-reference the format has. A jump whose target was discarded or
re-cut away is dropped rather than exported dangling, since noteman
would have nothing to resolve it to.

tests/test_markers.py covers the enum size - that is the coupling
between two repos - along with cut-edit alignment, index resolution,
the dangling-target drop, and round-trips through both the project file
and a real bundle.

Closes #28
Closes #29
Closes #30
2026-07-29 00:05:48 +03:00