A python tool to easily map qlc buttons and midi.
Project description
QLC+ MIDI Mapper
A Python tool to inspect, edit, and manage MIDI mappings in QLC+ Virtual Console workspaces (.qxw files).
It is designed to make large MIDI setups readable, exportable, and portable across DAWs and controllers, without manually editing XML.
✨ Features
- Load and parse QLC+
.qxwworkspace files - Discover Virtual Console Buttons and Sliders
- Inspect and edit MIDI input mappings
- Buttons → MIDI Notes (0–127)
- Sliders → MIDI CC (0–127)
- Decode and edit QLC+ Input Channels (raw values stored in XML)
- Group widgets into logical rows (by function or caption)
- Import / export mappings as CSV
- Export MIDI maps for:
- Studio One (
.pitchlist, notes only) - Reaper (note-name map, notes only)
- Studio One (
📦 Installation
From PyPI (recommended)
pip install qlc-midi-mapper
This installs:
- the backend
- the Tkinter-based GUI
- the CLI entry point
From source (development)
git clone https://gitlab.com/remi.giorno/qlc_midi_mapper.git
cd qlc_midi_mapper
pip install -e ".[test]"
🚀 Usage
GUI
Run the application with:
qlc_midi_mapper
The GUI allows you to:
- Open a
.qxwworkspace - View and edit MIDI mappings
- Clearly distinguish Buttons (NOTE) from Sliders (CC)
- Import/export CSV mappings
- Export DAW-compatible MIDI maps
🧠 QLC+ MIDI encoding (important)
QLC+ stores MIDI input mappings in the XML as:
<Input Universe="0" Channel="..."/>
That Channel value is not the MIDI CC or Note number.
QLC+ uses a single integer Input Channel space, where different MIDI message types occupy distinct numeric blocks:
| Message type | MIDI # | QLC+ Input Channel |
|---|---|---|
| CC | 0–127 | 128–255 |
| NOTE | 0–127 | 129–256 |
QLC+ may additionally add multiples of 4096 internally for MIDI channel / OMNI encoding. These upper blocks must be preserved when remapping inputs.
This application always exposes mappings as:
- Type:
CCorNOTE - MIDI#: the real MIDI number (0–127)
- QLC_InputChannel: the raw integer stored in the
.qxwfile
📤 CSV format
Exported CSV files contain:
| Column | Description |
|---|---|
| Name | Logical row name (function or caption) |
| Type | CC or NOTE |
| MIDI# | Real MIDI number (0–127) |
| QLC_InputChannel | Raw value stored in QLC+ |
| Caption | Widget caption |
| Function | QLC+ function name (if any) |
| Path | Virtual Console path |
CSV import rules
Nameis required- Either
MIDI#orQLC_InputChannelmust be provided - If
MIDI#is used, the correct QLC+ Input Channel is computed automatically based onType
🎹 DAW Export
Studio One
Exports a .pitchlist file compatible with Studio One (NOTE widgets only):
<Music.PitchNameList>
<Music.PitchName pitch="42" name="[FX] Left→Right"/>
</Music.PitchNameList>
Arrow symbols are sanitized to avoid XML-escaped artifacts.
Reaper
Exports a tab-separated MIDI note-name file (NOTE widgets only):
42 [FX] Left→Right
CC / fader mappings are intentionally excluded from DAW exports, as DAWs do not use note-name maps for CC.
🧠 Project Structure
qlc_midi_mapper/
├── src/qlc_midi_mapper/
│ ├── workspace.py # Core backend logic (XML, MIDI, CSV)
│ ├── models.py # Data models (widgets, rows)
│ ├── gui/ # Tkinter GUI
│ └── __main__.py # CLI entry point
└── tests/ # Pytest test suite
The backend (MidiWorkspace) is GUI-agnostic and fully unit-tested.
🧪 Tests
Run tests locally with:
pytest
The test suite covers:
- XML parsing
- Widget discovery
- Logical grouping
- CSV import/export
- DAW export formats
- XML round-tripping
🛠 Development Tools
- ruff — linting
- black — formatting
- pytest — testing
- GitLab CI — automated lint / test / build / publish
All configuration lives in pyproject.toml.
📄 License
MIT License
🙌 Contributing
Contributions are welcome!
- Bug reports
- Feature requests
- DAW export improvements
- Controller-specific workflows
Open an issue or merge request on GitLab.
🎛 Why this exists
QLC+ workspaces scale fast.
This tool exists to bring structure, portability, and sanity to complex MIDI-driven lighting rigs.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qlc_midi_mapper-1.0.0.tar.gz.
File metadata
- Download URL: qlc_midi_mapper-1.0.0.tar.gz
- Upload date:
- Size: 24.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dcae012dc272f4ae211783486bfafa5907218fd547cd360cc06f4f29a5b47c5d
|
|
| MD5 |
fab401c8ff6718c4df11bbe3ef66b081
|
|
| BLAKE2b-256 |
d5efbdd9b24da747ec9036b80320212bbdf09996f5529e3fee924cc54666c70f
|
File details
Details for the file qlc_midi_mapper-1.0.0-py3-none-any.whl.
File metadata
- Download URL: qlc_midi_mapper-1.0.0-py3-none-any.whl
- Upload date:
- Size: 22.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7dca3dc99ae57673b071b8c4effb4e8cb1a92b787ea45ed46b35471e524f37f
|
|
| MD5 |
381fe0c5387c13ba8eec190e596e3927
|
|
| BLAKE2b-256 |
79587bc492327228324fb908aa20cd725d25c6daea57e5c428e401c0a0ade84f
|