pymotivaxmc2
An asynchronous Python library for controlling Emotiva XMC-2 (and compatible) processors over their UDP
remote-control interface — discovery, commands, and real-time property notifications, all on asyncio.
Python 3.11+ · MIT · typed (py.typed)
Highlights
- One controller, the whole device.
EmotivaControllerdiscovers the unit, negotiates the protocol version, binds the UDP ports, and hands you typed helpers for power, volume, mute, inputs, and sources — then tears it all down ondisconnect(). - Events, not polling. Subscribe to volume, power, source, mode, and more; the device pushes each
change to an
asynccallback. Subscribe-time values arrive through the same callback, so you reach a consistent state the moment you subscribe. - A typed command surface.
Command,Property,Input, andZoneenums replace magic strings, so a wrong input or property is a name error at your editor, not a silent no-op on the wire. - Speaks every protocol version. Auto-negotiates protocol 2.0 / 3.0 / 3.1 from the device's own
transponder reply and parses both the old element-per-property and the new
<property>-attribute frame shapes. - Resilient by default. Commands are concurrency-limited and retried with exponential backoff; so are discovery and subscription. Callbacks run with a timeout so one slow consumer can't stall the notify loop.
- A CLI in the box.
emu-clidrives power, volume, mute, input, Zone 2, and status snapshots straight from the shell — handy for testing without writing code. - Typed end to end. Ships
py.typed(PEP 561), so consumers get real autocomplete and type-checking against the public surface.
Install
pip install pymotivaxmc2
Quick taste
import asyncio
from pymotivaxmc2 import EmotivaController, Property
async def main():
ctrl = EmotivaController("192.168.1.50") # your processor's IP
await ctrl.connect() # discover, negotiate, bind ports
try:
# React to volume changes the device pushes us
@ctrl.on(Property.VOLUME)
async def on_volume(value):
print("Volume is now", value, "dB")
await ctrl.subscribe(Property.VOLUME) # initial value arrives on the callback too
await ctrl.power_on()
await ctrl.set_volume(-25.0)
await asyncio.sleep(30) # live notifications for 30s
finally:
await ctrl.disconnect()
asyncio.run(main())
Register the callback before you subscribe — subscribe() replays the device's current value through
your @on callback, so ordering it first means you never miss the initial state. The
Quickstart walks through the whole flow.
No pairing, no cloud. The processor just has to be reachable on the LAN.
connect()finds it with a UDP ping and reads its capabilities from the reply — see Connection & discovery.
Documentation
- Architecture overview — the layers, the one import rule, and the connection lifecycle.
- Quickstart — install, connect, and send your first commands.
- Commands — the full helper surface on
EmotivaController, plus the enums. - Subscriptions — real-time property events, their callbacks, and the reconnect contract.
- Connection & discovery — how
connect()finds the device, the UDP port map, and protocol negotiation. - Command-line interface —
emu-clifor driving the device from the shell.
Development
git clone https://github.com/locveil/pymotivaxmc2.git
cd pymotivaxmc2
pip install -e ".[dev]"
pytest
Three CI-enforced health gates (import layering, no TYPE_CHECKING guards, and pyright at zero errors)
guard every commit — see Contributing for how to run them locally and why a typed
library treats those as contracts.
Acknowledgements
- The Emotiva Remote Interface Description (vendored under
docs/Emotiva_Remote_Interface_Description.md) — the protocol specification this library implements.
License
MIT — see LICENSE.
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 pymotivaxmc2-0.8.0.tar.gz.
File metadata
- Download URL: pymotivaxmc2-0.8.0.tar.gz
- Upload date:
- Size: 30.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a56e6a466a348d1edf0a7a7467ea2174b74983840afe0116df1389f39c6f4eec
|
|
| MD5 |
f6d0a1165ef057fd61d598a00cf7ea4d
|
|
| BLAKE2b-256 |
1870787c785253f3fa3bcceff80fe2cd7112dd8f5dd28765344a805ca8d751c4
|
Provenance
The following attestation bundles were made for pymotivaxmc2-0.8.0.tar.gz:
Publisher:
ci.yml on locveil/pymotivaxmc2
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymotivaxmc2-0.8.0.tar.gz -
Subject digest:
a56e6a466a348d1edf0a7a7467ea2174b74983840afe0116df1389f39c6f4eec - Sigstore transparency entry: 2172636276
- Sigstore integration time:
-
Permalink:
locveil/pymotivaxmc2@927ae184ad817ef64b926c9d23b3514a4f476b9f -
Branch / Tag:
refs/tags/v0.8.0 - Owner: https://github.com/locveil
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@927ae184ad817ef64b926c9d23b3514a4f476b9f -
Trigger Event:
push
-
Statement type:
File details
Details for the file pymotivaxmc2-0.8.0-py3-none-any.whl.
File metadata
- Download URL: pymotivaxmc2-0.8.0-py3-none-any.whl
- Upload date:
- Size: 31.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4afd22678e3c22c8193c2efd064254ab487f74ab4724cfb42630f4bf0b9151f5
|
|
| MD5 |
5d6a6caf93cffd99521a5c69229b8f44
|
|
| BLAKE2b-256 |
8c15c6ec12c5704e418ed5a790bd39248c12ceadb67cbba082a6422787a486ba
|
Provenance
The following attestation bundles were made for pymotivaxmc2-0.8.0-py3-none-any.whl:
Publisher:
ci.yml on locveil/pymotivaxmc2
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pymotivaxmc2-0.8.0-py3-none-any.whl -
Subject digest:
4afd22678e3c22c8193c2efd064254ab487f74ab4724cfb42630f4bf0b9151f5 - Sigstore transparency entry: 2172636371
- Sigstore integration time:
-
Permalink:
locveil/pymotivaxmc2@927ae184ad817ef64b926c9d23b3514a4f476b9f -
Branch / Tag:
refs/tags/v0.8.0 - Owner: https://github.com/locveil
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@927ae184ad817ef64b926c9d23b3514a4f476b9f -
Trigger Event:
push
-
Statement type: