mirror of
https://github.com/onyx-and-iris/xair-api-python.git
synced 2025-04-20 04:03:53 +01:00
Compare commits
6 Commits
6a2df6352d
...
caaf2689ff
Author | SHA1 | Date | |
---|---|---|---|
caaf2689ff | |||
7e7aa1b4de | |||
2dc096e306 | |||
ed397e57aa | |||
718ecbd982 | |||
69cabb3db0 |
@ -11,6 +11,14 @@ Before any major/minor/patch bump all unit tests will be run to verify they pass
|
||||
|
||||
- [ ]
|
||||
|
||||
## [2.3.2] - 2024-02-16
|
||||
|
||||
### Added
|
||||
|
||||
- Configurable kwarg `connect_timeout` added. Defaults to 2 seconds.
|
||||
- New error class `XAirRemoteConnectionTimeoutError`. Raised if a connection validation times out.
|
||||
- timeout kwarg + Errors section added to README.
|
||||
|
||||
## [2.3.1] - 2024-02-15
|
||||
|
||||
### Changed
|
||||
|
11
README.md
11
README.md
@ -55,7 +55,7 @@ if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
#### `xair_api.connect(kind_id, ip=ip, delay=delay)`
|
||||
#### `xair_api.connect(kind_id, ip=ip, delay=0.02, connect_timeout=2)`
|
||||
|
||||
Currently the following devices are supported:
|
||||
|
||||
@ -72,6 +72,7 @@ The following keyword arguments may be passed:
|
||||
- `port`: mixer port, defaults to 10023 for x32 and 10024 for xair
|
||||
- `delay`: a delay between each command (applies to the getters). Defaults to 20ms.
|
||||
- a note about delay, stability may rely on network connection. For wired connections the delay can be safely reduced.
|
||||
- `connect_timeout`: amount of time to wait for a validated connection. Defaults to 2s.
|
||||
|
||||
## API
|
||||
|
||||
@ -317,6 +318,14 @@ for example:
|
||||
print(mixer.query("/ch/01/mix/on"))
|
||||
```
|
||||
|
||||
### Errors
|
||||
|
||||
- `errors.XAirRemoteError`: Base error class for XAIR Remote.
|
||||
- `errors.XAirRemoteConnectionTimeoutError`:Exception raised when a connection attempt times out.
|
||||
- The following attributes are available:
|
||||
- `ip`: IP of the mixer.
|
||||
- `port`: Port of the mixer.
|
||||
|
||||
### `Tests`
|
||||
|
||||
Unplug any expensive equipment before running tests.
|
||||
|
@ -1,6 +1,6 @@
|
||||
[tool.poetry]
|
||||
name = "xair-api"
|
||||
version = "2.3.1"
|
||||
version = "2.3.2"
|
||||
description = "Remote control Behringer X-Air | Midas MR mixers through OSC"
|
||||
authors = ["onyx-and-iris <code@onyxandiris.online>"]
|
||||
license = "MIT"
|
||||
|
@ -1,2 +1,14 @@
|
||||
class XAirRemoteError(Exception):
|
||||
"""Base error class for XAIR Remote."""
|
||||
|
||||
|
||||
class XAirRemoteConnectionTimeoutError(XAirRemoteError):
|
||||
"""Exception raised when a connection attempt times out"""
|
||||
|
||||
def __init__(self, ip, port):
|
||||
self.ip = ip
|
||||
self.port = port
|
||||
|
||||
super().__init__(
|
||||
f"Timeout attempting to connect to mixer at {self.ip}:{self.port}"
|
||||
)
|
||||
|
@ -1,6 +1,35 @@
|
||||
import functools
|
||||
import time
|
||||
from math import exp, log
|
||||
|
||||
from .errors import XAirRemoteConnectionTimeoutError
|
||||
|
||||
|
||||
def timeout(func):
|
||||
"""
|
||||
Times out the validate_connection function once time elapsed exceeds remote.connect_timeout.
|
||||
"""
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
remote, *_ = args
|
||||
|
||||
err = None
|
||||
start = time.time()
|
||||
while time.time() < start + remote.connect_timeout:
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
remote.logger.debug(f"login time: {round(time.time() - start, 2)}")
|
||||
err = None
|
||||
break
|
||||
except XAirRemoteConnectionTimeoutError as e:
|
||||
err = e
|
||||
continue
|
||||
if err:
|
||||
raise err
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
def lin_get(min, max, val):
|
||||
return min + (max - min) * val
|
||||
|
@ -14,11 +14,11 @@ from pythonosc.dispatcher import Dispatcher
|
||||
from pythonosc.osc_message_builder import OscMessageBuilder
|
||||
from pythonosc.osc_server import BlockingOSCUDPServer
|
||||
|
||||
from . import adapter, kinds
|
||||
from . import adapter, kinds, util
|
||||
from .bus import Bus
|
||||
from .config import Config
|
||||
from .dca import DCA
|
||||
from .errors import XAirRemoteError
|
||||
from .errors import XAirRemoteConnectionTimeoutError, XAirRemoteError
|
||||
from .fx import FX, FXSend
|
||||
from .kinds import KindMap
|
||||
from .lr import LR
|
||||
@ -47,8 +47,6 @@ class OSCClientServer(BlockingOSCUDPServer):
|
||||
class XAirRemote(abc.ABC):
|
||||
"""Handles the communication with the mixer via the OSC protocol"""
|
||||
|
||||
_CONNECT_TIMEOUT = 0.5
|
||||
|
||||
_info_response = []
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
@ -57,6 +55,7 @@ class XAirRemote(abc.ABC):
|
||||
self.xair_ip = kwargs["ip"] or self._ip_from_toml()
|
||||
self.xair_port = kwargs["port"]
|
||||
self._delay = kwargs["delay"]
|
||||
self.connect_timeout = kwargs["connect_timeout"]
|
||||
self.logger = logger.getChild(self.__class__.__name__)
|
||||
if not self.xair_ip:
|
||||
raise XAirRemoteError("No valid ip detected")
|
||||
@ -74,13 +73,10 @@ class XAirRemote(abc.ABC):
|
||||
conn = tomllib.load(f)
|
||||
return conn["connection"].get("ip")
|
||||
|
||||
@util.timeout
|
||||
def validate_connection(self):
|
||||
self.send("/xinfo")
|
||||
time.sleep(self._CONNECT_TIMEOUT)
|
||||
if not self.info_response:
|
||||
raise XAirRemoteError(
|
||||
"Failed to setup OSC connection to mixer. Please check for correct ip address."
|
||||
)
|
||||
if not self.query("/xinfo"):
|
||||
raise XAirRemoteConnectionTimeoutError(self.xair_ip, self.xair_port)
|
||||
self.logger.info(
|
||||
f"Successfully connected to {self.info_response[2]} at {self.info_response[0]}."
|
||||
)
|
||||
@ -117,7 +113,12 @@ def _make_remote(kind: KindMap) -> XAirRemote:
|
||||
"""
|
||||
|
||||
def init_x32(self, *args, **kwargs):
|
||||
defaultkwargs = {"ip": None, "port": 10023, "delay": 0.02}
|
||||
defaultkwargs = {
|
||||
"ip": None,
|
||||
"port": 10023,
|
||||
"delay": 0.02,
|
||||
"connect_timeout": 2,
|
||||
}
|
||||
kwargs = defaultkwargs | kwargs
|
||||
XAirRemote.__init__(self, *args, **kwargs)
|
||||
self.kind = kind
|
||||
@ -135,7 +136,12 @@ def _make_remote(kind: KindMap) -> XAirRemote:
|
||||
self.config = Config.make(self)
|
||||
|
||||
def init_xair(self, *args, **kwargs):
|
||||
defaultkwargs = {"ip": None, "port": 10024, "delay": 0.02}
|
||||
defaultkwargs = {
|
||||
"ip": None,
|
||||
"port": 10024,
|
||||
"delay": 0.02,
|
||||
"connect_timeout": 2,
|
||||
}
|
||||
kwargs = defaultkwargs | kwargs
|
||||
XAirRemote.__init__(self, *args, **kwargs)
|
||||
self.kind = kind
|
||||
|
Loading…
x
Reference in New Issue
Block a user