Consolidates everything the desktop app depends on into app-desktop/ so it
packages cleanly as a standalone Windows exe:
- app-desktop-macos/ -> app-desktop/src/ (drop macOS-only naming, app now
targets Windows via PyInstaller too)
- remote-server/ws_server.py and app-presets/ moved into app-desktop/src/
(both were exclusive dependencies of main.py/presets.py) — fixes a
PyInstaller "missing module" error for ws_server that only surfaced once
packaging was attempted, since its old location wasn't on the analyzer's
search path
- .venv relocated into app-desktop/src/ alongside the code it serves
- run.py moved into src/, path logic simplified now that it's co-located
with main.py instead of bridging from the repo root
- Deleted app/, server/ — stale __pycache__-only fossils from prior reorgs
- .gitignore: added missing .venv/ entry (was only covering venv/, a
different name — the real folder was never actually ignored) and
app-desktop/build|dist/ for PyInstaller output
presets.py: added a frozen-vs-source branch. Running from source is
unchanged (app-presets/ next to the code). A packaged exe can't write to
Program Files, so it uses %APPDATA%\VirtualController\ instead — standard
Windows convention. First launch on a machine with no AppData presets yet
seeds from presets.json bundled into the exe (PyInstaller --add-data,
baked into VirtualController.spec), so a fresh install starts with real
presets instead of empty; every launch after that only touches AppData.
Verified: exe builds clean (no missing-module warnings), launches with a
real window, and a clean first-launch correctly seeds AppData from the
bundled presets.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
extension-reaper-macos: split main.cpp into tracking.cpp (polls selected
envelope/automation items, reads/writes D_BASELINE) and socket.cpp (basic
UDP listener, non-blocking, drains all pending packets per tick). Nudging
now applies to every selected automation item across every track in the
project, not just the first one found.
app-desktop-macos: new "Extension" column (mirrors the OSC/Remote columns)
to enable/disable the UDP connection and point it at a host/port, plus a
log window. FocusFaderWidget gets an OSC/Ext output-mode toggle (mirrors
TransportWidget's MIDI/OSC toggle) so a fader can drive the extension
directly instead of/alongside OSC. Also renamed the Remote/Tablet buttons
for clarity and split their status indicator into its own column.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
C/C++ extension built directly against the vendored Cockos reaper-sdk
headers (no Rust/reaper-rs wrapper layer). Loads, registers a test
action, and confirms via REAPER's console — confirmed working in
REAPER 2026-07-15.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Stripped upstream git history; starting point for replacing the native
SWELL/Win32 mapping UI with something more suited to bulk editing.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Desktop:
- New dedicated MIDI Controller In port (separate from MIDI In), same CC learn/bind pipeline but never passes notes through; positioned first in the IO column order
- Fixed MIDI In "Not Connected" not persisting across restart (missing save_io_config call)
- Fixed MIDI Out/Transport Out mutual-exclusion incorrectly flagging "Not Connected" as an in-use port
- Renamed "Remote" checkbox to "App" on Fader/Toggle/Transport widgets
- FocusFaderWidget/FocusToggleWidget: new Hardware section (Learn + CC/CH bind) so a physical controller can drive a Channel Focus widget alongside the app/OSC, plus an independent Feedback checkbox that sends translated CC out (for motorized fader / LED sync)
- JL Cooper touch-sense profile ("No Profile" / "MIDI JL Cooper CC Mode") on FaderWidget/FocusFaderWidget: touch channel (value channel - 1, same CC) is filtered out of the value and gates incoming OSC/DAW feedback while touching
- FocusFeedbackWidget: "Custom" checkbox to show a manually-typed static string instead of live OSC feedback, disabling Learn/OSC input and suppressing the iPad broadcast while active
- New daw-config-reaper/ folder with reaper-osc-config-paul-custom.ReaperOSC
iOS:
- New FocusToggleWidget (dedicated Channel Focus toggle, split out of shared ToggleWidget) with colorName-aware darken/border and isMomentary handling — keeps Channel-Focus-only behavior off the regular ToggleWidget
- Arrange mode long-press menu: text alignment (left/center/right) and a 10-color named-palette Text Color picker for TitleWidget/FocusFeedbackWidget, persisted in the saved layout
- FocusFeedbackWidget: Reset Size action, monospaced-digit font fix for timestamp/counter jitter
- New "Cancel Changes" button in Arrange mode — reverts layout/hides/aligns to the state at Arrange-mode entry and restores desktop-side Remote/dest assignments
- Grid line brightness increased for visibility
- Bonjour discovery for desktop auto-connect
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>