Repository navigation
The history holds a take per track, and the RC-500 opens pull, rename, clear and restore - #161
Merged
Merged
Conversation
One scripted session on a synthetic one-track card goes through the recorder as the app wires it - the first sighting, push onto an empty slot and over a take, rename, trim, downmix, set tempo, swap, clear, Restore this state, Undo - and every row it leaves is dumped and compared with a text written by this suite from the code as it stands now. The history is about to learn that a memory can hold a take per track; the RC-5 has one, so nothing it records may move, and this is the check that says so line by line.
…lk every track The core's take carried no track: a slot state was a body and at most one take, the archive and the journal heard a slot and a file name, and restore and clear looked in the RC-5's one folder. A two-track memory holds a take per track, and the two can share a file name, so the track is now part of every take the core names - in commands::Take, in SlotState (a body and a list of takes), in the Archive and in the journal's audioWritten and loudnessMeasured. restore writes each take into its own track's folder, archives whatever every track holds before it leaves, ends a track the state names no take for empty, and checks each track section of the body against the take beside it. A take on a track the model does not have, two takes on one track, and a body with fewer or more track sections than the card's model are refused by name before anything moves. clear archives and removes every track's files. Push, trim, downmix and normalize stay on the first track: they are closed on every model with more. On the RC-5 nothing changes - the same files, the same archive calls, the same refusal words - and the golden record of what the history writes for an RC-5 session still matches line for line.
The recorder wrote every take as track 1: what an operation archived, what landed, and what each slot held afterwards. Now the track the core reports goes into the row, a landed take is stamped from its own track's folder, and after an operation each track is written down from its own folder, skipping only the tracks the operation already wrote. Where a slot's take inherits a hash from an earlier row, only that track's rows are asked: on a two-track card both tracks can hold a file of one name, size and stamp, and what one track held must never be handed to the other. A sighting stays a fact about the first track. The reads that file one read no other track, and take_sightings keeps no track, so the readers ask it about track 1 alone; hashOfSighting now takes the track of the take it is asked about and checks that track's own WavLen. The recorder learns the card's model from its marker when the session opens. A two-track card's first sighting already kept every track; it is now covered: two rows for a memory with two takes, one row on track 2 for a memory with only the second track, no empty track-1 row beside it.
…y track The readers took one take per row: the timeline asked for a single row with LIMIT 1 and no order by track, a card row carried one archived take, the row model and both Restore buttons put back one take on the first track, and an Undo step kept, restored or emptied the slot as a whole. Each now reads a list, one take per track in track order. - The timeline offers the state's takes, or the takes it archived when the operation left the slot empty, and a card row carries every take it archived. - A row is restorable when every take of its state can be produced, and what it restores is what the operation left: a clear's archived takes are no part of the empty slot it left. One reader, recordedState, builds that state for the slot tab and for the History window alike - until now both put a clear's archived take beside its empty body, a state the core refused. - An Undo step names the takes that go back and the tracks that go empty; every other track keeps its take, and the run hands the core that take as the card holds it, so a track the operation did not change is left as it was. Putting a body back checks every track section against the card. Undo stays hidden in 0.9.6; its code and tests are made true for N tracks and nothing is added to it. On the RC-5 every row and step reads as before, and the golden record still matches.
…s each operation The two-track model was read-only. It now opens the operations that carry a memory whole, every track of it: pull, rename, clear and restore. The rest work on the first track alone or move only its audio, and stay closed; a refusal on a model this app reads in part says what is open there instead of "only speaks RC-5". - Clear needs the model's never-touched memory. The RC-500's is on record now, taken from a real card: the default name plus it reproduces, byte for byte, every factory-empty memory of two copies of that card. - Pull names a two-track memory's files "<slot> - <name> Track1.wav" and "... Track2.wav"; the RC-5's names do not change. Two takes of one memory under one file name, pulled with the pedal's own names, no longer land on each other. - The settings pair is written only where the controls are open: with a rename open on the RC-500, "any write is open" no longer let it through. - The face asks the operation, not "is anything writable": the slot menu greys each closed item and ends with one sentence built from the table, the status line says what the card's model has open, the inspector and the drums say why a control is a lamp. A memory with only its second track recorded is a memory with audio: it can be pulled and cleared. - With no pedal chosen, a Disconnect walks out the first pedal of the card's own model, never the first RC-5, and Connect sends nothing to nobody.
…k memory gets no first-track number An adversarial review of the branch, and one of the RC-500 factory memory. - restore archived and removed each file in one pass: on a two-track slot an archive that refused the second take left the first already deleted and the body still claiming it. It now keeps every track's take first, then removes, as clear always did. - Pull disambiguated colliding names one file at a time, so the two takes of one memory could land as "03 - take Track1.wav" beside "take Track2.wav". A collision now prefixes every take of that memory. - The loudness cell's double-click and the history's readings filled a two-track memory's LUFS cell with the first track's number, which the context menu already declines to measure. Neither does so now: the cell stays empty on a memory with more than one track. - The golden text is compared byte for byte; .gitattributes keeps a Windows checkout from turning its line endings. - A Disconnect without a chosen pedal reads the card's model when the eject is asked for, not after the unmount, when a scan may already have found no card; with no model it says so instead of naming an empty one. - The factory memory's source comment counts the emptiest bank right (98) and says plainly it is derived from card copies, not from the factory. - pull, rename, clear and restore on the RC-500 leave both SYSTEM banks byte for byte.
Restore rule, one for N tracks: a row's state is its body and the takes it left, and it is restorable when, track by track, the body's WavStat agrees with the take beside it and that take is kept (restorableState, beside recordedState, which both Restore paths read). The core's refusals take main's ASCII dash.
… track
The History tab read one take per row. On a memory of two tracks a row now
names its takes by track, the way the table's WAV column does ("T1
001_1.WAV, T2 001_2.WAV"), and its menu has an export line per track:
"Export track 1 take..." and "Export track 2 take...", each grey when that
track's take is not kept, so the menu keeps its shape from row to row. The
file proposed for a track's take carries the track, as a pulled one does. A
memory of one track keeps its one "Export take..." line and its words.
Restore this state already puts back every track's take (recordedState);
the row says so by being restorable only when each of them is kept.
AliceLafox
marked this pull request as ready for review
October 25, 2026 19:30
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The history kept one take per slot state. A memory of the two-track RC-500 holds a take per track, so before anyone has a history database the model changes: a slot state is a body plus the set of takes its track folders hold, at most one per track, each knowing its track. The RC-500 then opens the operations that carry a memory whole, every track of it: pull, rename, clear and restore. Everything else stays closed on it.
What changes
Commands.hpp).Takecarries its track,SlotStateis a body and a list of takes, and theArchiveand the journal'saudioWritten/loudnessMeasuredhear the track.restorewrites each take into its own track folder, archives every track's files first, and ends a track with no take empty.cleararchives and removes every track. A take on a track the model does not have, two takes on one track, and a body with fewer or more track sections than the card's model are refused before anything moves.take_sightingskeeps no track, and every read that files one reads only that track. No schema change.kRc500opens read, pull, rename, clear and restore, and a never-touched memory of it is on record now (see the next section). Pull names two-track files<slot> - <name> Track1.wavand... Track2.wav; RC-5 names do not change. A refusal on a model the app reads in part says what is open there. The settings pair is written only where the controls are open.restorableState, besiderecordedState, which both Restore paths read. A row's state is its body and the takes it left. The row is restorable when, on every track, the body's WavStat agrees with the take beside it and that take is kept. The core's refusals use main's ASCII dash.The RC-500's "factory" memory is derived from card copies, not from the factory
Clear needs the state of a never-touched memory, and no factory-fresh RC-500 card, and no clear done by the pedal itself, has been seen.
kRc500FactorySectionscomes from the one RC-500 this app has met, its card copied five times as it filled up. In both banks of every copy, every memory without a take is byte for byte the default name plus that text: 98 of the 99 in the emptiest bank and 92 in the fullest. Every memory that differs holds a take. Whether the pedal's own MEMORY CLEAR leaves exactly this, and whether the pedal keeps our cleared body as written, is a step of the hardware checkpoint.Known limit in 0.9.6
A two-track memory has no loudness number.
take_sightingskeeps no track (schema v10, unchanged here), and every read that files a sighting reads the first track's file, so the history can speak for track 1 only. Rather than show track 1's number where it would pass for the mix's, the loudness cell of a memory with more than one track stays empty. The history does not fill it, a double-click does not measure it, Check loudness is not offered, and the player meters one-track memories only. A per-track loudness needs a track intake_sightingsand is left for a later release.What does not change
For the RC-5, every byte the history writes, reads and restores.
tests/golden/rc5-history-rows.txtwas written byhistory_golden_testsfrom the code before this branch (its first commit). It pins one scripted session row for row: first sighting, push, replace, rename, trim, downmix, tempo, swap, clear, Restore this state and Undo. It matches on every commit after it.Review
An adversarial review by a fresh session found one P1 and four P2s, all fixed in the last commit. The P1:
restoreremoved track 1's take before track 2's was archived. The P2s: a pulled pair split across stems, track 1's loudness on a two-track row, CRLF on the golden text, and the Disconnect fallback reading the model after the unmount. A second review attacked the RC-500 factory memory and found nothing to fix in code. Running the realclearon a scratch copy of the card turned the pedal's newer bank into its own older bank, byte for byte.Tests
history_golden_tests(the RC-5 rows),history_tracks_tests(the history of a two-track card, end to end through the recorder),card_permissions_tests.heldBeforefails the tests. Keeping archived takes in a restored state fails them too, with the exact refusal the old code produced.Not in this PR