Project file format
A Ferrous Lineup project is a text file in RON, “Rusty Object
Notation”, which looks like Rust’s own struct and enum syntax. The app
writes it through serde, reads it through the same types, and saves it
with the extension .lineup.
(
format: 29,
tempo: 130.0,
scale: (root: C, kind: Major),
channels: [
(name: "Kick", kind: Sampler(Builtin(Kick)), volume: 0.8, muted: false),
// ...
],
// ...
)
Saving explains RON, serde and the ProjectFile
struct that stands between the file and the live Project. This page is
the reference for the number at the top: FORMAT_VERSION is 29 in
crates/lineup-core/src/file.rs.
The format number
The number says which features a file may contain. It is not the app’s version.
format_for writes the lowest format that can hold the project, not
always 29. A plain project stays format 1, so any version of Ferrous
Lineup can open it. A song with a chord sheet but no band is format 12;
a band is format 13; a locked channel is at least format 23. The number
is that of the highest feature the song uses, and each format can hold
everything the ones below it hold.
Every field a format adds has a serde default. A field at its default is left out when writing, and a missing field gets its default when reading. So a song that uses nothing new is written exactly as before, and a file needs no conversion step when it is opened: it carries only what it uses.
| Format | What it adds | What a version that reads only the formats below would get wrong | Explained in |
|---|---|---|---|
| 1 | The base: channels, patterns, tracks, clips, tempo and key. | Nothing; every version reads it. | Saving |
| 2 | Channels that play an external MIDI synth. | It would not know the MidiOut channel and would not send the notes out. | MIDI |
| 3 | Nine more built-in drums, patterns longer than four bars, and time signatures. | It would not know the drums, would cut long patterns short without a word, and would draw every bar in four. | Tempo, meter, swing and feel |
| 4 | Sections, clips that repeat, and a loop region. | It would play every repeat once and lose the loop. | The project |
| 5 | Time markers, which change the time signature partway through a song. | It would draw every bar in the song’s first time signature. | Tempo, meter, swing and feel |
| 6 | A twelve-tone row or a pitch-class set as the key. | It would not know either kind of key and could not open the file. | Twelve-tone rows, Pitch-class sets |
| 7 | Tempo changes through a song, and loose timing. | It would play the whole song at its first tempo and put every note on the grid. | Tempo, meter, swing and feel |
| 8 | Key changes through a song. | It would show and play the whole song in its first key. | Scales, modes and keys |
| 9 | A General MIDI instrument on a channel. | It would play every Lineup Osc with the same sound and send no program changes. | SoundFonts |
| 10 | Notes that start or end between steps, such as an imported MIDI file’s triplets. | It would move them onto the grid and change the rhythm. | MIDI |
| 11 | Beats grouped irregularly, such as 7/8 counted 2+2+3. | It would read 7/8 but draw a beat line on every eighth note. | Tempo, meter, swing and feel |
| 12 | The chord sheet: the song’s harmony, bar by bar. | It would lose the sheet without a word when saving. | The chord sheet |
| 13 | The band that plays the chord sheet, and the patterns it writes. | It would keep the band’s patterns as plain patterns and stop following the sheet. | How the band plays |
| 14 | The band’s song form: an intro, repeated choruses and an ending. | It would play the song once, as written, with no repeats or ending. | Song form |
| 15 | The style’s second variation, chosen by markers on the chord sheet. | It would play the whole song in the first variation. | Song form |
| 16 | Swing, the eighth notes played long-short. | It would play every pair of eighths evenly. | Tempo, meter, swing and feel |
| 17 | The band’s guitar, strings and organ. | It would know only piano, bass and drums, and could not read their parts. | How the band plays |
| 18 | Shots, holds, rests and pushes on the chord sheet. | It would drop the marks and play the style straight through. | Shots, holds, rests and pushes |
| 19 | The band’s soloist. | It would know no soloist player or soloist part. | The soloist |
| 20 | A band’s rhythm taken from one style and its instruments from another, the exact harmony style, and accents alone. | It would use one style for every part and lose the accents-only setting. | How the band plays, The orchestra |
| 21 | The master mixer, solo and stereo reverb. | It would play the song with the default master and reverb, not the mix you saved. | The mixer |
| 22 | Your own styles, saved with the band. | It would fall back to the style it knows by name, so the band would play something else. | Your own styles |
| 23 | Locked channels. | It would let styles and the band write over the locked part. | Song form |
| 24 | A different style for part of a song. | It would play the whole song in the band’s own style. | Song form |
| 25 | Two chords at once on the chord sheet, written Eb7 over Fb. | It could not read a polychord, so it could not open the file. | Hearing harmony |
| 26 | A pan and a reverb send on each channel. | It would play every channel in the middle with all of it in the reverb. | The mixer |
| 27 | Sending a built-in drum over MIDI. | It would play the drum itself instead of sending it to the external synth. | MIDI |
| 28 | A horn section in the band, and EQ, compression and delay on a channel. | It would play no horns, and every channel without its effects. | How the band plays, The mixer |
| 29 | A band playing the drums of another style than its chord and bass parts, or leaving the drums to the song. | It would play the drums of the band’s own style. | How the band plays, The library |
Two records can be in a file of any format, because a version that
skips them still plays the song exactly. One says where each part of the
song came from (The library).
The other is a key written the other way round, such as G♭ major rather
than F♯ major: the key is saved as (root: FSharp, kind: Major, respelled: true), and a version that does not know respelled reads
it as F♯ major, with the same notes (Scales, modes and
keys).
Files from a newer version
A newer Ferrous Lineup may write a format this one has never seen. Such
a file may contain names and fields this version cannot read, and even
if it reads, their meaning may have changed. So the reader checks the
format number and refuses anything above FORMAT_VERSION:
this file uses format 30, made by a newer version of Ferrous Lineup (this one reads up to format 29)
The whole file is read first, and the number checked after. When the text cannot be read at all, the reader looks for the number at its start without reading the rest, so a file from a newer version is explained by its format number rather than by a puzzling unknown field (Saving).
Saving safely
file::save writes to a temporary file next to the target, ending in
.lineup.tmp, then renames it. A crash or a full disk therefore leaves
the old project as it was, and a half-written file is never mistaken for
a saved one; if the save fails, the temporary file is removed. Line
endings are always \n, whatever the system, and a byte-order mark at
the start of a file is ignored when reading (Saving without losing the
old file).