// AUDIO_HAXOR — TAURI v2 AUDIO PLUGIN SCANNER

Tutorial Report GitHub Issues
// Color scheme

>_DEVELOPER REFERENCE

Tauri v2 · Rust backend app_lib · release version in package.json / src-tauri/tauri.conf.json / src-tauri/Cargo.toml. Main UI is frontend/index.html; the menu-bar tray runs a separate WebView (frontend/tray-popover.html + frontend/js/tray-popover.js).

Step-by-step tutorial — how to use AUDIO_HAXOR

The full end-user walkthrough now lives as a 19-step, multi-page tour under docs/tutorial/. Each step is a proper deep-dive: every control, column, filter, row action, keybinding, and IPC command — grounded in the actual source. Cyberpunk styling, CRT scanlines, neon accents, entrance animations.

Open the tutorial →

Chapters

  • 01 — First launch: HUD header, process stats, tab bar, boot sequence. Read →
  • 02 — Scan roots: per-scanner directory lists, blacklist, performance tunables. Read →
  • 03 — Scan All & Walkers: unified scan, per-type scans, live walker tiles. Read →
  • 04 — Plugins: VST/VST3/AU/CLAP, KVR update flow, dependency graph. Read →
  • 05 — Samples: streaming table, waveform + spectrogram preview, fingerprint duplicates. Read →
  • 06 — BPM / key / LUFS analysis: algorithm notes (onset autocorrelation, Krumhansl-Kessler, BS.1770). Read →
  • 07 — DAW projects: thirteen formats, extract plugins, xref cache. Read →
  • 08 — MIDI / Presets / PDFs: metadata extractors, preset catalog, PDF page counts. Read →
  • 09 — Command palette: Cmd+K launcher, DB preview, toggles. Read →
  • 10 — Floating player: waveform seek, EQ, gain, pan, speed, reverse, A/B loop. Read →
  • 11 — Tray popover: menu-bar HUD, scrubber drag, theme sync. Read →
  • 12 — Favorites / Notes / Tags: cross-inventory organization, multi-filter, tag cloud. Read →
  • 13 — Files browser: navigation, bookmarks, lazy waveforms, native drag-out. Read →
  • 14 — Scan history & diffs: merged sidebar, per-type detail, added/removed diffs. Read →
  • 15 — Visualizer: six tiles, engine spectrum vs Web Audio fallback, idle backoff. Read →
  • 16 — Audio Engine tab: device selection, plugin insert chain, diagnostics. Read →
  • 17 — Theme & color schemes: Cyberpunk, Midnight, Matrix, Ember, Arctic + custom editor. Read →
  • 18 — Keyboard shortcuts: full default keymap, rebinding UI, FZF syntax. Read →
  • 19 — ALS generator: genre / key / hardness, 27-slider track counts, 6-lane × 8-bar-block section timeline, KICKS bus + group-level sidechain, return sends, Eq8 HPF + Limiter master chain. Read →

Application feature map

Checklist-style index of shipped surfaces (verify in frontend/ + src-tauri/). Deeper behavior lives in README.md and rustdoc.

Main tabs

  • Plugins — VST/VST3/AU/CLAP scan, SQLite table, KVR resolve + update check with queued “next update” flow (js/kvr.js), export/import (JSON/CSV/TOML), per-scan history + diff, optional disk-usage strip (js/disk-usage.js), plugin dependency graph (js/dep-graph.js).
  • Samples — audio library scan + history/diff, paginated table with sort/persisted columns (js/sort-persist.js, js/columns.js), inline preview / floating player (js/audio.js), waveform/spectrogram caches + decode worker, BPM/key/LUFS fields and batch analysis, chromaprint fingerprint cache + find similar + content duplicates, smart playlists (js/smart-playlists.js).
  • DAW — project scan (multiple DAW formats), open folder/project, extract plugins from project, xref/index build and cached plugin lists per project (js/daw.js, js/xref.js), Ableton ALS/XML and generic project file reads, Bitwig .bwproject via read_bwproject, history/diff, disk usage.
  • Presets — preset scan, history/diff, export/import, disk usage.
  • MIDI — MIDI scan + SQLite (db_query_midi), history/diff, note/tempo/key metadata (js/midi.js), export full tab or selection subset (js/export.js).
  • PDFs — PDF scan, optional metadata extraction batch + progress events, open in viewer / default app, export DSV/JSON, import JSON, history/diff (js/pdf.js).
  • Videos — video file scan + SQLite (db_query_video), history/diff, inline preview / fullscreen player, export/import JSON/DSV, optional AudioEngine vs HTML5 decode route in Settings (js/video.js).
  • Favorites — starred paths across types (js/favorites.js), export/import.
  • Notes — per-item notes (js/notes.js), export/import, clear.
  • Tags — global tag manager + filter bar (position top/bottom; js/multi-filter.js).
  • Files — power file browser. Multi-pane 1–4 with full per-pane state (path / entries / selection / scroll / tabs / nav history / sort / ext-filter / show-hidden / search mode) in the fileBrowserPanesV3State persistence blob so sort column, ext-filter chip, hidden-files toggle, Spotlight-or-name search mode, scroll position, and nav history (Cmd+[/Cmd+], capped at 50 entries) all survive across launches; one-shot bootScrollPending flag restores scroll once without fighting later programmatic scrolls; 250 ms debounced scroll save. Drag-resize handles + ⇆ swap buttons between panes. Trello-style drag-reorder: drag a pane's tab strip to permute pane positions (_fbReindexPanesFromDOM re-interleaves resize gutters + follows the active idx with the moved content); drag any .fb-tab inside one pane to reorder per-pane tabs; both reuse the shared initDragReorder engine and emit localized toast.reordered_panes / toast.reordered_tabs via the engine's toastKey opt. Sync scroll toggle, cross-pane copy/move + native drag-out to Finder/Desktop (tauri-plugin-drag); cross-pane drops emit toast.fb_drop_copied_n / toast.fb_drop_moved_n / toast.fb_drop_failed; native drag-out emits toast.fb_drag_started_n after tauri.drag.startDrag resolves (previously silent on success). Tree-view sidebar (lazy-expanded, fs_list_subdirs). Inline previews: image thumbnails + EXIF row badge, PDF thumbnails (SQLite-cached at image_preview_cache / pdf_preview_cache), audio waveforms, video first-frame (qlmanage on macOS), git-status badges (git status --porcelain). Color labels (Finder-style 7 colors, per-pane filter chip strip below ext-filter). Modals: Get Info (size + mtime/ctime/atime + perms drwx + uid/gid + xattrs + EXIF + audio metadata from audio_samples + disk usage from sysinfo), Hash (SHA-256 single + bulk + Copy All), Chmod single + bulk, Diff two files (similar crate, unified diff modal), Find in Files (recursive grep — binary-skip + size cap), Find Duplicates (size+ext prefilter then SHA-256), Compare Folders (3-bucket diff active↔next pane), Symlink target editor, Bookmarks manager (rename / reorder / delete), Quick Open (recent palette), Spotlight (cross-inventory FTS5 across audio_samples_fts+daw_projects_fts+presets_fts+midi_files_fts+pdfs_fts+video_files_fts). File ops: Move to Trash (recoverable via trash crate) + Delete Permanently + Secure Delete (fs_secure_delete — overwrites file length with zero buffer in 64 KiB chunks, fsync, unlink; rejects directories; symlinks unlink the link only; confirm dialog states honest SSD/CoW caveats) + Duplicate ({stem} copy.ext) + Make Alias (Unix symlink) + Touch (filetime) + Compress to .zip + Extract .zip/.tar/.tar.gz/.7z (zip+tar+sevenz-rust2 — path-traversal safe) + Run as Program (Unix +x) + Open in External Editor ($VISUAL/$EDITOR/code/subl/platform default) + bulk Hash/Chmod/Touch/Compress/Extract. The three deletion options come from a shared _pathDeleteItems(path, name, isDir, onAfter) helper in context-menu.js and are mirrored into every inventory table row (audio / DAW / MIDI / preset / PDF / video) so right-clicking any sample / project / preset / pdf / video also exposes Move to Trash / Delete Permanently / Secure Delete. On successful delete the helper removes the matching tr[data-{type}-path] row from the DOM (so the user sees the deletion immediately without forcing an inventory re-query) AND reloads the file browser if the deleted path lived under the current dir using a directory-boundary-safe prefix check (/foo does NOT match /foobar/x). Hex / binary viewer preview-pane fallback (fs_read_head_bytes raw ArrayBuffer). Auto-reload watcher (fb_watcher: single-dir non-recursive notify with 300ms Rust + 150ms JS debounce). All Finder + Nautilus ops (Copy/Cut/Paste files, Pattern Select, Invert Selection, Shift+Del = permanent, Ctrl+H hidden, New Folder with Selection). Every status toast is i18n-routed — 33+ surface-specific keys (toast.fb_copied_to_pane_n, fb_renamed_n, fb_chmod_on_n, fb_pasted_n, fb_moved_n_into, fb_compressed_to, fb_extracted_n_archives, fb_label_applied_n, fb_saved_n_bookmarks, fb_trashed_n_dupes, fb_permanently_deleted_n, fb_moved_n_to_trash, fb_aliased_to, fb_duplicated_to, fb_opening_in_bin, fb_moved_to_trash_name, …) replace the generic raw-English fallback. Lossless V3 persistence in prefs: pane paths/tabs/active-idx/flex-widths/expanded-tree-nodes/labels/sync-scroll/show-hidden/sort-col/ext-filter/search-mode/scroll/nav-history. (js/file-browser.js, js/context-menu.js, js/drag-reorder.js, js/native-file-drag.js, src-tauri/src/fb_watcher.rs, ~40 fs_* Tauri commands in lib.rs.)
  • History — unified scan run + per-inventory scan records, compare/diff, prune/delete entries (js/history.js).
  • Visualizer — spectrum/waveform views driven from playback / engine (js/visualizer.js).
  • Walkers — live unified-walker status (js/walker-status.js, get_walker_status).
  • Audio Engine — subprocess JSON API: file decode, transport, seek, loop/speed/reverse, DSP/EQ/mono, optional spectrum bins, VST3/AU insert chain + editor windows (js/audio-engine.js + IPC audio_engine_invoke).
  • Settings — file-backed prefs + SQLite app strings; UI locale; light/dark + CRT + neon; color schemes / custom presets; scan roots & blacklists; auto-scan, folder watch, incremental scan, prune-old-scans, include-backups; autoplay & playback toggles; auto-update; PDF metadata auto-extract; analysis auto-run; table page size; log verbosity; cache table rebuild/clear (incl. xref/fingerprint); BPM/LUFS jobs; data-dir file list; export settings/log as PDF; shortcut editor (js/settings.js, js/settings-search.js, js/i18n-ui.js).

Scanning & database

  • Unified scanscan_unified walks configured roots once and fans progress into the same per-type events as standalone scans (prepare_unified_scan, stop_unified_scan, get_unified_scan_run).
  • Standalone scans — plugins, samples, DAW, presets, MIDI, PDF each support custom roots, exclude paths, stop/resume where applicable, progress listeners, and a header resume all when workers are paused.
  • SQLite — library tables for inventory + analysis fields; filter stats helpers; palette preview query; audio-library path list for fingerprints.
  • Import/export — tab-scoped JSON/DSV/CSV/TOML where implemented; plugin xref export; smart-playlist export; favorites/notes; PDFs; MIDI export.

Playback & tray (summary)

  • Floating player: history list, filter field, shuffle, loop modes, A/B loop, 3-band EQ + gain + pan, mono, volume, playback speed + reverse, favorite/tag current track, export/import/clear recently played, expand/collapse, hide/show pill — see js/audio.js.
  • Autoplay next source — Settings chooses whether EOF / failure-chain advance follows player history or visible Samples table; tray/menu/shortcuts/palette use respectAutoplaySource; floating Next/Previous buttons use history order only (see tray section below).

Tooling & discovery

  • Heatmap dashboard — sample metadata visualization (js/heatmap-dashboard.js).
  • Duplicate finder — content-level reports (js/duplicates.js).
  • Process stats — main and audio-engine RSS/CPU/thread probes in header/settings.
  • Logging — in-app log, clear, open log file, optional PDF export. Long-running breadcrumbs go to app.log in the data directory:
    • HEALTH (every 30 s, host) — RSS, virt, thread count, audio-engine + preview-engine pids and RSS, IPC counters (avg / max / peak queue / inflight) for both engine streams. Generated by the ah-health-sampler thread spawned at the end of setup(); first tick is skipped to avoid lazy-init noise. Also fires a { "cmd": "ping" } keep-alive request to the audio-engine subprocess when the previous 30-second window had fewer than 5 IPC calls, so JUCE’s working set never gets paged out under long idle.
    • HEALTH-JS (every 30 s, frontend) — JS heap (used / total / limit), waveform & spectrogram cache sizes, in-flight SQLite waveform hydration, decode-worker pending count, AudioContext + playback context state. Emitted by _startJsHealthSampler in frontend/js/audio.js; pushed through vstUpdater.appendLog to land in the same log file as the host’s HEALTH line.
    • Engine fatal-signal handlerengine.log captures [ENGINE crash] handler entered, fatal signal <n>, raw stack-frame addresses, and the dyld image map on SIGSEGV / SIGBUS / SIGABRT in the JUCE subprocess. Signal-safe writer; lets you symbolicate after the fact even when the helper aborted before draining buffers.
    • App background mode (macOS) — APP BG: resignActive / APP BG: becomeActive lines mark every transition into and out of the App Nap window so you can correlate slow-first-playback reports with actual idle dwell time.

UX & desktop integration

  • Help overlay — shortcut reference (js/help-overlay.js).
  • Context menus — row actions across tabs (js/context-menu.js).
  • Tooltips — hover titles for dense controls (js/tooltip-hover.js).
  • Keyboard — navigable tables (js/keyboard-nav.js), batch selection (js/batch-select.js), drag-reorder for sections/tabs (js/drag-reorder.js).
  • Embedded terminal — PTY-backed xterm.js terminal (js/terminal.js, src-tauri/src/terminal.rs). Login shell, 256-color + truecolor, drag-to-dock corners, resizable, Ctrl+T toggle. Screenshot →
  • Modals — draggable custom dialogs where enabled (js/modal-drag.js).
  • UI idlejs/ui-idle.js sets html.ui-idle-heavy-cpu when the window is backgrounded/minimized/hidden to pause scanlines and suppress toasts.
  • Native menus — macOS/Windows menu bar mirrors many actions; GitHub / Docs items open external links.
  • macOS — Mission Control / Spaces preview fixsrc-tauri/src/space_preview_macos.rs. WKWebView renders out-of-process via WebContent + GPU XPC, so the WindowServer’s snapshot mechanism (Mission Control / Spaces / Cmd-Tab thumbnails when the window is in another Space) captures a blank gray rectangle (WebKit bug 146877). The fix layers an NSImageView overlay above the live WKWebView, periodically refreshed via WKWebView.takeSnapshot: while the window is key. The overlay is unhidden when the window resigns key / becomes occluded so the snapshot grabs the bitmap-backed CALayer; live WebView resumes when focus returns. Class lookup is done by walking the superclass chain via class_getName rather than sending +name to the class object — wry’s WryWebView subclass does not implement +name and would otherwise throw NSInvalidArgumentException.
  • macOS — App Nap mitigationsrc-tauri/src/app_activity_macos.rs. After hours of idle, macOS throttles CPU, coalesces timers, and (under memory pressure) compresses or swaps the host’s pages, so the next sample playback lags for seconds while the OS un-throttles. The fix holds an NSProcessInfo.beginActivityWithOptions:reason: token (option set UserInitiatedAllowingIdleSystemSleep — same as Music.app: keeps the host unthrottled but still permits the laptop to sleep when the user walks away). Installed from RunEvent::Ready, not setup(), because setup() runs inside applicationDidFinishLaunching:; an unwind across that extern "C" boundary aborts the process. Both this install and the Mission Control install are wrapped in objc2::exception::catch (not std::panic::catch_unwind — the latter aborts when it sees a foreign exception class).
  • macOS — App background mode loggingapp_activity_macos.rs registers NSApplicationDidResignActiveNotification and NSApplicationDidBecomeActiveNotification observers that write APP BG: resignActive / APP BG: becomeActive lines to app.log. Useful to correlate “first playback after long idle was sluggish” reports with how long the app was actually backgrounded.

ALS generator (Ableton Live Set authoring)

src-tauri/src/als_generator.rs (template + gzip I/O) and track_generator.rs / trance_generator.rs (arrangement) turn the analyzed sample library into a full techno / schranz / trance layout and write it as a gzipped .als file openable directly in Ableton Live 11 / 12. The IPC entry point is generate_als_project (see IPC inventory below). The frontend UI is frontend/js/als-generator.js plus the section-override timeline at frontend/js/als-timeline.js.

What ships today

  • Arrangement engine — base track types (kick, clap, snare, hat, perc, ride, fill, bass, sub, lead, synth, pad, arp, riser, downlifter, crash, impact, hit, sweep up/down, snare roll, reverse, sub drop, boom kick, atmos, glitch, scatter, vox) across seven sections (intro / build / breakdown / drop 1 / drop 2 / fadedown / outro). Schranz adds a dedicated hardcore kick track (HARDCORE_KICK) and a layered kick group (PUNCH / RUMBLE / NOISE on three child tracks under one KICK_LAYER bus, so the body / sub / hiss layers can be mixed independently and sidechained as one source). All genres add a breakbeat track (chopped break loops on the drum group) and a pre-drop fill pattern derived from real schranz template analysis (snare roll + filtered downsweep + impact landing on the downbeat). Default bar counts per genre: 224 Techno (32×7), 256 Trance (32/32/48/32/32/32/48), 208 Schranz (32/32/16/32/48/32/16). Per-section lengths are user-editable per genre — drag any section boundary in the timeline canvas (8-bar snap, min 8, max 128 bars) to resize; saved under alsSectionLengthsByGenre in prefs and plumbed through ProjectConfig.section_lengths to the generator. Templates are authored against the canonical 224-bar Techno layout and remapped onto the user’s layout at generate time via remap_bar_range.
  • Section-override timeline — 6-lane HUD canvas lets you pin per-8-bar-block values for chaos / glitch / density / variation / parallelism / scatter. Each section is subdivided on the Ableton phrase grid (28 blocks for Techno, 32 for Trance, 26 for Schranz) so you can shape dynamics at phrase granularity, not just at the 32-bar section level. Drag top edge, shift-click to add, scroll to nudge ±0.05, right-click to delete. Persists to alsSectionOverrides in prefs as a flat bar-start → value map; legacy section-name keys migrate on first load.
  • Sample selection — key & BPM-matched queries against audio_samples, atonal filter per-type, genre- specific SQL fallback categories when sample-analysis rows aren’t populated. Audio-based category inference fallback: when filename / path heuristics yield zero matches for a slot (long-tail manufacturer naming the manufacturer-signal table does not cover), the selector consults stored audio analysis fields (LUFS, spectral centroid, transient density, length bucket) to decide whether the sample looks like a kick, hat, pad, etc., so generation does not silently drop the slot. Blacklist / whitelist modals filter the pool.
  • Bus topology — six group buses emitted only when populated (count is computed from the sample pool, not a magic number): KICKS (its own bus so the kick pulse can safely drive every sidechain), DRUMS, BASS, BASS FX, MELODICS, FX. Colors per category, TrackGroupId wired so children nest in Ableton’s mixer.
  • Group-level sidechain — a Compressor2 with SideChain pre-enabled is injected into DRUMS / BASS / BASS FX / MELODICS buses, routed to AudioIn/Track.<KICKS_group_id>/PostFxOut. One compressor per bus (not per track) to avoid stacked compression. FX bus is deliberately un-ducked so risers / impacts / crashes stay transient. Template: src-tauri/src/group_sidechain_compressor_template.xml (Threshold ≈ −14 dB, Ratio 4:1, Attack ≈ 5 ms, Release ≈ 150 ms).
  • Return-bus sends — every AudioTrack’s two Sends are populated per category by send_levels_for(): low-end (kick / sub / bass / sub drop / boom kick) stays dry; drums get a light reverb kiss; leads / arps add both reverb and delay; pads / atmos run wettest; FX send moderate reverb but little delay. The base template’s Return A (Reverb) and Return B (Delay) remain untouched.
  • Master chain — MainTrack’s DeviceChain now gets an Eq8 with Band.0 as a 12 dB/oct HPF at 30 Hz (rumble cleanup), followed by a Limiter at Ceiling −0.3 dB, AutoRelease on, Lookahead on, LinkChannels on. These sit before the template’s existing StereoGain (Utility), so the chain runs rumble-cleanup → peak-catch → final trim. Templates live at src-tauri/src/master_eq8_hpf_template.xml and src-tauri/src/master_limiter_template.xml.
  • Locators at every section boundary (Intro / Build / Drop 1 / …) across all songs, including the song key label, so in-Ableton navigation is immediate. Inserted by create_locators_xml_multi.
  • Multi-song mode — N songs concatenated with a 32-bar gap; each song re-rolls sample selection from the same pool so arrangements diverge. IDs are allocated through IdAllocator (starts at 1 000 000 with HashSet dedup against reserved template IDs).
  • Deterministic seed — wizard field (#alsSeed) with 🎲 randomize button and 🔒 Lock toggle (#alsSeedLocked). When set, every random decision (swoosh rotation, scatter hits, fills, glitches, parallelism thinning, variation chunking, chaos gaps, density accents, sample-shuffle tie-breakers) derives from the seed via a thread-local StdRng in track_generator.rs (init_gen_rng / with_gen_rng), seeded at the top of generate() and cleared on every exit path. generate_als_project resolves config.seed.unwrap_or_else(rand::random) and echoes the used seed back in the result JSON so the wizard can display “Seed: 12345” and offer a “regenerate with same seed” flow. Seeds travel as JSON strings to round-trip through JS Number precision without truncation; deserialize_seed in als_project.rs accepts either numeric or string form and treats empty strings as “pick a fresh random seed”. Project names and word patterns are derived from the same seed via generate_project_name(config, seed); the filename still carries a wall-clock YYYYMMDD_HHMMSS suffix so back-to-back locked runs never collide on disk. restoreAlsPrefs drops the stored seed on startup when Lock is off, preventing a previous session’s seed from silently pinning every new generation.

Deeper reference documents

Rust API (rustdoc)

Generated HTML for the library crate:

  • Browse app_lib docs (after pnpm run doc:sync)
  • Local cargo output (workspace target/ at repo root): target/doc/app_lib/index.html
pnpm run doc:open    # build + open in browser
pnpm run doc:sync    # copy tree into docs/api/

Main window IPC & i18n

frontend/js/ipc.js is the Tauri invoke bridge (window.vstUpdater wraps @tauri-apps/api/core invoke):

  • window.vstUpdater: wraps invoke for DB queries, prefs, scans, PDF/MIDI helpers, audio_engine_invoke (subprocess audio engine JSON API — UI in frontend/js/audio-engine.js + frontend/js/audio.js), and palette search (db_query_palette_preview).
  • Strings: startup get_app_strings fills window.__appStr; appFmt / toastFmt for UI and toasts. reloadAppStrings(locale) reloads maps, reapplies i18n, invalidates the command palette static cache, refreshes the native menu (refresh_native_menu), and re-syncs tray now playing.
  • menu-action events: native menu bar and tray dispatch action IDs into the main window. Tray seek uses a single payload form seek:<fraction> (0..1) → seekPlaybackToPercent without a separate IPC command.
  • Host EOF poll: listen('audio-engine-playback-eof', …) forwards to handleEnginePlaybackEofFromPoll when Rust detects end-of-file while WebView timers may be throttled — same advance behavior as the in-window playback path.

Command palette (Cmd+K)

frontend/js/command-palette.js — quick launcher bound by default to Cmd+K / Ctrl+K via shortcuts.js (commandPalette).

  • Static rows: jump to tabs, start/stop scans, exports/imports, transport, EQ/mono, theme/CRT, and many settings toggles. Labels use appFmt; shortcut hints use live getShortcuts + formatKey.
  • Database search: with query length ≥ 2, calls dbQueryPalettePreview (one pooled Rust task, six capped inventory queries). Results cover plugins, audio samples, DAW projects, presets, PDFs, and MIDI files. Choosing a hit switches to the right tab and seeds that tab’s search field — the palette does not rely on in-memory paginated tables alone.
  • Transport alignment: palette Next track / Previous track call nextTrack({ respectAutoplaySource: true }) / prevTrack({ respectAutoplaySource: true }), same as the tray, menu bar, and keyboard shortcuts (see below).

Keyboard shortcuts

frontend/js/shortcuts.js — persisted overrides and executeShortcut(id) dispatch.

  • Rebinding: Settings UI lists every action in SHORTCUT_LABEL_KEYS; custom bindings are persisted (see that module for storage and capture UI).
  • Scope: tab switching (plugins through audio engine), focus search, help overlay, playback (play/pause, loop, mute, volume, shuffle, A/B loop, player visibility), file ops (reveal, copy path, favorite, notes), selection, export/import current tab, dependency graph, duplicates/similar, theme, prefs, scan/stop variants, PDF metadata, fingerprint cache, BPM/key/LUFS jobs, cache clears, log verbosity, table page size, autoplay source, tag filter bar, and more.
  • Next / Previous track keys invoke nextTrack / prevTrack with respectAutoplaySource: true so ordering follows autoplayNextSource (player history vs Samples table), not only the floating history list.

Tray popover & playback IPC

High level (details in source comments):

  • State: Main window calls update_tray_now_playing (Tauri v2: invoke(..., { payload: { … } })) from syncTrayNowPlayingFromPlayback in frontend/js/audio.js. Payload includes ui_theme, optional appearance (CSS variables from SCHEME_VAR_KEYS), and now-playing fields.
  • Theme & color schemes: Popover applies data-theme and inline scheme vars so the HUD tracks Settings light/dark and color presets.
  • Previous / Next: Snake-case menu IDs prev_track / next_track (tray popover, native menu bar, tray_prev / tray_next) call prevTrack / nextTrack with respectAutoplaySource: true so the list follows autoplayNextSource (player history vs visible Samples table). Floating player buttons use camelCase actions and stay on the history list only.
  • Autoplay next (on/off): Gates end-of-track and failed-preview auto-advance (tryPreviewAutoplayNextOnFailureAsync in previewAudio) along the same list as EOF (autoplayNextSource), after an error toast; can chain across multiple bad files. Does not gate manual prev/next from tray/menu/shortcuts.
  • Tray mirror: The popover has no separate queue — it reflects the main window via syncTrayNowPlayingFromPlayback after the current path updates.
  • Tray seek: Popover scrubber sends menu-action with payload seek:<fraction>; see IPC section above.
  • HUD subtitle: syncTrayNowPlayingFromPlayback clears a redundant subtitle when #npMetaLine would duplicate the track title (e.g. basename-only path matching the displayed name).

Monorepo layout

High-level tree (names only — open the repo for full detail).

audio-haxor/
├── docs/              # This hub + synced rustdoc (docs/api/) + hud-static.css, hud-theme.js
├── frontend/          # Main WebView: index.html, js/*.js, tray-popover.html
├── i18n/              # app_i18n_*.json string catalogs
├── reports/           # Generated artifacts (e.g. i18n audit HTML)
├── scripts/           # pnpm wrappers, Python i18n tools, JS test runners, shell maintenance
├── src-tauri/         # Rust crate (lib + binary), capabilities, bundled resources
│   └── src/           # lib.rs invoke surface + domain modules (see below)
└── package.json       # pnpm scripts; version mirrors tauri.conf / Cargo for releases

Package scripts (pnpm)

Entry points from package.json — run from repo root with pnpm ….

dev / tauri:dev          → tauri dev
build / tauri:build      → tauri build (+ postbundle audio-engine helper on full build)
tauri:build:ci           → CI build without signing
test → scripts/test.sh (combined)
test:js → node scripts/run-js-tests.mjs
test:rust                → cargo test --manifest-path src-tauri/Cargo.toml
test:audio-engine        → node scripts/run-audio-engine-tests.mjs
doc / doc:open / doc:sync → rustdoc; doc:sync copies target/doc → docs/api/
clean / bust / rebuild / nuke / deploy → maintenance shell scripts
db:vacuum / db:stats     → SQLite maintenance helpers
i18n:sort / i18n:sort:check / i18n:audit → catalog sort + HTML audit report

Shell helpers under scripts/

Thin wrappers around builds, tests, deploy, and DB housekeeping — read each file for flags and safety rails.

  • build.sh / rebuild.sh / clean.sh / nuke.sh / bust.sh — lifecycle and cache busting.
  • test.sh / ship-check.sh — pre-ship validation.
  • postbundle-audio-engine-helper.sh — runs after pnpm build to place the audio-engine helper next to the app bundle.
  • bundle_dmg.sh / deploy.sh / cyberpunk.sh — packaging and themed extras.
  • db-vacuum.sh / db-stats.sh — on-disk SQLite maintenance.

Tauri invoke inventory

Authoritative list lives in src-tauri/src/lib.rs inside tauri::generate_handler![…]. Grouped here for orientation (names only). JS calls use the string form (e.g. invoke('terminal_spawn', …)) even when Rust registers terminal::terminal_*.

Core / filesystem
  get_version, get_build_info, get_walker_status, get_home_dir, get_process_stats
  open_update_url, open_prefs_file, get_prefs_path, open_file_default, open_with_app
  fs_list_dir, delete_file, delete_inventory_item, rename_file
  read_text_file, write_text_file, write_binary_file, ensure_snapshot_export_dir
  read_cache_file, write_cache_file, list_data_files, delete_data_file

Plugin scan + KVR + plugin history
  scan_plugins, stop_scan, check_updates, stop_updates, resolve_kvr
  history_get_scans, history_get_detail, history_delete, history_clear, history_diff, history_latest
  kvr_cache_get, kvr_cache_update
  open_plugin_folder, export_plugins_json, export_plugins_csv, import_plugins_json

Audio samples + analysis + fingerprints + waveform caches
  scan_audio_samples, stop_audio_scan, get_audio_metadata
  audio_history_save, audio_history_get_scans, audio_history_get_detail, audio_history_delete
  audio_history_clear, audio_history_latest, audio_history_diff
  estimate_bpm, detect_audio_key, measure_lufs, batch_analyze
  sample_analysis_seed, sample_analysis_start, sample_analysis_stop, sample_analysis_stats
  compute_fingerprint, find_similar_samples, build_fingerprint_cache, stop_fingerprint_cache
  find_content_duplicates, cancel_content_duplicate_scan
  upsert_waveform_cache_entry, read_waveform_cache_entry, upsert_spectrogram_cache_entry
  waveform_prefetch_start, waveform_prefetch_stop, waveform_prefetch_stats
  open_audio_folder, export_audio_json, export_audio_dsv, import_audio_json

DAW projects
  scan_daw_projects, stop_daw_scan
  daw_history_save, daw_history_get_scans, daw_history_get_detail, daw_history_delete, daw_history_clear, daw_history_latest, daw_history_diff
  open_daw_folder, open_daw_project, extract_project_plugins, read_als_xml, read_bwproject, read_project_file
  export_daw_json, export_daw_dsv, import_daw_json

Presets / MIDI / PDF / Video
  scan_presets, stop_preset_scan, preset_history_*, open_preset_folder
  export_presets_json, export_presets_dsv, import_presets_json
  scan_midi_files, stop_midi_scan, midi_history_*, db_query_midi, db_midi_filter_stats, get_midi_info
  scan_video_files, stop_video_scan, db_query_video, db_video_filter_stats
  export_videos_json, export_videos_dsv, import_videos_json
  scan_pdfs, stop_pdf_scan, pdf_history_*, open_pdf_file, pdf_metadata_get
  pdf_metadata_extract_abort, pdf_metadata_extract_batch, pdf_metadata_unindexed
  export_pdfs_json, export_pdfs_dsv, import_pdfs_json, export_pdf

Unified scan + logging
  scan_unified, get_unified_scan_run, prepare_unified_scan, stop_unified_scan
  append_log, read_log, clear_log

Audio engine subprocess
  audio_engine_invoke, audio_engine_restart
  audio_engine_eof_watchdog_start, audio_engine_eof_watchdog_stop, set_audio_engine_next_track_hint
  set_playback_active_flag, set_playback_active_and_wait, set_bg_job_throttle, get_bg_job_throttle
  get_audio_engine_process_stats

Preferences + favorites + player history + notes + tags
  prefs_get_all, prefs_set, prefs_remove, prefs_save_all
  favorites_list, favorites_add, favorites_remove, favorites_clear, favorites_is, favorites_set_all
  player_history_list, player_history_add, player_history_remove, player_history_clear
  player_history_reorder, player_history_import, player_history_set_all
  note_get, note_set, notes_get_all
  tags_standalone_list, tags_standalone_set, tags_standalone_add, tags_standalone_remove
  tags_all, tags_counts, tags_items_with, tag_rename, tag_delete, tag_add_to_item, tag_remove_from_item, tag_has

i18n + tray + native chrome
  get_app_strings, get_toast_strings, refresh_native_menu
  tray_menu::update_tray_now_playing, tray_menu::tray_popover_action, tray_menu::tray_popover_resize
  tray_menu::tray_popover_get_state, tray_menu::tray_popover_push_subtitle, tray_menu::tray_popover_get_ui_theme
  tray_menu::show_main_window, tray_menu::tray_popover_hide

SQLite + DB helpers
  db_query_audio, db_query_plugins, db_query_daw, db_query_presets, db_query_pdfs, db_query_midi, db_query_video, db_query_palette_preview
  db_audio_stats, db_daw_stats, db_preset_stats, db_pdf_stats, db_plugin_filter_stats
  db_audio_filter_stats, db_daw_filter_stats, db_preset_filter_stats, db_pdf_filter_stats, db_midi_filter_stats, db_video_filter_stats
  get_active_scan_inventory_counts, db_list_scans
  db_update_bpm, db_update_key, db_update_lufs, db_update_analysis, db_backfill_audio_meta
  db_get_analysis, db_unanalyzed_paths, db_audio_library_paths, db_migrate_json
  db_cache_stats, db_clear_caches, db_clear_cache_table

Import/export TOML
  export_toml, import_toml

ALS + MIDI authoring + sample crates
  generate_als_project, cancel_als_generation
  generate_midi_lead, generate_midi_kits, generate_trance_starter, find_trance_samples
  clear_als_sample_blacklist, get_als_blacklist_count, get_als_blacklist_entries, add_to_als_blacklist, remove_from_als_blacklist
  get_als_whitelist_entries, get_als_whitelist_count, add_to_als_whitelist, remove_from_als_whitelist, clear_als_whitelist
  als_query_samples, crate_category_counts, crate_facets, genre_rules_report, crate_query
  crate_favorite_pack_toggle, crate_favorite_packs_list, crate_similar_candidates

Embedded terminal
  terminal_spawn, terminal_write, terminal_resize, terminal_kill

Folder watch
  start_file_watcher, stop_file_watcher, get_file_watcher_status

Rust modules (src-tauri/src)

One file per concern where possible; heavy lifting is split so IPC handlers stay thin.

  • lib.rs / main.rs — Tauri builder, generate_handler, window restore, plugin registration.
  • db.rs — SQLite with WAL; dedicated writer mutex vs round-robin read pool (see module docs — avoids starving UI queries during migrations/writes).
  • history.rs — scan snapshots, preferences merge, typed history structs per domain.
  • scanner.rs — plugin inventory; audio_scanner.rs, daw_scanner.rs, preset_scanner.rs, midi_scanner.rs, pdf_scanner.rs, video_scanner.rs — parallel domain walkers.
  • als_project.rs, als_generator.rs, track_generator.rs, trance_generator.rs, midi_generator.rs — ALS project config, template/XML + gzip I/O, techno/schranz/trance arrangement, MIDI helpers for generated sets.
  • unified_walker.rs — single filesystem pass feeding the same progress channels as standalone scans.
  • audio_engine.rs — subprocess lifecycle + JSON RPC bridge for decode, transport, DSP, optional plugins.
  • bpm.rs / key_detect.rs / lufs.rs — analysis primitives; similarity.rs, content_hash.rs — chromaprint / duplicate detection helpers.
  • kvr.rs — KVR resolve + update queue integration.
  • xref.rs — DAW project cross-reference and cached plugin lists per project.
  • file_watcher.rs — notify-based rescans from configured roots.
  • midi.rs, pdf_meta.rs — format-specific metadata extraction.
  • path_norm.rs, scanner_skip_dirs.rs, audio_extensions.rs, bulk_stat.rs — path rules, skipping, and IO batching.
  • open_with_app.rs — platform “open with” / reveal patterns.
  • terminal.rs — embedded PTY terminal: terminal_spawn, terminal_write, terminal_resize, terminal_kill. Reader buffers incomplete UTF-8 tails across read() calls so split multi-byte chars do not get dropped by from_utf8_lossy; xterm.js’s Ctrl+L handler calls term.clear() before the write so the scrollback flushes (the ESC[2J alone does not).
  • app_i18n.rs — loads catalogs for get_app_strings; native_menu.rs, tray_menu.rs — menu bar + tray popover wiring.
  • app_activity_macos.rs (macOS) — App Nap mitigation: holds an NSProcessInfo activity assertion for process lifetime, registers NSApplicationDidResignActive / DidBecomeActive observers that log background-mode transitions to app.log. Installed from RunEvent::Ready (not setup()) and wrapped in objc2::exception::catch.
  • space_preview_macos.rs (macOS) — Mission Control / Spaces / Cmd-Tab snapshot fix: layers a periodically-refreshed NSImageView overlay above the WKWebView so the WindowServer’s out-of-Space snapshot grabs a bitmap-backed CALayer instead of an empty CARemoteLayer (WebKit bug 146877). Walks the runtime superclass chain via class_getName to match wry’s WryWebView subclass.
  • tray_popover_escape_macos.rs (macOS) — installs an NSEvent local key-monitor so Escape closes the tray popover even when the popover’s WKWebView never becomes first responder (JS keydown would otherwise never fire).

SQLite & performance notes

The database layer is documented in-source: WAL mode, a single writer connection for migrations and serialized writes, and a pool of read-only handles rotated for db_query_* so one long query does not block the whole UI.

  • Filter stats — capped aggregation helpers back tab headers and multi-filter UX without loading entire tables into the WebView.
  • Analysis columns — BPM, musical key, LUFS, and batch backfill commands keep the library table the source of truth for sort/filter.
  • Cachesdb_cache_stats / db_clear_cache_table expose maintenance for derived tables (fingerprints, xref, etc.) without nuking raw library rows.

Audio engine subprocess

The UI talks to a separate audio-engine binary via audio_engine_invoke (see frontend/js/audio-engine.js). Rust forwards JSON messages, restarts the child when needed, and exposes EOF watchdog hooks so backgrounded WebViews still advance transport when macOS throttles timers.

  • Playback — file load, seek, speed, reverse, loop modes, gain/pan/mono, multi-band EQ.
  • Optional analysis path — spectrum bins for the visualizer when enabled.
  • Plugin hosting — VST3/AU insert chain with editor windows where supported.
  • Keep-alive ping — host’s HEALTH sampler sends { "cmd": "ping" } every 30 s when the previous window had fewer than 5 IPC calls, keeping JUCE’s working set resident in RAM so the first playback_load after long idle does not block on page-in.
  • Fatal-signal crash dump — engine installs a signal-safe handler on SIGSEGV / SIGBUS / SIGABRT that writes [ENGINE crash] handler entered, fatal signal <n> si_addr=0x…, raw frame addresses, and the dyld image map to engine.log before the helper aborts. Symbolicate the addresses against the dyld bases with atos to recover function names.
  • Testspnpm run test:audio-engine exercises the JSON surface from Node without the full Tauri shell.

Frontend js/ module index

Every module below is plain browser JS loaded by frontend/index.html (order matters for globals — release builds may differ from dev bundling assumptions; cross-file calls are guarded where noted in source).

Shell & IPC

  • app.js — boot, tab wiring, global listeners.
  • ipc.jswindow.vstUpdater, string hydration, menu-action routing.
  • utils.js — shared helpers (formatting, DOM, async guards).

Tabs & data

  • plugins.js, daw.js, presets.js, midi.js, pdf.js — table UX per inventory type.
  • history.js, walker-status.js — scan runs and live walker HUD.
  • xref.js, dep-graph.js, disk-usage.js — DAW xref, dependency graph, disk strip.
  • smart-playlists.js, duplicates.js, heatmap-dashboard.js — library intelligence views.
  • file-browser.js, native-file-drag.js — Files tab and native drag metadata.

Playback & engine

  • audio.js — floating player, history, tray sync, autoplay chains.
  • audio-engine.js — JSON client for the subprocess engine.
  • audio-decode-worker.js — off-main-thread decode for waveforms/spectrograms.
  • visualizer.js — spectrum/waveform presentation.

Settings, i18n, palette

  • settings.js, settings-search.js — prefs UI and fuzzy search over settings keys.
  • i18n-ui.js — reapplies translated strings and locale toggles.
  • command-palette.js — Cmd/Ctrl+K launcher + DB preview queries.
  • shortcuts.js — keymap persistence + executeShortcut.
  • kvr.js — KVR resolve/update UX.

Desktop polish

  • context-menu.js, tooltip-hover.js, help-overlay.js, modal-drag.js.
  • keyboard-nav.js, batch-select.js, drag-reorder.js, sort-persist.js, columns.js.
  • multi-filter.js, favorites.js, notes.js, export.js.
  • ui-idle.js — backs off animations when the window is not visible.
  • terminal.js — embedded PTY terminal (xterm.js, drag-to-dock, resize, Ctrl+T).
  • tray-popover.js — separate WebView HUD (loaded from tray-popover.html).

Static docs styling

This page shares hud-static.css with the generated i18n audit report so file:// and tauri:// views stay visually aligned. hud-theme.js wires theme toggle, CRT overlay, neon pulse, and the same color-scheme grid as the app HUD.

  • i18n auditpnpm run i18n:audit writes reports/i18n_catalog_audit.html by default (override with -o). Open that file after generation; it inlines CSS from hud-static.css for a self-contained artifact.
  • Catalog maintenancepnpm run i18n:sort normalizes key ordering; i18n:sort:check fails CI-style when catalogs drift.

Repository

Tests (quick ref)

Counts change with every commit; run locally for current totals.

  • Rust: cargo test --manifest-path src-tauri/Cargo.toml
  • JavaScript: pnpm run test:js — pure helpers and micro-tests; not DOM/Tauri/E2E (see README)
  • Combined: pnpm test