{"id":50797778,"url":"https://github.com/jcksnvllxr80/midicontrollercontrollerapp","last_synced_at":"2026-06-12T16:01:25.788Z","repository":{"id":363225722,"uuid":"1262235569","full_name":"jcksnvllxr80/MidiControllerControllerApp","owner":"jcksnvllxr80","description":"Native desktop app to configure and control a MIDI guitar-pedal controller over USB/serial. Built with Tauri, Svelte, and Rust.","archived":false,"fork":false,"pushed_at":"2026-06-08T01:08:34.000Z","size":222,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-08T02:23:29.162Z","etag":null,"topics":["midi","rust","serial","svelte","tauri"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jcksnvllxr80.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-06-07T18:37:05.000Z","updated_at":"2026-06-08T01:08:37.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/jcksnvllxr80/MidiControllerControllerApp","commit_stats":null,"previous_names":["jcksnvllxr80/midicontrollercontrollerapp"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/jcksnvllxr80/MidiControllerControllerApp","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcksnvllxr80%2FMidiControllerControllerApp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcksnvllxr80%2FMidiControllerControllerApp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcksnvllxr80%2FMidiControllerControllerApp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcksnvllxr80%2FMidiControllerControllerApp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jcksnvllxr80","download_url":"https://codeload.github.com/jcksnvllxr80/MidiControllerControllerApp/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jcksnvllxr80%2FMidiControllerControllerApp/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34251773,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["midi","rust","serial","svelte","tauri"],"created_at":"2026-06-12T16:01:24.492Z","updated_at":"2026-06-12T16:01:25.778Z","avatar_url":"https://github.com/jcksnvllxr80.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MidiController Controller App\n\nNative desktop app for configuring and controlling the MidiController, built with\n**Tauri v2 + Svelte + TypeScript**. It replaces the old web app + HTTP-to-a-Pi bridge:\nthe controller is now reached over a **pluggable transport** (Serial / USB now;\nWi-Fi / Ethernet later), discovered by scanning on connect.\n\nSee [`docs/plan.md`](docs/plan.md) for the full design and roadmap.\n\n## Architecture at a glance\n\n```\nSvelte UI ──invoke()/listen()──▶ Rust commands ──▶ Transport trait\n(Connect/Control/                 (scan/connect/        ├─ SerialTransport (serialport)\n Configure/JSON)                   disconnect/          ├─ UsbTransport   (nusb)\n                                    send_request)        ├─ MockTransport  (in-memory)\n                                                         └─ Wi-Fi/Ethernet (future)\n                                                              │ newline-JSON wire protocol\n                                                              ▼  firmware IConfigTransport\n```\n\nThe UI talks only to `src/lib/transport.ts`; it never knows which link is in use.\nThe wire protocol (`src-tauri/src/protocol/`) is one framed JSON request/response channel\nthat unifies the web app's old config (:8081) and control (:8090) HTTP APIs, and is meant to\nmatch the firmware's `IConfigTransport` (see the `MidiControllerCpp` repo).\n\n## Project layout\n\n```\nsrc/                       Svelte frontend\n  main.ts · App.svelte\n  routes/                  Connect · Control · Configure · JsonView\n  lib/                     transport.ts · protocol.ts · stores.ts\n  assets/devices/*.svg     per-protocol device-card icons\nsrc-tauri/                 Rust backend\n  src/\n    commands.rs            scan_devices / connect_device / disconnect_device /\n                           send_request / connection_status  (+ events)\n    state.rs               registry + active connection (Arc\u003cMutex\u003e)\n    error.rs               AppError\n    transport/             mod.rs (Transport trait) · registry.rs ·\n                           serial.rs · usb.rs · mock.rs\n    protocol/              mod.rs (Request/Response) · codec.rs (JSON-lines framing)\ndocs/plan.md               design + roadmap\n```\n\n## Prerequisites\n\n- **Node.js** 18+ (tested on 20.x) and **npm**\n- **Rust** stable — `rustc` / `cargo`, installed via [rustup](https://rustup.rs)\n- **WebView runtime**:\n  - Windows — WebView2 (preinstalled on Windows 11)\n  - macOS — WKWebView (built in)\n  - Linux — `webkit2gtk` + the standard [Tauri Linux build deps](https://v2.tauri.app/start/prerequisites/)\n\nThe Tauri **v2** CLI is pinned in `devDependencies`, so there is nothing to install globally —\nalways invoke it via `npm run tauri …`. (A globally installed `cargo tauri` may be v1; ignore it.)\n\n## Quick start\n\n```bash\nnpm install            # frontend deps + the local Tauri v2 CLI\nnpm run tauri dev      # compiles the Rust backend, starts Vite, opens the app (hot reload)\n```\n\nOn launch you get a **Connect** screen. Click **Scan** to enumerate devices across all\ntransports; each shows an image, name, and protocol. A **Mock MidiController (dev)** device is\nalways present, so you can drive the entire UI with no hardware attached. Set the env var\n`MIDICTRL_NO_MOCK=1` before launching to hide it.\n\n## Build\n\n```bash\nnpm run build          # frontend only -\u003e static assets in dist/\nnpm run tauri build    # full desktop app + native installers (release)\n```\n\n`npm run tauri build` outputs the binary and platform installers under\n`src-tauri/target/release/` (bundles in `src-tauri/target/release/bundle/`):\n\n| Platform | Artifacts |\n|---|---|\n| Windows | `.msi` (WiX) and `.exe` (NSIS) |\n| macOS | `.app` and `.dmg` |\n| Linux | `.deb` and `.AppImage` |\n\nBackend only (no bundling):\n\n```bash\ncd src-tauri \u0026\u0026 cargo build              # debug\ncd src-tauri \u0026\u0026 cargo build --release    # optimized\n```\n\n## Test\n\n```bash\nnpm test                       # frontend tests (Vitest + jsdom)     — 52 tests\nnpm run check                  # type-check Svelte + TS (svelte-check) — 0 errors\ncd src-tauri \u0026\u0026 cargo test     # backend unit + e2e tests            — 125 tests\n```\n\nRun the whole gate in one line (works in bash and PowerShell 7):\n\n```bash\nnpm test \u0026\u0026 npm run check \u0026\u0026 npm run build \u0026\u0026 cargo test --manifest-path src-tauri/Cargo.toml\n```\n\nWhat's covered (**177 tests total**):\n\n- **Backend (`cargo test`, 125)** — protocol serde + the exact per-`op` wire strings;\n  JSON-lines codec framing (encode / line-read / roundtrip; noise, wrong-id, stale-id,\n  large/nested payloads); every Mock op with parametric coverage (all d-pad directions,\n  all buttons, all entity kinds); registry fan-out + protocol mapping; Serial/USB discovery\n  shape + connect guards; `AppState` connect/disconnect/send/status; error serialization;\n  and an **end-to-end wire harness** (`wire_e2e.rs`) that runs full sessions against a fake\n  firmware speaking the framed protocol over a real byte stream.\n- **Frontend (`npm test`, 52)** — protocol constants + the same 18-op wire contract mirrored\n  on the TS side; the `transport.ts` invoke/listen wrappers against a mocked Tauri bridge;\n  and **component tests** (Testing Library + jsdom) driving the real Svelte views —\n  Connect (scan → device cards → connect, empty/error states), Control (every d-pad/button →\n  correct op + display), Configure (list/select/new/save/delete/tabs/invalid-JSON), JSON\n  view, and the App shell (connect gating, nav, disconnect, live status events).\n\nThe 18-op wire contract is asserted from **both** languages, so any Rust↔TS drift fails a test.\n\n## Troubleshooting\n\n- **`tauri` runs the wrong version** — always use `npm run tauri …`; the v2 CLI is local to this\n  project. A global `cargo tauri` may be an older v1 install.\n- **Vite / Node engine errors** — Vite 6 needs Node 18+. On Node 20.10 stay on Vite 6 (not 7);\n  `npm install` already pins compatible versions.\n- **Scan shows no devices** — the Mock device should always appear; if it doesn't, ensure\n  `MIDICTRL_NO_MOCK` is unset. Real serial/USB devices only show when plugged in.\n- **`npm run tauri build` fails on Linux** — install the Tauri Linux system dependencies\n  (`webkit2gtk`, `librsvg`, …) per the prerequisites link above.\n\n## Status\n\n| Area | State |\n|---|---|\n| Tauri v2 + Svelte + TS shell, Connect/Control/Configure/JSON | ✅ working |\n| Transport trait + registry + JSON-lines protocol + codec | ✅ working |\n| MockTransport (full protocol, seeded data) | ✅ working |\n| SerialTransport — discover / connect+identify / request | ✅ implemented (needs firmware speaking the wire protocol to round-trip) |\n| UsbTransport — **discovery** by VID/PID | ✅ working |\n| UsbTransport — connect / request | ⛔ stub, pending the firmware's USB descriptor (CDC vs vendor/HID) — see plan Open Q#1 |\n| Wi-Fi / Ethernet transports | ⛔ not started (same trait, future) |\n| Configure editor | functional per-entity JSON editor (list/get/write/delete); full bespoke pedal/param UI is a later pass |\n\n## Notes / open coordination\n\n- **Wire protocol** (`src-tauri/src/protocol/`) must match the firmware's `IConfigTransport`.\n  It is documented as the source of truth to co-design with the firmware effort.\n- **Serial vs USB**: if the firmware enumerates as a USB-CDC virtual COM port, use the\n  Serial transport (it covers CDC) and `usb.rs` stays a stub. If it exposes a vendor/HID USB\n  interface, fill in `usb.rs` connect/request. Set `FIRMWARE_FILTER` in `usb.rs` to the\n  firmware's VID/PID to narrow discovery.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjcksnvllxr80%2Fmidicontrollercontrollerapp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjcksnvllxr80%2Fmidicontrollercontrollerapp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjcksnvllxr80%2Fmidicontrollercontrollerapp/lists"}