5 Commits
Author SHA1 Message Date
Esa Kataja cdf37302d7 Ask before reopening a bundle that carries no cuts
A bundle without a source block cannot be round-tripped, but its PDF can
still be cut from scratch. Offer that instead of refusing: confirm, run
detection, and line the markers up by position when the slice counts
match exactly.
2026-07-29 15:06:45 +03:00
Esa Kataja 61b8ec8301 Make a bundle reopenable, and number slices
A bundle was a one-way trip. The slice images are output and the cuts
that produced them lived only in the producer's own project file, so a
bundle someone handed you meant cutting the score again from scratch.

The manifest now carries the geometry, in a `source` block: per page the
cut polylines, skew, levels and content rectangle, all in normalised
coordinates so they survive any render resolution, and per slice the page
and slot it came from. Discards are stated by omission — a slot no slice
claims was discarded — since shipping a discarded slice's image would
defeat discarding it.

`noteman-slicer open song.zip` unpacks the archived PDF, rebuilds the
project from that geometry, restores markers, engravings and the title
block, and opens the editor. Jump destinations go back from an array
index to the (page, slot) the editor works in. The images in the zip are
discarded: the PDF is what the pipeline renders from. Re-exporting a
reopened bundle reproduces its manifest exactly. It refuses to overwrite
a PDF or project file already sitting there, because the obvious place to
unpack is where someone's unfinished cuts live.

Separately, every slice can now carry the measure it starts at, not just
a re-engraved one — a scanned system is numbered in the score the same
way, and noteman wants to answer "take it from bar 33" about either. It
moves off the replacement onto the page, alongside markers and discards,
and out of the bundle's engraving object onto the slice.
2026-07-29 14:30:54 +03:00
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