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.
Metadata
Release files for pymotivaxmc2 0.8.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pymotivaxmc2-0.8.0.tar.gz | 30.5 kB | With provenance | Details for pymotivaxmc2-0.8.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pymotivaxmc2-0.8.0-py3-none-any.whl | Python 3 | none | any | Details for pymotivaxmc2-0.8.0-py3-none-any.whl |
Total release size: 62.4 kB
Release files / pymotivaxmc2-0.8.0.tar.gz
| Download URL | pymotivaxmc2-0.8.0.tar.gz |
|---|---|
| Size | 30.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a56e6a466a348d1edf0a7a7467ea2174b74983840afe0116df1389f39c6f4eec
|
|
BLAKE2b-256 checksum How to use checksums |
1870787c785253f3fa3bcceff80fe2cd7112dd8f5dd28765344a805ca8d751c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 15, 2026.
Transparency logRelease files / pymotivaxmc2-0.8.0-py3-none-any.whl
| Download URL | pymotivaxmc2-0.8.0-py3-none-any.whl |
|---|---|
| Size | 31.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
4afd22678e3c22c8193c2efd064254ab487f74ab4724cfb42630f4bf0b9151f5
|
|
BLAKE2b-256 checksum How to use checksums |
8c15c6ec12c5704e418ed5a790bd39248c12ceadb67cbba082a6422787a486ba
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 15, 2026.
Transparency logSecurity for pymotivaxmc2 0.8.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for pymotivaxmc2-0.8.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 15, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.