Refonte en rust : https://github.com/JulienCr/xtouch-gw
Passerelle Node.js/TypeScript pour piloter Voicemeeter, QLC+ et OBS depuis un Behringer X‑Touch (MIDI DIN).
- Unifier plusieurs applications sous une seule surface de contrôle (X‑Touch), sans reconfigurer chaque appli.
- Profiter d’une synchro bidirectionnelle fiable (faders motorisés, LEDs, LCD) avec snapshot au boot et à chaque changement de page.
- Structurer les usages par « pages » pour basculer instantanément entre des profils (son, lumières, régie vidéo).
- Acheminer et transformer le MIDI au besoin (bridges/passthroughs, PitchBend → CC/Note pour compat QLC+).
- Déployer une config simple en YAML avec hot‑reload et outils de debug (CLI + sniffer).
L’app gère notamment:
- Système de pages: définissez plusieurs pages de mapping et passez de l’une à l’autre depuis la X‑Touch. Par défaut, deux notes MIDI (46=précédent, 47=suivant) sur un canal configurable déclenchent le changement de page.
- Bridges MIDI par page (passthroughs) et bridge global Voicemeeter
- Feedback vers la surface (faders motorisés, LCD, LEDs) et labels LCD
- CLI de développement (learn/sniffer/fader/lcd) et Sniffer Web MIDI
flowchart LR
XT["🎛 X‑Touch"] --> XTD["XTouchDriver"]
XTD --> R["Router (pages)"]
R --> VMDr["VoicemeeterDriver"]
R --> QLCDr["QLCDriver"]
R --> OBSDr["OBSDriver"]
VMDr --> VM["Voicemeeter"]
QLCDr --> QLC["QLC+"]
OBSDr --> OBS["OBS"]
VM --> VMDr
QLC --> QLCDr
OBS --> OBSDr
C["Config (YAML, hot‑reload)"] --> R
C --> VMDr
C --> QLCDr
C --> OBSDr
VMDr --> XTD
QLCDr --> XTD
OBSDr --> XTD
Diagrammes détaillés dans docs/specifications.md.
- Node.js >= 24.1
- pnpm (via Corepack)
corepack enable
pnpm installpnpm dev # lancement en développement (tsx watch)
pnpm build # transpile TypeScript → dist/
pnpm start # exécute dist/index.js
pnpm test # tests unitaires (Vitest) + couverture
pnpm test:watch # tests en mode watchPour activer des logs détaillés (PowerShell):
$env:LOG_LEVEL="debug"; pnpm devFichier lu au démarrage, avec hot‑reload. Exemple réaliste aligné sur le code actuel:
midi:
input_port: "UM-One"
output_port: "UM-One"
paging:
channel: 1 # canal NoteOn pour la navigation
prev_note: 46 # page précédente
next_note: 47 # page suivante
pages:
- name: "Voicemeeter+QLC"
lcd:
labels: # 8 scribble strips (0..7). Supporte "\n" pour 2 lignes.
- "Mic\nBaba"
- "Mic\nMath"
- "Mic\nJu"
- "Son\nMac"
- "Son\nPC"
- "Son\nMASTER"
- "Son\nRetours"
- "Lum\nFace"
passthroughs:
- driver: "midi"
to_port: "xtouch-gw"
from_port: "xtouch-gw-feedback"
filter:
channels: [1,2,3,4,5,6,7]
types: ["noteOn","noteOff","controlChange","pitchBend"]
includeNotes: [0,8,16,24]
- driver: "midi"
to_port: "qlc-in"
from_port: "qlc-out"
filter:
channels: [8,9]
types: ["noteOn","noteOff","controlChange","pitchBend"]
transform:
pb_to_cc:
target_channel: 1
base_cc: "0x45" # ch1→0x46, ch2→0x47, …
controls: {} # mappings (router) – optionnels à ce stade
# Exemple de mapping MIDI direct global (sans passer par un bridge):
# Convertit automatiquement PB→CC si le fader émet en PitchBend.
# Ici: fader1 → CC81 ch1 sur le port QLC (qlc-in)
controls:
fader1:
app: "qlc"
midi:
type: "cc"
channel: 1
cc: 81
- name: "Default"
controls: {}Comportement:
- Si au moins une page définit
passthrough/passthroughs, le mode passthrough par page est actif. À chaque changement de page, les bridges de la page sont (ré)ouverts. - Sinon, un bridge global X‑Touch ⇄ Voicemeeter est activé automatiquement (
xtouch-gw/xtouch-gw-feedback).
- Navigation entre pages via NoteOn sur
paging.channel(par défaut ch=1) avecprev_note(46) etnext_note(47). - Labels LCD par page via
pages[].lcd.labels:- soit une chaîne avec saut de ligne
upper\nlower - soit un objet
{ upper, lower }
- soit une chaîne avec saut de ligne
- Si aucun label n’est fourni, le nom de la page est affiché en haut du strip 0.
La CLI se lance avec l’application et offre:
pages,page <idx|name>emit <controlId> [value]midi-ports,midi-open <idx|name>,midi-closelearn <id>(propose uncontrolIdet une ligne YAML)fader <ch> <0..16383>(moteur)lcd <strip0-7> <upper> [lower]
Détails et workflow anti‑conflits de ports dans docs/CLI.md.
pnpm sniff:webOuvre ensuite http://localhost:8123/ pour voir les messages MIDI en hex avec Δ temps.
- Variable
LOG_LEVEL:error | warn | info | debug | trace. - Exemple (PowerShell):
$env:LOG_LEVEL="debug"; pnpm dev
- Après des changements de logique, redémarrer le process (ou rebuild) pour éviter un ancien comportement chargé en mémoire.
- En cas de boucle MIDI (loopMIDI en sécurité), couper un des ponts/bridges, vérifier les filtres, puis redémarrer les ports.
- Vérifier les noms de ports
midi.input_port/midi.output_portet les ports des bridges.
MPL-2.0 (Mozilla Public License 2.0)