{"id":47595969,"url":"https://github.com/bernardopg/ioruba","last_synced_at":"2026-05-22T22:01:07.151Z","repository":{"id":329881275,"uuid":"1120867289","full_name":"bernardopg/ioruba","owner":"bernardopg","description":"DIY Arduino-driven desktop audio mixer built with Tauri 2, React, TypeScript, and Rust.","archived":false,"fork":false,"pushed_at":"2026-05-22T21:38:12.000Z","size":5164,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-22T21:49:32.190Z","etag":null,"topics":["arduino-nano","audio-mixer","hardware-control","linux-audio","pipewire","react","rust","serial-communication","tauri","typescript"],"latest_commit_sha":null,"homepage":"https://bernardopg.github.io/ioruba/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bernardopg.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","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},"funding":{"github":["bernardopg"],"buy_me_a_coffee":"WctwoM9eMU"}},"created_at":"2025-12-22T04:30:22.000Z","updated_at":"2026-05-22T21:38:15.000Z","dependencies_parsed_at":"2026-05-22T20:02:20.604Z","dependency_job_id":null,"html_url":"https://github.com/bernardopg/ioruba","commit_stats":null,"previous_names":["bernardopg/iaruba","bernardopg/ioruba"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/bernardopg/ioruba","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bernardopg%2Fioruba","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bernardopg%2Fioruba/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bernardopg%2Fioruba/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bernardopg%2Fioruba/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bernardopg","download_url":"https://codeload.github.com/bernardopg/ioruba/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bernardopg%2Fioruba/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33372736,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-22T21:56:13.512Z","status":"ssl_error","status_checked_at":"2026-05-22T21:56:10.769Z","response_time":265,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["arduino-nano","audio-mixer","hardware-control","linux-audio","pipewire","react","rust","serial-communication","tauri","typescript"],"created_at":"2026-04-01T18:04:50.485Z","updated_at":"2026-05-22T22:01:07.144Z","avatar_url":"https://github.com/bernardopg.png","language":"TypeScript","funding_links":["https://github.com/sponsors/bernardopg","https://buymeacoffee.com/WctwoM9eMU","https://www.buymeacoffee.com/WctwoM9eMU"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n[![Release workflow](https://github.com/bernardopg/ioruba/actions/workflows/release.yml/badge.svg)](https://github.com/bernardopg/ioruba/actions/workflows/release.yml)\n[![CI workflow](https://github.com/bernardopg/ioruba/actions/workflows/ci.yml/badge.svg)](https://github.com/bernardopg/ioruba/actions/workflows/ci.yml)\n[![Version](https://img.shields.io/github/package-json/v/bernardopg/ioruba?filename=package.json\u0026label=version)](package.json)\n[![Project status](https://img.shields.io/badge/status-active%20development-2ea043)](TODO.md)\n[![Last commit](https://img.shields.io/github/last-commit/bernardopg/ioruba?label=last%20commit)](https://github.com/bernardopg/ioruba/commits/main)\n[![License: MIT](https://img.shields.io/badge/license-MIT-0A66C2)](LICENSE)\n\n\u003cbr /\u003e\n\n[![GitHub Sponsors](https://img.shields.io/badge/GitHub%20Sponsors-30363D?logo=GitHub-Sponsors\u0026logoColor=EA4AAA)](https://github.com/sponsors/bernardopg)\n[![Buy Me a Coffee](https://img.shields.io/badge/Buy%20Me%20a%20Coffee-FFDD00?logo=buy-me-a-coffee\u0026logoColor=black)](https://www.buymeacoffee.com/WctwoM9eMU)\n\n\u003cbr /\u003e\n\n[![Tauri 2](https://img.shields.io/badge/Tauri-2-24C8DB?logo=tauri\u0026logoColor=fff)](https://tauri.app/)\n[![Rust](https://img.shields.io/badge/Rust-%23000000.svg?logo=rust\u0026logoColor=white)](https://www.rust-lang.org/)\n[![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?logo=typescript\u0026logoColor=fff)](https://www.typescriptlang.org/)\n[![C++](https://img.shields.io/badge/C++-%2300599C.svg?logo=c%2B%2B\u0026logoColor=white)](https://isocpp.org/)\n[![Arduino Nano](https://img.shields.io/badge/Arduino%20Nano-00979D?logo=arduino\u0026logoColor=white)](https://www.arduino.cc/)\n[![Node.js 22](https://img.shields.io/badge/Node.js-22-5FA04E?logo=node.js\u0026logoColor=white)](https://nodejs.org/en)\n[![PT-BR Docs](https://img.shields.io/badge/docs-PT--BR-0A66C2?logo=readthedocs\u0026logoColor=white)](docs/translations/pt-br/README.md)\n\n\u003cbr /\u003e\n\n[![Linux: Supported](https://img.shields.io/badge/Linux-supported-3FB950?logo=linux\u0026logoColor=black)](#platform-support)\n[![macOS: Partial](https://img.shields.io/badge/macOS-partial-A0A0A0?logo=apple\u0026logoColor=white)](#platform-support)\n[![Windows: Partial](https://img.shields.io/badge/Windows-partial-0078D6?logo=windows11\u0026logoColor=white)](#platform-support)\n[![Arch Linux](https://img.shields.io/badge/Arch%20Linux-compatible-1793D1?logo=arch-linux\u0026logoColor=fff)](#platform-support)\n\n\u003c/div\u003e\n\n# Ioruba\n\nIoruba transforms an **Arduino Nano + 3 knobs** into a tactile desktop control deck.\nThe active stack is a **Tauri 2 + React + TypeScript** desktop app backed by a **Rust** audio layer (using `pactl` on Linux) and **Arduino C++** firmware for the physical controller.\n\n\u003e **Current platform status**\n\u003e Real audio control is production‑ready on **Linux** via `pactl`.\n\u003e macOS and Windows builds are useful for UI review, packaging checks, and demo mode, but they do **not** yet provide a functional audio backend.\n\n## 📚 Quick links\n\n- [Releases](https://github.com/bernardopg/ioruba/releases)\n- [Quick Start](QUICKSTART.md)\n- [Hardware Setup](docs/guides/hardware-setup.md)\n- [Nano Setup](NANO_SETUP.md)\n- [Profile Examples](docs/guides/profile-examples.md)\n- [Translation Guide](docs/guides/translation-guide.md)\n- [PT‑BR Docs](docs/translations/pt-br/README.md)\n- [Support \u0026 Debugging](docs/debug/support.md)\n- [Testing](TESTING.md)\n- [Contributing](CONTRIBUTING.md)\n- [Funding](FUNDING.md)\n- [Roadmap](TODO.md)\n\n![Ioruba visual reference](/docs/assets/screenshot.png)\n_Archived screenshot – provides a visual reference for the tactile dashboard direction._\n\n---\n\n## 🎛️ Why this repository exists\n\nThe project preserves the hands‑on feel of a small mixer while modernising the software stack:\n\n- **Desktop runtime** – `apps/desktop` (Tauri 2, React, TypeScript, Zustand)\n- **Firmware** – `firmware/arduino/ioruba-controller` (Arduino Nano C++)\n- **Shared logic** – `packages/shared` (TypeScript domain types, protocol parsing, runtime math)\n- **Linux audio backend** – Rust implementation using `pactl` (master, application, source, sink targets)\n- **Persistence** – JSON profiles stored in the app’s config directory\n- **CI** – validates TypeScript, Rust, and firmware compilation\n- **Legacy** – an archived Python/GTK prototype remains under `legacy/` for historical reference\n\n## ✅ What you get today\n\n- Serial packets like `512|768|1023` (three 10‑bit values)\n- Firmware handshake: `HELLO board=...; fw=...; protocol=...; knobs=...`\n- Backward compatibility with legacy packet format `P1:512`\n- Live telemetry and a persistent watch log inside the desktop app\n- Editable JSON profiles (stored per‑platform config directory)\n- Demo mode for UI validation without touching system audio\n- Linux audio target handling for **master**, **application**, **source**, and **sink**\n- CI for desktop/shared validation plus firmware compilation\n- Tagged release workflows producing desktop bundles (`deb`, `rpm`, `AppImage`), firmware artifacts, and Arch packaging metadata (`PKGBUILD` + `.SRCINFO`)\n\n## 🖥️ Platform support\n\n| Platform | Status    | Notes                                                                                             |\n|----------|-----------|---------------------------------------------------------------------------------------------------|\n| Linux    | ✅ Supported | Main production path: serial workflow, `pactl` audio backend, demo mode, hardware validation.    |\n| macOS    | ⚠️ Partial  | Desktop shell and demo‑mode validation work; real audio control not yet implemented.             |\n| Windows  | ⚠️ Partial  | Desktop shell and demo‑mode validation work; real audio control not yet implemented.             |\n\n\u003e **Note:** Linux is the only platform with a production‑ready audio backend (`pactl`) at this time.\n\n## ⚡ Fast installation\n\nPre‑built installers are published under the latest release:\n[https://github.com/bernardopg/ioruba/releases/latest](https://github.com/bernardopg/ioruba/releases/latest)\n\n### Arch Linux (AUR)\n\n```bash\n# Source build\nyay -S ioruba-desktop\n\n# Prebuilt AppImage\nyay -S ioruba-desktop-bin\n```\n\n### Debian / Ubuntu / Linux Mint / Pop!_OS\n\n```bash\ncurl -s https://api.github.com/repos/bernardopg/ioruba/releases/latest \\\n  | jq -r '.assets[] | select(.name | test(\"\\\\.deb$\")) | .browser_download_url' \\\n  | xargs -n1 curl -LO\n\nsudo apt install ./Ioruba_*_amd64.deb\n```\n\n### Fedora / RHEL / CentOS Stream / openSUSE (RPM)\n\n```bash\ncurl -s https://api.github.com/repos/bernardopg/ioruba/releases/latest \\\n  | jq -r '.assets[] | select(.name | test(\"\\\\.rpm$\")) | .browser_download_url' \\\n  | xargs -n1 curl -LO\n\n# If you use dnf (Fedora/RHEL):\nsudo dnf install ./Ioruba-*.x86_64.rpm\n# For zypper (openSUSE) or yum (older CentOS), substitute accordingly.\n```\n\n### Any Linux distro (AppImage)\n\n```bash\ncurl -s https://api.github.com/repos/bernardopg/ioruba/releases/latest \\\n  | jq -r '.assets[] | select(.name | test(\"\\\\.AppImage$\")) | .browser_download_url' \\\n  | xargs -n1 curl -LO\n\nchmod +x Ioruba_*.AppImage\n./Ioruba_*.AppImage\n```\n\n### Windows\n\nDownload the Windows installer assets from the latest release page (`.exe` / `.msi`).\n\n### macOS (Apple Silicon and Intel)\n\nDownload the macOS app bundle archive from the latest release page:\n- `Ioruba_..._aarch64.app.tar.gz`\n- `Ioruba_..._x64.app.tar.gz`\n\n\u003e **Reminder:** On macOS and Windows the app runs in UI/demo mode only; audio control requires Linux.\n\n## 🧰 Prerequisites (for source builds)\n\n- **Node.js** `22` (same major used in CI) + `npm`\n- **Rust** stable + `cargo`\n- `arduino-cli`\n- `pactl` (Linux only, for audio backend)\n- Git\n\n## 🚀 Quick start (source)\n\n```bash\n# 1️⃣ Clone \u0026 install\ngit clone https://github.com/bernardopg/ioruba.git\ncd ioruba\nnpm install\n\n# 2️⃣ Verify the stack\nnpm run verify   # runs typecheck, tests, Rust checks, and desktop build\n\n# 3️⃣ Compile firmware (optional if you already have a flashed board)\nnpm run firmware:compile\n\n# 4️⃣ Launch the desktop app\nnpm run desktop:dev   # Vite frontend only (fast iteration)\nnpm run desktop:watch # Full Tauri desktop shell (serial, persistence, backend)\n\n# 5️⃣ Hardware setup\n#   - Wire the controller → see docs/guides/hardware-setup.md\n#   - Flash the Nano   → see NANO_SETUP.md\n#   - Example profiles → docs/guides/profile-examples.md\n```\n\n### What to confirm when the app opens\n\n1. The app detects serial ports (or uses your preferred port).\n2. The status card progresses through connection states (not stuck on “idle”).\n3. The runtime receives the firmware handshake (`HELLO …`) alongside knob frames.\n4. The **Watch** tab shows frames like `512|768|1023`.\n5. Turning knobs moves the telemetry chart.\n6. The active profile is saved as JSON and survives restarts.\n7. Clicking **Atualizar áudio** refreshes the Linux audio inventory.\n8. Knobs control the configured targets (master volume, apps, microphone, etc.).\n\nDefault profile mapping:\n\n| Knob | Default label      | Target                                         |\n|------|--------------------|------------------------------------------------|\n| 1    | Master Volume      | Default output / master volume                 |\n| 2    | Applications       | Spotify, Google Chrome, Firefox                |\n| 3    | Microphone         | Default microphone input                       |\n\n## 📂 Where the app stores data\n\nThe desktop app persists two files in the platform‑specific config directory:\n\n- `ioruba-state.json` – active profile and runtime state\n- `ioruba-watch.log` – structured watch events (auto‑trimmed to ~1 MiB)\n\n| OS      | Path                                                     |\n|---------|----------------------------------------------------------|\n| Linux   | `~/.config/io.ioruba.desktop/`                           |\n| macOS   | `~/Library/Application Support/io.ioruba.desktop/`       |\n| Windows | `%APPDATA%\\\\io.ioruba.desktop\\\\`                         |\n\n## 🧰 Common npm scripts\n\n| Script                         | Description                                                            |\n|--------------------------------|------------------------------------------------------------------------|\n| `npm run verify`               | Full validation: typecheck, tests, Rust, desktop build.               |\n| `npm run desktop:dev`          | Starts the Vite frontend (UI work).                                    |\n| `npm run desktop:watch`        | Starts the full Tauri desktop shell (development).                    |\n| `npm run desktop:icons`        | Regenerates desktop/icon assets from `app-icon.svg`.                  |\n| `npm run desktop:tauri:build`  | Builds the Tauri app locally (no installers).                         |\n| `npm run firmware:compile`     | Compiles the Arduino Nano firmware.                                   |\n| `npm run rust:test`            | Runs the Rust backend tests.                                          |\n| `npm run rust:audit`           | Audits the Rust lockfile (includes local glib backport).              |\n\n## 🗂️ Repository map\n\n| Path                                 | Purpose                                                                    |\n|--------------------------------------|----------------------------------------------------------------------------|\n| `apps/desktop`                       | Tauri 2 desktop app, React UI, Zustand state, telemetry dashboards.       |\n| `apps/desktop/src-tauri`             | Rust commands (persistence, watch logging, Linux audio control).          |\n| `packages/shared`                    | Shared domain types, defaults, runtime math, protocol parsing.            |\n| `firmware/arduino/ioruba-controller` | Arduino firmware for Nano‑compatible boards.                               |\n| `docs/guides`                        | Practical setup guides (hardware, Nano, profiles, translations).          |\n| `docs/migration`                     | Migration planning and parity audit material.                              |\n| `legacy`                             | Archived Python/GTK prototype and historical leftovers.                   |\n| `docs/debug/support.md`              | Support playbook for serial, audio, and profile‑debug issues.             |\n| `TESTING.md`                         | Automated checks, smoke tests, release validation matrix.                 |\n\n## 📚 Documentation map\n\n| Document                                                          | When you need…                                                            |\n|-------------------------------------------------------------------|---------------------------------------------------------------------------|\n| [QUICKSTART.md](QUICKSTART.md)                                    | Fastest path from zero to a running app (Linux).                         |\n| [NANO_SETUP.md](NANO_SETUP.md)                                    | Flashing and validating the Arduino Nano.                                |\n| [docs/guides/hardware-setup.md](docs/guides/hardware-setup.md)    | Wiring the physical controller (potentiometers, breadboard/enclosure).   |\n| [docs/guides/profile-examples.md](docs/guides/profile-examples.md)| Ready‑to‑paste JSON profile samples and Linux target‑matching rules.     |\n| [docs/guides/translation-guide.md](docs/guides/translation-guide.md)| How translations work in the desktop app and validation steps.          |\n| [docs/translations/pt-br/README.md](docs/translations/pt-br/README.md)| Portuguese translation index for docs and root manuals.                  |\n| [docs/debug/support.md](docs/debug/support.md)                    | Troubleshooting serial, audio, and profile‑related issues.               |\n| [TESTING.md](TESTING.md)                                          | Automated checks, smoke tests, and release validation.                   |\n| [docs/migration/logic-audit.md](docs/migration/logic-audit.md)    | Parity coverage with the archived Python/GTK implementation.             |\n| [CONTRIBUTING.md](CONTRIBUTING.md)                                | Guidelines for contributing code, docs, translations, etc.               |\n| [FUNDING.md](FUNDING.md)                                          | How to support the project (GitHub Sponsors, Buy Me a Coffee, etc.).     |\n| [TODO.md](TODO.md)                                                | Roadmap and upcoming features.                                           |\n\n## 🗃️ Legacy archive\n\nThe repository retains one archived implementation for historical reference:\n\n- `legacy/arduino-audio-controller`\n\nDeeper migration context lives in `docs/migration`. The **active** product surface resides in:\n- `apps/desktop`\n- `packages/shared`\n- `firmware/arduino/ioruba-controller`\n\n## 📜 License\n\nMIT © Bernardo Gomes\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbernardopg%2Fioruba","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbernardopg%2Fioruba","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbernardopg%2Fioruba/lists"}