╔════════════════════════════════════════════════════════════════════════════════════════════╗
║ ║
║ ██████╗ ███████╗███╗ ███╗ █████╗ ██████╗ ██╗ ██╗██████╗ █████╗ ██████╗ ║
║ ██╔══██╗██╔════╝████╗ ████║██╔══██╗██╔══██╗██║ ██║██╔══██╗██╔══██╗██╔══██╗ ║
║ ██████╔╝█████╗ ██╔████╔██║███████║██████╔╝██║ █╗ ██║██████╔╝███████║██████╔╝ ║
║ ██╔══██╗██╔══╝ ██║╚██╔╝██║██╔══██║██╔═══╝ ██║███╗██║██╔══██╗██╔══██║██╔═══╝ ║
║ ██║ ██║███████╗██║ ╚═╝ ██║██║ ██║██║ ╚███╔███╔╝██║ ██║██║ ██║██║ ║
║ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ║
║ ║
║ your phone is the control surface ║
║ ║
╚════════════════════════════════════════════════════════════════════════════════════════════╝
RemapWrap layouts, built by machine. A folder of samples becomes a soundboard, a list of applications becomes a mixer, a list of shortcuts becomes a deck.
pip install remapwrap
remapwrap soundboard ./samples -o board.json a pad per sound file
remapwrap mixer Discord Spotify chrome -o mix.json a slider per application
remapwrap deck "Copy:ctrl+c" "Paste:ctrl+v" -o keys.json
remapwrap check board.json would this work
remapwrap describe board.json what is in it
Open the RemapWrap dashboard, import the file, and the surface is on your phone.
Why this exists
A forty-pad soundboard is twenty minutes of dragging, and the folder of samples already knows what the pads are. So does the list of applications currently playing audio, and so does the config file where somebody keeps their shortcuts. Every one of those is a layout that a person should not have to build by hand.
The dashboard is where a surface gets adjusted — moved, recoloured, tried. This is where one gets made.
What a layout is
One JSON document. Cells, not pixels, so the same layout fits a phone held either way.
{"cols": 12, "rows": 21, "keys": [
{"id": "k1", "type": "pad", "behaviour": "trigger",
"command": "sound.play", "arg": "airhorn.wav",
"label": "AIRHORN", "sub": "soundboard", "color": "#2a1216",
"x": 0, "y": 0, "w": 4, "h": 4, "shape": "rect"}
]}
Five control types — key, toggle, pad, dial, slider — four shapes,
and a command from a fixed catalogue. Read or write it with anything; it is
JSON, and this package imports nothing that is not in the standard library.
The rules are written twice on purpose
The dashboard enforces these rules in JavaScript. This package enforces them again in Python, and that is not duplication for its own sake: two implementations of one rule set disagree exactly where one of them is wrong. Running them against each other has found more defects in this codebase than reading either one ever did.
check returns sentences rather than codes, because the person reading them is
the person who has to fix it:
- BAD DIAL is a dial bound to 'capture.shot', which takes no value. A dial cannot fire it.
- BAD KEY is a key bound to 'audio.master', which reports a value. Use a dial or a slider.
- OFF BOARD sits at 22,14 and is 4x4, which runs off a 24x16 board.
- TYPO is bound to 'not.a.command', which is not a command.
- ELLIPSE is a circle 4x6; a circle has one dimension.
- 'BAD DIAL' and 'OVER A' overlap.
A generator that cannot produce a valid layout raises instead of writing a broken one.
As a library
from remapwrap import generate, layout
board = generate.soundboard("./samples")
layout.place(board, layout.control(
type="slider", command="audio.master", label="MASTER"))
problems = layout.check(board)
if not problems:
layout.save(board, "board.json")
place finds a free spot and leaves a cell of air around it, because a surface
where every key touches its neighbour is a surface people press two of at once.
What it does not do
It does not talk to your phone, press a key, or open a socket. It writes the document a surface is made of, and the RemapWrap dashboard does the rest. There is no network code in this package at all.
Dependencies
None. Standard library, Python 3.8 and up.
╔════════════════════════════════════════════════════════════╗
║ ║
║ ███████╗ ██╗ ██╗███████╗██╗ ██╗███████╗ ║
║ ██╔════╝ ██║ ██╔╝██╔════╝╚██╗ ██╔╝██╔════╝ ║
║ █████╗ █████╗█████╔╝ █████╗ ╚████╔╝ ███████╗ ║
║ ██╔══╝ ╚════╝██╔═██╗ ██╔══╝ ╚██╔╝ ╚════██║ ║
║ ██║ ██║ ██╗███████╗ ██║ ███████║ ║
║ ╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝ ╚══════╝ ║
║ ║
║ · C R E A T I V E · ║
║ ║
║ ──────────────────────────────────────── ║
║ ║
║ Vincent Gonzalez ║
║ f-keys.com ║
║ ORCID 0009-0005-3640-014X ║
║ ║
╚════════════════════════════════════════════════════════════╝
Part of F-Keys — independent hardware, software and internet products. See the working log and live status.
Part of F-Keys — independent hardware, software and internet products. See the working log and live status.
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 remapwrap-0.1.3.tar.gz.
File metadata
- Download URL: remapwrap-0.1.3.tar.gz
- Upload date:
- Size: 13.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d50e7075281c2550ac9ff58d7fe3a3d822a9481d9f73994f9c8dae0032e1324
|
|
| MD5 |
c6b350605fe9a90cba8f7a9259f4047c
|
|
| BLAKE2b-256 |
6791bdcd929cf47ea0eacd992349a173842c249c65d2de609e35b8b49417c5ba
|
File details
Details for the file remapwrap-0.1.3-py3-none-any.whl.
File metadata
- Download URL: remapwrap-0.1.3-py3-none-any.whl
- Upload date:
- Size: 12.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fa506b62fc69d1ce81f91da335d18fe98f90360448e543a1f27e89863d0651f6
|
|
| MD5 |
c7fe684f0244811ec5d13130b982aa00
|
|
| BLAKE2b-256 |
20c0255106f07a51029148e2b1dccd37f3cb703054ce0062bb482b6ae46aea24
|