Skip to content

Contents dialog: export the list of the found presets and import it back to pick what to convert - #336

Merged
git-moss merged 5 commits into
git-moss:mainfrom
douglas-carmichael:contents-export
Aug 14, 2026
Merged

Contents dialog: export the list of the found presets and import it back to pick what to convert#336
git-moss merged 5 commits into
git-moss:mainfrom
douglas-carmichael:contents-export

Conversation

@douglas-carmichael

@douglas-carmichael douglas-carmichael commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

The Contents dialog knows a lot about a source that is available nowhere else: for a disk image or a bank it is the only place where the preset names, their zone counts, key ranges and categories can be seen at all. For a large library that list is exactly what you want before converting - to decide what to convert, to check a library against a paper index, or to keep a record of what an old floppy or CD actually contains. Right now it can only be read on screen, a few dozen lines at a time (my Logic EXS24 folder lists 1031 presets), and the presets to convert have to be ticked one by one in the tree.

Two buttons close that gap, and together they make a workflow which the tree alone cannot offer: filling a hardware sampler from a big library - export the list, decide in a spreadsheet which sounds go on the card, import the result and convert exactly those.

Export List...

Writes the list - the list, not the presets - as CSV or JSON:

Name,Category,Zones,Key Low,Key High,MIDI Low,MIDI High,Folder,File,Container,Index,Selected,Path
BELL PAD,Bell,6,C0,C5,24,84,Bass Library,EIII Vol1.iso,Bank 2,3,true,/Users/…/EIII Vol1.iso
"BASS, CLRNT",,4,C0,F3,24,65,Bass Library,EIII Vol1.iso,Bank 2,4,false,/Users/…/EIII Vol1.iso
  • The exported list is what the tree currently shows, in display order, so a search filter narrows the export as well.
  • The ticked state is one of the fields, so a selection is not lost by exporting.
  • The format follows the ending of the picked file; a file typed without an ending gets the ending of the format selected in the file dialog, since not every platform appends it.
  • A preset without zones writes empty key-range fields (CSV) and null (JSON).

Import List...

Reads such a list back in and ticks exactly the presets it selects.

  • A row selects its preset when its Selected field says so - true, x, 1, yes, in any capitalisation, because a spreadsheet writes TRUE and a person writes x.
  • A list without a Selected field selects every preset it contains, so deleting the rows you do not want is a valid way to narrow the list down. Presets the list does not mention are not ticked.
  • A row is matched by its file plus the index of the preset inside of it, so two presets of the same name in different banks stay apart, and a library which moved to another folder is still found by its file name. A row which carries only a name selects every preset of that name, which makes a hand-written list work.
  • CSV columns are looked up through the header line, so a list may be reordered or reduced to Name/Index/File/Selected - which is what comes back out of a spreadsheet. Semicolon and tabulator separated files are read too (a spreadsheet writes semicolons in the countries which use the comma as decimal separator).
  • Rows which match nothing are counted and reported in the status line instead of stopping the import.

Notes

  • The column names and JSON attribute names are deliberately not translated - they are read by other applications and must not depend on the language of the user interface.
  • New ui/ContentsExporter and ui/ContentsImporter; the importer uses the Jackson which is already a dependency, the exporter formats CSV/JSON directly (RFC 4180 quoting, full JSON escaping).
  • ContentsEntry gained getLowestKey ()/getHighestKey () and its formatNote is public now, so the key range can be written both as note names and as MIDI note numbers.
  • ContentsDialog takes the BasicConfig, so both dialogs start in - and remember - the last used folder like the other file dialogs, and its auditionLabel is renamed to statusLabel since it now reports export and import results as well.

Verified with a round-trip harness over 13 cases: CSV and JSON full round trips, a re-export from a spreadsheet (quoted fields, CRLF, TRUE/FALSE), a semicolon separated list, a name-only list, unmatched rows, a moved library, hand-edited JSON, and two presets of the same name in different images. Compiles with JDK 25/26.

The two buttons sit in the bottom row next to Play. If you would rather have them in the top row next to Select all/Select none, say so and I will move them.

…N file

The new 'Export List...' button writes the presets which are currently
listed - not the presets themselves - to a CSV or JSON file: name,
category, number of zones, key range as note names and as MIDI note
numbers, folder, file, containers, index inside of the file and whether
the preset is ticked. This gives an inventory of a disk image, a bank or
a preset folder which can be read in a spreadsheet or by a script.

The search filter applies to the written list as well and the file
format follows the ending of the picked file; a file without an ending
gets the one of the format which is selected in the file dialog.
'Import List...' reads a written list back in and ticks exactly the
presets which it selects, so the presets to convert can be picked in
another application: export the list, tick what should be converted in
e.g. a spreadsheet, save it as CSV again and import it.

A row selects its preset when its 'Selected' field says so ('true', 'x',
'1' or 'yes'); a list which has no such field selects every preset it
contains, so deleting the rows which should not be converted works as
well. Presets which the list does not mention are not ticked.

A row is matched by its file and the index of the preset inside of it,
so presets of the same name in different banks stay apart and a library
which was moved to another folder is still found by its file name; a row
which has only a name selects every preset of that name. Reading a CSV
file goes through the header line, so its columns may be reordered or
reduced, and semicolon or tabulator separated files - as a spreadsheet
writes them in some countries - are read as well. Rows which match
nothing are reported instead of stopping the import.
@douglas-carmichael douglas-carmichael changed the title Contents dialog: export the list of the found presets as a CSV or JSON file Contents dialog: export the list of the found presets and import it back to pick what to convert Aug 9, 2026
@git-moss

Copy link
Copy Markdown
Owner

I am not sure about this. Feels a bit like feature creep, which would be hardly ever used by someone. What I would find interesting for developing, is to log the info of a whole run (could be an Option for "Analyze" or go into the Debug menu) with the info about Loops, Envelopes, LFO etc. which would help to find test files.

@douglas-carmichael

Copy link
Copy Markdown
Contributor Author

The users this is aimed at are the ones the Contents dialog itself is aimed at: people who accumulated a large library over years of hardware samplers — the composer with shelves of Emulator and Akai media. At that scale the dialog stops working as a screen-only list (the EXS24 folder alone lists 1031 presets; a legacy CD collection is thousands across dozens of images), and it is the only inventory of what those disks actually contain. Export turns that into a searchable record of media which will not stay readable forever; import makes converting a curated subset repeatable instead of ticking thousands of checkboxes again. Whoever does not open the dialog never sees the two buttons, so it does not get in anyone else's way.

The run log is a good idea and a different problem — finding test files for development rather than picking presets for conversion — so I built it: analysis-log. An option ("Log analysis details" in the Settings dialog, -ad on the command line — an option rather than a Debug menu entry, so a whole-library run can be done from the CLI and redirected to a file) makes Analyse log for every found multi-sample what it contains:

Analysis of 'Feature Test':
  File: /Users/.../Sounds/Feature Test.sfz
  Group 1 'Group 1': 2 zones
    Zone 'tone': keys C1/36..C3/60, root C2/48, velocity 1..100, 48000 Hz, 16 bits, stereo, 3147590 frames, gain -3.0 dB, panning -30 %, tuning +0.10 semi-tones
      Round robin #1
      Loop: forwards 1000..40000, until release, cross-fade 2400 frames
      Amplitude velocity: depth +50 %
      Amplitude envelope: attack 0.010 s, decay 0.500 s, sustain 80 %, release 0.300 s
      Tremolo: 3.20 Hz, depth 6.0 dB
      Vibrato: 5.50 Hz, depth +50 cents, delay 0.200 s
      Filter: low-pass, 2 poles, cutoff 1200 Hz, resonance 6.0 dB, key tracking +8 %
        Filter velocity: depth +60 cents
        Filter envelope: depth +2400 cents, attack 0.200 s, decay 0.400 s, sustain 30 %

Only attributes which a source actually uses are logged, so searching is the finder: grep Vibrato or until release over the log of a whole library and the File: line above the hit is the test file. The details describe the source as it was read, before any processing, and the attribute names are deliberately not translated, so a search pattern does not depend on the language of the user interface. Performances are logged as well, with the MIDI channel and key clip of each instrument. I will open it as its own PR.

@git-moss
git-moss merged commit 8bdc3c8 into git-moss:main Aug 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants