Transform MIDI controllers and game controllers into advanced macro pads with multi-protocol input, velocity sensitivity, LED feedback, daemon architecture, and visual configuration GUI.
v3.0.0: Multi-protocol input support - MIDI Controllers + Game Controllers (HID) v2.0.0: Full-featured Tauri GUI with MIDI Learn, per-app profiles, device templates, and live event console v1.0.0: Production-ready daemon with 0-10ms config reloads, IPC control, and auto-start support
Velocity-sensitive RGB LED feedback on Native Instruments Maschine Mikro MK3
Conductor now supports multiple input protocols through a unified input system:
- Full MIDI Support - All MIDI message types (Note, CC, Aftertouch, Pitch Bend)
- RGB LED Feedback - Full HID-based LED control for supported devices
- Velocity Sensitivity - Different actions for soft/medium/hard presses
- Device Templates - 6 built-in templates for popular MIDI controllers
- Gamepads: Xbox (360, One, Series X|S), PlayStation (DualShock 4, DualSense), Switch Pro Controller
- Joysticks: Flight sticks, arcade sticks (any SDL2-compatible device)
- Racing Wheels: Logitech, Thrustmaster, any SDL2-compatible racing wheel
- HOTAS: Hands On Throttle And Stick systems
- Custom Controllers: Any SDL2-compatible HID device
- Official Templates: 3 built-in templates (Xbox, PlayStation, Switch Pro)
- Analog Support: Triggers, analog sticks with threshold detection
- Button Chords: Multi-button combinations for complex macros
- Hybrid Workflows - Use MIDI controller + gamepad simultaneously
- Hot-Plug Detection - Automatic device connection/disconnection handling
- MIDI Learn Mode - One-click auto-detection works with both MIDI and gamepad inputs
- Protocol-Agnostic - Same event processing for all input types
- Non-Overlapping IDs - MIDI (0-127), Gamepad (128-255), no conflicts
- Tauri GUI - Modern desktop application for visual configuration
- MIDI Learn Mode - One-click auto-detection of MIDI and gamepad inputs
- Device Templates - 9 built-in templates (6 MIDI + 3 gamepad)
- Per-App Profiles - Automatic profile switching based on active application
- Live Event Console - Real-time input event monitoring and debugging
- Settings Panel - Configure auto-start, theme, and preferences
- Background Daemon - Runs as a system service with auto-start
- Hot-Reload - Configuration changes detected and applied in 0-10ms
- IPC Control - Control daemon via
conductorctlCLI or GUI - Multi-mode operation - Switch between different mapping sets
- Configurable mappings - Visual editor or TOML-based configuration
- Ultra-low latency - Sub-millisecond input response, <20ms config reload
- Cross-platform - Works on macOS and Linux (systemd/launchd)
- Velocity Sensitivity - Different actions for soft/medium/hard presses
- Long Press Detection - Hold actions with configurable thresholds
- Double-Tap Detection - Quick double-tap triggers
- Chord Detection - Multiple buttons/pads pressed simultaneously
- Encoder Direction - Clockwise/counter-clockwise detection
- Analog Sticks - Directional detection with dead zones
- Analog Triggers - Threshold-based trigger actions
- Aftertouch Support - Pressure-sensitive actions (MIDI)
- Pitch Bend Support - Touch strip integration (MIDI)
- Visual Feedback - Real-time LED feedback on supported MIDI devices
- Multiple Schemes - Rainbow, pulse, breathing, reactive, and more
- Mode Indication - Color-coded modes for easy identification
- Velocity Visualization - LED brightness matches pad velocity
- HID Support - Full RGB control for Maschine Mikro MK3
- MIDI LED - Basic feedback for standard MIDI devices
📖 See LED_FEEDBACK.md for complete LED system documentation
| Device | Status | LED Feedback | Notes |
|---|---|---|---|
| Native Instruments Maschine Mikro MK3 | ✅ Full Support | RGB (HID) | Recommended |
| Generic MIDI Controllers | ✅ Supported | Basic (MIDI) | Most features work |
| Akai APC Mini | Basic (MIDI) | Should work | |
| Novation Launchpad | Basic (MIDI) | Should work |
| Controller | Template | Status | Platform Compatibility |
|---|---|---|---|
| Xbox Controller (360, One, Series X|S) | ✅ Official | ✅ Full Support | Windows, macOS, Linux |
| PlayStation Controller (DualShock 4, DualSense) | ✅ Official | ✅ Full Support | Windows, macOS, Linux |
| Nintendo Switch Pro Controller | ✅ Official | ✅ Full Support | Windows, macOS, Linux |
| Generic SDL2-Compatible Gamepads | ✅ Supported | Windows, macOS, Linux |
| Device Type | Template | Status | Notes |
|---|---|---|---|
| Flight Sticks | ✅ Supported | Any SDL2-compatible device works | |
| Arcade Sticks | ✅ Supported | Button mapping via MIDI Learn | |
| HOTAS Systems | ✅ Supported | Full analog axis support |
| Device Type | Template | Status | Notes |
|---|---|---|---|
| Logitech Wheels | ✅ Supported | Steering, pedals, buttons | |
| Thrustmaster Wheels | ✅ Supported | All SDL2 axes supported | |
| Generic Racing Wheels | ✅ Supported | Any SDL2-compatible wheel |
Want to add support for your device? See CONTRIBUTING.md
Download the latest release for your platform:
# Install binaries
sudo install -m 755 conductor /usr/local/bin/
sudo install -m 755 conductorctl /usr/local/bin/
# macOS: Install as LaunchAgent
launchctl load ~/Library/LaunchAgents/com.amiable.conductor.plist
# Linux: Install as systemd service
systemctl --user enable conductor
systemctl --user start conductorSee DEPLOYMENT.md for complete installation and service setup guides.
# Clone the repository
git clone https://github.com/amiable-dev/conductor.git
cd conductor
# Build the workspace (all 3 packages)
cargo build --release --workspace
# Install binaries
sudo install -m 755 target/release/conductor /usr/local/bin/
sudo install -m 755 target/release/conductorctl /usr/local/bin/
# Install man pages
sudo mkdir -p /usr/local/share/man/man1
sudo install -m 644 conductor-daemon/docs/*.1 /usr/local/share/man/man1/Workspace Structure (v1.0.0):
Conductor uses a modular 3-package Cargo workspace:
conductor/
├── conductor-core/ # Pure Rust engine library
│ ├── Public API for embedding (30+ types)
│ ├── Zero UI dependencies
│ └── Event processing, mapping, actions
├── conductor-daemon/ # Background daemon + diagnostic tools
│ ├── Main daemon binary (conductor)
│ ├── CLI control tool (conductorctl)
│ └── 6 diagnostic binaries
└── conductor/ # Backward compatibility layer
└── Re-exports conductor-core (v0.1.0 tests only)
Package Guide:
- Use conductor-core when embedding Conductor as a library
- Use conductor-daemon for standalone CLI/daemon usage
- Use conductor (root) only for v0.1.0 backward compatibility
Public API Example:
use conductor_core::{Config, MappingEngine, EventProcessor, ActionExecutor};
let config = Config::load("config.toml")?;
let mut engine = MappingEngine::new();
// Process MIDI events, map to actions, execute...Build Commands:
# Build entire workspace (all 3 packages)
cargo build --workspace
# Build specific package
cargo build -p conductor-core
cargo build -p conductor-daemon
# Test workspace
cargo test --workspaceRequirements:
- Rust 1.70+ (Install via rustup)
- macOS 11+ or Linux with systemd
- Install binaries (see Installation above)
- Create config at
~/.config/conductor/config.toml - Start daemon:
# macOS launchctl load ~/Library/LaunchAgents/com.amiable.conductor.plist # Linux systemctl --user start conductor
- Control daemon:
conductorctl status # Check daemon status conductorctl reload # Reload configuration conductorctl ping # Test connectivity
- Edit config - Changes are auto-detected and reloaded in <10ms!
- Connect your MIDI controller (e.g., Native Instruments Maschine Mikro MK3)
- Install necessary drivers (Native Instruments Controller Editor for NI devices)
- Run directly:
conductor --config config.toml --log-level debug
- Press pads to trigger macros!
For gamepads with official templates (Xbox, PlayStation, Switch Pro):
- Open Conductor GUI (or use CLI with template config)
- Select Device Template:
- Navigate to "Device Templates" section
- Filter by category: "Gamepad Controllers"
- Choose your controller:
- Xbox Controller (Xbox 360, One, Series X|S)
- PlayStation Controller (DualShock 4, DualSense)
- Switch Pro Controller
- Generate Configuration:
- Click "Create from Template"
- Templates include pre-configured modes:
- Desktop Mode: Navigation, window management, shortcuts
- Media Mode: Playback control, volume adjustment
- Additional Modes: Browser (Switch), Gaming (PlayStation)
- Connect Gamepad and press buttons to trigger actions
- Customize via MIDI Learn or manual TOML editing
Pre-configured Features:
- Face buttons → Enter, Escape, Copy, Paste
- D-Pad → Arrow keys
- Shoulder buttons → Tab navigation
- Guide/Home button → Spotlight search
- Analog triggers → Volume control
- Button chords → Mode switching
For joysticks, racing wheels, HOTAS, or custom controllers:
-
Create Base Configuration:
# Start with minimal config cp config/examples/gamepad-basic.toml ~/.config/conductor/config.toml
-
Use MIDI Learn to Map Buttons:
- Open Conductor GUI
- Enable "MIDI Learn" mode
- Click on a mapping you want to configure
- Press the button/axis on your controller
- Pattern detection will auto-suggest GamepadButton or GamepadAnalogStick
- Save the mapping
-
Manual TOML Configuration Example:
[[modes]] name = "Flight Mode" color = "blue" [[modes.mappings]] description = "Fire primary weapon" [modes.mappings.trigger] type = "GamepadButton" button = 128 # First trigger button [modes.mappings.action] type = "Keystroke" keys = "space" [[modes.mappings]] description = "Pitch control via stick" [modes.mappings.trigger] type = "GamepadAnalogStick" axis = 129 # Y-axis direction = "Up" threshold = 0.5 [modes.mappings.action] type = "Keystroke" keys = "w"
-
Test Your Configuration:
conductorctl reload # Move sticks, press buttons to trigger actions
Button ID Reference (for manual config):
- Face Buttons: 128-131
- D-Pad: 132-135
- Shoulders: 136-137 (bumpers), 143-144 (triggers)
- Stick Clicks: 138-139
- Menu/System: 140-142
- Analog Axes: 128-133 (sticks + triggers)
📖 See technical documentation for complete button/axis mapping reference
Edit config.toml to customize your mappings. The enhanced configuration supports:
[[modes.mappings]]
description = "Spotlight Search"
[modes.mappings.trigger]
type = "Note"
note = 12
velocity_min = 1 # Optional
velocity_max = 127 # Optional
[modes.mappings.action]
type = "Keystroke"
keys = "space"
modifiers = ["cmd"][[modes.mappings]]
description = "Gamepad A Button"
[modes.mappings.trigger]
type = "GamepadButton"
button = 128 # South button (A/Cross/B)
[modes.mappings.action]
type = "Keystroke"
keys = "space"[[modes.mappings]]
description = "Quick Save (LB + A)"
[modes.mappings.trigger]
type = "GamepadButtonChord"
buttons = [136, 128] # LB + A
max_interval_ms = 100
[modes.mappings.action]
type = "Keystroke"
keys = "s"
modifiers = ["ctrl"][[modes.mappings]]
description = "Left stick up → W key"
[modes.mappings.trigger]
type = "GamepadAnalogStick"
axis = 129 # Left stick Y-axis
direction = "Up"
threshold = 0.5
[modes.mappings.action]
type = "Keystroke"
keys = "w"[[modes.mappings]]
description = "Right trigger → Volume up"
[modes.mappings.trigger]
type = "GamepadTrigger"
trigger = 133 # Right trigger analog axis
threshold = 0.3
[modes.mappings.action]
type = "VolumeControl"
action = "Up"# Soft press
[[modes.mappings]]
description = "Volume Down (soft)"
[modes.mappings.trigger]
type = "VelocityRange"
note = 13
min_velocity = 1
max_velocity = 40
[modes.mappings.action]
type = "VolumeControl"
action = "Down"
# Hard press
[[modes.mappings]]
description = "Volume Up (hard)"
[modes.mappings.trigger]
type = "VelocityRange"
note = 13
min_velocity = 80
max_velocity = 127
[modes.mappings.action]
type = "VolumeControl"
action = "Up"[[modes.mappings]]
description = "Quit App (long press)"
[modes.mappings.trigger]
type = "LongPress"
note = 4
min_duration_ms = 1500
[modes.mappings.action]
type = "Keystroke"
keys = "q"
modifiers = ["cmd"][[modes.mappings]]
description = "Fullscreen (double tap)"
[modes.mappings.trigger]
type = "DoubleTap"
note = 16
max_interval_ms = 300
[modes.mappings.action]
type = "Keystroke"
keys = "f"
modifiers = ["ctrl", "cmd"][[modes.mappings]]
description = "Force Quit (chord)"
[modes.mappings.trigger]
type = "NoteChord"
notes = [8, 12] # Both pads must be pressed
max_interval_ms = 100
[modes.mappings.action]
type = "Keystroke"
keys = "escape"
modifiers = ["cmd", "option"][[global_mappings]]
description = "Volume Up"
[global_mappings.trigger]
type = "EncoderTurn"
cc = 2
direction = "Clockwise"
[global_mappings.action]
type = "VolumeControl"
action = "Up"Control the daemon from the command line:
# Check daemon status
conductorctl status
# Reload configuration
conductorctl reload
# Test connectivity
conductorctl ping
# Stop daemon
conductorctl stop
# Validate config before applying
conductorctl validate --config new-config.toml
# JSON output for scripting
conductorctl --json status | jq .data.uptime_secs# View reload performance
conductorctl status | grep -A5 "Reload Performance"
# Output includes:
# - Last reload time (ms)
# - Average reload time
# - Fastest/slowest reloads
# - Performance grade (A-F)See man conductorctl for full command reference.
Visualize all MIDI events from your controller:
midi_diagnostic 2 # If installed
# Or: cargo run --bin midi_diagnostic 2Features:
- Real-time event visualization
- Velocity bars
- Hold duration tracking
- Beautiful colored output
List all available MIDI devices:
test_midi # If installed
# Or: cargo run --bin test_midi- Keystroke - Simulate keyboard shortcuts
- Text - Type text strings
- Launch - Open applications
- Shell - Execute shell commands
- Delay - Add delays between actions
- MouseClick - Simulate mouse clicks
- VolumeControl - System volume control (Up/Down/Mute/Set)
- ModeChange - Switch between mapping modes
- Sequence - Chain multiple actions
- Repeat - Repeat an action multiple times
- Conditional - Execute based on conditions
The system supports multiple modes, each with its own set of mappings:
- Default Mode - General productivity shortcuts
- Development Mode - Git commands, build tools
- Media Mode - Music and video controls
- Custom Modes - Create your own!
Switch modes using:
- Encoder rotation (MIDI)
- Specific button/pad combinations
- CC messages (MIDI)
- Button chords (Gamepad)
- Check if device is connected:
system_profiler SPUSBDataType | grep -i mikro - Install necessary drivers (e.g., Native Instruments Controller Editor)
- Check Audio MIDI Setup:
open -a "Audio MIDI Setup"
- Check if gamepad is connected and recognized by OS
- Test with system gamepad settings or Steam Big Picture
- Ensure SDL2-compatible drivers are installed
- Check debug output:
conductor --log-level debug - Verify gamepad shows in system controller list
- Build in release mode:
cargo build --release - Close unnecessary applications
- Check CPU usage
- Run diagnostic tool to verify input events
- Check config.toml for correct button/note numbers
- Verify velocity/duration thresholds
- For gamepads: Check button ID mapping (MIDI Learn recommended)
[advanced_settings]
chord_timeout_ms = 50 # Max time between notes for chord
double_tap_timeout_ms = 300 # Max time between taps
hold_threshold_ms = 2000 # Time before hold is detected[[modes.mappings]]
description = "Context-aware action"
[modes.mappings.trigger]
type = "Note"
note = 20
[modes.mappings.action]
type = "Conditional"
[modes.mappings.action.condition]
type = "AppRunning"
app_name = "Terminal"
[modes.mappings.action.then_action]
type = "Keystroke"
keys = "c"
modifiers = ["ctrl"]
[modes.mappings.action.else_action]
type = "Launch"
app = "Terminal"conductor/
├── src/
│ ├── main.rs # Main application
│ ├── config.rs # Configuration structures
│ ├── actions.rs # Action execution
│ ├── mappings.rs # Trigger mapping engine
│ ├── event_processor.rs # Enhanced event processing
│ └── bin/
│ ├── test_midi.rs # MIDI port tester
│ └── midi_diagnostic.rs # Diagnostic tool
├── config.toml # User configuration
└── Cargo.toml # Dependencies
- Add to
Triggerenum inconfig.rs - Add to
ProcessedEventenum inevent_processor.rs - Update
EventProcessor::process()to detect the trigger - Update
MappingEngine::trigger_matches_processed()to handle matching
- Add to
ActionConfigenum inconfig.rs - Add to
Actionenum inactions.rs - Update
ActionExecutor::execute()to handle the action
- Input Event Latency: < 1ms typical
- Config Reload Time: 0-10ms typical (Grade A: <20ms target)
- Startup Time: < 500ms
- Memory Usage: 5-10MB
- CPU Usage: < 1% idle, < 5% active
- Binary Size: ~3-5MB (release build with LTO)
Run benchmarks:
cargo bench --package conductor-daemonTypical benchmark results (Apple M1):
- 2 modes, 10 mappings: 0-2ms reload
- 5 modes, 50 mappings: 2-5ms reload
- 10 modes, 100 mappings: 5-8ms reload
All achieve Grade A performance (<20ms).
We welcome contributions! Please see CONTRIBUTING.md for:
- How to report bugs
- How to propose features
- Development setup guide
- Coding standards
- Pull request process
Check out good first issues to get started.
- Deployment Guide - Complete installation and service setup
- Full Documentation - Complete user guide
- LED Feedback System - LED control documentation
- Configuration Reference - TOML configuration guide
- API Documentation - Rust API docs
- Man Pages:
man conductor,man conductorctl
- Discussions - Ask questions, share configs
- Issues - Bug reports, feature requests
- Security - Security vulnerability reporting
- Workspace architecture (conductor-core, conductor-daemon, conductor)
- Pure Rust engine library with zero UI dependencies
- 339 tests, all passing
- Background daemon with IPC server
- Config hot-reload with 0-10ms latency
- CLI control tool (conductorctl)
- systemd/launchd integration
- Comprehensive documentation and deployment guides
- Tauri-based visual configurator
- MIDI Learn mode (click → press → auto-map)
- Per-app profiles with frontmost app detection
- Device templates for popular controllers
- Live event console
- Multi-protocol input system (MIDI + HID/Gamepad)
- Unified InputEvent abstraction
- Gamepad device templates (Xbox, PlayStation, Switch Pro)
- MIDI Learn support for gamepad buttons
- Hot-plug detection for game controllers
- OSC protocol support
- Keyboard intercept (system-wide hotkeys)
- Custom USB device support
- Plugin system for community extensions
- Virtual MIDI output for DAW integration
- Profile sharing/export marketplace
- WebSocket API for remote control
- AI-powered natural language configuration
- Workflow pattern recognition
See .research/ for detailed implementation proposals.
Conductor is licensed under the MIT License.
Copyright (c) 2025 Amiable
Built with: