pyvmancer
Python library and CLI to automate the LZX Industries Videomancer over USB.
Two control paths, usable together or independently:
| Path | Transport | Covers |
|---|---|---|
| USB MIDI | ALSA rawmidi or any mido backend |
12 parameters (7/14-bit CC), preset recall, note triggers, clock/transport |
| USB serial | /dev/ttyACM* or libusb |
programs, presets, modulation operators, video, settings, filesystem |
Install
pip install pyvmancer # MIDI only
pip install "pyvmancer[all]" # adds serial and libusb transports
On Linux the python-rtmidi dependency links libasound.so.2:
sudo apt-get install libasound2t64
Use
import pyvmancer as vm
d = vm.Videomancer.open()
d.load_program("Isotherm")
d.set_named("Posterize", 5) # native units: Posterize is 0..7
d.set_named("Mix", 80) # Mix is 0..100
d.set_source("Contrast", "free lfo")
d.set_param(1, 0.75) # or address slots directly, 0.0..1.0
d.set_param(7, True) # toggles take bools
d.trigger(4) # note-trigger a modulation operator
d.set_bpm(128)
d.play()
d.close()
Device knowledge the library encodes, rather than leaving to each caller:
d.park() # manual values to a reference, so a CC is absolute
p = d.parameter("Posterize") # p.role, p.steps, p.sample_values()
d.program_manifest().get("combing").description
d.file_hash("sd:/programs/lzx/combing.vmprog")
d.video_state().source_locked # per-input lock, not the genlock flag
d.resync() # bounce the timing to re-init the output raster
MIDI only, no serial link needed:
with vm.open_midi(channel=1) as m:
m.set_param(1, 0.5)
m.select_preset(3)
m.run_clock(120, beats=8)
CLI
vmancer devices # discover attached units and their device nodes
vmancer operators # list the 25 modulation operators
vmancer set 1=0.5 7=on # set parameters over MIDI
vmancer preset 3 # recall a preset
vmancer programs # list installed FPGA programs
vmancer load Isotherm # load a program
vmancer manifest # SD program library metadata
vmancer hash sd:/programs/x.vmprog
vmancer resync # recover an output that stopped passing frames
vmancer shell modulation status # run any raw shell command
Firmware upgrade
LZX publishes firmware as GitHub releases on
lzxindustries/videomancer-firmware,
tagged videomancer/<version>. pyvmancer resolves a release, downloads its
UF2, validates it, and flashes it through the RP2040 bootloader.
vmancer firmware list # published releases, newest first
vmancer firmware status # running version vs the newest release
vmancer firmware download 1.0.0-rc.46 # fetch and validate a UF2, no flashing
vmancer firmware upgrade # dry run: shows what would be flashed
vmancer firmware upgrade --yes # flash the latest release
vmancer firmware upgrade 1.0.0-rc.40 --yes --force # pin a version, or downgrade
upgrade is a dry run unless --yes is given. With --yes it issues
reboot bootloader, waits for the UF2 volume to appear (mounting it with
udisksctl if nothing automounted it), copies the image, then waits for the
device to re-enumerate and reports the version it comes back on. Pass
--manual when the unit was put into bootloader mode by hand (hold BOOT while
powering on), which is the recovery path when the serial link is unusable, and
--volume when the bootloader is already mounted somewhere.
Allow minutes, not seconds: the image only reaches the device when the copy is flushed, and a 24 MB UF2 takes a while over a FAT mount. The device reboots itself once the last block lands, and the version it reports afterwards is the proof the flash took.
import pyvmancer as vm
vm.resolve_release("latest").version # newest published version
image = vm.inspect_uf2("videomancer-1.0.0-rc.46.uf2")
image.blocks, image.families # validated before anything is written
with vm.open_shell() as shell:
vm.upgrade("latest", shell=shell, report=print)
Every Videomancer release to date is flagged as a prerelease on GitHub, so
latest includes prereleases; pass --stable / stable_only=True to refuse
them. Set GITHUB_TOKEN if you hit the unauthenticated API rate limit.
Program library
The FPGA programs ship separately from the firmware, tagged programs/<version>
on the same repository. pyvmancer resolves a release, verifies the archive
against its published checksums.sha256, and copies it onto the SD card.
vmancer library list # published library releases
vmancer library status # newest release vs what is on the card
vmancer library download 1.0.3 # fetch and verify an archive, no install
vmancer library install # dry run: shows what would be installed
vmancer library install --yes # install the latest release
vmancer library install --yes --force # re-upload files already present
import pyvmancer as vm
with vm.open_shell() as shell:
vm.install("latest", shell=shell, report=print)
Files already on the card at the archive's size are skipped, so an interrupted
run resumes by re-running it. The upload uses fs put, the shell's raw
streaming path: about 157 kB/s, so a full 14 MB library takes about 90 seconds.
The base64 fs write path manages roughly 3 kB/s and is only for small files.
Restart the device after installing. The program index is built at boot, so newly installed programs are not listed — and cannot be loaded — until the unit is power cycled.
Permissions
MIDI needs read/write on /dev/snd/midiC*D* (usually granted by a desktop ACL);
serial needs the dialout group or an ACL on /dev/ttyACM*. See
docs/permissions.md.
Docs
- docs/protocol.md — MIDI implementation and the serial command set
- docs/permissions.md — device node access, containers, udev
- docs/firmware-notes.md — observed firmware behaviour and quirks
- CHANGELOG.md — release history
Status
Verified against a Videomancer running firmware 1.0.0-rc.37 and 1.0.0-rc.40.
Not affiliated with LZX Industries.
License
Apache-2.0
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 pyvmancer-0.3.0.tar.gz.
File metadata
- Download URL: pyvmancer-0.3.0.tar.gz
- Upload date:
- Size: 112.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb3b634640648e547a513b57e8979aa1f3f0d56cb64555d88b9d34d0079ae716
|
|
| MD5 |
3615c75925db6ecf02e8c2d1c5687642
|
|
| BLAKE2b-256 |
8120d7015e8ff219e1243295a7f05412f8a59907a79e090d463dc05c77404b2c
|
Provenance
The following attestation bundles were made for pyvmancer-0.3.0.tar.gz:
Publisher:
release.yml on anarkiwi/pyvmancer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyvmancer-0.3.0.tar.gz -
Subject digest:
fb3b634640648e547a513b57e8979aa1f3f0d56cb64555d88b9d34d0079ae716 - Sigstore transparency entry: 2376771265
- Sigstore integration time:
-
Permalink:
anarkiwi/pyvmancer@1efdd945650036a9c48bddefdb871d205438c9aa -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/anarkiwi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1efdd945650036a9c48bddefdb871d205438c9aa -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyvmancer-0.3.0-py3-none-any.whl.
File metadata
- Download URL: pyvmancer-0.3.0-py3-none-any.whl
- Upload date:
- Size: 59.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5c1fa38f575f76e8ab889617b3361dbf762f9eed0c87ff621a4cb7db99ed16e1
|
|
| MD5 |
9bec4874bdaeee6bb9e1e0f7574c90e3
|
|
| BLAKE2b-256 |
3d3f8781c80dfd6900ac504df6286c8c6371673a59c390bee58c359835b88c51
|
Provenance
The following attestation bundles were made for pyvmancer-0.3.0-py3-none-any.whl:
Publisher:
release.yml on anarkiwi/pyvmancer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyvmancer-0.3.0-py3-none-any.whl -
Subject digest:
5c1fa38f575f76e8ab889617b3361dbf762f9eed0c87ff621a4cb7db99ed16e1 - Sigstore transparency entry: 2376771385
- Sigstore integration time:
-
Permalink:
anarkiwi/pyvmancer@1efdd945650036a9c48bddefdb871d205438c9aa -
Branch / Tag:
refs/tags/v0.3.0 - Owner: https://github.com/anarkiwi
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@1efdd945650036a9c48bddefdb871d205438c9aa -
Trigger Event:
release
-
Statement type: