Turn your laptop trackpad into a real instrument.
Strum chords, control MIDI, orchestrate systems — all from your touchpad.
Strumer brings the physical "strumming" feel of the legendary Omnichord directly to your laptop trackpad. Select a chord on your keyboard and strum the strings by sliding your finger on the trackpad. It works as a fully functional MIDI controller with your DAW, and can also act as a system orchestration tool.
- Features
- Platform Support
- Installation
- Usage
- Architecture
- Developer Notes
- Roadmap
- Contributing
- License
Works with Standard Block Chord logic for advanced VST (Virtual Studio Technology) compatibility. When you slide your finger on the trackpad, the notes of the strings are triggered simultaneously with near-zero latency.
Uses a trigonometric drift filter to prevent the natural hand jitters (drift).
- Your finger's instantaneous X/Y position is calculated using
math.atan2 - It is then locked (quantized) to the nearest 45-degree (8-way) virtual rail
- Only Dot Product (projection) advancements on this rail are converted into velocity. Reverse deviations or vertical jitters are filtered out. You play smoothly as if there were physical grooves on the trackpad
Replicates essential MIDI keyboard controls:
- Sustain Pedal: Hold
Shiftto sendMIDI CC 64 (Value 127)to your DAW. Release to turn off. - Octave Gearbox: Shift gears between ±4 octaves using
Up Arrow/Down Arrow. The system clips itself within the0-127 MIDIboundaries.
The interface is built with the rich library using a persistent layout architecture:
- No screen clearing: The skeleton is drawn once; only changing pixels are updated using a delta-render algorithm.
- Realistic Oscilloscope: Velocity data is passed through a decay filter, creating smoothly gliding waveforms — just like an analog device.
Launch with --mode system and the trackpad becomes a DevOps orchestration device. Chords map to services (C = Web Server, D = Database); strumming speed controls scale-up and scale-down of Docker containers.
Note
System Mode is experimental / proof-of-concept. It does not execute real infrastructure commands yet — it only simulates and logs the actions that would be taken.
| Platform | Status | Notes |
|---|---|---|
| macOS | ✅ Full Support | Native CoreFoundation patches included |
| Linux | ✅ Supported | Requires X11 or Wayland with pynput support |
| Windows | ✅ Supported | Works with standard touchpad drivers |
- Python 3.9+ (tested up to 3.13)
- A laptop with a trackpad/touchpad
- A MIDI-compatible DAW (e.g., Ableton, FL Studio, Logic Pro) for MIDI mode
# Clone the repository
git clone https://github.com/thevalmarch/strumer.git
cd strumer
# Install dependencies
pip install -r requirements.txt
# Run
python src/strumer.pymake install # Install dependencies
make run # Run in MIDI mode
make run-system # Run in System modemacOS
You must grant Accessibility permission to your Terminal application:
System Settings → Privacy & Security → Accessibility
Without this, low-level keyboard/mouse events cannot be captured.
Linux
You may need to add your user to the input group:
sudo usermod -aG input $USERThen log out and back in. Some Wayland compositors may require additional configuration for pynput.
Windows
No special permissions required. Run your terminal as a normal user.
Standard MIDI Mode (strum chords, send MIDI to your DAW):
python src/strumer.pyDevOps System Mode (container and log orchestration):
python src/strumer.py --mode system| Key | Action |
|---|---|
Q W E R T Y U |
Major chords (C, D, E, F, G, A, B) |
A S D F G H J |
Minor chords (Cm, Dm, Em, Fm, Gm, Am, Bm) |
Z X C V B N M |
Dominant 7th chords (C7, D7, E7, F7, G7, A7, B7) |
| Trackpad Swipe | Strum — speed and direction are detected |
Space |
Panic / Mute All (kills all hanging notes) |
Shift |
Sustain Pedal |
Up / Down |
Octave shift (±4 range) |
ESC |
Exit |
strumer/
├── src/
│ ├── __init__.py # Package marker
│ ├── __main__.py # Entry point for `python -m src`
│ ├── strumer.py # Backward-compatible wrapper (re-exports public API)
│ ├── app.py # main() entry point with arg parsing
│ ├── config.py # Version and constants
│ ├── math_utils.py # Pure functions (clamp, velocity, snap_vector, decay)
│ ├── chords.py # Chord data, key mapping, JSON/YAML config loading
│ ├── ui.py # UIState class and Rich TUI rendering
│ ├── midi_engine.py # MidiEngine class (rtmidi wrapper)
│ ├── midi_mapping.py # MIDI CC mapping and learn mode
│ ├── input_handler.py # InputHandler (pynput wrapper)
│ ├── controller.py # TrackpadController orchestrator
│ ├── platform_patches.py # macOS Quartz/pynput patches, terminal mgmt
│ ├── recorder.py # Session recording and playback (.strumer format)
│ ├── gestures.py # Multi-touch gesture recognition
│ ├── sound_engine.py # Built-in polyphonic synthesizer (oscillator + ADSR)
│ ├── effects.py # Audio effects (reverb, chorus)
│ ├── plugins/ # Plugin system
│ │ ├── __init__.py # Public API re-exports
│ │ ├── base.py # ABC base classes (Instrument, Effect, Gesture)
│ │ ├── registry.py # Singleton plugin registry
│ │ └── loader.py # Dynamic plugin discovery and loading
│ └── platform_backends/ # Platform-specific multi-touch backends
│ ├── __init__.py # Backend auto-detection
│ └── macos_multitouch.py # macOS MultitouchSupport.framework
├── plugins/
│ └── example_instrument/ # Example community plugin
│ ├── plugin.json # Plugin metadata
│ └── instrument.py # BrightPiano implementation
├── recordings/ # User-generated session recordings
├── tests/ # 116 unit tests
├── config/
│ ├── chords.json # Chord voicings and key mapping
│ ├── chords.example.json # Extended voicings example
│ ├── chords.example.yaml # YAML config example
│ └── midi_map.json # MIDI CC mapping config
├── .github/
│ ├── workflows/ci.yml # CI pipeline (lint, test, syntax check)
│ ├── ISSUE_TEMPLATE/ # Bug report & feature request templates
│ └── PULL_REQUEST_TEMPLATE.md
├── pyproject.toml # Python packaging & metadata
├── requirements.txt # Pinned dependencies
├── Makefile # Developer shortcuts
├── LICENSE # MIT License
├── CHANGELOG.md # Version history
├── CONTRIBUTING.md # Contribution guidelines
└── CODE_OF_CONDUCT.md # Community standards
| Module | Responsibility |
|---|---|
controller.py |
Orchestrator: ties input, MIDI, recording, and UI together |
chords.py |
Chord data, key mapping, JSON/YAML config with validation |
midi_engine.py |
MIDI output via rtmidi (note on/off, CC, sustain) |
midi_mapping.py |
Configurable gesture-to-CC mapping with learn mode |
sound_engine.py |
Built-in polyphonic synth (sine/saw/square/triangle + ADSR) |
effects.py |
Audio effects (Schroeder reverb, chorus) |
recorder.py |
Session recording and playback (.strumer JSON Lines format) |
gestures.py |
Multi-touch gesture recognition (pinch, rotate) |
ui.py |
Thread-safe TUI state management with persistent layout |
math_utils.py |
8-way drift filtering via atan2 + dot product |
platform_patches.py |
macOS CoreFoundation fix, Python 3.13 thread fix |
plugins/ |
Plugin system: base classes, registry, dynamic loader |
Because this codebase pushes OS boundaries, several system patches are embedded inside:
-
Python 3.13 Thread Handle Collision: The
TypeError: '_thread._ThreadHandle' object is not callableerror caused by a collision between Python 3.13's Thread architecture andpynput's macOS darwin adaptation has been fixed via class-level Method Aliasing (_pynput_handle). This patch only applies on macOS. -
Terminal Echo Suppression: On UNIX systems,
ECHOandICANONflags intermiosare disabled to prevent keystroke echo from disrupting the TUI. On Windows, this is handled natively byrich. -
CoreFoundation Symlink Patch (macOS): Quartz symbols (
CFMachPortCreateRunLoopSource, etc.) removed in modern macOS versions are dynamically scanned via CoreFoundation and injected into the Quartz module.
- Modular architecture (split single-file
strumer.pyinto separate modules) - Custom chord voicing editor (JSON/YAML config with key mapping)
- MIDI learn mode for arbitrary CC mapping
- Recording and playback of strum sessions
- Multi-touch gesture support (pinch for velocity curves)
- Built-in sound engine (no external DAW required)
- Plugin system for community instruments
Contributions are welcome! Please read the Contributing Guide before submitting a Pull Request.
This project is licensed under the MIT License.
Keep Strumming. Keep Hacking.
Made by Val March
