Standalone C++17 library that writes an unencrypted rekordbox/CDJ USB image
(export.pdb + per-track ANLZ files) from a plain intermediate model. No Qt,
no Mixxx dependency — that keeps the byte-fiddly serialization testable in
isolation before it's wired into Mixxx (see ../docs/export-design.md,
Phase 0).
include/openboxxx/ public headers (model, byteio, writers, exporter, reader)
src/
pdb/ export.pdb writer (LITTLE-endian DeviceSQL pages) + device_sql_string
anlz/ ANLZ .DAT writer (BIG-endian tagged sections)
usb/ PIONEER/ path assignment
mapping/ rekordbox colour/rating/key encodings (invert Mixxx importer)
verify/ round-trip check (tier 1) — stub pending Kaitai parser wiring
diag/ diagnostic manifest for the in-app bug reporter
adapter/ mixxxdb.sqlite -> ExportModel reader + beats-blob protobuf parser (Phase 1)
tools/ openboxxx_export_cli — Phase 0 driver / smoke test
openboxxx_from_mixxx — Phase 1 reader CLI (real library -> USB)
tests/ dependency-free unit tests (+ SQLite fixture tests for the adapter)
cmake -S . -B build
cmake --build build
ctest --test-dir build --output-on-failure
./build/openboxxx_export_cli # smoke test on a built-in demo model
./build/openboxxx_export_cli --out /tmp/u # also write the USB image to diskTwo independent parsers prove our bytes are real rekordbox format:
anlz_oracle— parses our ANLZ withpyrekordbox(MIT).pdb_roundtrip— compilesthird_party/crate-digger/rekordbox_pdb.ksy(EPL-1.0, test-only) to a throwaway parser viakaitai-struct-compilerand reads back ourexport.pdb.
pip install -r tools/requirements.txt # pyrekordbox + kaitaistruct
brew install kaitai-struct-compiler # (or your platform's package)
cmake -S . -B build -DOPENBOXXX_ORACLE_PYTHON=$(which python3)
ctest --test-dir build # openboxxx_export_tests + anlz_oracle + pdb_roundtrip
# or run either directly:
python3 tools/verify_anlz.py OURS.DAT --ref /path/to/real/ANLZ0000.DAT
kaitai-struct-compiler -t python --outdir /tmp/p third_party/crate-digger/rekordbox_pdb.ksy
PYTHONPATH=/tmp/p python3 tools/verify_pdb.py OURS/PIONEER/rekordbox/export.pdbEach oracle test registers only if its tools are present, so environments without them simply skip it.
If SQLite is available at configure time, the build also produces
openboxxx_from_mixxx — a standalone CLI that reads a Mixxx mixxxdb.sqlite
directly (no Mixxx build required) and writes a CDJ USB image. The eventual
in-Mixxx export job fills the same ExportModel, so all mapping decisions are
shared.
# dry run — read the library and report counts, write nothing
./build/openboxxx_from_mixxx --db "$HOME/.mixxx/mixxxdb.sqlite"
# write the PIONEER/ tree (and optionally copy the audio for a playable stick)
./build/openboxxx_from_mixxx --db /path/to/mixxxdb.sqlite --out /Volumes/USB --copy-audio
# --limit N export only the first N tracks (quick tests)
# --ids A,B,C export only these Mixxx track ids (targeted test sets)
# --no-intro-outro don't map Mixxx Intro/Outro cues as memory cuesThe DB is opened read-only; the tool never modifies the user's library.
Units decoded and validated against a real 2.x library: cue positions are
fractional stereo samples, beatgrid first-beat is in frames, colours are
0x00RRGGBB. macOS default DB path is
~/Library/Containers/org.mixxx.mixxx/Data/Library/Application Support/Mixxx/mixxxdb.sqlite.
| Piece | State |
|---|---|
byteio explicit LE/BE |
✅ implemented + tested |
device_sql_string encoder |
✅ implemented + tested |
mapping colour/rating |
✅ implemented + tested |
| ANLZ container + PPTH + PQTZ | ✅ implemented; validated via anlz_oracle |
| ANLZ PCOB / PCPT cue entries | ✅ layout validated via anlz_oracle (cue ordering TODO) |
PDB page allocator (PdbPage) |
✅ framing validated via pdb_roundtrip |
PDB tracks + lookups + playlists (buildExportPdb) |
✅ round-trips via pdb_roundtrip |
| PDB full 20-table set + colours palette | ✅ emitted; round-trips (colour_id resolves) |
verify round-trip (native C++) |
⛔ TODO — port the read-back into the lib for in-app use |
The MVP export (all 20 standard tables incl. the 8-colour palette; tracks with
colour_id, artists/albums/genres/keys; playlists; ANLZ beatgrid + hot/memory
cues) now round-trips through independent parsers. Remaining before a hardware
test: refine the observed track_row constants / index_shift across rekordbox
versions, and add artwork. ANLZ Phase-2 (cosmetic): vbr, wf_preview,
wf_tiny_preview.
| Piece | State |
|---|---|
beats blob protobuf parser (BeatGrid-2.0 / BeatMap-1.0) |
✅ implemented + unit-tested |
mixxxdb.sqlite reader → ExportModel |
✅ implemented + SQLite-fixture tested |
openboxxx_from_mixxx CLI (real library → USB) |
✅ works; audio copy behind --copy-audio |
| Validated on a real ~2,900-track library | ✅ export.pdb round-trips; ANLZ cue/beat times match the DB exactly |
| Tier-2 diff vs genuine rekordbox ANLZ | ✅ shared sections (PPTH/PQTZ/PCOB×2) match field-for-field; only vbr+waveforms missing (Phase 2) |
| — found + fixed: negative-position hot cue dropped | ✅ now clamped to 0 (was silently losing a hot cue) |
| — found + fixed: duplicate memory cue (MainCue≡Intro) | ✅ now deduped by millisecond |
In-Mixxx RekordboxExportJob + dialog + Library-menu button |
✅ built (behind REKORDBOX_EXPORT) in a Mixxx fork; fills the same model from live objects |
| In-Mixxx "Cue Sheet → Tracklist" tool | ✅ built (.cue → .txt) |
| Cross-platform build | ✅ compiles + links on macOS Intel/ARM, Windows, Linux (CI green); downloadable Releases |
| Import test in rekordbox desktop (tier 3) | ⛔ pending — not yet confirmed |
| Physical CDJ/XDJ hardware (tier 4) | ⛔ pending — the real proof; testers welcome |
Known minor deviation (not yet changed): rekordbox writes the hot-cue PCOB
before the memory PCOB; we emit memory first. Readers key off each list's
cue_type field, not position, so this is cosmetic — left as-is until a
populated real reference confirms the convention.